Zepar
The Fate Weaver
Unit #115
| HP | PWR | CP | Speed | Range | Tier |
|---|---|---|---|---|---|
| 12 (+6) | 3 (+1) | 3 (+2) | Fast | Local | B |
Abilities
Passive
c: When any Other Local Demon would take damage (after n), you may instead deal any amount of its incoming damage as Fixed Damage to Any Other Local Demon(s) that are Allied* to the damaged Demon.
Engine Implementation
def _zepar_damage_redirect(
state: GameState, event: GameEvent, demon: DemonInstance, depth: int
):
"""#115 Zepar idx=0 — Field Passive: Damage Redirect.
When any Other Local Demon would take damage (after DEF), Zepar may redirect
any amount of that damage as Fixed Damage to another allied demon of the
damaged demon's owner (in the same lane).
Fires on DAMAGE_RECEIVED. Checks:
- event.target is NOT Zepar itself
- event.target is in the same lane as Zepar (Local)
- Zepar is not fatally_wounded
Auto-redirects all damage (event.value) to the first eligible ally of the
damaged demon (same owner as target, same lane, not target itself, not
fatally_wounded).
NOTE: The redirected damage is Fixed (bypasses DEF). The original damage
was already applied — to fully redirect we would need to undo it. Since the
event fires AFTER the damage lands, this implementation adds the redirect
damage ON TOP. A true pre-empt would require event cancellation which this
engine does not support. This is a best-effort approximation.
"""
from engine.operations import deal_fixed_damage
# Must have a target
if event.target is None:
return None
# Zepar must not be the damaged target
if event.target.instance_id == demon.instance_id:
return None
# Re-fetch Zepar from state
zepar_current = next(
(d for d in state.demons if d.instance_id == demon.instance_id), None
)
if zepar_current is None or zepar_current.fatally_wounded:
return None
# Zepar must be in the same lane as the damaged target
if event.target.lane != zepar_current.lane:
return None
x = event.value if event.value is not None else 0
if x <= 0:
return None
# Find an eligible ally of the damaged demon to redirect damage to:
# same owner as target, same lane, not the target itself, not fatally_wounded
damaged_owner = event.target.owner
eligible = [
d for d in state.demons
if d.owner == damaged_owner
and d.lane == event.target.lane
and d.instance_id != event.target.instance_id
and not d.fatally_wounded
]
if not eligible:
return None # No eligible redirect target
redirect_target = eligible[0]
# _fire_events=False prevents cascade: redirected damage should not
# re-trigger Zepar or other DAMAGE_RECEIVED handlers
return deal_fixed_damage(state, redirect_target, x, _fire_events=False)
register_trigger("115", 0, _zepar_damage_redirect)
Bloodletting — 1 AP
Bloodletting: 1 AP - a: Deal 1 Fixed Damage to All Local Enemy Demons.
Engine Implementation
def _zepar_bloodletting(
state: GameState, demon: DemonInstance, targets, choices, rng
) -> GameState:
"""#115 Zepar — Bloodletting
Action, 1 AP, (exhaust): Deal 1 Fixed Damage to All Local Enemy Demons.
"All Local Enemy Demons" = enemies in same lane as Zepar.
Fixed Damage bypasses DEF.
"""
from engine.operations import deal_fixed_damage
opponent = Side.PLAYER_2 if demon.owner == Side.PLAYER_1 else Side.PLAYER_1
local_enemies = [
d for d in state.demons
if d.lane == demon.lane and d.owner == opponent and not d.fatally_wounded
]
for enemy in local_enemies:
e_current = next(
(d for d in state.demons if d.instance_id == enemy.instance_id), None
)
if e_current is None or e_current.fatally_wounded:
continue
state = deal_fixed_damage(state, e_current, 1)
return state
register_ability("115", 1, _zepar_bloodletting)
Related Articles