Sketchiverse Posted March 21, 2015 Share Posted March 21, 2015 Hello forum, So I've been working on adding a new item for my character. It's a kind of bell, just like the Old Bell, so I'm trying to use the same animation as the Old Bell does. So I did it, and it works only in RoG, obviously. Because the Old Bell only exists in RoG, and therefore so does the character bell ringing animation. Then I need to bring that anim state to the base game when my character mod is activated. I looked around the files and I found this in DLC001/stategraphs/SGwilson : actionhandlers = { -- .... ActionHandler(ACTIONS.PLAY, function(inst, action) if action.invobject then if action.invobject:HasTag("flute") then return "play_flute" elseif action.invobject:HasTag("horn") then return "play_horn" elseif action.invobject:HasTag("bell") then return "play_bell" end end end), -- ....}and also this:states = { -- .... State{ name = "play_bell", tags = {"doing", "playing"}, onenter = function(inst) inst.components.locomotor:Stop() inst.AnimState:PlayAnimation("bell") inst.AnimState:OverrideSymbol("bell01", "bell", "bell01") --inst.AnimState:Hide("ARM_carry") inst.AnimState:Show("ARM_normal") if inst.components.inventory.activeitem and inst.components.inventory.activeitem.components.instrument then inst.components.inventory:ReturnActiveItem() end end, onexit = function(inst) if inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) then inst.AnimState:Show("ARM_carry") inst.AnimState:Hide("ARM_normal") end end, timeline= { TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/common/glommer_bell") end), TimeEvent(60*FRAMES, function(inst) inst:PerformBufferedAction() end), }, events= { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end), }, }, -- ....} Now I assume these are the stategraphs for the character's bell ringing animation. They're not included in the base game. I want to add them to the normal character stategraph, preferably using functions like AddStateGraphPostInit, that I found thanks to Corrosive's topic here, but I don't know how to use them exactly. For now I tried a few things like adding the code you see up here in my modmain.lua and then...?if not IsDLCEnabled(REIGN_OF_GIANTS) then AddStategraphActionHandler("SGwilson", function(inst) --[[ actionhandlers ??? ]] end) AddStategraphState("SGwilson", function(inst) --[[ states ??? ]] end)endI know I could make an entire SGwilburn.lua just for my character (his name is Wilburn) but that seems a bit too much and I want to make clean code if possible. Thanks a lot for helping. By the way if you want to see the current version of the character you can go here. It is kind of complete, I'm just trying to add some content. Link to comment Share on other sites More sharing options...
Blueberrys Posted March 21, 2015 Share Posted March 21, 2015 @Sketchiverse Check out the stategraph portions of the API examples mod. Copied here for convenience.------------------------------------- Actions and Handlers---- AddAction(action)-- Puts a new action into the global actions table and sets up the basic-- string for it.---- AddStategraphActionHandler("stategraphname", newActionHandler)-- Appends a handler for your action (or an existing action!) to an-- existing stategraph.-------------------------------------local Action = GLOBAL.Actionlocal ActionHandler = GLOBAL.ActionHandlerlocal MYACT = Action(3)MYACT.str = "Do My Action"MYACT.id = "MYACT"MYACT.fn = function(act) print(act.doer.. " is doing my action!")endAddAction(MYACT)AddStategraphActionHandler("wilson", ActionHandler(MYACT, "doshortaction"))------------------------------------- Stategraph mod example---- AddStategraphState("stategraphname", newState)-- AddStategraphEvent("stategraphname", newEvent)-- AddStategraphActionHandler("stategraphname", newActionHandler)-- Use these functions to append new states, events, and actions handlers-- to existing states.---- AddStategraphPostInit("stategraphname", initfn)-- Use this to modify and mangle existing stategraphs, such as digging-- into existing states or appending new functionality to existing-- handlers.-- -----------------------------------local State = GLOBAL.Statelocal TimeEvent = GLOBAL.TimeEventlocal EventHandler = GLOBAL.EventHandlerlocal FRAMES = GLOBAL.FRAMESlocal spinstate = State({ name = "spin_around", tags = {"idle", "canrotate"}, onenter = function(inst) inst.Transform:SetRotation(0) inst.AnimState:PushAnimation("idle_loop", true) end, timeline = { TimeEvent(20*FRAMES, function(inst) inst.Transform:SetRotation(90) end), TimeEvent(40*FRAMES, function(inst) inst.Transform:SetRotation(180) end), TimeEvent(60*FRAMES, function(inst) inst.Transform:SetRotation(270) end), TimeEvent(80*FRAMES, function(inst) inst.Transform:SetRotation(0) end), TimeEvent(100*FRAMES, function(inst) inst.sg:GoToState("idle") end), }, events = { },})local newIdleTimeout = function(inst) if math.random() < 0.5 then inst.sg:GoToState("funnyidle") else inst.sg:GoToState("spin_around") endendlocal function SGWilsonPostInit(sg) -- note! This overwrites the old timeout behavior! If possible you should -- always try appending your behaviour instead. sg.states["idle"].ontimeout = newIdleTimeoutendAddStategraphState("wilson", spinstate)AddStategraphPostInit("wilson", SGWilsonPostInit) Link to comment Share on other sites More sharing options...
Sketchiverse Posted March 21, 2015 Author Share Posted March 21, 2015 @Blueberrys It worked !! Thank you Blueberrys ! I'll rely on these API examples more often from now on.Have a good day ! For those who want to see how it looks in my case :In modmain.lua:local State = GLOBAL.Statelocal Action = GLOBAL.Actionlocal ActionHandler = GLOBAL.ActionHandlerlocal TimeEvent = GLOBAL.TimeEventlocal EventHandler = GLOBAL.EventHandlerlocal ACTIONS = GLOBAL.ACTIONSlocal FRAMES = GLOBAL.FRAMES-- Adding the bell ringing animation from Reign of Giants.local bell_handler = ActionHandler(ACTIONS.PLAY, function(inst, action) if action.invobject then if action.invobject:HasTag("flute") then return "play_flute" elseif action.invobject:HasTag("horn") then return "play_horn" elseif action.invobject:HasTag("bell") then return "play_bell" end end end)local bell_state = State{ name = "play_bell", tags = {"doing", "playing"}, onenter = function(inst) inst.components.locomotor:Stop() inst.AnimState:PlayAnimation("bell") inst.AnimState:OverrideSymbol("bell01", "bell", "bell01") --inst.AnimState:Hide("ARM_carry") inst.AnimState:Show("ARM_normal") if inst.components.inventory.activeitem and inst.components.inventory.activeitem.components.instrument then inst.components.inventory:ReturnActiveItem() end end, onexit = function(inst) if inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) then inst.AnimState:Show("ARM_carry") inst.AnimState:Hide("ARM_normal") end end, timeline= { TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/common/glommer_bell") end), TimeEvent(60*FRAMES, function(inst) inst:PerformBufferedAction() end), }, events= { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end), }, }if not IsDLCEnabled(REIGN_OF_GIANTS) then AddStategraphActionHandler("wilson", bell_handler) AddStategraphState("wilson", bell_state)end Link to comment Share on other sites More sharing options...
Sketchiverse Posted March 22, 2015 Author Share Posted March 22, 2015 @Blueberrys Okay, so I went a bit further, added the actual code for the item's effect in-game, but something is really odd : it works only in RoG...! ... again, I know, but the problem is different.I'm stuck again and I can't find a way, I've been trying for half a day already Looking back up in my code, I wrote this (modmain.lua) : local bell_state = State{--.... timeline = { TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/<mycustomsound>") end), TimeEvent(30*FRAMES, function(inst) inst:PerformBufferedAction() end), }--....} and that inst:PerformBufferedAction() is supposed to... call the OnPlayed function described in my prefab's file (or something like that) Well, this works perfectly in RoG, but not in the base game, and I'd rather have a fully compatible mod. I've searched for issues involving this function on the forums but it didn't help. Anyone has an idea...? Sorry again, I'm really doing my best here... To be precise, in non-RoG, upon using the bell item, it successfully plays the bell animation and the <mycustomsound> I specified in the code up here... but the effect in my bell's OnPlayed function doesn't happen. I tested it with a print("something") at the start of OnPlayed and it doesn't show up. The item consumption still occurs though, so it must be going to the prefab's file at some point... Also just for clarifying, I removed the IsDLCEnabled condition at the end. It's useless and I wouldn't be able to correctly change my custom bell's sound if I left it. Link to comment Share on other sites More sharing options...
Blueberrys Posted March 22, 2015 Share Posted March 22, 2015 @Sketchiverse Hmm. What does your action look like? The path from PerformBufferedActionEntityScript:PerformBufferedAction() > EntityScript.bufferedaction:Do() > BufferedAction.action.fn(self) From there, I need to know what your action's fn is. Link to comment Share on other sites More sharing options...
Sketchiverse Posted March 23, 2015 Author Share Posted March 23, 2015 @Blueberrys I didn't make a new action, I'm using ACTIONS.PLAY and I just changed wilson's stategraph's action handler and state. Do I need to edit ACTIONS.PLAY.fn ? The api example isn't very clear to me... It says that you can make a new action and edit its action.fn, and it puts a print("doing action") or something in it, but what if I didn't create an action ? In actions.lua for the base game and for RoG, the function is :ACTIONS.PLAY.fn = function(act) if act.invobject and act.invobject.components.instrument then return act.invobject.components.instrument:Play(act.doer) endend Link to comment Share on other sites More sharing options...
Blueberrys Posted March 23, 2015 Share Posted March 23, 2015 @Sketchiverse No, you don't need to edit it. I just needed to know what the action's fn is doing. The instrument component in base DS doesn't call any onplayed function.(instrument.lua) copied for referencefunction Instrument:Play(musician) local pos = Vector3(musician.Transform:GetWorldPosition()) local ents = TheSim:FindEntities(pos.x,pos.y,pos.z, self.range) for k,v in pairs(ents) do if v ~= self.inst and self.onheard then self.onheard(v, musician, self.inst) end end return true end You will need to either add that in yourself, or find another work around.Use this to add it.AddComponentPostInit("instrument", function(inst) local oldPlay = inst.Play function inst:Play(musician) if self.onplayed then self.onplayed(self.inst, musician) end return oldPlay(self, musician) endend)Edit: Also, use [ member='Blueberrys' ] to give me a notification (without the spaces). Edit 2: Fixed error mentioned below (oldPlay invalid and pass self to oldPlay) Link to comment Share on other sites More sharing options...
Sketchiverse Posted March 23, 2015 Author Share Posted March 23, 2015 @Blueberrys Ohh I see now ! I didn't think about it, I didn't really understand how it all worked, the whole thing with actions and components etc. ^^' I guess that's how you learn. Thanks a lot for your help again ! I didn't change the instrument component with AddComponentPostInit as you told me, though. That crashed because musician was nil. I did this, just for the records :local Vector3 = GLOBAL.Vector3local Instrument = require "components/instrument"local Base_Instrument_Play = Instrument.Play function Instrument:Play(musician) --Instruction that was only in RoG if self.onplayed then self.onplayed(self.inst, musician) end ---------------------------------- local pos = Vector3(musician.Transform:GetWorldPosition()) local ents = TheSim:FindEntities(pos.x,pos.y,pos.z, self.range) for k,v in pairs(ents) do if v ~= self.inst and self.onheard then self.onheard(v, musician, self.inst) end end return true endIt works perfectly now (if I've made enough testing) I can work on the rest of the update Bye bye, thanks again ! Link to comment Share on other sites More sharing options...
Blueberrys Posted March 23, 2015 Share Posted March 23, 2015 @Sketchiverse Whoops, forgot to pass self. I fixed it now. I would recommend that you try to preserve the original function instead of overwriting it completely. Try my code again, if you have the time. Edit: Andd.. also forgot to change how oldPlay is declared, fixed that too. 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.