Near4422 Posted February 15, 2021 Share Posted February 15, 2021 Hello guys! ----------------- EDIT -------------------- I've created a separate subject that gathers all stuff around my very first character. So to anyone who'd like to contribute - Please head here -> local function onattack(inst, owner, target) owner.components.health:DoDelta(3,false,"scare_scythe") end I'd like to change it to aura that deals 1 point of damage to every monster unit (only monsters, not animals etc) every tick... (let's say every 2 secs) within certain distance from the character and heal character for the damage dealt. Could someone help me with it? Thank you in advance! Link to comment Share on other sites More sharing options...
Combustiblemon Posted February 15, 2021 Share Posted February 15, 2021 local function IsVaildTarget(target) return target ~= nil and target.components.health ~= nil --can't drain when target has no health and not ((target:HasTag("prey") and not target:HasTag("hostile")) or target:HasTag("structure") or target:HasTag("wall") or target:HasTag("companion")) end local function onattack(inst, owner, target) target:AddTag("scythevictim") local count = 0 local pt = Vector3(target.Transform:GetWorldPosition()) local range = 5 local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, range) for i,ent in ipairs(ents) do if IsVaildTarget(ent) or ent and ent.components.health and ent:HasTag("scythevictim") then --because of scythevictim tag, you can even drain 'not vaild target(like wall, chester)' when it's directly attacked. if ent._scythedmgtask ~= nil then ent._scythedmgtask:Cancel() --it will reset its timer when it's re-attacked before timer done end ent._scythedmgtask = ent:DoTaskInTime(10, function(ent) ent._scythecount = nil ent._scythedmg = nil ent._scythedmgtask = nil end) --reset everything when 10 sec timer is done if ent._scythecount == nil then ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-1, false, owner) end) --every 2 seconds, it will deal 1 damage ent._scythecount = ent._scythecount + 1 else --it can be applied multiple times! ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-ent._scythecount, false, owner) end) --every 2 seconds, it will deal 'ent._scythecount' damage ent._scythecount = ent._scythecount + 1 end count = count + ent._scythecount --since ent._scythecount = damage dealt, you will heal total amount of damage dealt end end if owner._draintask ~= nil then owner._draintask:Cancel() owner._drain:Cancel() end --it will reset its timer when it is attacked before time done owner._draintask = owner:DoTaskInTime(10, function(owner) owner._drain = nil owner._draintask = nil end) owner._drain = owner:DoPeriodicTask(2, function(owner) owner.components.health:DoDelta(count) end) end Phew, that was lot of codes! I'm not good at modding but at least this is what I can do. If you encounter an error, please let me know by uploading game logs so I can fix it. Link to comment Share on other sites More sharing options...
Near4422 Posted February 15, 2021 Author Share Posted February 15, 2021 @Combustiblemon Thank you for your work so much! That's a looot of code... i wouldn't be able to figure it out on my own. Tho i must inform you it doesn't work as intended... or i failed to implement it propperly. Thing is when i attack anything all characters freeze for a brief moment in place and then the server disconnects me. I've searched through the server files and hopefully attatched the propper file with logs - hopefully this will help you understand what happened (because i have no idea at all....) And i wanted to ask a few questions to better understand your code. First of all - thank you for comments! Second - this code triggers on attack right? Since this function was originally placed inside the 'scythe' item. My intention was to create an aura that works all the time (or at least when the scythe is equipped) without the need to hit an enemy (but if that's the only way to get targets for the function - it'll be still fine). Tag 'prey' is being applied to characters i've attacked - do I get it right? server_log.txt Link to comment Share on other sites More sharing options...
Near4422 Posted February 15, 2021 Author Share Posted February 15, 2021 55 minutes ago, Combustiblemon said: local function IsVaildTarget(target) return target ~= nil and target.components.health ~= nil --can't drain when target has no health and not ((target:HasTag("prey") and not target:HasTag("hostile")) or target:HasTag("structure") or target:HasTag("wall") or target:HasTag("companion")) end local function onattack(inst, owner, target) target:AddTag("scythevictim") local count = 0 local pt = Vector3(target.Transform:GetWorldPosition()) local range = 5 local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, range) for i,ent in ipairs(ents) do if IsVaildTarget(ent) or ent and ent.components.health and ent:HasTag("scythevictim") then --because of scythevictim tag, you can even drain 'not vaild target(like wall, chester)' when it's directly attacked. if ent._scythedmgtask ~= nil then ent._scythedmgtask:Cancel() --it will reset its timer when it's re-attacked before timer done end ent._scythedmgtask = ent:DoTaskInTime(10, function(ent) ent._scythecount = nil ent._scythedmg = nil ent._scythedmgtask = nil end) --reset everything when 10 sec timer is done if ent._scythecount == nil then ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-1, false, owner) end) --every 2 seconds, it will deal 1 damage ent._scythecount = ent._scythecount + 1 else --it can be applied multiple times! ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-ent._scythecount, false, owner) end) --every 2 seconds, it will deal 'ent._scythecount' damage ent._scythecount = ent._scythecount + 1 end count = count + ent._scythecount --since ent._scythecount = damage dealt, you will heal total amount of damage dealt end end if owner._draintask ~= nil then owner._draintask:Cancel() owner._drain:Cancel() end --it will reset its timer when it is attacked before time done owner._draintask = owner:DoTaskInTime(10, function(owner) owner._drain = nil owner._draintask = nil end) owner._drain = owner:DoPeriodicTask(2, function(owner) owner.components.health:DoDelta(count) end) end Phew, that was lot of codes! I'm not good at modding but at least this is what I can do. If you encounter an error, please let me know by uploading game logs so I can fix it. #Ping. I don't know how to tag people here yet propperly. Hopefully it works. I've added a response above Link to comment Share on other sites More sharing options...
Combustiblemon Posted February 17, 2021 Share Posted February 17, 2021 local function IsVaildTarget(target) return target ~= nil and target.components.health ~= nil --can't drain when target has no health and not ((target:HasTag("prey") and not target:HasTag("hostile")) or target:HasTag("structure") or target:HasTag("wall") or target:HasTag("companion")) end local function DamageAura(inst) local owner = inst.components.inventoryitem.owner or nil if not owner then return end local count = 0 local x,y,z = owner.Transform:GetWorldPosition() local pt = owner:GetPosition() local range = 5 local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, range) for i,ent in ipairs(ents) do if IsVaildTarget(ent) or ent and ent.components.health and ent:HasTag("scythevictim") then --because of scythevictim tag, you can even drain 'not vaild target(like wall, chester)' when it's directly attacked. if ent._scythedmgtask ~= nil then ent._scythedmgtask:Cancel() ent._scythedmg:Cancel() --it will reset its timer when it's re-attacked before timer done end ent._scythedmgtask = ent:DoTaskInTime(10, function(ent) ent._scythecount = nil ent._scythedmg = nil ent._scythedmgtask = nil end) --reset everything when 10 sec timer is done if ent._scythecount == nil then ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-1, false, owner) end) --every 2 seconds, it will deal 1 damage ent._scythecount = 1 else --it can be applied multiple times! ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-ent._scythecount, false, owner) end) --every 2 seconds, it will deal 'ent._scythecount' damage ent._scythecount = ent._scythecount + 1 end count = count + ent._scythecount --since ent._scythecount = damage dealt, you will heal total amount of damage dealt end end owner.components.health:DoDelta(count) end local function onattack(inst, owner, target) if target._auratargettask ~= nil then target._auratargettask:Cancel() end if not target:HasTag("scythevictim") then target:AddTag("scythevictim") end target._auratargettask = target:DoTaskInTime(10, function(target) target:RemoveTag("scythevictim") end) end ---------------------------------------------------------- inst._auratask = inst:DoPeriodicTask(2, DamageAura) --add this line into weapon main function The error was 'ent._scythecount = ent._scythecount + 1', because it was nil(none value). I edited so damage aura will work even you didn't attack at all, but attacking specific target(like chester) will add tag "scythevictim" to target, so target can be damaged by aura. There are no visual effects besides of health effect, so I'd recommend you add some animation effects. You can ping someone by @, @Near4422 like this. Sorry for being late, I didn't have times to do coding. Aaaand, this is solo DS-modding category, not DST one. You've mistaken I guess? There are more active and has more people to help you. Link to comment Share on other sites More sharing options...
Ultroman Posted February 17, 2021 Share Posted February 17, 2021 Neat Just wanted to note that you're leaving all your victims with the "scythevictim" tag on forever. Mostly for future readers who might find this post. It could give problems if one tried to use this code for their "aura" (it's more like AoE with life-steal over time), since if you target things based on a tag that never gets removed, you might end up targetting victims that should not have the tag anymore. Also, putting public variables on the owner with as mundane names as _draintask and _drain may lead to compatibility problems with other mods that have used the same exact naming. When adding to a "public pool" of variables, always make sure your variables are named sufficiently unique for it to be statistically improbable that others have already used it. Perhaps a moniker for your mod as a prefix e.g. owner._AAA_draintask. Link to comment Share on other sites More sharing options...
Near4422 Posted February 17, 2021 Author Share Posted February 17, 2021 @Combustiblemon Thank's for you effort! I really appreciate it. I am going to try this out soon Answering your questions - yes i must have misteaken, I'm sorry for that.@Ultroman That's a very significant notice. Altough I do understand what you mean - I don't feel like i know how to use this knowledge in sake for mods compability :/ Thank you for linking that megathread - I am going to have a lot of reading I assume that i should write something that will be removing tag once the target is further away than specific distance from the character... Link to comment Share on other sites More sharing options...
Ultroman Posted February 17, 2021 Share Posted February 17, 2021 You'll figure it out Link to comment Share on other sites More sharing options...
Near4422 Posted February 18, 2021 Author Share Posted February 18, 2021 @Combustiblemon It works! Tho something is clearly wrong with the numbers - I am trying to figure it out. Don't know why yet, but character gets healed for weird amounts of health points every 2 seconds - even with single spider I get healed by 15, 18 or even 20 HP per tick. For the damage dealt - it seems to be stacking up due to this part of code: else --it can be applied multiple times! ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-ent._scythecount, false, owner) end) --every 2 seconds, it will deal 'ent._scythecount' damage ent._scythecount = ent._scythecount + 1 end The longer the fight goes - the more damage is being dealt to a single enemy. Also In a random moment an enemy stops being damaged by the aura and after (approximetly) 10 seconds it starts to work again. The healing received also seems to be somehow stacking up to the infinity - i assume due to the constant incrementing the 'count' value. I've managed to solve the issue by removing this part of the code: else --it can be applied multiple times! ent._scythedmg = ent:DoPeriodicTask(2, function(ent) ent.components.health:DoDelta(-ent._scythecount, false, owner) end) --every 2 seconds, it will deal 'ent._scythecount' damage ent._scythecount = ent._scythecount + 1 But there are still issues to be covered. For example the character gets healing even after the prey is dead. Next up - loosing an agro on mob (walking away from it so it losses interrest) still maintains the tag on him and results in taking damage and receaving healing. We're getting close on it! At least the game stopped crashing Link to comment Share on other sites More sharing options...
Lillyth Posted February 24, 2021 Share Posted February 24, 2021 -- Outside Fn local auraDuration = 0 -- Inside Fn inst:ListenForEvent("onattackother", function(inst, data) auraDuration = 6 -- Turn on our aura for 6 seconds (Hit again to reapply) end) local function ScytheTick() local x, y, z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, 4, nil) -- Play around with distance to suit your needs. I put it to "4" as an example. for i, v in ipairs(ents) do if v.components.health and not v.components.health:IsDead() then -- Make sure our target isn't dead and has the health component local damage = 1 v.components.combat:GetAttacked(inst, damage) -- 1 point of damage, coming from inst (Player) inst.components.health:DoDelta(damage) -- Heal us with it, as well. end end end inst:DoPeriodicTask(2, function() if auraDuration > 0 then ScytheTick() auraDuration = auraDuration - 2 end end, nil) -- Every 2 seconds, run ScytheTick function This is how I'd handle it, assuming you put it in your character prefab lua. Untested, but I'm pretty positive it'll work. Change variables as you need @Near4422 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.