15func should_queue(card:Dictionary, direction:Vector2i, affected_cells:Array) -> bool:
16 if direction == Vector2i.ZERO
or affected_cells.is_empty():
18 var targeting = _targeting(card)
19 var type = str(targeting.get(
"type",
"projectile"))
20 if card.has(
"compound")
and str(card.get(
"manifestation",
"")) ==
"":
22 return type
in [
"projectile",
"lob"]
25func create_effect(card:Dictionary, origin_cell:Vector2i, affected_cells:Array, used_slot:int, direction:Vector2i, options:Dictionary = {}) -> Dictionary:
26 var targeting = _targeting(card)
27 var type = str(targeting.get(
"type",
"projectile"))
28 var travel_seconds = max(0.08, float(options.get(
"travel_ms", 520)) / 1000.0)
29 var end_cell = _impact_cell(card, origin_cell, affected_cells, direction)
31 "card": card.duplicate(true),
32 "used_slot": used_slot,
33 "card_id": str(card.get(
"id",
"")),
35 "shape": str(card.get(
"visual", {}).get(
"shape", type)),
36 "origin_cell": origin_cell,
38 "direction": direction,
39 "affected_cells": affected_cells.duplicate(true),
41 "duration": travel_seconds,
42 "color": str(card.get(
"visual", {}).get(
"color", options.get(
"color",
"#ffffff")))
46func step_effects(active_effects:Array, delta:float) -> Dictionary:
49 for raw_effect
in active_effects:
50 if not raw_effect
is Dictionary:
52 var effect = raw_effect.duplicate(true)
53 effect[
"age"] = float(effect.get(
"age", 0.0)) + delta
54 if float(effect.get(
"age", 0.0)) >= float(effect.get(
"duration", 0.1)):
64func resolve_cells(effect:Dictionary, resolver:Callable =
Callable()) -> Array:
65 if resolver.is_valid():
66 var resolved = resolver.call(
67 effect.get(
"card", {}),
68 _cell_from_any(effect.get(
"origin_cell", Vector2i.ZERO)),
69 _cell_from_any(effect.get(
"direction", Vector2i.ZERO))
72 return resolved.duplicate(true)
73 var cells = effect.get(
"affected_cells", [])
74 return cells.duplicate(true)
if cells
is Array
else []
77func _impact_cell(card:Dictionary, origin_cell:Vector2i, affected_cells:Array, direction:Vector2i) -> Vector2i:
78 var targeting = _targeting(card)
79 var type = str(targeting.get(
"type",
"projectile"))
80 if type ==
"lob" and direction != Vector2i.ZERO:
81 return origin_cell + direction * int(targeting.get(
"range", 1))
82 if affected_cells.is_empty():
84 return _cell_from_any(affected_cells[affected_cells.size() - 1])
87func _targeting(card:Dictionary) -> Dictionary:
88 var targeting = card.get(
"targeting", {})
89 return targeting
if targeting
is Dictionary
else {}
92func _cell_from_any(value) -> Vector2i:
96 return Vector2i(int(value.x), int(value.y))
97 if value
is Array
and value.size() >= 2:
98 return Vector2i(int(value[0]), int(value[1]))
99 if value
is Dictionary
and value.has(
"cell"):
100 return _cell_from_any(value.get(
"cell"))