I was working on my own tactical ai improvement add-on when lukep pointed me to this addon. There is little I can do to improve it, but I will point a few things I've, which might be of interest.
1. Regarding the problem of traps, summons, create minions, and now mucus, these are all talents that the concept of "within range" is different. So the range for a summoned npc is how far from the caster you can summon, or for a trap, the same, and not is the target npc within range. Rampage also suffers from this problem.
So I created a very simple workaround - I add 1 to the range for traps and mucus and rampage, and 5 to summons, minions and rampage. So the npc will cast summon when the player is five spaces away than the radius.
Here's the code:
Code: Select all
--- local within_range = target_dist and target_dist <= (self:getTalentRange(t) + self:getTalentRadius(t))
+++ local add_range = 0
+++ if t.type[1] == "cunning/traps" or t.name == "Mucus" or t.name == "Rampage" then
+++ add_range = 1
+++ elseif t.is_summon or t.name == "Create Minions" then
+++ add_range = 5
+++ end
+++ local within_range = target_dist and target_dist <= (self:getTalentRange(t) + self:getTalentRadius(t) + add_range)
Code: Select all
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
...
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
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
non_target_talents["Unstoppable"] = 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
Code: Select all
--- if avail.defend and need_heal and nb_foes_seen > 0 then
--- want.defend = 1 + need_heal / 2 + nb_foes_seen * 0.5
+++ if avail.defend and nb_foes_seen > 0 then
+++ table.sort(avail.defend, function(a,b) return a.val > b.val end)
+++ want.defend = 1 + (need_heal / 2 or 0) + nb_foes_seen * 0.5
end
Code: Select all
-- if avail.buff and want.attack and want.attack > 0 then
-- want.buff = math.max(0.01, want.attack + 0.5)
+++ if avail.buff then
+++ if want.attack and want.attack > 0 then
+++ want.buff = math.max(0.01, want.attack + 0.5)
+++ else
+++ table.sort(avail.buff, function(a,b) return a.val > b.val end)
+++ want.buff = avail.buff[1].val
+++ end
end
I agree with lukep that one of the biggest drawbacks of the tactical ai now, is that it treats each talent separately. But many talents have 2 or more tactics. And these are often the best talents of all. But the ai processes them per tactic and doesn't have any way of adding them together.
And this line actually makes it worse, as it adds in artificially the attack value. This makes no sense to me:
Code: Select all
want.disable = (want.attack or 0) + avail.disable[1].val
Code: Select all
want.disable = (want.attack or 0)/2 + avail.disable[1].val
Code: Select all
-- Save the tactic, if the talent is instant it gets a huge bonus
-- Note the addition of a less than one random value, this means the sorting will randomly shift equal values
val = ((t.no_energy==true) and val * 10 or val) + rng.float(0, 0.9)
e.g.
Code: Select all
want.defend = 1 + need_heal / 2 + nb_foes_seen * 0.5
want.cure = 3 + nb_detrimental_effs
want.buff = math.max(0.01, want.attack + 0.5)