wowcobo Posted January 20, 2015 Share Posted January 20, 2015 So im fairly new to modding dont starve, and im trying to make a character. The idea is that just like how you get a little sanity when you pick a flower, this character also gets a little sanity when she pants a pinecone. i have tried messing with some code that looks a little like this: local function sanity_onplant:pinecone(cause) inst.components.sanity:DoDelta(TUNING.SANITY_TINY)endinst:ListenForEvent("onplant",DoDelta) but it just crashesdoes anyone have any tips on how i could fix the formatting on this code or how i could find/write the correct code for what im trying to do? Link to comment Share on other sites More sharing options...
Corrosive Posted January 21, 2015 Share Posted January 21, 2015 Hey, I'm fairly new to modding as well, so there /may/ be a "best practice" way of doing this I'm not aware of, but for all intents and purposes, the answer below should work fine. Instead of using event listeners(which I believe are a bit more low level than your typical lua script), you might want to try simply overriding the "ondeploy" function. Note, however that since the ondeploy function is declared as "local function", you wont have access to it. What you do have access to is the deployable component-- overriding the function is as simple as giving deployable.ondeploy a new version of the ondeploy function. Here's how you might achieve that, with comments describing what's going on.GLOBAL.require "tuning"--We need to import some things from the GLOBAL namespaceGetRandomWithVariance = GLOBAL.GetRandomWithVarianceRemovePhysicsColliders = GLOBAL.RemovePhysicsCollidersGetTime = GLOBAL.GetTime-- Note that the ondeploy function calls this function in pinecone.lue. Since it is declared as a local function-- there, we need to include it here.local function plant(inst, growtime) inst:RemoveComponent("inventoryitem") RemovePhysicsColliders(inst) inst.AnimState:PlayAnimation("idle_planted") inst.SoundEmitter:PlaySound("dontstarve/wilson/plant_tree") inst.growtime = GetTime() + growtime print ("PLANT", growtime) inst.growtask = inst:DoTaskInTime(growtime, growtree)end-- This is effectively a clone of the original function... with one exception. The original function didn't pass -- the "deployer" variable, which is needed to figure out who to apply the sanity gain to. Note that unlike many-- languages, LUA doesn't require that you call a function using the same number of arguments that it is defined-- with. Looking in component's definition file, deployable.lua, the ondeploy function is actually declared as:---- function Deployable:Deploy(pt, deployer)---- That means that it IS in fact passing a reference to the deployer, so we can add it to our list of arguments.local function ondeployOverride (inst, pt, deployer) -- This is the only thing that needed to be added. deployer.components.sanity:DoDelta(TUNING.SANITY_TINY) inst = inst.components.stackable:Get() inst.Transform:SetPosition(pt:Get() ) local timeToGrow = GetRandomWithVariance(TUNING.PINECONE_GROWTIME.base, TUNING.PINECONE_GROWTIME.random) plant(inst, timeToGrow) --tell any nearby leifs to chill out local ents = TheSim:FindEntities(pt.x,pt.y,pt.z, TUNING.LEIF_PINECONE_CHILL_RADIUS, {"leif"}) local played_sound = false for k,v in pairs(ents) do local chill_chance = TUNING.LEIF_PINECONE_CHILL_CHANCE_FAR if distsq(pt, Vector3(v.Transform:GetWorldPosition())) < TUNING.LEIF_PINECONE_CHILL_CLOSE_RADIUS*TUNING.LEIF_PINECONE_CHILL_CLOSE_RADIUS then chill_chance = TUNING.LEIF_PINECONE_CHILL_CHANCE_CLOSE end if math.random() < chill_chance then if v.components.sleeper then v.components.sleeper:GoToSleep(1000) end else if not played_sound then v.SoundEmitter:PlaySound("dontstarve/creatures/leif/taunt_VO") played_sound = true end end end end-- Create a function to pass to addPrefabPostInitlocal function pineconeMod(inst) inst.components.deployable.ondeploy = ondeployOverrideend-- And finally, register it to the list of functions to be run on the pinecone prefabAddPrefabPostInit("pinecone", pineconeMod) Link to comment Share on other sites More sharing options...
Blueberrys Posted January 26, 2015 Share Posted January 26, 2015 @wowcobo, @Corrosive For the sake of DRY, here's another way to implement it without rewriting the function as it was.local function pineconeMod(inst) inst.old_ondeploy = inst.components.deployable.ondeploy inst.components.deployable.ondeploy = function(inst, pt, deployer) inst:old_ondeploy(pt) deployer.components.sanity:DoDelta(TUNING.SANITY_TINY) endendAddPrefabPostInit("pinecone", pineconeMod)(Theoretical code, not tested) This should also improve compatibility with other mods. Link to comment Share on other sites More sharing options...
SenL Posted January 30, 2015 Share Posted January 30, 2015 It works. Thanks Blueberrys. Link to comment Share on other sites More sharing options...
Corrosive Posted January 30, 2015 Share Posted January 30, 2015 @Blueberrys Good call. I'm so used to programming environments where every function is frustratingly protected <.< Link to comment Share on other sites More sharing options...
SenL Posted February 1, 2015 Share Posted February 1, 2015 Hi Blueberrys The code works as host buit as client, even when that char is not being used at all (mod is enabled but not used), client crashes.Log: ...[string "../mods/mychar/modmain.lua"]:61: attempt to index field 'deployable' (a nil value)... Help? Edit: whoops, probably should post @ DST instead... Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.
Please be aware that the content of this thread may be outdated and no longer applicable.