TemporarySolutn Posted September 22, 2020 Share Posted September 22, 2020 (edited) I'm trying to replace the default walking and idle animations with their sandstorm counterparts as long as they have specific tag or something and it is proving to be super complicated. Edited September 22, 2020 by JustCrimson Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/ Share on other sites More sharing options...
Serpens Posted September 23, 2020 Share Posted September 23, 2020 (edited) first you need to know where for example the idle animation is defined. How did I found it? I know that the idle animation is replaced by a hungry animation when hungry. So I first looked in the hunger component. Then I searched for all event listeners that are pushed within this component, but found nothing that is related to animations. So I searched for "components.hunger" instead and finally found within the stategraphs SGWilson the code: elseif inst.components.hunger:GetPercent() < TUNING.HUNGRY_THRESH then inst.AnimState:PlayAnimation("hungry") inst.SoundEmitter:PlaySound("dontstarve/wilson/hungry") (if one knew that animations are mostly handled in stategraphs, the search would have been easier). For the search I used notepad++ and the "search all files" feature, to search within the unpacked scripts folder of the game and only for lua files. So curently the state we were searching for has the name "funnyidle" in line 2333 of SGWilson. Now we need to overwrite that state, but without breaking any other mod that also does this, nor breaking it when the devs update the game. So the best would be if we save the old code, then check for your specific tag. if your tag is there, we do your code, if not, we simply call the old unchanged function. To change an existiing state we can use in modmain lua this command (this is an example from my shadow maxwell mod): AddStategraphPostInit("shadowmaxwell",function(sg) if sg.states.death~=nil then local old_onenter = sg.states.death.onenter local function new_onenter(inst,...) if inst.components~=nil and inst.components.container~=nil then inst.components.container:Close() inst.components.container:DropEverything() inst.components.container.canbeopened = false end return old_onenter(inst,...) end sg.states.death.onenter = new_onenter end end This example overwrites the onenter function from the state with the name death for my shadowmaxwell. You instead want to change the state for SGWilson. All normal game characters use this SGWilson, so there is no extra file for every character. So you need to do AddStategraphPostInit("wilson"...) and within the new_onenter function you can check if inst.prefab is your special character and if it has your tag. So now try to complete the code to replace the idle animation. Edited September 23, 2020 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1373549 Share on other sites More sharing options...
TemporarySolutn Posted September 25, 2020 Author Share Posted September 25, 2020 (edited) On 9/23/2020 at 5:22 AM, Serpens said: Spoiler first you need to know where for example the idle animation is defined. How did I found it? I know that the idle animation is replaced by a hungry animation when hungry. So I first looked in the hunger component. Then I searched for all event listeners that are pushed within this component, but found nothing that is related to animations. So I searched for "components.hunger" instead and finally found within the stategraphs SGWilson the code: elseif inst.components.hunger:GetPercent() < TUNING.HUNGRY_THRESH then inst.AnimState:PlayAnimation("hungry") inst.SoundEmitter:PlaySound("dontstarve/wilson/hungry") (if one knew that animations are mostly handled in stategraphs, the search would have been easier). For the search I used notepad++ and the "search all files" feature, to search within the unpacked scripts folder of the game and only for lua files. So curently the state we were searching for has the name "funnyidle" in line 2333 of SGWilson. Now we need to overwrite that state, but without breaking any other mod that also does this, nor breaking it when the devs update the game. So the best would be if we save the old code, then check for your specific tag. if your tag is there, we do your code, if not, we simply call the old unchanged function. To change an existiing state we can use in modmain lua this command (this is an example from my shadow maxwell mod): AddStategraphPostInit("shadowmaxwell",function(sg) if sg.states.death~=nil then local old_onenter = sg.states.death.onenter local function new_onenter(inst,...) if inst.components~=nil and inst.components.container~=nil then inst.components.container:Close() inst.components.container:DropEverything() inst.components.container.canbeopened = false end return old_onenter(inst,...) end sg.states.death.onenter = new_onenter end end This example overwrites the onenter function from the state with the name death for my shadowmaxwell. You instead want to change the state for SGWilson. All normal game characters use this SGWilson, so there is no extra file for every character. So you need to do AddStategraphPostInit("wilson"...) and within the new_onenter function you can check if inst.prefab is your special character and if it has your tag. So now try to complete the code to replace the idle animation. How would I check if the player is moving or standing still? just inst:HasStateTag("run_start") and etc? because I need to get it for the walk_pre, loop, and pst. Also the last time I tried something similar to this the animation looked like it was ending too soon (also what is the difference between walking and running and which should I use) Right so I see what I'm doing, but I'm not sure how to do the idle animation. The sandstorm idle is the only one in "idle" and not "funnyidle". I don't know the difference or what to do about it (haven't tested my code yet either so I could be doing everything horribly wrong). (also that code doesnt have an ending parenthesis) Edited September 25, 2020 by JustCrimson Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1374422 Share on other sites More sharing options...
Serpens Posted September 25, 2020 Share Posted September 25, 2020 4 hours ago, JustCrimson said: How would I check if the player is moving or standing still? just inst:HasStateTag("run_start") and etc? because I need to get it for the walk_pre, loop, and pst. Also the last time I tried something similar to this the animation looked like it was ending too soon (also what is the difference between walking and running and which should I use) Right so I see what I'm doing, but I'm not sure how to do the idle animation. The sandstorm idle is the only one in "idle" and not "funnyidle". I don't know the difference or what to do about it (haven't tested my code yet either so I could be doing everything horribly wrong). (also that code doesnt have an ending parenthesis) I'm no expert about animations and I never made a custom character. I just know how to change the stategraphs like above and I also suceeded to make the shadow maxwell do the "hungry" animations as "funnyidle". And I thought this is similar to your request, isn't it? funnyidle is the animation the character does every ~10 seconds or so. But even if you don't want to change funnyilde, the same code style should apply to all other stategraphs. If you explain alot more detailed, what exactly you want to achieve, I can see if I can help you more than this. Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1374480 Share on other sites More sharing options...
TemporarySolutn Posted September 25, 2020 Author Share Posted September 25, 2020 23 minutes ago, Serpens said: I'm no expert about animations and I never made a custom character. I just know how to change the stategraphs like above and I also suceeded to make the shadow maxwell do the "hungry" animations as "funnyidle". And I thought this is similar to your request, isn't it? funnyidle is the animation the character does every ~10 seconds or so. But even if you don't want to change funnyilde, the same code style should apply to all other stategraphs. If you explain alot more detailed, what exactly you want to achieve, I can see if I can help you more than this. No, but what you gave me is probably going to work for everything else, the sand idle (the constant sand position) is just a regular idle so it should work if I just do that Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1374497 Share on other sites More sharing options...
TemporarySolutn Posted September 28, 2020 Author Share Posted September 28, 2020 (edited) On 9/25/2020 at 4:56 AM, Serpens said: If you explain alot more detailed, what exactly you want to achieve, I can see if I can help you more than this. I want my character to use the same walking and idle animations, as if they were in a sandstorm, while they have a specific tag Here is the code I have now --[[---------------------------- Sunburning ----------------------------]]-- AddStategraphPostInit("wilson", function(sg) local function OverrideRunStateAnim(inst) if (inst.sg.statemem.groggy or inst.sg.statemem.moosegroggy or inst.sg.statemem.goosegroggy) then return true elseif (inst.sg.statemem.careful) then return true else return false end end --[["run_start/pre"]]-- if sg.states.run_start ~= nil then local old_onenter = sg.states.run_start.onenter local function new_onenter(inst,...) if inst.prefab == "wyrdelyn" and inst:HasTag("sunburning") and not OverrideRunStateAnim(inst) then inst.AnimState:PlayAnimation("sand_walk_pre") end return old_onenter(inst,...) end sg.states.run_start.onenter = new_onenter end --[["run/loop"]]-- if sg.states.run ~= nil then local old_onenter = sg.states.run.onenter local function new_onenter(inst,...) if inst.prefab == "wyrdelyn" and inst:HasTag("sunburning") and OverrideRunStateAnim(inst) then inst.AnimState:PlayAnimation("sand_walk") end return old_onenter(inst,...) end sg.states.run.onenter = new_onenter end --[["run_stop/pst"]]-- if sg.states.run_stop ~= nil then local old_onenter = sg.states.run_stop.onenter local function new_onenter(inst,...) if inst.prefab == "wyrdelyn" and inst:HasTag("sunburning") and OverrideRunStateAnim(inst) then inst.AnimState:PlayAnimation("sand_walk_pst") end return old_onenter(inst,...) end sg.states.run_stop.onenter = new_onenter end --[["idle"]]-- if sg.states.idle ~= nil then local old_onenter = sg.states.idle.onenter local function new_onenter(inst,...) if inst.prefab == "wyrdelyn" and inst:HasTag("sunburning") and OverrideRunStateAnim(inst) then if not (inst.AnimState:IsCurrentAnimation("sand_walk_pst") or inst.AnimState:IsCurrentAnimation("sand_walk") or inst.AnimState:IsCurrentAnimation("sand_walk_pre")) then inst.AnimState:PlayAnimation("sand_idle_pre") end inst.AnimState:PushAnimation("sand_idle_loop", true) end return old_onenter(inst,...) end sg.states.idle.onenter = new_onenter end end) It all runs, but it just doesn't play any of the animations. The line is being ran like I can put print statements next to it, I just don't play the animation and I get no errors Edited September 28, 2020 by JustCrimson Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1375479 Share on other sites More sharing options...
Serpens Posted September 28, 2020 Share Posted September 28, 2020 (edited) I think this will do it:, using the upvaluehacker to change a local function, will already solve all run states. local UpvalueHacker = GLOBAL.require("upvaluehacker") AddStategraphPostInit("wilson", function(sg) if sg.states.run ~= nil then local old_GetRunStateAnim = UpvalueHacker.GetUpvalue(sg.states.run.onenter, "GetRunStateAnim") local function new_GetRunStateAnim(inst,...) if not inst.sg.statemem.heavy and inst.prefab=="wilson" then return "sand_walk" else return old_GetRunStateAnim(inst,...) end end UpvalueHacker.SetUpvalue(sg.states.run.onenter, new_GetRunStateAnim, "GetRunStateAnim") -- this will overwrite that local function, working for run_start,run and run_stop at once end if sg.states.idle ~= nil then local old_onenter = sg.states.idle.onenter local function new_onenter(inst,pushanim,...) old_onenter(inst,pushanim,...) if inst.prefab == "wilson" then if inst.sg.currentstate.name=="idle" then -- if we not left the idle state if not inst.components.inventory:IsHeavyLifting() then local anims = {} if not (inst.AnimState:IsCurrentAnimation("sand_walk_pst") or inst.AnimState:IsCurrentAnimation("sand_walk") or inst.AnimState:IsCurrentAnimation("sand_walk_pre")) then table.insert(anims, "sand_idle_pre") end table.insert(anims, "sand_idle_loop") if pushanim then for k, v in pairs(anims) do inst.AnimState:PushAnimation(v, k == #anims) end else inst.AnimState:PlayAnimation(anims[1], #anims == 1) for k, v in pairs(anims) do if k > 1 then inst.AnimState:PushAnimation(v, k == #anims) end end end end end end end sg.states.idle.onenter = new_onenter end end) AddStategraphPostInit("wilson_client", function(sg) if sg.states.run ~= nil then local old_GetRunStateAnim = UpvalueHacker.GetUpvalue(sg.states.run.onenter, "GetRunStateAnim") local function new_GetRunStateAnim(inst,...) if not inst.sg.statemem.heavy and inst.prefab=="wilson" then return "sand_walk" else return old_GetRunStateAnim(inst,...) end end UpvalueHacker.SetUpvalue(sg.states.run.onenter, new_GetRunStateAnim, "GetRunStateAnim") end if sg.states.idle ~= nil then local old_onenter = sg.states.idle.onenter local function new_onenter(inst,pushanim,...) old_onenter(inst,pushanim,...) if inst.prefab == "wilson" then if inst.sg.currentstate.name=="idle" then -- if we not left the idle state if (inst.replica.inventory ~= nil and inst.replica.inventory:IsHeavyLifting()) then return elseif pushanim == "cancel" then return elseif inst:HasTag("nopredict") or inst:HasTag("pausepredict") then return elseif pushanim == "noanim" then return end if inst.replica.rider ~= nil and inst.replica.rider:IsRiding() then return end if ( inst.AnimState:IsCurrentAnimation("sand_walk_pst") or inst.AnimState:IsCurrentAnimation("sand_walk") or inst.AnimState:IsCurrentAnimation("sand_walk_pre") ) then if pushanim then inst.AnimState:PushAnimation("sand_idle_loop", true) else inst.AnimState:PlayAnimation("sand_idle_loop", true) end end end end end sg.states.idle.onenter = new_onenter end end) If you don't want the "funny_idle" animation to play, you can overwrite ontimeout within the idle state, or change the funnyidle itself. I tried to overwrite as less as possible. The idle state is quite important, it is not only for simple animation change. So if we break it somehow (or eg a game update changes it a bit, while we overwrote it) alot can break. So it is quite dangerous to change it. Therefore I first call the old_onenter within the new_onenter, to eg. trigger a state change and other stuffs. After that I only change the animation to sand, if we not already switched state and if the first few conditions from the old_onenter are not true. This last part is problematic, because if the devs change the onenter function and add some additional animations that have priority over the sand animation, then this will break our code. But this code is still better than overwriting (coyp/pasting) the whole onenter function. This is the best way I found, although it is by far not perfect, since a game update could break it. Edited September 28, 2020 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/121917-anyone-know-how-to-swap-default-animations/#findComment-1375506 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now