diff --git a/commands/default_cmdsets.py b/commands/default_cmdsets.py index 9dd8897..4fec52b 100644 --- a/commands/default_cmdsets.py +++ b/commands/default_cmdsets.py @@ -18,7 +18,7 @@ from evennia.contrib.game_systems.clothing import ClothedCharacterCmdSet from evennia.contrib.game_systems.containers import ContainerCmdSet from evennia import default_cmds -from .encounter_cmdset import CmdEngage +from .encounter.engage import CmdEngage from .clothing import CmdRemove class CharacterCmdSet(default_cmds.CharacterCmdSet): diff --git a/commands/encounter/__init__.py b/commands/encounter/__init__.py new file mode 100644 index 0000000..69999aa --- /dev/null +++ b/commands/encounter/__init__.py @@ -0,0 +1,41 @@ +from commands.command import Command + +class EncounterCommand(Command): + energy_cost = 1 + allow_self_target = False + + def handler(self): + return self.caller.ndb.encounter_handler + + def can_perform(self): + # Returns whether the caller is having their turn and if they have enough energy + # to make this action + return self.handler().can_act(self) + + def has_target(self): + # Targeting code: + # Looks for the suggested target + # If none is found but there is only one other character in the encounter, + # default to that other character + # Else ask player for clarification + if self.target: + self.target = self.caller.search(self.target) + if not self.target: + default_target = self.handler().has_default_target(self.caller) + if default_target: + self.caller.msg("Defaulting to other character in encounter") + self.target = default_target + else: + self.caller.msg(f"Who are you trying to {self.key}?") + self.target = None + else: + default_target = self.handler().has_default_target(self.caller) + if default_target: + self.target = default_target + else: + self.caller.msg(f"Who are you trying to {self.key}?") + self.target = None + if self.caller == self.target and not self.allow_self_target: + self.msg(f"You aren't supposed to {self.key} yourself!") + return self.target + diff --git a/commands/encounter/actions.py b/commands/encounter/actions.py new file mode 100644 index 0000000..ef8c3ac --- /dev/null +++ b/commands/encounter/actions.py @@ -0,0 +1,36 @@ +from commands.encounter import EncounterCommand + +# Bite (Regular) +class CmdBite(EncounterCommand): + "Bite down on your target with your teeth" + key = "bite" + help_category = "Violence" + + def parse(self): + self.args = self.args.strip() + target, *adverb = self.args.split(":") + self.target = target.strip() + self.adverb = ' ' + adverb[0].strip() if adverb else '' + + def func(self): + if super().has_target() and super().can_perform(): + self.caller.msg(f"You bite {self.target.key}{self.adverb}") + self.target.msg(f"{self.caller.key} bites you{self.adverb}") + # damage calculations, chance to miss, etc + +# Kiss (Regular) +class CmdKiss(EncounterCommand): + "Kiss the target with your lips" + key = "kiss" + help_category = "Sex" + + def parse(self): + self.args = self.args.strip() + target, *adverb = self.args.split(':') + self.target = target.strip() + self.adverb = ' ' + adverb[0].strip() if adverb else '' + + def func(self): + if super().has_target() and super().can_perform(): + self.caller.msg(f"You kiss {self.target}{self.adverb}") + self.target.msg(f"{self.caller} kisses you{self.adverb}") diff --git a/commands/encounter/engage.py b/commands/encounter/engage.py new file mode 100644 index 0000000..a7cd8fd --- /dev/null +++ b/commands/encounter/engage.py @@ -0,0 +1,36 @@ +from commands.command import Command +from evennia.utils import inherits_from +from typeclasses.characters import Character +from evennia.utils.create import create_script + +class CmdEngage(Command): + """ + Initiates an encounter with the selected target + """ + key = "engage" + aliases = ["encounter", "fight"] + def func(self): + if not self.args: + self.caller.msg("Usage: engage ") + return + target = self.caller.search(self.args) + if not target: + return + if not inherits_from(target, Character) or not target.access(self.caller, 'engage'): + self.caller.msg(target.db.engage_err_msg or f"You can't initiate an encounter with {target.name}.") + return + if target == self.caller: + self.caller.msg("You can't initiate an encounter with yourself!") + return + if target.ndb.encounter_handler: + target.ndb.encounter_handler.add_character(self.caller) + target.ndb.encounter_handler.msg_all(f"{self.caller} joins the encounter") + else: + handler = create_script("encounter_handler.EncounterHandler") + handler.add_character(self.caller) + handler.add_character(target) + target.msg(f"{self.caller} has engaged you in an encounter!") + target.msg("You may leave using the flee command (or aliases)") + self.caller.msg(f"You have entered an encounter with {target}. Be polite!") + self.caller.msg("It is now your turn:") + diff --git a/commands/encounter/sets.py b/commands/encounter/sets.py new file mode 100644 index 0000000..08afac3 --- /dev/null +++ b/commands/encounter/sets.py @@ -0,0 +1,7 @@ +from evennia import CmdSet +from .actions import * + +class SetSpeciesHuman(CmdSet): + def at_cmdset_creation(self): + self.add(CmdBite) + self.add(CmdKiss) diff --git a/commands/encounter/special.py b/commands/encounter/special.py new file mode 100644 index 0000000..7adf3da --- /dev/null +++ b/commands/encounter/special.py @@ -0,0 +1,88 @@ +from evennia import CmdSet +from commands.encounter import EncounterCommand + +class CmdPass(EncounterCommand): + "Pass the turn over to the next character" + energy_cost = 0 + key = "pass" + aliases = ["next", "finish", "done"] + help_category = "Encounter" + + def func(self): + if super().can_perform(): + self.caller.msg("You end your turn") + super().handler().next_turn() + +class CmdRP(EncounterCommand): + "Free-form text input (for describing your actions in RP)" + energy_cost = 0 + key = "rp" + arg_regex = None + aliases = [">"] + help_category = "Encounter" + + def func(self): + if super().can_perform(): + super().handler().msg_all(self.args.strip()) + +class CmdFlee(EncounterCommand): + "Exits the current encounter" + energy_cost = 0 + key = "flee" + aliases = ["escape", "run", "run away", "leave"] + help_category = "Encounter" + + def func(self): + super().handler().msg_all(f"{self.caller.key} left the encounter") + super().handler().remove_character(self.caller) + +class CmdOOC(EncounterCommand): + "Say something out-of-character" + energy_cost = 0 + key = "(" + arg_regex = None + + def func(self): + super().handler().msg_all(f"({self.caller}: {self.args.strip()})") + +class CmdPose(EncounterCommand): + """ + strike a pose + + Usage: + pose + pose's + + Example: + pose is standing by the wall, smiling. + -> others will see: + Tom is standing by the wall, smiling. + + Describe an action being taken. The pose text will + automatically begin with your name. + """ + key = "pose" + aliases = [":", "emote"] + locks = "cmd:all()" + arg_regex = None + energy_cost = 0 + def parse(self): + args = self.args + if args and not args[0] in ["'", ",", ":"]: + args = " %s" % args.strip() + self.args = args + def func(self): + if super().can_perform(): + if not self.args: + self.msg("What do you want to do?") + else: + msg = f"{self.caller.name}{self.args}" + super().handler().msg_all_rich((msg, {'type':'pose'}), self.caller) + +class SetEncounterSpecial(CmdSet): + def at_cmdset_creation(self): + self.add(CmdPass) + self.add(CmdRP) + self.add(CmdFlee) + self.add(CmdOOC) + self.add(CmdPose) diff --git a/commands/encounter_cmdset.py b/commands/encounter_cmdset.py deleted file mode 100644 index 7a94a12..0000000 --- a/commands/encounter_cmdset.py +++ /dev/null @@ -1,209 +0,0 @@ -from commands.command import Command -from evennia import create_script -from evennia import CmdSet - -from evennia.utils import inherits_from -import typeclasses.characters - -class EncounterCommand(Command): - energy_cost = 1 - allow_self_target = False - - def handler(self): - return self.caller.ndb.encounter_handler - - def can_perform(self): - # Returns whether the caller is having their turn and if they have enough energy - # to make this action - return self.handler().can_act(self) - - def has_target(self): - # Targeting code: - # Looks for the suggested target - # If none is found but there is only one other character in the encounter, - # default to that other character - # Else ask player for clarification - if self.target: - self.target = self.caller.search(self.target) - if not self.target: - default_target = self.handler().has_default_target(self.caller) - if default_target: - self.caller.msg("Defaulting to other character in encounter") - self.target = default_target - else: - self.caller.msg(f"Who are you trying to {self.key}?") - self.target = None - else: - default_target = self.handler().has_default_target(self.caller) - if default_target: - self.target = default_target - else: - self.caller.msg(f"Who are you trying to {self.key}?") - self.target = None - if self.caller == self.target and not self.allow_self_target: - self.msg(f"You aren't supposed to {self.key} yourself!") - return self.target - - -# Bite (Regular) -class CmdBite(EncounterCommand): - "Bite down on your target with your teeth" - key = "bite" - help_category = "Violence" - - def parse(self): - self.args = self.args.strip() - target, *adverb = self.args.split(":") - self.target = target.strip() - self.adverb = ' ' + adverb[0].strip() if adverb else '' - - def func(self): - if super().has_target() and super().can_perform(): - self.caller.msg(f"You bite {self.target.key}{self.adverb}") - self.target.msg(f"{self.caller.key} bites you{self.adverb}") - # damage calculations, chance to miss, etc - -# Kiss (Regular) -class CmdKiss(EncounterCommand): - "Kiss the target with your lips" - key = "kiss" - help_category = "Sex" - - def parse(self): - self.args = self.args.strip() - target, *adverb = self.args.split(':') - self.target = target.strip() - self.adverb = ' ' + adverb[0].strip() if adverb else '' - - def func(self): - if super().has_target() and super().can_perform(): - self.caller.msg(f"You kiss {self.target}{self.adverb}") - self.target.msg(f"{self.caller} kisses you{self.adverb}") - -class SetSpeciesHuman(CmdSet): - def at_cmdset_creation(self): - self.add(CmdBite) - self.add(CmdKiss) - -# Special encounter commands - -class CmdPass(EncounterCommand): - "Pass the turn over to the next character" - energy_cost = 0 - key = "pass" - aliases = ["next", "finish", "done"] - help_category = "Encounter" - - def func(self): - if super().can_perform(): - self.caller.msg("You end your turn") - super().handler().next_turn() - -class CmdRP(EncounterCommand): - "Free-form text input (for describing your actions in RP)" - energy_cost = 0 - key = "rp" - arg_regex = None - aliases = [">"] - help_category = "Encounter" - - def func(self): - if super().can_perform(): - super().handler().msg_all(self.args.strip()) - -class CmdFlee(EncounterCommand): - "Exits the current encounter" - energy_cost = 0 - key = "flee" - aliases = ["escape", "run", "run away", "leave"] - help_category = "Encounter" - - def func(self): - super().handler().msg_all(f"{self.caller.key} left the encounter") - super().handler().remove_character(self.caller) - -class CmdOOC(EncounterCommand): - "Say something out-of-character" - energy_cost = 0 - key = "(" - arg_regex = None - - def func(self): - super().handler().msg_all(f"({self.caller}: {self.args.strip()})") - -class CmdPose(EncounterCommand): - """ - strike a pose - - Usage: - pose - pose's - - Example: - pose is standing by the wall, smiling. - -> others will see: - Tom is standing by the wall, smiling. - - Describe an action being taken. The pose text will - automatically begin with your name. - """ - key = "pose" - aliases = [":", "emote"] - locks = "cmd:all()" - arg_regex = None - energy_cost = 0 - def parse(self): - args = self.args - if args and not args[0] in ["'", ",", ":"]: - args = " %s" % args.strip() - self.args = args - def func(self): - if super().can_perform(): - if not self.args: - self.msg("What do you want to do?") - else: - msg = f"{self.caller.name}{self.args}" - super().handler().msg_all_rich((msg, {'type':'pose'}), self.caller) - -class SetEncounterSpecial(CmdSet): - def at_cmdset_creation(self): - self.add(CmdPass) - self.add(CmdRP) - self.add(CmdFlee) - self.add(CmdOOC) - self.add(CmdPose) - -# Encounter-related character commands - -class CmdEngage(Command): - """ - Initiates an encounter with the selected target - """ - key = "engage" - aliases = ["encounter", "fight"] - def func(self): - if not self.args: - self.caller.msg("Usage: engage ") - return - target = self.caller.search(self.args) - if not target: - return - if not inherits_from(target, typeclasses.characters.Character) or not target.access(self.caller, 'engage'): - self.caller.msg(target.db.engage_err_msg or f"You can't initiate an encounter with {target.name}.") - return - if target == self.caller: - self.caller.msg("You can't initiate an encounter with yourself!") - return - if target.ndb.encounter_handler: - target.ndb.encounter_handler.add_character(self.caller) - target.ndb.encounter_handler.msg_all(f"{self.caller} joins the encounter") - else: - handler = create_script("encounter_handler.EncounterHandler") - handler.add_character(self.caller) - handler.add_character(target) - target.msg(f"{self.caller} has engaged you in an encounter!") - target.msg("You may leave using the flee command (or aliases)") - self.caller.msg(f"You have entered an encounter with {target}. Be polite!") - self.caller.msg("It is now your turn:") - - diff --git a/typeclasses/characters.py b/typeclasses/characters.py index afec07c..556018a 100644 --- a/typeclasses/characters.py +++ b/typeclasses/characters.py @@ -2,7 +2,7 @@ from evennia.contrib.game_systems.clothing import ClothedCharacter from evennia.contrib.rpg.traits import TraitHandler -from commands.encounter_cmdset import SetEncounterSpecial +from commands.encounter.special import SetEncounterSpecial from world.species import SPECIES_CMDSET CURRENT_VERSION = 1 diff --git a/world/species.py b/world/species.py index 643f242..7a12158 100644 --- a/world/species.py +++ b/world/species.py @@ -1,4 +1,4 @@ -from commands.encounter_cmdset import SetSpeciesHuman +from commands.encounter.sets import SetSpeciesHuman SPECIES_LIST = [ "Human",