SenL Posted January 31, 2016 Share Posted January 31, 2016 (edited) I have mychar mod almost ready. He will be able to root and when he is rooted he will heal nearby players. What is happening: it will also piss off nearby hostiles even when they are not provoked (such as Tree guard wandering around peacefully suddenly angry at mychar) What I want: only do SuggestTarget() when the hostile is in "attack" (or hunt or combat) mode Kind of like in mmorpg where the mob switches target to healer. How do I accomplish this? Current code (modmain) Spoiler --suggest self as target for all nearby hostiles local healer = inst local x,y,z = healer.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z,healradius) --healradius is a variable for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") and not target:HasTag("structure") and not target:HasTag("eyeplant") and not target:HasTag("wall") then --suggest target if target.components.combat then target.components.combat:SuggestTarget(healer) end end end Side question: I read that FindEntities() is not CPU-friendly. Is there more efficient way? Edited January 31, 2016 by SenL Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/ Share on other sites More sharing options...
DarkXero Posted January 31, 2016 Share Posted January 31, 2016 1 hour ago, SenL said: How do I accomplish this? if target.components.combat and target.components.combat.target then target.components.combat:SuggestTarget(healer) end 1 hour ago, SenL said: I read that FindEntities() is not CPU-friendly. Is there more efficient way? In this case, I don't think so. But your character isn't permanently rooted, so... it's ok. Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715806 Share on other sites More sharing options...
SenL Posted February 1, 2016 Author Share Posted February 1, 2016 1) You added target.components.combat.target Does it mean that the target has a "target" (meaning when target is not provoked this "target" is nil)? 2) Can I call the heal task every second? (currently every 10 seconds) Will it be bad for CPU? Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715814 Share on other sites More sharing options...
Kzisor Posted February 1, 2016 Share Posted February 1, 2016 Just now, SenL said: 2) Can I call the heal task every second? (currently every 10 seconds) Will it be bad for CPU? Is the "heal task" what you posted earlier? Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715815 Share on other sites More sharing options...
SenL Posted February 1, 2016 Author Share Posted February 1, 2016 (edited) Yes, it has inst:GetDistanceSqToInst() for each GLOBAL.AllPlayers and then it has TheSim:FindEntities(x,y,z, healradius) --healradius is a variable I could split them up into two tasks... one heal every second, and the findentities every 5 or 10... not sure Edited February 1, 2016 by SenL Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715817 Share on other sites More sharing options...
Kzisor Posted February 1, 2016 Share Posted February 1, 2016 Just now, SenL said: Yes, it has inst:GetDistanceSqToInst() for each GLOBAL.AllPlayers and then it has TheSim:FindEntities(x,y,z, healradius) --healradius is a variable Post the full function, because I am thinking there is actually a better way of optimizing it so you don't burn cpu cycles iterating through useless junk. Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715819 Share on other sites More sharing options...
SenL Posted February 1, 2016 Author Share Posted February 1, 2016 Sure. local function dorootedhealtask(inst) local healradius = 70 --may be too high? --heal all non-ghost players nearby for _, v in pairs(GLOBAL.AllPlayers) do if not v:HasTag("playerghost") then if inst:GetDistanceSqToInst(v) < healradius then if v.components.sanity then v.components.sanity:DoDelta(10) end if v.components.health then v.components.health:DoDelta(10) end end end end --suggest self as target for all nearby hostiles local healer = inst local x,y,z = healer.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z,healradius) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") and not target:HasTag("structure") and not target:HasTag("eyeplant") and not target:HasTag("wall") then --suggest target if target.components.combat and target.components.combat.target then target.components.combat:SuggestTarget(healer) end end end end Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715820 Share on other sites More sharing options...
Kzisor Posted February 1, 2016 Share Posted February 1, 2016 (edited) 5 minutes ago, SenL said: Sure. There is definitely an easier and more efficient way. You're currently running 2 loops, when in fact you could only run a single loop. local function dorootedhealtask(inst) local healradius = 70 --may be too high? --suggest self as target for all nearby hostiles local healer = inst local x,y,z = healer.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z,healradius) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") and not target:HasTag("structure") and not target:HasTag("eyeplant") and not target:HasTag("wall") then --suggest target if target.components.combat and target.components.combat.target then target.components.combat:SuggestTarget(healer) end else if not target:HasTag("playerghost") and target:HasTag("player") then if inst:GetDistanceSqToInst(target) < healradius then if target.components.sanity then target.components.sanity:DoDelta(10) end if target.components.health then target.components.health:DoDelta(10) end end end end end end This single loop now iterates through all the entities, healing players when it comes across them and forcing targets to attack the healer. Edited February 1, 2016 by Kzisor Fixed code errors, changed v: to traget: Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715825 Share on other sites More sharing options...
DarkXero Posted February 1, 2016 Share Posted February 1, 2016 8 minutes ago, SenL said: Does it mean that the target has a "target" (meaning when target is not provoked this "target" is nil)? Yeah, when mobs have a target on their combat component, they will enter the ChaseAndAttack behavior sooner or later. So if a mob has a combat target, then it's angry. Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715828 Share on other sites More sharing options...
SenL Posted February 1, 2016 Author Share Posted February 1, 2016 Thank you both! Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715830 Share on other sites More sharing options...
Muche Posted February 1, 2016 Share Posted February 1, 2016 Is there a difference between local ents = TheSim:FindEntities(x,y,z,healradius) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") and not target:HasTag("structure") and not target:HasTag("eyeplant") and not target:HasTag("wall") then and local ents = TheSim:FindEntities(x,y,z,healradius, nil, {"structure", "eyeplant", "wall"}) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") then performance-wise? Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715880 Share on other sites More sharing options...
Kzisor Posted February 1, 2016 Share Posted February 1, 2016 1 hour ago, Muche said: Is there a difference between local ents = TheSim:FindEntities(x,y,z,healradius) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") and not target:HasTag("structure") and not target:HasTag("eyeplant") and not target:HasTag("wall") then and local ents = TheSim:FindEntities(x,y,z,healradius, nil, {"structure", "eyeplant", "wall"}) for i, target in ipairs(ents) do if target ~= healer and target.entity:IsVisible() and target.components.health ~= nil and target.components.locomotor ~= nil and not target:HasTag("player") then performance-wise? The way I understand TheSim:FindEntities working is that we're querying the C/C++ engine of Don't Starve asking it to return us entities within the radius. Passing the tags to C/C++ versus keeping the checks in LUA is a very minor performance issue. While yes it would be faster to do it inside C/C++ you gain overhead for passing those parameters which reduce the true benefit gained from it. All in all it is about the same performance wise. Link to comment https://forums.kleientertainment.com/forums/topic/63562-how-to-do-suggesttarget-only-when-they-are-pissed-off/#findComment-715919 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