Project Zombolewd Framework - G-Vodan/LLZomboLewd GitHub Wiki
- Quick Start
- Modding: Prerequisites
- Modding: Adding Animations (Part 1)
- Modding: Adding Animations (Part 2 - DirectX format)
- Modding: Adding Animations (Part 2 - FBX format)
- Modding: Adding Animations (Part 3 - XML Editing)
- Modding: Adding Animations (Part 4 - Animation Config)
- Modding: Adding Animations (Part 5 - Testing)
- Modding: Adding Animations (Part 6 - Troubleshoot)
- Modding: Animation Events
- Modding: Programming APIs (Part 1 - Playing Animations)
- Modding: Programming APIs (Part 2 - Animation Callbacks)
ZomboLewd is an animation framework that is made to aid mods on animations, sounds, assets, models, and other things related to sexual-related acts in Project Zomboid. Its gameplay functionalities are intentionally limited to incentivize community involvement as we join together to create a lewder experience in Project Zomboid.
While in-game, you can masturbate by Right-clicking to show the context menu.
If you have NPC mods installed or in the future whenever PZ updates with official NPC support, you can right-click them to activate a scene immediately.
If you want to start modding for ZomboLewd, you will need a few basic programs to start.
- A text editor capable of editing code. My personal go-to is Visual Studio Code or if you want something more lightweight to get the job done, Notepad++.
- An animation program (if you want to animate). A popular free choice is Blender (however Blender doesn't work for editing .X files, see below).
The easiest way to start adding your own custom animations is to download the modding template for ZomboLewd and install it like any regular mod in your Project Zomboid's mod folder.
The best way to edit .X files (at the time of writing) is to download the program FragMotion. It is quite a dated program and does not have all the features like your more contemporary animation program but it is the fastest way to edit and replace animations already in Project Zomboid.
Here are the official instructions from Jaivosdents:
- Download FragMotion and activate a 7-day trial every week.
- Take an animation from ZomboLewd's anims_X folder or within Project Zomboid/media/Anims_X
- Open the animation in FragMotion
- Click on the animation name on the hierarchy top right
- Modify the name from properties
- Click on Select Bones, on the tools windows on the bottom right
- Go to Windows > Keyframe Editor and then remove everything except for the first and last frame
- Close the Keyframe Editor, then click on Windows > Keyframe Slide.
- Then on the bottom, move the frame scale begin animating the model
Coming Soon. Our modders are still currently looking for ways to make FBX work well which will supersede the DirectX method in the future. Stay tuned!
If you already have a template .FBX file that already works as a replacer for animations for Project Zomboid, this should also work just as well in the meantime.
Once you have finished exporting a .X or .fbx file, navigate to your _Mods_Template_For_ZomboLewd you downloaded from Part 1, then click into media/anims_X/Bob.
Save your new animation into this folder. Feel free to remove the animations already in the directory, they were there to give you an example of how they should be placed.
Next, navigate to media/AnimSets/player/actions in within the same mod. Clone the file named __AnimSetTemplate.xml, and name the file appropriately to what the animation should be. Open up the .XML file, it should look something like this:
<?xml version="1.0" encoding="utf-8"?>
<animNode>
<m_Name> NAME_OF_ANIMATION (SHOULD BE SAME IN ANIMATIONLIST) </m_Name>
<m_AnimName> ANIMATION_FILE_NAME_ENDING_IN_X_OR_FBX </m_AnimName>
<m_deferredBoneAxis>Y</m_deferredBoneAxis>
<m_SyncTrackingEnabled>false</m_SyncTrackingEnabled>
<m_SpeedScale>1.05</m_SpeedScale>
<m_BlendTime>0.10</m_BlendTime>
<m_Conditions>
<m_Name>PerformingAction</m_Name>
<m_Type>STRING</m_Type>
<m_StringValue> NAME_OF_ANIMATION (SHOULD BE SAME IN ANIMATIONLIST) </m_StringValue>
</m_Conditions>
<m_SubStateBoneWeights>
<boneName>Dummy01</boneName>
<weight>1.0</weight>
</m_SubStateBoneWeights>
</animNode>
Line 3: <m_Name> NAME_OF_ANIMATION (SHOULD BE SAME IN ANIMATIONLIST) </m_Name>
Make up a name that will be used as the identifier in-game for this animation. The game and ZomboLewd will reference this name in order to fetch the animation. Make sure to make it unique; if another animation mod uses the same name, it may potentially overwrite your animation.
Example:
<m_Name>QueuedResonance_MyAnimation_Name</m_Name>
Line 4: <m_AnimName> ANIMATION_FILE_NAME_ENDING_IN_X_OR_FBX </m_AnimName>
This should be the same name as the animation you saved at the beginning of Part 3, located in media/anims_X/Bob. Do not include file extensions.
Example:
Saved an animation to media/anims_X/Bob/Bob_Animation_File.fbx
<m_AnimName>Bob_Animation_File</m_AnimName>
Line 12: <m_StringValue> NAME_OF_ANIMATION (SHOULD BE SAME IN ANIMATIONLIST) </m_StringValue>
Use the same name as Line 3 here.
Example:
<m_StringValue>QueuedResonance_MyAnimation_Name</m_StringValue>
Save the file.
Navigate to media/lua/shared/ZomboLewd/AnimationConfigs in within the same mod. Clone the file named __AnimationConfigTemplate.lua and name it the same as Line 3 from your XML file in Part 3.
Example:
QueuedResonance_MyAnimation_Name.lua
Open up the Lua file and read the instructions contained within. We have included a few Lua files as references you can use to help edit your custom Lua animation config. Feel free to remove them afterwards. It should look like this:
require "ZomboLewd/ZomboLewdConfig" --- Always include this at the top to forceload ZomboLewd prior to this animation file
--[[
prefix: this word will be combined with id to create a unique identifier. Recommend using your name here (ie. prefix = "QueuedResonance_")
id: the id of the animation used to fetch its name, will differ depending on the user's language.
tags: a list of tags, can be custom or established, such as "Masturbation", "Aggressive", etc. Used for mods to determine animations
actors: a list of actors in the animation.
gender: the gender of the actor in this scene
stages: a list of animations to be played in order
perform:
Your XML file should have these values:
<m_Name>PerformingAction</m_Name>
<m_Type>STRING</m_Type>
<m_StringValue>ANIMATION_STRING_NAME</m_StringValue> <--- USE THIS FOR PERFORM
duration: specifies how long you want this animation to play during the TimedAction sequences. TimedActions are the green
progress bar you see on top of your head whenever you do an action that requires "time" to complete. Duration does not
necessarily equal to the actual animation length (but you can make it so if you like). If Duration is longer than the
actual animation length itself, the animation will loop (useful if you want to make a looping animation without animating the entire thing)
]]
table.insert(ZomboLewdAnimationData, {
prefix = "Prefix_",
id = "Sex_Act_Name",
tags = {"Masturbation", "MyTag"},
actors = {
{
gender = "Female",
stages = {
{
perform = "ANIMATION_STRING_NAME",
duration = 300
}
}
},
{
gender = "Male",
stages = {
{
perform = "ANIMATION_STRING_NAME",
duration = 300
}
}
}
}
})
That's pretty much it in terms of adding custom animations for ZomboLewd. To test, follow these instructions:
- If Project Zomboid was already launched while you were adding animations, you must close and reopen it.
- Recommend turning on Debug mode for Project Zomboid, which you can add -debug to the launch options prior to opening the game.
- Enable your custom animation mod (if it hasn't been enabled already).
- Enter a scenario or start/load an existing game.
- If it is a Masturbation animation, it should appear in your right-click context menu.
- If it is an Intercourse animation, it should play if you ask an NPC for sex.
- If you do not have an NPC mod installed, you can install ModOptions, pause the game, navigate to Options, there will be a new tab called [Mods]. You can enable ZomboLewd's Debug Mode here.
- Once ZomboLewd's Debug Mode is enabled, you can spawn an NPC by right-clicking > spawn comfort survivor. Then right-clicking the NPC to ask for sex.
This is an optional section in case your animations are not playing in the game.
- Animations are not playing / Console is saying "AnimClip not found:"
This means the game could not find your animation file in media/anims_X/Bob. If you have added an animation while Project Zomboid was still open, you must restart it. If your animation file ends in .x, you may have incorrectly named the animation set. Navigate to media/anims_X/Bob/YOUR_ANIMATION.x, and open it with the text editor. CTRL+F to open up the text finder, and type in AnimationSet. Make sure the AnimationSet matches with your XML's AnimName field.
Save it with the new name, and restart Project Zomboid.
Coming Soon.
For those experienced in Lua, you can tap into the potential of ZomboLewd by allowing it to play animations based on your mod's specifications and usage. We highly recommend reading through all of ZomboLewd's coding (as it is open source!) to understand how it works. We included many comments on each part of the code within the framework. However, if you just want to simply play animations, here is the needed functionality to do so.
Notice |
---|
These APIs can change without notice as ZomboLewd receives updates. Please look at the relevant threads, Discord, and other related media to determine when and how these APIs were changed. |
Here are some example scripts on how to play basic animations with the framework for your mod.
Playing a Masturbation / Single Animation on one actor
--- In a client script
local ZomboLewd = require("ZomboLewd/ZomboLewd") --- Initialize the framework
local AnimationHandler = ZomboLewd.AnimationHandler --- The animation system we need to play the animations
local Animations = ZomboLewd.Animations --- All preloaded animations in memory
local AnimationUtils = ZomboLewd.AnimationUtils --- Additional functions that optionally can be needed
Events.OnCreatePlayer.Add(function(player)
local character = getSpecificPlayer(player) --- Get our newly spawned player
local isFemale = character:isFemale() --- Check if they are a female
--- Navigate to ZomboLewdAnimationUtils.lua for more information about getAnimations. In a nutshell, we specify the amount of actors,
-- how much males, how much females, and get only animations with the Masturbation tag.
local animationList = ContextMenu.Client.AnimationUtils:getAnimations(1, isFemale and 0 or 1, isFemale and 1 or 0, {"Masturbation"})
--- Choose a random masturbation animation in the given list!
local index = ZombRand(1, #animationList + 1)
local chosenAnimation = animationList[index]
--- Play the animation. Navigate to ZomboLewdAnimationHandler.lua for more information about the Play function.
AnimationHandler.Client.AnimationHandler.Play(nil, {character}, chosenAnimation)
end)
Playing a Intercourse / Duo Animation on two actors
--- In a client script
local ZomboLewd = require("ZomboLewd/ZomboLewd") --- Initialize the framework
local AnimationHandler = ZomboLewd.AnimationHandler --- The animation system we need to play the animations
local Animations = ZomboLewd.Animations --- All preloaded animations in memory
local AnimationUtils = ZomboLewd.AnimationUtils --- Additional functions that optionally can be needed
Events.OnCreatePlayer.Add(function(player)
local character = getSpecificPlayer(player) --- Get our newly spawned player
local isFemale = character:isFemale() --- Check if they are a female
--- Let's get 1 random NPC / Player / Whatever in the game for the sex lottery LOL
local chosenTarget = nil
local targets = getCell():getObjectList()
for i = targets:size(), 1, -1 do
local thisTarget = targets:get(i - 1)
--- Check if this is the relevant NPC / Player
if instanceof(thisTarget, "IsoPlayer") and thisTarget ~= character then
chosenTarget = target
end
end
--- We can determine the sexuality by determining the gender of the target character fetched
local maleCount, femaleCount = 0, 0 do
if isMainHeroFemale and isTargetFemale then
--- Lesbian
maleCount = 0
femaleCount = 2
elseif isMainHeroFemale == false and isTargetFemale == false then
--- Gay
maleCount = 2
femaleCount = 0
else
--- Straight
maleCount = 1
femaleCount = 1
end
end
--- Choose random animation as a test with the Sex tag. Navigate to ZomboLewdAnimationUtils for more information about how to get animations.
local animationList = contextMenu.Client.AnimationUtils:getAnimations(2, maleCount, femaleCount, {"Sex"})
local index = ZombRand(1, #animationList + 1)
local chosenAnimation = animationList[index]
--- Play the animation. Navigate to ZomboLewdAnimationHandler.lua for more information about the Play function.
AnimationHandler.Play(nil, {character, chosenTarget}, chosenAnimation)
end)
There are certain times you want your mod to be doing something before an animation starts, when the animation starts, during an animation, and when it finally stops. ZomboLewd made it easy to include this functionality.
Take this code for example:
AnimationHandler.Play(nil, {character}, chosenAnimation)
We can add additional callbacks by including a callback function table as the last argument.
--- Refer to ZomboLewdAnimationHandler.lua for more information regarding the Play function.
AnimationHandler.Play(nil, {character}, chosenAnimation, nil, nil, {
WaitToStart = function()
--- What happens while the animation is waiting to start?
--- This happens when the actors are currently doing something else or is walking towards the animation destination
print("Waiting for animation to start...")
end,
Start = function()
--- What happens when the animation starts?
print("Animation has started!")
end,
Update = function()
--- What happens during the animation?
print("Animation currently playing")
end,
Stop = function()
--- What happens when the animation is cancelled?
--- Usually happens when one of the actors in the animation cancels it by running, interacting, or shoving
print("This animation got cancelled!")
end,
Perform = function()
--- What happens once the animation successfully finishes?
--- If the animation plays to full only.
print("Animation has successfully finished!")
end
})
Notice |
---|
Callbacks are activated for each actor on the scene, separately. For example, if we use PlayDuo and include a callback table, WaitToStart, Start, Stop, and Perform will be called twice (as each actor is considered their own entity). |