Add sentry pacing to opening battle
This commit is contained in:
@@ -607,7 +607,7 @@ func _prepare_unit(source_unit: Dictionary) -> Dictionary:
|
||||
unit["persist_progression"] = bool(unit.get("persist_progression", true))
|
||||
unit["ai_target_priority"] = max(0, int(unit.get("ai_target_priority", 0)))
|
||||
unit["ai_behavior"] = str(unit.get("ai_behavior", "")).strip_edges().to_lower()
|
||||
if unit["ai_behavior"] != "guard":
|
||||
if not ["guard", "sentry"].has(unit["ai_behavior"]):
|
||||
unit["ai_behavior"] = ""
|
||||
if unit["ai_behavior"] == "guard" and not unit.has("ai_guard_radius"):
|
||||
unit["ai_guard_radius"] = 2
|
||||
@@ -616,6 +616,15 @@ func _prepare_unit(source_unit: Dictionary) -> Dictionary:
|
||||
if not is_inside(guard_anchor):
|
||||
guard_anchor = unit["pos"]
|
||||
unit["ai_guard_anchor"] = guard_anchor
|
||||
if unit["ai_behavior"] == "sentry" and not unit.has("ai_sentry_radius"):
|
||||
unit["ai_sentry_radius"] = 4
|
||||
unit["ai_sentry_radius"] = max(0, int(unit.get("ai_sentry_radius", 0)))
|
||||
unit["ai_sentry_activation_turn"] = max(0, int(unit.get("ai_sentry_activation_turn", 0)))
|
||||
var sentry_anchor := _condition_cell(unit.get("ai_sentry_anchor", [unit["pos"].x, unit["pos"].y]))
|
||||
if not is_inside(sentry_anchor):
|
||||
sentry_anchor = unit["pos"]
|
||||
unit["ai_sentry_anchor"] = sentry_anchor
|
||||
unit["ai_awake"] = bool(unit.get("ai_awake", false))
|
||||
unit["status_effects"] = []
|
||||
unit["acted"] = false
|
||||
unit["moved"] = false
|
||||
@@ -3117,6 +3126,11 @@ func _run_enemy_turn() -> void:
|
||||
|
||||
func _enemy_take_action(enemy: Dictionary) -> void:
|
||||
var movement_cells := _movement_range_for_unit(enemy)
|
||||
if _is_ai_sentry(enemy) and not _ai_sentry_is_awake(enemy, movement_cells):
|
||||
var sentry_return_cell := _best_ai_sentry_return_cell(enemy, movement_cells)
|
||||
if sentry_return_cell != enemy["pos"]:
|
||||
_move_ai_unit(enemy, sentry_return_cell)
|
||||
return
|
||||
if _is_ai_guard(enemy):
|
||||
movement_cells = _ai_guard_movement_cells(enemy, movement_cells)
|
||||
if not _ai_guard_is_engaged(enemy, movement_cells):
|
||||
@@ -3185,6 +3199,60 @@ func _is_ai_guard(unit: Dictionary) -> bool:
|
||||
return str(unit.get("ai_behavior", "")).strip_edges().to_lower() == "guard"
|
||||
|
||||
|
||||
func _is_ai_sentry(unit: Dictionary) -> bool:
|
||||
return str(unit.get("ai_behavior", "")).strip_edges().to_lower() == "sentry"
|
||||
|
||||
|
||||
func _ai_sentry_anchor(unit: Dictionary) -> Vector2i:
|
||||
var anchor: Vector2i = unit.get("ai_sentry_anchor", unit.get("pos", Vector2i(-1, -1)))
|
||||
if not is_inside(anchor):
|
||||
return unit.get("pos", Vector2i(-1, -1))
|
||||
return anchor
|
||||
|
||||
|
||||
func _ai_sentry_radius(unit: Dictionary) -> int:
|
||||
return max(0, int(unit.get("ai_sentry_radius", 0)))
|
||||
|
||||
|
||||
func _ai_sentry_contains_cell(unit: Dictionary, cell: Vector2i) -> bool:
|
||||
return _manhattan(_ai_sentry_anchor(unit), cell) <= _ai_sentry_radius(unit)
|
||||
|
||||
|
||||
func _ai_sentry_is_awake(unit: Dictionary, movement_cells: Array[Vector2i]) -> bool:
|
||||
if bool(unit.get("ai_awake", false)):
|
||||
return true
|
||||
var activation_turn := int(unit.get("ai_sentry_activation_turn", 0))
|
||||
if activation_turn > 0 and turn_number >= activation_turn:
|
||||
unit["ai_awake"] = true
|
||||
return true
|
||||
var target_team := _opposing_team(str(unit.get("team", "")))
|
||||
if target_team.is_empty():
|
||||
return false
|
||||
for target in get_living_units(target_team):
|
||||
if _ai_sentry_contains_cell(unit, target.get("pos", Vector2i(-1, -1))):
|
||||
unit["ai_awake"] = true
|
||||
return true
|
||||
if not _best_ai_physical_attack_action(unit, [unit.get("pos", Vector2i(-1, -1))]).is_empty():
|
||||
unit["ai_awake"] = true
|
||||
return true
|
||||
if not movement_cells.is_empty() and not _best_ai_physical_attack_action(unit, movement_cells).is_empty():
|
||||
unit["ai_awake"] = true
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _best_ai_sentry_return_cell(unit: Dictionary, movement_cells: Array[Vector2i]) -> Vector2i:
|
||||
var best_cell: Vector2i = unit.get("pos", Vector2i(-1, -1))
|
||||
var anchor := _ai_sentry_anchor(unit)
|
||||
var best_distance := _manhattan(best_cell, anchor)
|
||||
for cell in movement_cells:
|
||||
var distance := _manhattan(cell, anchor)
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
best_cell = cell
|
||||
return best_cell
|
||||
|
||||
|
||||
func _ai_guard_anchor(unit: Dictionary) -> Vector2i:
|
||||
var anchor: Vector2i = unit.get("ai_guard_anchor", unit.get("pos", Vector2i(-1, -1)))
|
||||
if not is_inside(anchor):
|
||||
|
||||
@@ -63,6 +63,18 @@ func hydrate_deployment(deployment: Dictionary) -> Dictionary:
|
||||
unit["ai_guard_radius"] = int(deployment.get("ai_guard_radius", 0))
|
||||
elif unit["ai_behavior"] == "guard":
|
||||
unit["ai_guard_radius"] = 2
|
||||
if deployment.has("ai_sentry_anchor"):
|
||||
unit["ai_sentry_anchor"] = deployment["ai_sentry_anchor"]
|
||||
elif unit["ai_behavior"] == "sentry":
|
||||
unit["ai_sentry_anchor"] = deployment.get("pos", [0, 0])
|
||||
if deployment.has("ai_sentry_radius"):
|
||||
unit["ai_sentry_radius"] = int(deployment.get("ai_sentry_radius", 0))
|
||||
elif unit["ai_behavior"] == "sentry":
|
||||
unit["ai_sentry_radius"] = 4
|
||||
if deployment.has("ai_sentry_activation_turn"):
|
||||
unit["ai_sentry_activation_turn"] = int(deployment.get("ai_sentry_activation_turn", 0))
|
||||
if deployment.has("ai_awake"):
|
||||
unit["ai_awake"] = bool(deployment.get("ai_awake", false))
|
||||
unit["level"] = int(deployment.get("level", officer.get("level", 1)))
|
||||
unit["exp"] = int(deployment.get("exp", officer.get("exp", 0)))
|
||||
unit["max_hp"] = int(stats.get("hp", stats.get("max_hp", 1)))
|
||||
|
||||
Reference in New Issue
Block a user