D3dans Posted February 6, 2025 Share Posted February 6, 2025 Trying to bounce from C++ to LUA is a ride. So far I've not had any luck getting things to work. One of those things being increasing a mod character's speed for X amount of seconds after taking damage from a hostile source. I've peeked at other mods, looked into LUA tutorials, and dug through DST's base code and have yet to wrap my head around what I've got wrong. -- When hit, increase speed for 5 seconds local function CombatSpeed(inst) local self = inst.components.combat local _GetAttacked = self.GetAttacked self.GetAttacked = function(self, attacker, damage, weapon, stimuli) if attacker and damage then -- Increase run speed for 5 seconds local startTimer = os.time() local endTimer = startTimer+5 if os.time() <= endTimer then inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 1.6) inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 1.6) -- if hit again before timer ends, reset 5 second timer countdown if attacker and damage then startTimer = os.time() end end --if timer ends, reset run speed back to default inst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * 1.0) inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * 1.0) end return _GetAttacked(self, attacker, damage, weapon, stimuli) end end If anyone could point me in the right direction on how to do this, that would be awesome. My brain is fried from looking at this for hours and I bet you if anything, it's something super simple and obvious that I'm overlooking at the moment. Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/ Share on other sites More sharing options...
Baguettes Posted February 7, 2025 Share Posted February 7, 2025 Hello, welcome to the forums! (The good part, that is...) What I see here is that you're trying to hook into the combat component's GetAttacked function. While yes, this is entirely possible, there's Event Listeners in DST for it if what you're aiming for doesn't require modifying how Combat itself works to begin with. You can try to combine an event listener for your character, and an external speed modifier together. For this, I'd do: inst:ListenForEvent("attacked", FN_NAME_HERE) in your Character's Lua file, under the master_postinit function. Then, above both Common and Master postinits, you can add a local fn with a name that you chose above: --Data is a table, purely optional, but it contains all of what the GetAttacked function passes (attacker, damage, etc.) local function FN_NAME_HERE(inst, data) --Params are: Source (from which instance), Modifier, Key (as String, optional) inst.components.locomotor:SetExternalSpeedMultiplier(inst, 1.6, "panic") --This should be self-explanatory! A timer component should exist on all players to begin with, so no need for nil checks. if not inst.components.timer:TimerExists("panic_speedboost") then inst.components.timer:StartTimer("panic_speedboost", 5) else inst.components.timer:SetTimeLeft("panic_speedboost", 5) end end Then, below the first event listener, add another one: inst:ListenForEvent("timerdone", FN_NAME_HERE) After that, you create another local function with the same name. --This time, data contains only one thing: Timer name, as a string. Data itself is still a table, however! local function FN_NAME_HERE(inst, data) if data.name == "panic_speedboost" then inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "panic") end end That should do it. There's also a debuff component for things, but that requires creating a prefab and assigning three functions to what happens when the effect is applied, removed, and extended. If you want to know and would rather make this into a buff, please do tell me. Also, most game components are stored in scripts/components; taking a look into those may give you insight on what you can do with them, and create more character perks from it. Good luck, though! 2 1 Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/#findComment-1793722 Share on other sites More sharing options...
oregu Posted February 7, 2025 Share Posted February 7, 2025 (edited) You can informally add a component like Baguettes did of course, but if you're interested in something more modular then make a component instead. To add a component I'd recommend making a file in your modfolder like so: scripts/components/componentname I can relate to modding taking a lot out of you. When you do inst:AddComponent"battlehaste" it will automatically find battlehaste.lua Spoiler -- Where your OnAttacked function is passed, any attacked data that we want to ignore is is blocked here --[[ In components/combat.lua this "attacked" event pushes the following data: attacker, damage, damageresolved, original_damage, weapon, stimuli, spdamage, redirected, noimpactsound We will use data.attacker and data.damage --]] local function OnAttacked(inst, data) local self = inst.components.battlehaste local attacker = data.attacker local damage = data.damage --IsValid check because other "attacked" handlers may have removed us (from components/frozen.lua) --NOTE: see how EntityScript:PushEvent caches all listeners; that is why an invalid entity could still reach this event listener (from components/frozen.lua) if not attacker or not damage or not inst:IsValid() or not self.locomotor or not self.timer then return end -- Basic checks if not attacker:HasTag"hostile" or damage <= 0 then return end -- Special checks self:StartHasteTask() end local function OnTimerDone(inst, data) local self = inst.components.battlehaste if data.name == "battlehaste" then self:StopHasteTask() end end local BattleHaste = Class(function(self, inst) self.inst = inst self.inst:AddTag"battlehaste" -- Can easily check if something has this component self.task = nil self.checkperiod = .1 -- How often the task updates a second self:Reset() -- Simple init if not inst.components.locomotor then -- Locomotor is a required component, may as well try to add it if not present inst:AddComponent("locomotor") end self.locomotor = self.inst.components.locomotor if not inst.components.timer then -- Timer is a required component inst:AddComponent("timer") end self.timer = self.inst.components.timer inst:ListenForEvent("timerdone", OnTimerDone) self.inst:ListenForEvent("attacked", OnAttacked) -- Our main function, being attacked is a built-in global thing you can listen for end) function BattleHaste:StopHasteTask() self.locomotor:RemoveExternalSpeedMultiplier(self.inst, "battlehaste") if self.task then self.task:Cancel() self.task = nil end end --[[ Don't concern yourself too much with this but it's basically a smooth speed increase --]] function BattleHaste:RampMath(time, type) if not type then return self.speed end local min = 0 local max = self.speed local phase = self.ramp * type local cos = ((math.cos(((time + phase) * math.pi) / self.ramp)) + 1)/2 local range = self.speed - min local ramp = (cos * range) + min return ramp end -- The purpose of our component is mainly in this task local function HasteTask(inst) local self = inst.components.battlehaste if not self.timer:TimerExists"battlehaste" then --Just in case self:StopHasteTask() return end local curtime = self.timer:GetTimeElapsed"battlehaste" local ramptype = nil if curtime <= self.duration then if curtime < self.ramp then -- ease-in ramptype = 1 elseif curtime > self.duration - self.ramp then -- ease-out ramptype = 0 end local curspeed = self:RampMath(curtime, ramptype) local addspeed = curspeed if ramptype == 1 then addspeed = math.max(self.ongoingspeed, addspeed) end self.locomotor:SetExternalSpeedMultiplier(self.inst, "battlehaste", 1 + addspeed, SourceModifierList.additive) end end function BattleHaste:StartHasteTask() if self.task then self.ongoingspeed = self.locomotor:GetExternalSpeedMultiplier(self.inst, "battlehaste") - 1 else self.ongoingspeed = 0 end self:StopHasteTask() if not self.timer:TimerExists"battlehaste" then self.timer:StartTimer("battlehaste", self.duration) else self.timer:SetTimeLeft("battlehaste", self.duration) end self.task = self.inst:DoPeriodicTask(self.checkperiod, HasteTask) end -- Can set values externally if needed function BattleHaste:SetSpeedDuration(time) self.duration = time end function BattleHaste:SetSpeedMult(speed) self.speed = speed end function BattleHaste:SetRamping(ramp) -- How long it takes for speedboost to accelerate/deccelerate self.ramp = ramp end -- Basic saving/loading function BattleHaste:Reset() self.duration = 5 self.speed = 0.6 self.ramp = 0.3 self.task = nil self.ongoingspeed = 0 end function BattleHaste:OnSave() local data = { duration = self.duration, speed = self.speed, ramp = self.ramp, ongoingspeed = self.ongoingspeed, } return data end function BattleHaste:OnLoad(data) self.duration = data.duration or 5 self.speed = data.speed or 0.6 self.ramp = data.ramp or .3 -- How long it takes to ramp self.ongoingspeed = data.ongoingspeed or 0 end return BattleHaste Of course, I don't make components often (in fact this is my first time making one) so sorry if it's bugged, but with components you can put this on anything. Edited February 7, 2025 by oregu 1 1 Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/#findComment-1793856 Share on other sites More sharing options...
D3dans Posted February 7, 2025 Author Share Posted February 7, 2025 Thank you both so much for your help! LUA still continues to elude me, but despite the horrors I shall persist! I know it's going to be even a bigger mess figuring this out, and honestly if it's too much I may abandon the idea, but my next plan is an aura to increase action speeds for foraging items. I know it'll have to involve editing the animation speeds as well, but on the bright side there's at least one fun perk thanks to both of your help! Making items should be easier (knock on wood) and I'll start on that before messing with more perk making, regardless, wish me luck! And again, I cannot thank you both enough for the help! I know it's not much, but I credited you both as helpful sources inside the main character script files! :> Hope you two have a wonderful day and if you see me posting again asking for aid, then the horrors of LUA have still got their spooky little claws in me R.I.P. 2 Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/#findComment-1793953 Share on other sites More sharing options...
D3dans Posted April 19, 2025 Author Share Posted April 19, 2025 :^( Alas, I don't know if it's something I'm doing or what, but both methods of implementing this perk only winds up with me unable to load into a world with the mod enabled. Not sure if there's an easier way to test what I'm doing beyond launching DST off and on every change made, but man is this mod doing my head in still. Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/#findComment-1813083 Share on other sites More sharing options...
D3dans Posted April 19, 2025 Author Share Posted April 19, 2025 57 minutes ago, D3dans said: :^( Alas, I don't know if it's something I'm doing or what, but both methods of implementing this perk only winds up with me unable to load into a world with the mod enabled. Not sure if there's an easier way to test what I'm doing beyond launching DST off and on every change made, but man is this mod doing my head in still. Nevermind I'm a liar! Turns out I misplaced a comma in the speech LUA and that was the whole reason the mod itself wouldn't load... The little things in coding I swear. Link to comment https://forums.kleientertainment.com/forums/topic/163735-modding-character-speed-when-hit/#findComment-1813088 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