ColombianCam Posted September 23, 2019 Share Posted September 23, 2019 Last time I made a thread, it was about the woodie rework, a user named serpens pointed to me out I should use modmain whenever directly changing a pre-existing game file, in this case woodie scripts; However I have no clue how to do so, I'm gonna post some code that it's in the woodie and that I want it to be in the modmain, if someone could help me, because I had to redo my whole mod because a new update bricked it, I don't wanna be updating each time they update the woodie script. I used a compare plugin on notepad +++ to easily spot these changes from the woodie original script to my modded one. . if not TheWorld.ismastersim then inst.CanExamine = CannotExamine SetWereActions(inst, mode) SetWereVision(inst, mode) if inst.components.locomotor ~= nil then inst.components.locomotor.runspeed = (mode == WEREMODES.BEAVER and TUNING.BEAVER_RUN_SPEED) or (mode == WEREMODES.MOOSE and TUNING.WEREMOOSE_RUN_SPEED) or (--[[mode == WEREMODES.GOOSE and]] TUNING.WEREGOOSE_RUN_SPEED*2.5) end end else what I changed was insert the *2.5 for the weregoose run speed. I'm thinking that maybe I should just use global.tuning and make that value just equal that of *2.5 [SPOILER/] else--if mode == WEREMODES.GOOSE then t = t * TUNING.WEREGOOSE_DRAIN_TIME if inst.sg:HasStateTag("moving") then if inst._gooserunning ~= nil then inst._gooserunning:Cancel() end inst._gooserunning = inst:DoTaskInTime(TUNING.WEREGOOSE_RUN_DRAIN_TIME_DURATION, OnGooseRunningOver, CalculateWerenessDrainRate) inst._gooserunninglevel = 2 inst.components.wereness:DoDelta(TUNING.BEAVER_GNAW_GAIN*0.25) inst.components.sanity:DoDelta(TUNING.BEAVER_GNAW_GAIN*0.25) I added underneath inst._gooserunninglevel = 2 inst.components.wereness:DoDelta(TUNING.BEAVER_GNAW_GAIN*0.25) inst.components.sanity:DoDelta(TUNING.BEAVER_GNAW_GAIN*0.25) I read recezibs guide about postinit local OldGetPosition = inst.GetPosition inst.GetPosition = function(thing) local pos = OldGetPosition(thing) pos.x = math.floor(pos.x+0.5) pos.y = math.floor(pos.y+0.5) pos.z = math.floor(pos.z+0.5) return pos end local OldCalculateWerenessDrainRate = inst.CalculateWerenessDrainRate inst.CalculateWerenessDrainRate = function(inst) OldCalculateWerenessDrainRate(inst) end maybe it's something like this, I dunno. [SPOILER/] Then, I want to revert back woodie's sanity boost for planting trees, but I made it literally anything green-ish, for example bushes. local function ondeployitem(inst, data) if data.prefab == "pinecone" or data.prefab == "acorn" or data.prefab == "twiggy_nut" or data.prefab == "dug_berrybush" or data.prefab == "dug_grass" or data.prefab == "dug_sapling" or data.prefab == "butterfly" or data.prefab == "dug_sapling" or data.prefab == "lureplantbulb" or data.prefab == "berrybush_juicy" then --inst.components.beaverness:DoDelta(TUNING.WOODIE_PLANT_TREE_GAIN) inst.components.sanity:DoDelta(TUNING.SANITY_TINY) end end it's a totally new function so maybe it's postinit function or something? but then looking back, on the older woodie it was mentioned as a function also: local function onrespawnedfromghost(inst) if inst._wasnomorph == nil then inst._wasnomorph = inst.sg:HasStateTag("nomorph") or inst.sg:HasStateTag("silentmorph") inst:ListenForEvent("deployitem", ondeployitem) inst:ListenForEvent("werenessdelta", onwerenesschange) inst:ListenForEvent("newstate", onnewstate) inst:WatchWorldState("isfullmoon", OnIsFullmoon) end inst:ListenForEvent("deployitem", ondeployitem) and then afterwards in another function called onbecameghost it's mentioned. local function onbecameghost(inst, data) if not IsWereMode(inst.weremode:value()) then --clear any queued transformations inst.components.wereness:SetPercent(0, true) elseif data == nil or not data.corpse then CustomSetSkinMode(inst, "ghost_were"..WEREMODE_NAMES[inst.weremode:value()].."_skin") end inst.components.wereeater:ResetFoodMemory() inst.components.wereness:StopDraining() inst.components.wereness:SetWereMode(nil) if inst._wasnomorph ~= nil then inst._wasnomorph = nil inst:RemoveEventCallback("werenessdelta", onwerenesschange) inst:RemoveEventCallback("newstate", onnewstate) inst:RemoveEventCallback("deployitem", ondeployitem) inst:StopWatchingWorldState("isfullmoon", OnIsFullmoon) end inst:RemoveEventCallback("deployitem", ondeployitem) [SPOILER/] Finally the last code for this prefab is from the component tackler: inst:AddComponent("tackler") inst.components.tackler:SetOnStartTackleFn(OnTackleStart) inst.components.tackler:SetDistance(.5) inst.components.tackler:SetRadius(.75) inst.components.tackler:SetStructureDamageMultiplier(2) inst.components.tackler:AddWorkAction(ACTIONS.CHOP, 15) inst.components.tackler:AddWorkAction(ACTIONS.MINE, 4) inst.components.tackler:AddWorkAction(ACTIONS.HAMMER, 6) inst.components.tackler:SetOnCollideFn(OnTackleCollide) inst.components.tackler:SetOnTrampleFn(OnTackleTrample) inst.components.tackler:SetEdgeDistance(5) what I changed was inst.components.tackler:AddWorkAction(ACTIONS.HAMMER, 6) and inst.components.tackler:AddWorkAction(ACTIONS.CHOP, 15) their numeric values. [SPOILER/] I got another script I would like to edit and it's the were idols, I want to remove the perish component from it. wereitems.lua inst:AddComponent("perishable") inst.components.perishable:SetPerishTime(TUNING.PERISH_FASTISH) inst.components.perishable:StartPerishing() inst.components.perishable.onperishreplacement = "spoiled_food" So I couldn't, so I set a ridiculous perish time under mod main. AddPrefabPostInit ("wereitem_beaver",function(inst) inst.components.edible.healthvalue = 0 inst.components.edible.hungervalue = 0 inst.components.edible.sanityvalue = 0 inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM inst.components.perishable:SetPerishTime(2000) end) AddPrefabPostInit ("wereitem_moose",function(inst) inst.components.edible.healthvalue = 0 inst.components.edible.hungervalue = 0 inst.components.edible.sanityvalue = 0 inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM inst.components.perishable:SetPerishTime(2000) end) AddPrefabPostInit ("wereitem_goose",function(inst) inst.components.edible.healthvalue = 0 inst.components.edible.hungervalue = 0 inst.components.edible.sanityvalue = 0 inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM inst.components.perishable:SetPerishTime(2000) end) Still, I want the perish component to be removed completely. I figured it by borrowing code from a mod that changes food values: https://steamcommunity.com/sharedfiles/filedetails/?id=1208383973 [SPOILER/] The other script is lucy, where I made her deal 1 0 times more damage against treeguards. local function onattack(inst, attacker, target) if target:HasTag("leif") then inst.components.weapon:SetDamage(TUNING.AXE_DAMAGE*10) else inst.components.weapon:SetDamage(TUNING.AXE_DAMAGE) end end inst.components.weapon:SetDamage(TUNING.AXE_DAMAGE) inst.components.weapon:SetOnAttack(onattack) end) Finally I wanted to add the following to lucy: inst:AddInherentAction(ACTIONS.TERRAFORM) inst.components.tool:SetAction(ACTIONS.DIG, 2) inst.components.tool:SetAction(ACTIONS.HAMMER, 2) inst.components.tool:SetAction(ACTIONS.MINE, 2) inst:AddComponent("terraformer") inst:AddComponent("shaver") however it returins a nil value on "actions" if I try to incorporate it in modmain. [SPOILER/] Help. woodie.lua lucy.lua modmain.lua Link to comment Share on other sites More sharing options...
Ultroman Posted September 23, 2019 Share Posted September 23, 2019 2 hours ago, ColombianCam said: what I changed was insert the *2.5 for the weregoose run speed. I'm thinking that maybe I should just use global.tuning and make that value just equal that of *2.5 When you change TUNING variables, you change it for anything else that uses that variable, in this case Weregoose, so it's not a good idea to change them. Woodie is an incredibly complex character in terms of code, and what you're trying to do is almost impossible because all the functions are local, so you have to go through each one to see where they're called and where they're referenced, to see if you can replace them at some point. It looks rather difficult, TBH. I think you'll have a much easier time, if you just made a new character mod and steal woodie's code. That way you have full control over the code. I don't see an easy way to get this to work properly. Mostly because of all the server/client communication happening everywhere in the code. I hope someone else can take a look at find a loophole I didn't see. Link to comment Share on other sites More sharing options...
Serpens Posted September 23, 2019 Share Posted September 23, 2019 (edited) The reason to put as much code you can into modmain and not change original game files is mostly to stay compatible to game updates and also get them. There are many old mods out there that use very old modified game files, so if you enable them you will lack much new content or even get a crash, because another script is trying to call one of the new funcitons that are not included in your own. But sometimes it is better to overwrite the original file: 1) if you want to change nearly everything within the file 2) if you dont want any game updates to add new stuff to the files 3) if there is too much you can not do in modmain (eg. because everything is "local"). Oftens there are workarounds for this, but if 1) or 2) is also true, it is not worth the affort). But then you should compare the new original file with your old modfile from time to time, to see if the devs made changes to the original file you also want/need to include in your modified file. Usually the need to update your mod frequently is lower if you use modmain. I case of your spoiler-code, you see that this is the value for "components.locomotor.runspeed". So all you have to change is this value. In your previous thread I already gave you code to see if woodie is weregoose or sth else. And there you also can put the new runspeed: -- # BEFORE adding runspeed: inst:ListenForEvent("transform_wereplayer",function(inst,data) -- transforms from woodie to data.mode if inst~=nil and data~=nil then if data.mode=="goose" then -- if we transform into goose, change our collision, so we can go over the world edges inst.Physics:ClearCollidesWith(GLOBAL.COLLISION.LIMITS) end end end) -- # after adding runspeed: inst:ListenForEvent("transform_wereplayer",function(inst,data) -- transforms from woodie to data.mode if inst~=nil and data~=nil then if data.mode=="goose" then -- if we transform into goose, change our collision, so we can go over the world edges inst.Physics:ClearCollidesWith(GLOBAL.COLLISION.LIMITS) if inst.components.locomotor ~= nil then inst.components.locomotor.runspeed = TUNING.WEREGOOSE_RUN_SPEED*2.5 end end end end) Edited September 25, 2019 by Serpens Link to comment Share on other sites More sharing options...
ColombianCam Posted September 23, 2019 Author Share Posted September 23, 2019 it doesn't work. I tried putting the parenthesis around the runspeed value, going back before runspeed and just pasting underneath inst.Physics:ClearCollidesWith(GLOBAL.COLLISION.LIMITS) inst.components.locomotor.runspeed = TUNING.WEREGOOSE_RUN_SPEED*2.5) Link to comment Share on other sites More sharing options...
Ultroman Posted September 23, 2019 Share Posted September 23, 2019 You can't have a closing parenthesis without a starting parenthesis. inst.components.locomotor.runspeed = TUNING.WEREGOOSE_RUN_SPEED * 2.5 You seem to be missing key knowledge about the Lua language. To spare yourself much pain and trial and error, take the time to go through the Lua Crash Course linked in this post and perhaps some more tutorials on the language. I promise, it will ease the work for you. Link to comment Share on other sites More sharing options...
ColombianCam Posted September 23, 2019 Author Share Posted September 23, 2019 I've solved most problems by directly changing the tuning values by using requires tuning, however I can't still change exactly the weremoose and beaver workable actions to be more efficent, it crashes when I use workmultiplier.lua, The value of tackle work 2 is equivalent to honeycristals. AddStategraphPostInit("wilson",function(sg) if sg.states.tackle_pre~=nil then local old_onexit = sg.states.tackle_pre.onexit local function new_onexit(inst,...) -- print("tackle_pre") inst.components.combat.externaldamagemultipliers:SetModifier("TackleDamage", 1.5) if inst.components.workmultiplier ~= nil then inst.components.workmultiplier:AddMultiplier:SetModifier("TackleWork", 2) return old_onexit(inst,...) sg.states.tackle_pre.onexit = new_onexit end if sg.states.tackle_stop~=nil then local old_onexit = sg.states.tackle_stop.onexit local function new_onexit(inst,...) -- print("tackle_stop") inst.components.workmultiplier:RemoveMultiplier:RemoveModifier("TackleWork") inst.components.combat.externaldamagemultipliers:RemoveModifier("TackleDamage") elseif inst.components.workmultiplier ~= nil then inst.components.workmultiplier:RemoveMultiplier:RemoveModifier("TackleWork") end return old_onexit(inst,...) sg.states.tackle_stop.onexit = new_onexit end if sg.states.tackle_collide~=nil then -- when colliding with something, tackle_stop is not called, so we have to revert the damage to normal here local old_onexit = sg.states.tackle_collide.onexit local function new_onexit(inst,...) -- print("tackle_collide") elseif inst.components.workmultiplier ~= nil then inst.components.workmultiplier:RemoveMultiplier:RemoveModifier("TackleWork") return old_onexit(inst,...) sg.states.tackle_collide.onexit = new_onexit end end) I couldn't get it to work so I just used directly the honey crystals buff; It's exactly what I intended in relation to work values, where I wanted the tackle to go from 8 - to 15, but instead with honey crystals it goes to 16. AddStategraphPostInit("wilson",function(sg) if sg.states.tackle_pre~=nil then local old_onexit = sg.states.tackle_pre.onexit local function new_onexit(inst,...) -- print("tackle_pre") inst.components.debuffable:AddDebuff("buff_workeffectiveness", "buff_workeffectiveness") inst.components.combat.externaldamagemultipliers:SetModifier("TackleDamage", 1.5) return old_onexit(inst,...) end sg.states.tackle_pre.onexit = new_onexit end if sg.states.tackle_stop~=nil then local old_onexit = sg.states.tackle_stop.onexit local function new_onexit(inst,...) -- print("tackle_stop") inst.components.debuffable:RemoveDebuff("buff_workeffectiveness", "buff_workeffectiveness") inst.components.combat.externaldamagemultipliers:RemoveModifier("TackleDamage") return old_onexit(inst,...) end sg.states.tackle_stop.onexit = new_onexit end if sg.states.tackle_collide~=nil then -- when colliding with something, tackle_stop is not called, so we have to revert the damage to normal here local old_onexit = sg.states.tackle_collide.onexit local function new_onexit(inst,...) -- print("tackle_collide") inst.components.debuffable:RemoveDebuff("buff_workeffectiveness", "buff_workeffectiveness") inst.components.combat.externaldamagemultipliers:RemoveModifier("TackleDamage") return old_onexit(inst,...) end sg.states.tackle_collide.onexit = new_onexit end end) Link to comment Share on other sites More sharing options...
Serpens Posted September 25, 2019 Share Posted September 25, 2019 On 23.9.2019 at 4:18 PM, ColombianCam said: it doesn't work. I tried putting the parenthesis around the runspeed value, going back before runspeed and just pasting underneath inst.Physics:ClearCollidesWith(GLOBAL.COLLISION.LIMITS) inst.components.locomotor.runspeed = TUNING.WEREGOOSE_RUN_SPEED*2.5) sry the parenthesis was my mistake when copy pasting from your code where the parenthesis was right yes, your workmultiplier code is wrong: Quote workmultiplier:AddMultiplier:SetModifier("TackleWork", 2) this should also look strange to you. 1) 2 times a ":", you use ":" when calling a function. and when calling a function there must be (...) after the next word, just like you see it everywhere. But in this case adding () would still be wrong, because we dont want to call 2 functions. AddMultiplier and SetModifier already sounds like it would do mostly the ame, and so it is. So oyu can only use one of them. In this case you have to use AddMultiplier. Just open workmultiplier.lua and you will see those functions (same for Remove...) But to be fair, it is not that easy to see when to use which of them, if you are a beginner. But you should have learned to not use both of them for the same thing and not within the same statement. A try of explanation when to use what: You use Set/Remove-Modifier whenever you are directly accessing a SourceModifierList. To see if that is the case you have to read the component code. In case of the combat component and the externaldamagemultipler you will find "self.externaldamagemultipliers = SourceModifierList(self.inst)" . so when dealing with the externaldamagemultipliers, you have to use SetModifier. And now look at the code of workmultiplier. We have SourceModifierList there, but it is packed into "self.actions[action] = SourceModifierList..." and you see that there are already functions like "AddMultiplier" that already does SetModifier at the bottom of said function. So AddMultiplier is a helper function, to make it easier for you to deal with this self.actions[action] construction. So dont use SetModifier in this case, but the helper functions of workmultiplier. You should read and try to understand the error messages. Go to the line that is mentioned in the error message (within your logfile) and then try to find the error there. Most of the time it is easy, sometimes it is more difficult, then you can ask here. But after we told you the problem, try to understand it, so the next time you have the same issue, you will know the solution yourself 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