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)
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
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)
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
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)
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)}"
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"
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}"
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!"
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])
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()
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))
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)
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()
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:]) + "```"
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")
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}"
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 "")
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"
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
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}"
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
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)
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}"
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)