Make turnbased combat work

This commit is contained in:
Griatch 2023-05-15 19:34:38 +02:00
parent ea7a3c83d7
commit f70fd64478
7 changed files with 139 additions and 60 deletions

View file

@ -200,10 +200,6 @@ class CombatActionStunt(CombatAction):
f"to gain {'advantage' if self.advantage else 'disadvantage'} "
f"against $You({target.key})!"
)
self.msg(
"|yHaving succeeded, you hold back to plan your next move.|n [hold]",
broadcast=False,
)
else:
self.msg(f"$You({defender.key}) $conj(resist)! $You() $conj(fail) the stunt.")
@ -258,6 +254,7 @@ class CombatActionWield(CombatAction):
def execute(self):
self.combatant.equipment.move(self.item)
self.msg(f"$You() $conj(wield) $You({self.item.key}).")
# main combathandler
@ -311,6 +308,7 @@ class EvAdventureCombatBaseHandler(DefaultScript):
key=combathandler_key,
obj=obj,
persistent=persistent,
autostart=False,
**kwargs,
)
obj.ndb.combathandler = combathandler

View file

@ -210,6 +210,18 @@ class EvAdventureTurnbasedCombatHandler(EvAdventureCombatBaseHandler):
self.stop()
self.delete()
def get_combat_summary(self, combatant):
"""Add your next queued action to summary"""
summary = super().get_combat_summary(combatant)
next_action = self.get_next_action_dict(combatant) or {"key": "hold"}
next_repeat = self.time_until_next_repeat()
summary = (
f"{summary}\n Your queued action: [|b{next_action['key']}|n] (|b{next_repeat}s|n until"
" next round,\n or until all combatants have chosen their next action)."
)
return summary
def get_sides(self, combatant):
"""
Get a listing of the two 'sides' of this combat, from the perspective of the provided
@ -265,19 +277,18 @@ class EvAdventureTurnbasedCombatHandler(EvAdventureCombatBaseHandler):
self.combatants[combatant] = action_dict
# track who inserted actions this turn (non-persistent)
did_action = set(self.ndb.did_action or ())
did_action = set(self.ndb.did_action or set())
did_action.add(combatant)
if len(did_action) >= len(self.combatants):
# everyone has inserted an action. Start next turn without waiting!
self.force_repeat()
def get_next_action_dict(self, combatant, rotate_queue=True):
def get_next_action_dict(self, combatant):
"""
Give the action_dict for the next action that will be executed.
Args:
combatant (EvAdventureCharacter, EvAdventureNPC): The combatant to get the action for.
rotate_queue (bool, optional): Rotate the queue after getting the action dict.
Returns:
dict: The next action-dict in the queue.
@ -355,6 +366,8 @@ class EvAdventureTurnbasedCombatHandler(EvAdventureCombatBaseHandler):
for combatant in combatants:
self.execute_next_action(combatant)
self.ndb.did_action = set()
# check if anyone is defeated
for combatant in list(self.combatants.keys()):
if combatant.hp <= 0:
@ -364,6 +377,8 @@ class EvAdventureTurnbasedCombatHandler(EvAdventureCombatBaseHandler):
self.combatants.pop(combatant)
self.defeated_combatants.append(combatant)
self.msg("|r$You() $conj(fall) to the ground, defeated.|n", combatant=combatant)
else:
self.combatants[combatant] = self.fallback_action_dict
# check if anyone managed to flee
flee_timeout = self.flee_timeout
@ -402,10 +417,14 @@ def _get_combathandler(caller, turn_timeout=30, flee_time=3, combathandler_key="
caller.location,
interval=turn_timeout,
attributes=[("flee_time", flee_time)],
combathandler_key=combathandler_key,
key=combathandler_key,
)
def _rerun_current_node(caller, raw_string, **kwargs):
return None, kwargs
def _queue_action(caller, raw_string, **kwargs):
"""
Goto-function that queue the action with the CombatHandler. This always returns
@ -462,6 +481,10 @@ def _get_default_wizard_options(caller, **kwargs):
return [
{"key": ("back", "b"), "goto": (_step_wizard, {**kwargs, **{"step": "back"}})},
{"key": ("abort", "a"), "goto": (_step_wizard, {**kwargs, **{"step": "abort"}})},
{
"key": "_default",
"goto": (_rerun_current_node, kwargs),
},
]
@ -473,6 +496,7 @@ def node_choose_enemy_target(caller, raw_string, **kwargs):
action_dict = kwargs["action_dict"]
combathandler = _get_combathandler(caller)
_, enemies = combathandler.get_sides(caller)
options = [
@ -489,6 +513,30 @@ def node_choose_enemy_target(caller, raw_string, **kwargs):
return text, options
def node_choose_enemy_recipient(caller, raw_string, **kwargs):
"""
Choose an enemy as a 'recipient' for an action.
"""
text = "Choose an enemy as a recipient."
action_dict = kwargs["action_dict"]
combathandler = _get_combathandler(caller)
_, enemies = combathandler.get_sides(caller)
options = [
{
"desc": target.get_display_name(caller),
"goto": (
_step_wizard,
{**kwargs, **{"action_dict": {**action_dict, **{"recipient": target}}}},
),
}
for target in enemies
]
options.extend(_get_default_wizard_options(caller, **kwargs))
return text, options
def node_choose_allied_target(caller, raw_string, **kwargs):
"""
Choose an enemy as a target for an action
@ -507,11 +555,49 @@ def node_choose_allied_target(caller, raw_string, **kwargs):
_step_wizard,
{
**kwargs,
**{
"action_dict": {
**{**action_dict, **{"target": caller, "recipient": caller}}
}
**{"action_dict": {**action_dict, **{"target": caller}}},
},
),
}
]
options.extend(
[
{
"desc": target.get_display_name(caller),
"goto": (
_step_wizard,
{
**kwargs,
**{"action_dict": {**action_dict, **{"target": target}}},
},
),
}
for target in allies
]
)
options.extend(_get_default_wizard_options(caller, **kwargs))
return text, options
def node_choose_allied_recipient(caller, raw_string, **kwargs):
"""
Choose an allied recipient for an action
"""
text = "Choose an ally as a recipient."
action_dict = kwargs["action_dict"]
combathandler = _get_combathandler(caller)
allies, _ = combathandler.get_sides(caller)
# can choose yourself
options = [
{
"desc": "Yourself",
"goto": (
_step_wizard,
{
**kwargs,
**{"action_dict": {**action_dict, **{"recipient": caller}}},
},
),
}
@ -527,7 +613,7 @@ def node_choose_allied_target(caller, raw_string, **kwargs):
**{
"action_dict": {
**action_dict,
**{"target": target, "recipient": target},
**{"recipient": target},
}
},
},
@ -585,7 +671,10 @@ def node_choose_use_item(caller, raw_string, **kwargs):
options = [
{
"desc": item.get_display_name(caller),
"goto": (_step_wizard, {**kwargs, **{**action_dict, **{"item": item}}}),
"goto": (
_step_wizard,
{**kwargs, **{"action_dict": {**action_dict, **{"item": item}}}},
),
}
for item in caller.equipment.get_usable_objects_from_backpack()
]
@ -607,7 +696,10 @@ def node_choose_wield_item(caller, raw_string, **kwargs):
options = [
{
"desc": item.get_display_name(caller),
"goto": (_step_wizard, {**kwargs, **{**action_dict, **{"item": item}}}),
"goto": (
_step_wizard,
{**kwargs, **{"action_dict": {**action_dict, **{"item": item}}}},
),
}
for item in caller.equipment.get_wieldable_objects_from_backpack()
]
@ -623,6 +715,8 @@ def node_combat(caller, raw_string, **kwargs):
combathandler = _get_combathandler(caller)
caller.msg(f"combathandler.combatants: {combathandler.combatants}")
text = combathandler.get_combat_summary(caller)
options = [
{
@ -642,8 +736,8 @@ def node_combat(caller, raw_string, **kwargs):
{
"steps": [
"node_choose_ability",
"node_choose_allied_target",
"node_choose_enemy_target",
"node_choose_allied_recipient",
],
"action_dict": {"key": "stunt", "advantage": True},
},
@ -656,7 +750,7 @@ def node_combat(caller, raw_string, **kwargs):
{
"steps": [
"node_choose_ability",
"node_choose_enemy_target",
"node_choose_enemy_recipient",
"node_choose_allied_target",
],
"action_dict": {"key": "stunt", "advantage": False},
@ -701,6 +795,10 @@ def node_combat(caller, raw_string, **kwargs):
"desc": "hold, doing nothing",
"goto": (_queue_action, {"action_dict": {"key": "hold"}}),
},
{
"key": "_default",
"goto": "node_combat",
},
]
return text, options
@ -763,6 +861,8 @@ class CmdTurnAttack(Command):
{
"node_choose_enemy_target": node_choose_enemy_target,
"node_choose_allied_target": node_choose_allied_target,
"node_choose_enemy_recipient": node_choose_enemy_recipient,
"node_choose_allied_recipient": node_choose_allied_recipient,
"node_choose_ability": node_choose_ability,
"node_choose_use_item": node_choose_use_item,
"node_choose_wield_item": node_choose_wield_item,
@ -770,6 +870,7 @@ class CmdTurnAttack(Command):
},
startnode="node_combat",
combathandler=combathandler,
auto_look=False,
# cmdset_mergetype="Union",
persistent=True,
)

View file

@ -49,6 +49,9 @@ class EquipmentHandler:
WieldLocation.BACKPACK: [],
},
)
self.slots[WieldLocation.BACKPACK] = [
obj for obj in self.slots[WieldLocation.BACKPACK] if obj and obj.id
]
def _save(self):
"""
@ -358,6 +361,7 @@ class EquipmentHandler:
obj
for obj in self.slots[WieldLocation.BACKPACK]
if obj
and obj.id
and obj.inventory_use_slot
in (WieldLocation.WEAPON_HAND, WieldLocation.TWO_HANDS, WieldLocation.SHIELD_HAND)
]
@ -376,7 +380,7 @@ class EquipmentHandler:
return [
obj
for obj in self.slots[WieldLocation.BACKPACK]
if obj and obj.inventory_use_slot in (WieldLocation.BODY, WieldLocation.HEAD)
if obj and obj.id and obj.inventory_use_slot in (WieldLocation.BODY, WieldLocation.HEAD)
]
def get_usable_objects_from_backpack(self):