lucas_risada Posted July 28, 2017 Share Posted July 28, 2017 Hey, everyone! I am creating a mod with electrical tools, including chainsaw and mining drill. So far, I started to program only the chainsaw. I began creating a component called "electicalTool" inspired in the "tool" component. I had an idea of doing the tools to work and deal damage over time, instead of doing multiple successive actions like the axe and pickaxe. I don't know if I will keep it this way, but this is the way it works now (I need to include a range check, I know it): local ACTION_DELAY = 0.3 local ElectricalTool = Class(function(self, inst) self.inst = inst self.target = nil self.onWork = nil self.onFinishedWork = nil end) -------------------------------------------------------------------------- function ElectricalTool:SetOnWorkFn(fn) self.onWork = fn end function ElectricalTool:SetOnFinishedWorkFn(fn) self.onFinishedWork = fn end -------------------------------------------------------------------------- local periodicTask = nil function WorkTask (self, doer, invobject, target) if target.components.workable ~= nil and target.components.workable:CanBeWorked() and ((target.components.workable.action == ACTIONS.CHOP and invobject.components.tool:CanDoAction (ACTIONS.CUTDOWN))) then --or (target.components.workable.action == ACTIONS.MINE and invobject.components.tool:CanDoAction (ACTIONS.DRILL))) then target.components.workable:WorkedBy( doer, --10 ( invobject ~= nil and invobject.components.tool ~= nil and invobject.components.tool:GetEffectiveness(ACTIONS.CUTDOWN) ) or ( doer ~= nil and doer.components.worker ~= nil and doer.components.worker:GetEffectiveness(ACTIONS.CUTDOWN) ) or 1 ) if self.onWork ~= nil then self.onWork(self.inst) end else self.FinishedWork (self.inst) if self.onFinishedWork ~= nil then self.onFinishedWork(self.inst) end end end function ElectricalTool:FinishedWork (inst) periodicTask:Cancel() periodicTask = nil end function ElectricalTool:Work(doer, invobject, target) if (periodicTask == nil) then periodicTask = self.inst:DoPeriodicTask (ACTION_DELAY, function () WorkTask (self, doer, invobject, target) end) WorkTask (self, doer, invobject, target) end end return ElectricalTool This is the chainsaw prefab code: local CHAINSAW_EFFECTIVENESS = 1 local assets = { Asset ("ANIM", "anim/chainsaw.zip"), Asset ("ANIM", "anim/swap_chainsaw.zip"), Asset ("ATLAS", "images/inventory_images/chainsaw.xml"), Asset ("IMAGE", "images/inventory_images/chainsaw.tex"), Asset("SOUNDPACKAGE", "sound/chainsaw.fev"), Asset("SOUND", "sound/chainsaw.fsb"), } local prefabs = { } local equipped = false local startedRevSound = false local function OnWork (inst) print ("Working") inst.SoundEmitter:KillAllSounds() inst.SoundEmitter:PlaySound ("chainsaw/chainsaw/rev", "rev") end local function OnFinishedWork (inst) print ("Finished Work") --inst.SoundEmitter:KillAllSounds() inst.SoundEmitter:KillSound ("rev") inst.SoundEmitter:PlaySound ("chainsaw/chainsaw/idle", "idle") end local function ChainsawFunction (colour) local function OnEquip (inst, owner) owner.AnimState:OverrideSymbol ("swap_object", "swap_chainsaw", "swap_chainsaw") owner.AnimState:Show ("ARM_carry") owner.AnimState:Hide ("ARM_normal") inst.SoundEmitter:KillAllSounds() inst.SoundEmitter:PlaySound ("chainsaw/chainsaw/equip", "equip") owner:AddTag ("playerghost") equipped = true end local function OnUnequip (inst, owner) owner.AnimState:Hide ("ARM_carry") owner.AnimState:Show ("ARM_normal") inst.SoundEmitter:KillSound ("rev") inst.SoundEmitter:KillSound ("idle") inst.SoundEmitter:KillSound ("equip") inst.SoundEmitter:PlaySound ("chainsaw/chainsaw/unequip") owner:RemoveTag ("playerghost") equipped = false end local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddAnimState() inst.entity:AddSoundEmitter() inst.entity:AddNetwork() MakeInventoryPhysics (inst) inst.AnimState:SetBank ("chainsaw") inst.AnimState:SetBuild ("chainsaw") inst.AnimState:PlayAnimation ("idle") inst:AddTag("sharp") inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end inst:AddComponent("inspectable") inst:AddComponent ("inventoryitem") inst.components.inventoryitem.imagename = "chainsaw" inst.components.inventoryitem.atlasname = "images/inventory_images/chainsaw.xml" inst:AddComponent("tool") inst.components.tool:SetAction(ACTIONS.CUTDOWN, CHAINSAW_EFFECTIVENESS) inst:AddComponent("electricalTool") inst.components.electricalTool:SetOnWorkFn (OnWork) inst.components.electricalTool:SetOnFinishedWorkFn (OnFinishedWork) inst:AddComponent ("equippable") inst.components.equippable:SetOnEquip (OnEquip) inst.components.equippable:SetOnUnequip (OnUnequip) return inst end return Prefab ("common/inventory/chainsaw", ChainsawFunction, assets, prefabs) And finally this is the modmain.lua where I create the custom action CUTDOWN: GLOBAL.STRINGS.NAMES.CHAINSAW = "Chainsaw" GLOBAL.STRINGS.CHARACTERS.GENERIC.DESCRIBE.CHAINSAW = "Tree-eater machine" PrefabFiles = { "chainsaw", } -- Creating new state to Cut Down using Chainsaw -- It is a placeholder because I cannot create animations local State = GLOBAL.State local TimeEvent = GLOBAL.TimeEvent local EventHandler = GLOBAL.EventHandler local FRAMES = GLOBAL.FRAMES local cutdownState = State({ name = "cutdown", tags = {"cutting", "working"}, onenter = function(inst) inst.AnimState:PlayAnimation("give") end, timeline = { TimeEvent(1 * FRAMES, function(inst) inst:PerformBufferedAction() end), }, events = { EventHandler("unequip", function(inst) inst.sg:GoToState("idle") end), EventHandler("finishedwork", function(inst) if inst.AnimState:AnimDone() then inst.sg:GoToState("idle") end end), }, }) -- Add the new state to the Stategraph AddStategraphState("wilson", cutdownState) AddStategraphState("wilson_client", cutdownState) --------------------------------------------------------------------------------------------------------------------------- -- Create the Action to cutdown the trees local CUTDOWN = AddAction("CUTDOWN", "Cut Down", function(act) if act.doer.components.inventory then if act.target.components.burnable ~= nil then if act.target.components.burnable:IsBurning() or act.target.components.burnable:IsSmoldering() then return false end end if act.invobject.components.electricalTool == nil then return false end act.invobject.components.electricalTool:Work (act.doer, act.invobject, act.target) return true end end) CUTDOWN.priority = 2 -- Make my custom action valid as a "tool" action GLOBAL.TOOLACTIONS.CUTDOWN = true -- Add my custom actions to the component itself AddComponentAction("EQUIPPED", "tool", function(inst, doer, target, actions, right) if target:HasTag("tree") and inst:HasTag("CUTDOWN_tool") then table.insert(actions, GLOBAL.ACTIONS.CUTDOWN) end end) AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(CUTDOWN, "cutdown")) AddStategraphActionHandler("wilson_client", GLOBAL.ActionHandler(CUTDOWN, "cutdown")) Regarding all these codes, I have two doubts: How can I make my custom action doable by holding space bar like all the other actions? How can I detect that the player moved after the action begins What would be the best way to remove the "chop" sound when working a tree using a tool? It is player in the following code (evergreens.lua): local function chop_tree(inst, chopper, chops) if not (chopper ~= nil and chopper:HasTag("playerghost")) then inst.SoundEmitter:PlaySound( chopper ~= nil and chopper:HasTag("beaver") and "dontstarve/characters/woodie/beaver_chop_tree" or "dontstarve/wilson/use_axe_tree" ) end ... If you have any suggestions/feedback on my code, feel free to say it. It is the first mod that I am creating for DST. Link to comment Share on other sites More sharing options...
ZupaleX Posted July 28, 2017 Share Posted July 28, 2017 1) You need to override the function in playercontroller which select the action to perform when holding the spacebar (PlayerController:GetActionButton) to include your action in the list of possible actions. There was a thread last week about that very same question and I answered it (about a jumping action). 2) What do you want to do if the player moved? 3) Yes. You need to change the do a AddPrefabPostInit to the trees and apply a new function to Workable:SetOnWorkCallback. 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