Teach enemy AI weapon-aware attacks
This commit is contained in:
@@ -2302,21 +2302,26 @@ func _enemy_take_action(enemy: Dictionary) -> void:
|
||||
if _try_enemy_skill_action(enemy):
|
||||
return
|
||||
|
||||
var target := _find_nearest_target(enemy, TEAM_PLAYER)
|
||||
if target.is_empty():
|
||||
return
|
||||
|
||||
if _is_in_attack_range(enemy, target["pos"]):
|
||||
_resolve_combat(enemy, target)
|
||||
var attack_action := _best_ai_physical_attack_action(enemy, [enemy["pos"]])
|
||||
if not attack_action.is_empty():
|
||||
_resolve_combat(enemy, attack_action["target"])
|
||||
return
|
||||
|
||||
var best_cell: Vector2i = enemy["pos"]
|
||||
var best_distance := _manhattan(best_cell, target["pos"])
|
||||
for cell in _movement_range_for_unit(enemy):
|
||||
var distance := _manhattan(cell, target["pos"])
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
best_cell = cell
|
||||
var move_attack_action := _best_ai_physical_attack_action(enemy, _movement_range_for_unit(enemy))
|
||||
if not move_attack_action.is_empty():
|
||||
best_cell = move_attack_action["origin"]
|
||||
else:
|
||||
var target := _find_nearest_target(enemy, TEAM_PLAYER)
|
||||
if target.is_empty():
|
||||
return
|
||||
|
||||
var best_distance := _manhattan(best_cell, target["pos"])
|
||||
for cell in _movement_range_for_unit(enemy):
|
||||
var distance := _manhattan(cell, target["pos"])
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
best_cell = cell
|
||||
|
||||
if best_cell != enemy["pos"]:
|
||||
var from_cell: Vector2i = enemy["pos"]
|
||||
@@ -2331,9 +2336,45 @@ func _enemy_take_action(enemy: Dictionary) -> void:
|
||||
if _try_enemy_skill_action(enemy):
|
||||
return
|
||||
|
||||
target = _find_nearest_target(enemy, TEAM_PLAYER)
|
||||
if not target.is_empty() and _is_in_attack_range(enemy, target["pos"]):
|
||||
_resolve_combat(enemy, target)
|
||||
attack_action = _best_ai_physical_attack_action(enemy, [enemy["pos"]])
|
||||
if not attack_action.is_empty():
|
||||
_resolve_combat(enemy, attack_action["target"])
|
||||
|
||||
|
||||
func _best_ai_physical_attack_action(attacker: Dictionary, origins: Array[Vector2i]) -> Dictionary:
|
||||
var best_action := {}
|
||||
var best_score := -999999
|
||||
var target_team := _opposing_team(str(attacker.get("team", "")))
|
||||
if target_team.is_empty() or _unit_has_action_lock(attacker, "attack"):
|
||||
return {}
|
||||
|
||||
for origin in origins:
|
||||
if not is_inside(origin):
|
||||
continue
|
||||
for target in get_living_units(target_team):
|
||||
if not _attack_cells_from(attacker, origin).has(target["pos"]):
|
||||
continue
|
||||
var damage := calculate_damage(attacker, target)
|
||||
var score := _physical_attack_ai_score(attacker, target, damage)
|
||||
score -= _manhattan(attacker["pos"], origin) * 2
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
best_action = {
|
||||
"origin": origin,
|
||||
"target": target,
|
||||
"damage": damage,
|
||||
"score": score
|
||||
}
|
||||
return best_action
|
||||
|
||||
|
||||
func _physical_attack_ai_score(attacker: Dictionary, target: Dictionary, damage: int) -> int:
|
||||
var score := damage * 10
|
||||
score += _weapon_effectiveness_bonus(attacker, target) * 6
|
||||
score += _ai_target_priority_score(target)
|
||||
if int(target.get("hp", 0)) - damage <= 0:
|
||||
score += 1000
|
||||
return score
|
||||
|
||||
|
||||
func _try_enemy_skill_action(enemy: Dictionary) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user