Start adding combat commands

This commit is contained in:
Griatch 2023-01-26 00:02:41 +01:00
parent a5afa75f59
commit 052683fce8

View file

@ -102,6 +102,7 @@ Choose who to block:
import random import random
from collections import defaultdict, deque from collections import defaultdict, deque
from evennia import Command, create_script
from evennia.scripts.scripts import DefaultScript from evennia.scripts.scripts import DefaultScript
from evennia.typeclasses.attributes import AttributeProperty from evennia.typeclasses.attributes import AttributeProperty
from evennia.utils import dbserialize, delay, evmenu, evtable, logger from evennia.utils import dbserialize, delay, evmenu, evtable, logger
@ -222,6 +223,10 @@ class CombatActionDoNothing(CombatAction):
Note: Note:
Refer to as 'nothing' Refer to as 'nothing'
action_dict = {
"key": "nothing"
}
""" """
@ -229,9 +234,9 @@ class CombatActionAttack(CombatAction):
""" """
A regular attack, using a wielded weapon. A regular attack, using a wielded weapon.
action-dict ('attack') action-dict = {
{ "key": "attack",
"defender": Character/Object "target": Character/Object
} }
Note: Note:
@ -242,17 +247,17 @@ class CombatActionAttack(CombatAction):
def execute(self): def execute(self):
attacker = self.combatant attacker = self.combatant
weapon = attacker.weapon weapon = attacker.weapon
defender = self.defender target = self.target
is_hit, quality, txt = rules.dice.opposed_saving_throw( is_hit, quality, txt = rules.dice.opposed_saving_throw(
attacker, attacker,
defender, target,
attack_type=weapon.attack_type, attack_type=weapon.attack_type,
defense_type=attacker.weapon.defense_type, defense_type=attacker.weapon.defense_type,
advantage=self.has_advantage(attacker, defender), advantage=self.has_advantage(attacker, target),
disadvantage=self.has_disadvantage(attacker, defender), disadvantage=self.has_disadvantage(attacker, target),
) )
self.msg(f"$You() $conj(attack) $You({defender.key}) with {weapon.key}: {txt}") self.msg(f"$You() $conj(attack) $You({target.key}) with {weapon.key}: {txt}")
if is_hit: if is_hit:
# enemy hit, calculate damage # enemy hit, calculate damage
weapon_dmg_roll = attacker.weapon.damage_roll weapon_dmg_roll = attacker.weapon.damage_roll
@ -262,14 +267,14 @@ class CombatActionAttack(CombatAction):
if quality is Ability.CRITICAL_SUCCESS: if quality is Ability.CRITICAL_SUCCESS:
dmg += rules.dice.roll(weapon_dmg_roll) dmg += rules.dice.roll(weapon_dmg_roll)
message = ( message = (
f" $You() |ycritically|n $conj(hit) $You({defender.key}) for |r{dmg}|n damage!" f" $You() |ycritically|n $conj(hit) $You({target.key}) for |r{dmg}|n damage!"
) )
else: else:
message = f" $You() $conj(hit) $You({defender.key}) for |r{dmg}|n damage!" message = f" $You() $conj(hit) $You({target.key}) for |r{dmg}|n damage!"
self.msg(message) self.msg(message)
# call hook # call hook
defender.at_damage(dmg, attacker=attacker) target.at_damage(dmg, attacker=attacker)
# note that we mustn't remove anyone from combat yet, because this is # note that we mustn't remove anyone from combat yet, because this is
# happening simultaneously. So checking of the final hp # happening simultaneously. So checking of the final hp
@ -277,7 +282,7 @@ class CombatActionAttack(CombatAction):
else: else:
# a miss # a miss
message = f" $You() $conj(miss) $You({defender.key})." message = f" $You() $conj(miss) $You({target.key})."
if quality is Ability.CRITICAL_FAILURE: if quality is Ability.CRITICAL_FAILURE:
attacker.weapon.quality -= 1 attacker.weapon.quality -= 1
message += ".. it's a |rcritical miss!|n, damaging the weapon." message += ".. it's a |rcritical miss!|n, damaging the weapon."
@ -291,14 +296,14 @@ class CombatActionStunt(CombatAction):
against an ally, or granting an advantage against them, we need to make a check first. We don't against an ally, or granting an advantage against them, we need to make a check first. We don't
do a check if giving an advantage to an ally or ourselves. do a check if giving an advantage to an ally or ourselves.
action_dict: action_dict = {
{ "key": "stunt",
"recipient": Character/NPC, "recipient": Character/NPC,
"target": Character/NPC, "target": Character/NPC,
"advantage": bool, # if False, it's a disadvantage "advantage": bool, # if False, it's a disadvantage
"stunt_type": Ability, # what ability (like STR, DEX etc) to use to perform this stunt. "stunt_type": Ability, # what ability (like STR, DEX etc) to use to perform this stunt.
"defense_type": Ability, # what ability to use to defend against (negative) effects of this "defense_type": Ability, # what ability to use to defend against (negative) effects of this
stunt. stunt.
} }
Note: Note:
@ -357,10 +362,11 @@ class CombatActionUseItem(CombatAction):
scrolls and potions, not swords and shields). If this is some sort of weapon or spell rune, scrolls and potions, not swords and shields). If this is some sort of weapon or spell rune,
we refer to the item to determine what to use for attack/defense rolls. we refer to the item to determine what to use for attack/defense rolls.
action_dict: } action_dict = {
"item": Object "key": "use",
"target": Character/NPC/Object "item": Object
} "target": Character/NPC/Object
}
Note: Note:
Refer to as 'use' Refer to as 'use'
@ -397,8 +403,9 @@ class CombatActionWield(CombatAction):
wielding, if any. wielding, if any.
action_dict = { action_dict = {
"item": Object "key": "wield",
} "item": Object
}
Note: Note:
Refer to as 'wield'. Refer to as 'wield'.
@ -413,6 +420,11 @@ class CombatActionFlee(CombatAction):
""" """
Start (or continue) fleeing/disengaging from combat. Start (or continue) fleeing/disengaging from combat.
action_dict = {
"key": "flee",
"item": Object
}
Note: Note:
Refer to as 'flee'. Refer to as 'flee'.
@ -431,6 +443,7 @@ class CombatActionHinder(CombatAction):
Hinder a fleeing opponent from fleeing/disengaging from combat. Hinder a fleeing opponent from fleeing/disengaging from combat.
action_dict = { action_dict = {
"key": "hinder",
"target": Character/NPC "target": Character/NPC
} }
@ -708,6 +721,85 @@ class EvAdventureCombatHandler(DefaultScript):
# Command-based combat commands # Command-based combat commands
class CmdAttack(Command):
"""
Start or join a fight.
Usage:
attack <target>
hit <target>
"""
key = "attack"
aliases = ("hit",)
def parse(self):
self.args = self.args.strip()
def func(self):
if not self.args:
self.msg("What are you attacking?")
reuturn
target = self.search(self.args)
if not target:
return
location = self.caller.location
combathandler = location.scripts.get("combathandler")
if not combathandler:
combathandler = create_script(
EvAdventureCombatHandler,
key="combathandler",
obj=location,
interval=2,
persistent=True,
)
# this can be done over and over
combathandler.add_combatant(self)
combathandler.queue_action(self.caller, {"target": target})
class CmdStunt(Command):
"""
Perform a combat stunt, that boosts an ally against a target, or
foils an enemy, giving them disadvantage against an ally.
Usage:
boost <recipient> vs <target>
foil <recipient> vs <target>
boost vs <target> (same as boost me vs target)
foil <target> (same as foil <target> vs me)
Example:
boost me vs Goblin
boost vs Goblin
foil Goblin vs me
foil Goblin
boost Wizard vs Goblin
"""
key = "stunt"
aliases = (
"boost",
"foil",
)
def parse(self):
if " vs " in self.args:
self.recipient, self.target = (part.strip() for part in self.args.split(" vs "))
elif self.cmdname == "foil":
self.recipient, self.target = "me", self.args.strip()
else:
self.recipient, self.target = self.args.strip(), "me"
def func(self):
pass
# ----------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------
# Combat Actions # Combat Actions
# ----------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------