Beispiel #1
0
 def do_action(self, game: Game, params: list[str], message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author), game.discord_users)
     player = discord_user.current_character
     player.zone = "Town"
     player.current_room = game.town.entry_room
     return "You leave the maze.\n" + player.current_room.describe(game)
Beispiel #2
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     to_return = "\n".join([
         f"{player.name}",
         f"HP: {player.display_health}/{player.max_health}",
         f"PP: {player.display_stamina}/{player.max_stamina}",
         f"MP {player.display_mana}/{player.max_mana}"
     ])
     if get_by_index(params, 0, "").lower() == "stats":
         to_return = to_return + "\n"
         to_return = to_return + "Attack Bonuses:\n"
         to_return = to_return + f"  Hit: {player.hit_bonus}\n"
         to_return = to_return + f"  Dmg: {player.dmg_bonus}\n"
         player_resistances = player.resistances
         if len(player_resistances["hit"].keys()) > 0:
             to_return = to_return + "Hit Resistances:\n"
             for k, v in player_resistances["hit"].items():
                 to_return = to_return + f"  {k.capitalize()}: {v}\n"
         if len(player_resistances["dmg"].keys()) > 0:
             to_return = to_return + "Damage Resistances:\n"
             for k, v in player_resistances["dmg"].items():
                 to_return = to_return + f"  {k.capitalize()}: {v}\n"
     return to_return
