Page 1 of 1
[1.0.4] logic error in tactical.lua for non targeted attacks
Posted: Mon Sep 02, 2013 10:05 am
by jenx
about line 70 we have:
Code: Select all
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
t_avail = true
end
But take a Talent like Frenzy, which returns nil (i.e. false) for TalentRequiresTarget. In this case, the talent Frenzy is available even though you are not within range of the npc.
Find a rare mold with Frenzy and it will cast it continually when no other talents are available, even though you are across the room!
We can fix this with:
Code: Select all
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
t_avail = true
end
I've tested it and it works properly now.
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 10:19 am
by jenx
jenx wrote:about line 70 we have:
Code: Select all
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
t_avail = true
end
But take a Talent like Frenzy, which returns nil (i.e. false!). In this case, the talent Frenzy is available even though you are not within range of the npc.
Find a rare mold with Frenzy and it will cast it continually when no other talents are available, even though you are across the room!
We can fix this with:
Code: Select all
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
t_avail = true
end
I've tested it and it works properly now.
oops - unintended consequences !!!
Regen infusions and healing infusions are not "within range". So either we make them within range, or alter the conditional.
I'll have to experiment further !
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 11:02 am
by jenx
Man, there are so many combinations, it is impossible to have a simple algorithm.
So, I think it might be simplest just to calculate Frenzy separately and leave existing code as is:
Code: Select all
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not self:getTalentRequiresTarget(t) or within_range) then
if t.name == "Frenzy" then -- leave like this in case we need to add other such talents
if target_dist == 1 then
t_avail = true
end
else
t_avail = true
end
not perfect, but I think it works. off to test....
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 11:15 am
by jenx
This is proving very difficult. There are LOTS of talents that don't require a target, and yet do damage. Talents that do burst damage in a radius around the caster, such as Kinetic Leech, Sun Flare, etc.
These are all available to the tactical ai, even though the enemy is not within range, because they return no target required, as per the example above with frenzy.
We need some way then to capture all those talents that do damage, but don't require a target. If I assume they include tactical = attack or attackarea, that might be a better option. Then we can use radius and target_dist to see if they can be used.
Obviously the tactical ai to date has been pretty dumb actually in the way it fights.
So my new strategy is to adjust within_range for talents such as regeneration. I think there are a lot more talents like Leech, Frenzy, than there are like regen.
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 11:52 am
by jenx
ok, so unless someone can think of a smarter way to do this, here is my approach:
Code: Select all
local non_target_talents = {}
non_target_talents["Infusion: Regeneration"] = true
non_target_talents["Infusion: Healing"] = true
non_target_talents["Infusion: Wild"] = true
non_target_talents["Infusion: Movement"] = true
non_target_talents["Infusion: Heroism"] = true
non_target_talents["Rune: Phase Door"] = true
non_target_talents["Rune: Shielding"] = true
non_target_talents["Rune: Controlled Phase Door"] = true
non_target_talents["Rune: Teleportation"] = true
non_target_talents["Rune: Reflection Shield"] = true
non_target_talents["Rune: Invisibility"] = true
non_target_talents["Rune: Speed"] = true
non_target_talents["Rune: Vision"] = true
non_target_talents["Rune: Manasurge"] = true
non_target_talents["Rune of the Rift"] = true
local deactivatable_sustains = {}
deactivatable_sustains["Thermal Aura"] = true
deactivatable_sustains["Kinetic Aura"] = true
deactivatable_sustains["Charged Aura"] = true
deactivatable_sustains["Thermal Shield"] = true
deactivatable_sustains["Kinetic Shield"] = true
deactivatable_sustains["Charged Shield"] = true
for tid, lvl in pairs(self.talents) do
local t = self:getTalentFromId(tid)
local t_avail = false
print(self.name, self.uid, "tactical ai talents testing", t.name, tid)
if t.tactical then
local tg = self:getTalentTarget(t)
local default_tg = {type=util.getval(t.direct_hit, self, t) and "hit" or "bolt"}
-- Only assume range... some talents may no require LOS, etc
within_range = target_dist and target_dist <= (self:getTalentRange(t) + self:getTalentRadius(t))
-- JENX the problem is with talents that don't care about the target at all, such as regeneration. So the following code captures these talents, by setting within_range as true.
if non_target_talents[t.name] then
within_range = true
end
if t.mode == "activated" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and (not (self:getTalentRequiresTarget(t) or 1) or within_range) then
t_avail = true
elseif t.mode == "sustained" and not t.no_npc_use and not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) then
if self:isTalentActive(t.id) and deactivatable_sustains[t.name] then
t_avail = true
elseif not self:isTalentActive(t.id) then
t_avail = true
end
end
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 7:44 pm
by Hachem_Muche
Obviously, you don't want to put a whole lot of talent-specific checks in this code.
A better way to handle non-targeted attacks is to make sure that all talents with tactical attack values check the number of targets hit. You can do this by changing the line
Code: Select all
if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 then
to
Code: Select all
if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 or (t.tactical and (t.tactical.attack or t.tactical.attackarea or t.tactical.disable)) then
any such talent that doesn't hit anything will get a weight of 0 and be skipped.
also, while debugging, you can comment out tactical.lua line 22 (if you haven't already)
to get all the useful ai data to print out in the output log.
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 10:01 pm
by jenx
Hachem_Muche wrote:Obviously, you don't want to put a whole lot of talent-specific checks in this code.
A better way to handle non-targeted attacks is to make sure that all talents with tactical attack values check the number of targets hit. You can do this by changing the line
Code: Select all
if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 then
to
Code: Select all
if self:getTalentRequiresTarget(t) or nb_foes_hit > 0 or nb_allies_hit > 0 or nb_self_hit > 0 or (t.tactical and (t.tactical.attack or t.tactical.attackarea or t.tactical.disable)) then
any such talent that doesn't hit anything will get a weight of 0 and be skipped.
also, while debugging, you can comment out tactical.lua line 22 (if you haven't already)
to get all the useful ai data to print out in the output log.
Many thanks! I'll try these suggestions.
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Mon Sep 02, 2013 11:34 pm
by jenx
oops - the problem with your suggestion Hachem is that the line you suggest changing comes AFTER it is decided if talents are available to use. The issue is that the AI is excluding lots of talents because the payer is not "within range", but these are talents that don't care about range, such as regeneration, healing, etc.
And because some heal talents do care about range, we can't simply check on tactical.
So I think my list of talents will have to do for the time being.
Ideally, we need to add a new flag (or two) to the talent descriptions, to differentiate more carefully different types of talents.
Re: [1.0.4] logic error in tactical.lua for non targeted att
Posted: Tue Sep 03, 2013 4:41 am
by jenx
ok - so I've gone through most of the talents and found the ones that tactical ai will not use unless it is adjacent to you (and therefore you are within range), even though these talents don't care where the player is.
These are talents that don't require a target and don't need to be within range. I've excluded talents with is_heal = true or is_teleport = true.
Code: Select all
local non_target_talents = {}
non_target_talents["Infusion: Regeneration"] = true
non_target_talents["Infusion: Wild"] = true
non_target_talents["Infusion: Movement"] = true
non_target_talents["Infusion: Heroism"] = true
non_target_talents["Rune: Shielding"] = true
non_target_talents["Rune: Reflection Shield"] = true
non_target_talents["Rune: Invisibility"] = true
non_target_talents["Rune: Speed"] = true
non_target_talents["Rune: Manasurge"] = true
non_target_talents["Rune of the Rift"] = true
non_target_talents["Sudden Growth"] = true
non_target_talents["Barrier"] = true
non_target_talents["Providence"] = true
non_target_talents["Resilience of the Dwarves"] = true
non_target_talents["Gift of the Highborn"] = true
non_target_talents["Grace of the Eternals"] = true
non_target_talents["Timeless"] = true
non_target_talents["Wrath of the Woods"] = true
non_target_talents["Nature's Pride"] = true
non_target_talents["Luck of the Little Folk"] = true
non_target_talents["Indomitable"] = true
non_target_talents["Rapid Shot"] = true
non_target_talents["Aim"] = true
if t.is_heal or t.is_teleport or non_target_talents[t.name] then
within_range = true
print("Talent doesn't care for range:", t.name, tid)
end
There could be more, but this is a good start. Tactical ai barely uses any of these, unless it is adjacent to you, but even then, usually some other talent takes precedence.