Mi2dRPGamEng/tests/test_ability_bar.py

172 lines
6.0 KiB
Python

from pathlib import Path
import pytest
from engine.character import Character
from engine.defs import DefRegistry
from engine.entity import EntityPosition
from engine.map import Map
from engine.tile import Tile, TileLayerInstance
from engine.ui import AbilityBar, AbilityBarSlot, populate_ability_bar
from engine.world import World
from resources.logic.actions import activate_ability_bar_slot
DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs"
@pytest.fixture()
def registry():
return DefRegistry.load(DEFS_DIR)
def make_human(registry, **kwargs) -> Character:
return Character(species_id="human", default_body_parts=registry.new_default_body_parts("human"), **kwargs)
def make_world(registry):
field = Map("field", 15, 15, 1)
for x in range(15):
for y in range(15):
field.set_tile(x, y, 0, Tile(flooring=TileLayerInstance("grass")))
world = World(registry=registry)
world.add_map(field)
return world
# --- AbilityBar state ---------------------------------------------------------------------
def test_ability_bar_starts_with_ten_empty_slots():
bar = AbilityBar()
assert len(bar.slots) == 10
assert all(slot is None for slot in bar.slots)
assert bar.selected_index is None
assert bar.selected_slot() is None
def test_assign_places_a_slot_at_the_given_index():
bar = AbilityBar()
slot = AbilityBarSlot(kind="hand", source_id="right_hand", ability_id="time_warp_sphere")
bar.assign(2, slot)
assert bar.slots[2] is slot
def test_select_sets_selected_index_and_selected_slot_reads_it_back():
bar = AbilityBar()
slot = AbilityBarSlot(kind="implant", source_id="chronoimplant", ability_id="time_warp_sphere")
bar.assign(5, slot)
bar.select(5)
assert bar.selected_index == 5
assert bar.selected_slot() is slot
def test_select_out_of_range_is_ignored():
bar = AbilityBar()
bar.select(0)
bar.select(99)
assert bar.selected_index == 0 # unchanged by the invalid select
def test_mouse_click_and_hotkey_both_just_call_select():
# No separate "click" concept - a mouse click on bar position i and pressing numkey i+1
# both resolve to the same select(i) call once input is wired to a bar index.
bar = AbilityBar()
slot = AbilityBarSlot(kind="hand", source_id="left_hand", ability_id="time_warp_sphere")
bar.assign(0, slot)
bar.select(0)
assert bar.selected_slot() is slot
# --- activate_ability_bar_slot resolver -----------------------------------------------------
def test_activate_ability_bar_slot_dispatches_to_hand(registry):
world = make_world(registry)
caster = make_human(registry, position=EntityPosition("field", 5.0, 5.0, 0.0))
caster.wield_item("right_hand", "chronowand", registry)
world.add_entity(caster)
slot = AbilityBarSlot(kind="hand", source_id="right_hand", ability_id="time_warp_sphere")
result = activate_ability_bar_slot(caster, world, registry, slot, (1, 0, 0), now=3.0)
assert result is not None
assert len(world.time_warp_zones) == 1
def test_activate_ability_bar_slot_dispatches_to_implant(registry):
world = make_world(registry)
caster = make_human(registry, position=EntityPosition("field", 5.0, 5.0, 0.0))
caster.install_implant("chronoimplant", registry)
world.add_entity(caster)
slot = AbilityBarSlot(kind="implant", source_id="chronoimplant", ability_id="time_warp_sphere")
result = activate_ability_bar_slot(caster, world, registry, slot, (1, 0, 0), now=3.0)
assert result is not None
assert len(world.time_warp_zones) == 1
def test_activate_ability_bar_slot_unknown_kind_returns_none(registry):
world = make_world(registry)
caster = make_human(registry, position=EntityPosition("field", 5.0, 5.0, 0.0))
world.add_entity(caster)
slot = AbilityBarSlot(kind="bogus", source_id="right_hand", ability_id="time_warp_sphere")
assert activate_ability_bar_slot(caster, world, registry, slot, (1, 0, 0), now=3.0) is None
# --- populate_ability_bar -------------------------------------------------------------------
def test_populate_fills_a_slot_for_a_wielded_ability_granting_item(registry):
bar = AbilityBar()
character = make_human(registry)
character.wield_item("right_hand", "chronowand", registry)
populate_ability_bar(bar, character, registry)
assert bar.slots[0] == AbilityBarSlot(kind="hand", source_id="right_hand", ability_id="time_warp_sphere")
assert bar.slots[1] is None
def test_populate_skips_a_wielded_item_with_no_granted_ability(registry):
bar = AbilityBar()
character = make_human(registry)
character.wield_item("right_hand", "staff_oak", registry)
populate_ability_bar(bar, character, registry)
assert all(slot is None for slot in bar.slots)
def test_populate_fills_a_slot_for_an_installed_implant(registry):
bar = AbilityBar()
character = make_human(registry)
character.install_implant("chronoimplant", registry)
populate_ability_bar(bar, character, registry)
assert bar.slots[0] == AbilityBarSlot(kind="implant", source_id="chronoimplant", ability_id="time_warp_sphere")
def test_populate_orders_hands_before_implants(registry):
bar = AbilityBar()
character = make_human(registry)
character.install_implant("chronoimplant", registry)
character.wield_item("right_hand", "storm_rod", registry)
populate_ability_bar(bar, character, registry)
assert bar.slots[0] == AbilityBarSlot(kind="hand", source_id="right_hand", ability_id="launch_lightning")
assert bar.slots[1] == AbilityBarSlot(kind="implant", source_id="chronoimplant", ability_id="time_warp_sphere")
def test_populate_clears_stale_slots_from_a_previous_call(registry):
bar = AbilityBar()
character = make_human(registry)
character.wield_item("right_hand", "chronowand", registry)
populate_ability_bar(bar, character, registry)
assert bar.slots[0] is not None
character.unwield("right_hand")
populate_ability_bar(bar, character, registry)
assert bar.slots[0] is None