Beispiel #3
0
 def do_noncombat(self, game: Game, params: list[str],
                  message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     from utils.Constanats import Triggers
     source_player = UserUtils.get_character_by_username(
         str(message.author), game.discord_users)
     room = source_player.current_room
     direction = get_by_index(params, 0)
     if direction is None:
         return f"No direciton specified. Proper usage of this command is:\n {Exit.show_help()}"
     door = room.get_door(direction.lower())
     if door is None:
         return f"Invalid direction. Room has no {direction} exit."
     old_room = source_player.current_room
     game.trigger(Triggers.BeforeLeaveRoom,
                  source_player=source_player,
                  source_entity=source_player,
                  room=old_room)
     game.trigger(Triggers.BeforeEnterRoom,
                  source_player=source_player,
                  source_entity=source_player,
                  room=door)
     source_player.current_room = door
     game.trigger(Triggers.LeaveRoom,
                  source_player=source_player,
                  source_entity=source_player,
                  room=old_room)
     game.trigger(Triggers.EnterRoom,
                  source_player=source_player,
                  source_entity=source_player,
                  room=source_player.current_room)
     return source_player.current_room.describe(game)
Beispiel #4
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     from utils.Constanats import EquipmentSlots
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     player.inventory.consolidate_items()
     player.inventory.sort_items()
     to_return = ""
     if len(player.inventory.equipment.values()) > 0:
         to_return = to_return + "Equipment:\n"
     for k, v in player.inventory.equipment.items():
         if v is not None and k != EquipmentSlots.Belt:
             to_return = to_return + k.capitalize() + ": " + v.name + "\n"
         if k == EquipmentSlots.Belt and len(v) > 0:
             to_return = to_return + "Belt:"
             for item_stack in player.inventory.equipment[
                     EquipmentSlots.Belt]:
                 to_return = to_return + f"\n{item_stack.quantity}x {item_stack.name}"
     if len(player.inventory.bag) > 0:
         to_return = to_return + "\nBag:"
     for item_stack in player.inventory.bag:
         to_return = to_return + f"\n{item_stack.quantity}x {item_stack.name}"
     return to_return
Beispiel #5
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     return player.current_room.describe(game)
Beispiel #6
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     room = player.current_room
     object_name = get_by_index(params, 0, None)
     if object_name is None:
         return "No object specified to loot. Usage is:\n" + LootCommand.show_help(
         )
     matched_object = next((fixture for fixture in room.fixtures
                            if fixture.name.lower() == object_name.lower()
                            and hasattr(fixture, "items")), None)
     if matched_object is None:
         return f"Lootable object {object_name} not found."
     looted_items = matched_object.items
     matched_object.items = []
     if len(looted_items) == 0:
         return f"{object_name.capitalize()} was empty."
     player.inventory.bag = player.inventory.bag + looted_items
     text_described_items = [
         f"{x.quantity}x {x.name}" for x in looted_items
     ]
     return f"Picked up {enumerate_objects(text_described_items)}"
Beispiel #7
0
 def do_noncombat(self, game: Game, params: list[str],
                  message: discord.Message) -> str:
     # look for matched item in belt then bag, calling use_effect on it
     # TODO Check if item quantity is greater than 0 before using
     # TODO check if item quantity is less than 0 after
     from discord_objects.DiscordUser import UserUtils
     from utils.ListHelpers import get_by_index
     from utils.Constanats import EquipmentSlots
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     item_name = get_by_index(params, 0, None)
     if item_name is None:
         return "Item name not specified. Usage is:\n" + UseItem.show_help()
     matched_item = player.inventory.get_belt_item_by_name(item_name)
     source_container = "belt"
     if matched_item is None:
         matched_item = player.inventory.get_bag_item_by_name(item_name)
         source_container = "bag"
     if matched_item is None:
         return f"{item_name} was not found on belt or in bags"
     matched_item.use_effect(game, player, params[1:])
     matched_item.quantity = matched_item.quantity - 1
     if matched_item.quantity == 0:
         if source_container == "belt":
             player.inventory.equipment[EquipmentSlots.Belt].remove(
                 matched_item)
         elif source_container == "bag":
             player.inventory.bag.remove(matched_item)
     return f"{item_name} used"
Beispiel #8
0
 def do_noncombat(self, game: Game, params: list[str],
                  message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     room = player.current_room
     items = room.items
     target_item_name = get_by_index(params, 0, None)
     if (target_item_name is None) or (target_item_name.lower() == "all"):
         if len(items) == 0:
             return "Nothing to pick up."
         pickup_strings = []
         for item in items:
             player.inventory.add_item_to_bag(item)
             pickup_strings.append(f"Picked up {item.quantity} {item.name}")
         room.items = []
         return "\n".join(pickup_strings)
     else:
         matched_item = next(
             (x
              for x in items if x.name.lower() == target_item_name.lower()),
             None)
         # matched_item = next(filter(lambda x: x.name.lower() == target_item_name.lower(), items), None)
         if matched_item is None:
             return "Item not found"
         player.inventory.add_item_to_bag(matched_item)
         room.items.remove(matched_item)
         return f"Picked up {matched_item.quantity} {matched_item.name}"
Beispiel #9
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     if discord_user.is_admin:
         return game.maze.admin_map(game)
     return "You are not an admin!"
Beispiel #10
0
 def do_action(self, game: Game, params: list[str], message: discord.Message) -> Optional[str]:
     from discord_objects.DiscordUser import UserUtils
     player = UserUtils.get_character_by_username(str(message.author), game.discord_users)
     current_room = player.current_room
     conversations = current_room.conversations
     my_conversation = next((conversation for conversation in conversations if conversation.character == player), None)
     if my_conversation is None:
         raise Exception(f"Conversation is none")
     my_conversation.handle_response(game, params[0])
Beispiel #11
0
    async def on_ready(self) -> None:
        print(f'{self.user} has connected to Discord!')
        print('Collecting users')
        guild = self.guilds[0]
        async for member in guild.fetch_members():
            if UserUtils.get_user_by_username(str(member), self.game.discord_users) is None:
                self.game.discord_users.append(DiscordUser(username=str(member), discord_obj=member))
        print(f'Users collected. Added {len(self.game.discord_users)} users.')
        UserUtils.print_all(self.game.discord_users)

        guild = self.guilds[0]
        text_channels = guild.text_channels
        if CHANNEL is None:
            self.game_channel = next(filter(lambda channel: channel.name == "muddle-game", text_channels), None)
        else:
            self.game_channel = next(filter(lambda channel: channel.name == CHANNEL, text_channels), None)
        await self.send_game_chat("Server started.")
        if len(self.game.players) == 0:
            self.game.load_players()
Beispiel #12
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     if discord_user is None:
         return "You are not listed as a user in this game."
     commands = discord_user.get_commands(game)
     command_aliases = [x.default_alias() for x in commands]
     command_aliases.sort()
     return "Your commands are:\n{}".format("\n".join(command_aliases))
Beispiel #13
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     slot = get_by_index(params, 0)
     worked, response = player.inventory.unequip_item(slot)
     if worked:
         return f"Unequipped item from {slot}"
     else:
         return response
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     target_player = UserUtils.get_character_by_username(
         str(message.author), game.discord_users)
     if target_player is None:
         return "You don't currently have a character. Use the !NewCharacter command to create one."
     room = target_player.current_room
     if room.combat is None:
         return self.do_noncombat(game, params, message)
     else:
         return self.enqueue_order(game, target_player, params)
Beispiel #15
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     if len(params) == 0:
         return ShowHelp.show_help()
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     if discord_user is None:
         return "You are not listed as a user in this game."
     supplied_alias = get_by_index(params, 0).lower()
     for command in discord_user.get_commands(game):
         lower_aliases = [x.lower() for x in command.aliases]
         if supplied_alias in lower_aliases:
             return command.show_help()
Beispiel #16
0
    def do_action(self, game: Game, params: list[str],
                  message: discord.Message) -> str:
        from discord_objects.DiscordUser import UserUtils
        from utils.ListHelpers import get_by_index
        from utils.Constanats import DamageTypes

        discord_user = UserUtils.get_user_by_username(str(message.author),
                                                      game.discord_users)
        enemy_name = get_by_index(params, 0, None)
        if enemy_name is None:
            return "No enemy specified. Usage is:\n" + SizeUpCommand.show_help(
            )
        player = discord_user.current_character
        room = player.current_room
        from utils.CommandHelpers import match_enemy, match_player
        enemies = [x for x in game.enemies if x.current_room == room]
        target = None
        match_enemy_result = match_enemy(enemies, params)
        if match_enemy_result is not None:
            target = match_enemy_result
        if target is None:
            return "Specified enemy not found."
        else:
            # list max health
            # for each damage type in damage-types
            # list hit resistance and damage resistance
            # grid with spacing of 15, left aligned, right pad to length of 15
            max_health = target.max_health
            hit_resistances = sum_resistances(target.natural_armor["hit"],
                                              target.armor_bonus["hit"])
            dmg_resistances = sum_resistances(target.natural_armor["dmg"],
                                              target.armor_bonus["dmg"])
            resp_strings = [
                f"You quickly thumb through your copy of Ogres and Oubliettes: A Field Guide and find the entry for {target.name}",
                f"Health: {max_health}", "Type".ljust(15) +
                "Hit Resist".ljust(15) + "Dmg Resist".ljust(15)
            ]
            for type in [
                    "slash", "pierce", "bludgeon", "electricity", "fire", "ice"
            ]:
                resp_strings.append(
                    type.capitalize().ljust(15) +
                    f"{hit_resistances.get(type,0 )}".ljust(15) +
                    f"{dmg_resistances.get(type,0)}".ljust(15))

            return resp_strings[0] + "```" + "\n".join(
                resp_strings[1:]) + "```"
Beispiel #17
0
    async def on_message(self, message: discord.Message) -> None:
        user = self.user
        author = message.author
        content = message.content
        channel = message.channel

        if author == user:  # ignore own messages
            return

        if channel != self.game_channel:
            return

        # Collect user if not in users
        discord_user = UserUtils.get_user_by_username(str(author), self.game.discord_users)
        if discord_user is None:
            print("New user found. Adding...")
            discord_user = DiscordUser(username=str(author), discord_obj=author)
            self.game.discord_user.append(discord_user)

        if not content.startswith("!"):
            return

        command_list = discord_user.get_commands(self.game)

        matches = re.match(r"^!(\w+)((?:\s\w+)+)?$", message.content)
        command = matches.group(1)
        param_match = matches.group(2)
        params = []
        if param_match:
            params = [m.group(0) for m in re.finditer(r'\w+', param_match)]

        matched_command = None
        for possible_command in command_list:
            lower_aliases = [x.lower() for x in possible_command.aliases]
            if command.lower() in lower_aliases:
                matched_command = possible_command

        if matched_command is not None:
            resp = matched_command.do_action(self.game, params, message)
            # print(f"Matched {command} to {matched_command.aliases[0]}")
            if resp is not None:
                await self.send_game_chat(resp, tagged_users=[discord_user])
            return

        if command.lower() == "get" and params[0].lower() == "ye" and params[1].lower() == "flask":
            await channel.send("You can't get ye flask")
Beispiel #18
0
 def do_action(self, game: 'Game', params: list[str],
               message: discord.Message) -> str:
     from game_objects.Character.Character import Character
     from discord_objects.DiscordUser import UserUtils, DiscordUser
     new_player = Character()
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     if discord_user is None:
         discord_user = DiscordUser(username=str(message.author),
                                    current_character=new_player,
                                    discord_obj=message.author)
     else:
         discord_user.current_character = new_player
     game.register_player(new_player)
     game.discord_users = game.discord_users + [discord_user]
     new_player.discord_user = discord_user
     return f"New character {new_player.name} created for {message.author}"
Beispiel #19
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     user = UserUtils.get_user_by_username(str(message.author),
                                           game.discord_users)
     character = user.current_character
     room = character.current_room
     combat = room.combat
     accepted = combat.accept_player_order(game, character,
                                           self.do_combat_action, params,
                                           self.combat_action_cost,
                                           self.command_valid)
     if accepted:
         action_count = combat.sum_actions_for_entity(character)
         remaining_actions = character.actions - action_count
         return "Order Accepted." + (
             f"You have {remaining_actions} action points remaining."
             if 0 < remaining_actions < character.actions else "")
Beispiel #20
0
 def do_noncombat(self, game: Game, params: list[str],
                  message: discord.Message):
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     target_spell = get_by_index(params, 0)
     if target_spell is None:
         return Cast.show_help()
     # attempt to match from known spells
     # if spellbook in mainhand or offhand
     #   attempt to match from spellbook
     # if spell can be used out of combat
     #   get target type from spell
     #   attempt to match from target types in room
     #   if all targets valid
     #       do it
     return "Not Implemented"
Beispiel #21
0
 def from_dict(cls, game, source_dict) -> Character:
     from discord_objects.DiscordUser import UserUtils
     from game_objects.Character.CharacterInventory import CharacterInventory
     from game_objects.Character.CharacterSkills import CharacterSkills
     new_char = Character(name=source_dict["name"])
     #  new_char.zone = source_dict["zone"]
     new_char.skills = CharacterSkills.from_dict(source_dict["skills"], new_char)
     new_char.inventory = CharacterInventory.from_dict(source_dict["inventory"])
     new_char.discord_user = UserUtils.get_user_by_username(source_dict["discord_user"], game.discord_users)
     new_char.health = source_dict["health"]
     new_char.max_health = source_dict["max_health"]
     new_char.stamina = source_dict["stamina"]
     new_char.max_stamina = source_dict["max_stamina"]
     new_char.mana = source_dict["mana"]
     new_char.max_mana = source_dict["max_mana"]
     new_char.base_actions = source_dict["base_actions"]
     new_char.base_resistances = source_dict["base_resistances"]
     return new_char
Beispiel #22
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     player = UserUtils.get_character_by_username(str(message.author),
                                                  game.discord_users)
     current_room = player.current_room
     players = current_room.get_characters(game)
     player_name = get_by_index(params, 0, None)
     if player_name is None and len(players) == 2:
         chosen_player = players[0] if players[0] != player else players[1]
     elif player_name is None and len(players) >= 2:
         return "You're left hanging."
     else:
         chosen_player = next((x for x in players if x.name.replace(
             " ", "").lower() == player_name.replace(" ", "").lower()),
                              None)
     if chosen_player is None:
         return "Named person was not found"
     return f"You give an epic high five to {chosen_player.name}"
Beispiel #23
0
 def do_action(self, game: Game, params: list[str],
               message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     item_name = get_by_index(params, 0, None)
     if item_name is None:
         return "Item name not specified. Usage is:\n" + Equip.show_help()
     slot = get_by_index(params, 1, None)
     if slot is None:
         return "Slot not specified. Usage is:\n" + Equip.show_help()
     matched_item = player.inventory.get_bag_item_by_name(item_name)
     if matched_item is None:
         return "Item not found"
     success, err_reason = player.inventory.equip_item(matched_item, slot)
     if success:
         return "Item equipped"
     return err_reason
Beispiel #24
0
 def do_action(self, game: Game, params: list[str], message: discord.Message) -> str:
     from discord_objects.DiscordUser import UserUtils
     from game_objects.Conversation import Conversation
     player = UserUtils.get_character_by_username(str(message.author), game.discord_users)
     current_room = player.current_room
     npcs = current_room.get_npcs(game)
     npc_name = get_by_index(params, 0, None)
     if npc_name is None and len(npcs) == 1:
         chosen_npc = npcs[0]
     else:
         chosen_npc = next((npc for npc in npcs if npc.name == npc_name), None)
     if chosen_npc is None:
         return "Named person was not found"
     new_conversation = Conversation()
     new_conversation.npc = chosen_npc
     new_conversation.character = player
     new_conversation.room = current_room
     current_room.conversations.append(new_conversation)
     new_conversation.init_conversation(game, chosen_npc.dialog_tree)
Beispiel #25
0
 def do_noncombat(self, game: Game, params: list[str],
                  message: discord.Message):
     from discord_objects.DiscordUser import UserUtils
     discord_user = UserUtils.get_user_by_username(str(message.author),
                                                   game.discord_users)
     player = discord_user.current_character
     target_item = get_by_index(params, 0)
     if target_item is None:
         return Drop.show_help()
     room = player.current_room
     player_bag = player.inventory.bag
     matched_item = player.inventory.get_bag_item_by_name(target_item)
     if matched_item is None:
         return "Item not found"
     quantity = int(get_by_index(params, 1, "1"))
     quantity = max(quantity, matched_item.quantity)
     if quantity >= matched_item.quantity:
         room.items.append(matched_item)
         player_bag.remove(matched_item)
     else:
         dropped_items = matched_item.take_count_from_stack(quantity)
         room.items.append(dropped_items)
     return f"Dropped {quantity} {matched_item.name}"
Beispiel #26
0
    def do_action(self, game: Game, params: list[str],
                  message: discord.Message) -> str:
        from discord_objects.DiscordUser import UserUtils
        from utils.ListHelpers import get_by_index
        from utils.Constanats import DamageTypes

        discord_user = UserUtils.get_user_by_username(str(message.author),
                                                      game.discord_users)
        player = discord_user.current_character
        enemies = player.current_room.combat.enemies
        target = None
        if len(params) > 0:
            from utils.CommandHelpers import match_enemy
            match_enemy_result = match_enemy(enemies, params)
            if match_enemy_result is not None:
                target = match_enemy_result
            if target is None:
                return "Specified enemy not found."
        elif len(enemies) == 1:
            target = enemies[0]
        if target is None:
            return "No enemy specified. Usage is:\n" + SizeUpCommand.show_help(
            )
        else:
            resistances = target.resistances
            hit_resistances = resistances["hit"]
            dmg_resistances = resistances["dmg"]
            min_hit_resistance = min([
                hit_resistances.get(DamageTypes.Slash, 0),
                hit_resistances.get(DamageTypes.Pierce, 0),
                hit_resistances.get(DamageTypes.Bludgeon, 0)
            ])
            min_dmg_resistance = min([
                dmg_resistances.get(DamageTypes.Slash, 0),
                dmg_resistances.get(DamageTypes.Pierce, 0),
                dmg_resistances.get(DamageTypes.Bludgeon, 0)
            ])
            relevant_types = [
                DamageTypes.Slash, DamageTypes.Pierce, DamageTypes.Bludgeon
            ]
            lowest_hit_resistance = random.choice([
                x for x in relevant_types
                if hit_resistances.get(x, 0) == min_hit_resistance
            ])
            lowest_dmg_resistance = random.choice([
                x for x in relevant_types
                if dmg_resistances.get(x, 0) == min_dmg_resistance
            ])
            damage_percent_index = (target.health *
                                    100) // target.max_health // 20
            health_percentile_strings = {
                0: "It's barely clinging to life.",
                1: "It's badly hurt.",
                2: "It has taken quite a few hits and seems weakened.",
                3:
                "It's taken a few hits, but it seems to still have plenty of strength.",
                4: "It seems mostly unhurt.",
                5: "It's completely unharmed."
            }
            best_hit_strings = {
                DamageTypes.Bludgeon:
                "It looks like it might be easiest to hit with a bludgeoning weapon.",
                DamageTypes.Slash:
                "It looks like it might be easiest to hit with a slashing weapon.",
                DamageTypes.Pierce:
                "It looks like it might be easiest to hit with a piercing weapon."
            }
            best_dmg_strings = {
                DamageTypes.Bludgeon:
                "It looks like it might be weak to bludgeoning damage.",
                DamageTypes.Slash:
                "It looks like it might be weak to slashing damage.",
                DamageTypes.Pierce:
                "It looks like it might be weak to piercing damage."
            }
            resp_strings = [
                f"You eye {target.combat_name} closely.",
                health_percentile_strings[damage_percent_index],
                best_hit_strings[lowest_hit_resistance],
                best_dmg_strings[lowest_dmg_resistance]
            ]
            return "\n".join(resp_strings)