BombardmentPigs Posted November 20, 2023 Share Posted November 20, 2023 (edited) Hello, I would like to know how to call a function after a specific tool action. For example, I might call function 1 when the prefab is used to chop a tree, call function 2 when mining, function 3 when digging, etc. By the way, this is for a prefab that can chop, mine, dig, hammer, and till. I know there is already a "ListenForEvent" thing but I can't seem to find a list of the events it can hear. So, where might I find this list? (if it exists and contains what I need) Any help would be appreciated! Edited November 25, 2023 by BombardmentPigs Link to comment Share on other sites More sharing options...
LeafyFly Posted November 20, 2023 Share Posted November 20, 2023 -- scripts/components/workable.lua worker:PushEvent("working", { target = self.inst }) Link to comment Share on other sites More sharing options...
ClumsyPenny Posted November 20, 2023 Share Posted November 20, 2023 7 minutes ago, LeafyFly said: -- scripts/components/workable.lua worker:PushEvent("working", { target = self.inst }) This doesn't really help. It doesn't tell you what action did the work and also it wouldn't run on Till, since it's not a work action. 2 hours ago, BombardmentPigs said: I know there is already a "ListenForEvent" thing but I can't seem to find a list of the events it can hear. So, where might I find this list? (if it exists and contains what I need) I don't think there's a convenient list of events, you sort just look for an event being pushed in the relevant components or other places. Unfortunately, I can't quite find an event that also sends the action inside the data. But I have an other idea! If you're willing to make a component (it's very easy, I'll guide you through it if needed), just have a function in this component called OnUsedAsItem(action, doer, target). The game runs this function on every component of an inventory item that is performing an action, as long as the component has this function, obviously. Right now it's only used by finiteuses to consume durability, but nothing stops you from using it yourself. Link to comment Share on other sites More sharing options...
LeafyFly Posted November 20, 2023 Share Posted November 20, 2023 6 minutes ago, ClumsyPenny said: This doesn't really help. It doesn't tell you what action did the work and also it wouldn't run on Till, since it's not a work action. local on_working = function(worker, data) local tool = worker and worker.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) local target = data and data.target local workable = target and target.components.workable if tool and tool.prefab == "your_tools_prefab_name" and workable then if workable.action == ACTIONS.CHOP then function1() elseif workable.action == ACTIONS.MINE then function2() elseif workable.action == ACTIONS.HAMMER then function3() end end end local onequip = function(inst, owner) --...... if owner:HasTag("player") then inst:ListenForEvent("working", on_working, owner) end end local onunequip = function(inst, owner) --...... if owner:HasTag("player") then inst:RemoveEventCallback("working", on_working, owner) end end -- scripts/components/farmtiller.lua function FarmTiller:Till(pt, doer) if TheWorld.Map:CanTillSoilAtPoint(pt.x, 0, pt.z, false) then TheWorld.Map:CollapseSoilAtPoint(pt.x, 0, pt.z) SpawnPrefab("farm_soil").Transform:SetPosition(pt:Get()) if doer ~= nil then doer:PushEvent("tilling") end return true end return false end Link to comment Share on other sites More sharing options...
Rickzzs Posted November 21, 2023 Share Posted November 21, 2023 (edited) maybe listen for owner's performaction event? Edited November 21, 2023 by Rickzzs Link to comment Share on other sites More sharing options...
BombardmentPigs Posted November 23, 2023 Author Share Posted November 23, 2023 (edited) Thanks for all your ideas everyone, I will try them when I have time. Edited November 23, 2023 by BombardmentPigs Link to comment Share on other sites More sharing options...
BombardmentPigs Posted November 24, 2023 Author Share Posted November 24, 2023 Alright, I tried to make a component with the OnUsedAsItem function, and added the custom component into my prefab, but the server crashed upon equipping the item. The code for the component is this: (Component is called multitoolsorter by the way) local MultiToolSorter = Class(function(self, inst) self.inst = inst end, nil, { --empty }) function ChopDeduct(self) self.inst.components.fueled:DoDelta(-120) end function HammerDeduct(self) self.inst.components.fueled:DoDelta(-120) end function DigDeduct(self) self.inst.components.fueled:DoDelta(-120) end function MineDeduct(self) self.inst.components.fueled:DoDelta(-120) end function MultiToolSorter:OnUsedAsItem(action, doer, target) if target.components.workable.action == ACTIONS.CHOP then ChopDeduct() elseif target.components.workable.action == ACTIONS.HAMMER then HammerDeduct() elseif target.components.workable.action == ACTIONS.DIG then DigDeduct() elseif target.components.workable.action == ACTIONS.MINE then MineDeduct() end end return MultiToolSorter The error in the server log is this: Quote [00:01:46]: [string "../mods/Mymod/scripts/component..."]:27: attempt to index local 'target' (a nil value) I looked into the finiteuses component but I couldn't see anything defining 'target', nor was there anything doing that inside of an item that has the finiteuses component, like the spear. This confused me as I now don't know how to define target to fix this. Assistance would be appreciated! Link to comment Share on other sites More sharing options...
ClumsyPenny Posted November 24, 2023 Share Posted November 24, 2023 (edited) 1 hour ago, BombardmentPigs said: I looked into the finiteuses component but I couldn't see anything defining 'target', nor was there anything doing that inside of an item that has the finiteuses component, like the spear. This confused me as I now don't know how to define target to fix this. OnUsedAsItem is run in entityscript.lua with all the relevant parameters, that's where the "target" parameter comes from. The reason it's nil is likely because some actions don't necessarily have a target, you have to keep in mind this is being run for every action possible you perform with that item, even something as simple as "Examine". All you have to do is simply add a check for target not being nil. Having checks like that is generally good practice anyway! Edited November 24, 2023 by ClumsyPenny Link to comment Share on other sites More sharing options...
BombardmentPigs Posted November 24, 2023 Author Share Posted November 24, 2023 11 hours ago, ClumsyPenny said: All you have to do is simply add a check for target not being nil. Having checks like that is generally good practice anyway! Got it, thanks. I added the check and it no longer crashes on equipping, but it crashes whenever it tries to chop, hammer, etc. The error is this: Quote [00:02:22]: [string "../mods/Mymod/scripts/component..."]:6: attempt to index local 'self' (a nil value) The code in the component now is this: local MultiToolSorter = Class(function(self, inst) self.inst = inst end) function ChopDeduct(self, inst) self.inst.components.fueled:DoDelta(-120) end function HammerDeduct(self, inst) self.inst.components.fueled:DoDelta(-120) end function DigDeduct(self, inst) self.inst.components.fueled:DoDelta(-120) end function MineDeduct(self, inst) self.inst.components.fueled:DoDelta(-120) end function MultiToolSorter:OnUsedAsItem(action, doer, target) if target ~= nil then if target.components.workable.action == ACTIONS.CHOP then ChopDeduct() elseif target.components.workable.action == ACTIONS.HAMMER then HammerDeduct() elseif target.components.workable.action == ACTIONS.DIG then DigDeduct() elseif target.components.workable.action == ACTIONS.MINE then MineDeduct() end end end return MultiToolSorter A similar error happens if I remove the 'self' part and it instead says that 'inst' is nil. This happens on all 4 functions (ChopDeduct, HammerDeduct, etc.) which are triggered when I chop, hammer, etc. Link to comment Share on other sites More sharing options...
ClumsyPenny Posted November 24, 2023 Share Posted November 24, 2023 2 minutes ago, BombardmentPigs said: A similar error happens if I remove the 'self' part and it instead says that 'inst' is nil. Well, you're not providing any arguments when calling the functions. Why are you functions global and not part of the component, anyway? Without changing anything about your code, fixing would be a simple as changing this in OnUsedAsItem (do the same for the other 3, obviously): ChopDeduct(self, self.inst) But I'd recommend making the functions part of the component: function MultiToolSorter:ChopDeduct() self.inst.components.fueled:DoDelta(-120) end And the other one: self:ChopDeduct() The reason you don't need any arguments here is because self is already being given as an argument by virtue of using the colon, and inst is referenced inside self as self.inst. 1 Link to comment Share on other sites More sharing options...
BombardmentPigs Posted November 24, 2023 Author Share Posted November 24, 2023 1 hour ago, ClumsyPenny said: Well, you're not providing any arguments when calling the functions. Why are you functions global and not part of the component, anyway? Without changing anything about your code, fixing would be a simple as changing this in OnUsedAsItem (do the same for the other 3, obviously): ChopDeduct(self, self.inst) But I'd recommend making the functions part of the component: function MultiToolSorter:ChopDeduct() self.inst.components.fueled:DoDelta(-120) end And the other one: self:ChopDeduct() The reason you don't need any arguments here is because self is already being given as an argument by virtue of using the colon, and inst is referenced inside self as self.inst. It worked perfectly for all the actions except tilling! Thanks! The problem now is how do I get the tilling to work? I have this in my prefab but my fuel doesn't go down when I till. local function OnTill(inst, data) inst.components.fueled:DoDelta(-120/35) end --In MainFunction: inst:ListenForEvent("tilling", OnTill) Link to comment Share on other sites More sharing options...
Hornete Posted November 25, 2023 Share Posted November 25, 2023 3 hours ago, BombardmentPigs said: It worked perfectly for all the actions except tilling! Thanks! The problem now is how do I get the tilling to work? I have this in my prefab but my fuel doesn't go down when I till. local function OnTill(inst, data) inst.components.fueled:DoDelta(-120/35) end --In MainFunction: inst:ListenForEvent("tilling", OnTill) The `tilling` event is pushed to the player using the till tool, rather than the tool itself, which is why this does not work properly. You should be able to have your implementation performed in OnUsedAsItem, same with the rest of the actions, though there is no target entity in the action of tilling of course. But perform a conditional for whether the action is the till action and deduct fuel afterwards. Thinking on it, it'd likely be a small (but good) optimization to cut out the middleman checks for target and indexes into the workable component and simply use the `action` parameter provided. But if your current implementation is what makes sense to you, then that is perfectly fine! 2 Link to comment Share on other sites More sharing options...
BombardmentPigs Posted November 25, 2023 Author Share Posted November 25, 2023 8 minutes ago, Hornete said: The `tilling` event is pushed to the player using the till tool, rather than the tool itself, which is why this does not work properly. You should be able to have your implementation performed in OnUsedAsItem, same with the rest of the actions, though there is no target entity in the action of tilling of course. But perform a conditional for whether the action is the till action and deduct fuel afterwards. Thinking on it, it'd likely be a small (but good) optimization to cut out the middleman checks for target and indexes into the workable component and simply use the `action` parameter provided. But if your current implementation is what makes sense to you, then that is perfectly fine! Thanks very much, now everything works perfectly! Thanks to everyone who helped me. Here's the component code in case anyone needs it: local MultiToolSorter = Class(function(self, inst) self.inst = inst end) function MultiToolSorter:ChopDeduct() self.inst.components.fueled:DoDelta(-120/130) end function MultiToolSorter:HammerDeduct() self.inst.components.fueled:DoDelta(-120/95) end function MultiToolSorter:DigTillDeduct() --btw I deduct the same amount of fuel for both dig and till so they all call the same function self.inst.components.fueled:DoDelta(-120/35) end function MultiToolSorter:MineDeduct() self.inst.components.fueled:DoDelta(-120/50) end function MultiToolSorter:OnUsedAsItem(action, doer, target) if action == ACTIONS.CHOP then self:ChopDeduct() elseif action == ACTIONS.HAMMER then self:HammerDeduct() elseif action == ACTIONS.DIG then self:DigTillDeduct() elseif action == ACTIONS.MINE then self:MineDeduct() elseif action == ACTIONS.TILL then self:DigTillDeduct() end end return MultiToolSorter 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