WesisBless Posted November 6, 2020 Share Posted November 6, 2020 (edited) Hey, its me again. So, I'm now working on the 'Monstrous!' update to Wanon's mod. To do this, I'm using this code in order to pull in builds. Both forms have completed art and are loading properly into the game upon certain conditions met. As of now, all important components of this update are complete. The final thing I'm doing is adding a bit of pizzazz to the mod to make it feel extra special. Thank you to everyone who helped me for this update! You're all wonderful!! Things that are currently working: Art for both forms 100% complete He 'transforms' to Fearsome at 50% sanity. Damage modifier works. He 'transforms' from Fearsome to Monstrous at 5% sanity. Damage modifier works. Adds 'monster' and 'playermonster' tags at 5% sanity. Removes at above 50%. Fire-Pit fuel sound plays upon all three transformations Animation plays upon all three transformations Combat coding for increasing damage-taken multiplier is done (Thank you penguin0616!!!) Things that I am currently working on: Sanity Auras (Currently preparing to update current version of mod on Workshop to test this) Not yet implemented in the code/tested: -- For the third form specifically, removing his usual speech file and adding a pool of ~10 random garbled messages that will be used when inspecting any item/announcing any event. (This isn't 100% necessary, but I feel it makes the mod more interesting and adds a level of challenge to playing him while insane) I attached warlock.lua to this post, will always update it once I have a 'current' version upon each major update. I'm open to any and all suggestions, since maybe I'm using faulty code or there's insight into a better set sanity than what I have him at. All of this is outside of master_postinit and common_postinit, and I'll post the code here as well just in case you don't want to do:wnload Spoiler ------- This is for the Sanity Transformations -------- local currentForm = nil -- logic consistent across all forms local forms = { normal = { damage_multiplier = 1.05, external_damage_taken_multiplier = 1 }, fearsome = { damage_multiplier = 1.15, external_damage_taken_multiplier = 1.10 }, monstrous = { damage_multiplier = 1.20, external_damage_taken_multiplier = 1.15 } } local function SetForm(inst, str) assert(forms[str], "Trying to SetForm with invalid name.") currentForm = str local data = forms[currentForm] inst.components.combat.damagemultiplier = data.damage_multiplier inst.components.combat.externaldamagetakenmultipliers:SetModifier(inst, data.external_damage_taken_multiplier) -- specialized logic per form, could put it in the form table above but too complex for this example if currentForm == "normal" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "fearsome" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "monstrous" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) end end local function OnSanityDrop(inst, data) -- Make sure not to react while the player is dead. if inst:HasTag("playerghost") or inst.components.health and inst.components.health:IsDead() then return end if currentForm == "normal" and inst.components.sanity.current < 50 then SetForm(inst, "fearsome") inst.AnimState:SetBuild("warlock_fearsome") elseif currentForm == "fearsome" and inst.components.sanity.current < 5 then SetForm(inst, "monstrous") inst:AddTag("monster") inst:AddTag("playermonster") inst.AnimState:SetBuild("warlock_monstrous") elseif currentForm == "fearsome" and inst.components.sanity.current > 50 then SetForm(inst, "normal") inst.AnimState:SetBuild("warlock") elseif currentForm == "monstrous" and inst.components.sanity.current > 50 then SetForm(inst, "normal") inst.AnimState:SetBuild("warlock") end -- removes the unwanted tags if inst.components.sanity.current > 50 then inst:RemoveTag("monster") inst:RemoveTag("playermonster") end end local function sanityaurafn(inst, observer) -- Create a temporary variable with the current value, so we don't call GetPercent() a million times. local currentSanity = inst.components.sanity:GetPercent() if currentSanity > 0.5 then return elseif currentSanity < 0.05 then return -TUNING.SANITYAURA_LARGE elseif currentSanity < 0.5 then return -TUNING.SANITYAURA_MED end end warlock.lua Edited November 12, 2020 by WesisBless Updating current info as not to flood this thread with various this and thats. Link to comment Share on other sites More sharing options...
WesisBless Posted November 6, 2020 Author Share Posted November 6, 2020 Update, tried running the mod with the coding I have in that file, got this error: Link to comment Share on other sites More sharing options...
WesisBless Posted November 6, 2020 Author Share Posted November 6, 2020 (edited) So I was able to fix the above error by removing the 'add tags' code for the third form, and I tweaked a few things... but now he flickers between the sprite for his third form and the sprite for his second... this has been an interesting journey so far. No longer relevant, have edited title to reflect current needed help. Edited November 8, 2020 by WesisBless Removed out of date information. Link to comment Share on other sites More sharing options...
WesisBless Posted November 10, 2020 Author Share Posted November 10, 2020 This is likely 100% an instance of me having no idea what I'm doing but trying to learn. I've been toying around with some of the combat components to take more damage when in his Fearsome/Monstrous forms... but I'm really struggling out in this sea on my own. Here's what's currently going on, because I'm going to take a break from this for a little bit to clear my head. The code in question: local function Combat:CalcDamage(target, weapon, multiplier) local externaldamagetakenmultipliers = self.externaldamagetakenmultipliers if not isInSecondForm or not isInThirdForm then return elseif isInSecondForm then inst.components.combat.externaldamagetakenmultipliers = 1.10 elseif isInThirdForm then inst.components.combat.externaldamagetakenmultipliers = 1.15 end end What happened after I utilized it: So I'm certain I'm just doing something very, very wrong. I'm attaching a to-date version of the warlock.lua as well, along with updating what is in the original post for this so people aren't confused by my scatterbrained attempt at coding this mod. Link to comment Share on other sites More sharing options...
AndRay Posted November 10, 2020 Share Posted November 10, 2020 Colons are lua shorthand for methods and they require the thing before the colon to already exist. Inside a prefab file, the game won't have loaded components/combat.lua unless you specifically tell it to do so. Running a simple require "components/combat.lua" at the top should fix it. I think modimport should as well, but I'm not that versed in Lua hierarchy. 1 Link to comment Share on other sites More sharing options...
penguin0616 Posted November 11, 2020 Share Posted November 11, 2020 @WesisBless #1: Don't override Combat:CalcDamage. #2: Deal with the externaldamagetakenmultiplier in your transformer. #3: Can't have a table's function be local. 2 Link to comment Share on other sites More sharing options...
WesisBless Posted November 11, 2020 Author Share Posted November 11, 2020 12 hours ago, penguin0616 said: #2: Deal with the externaldamagetakenmultiplier in your transformer. So I have tried a few things, but it really doesn't like the 'self' part of the external damage multiplier code and I don't know how to mess with it appropriately to get it to work right. I have tried a workaround that someone else was doing for another mod but the way they coded it was not agreeing with my code either and caused crash after crash, I'm not well-versed enough to clean it up. Anyways, I'll show you what I've got as of right now while I go combing through the forms for any other clues on what to do here. Spoiler local isInSecondForm = false local isInThirdForm = false local externaldamagetakenmultipliers = self.externaldamagetakenmultipliers local function TurnBackToNormal(inst) inst.components.combat.damagemultiplier = 1.05 inst.components.combat.externaldamagetakenmultipliers = 1 inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") inst.AnimState:SetBuild("warlock") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) isInSecondForm = false isInThirdForm = false end local function TurnIntoSecondForm(inst) inst.components.combat.damagemultiplier = 1.15 inst.components.combat.externaldamagetakenmultipliers = 1.10 inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") inst.AnimState:SetBuild("warlock_fearsome") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) isInSecondForm = true end local function TurnIntoThirdForm(inst) inst.components.combat.damagemultiplier = 1.20 inst.components.combat.externaldamagetakenmultipliers = 1.15 inst:AddTag("monster") inst:AddTag("playermonster") inst.AnimState:SetBuild("warlock_monstrous") isInThirdForm = true end local function OnSanityDrop(inst, data) -- Make sure not to react while the player is dead. if inst:HasTag("playerghost") or inst.components.health and inst.components.health:IsDead() then return end -- If sanity drops below 50, become the second form. if not isInSecondForm and inst.components.sanity.current < 50 then TurnIntoSecondForm(inst) -- This should enter 'monsterous' stage. elseif isInSecondForm and inst.components.sanity.current < 5 then TurnIntoThirdForm(inst) -- This should turn me back into normal, I hope. elseif isInSecondForm and inst.components.sanity.current > 50 then TurnBackToNormal(inst) end -- removes the unwanted tags if inst.components.sanity.current > 50 then inst:RemoveTag("monster") inst:RemoveTag("playermonster") end end Sorry for my messy hodge-podge of code, I wish I was better adapted so I could clean this up nice and neat. Someone else was suggesting something like it'd "be easier to have the state of each form in a single variable so you don't have to reset each one but just replace one" but I have no clue how to do that since I'm following someone else's code for this save having shoved a third form into it. That same person also said "also you should probably have the change in form function happen when you load in or something so it can apply the form when you join" which I wasn't sure what they were meaning by that and if it is better than what I have right now. Link to comment Share on other sites More sharing options...
penguin0616 Posted November 11, 2020 Share Posted November 11, 2020 (edited) Quote local externaldamagetakenmultipliers = self.externaldamagetakenmultipliers That would error because there is no "self" to reference. You can get rid of that line entirely, since it doesn't really help you. 2 hours ago, WesisBless said: Someone else was suggesting something like it'd "be easier to have the state of each form in a single variable so you don't have to reset each one but just replace one" Not completely sure what they meant, but this is roughly the approach I would take (and I believe is what they meant). local currentForm = nil -- logic consistent across all forms local forms = { normal = { damage_multiplier = 1.05, external_damage_taken_multiplier = 1 }, second = { damage_multiplier = 1.15, external_damage_taken_multiplier = 1.10 }, third = { damage_multiplier = 1.20, external_damage_taken_multiplier = 1.15 } } local function SetForm(inst, str) assert(forms[str], "Trying to SetForm with invalid name.") currentForm = str local data = forms[currentForm] inst.components.combat.damagemultiplier = data.damage_multiplier inst.components.combat.externaldamagetakenmultiplier = data.external_damage_taken_multiplier -- specialized logic per form, could put it in the form table above but too complex for this example if currentForm == "normal" then -- blah elseif currentForm == "second" then -- blah elseif currentForm == "third" then -- blah end end local function OnSanityDrop(inst, data) -- blah if currentForm == "SOMETHING" and inst.components.sanity.current < SOMETHING then SetForm(inst, "SOMETHING") end -- blah end Edited November 11, 2020 by penguin0616 1 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 11, 2020 Author Share Posted November 11, 2020 24 minutes ago, penguin0616 said: local forms = { normal = { damage_multiplier = 1.05 external_damage_taken_multiplier = 1 }, second = { damage_multiplier = 1.15, external_damage_taken_multiplier = 1.10 }, third = { damage_multiplier = 1.20, external_damage_taken_multiplier = 1.15 } } This whole thing looks so much better, and I'm going to implement it myself, however when I went to test and see if I modified everything correctly it yelled at me about the normal = { line. Here's the crash screen: And just so you can look and see my attempt at adding what I wanted and making sure things are where they should go: ------- This is for the Sanity Transformations -------- local currentForm = nil -- logic consistent across all forms local forms = { normal = { damage_multiplier = 1.05 external_damage_taken_multiplier = 1 }, fearsome = { damage_multiplier = 1.15, external_damage_taken_multiplier = 1.10 }, monstrous = { damage_multiplier = 1.20, external_damage_taken_multiplier = 1.15 } } local function SetForm(inst, str) assert(forms[str], "Trying to SetForm with invalid name.") currentForm = str local data = forms[currentForm] inst.components.combat.damagemultiplier = data.damage_multiplier inst.components.combat.externaldamagetakenmultiplier = data.external_damage_taken_multiplier -- specialized logic per form, could put it in the form table above but too complex for this example if currentForm == "normal" then inst.AnimState:SetBuild("warlock") inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "fearsome" then inst.AnimState:SetBuild("warlock_fearsome") inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "monstrous" then inst.AnimState:SetBuild("warlock_monstrous") inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) end end local function OnSanityDrop(inst, data) -- blah if currentForm == "normal" and inst.components.sanity.current < 50 then SetForm(inst, "fearsome") elseif currentForm == "fearsome" and inst.components.sanity.current < 5 then SetForm(inst, "monstrous") inst:AddTag("monster") inst:AddTag("playermonster") elseif currentForm == "monstrous" and inst.components.sanity.current > 50 then SetForm(inst, "normal") end -- removes the unwanted tags if inst.components.sanity.current > 50 then inst:RemoveTag("monster") inst:RemoveTag("playermonster") end Link to comment Share on other sites More sharing options...
penguin0616 Posted November 11, 2020 Share Posted November 11, 2020 2 hours ago, WesisBless said: normal = { damage_multiplier = 1.05 external_damage_taken_multiplier = 1 }, You forgot the comma after 1.05 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 11, 2020 Author Share Posted November 11, 2020 2 minutes ago, penguin0616 said: You forgot the comma after 1.05 Oh! Hahaha! It's always little things like that, isn't it? Thanks, I would have gone half mad before noticing that. Good news: No crashes! Bad news: Seems entering different sanity levels doesn't cause the form shift, I've moved the 'AnimState:SetBuild' to happen on the sanity drop instead of being in the specialized strings and that didn't change anything. I do have this in master_postinit: -- Listen for sanity drop for transformation inst:ListenForEvent("sanitydelta", OnSanityDrop) I'm going to mess around and see if I can't figure it on my own, but just in case you might figure it out before I do I'll post it here anyways. warlock.lua Link to comment Share on other sites More sharing options...
penguin0616 Posted November 11, 2020 Share Posted November 11, 2020 I'm not sure about dealing with animations, but glancing over your code reveals an issue with sanityaurafn. Since you check currentSanity < 0.5 before < 0.05, it will never reach -TUNING.SANITYAURA_LARGE You'll want to revise your if-statement order. For debugging your failed transformations, I suggest you put prints at each point of the process to see where it fails at. Hasn't failed me yet. 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 11, 2020 Author Share Posted November 11, 2020 7 minutes ago, penguin0616 said: glancing over your code reveals an issue with sanityaurafn. Fixed it, thanks! I was hoping someone would double-check that for me since I won't be able to test it reliably until I make this thing live to test the multiplayer aspects. As for testing the transformations, could you elaborate on what you mean by 'prints'? I haven't heard that term used yet so I don't know what it means, hah! Link to comment Share on other sites More sharing options...
penguin0616 Posted November 11, 2020 Share Posted November 11, 2020 4 minutes ago, WesisBless said: As for testing the transformations, could you elaborate on what you mean by 'prints'? The function print, built-in to Lua. Takes any number of arguments, concatenates them as a string, and displays the result. https://www.lua.org/pil/5.1.html Adding more than one print means you can call them prints. 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 11, 2020 Author Share Posted November 11, 2020 I'm really thankful for your patience with me, since I'm really still quite new to this. Just to make sure that I'm utilizing the prints correctly, this is what I've got in the code: local currentForm = nil print("currentForm was called") -- logic consistent across all forms local forms = { normal = { damage_multiplier = 1.05, external_damage_taken_multiplier = 1 }, fearsome = { damage_multiplier = 1.15, external_damage_taken_multiplier = 1.10 }, monstrous = { damage_multiplier = 1.20, external_damage_taken_multiplier = 1.15 } } local function SetForm(inst, str) assert(forms[str], "Trying to SetForm with invalid name.") currentForm = str local data = forms[currentForm] inst.components.combat.damagemultiplier = data.damage_multiplier inst.components.combat.externaldamagetakenmultiplier = data.external_damage_taken_multiplier -- specialized logic per form, could put it in the form table above but too complex for this example if currentForm == "normal" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "fearsome" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) elseif currentForm == "monstrous" then inst.SoundEmitter:PlaySound("dontstarve/common/fireAddFuel") SpawnPrefab("poopcloud").Transform:SetPosition(inst.Transform:GetWorldPosition()) end print("SetForm was called") end local function OnSanityDrop(inst, data) -- Make sure not to react while the player is dead. if inst:HasTag("playerghost") or inst.components.health and inst.components.health:IsDead() then return end if currentForm == "normal" and inst.components.sanity.current < 50 then SetForm(inst, "fearsome") inst.AnimState:SetBuild("warlock_fearsome") elseif currentForm == "fearsome" and inst.components.sanity.current < 5 then SetForm(inst, "monstrous") inst:AddTag("monster") inst:AddTag("playermonster") inst.AnimState:SetBuild("warlock_monstrous") elseif currentForm == "monstrous" and inst.components.sanity.current > 50 then SetForm(inst, "normal") inst.AnimState:SetBuild("warlock") end -- removes the unwanted tags if inst.components.sanity.current > 50 then inst:RemoveTag("monster") inst:RemoveTag("playermonster") end print("OnSanityDrop was called") end I can tell you with certainty that 'On sanity drop' was called. A lot. The Client Log is full of it. Please correct me if I'm doing this wrong, I'm always ready to learn what I'm doing wrong! client_log.txt Link to comment Share on other sites More sharing options...
penguin0616 Posted November 12, 2020 Share Posted November 12, 2020 @WesisBless I think I may know the issue. Since currentForm starts as nil, none of the if-statements you have would pass. This can be fixed by call SetForming and then OnSanityDrop during your character initialization. 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 12, 2020 Author Share Posted November 12, 2020 @penguin0616 Alright! So I assume I need to add a code to the master_postinit similar to the 'ListenForEvent' code I have for OnSanityDrop, or would this be something that goes in Modmain? I can't thank you enough for your help! Link to comment Share on other sites More sharing options...
penguin0616 Posted November 12, 2020 Share Posted November 12, 2020 I believe it would go in master_postinit, yes. 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 12, 2020 Author Share Posted November 12, 2020 Something like this: inst:ListenForEvent ("currentForm", SetForm) ? Link to comment Share on other sites More sharing options...
penguin0616 Posted November 12, 2020 Share Posted November 12, 2020 SetForm(inst, "normal") OnSanityDrop(inst, nil) 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 12, 2020 Author Share Posted November 12, 2020 Oh lovely, that worked! Only issue now is that the external damage taken multipliers aren't working. The increased damage is applying, just not the increased taken damage (I've been testing with a Spider, which I know does 20 damage on a hit.) Link to comment Share on other sites More sharing options...
penguin0616 Posted November 12, 2020 Share Posted November 12, 2020 Change inst.components.combat.externaldamagetakenmultiplier = data.external_damage_taken_multiplier to inst.components.combat.externaldamagetakenmultipliers:SetModifier(inst, data.external_damage_taken_multiplier) 1 1 Link to comment Share on other sites More sharing options...
WesisBless Posted November 12, 2020 Author Share Posted November 12, 2020 @penguin0616 My hero!!! Thank you so much! That worked!! Link to comment Share on other sites More sharing options...
penguin0616 Posted November 12, 2020 Share Posted November 12, 2020 You're welcome. 1 1 Link to comment 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