Commit cba08a5914473f316868227999a60f9f301ba1fe

Authored by Chris Davidson
1 parent 890cca83

Add a new AI target method that always targets the nearest enemy in FOV

Immobile melee stuff is really prone to getting stuck with a target it can't reach.  This is mostly relevant to melee Player pets.
Showing 1 changed file with 45 additions and 0 deletions
... ... @@ -109,3 +109,48 @@ newAI("charred_scar_target", function(self)
109 109 self:setTarget(game.player)
110 110 return true
111 111 end)
  112 +
  113 +-- Always retarget to closest
  114 +-- This is most useful on immobile melee prone to just wasting their turns if their current target isn't adjacent
  115 +newAI("target_closest", function(self)
  116 + if not self.x then return end
  117 + local log_detail = config.settings.log_detail_ai or 0
  118 + if log_detail > 0 then print("[ActorAI] Invoking target_closest AI for", self.uid, self.name, self.x, self.y) end
  119 + local aitarget = self.ai_target.actor
  120 + if aitarget then
  121 + if log_detail >= 2 then print("[target_closest AI] current target:", aitarget.uid, aitarget.name) end
  122 + if aitarget.summoner and (aitarget.dead or not game.level:hasEntity(aitarget)) then
  123 + if log_detail > 0 then print("[target_closest AI] targeting summoner of dead summon:", aitarget.uid, aitarget.name) end
  124 + self:setTarget(aitarget.summoner)
  125 + aitarget = self.ai_target.actor
  126 + end
  127 + end
  128 +
  129 + -- Find closest enemy and target it or set no target
  130 + -- Get list of actors ordered by distance
  131 + local arr = self.fov.actors_dist
  132 + local act
  133 + local sqsense = math.max(self.lite or 0, self.infravision or 0, self.heightened_senses or 0)
  134 + if log_detail >= 2 then print("[target_closest AI]", self.uid, self.name, "at", self.x, self.y, "searching for new targets in range", sqsense) end
  135 + sqsense = sqsense * sqsense
  136 + for i = 1, #arr do
  137 + act = self.fov.actors_dist[i]
  138 + if log_detail > 2 then print("\t checking target", act.x, act.y, act.uid, act.name) end
  139 + if act and act.x and not act.dead and self:reactionToward(act) < 0 and game.level.map:isBound(act.x, act.y) and
  140 + (((act.lite or 0) > 0) -- If it has lite we can always see it
  141 + or -- Otherwise check if we can see it with our "senses"
  142 + (self:canSee(act) and (self.fov.actors[act].sqdist <= sqsense) or game.level.map.lites(act.x, act.y))
  143 + ) and not act:attr("invulnerable") then
  144 +
  145 + print("[target_closest AI]", self.uid, self.name, "selecting NEW TARGET", act.x, act.y, act.uid, act.name)
  146 + self:setTarget(act)
  147 + return act
  148 + end
  149 + end
  150 + if aitarget then -- clear old target if a new one wasn't found or kept
  151 + if log_detail > 0 then print("[target_closest AI] clearing old target (no replacement):", aitarget.uid, aitarget.name) end
  152 + if log_detail > 1.4 and config.settings.cheat then game.log("#RED# [%s]%s #ORANGE#CLEARING OLD TARGET#LAST#: [%s]%s", self.uid, self.name, aitarget.uid, aitarget.name) end -- debugging
  153 + self:setTarget()
  154 + end
  155 + return self.ai_target.actor
  156 +end)
\ No newline at end of file
... ...