def handle_loot(character: Character, monster: Monster): """ Display the loot dropped from the monster and listen for input if the player wants to take any""" print_loot_table(monster.loot) while True: command = input() if command == 'take all': # takes everything gold = monster.give_loot('gold') if gold: # if it's successful character.award_gold(gold) print(f'{character.name} has looted {gold} gold.') monster_loot = list( monster.loot.keys()) # list of strings, the item's names for item_name in monster_loot: # loop through them and get every one item: 'Item' = monster.give_loot(item_name=item_name) if item: # if the loot is successful character.award_item(item=item) print(f'{character.name} has looted {item_name}.') elif "take" in command: item_name = command[5:] if item_name == "gold": gold = monster.give_loot("gold") if gold: # if it's successful character.award_gold(gold) print(f'{character.name} has looted {gold} gold.') else: # if we want to take an item item = monster.give_loot(item_name=item_name) if item: # if the loot is successful character.award_item(item=item) print(f'{character.name} has looted {item_name}.') elif command == "?": pac_looting() elif command == "exit": # end the looting process print('-' * 40) break else: print("Invalid command.") if not monster.loot: # if the loot is empty, exit the loot window print('-' * 40) break print_loot_table( monster.loot ) # print the updated table each time we take something
def handle_loot(character: Character, monster: Monster): """ Display the loot dropped from the monster and listen for input if the player wants to take any""" print_loot_table(monster.loot) while True: command = input() if command == 'take all': # takes everything gold = monster.give_loot('gold') if gold: # if it's successful character.award_gold(gold) print(f'{character.name} has looted {gold} gold.') monster_loot = list(monster.loot.keys()) # list of strings, the item's names for item_name in monster_loot: # loop through them and get every one item: 'Item' = monster.give_loot(item_name=item_name) if item: # if the loot is successful character.award_item(item=item) print(f'{character.name} has looted {item_name}.') elif "take" in command: item_name = command[5:] if item_name == "gold": gold = monster.give_loot("gold") if gold: # if it's successful character.award_gold(gold) print(f'{character.name} has looted {gold} gold.') else: # if we want to take an item item = monster.give_loot(item_name=item_name) if item: # if the loot is successful character.award_item(item=item) print(f'{character.name} has looted {item_name}.') elif command == "?": pac_looting() elif command == "exit": # end the looting process print('-' * 40) break else: print("Invalid command.") if not monster.loot: # if the loot is empty, exit the loot window print('-' * 40) break print_loot_table(monster.loot) # print the updated table each time we take something
def attack(self, victim: Monster): attacker_swing: (Damage, int) = self.get_auto_attack_damage(victim.level) auto_attack: Damage = attacker_swing[0] # type: Damage # the sor_damage below is used just to check for printing sor_damage: int = attacker_swing[1] # if the seal isn't active the damage will be 0 auto_attack_print = victim.get_take_attack_damage_repr(auto_attack, self.level) if sor_damage: print(f'{self.name} attacks {victim.name} for {auto_attack_print} from {self.KEY_SEAL_OF_RIGHTEOUSNESS}!') else: print(f'{self.name} attacks {victim.name} for {auto_attack_print}!') victim.take_attack(auto_attack, self.level)
def spell_melting_strike(self, spell: PaladinSpell, target: Monster): """ Damages the enemy for DAMAGE_1 damage and puts a DoT effect, the index of which is EFFECT :return successful cast or not""" mana_cost: int = spell.mana_cost damage: Damage = Damage(phys_dmg=spell.damage1) dot: 'DoT' = spell.harmful_effect dot.update_caster_level(self.level) self.mana -= mana_cost # damage the target and add the DoT print(f'{spell.name} damages {target.name} for {damage}!') target.take_attack(damage, self.level) target.add_buff(dot) return True
def convert_to_living_thing_object(self) -> VendorNPC or FriendlyNPC or Monster: """ Converts the Creature to whatever object he is according to his type column """ # TODO: move to creature_template.py entry: int = self.creature_id name: str = self.creature.name type_: str = self.creature.type level: int = parse_int(self.creature.level) health: int = parse_int(self.creature.health) mana: int = parse_int(self.creature.mana) armor: int = parse_int(self.creature.armor) min_dmg: int = parse_int(self.creature.min_dmg) max_dmg: int = parse_int(self.creature.max_dmg) quest_relation_id: int = parse_int(self.creature.quest_relation_id) loot_table: 'LootTable' = self.creature.loot_table gossip: str = self.creature.gossip respawnable: bool = self.creature.respawnable if type_ == "fnpc": return FriendlyNPC(name=name, health=health, mana=mana, level=level, min_damage=min_dmg, max_damage=max_dmg, quest_relation_id=quest_relation_id, loot_table=loot_table, gossip=gossip) elif type_ == "vendor": vendor_inventory = self.creature.build_vendor_inventory() return VendorNPC(name=name, entry=entry, health=health, mana=mana, level=level, min_damage=min_dmg, max_damage=max_dmg, quest_relation_id=quest_relation_id, loot_table=loot_table, inventory=vendor_inventory, gossip=gossip) elif type_ == "monster": gold_to_give_range = (CREATURE_DEFAULT_VALUES[level]['min_gold_reward'], CREATURE_DEFAULT_VALUES[level]['max_gold_reward']) xp_to_give = CREATURE_DEFAULT_VALUES[level]['xp_reward'] armor = armor if armor else CREATURE_DEFAULT_VALUES[level]['armor'] return Monster(monster_id=entry, name=name, health=health, mana=mana, armor=armor, level=level, min_damage=min_dmg, max_damage=max_dmg, quest_relation_id=quest_relation_id, loot_table=loot_table, xp_to_give=xp_to_give, gold_to_give_range=gold_to_give_range, gossip=gossip, respawnable=respawnable) else: raise Exception(f'{type_} is not a valid creature type!')
def attack(self, victim: Monster): attacker_swing: (Damage, int) = self.get_auto_attack_damage(victim.level) auto_attack: Damage = attacker_swing[0] # type: Damage # the sor_damage below is used just to check for printing sor_damage: int = attacker_swing[ 1] # if the seal isn't active the damage will be 0 auto_attack_print = victim.get_take_attack_damage_repr( auto_attack, self.level) if sor_damage: print( f'{self.name} attacks {victim.name} for {auto_attack_print} from {self.KEY_SEAL_OF_RIGHTEOUSNESS}!' ) else: print( f'{self.name} attacks {victim.name} for {auto_attack_print}!') victim.take_attack(auto_attack, self.level)
def setUp(self): """ Test loading three different types of monsters - vendor, fnpc, monster """ self.monster_entry = 16 self.monster_guid = 15 self.monster_type = 'monster' self.monster_zone = 'Northshire Abbey' self.monster_subzone = 'A Peculiar Hut' self.monster_gold_range = range(5, 9) self.monster_respawnable = False self.monster = Monster(monster_id=self.monster_entry, name="Brother Paxton", health=25, mana=0, armor=80, level=3, min_damage=7, max_damage=10, quest_relation_id=0, xp_to_give=100, gold_to_give_range=(5, 8), loot_table=None, gossip="Nobody will foil our plans!")
def engage_combat(character: Character, monster: Monster, alive_monsters: dict, guid_name_set: set, monster_GUID: int): """ This is where we handle the turn based combat of the game available_spells - set of string commands that enable our character to use the spells he has available. First we get both parties to enter combat. We start the loop and have the monster attack and immediately check if the character is not dead from the blow. If not, we take his command and if said command is one that does not end the turn (ie. wants to print some information about the fight) we enter an inner loop handling such commands and which continues to take commands until it gets one that does end the turn. We handle the command (which is most likely a spell or auto attack) and check if the monster is dead. :param character: the player :param monster: the monster that the player has attacked Parameters below are used solely to delete the monster from the dict & set once he's dead :param alive_monsters: Dictionary with the alive monsters in the subzone the player is in :param guid_name_set: Set which holds the name of each monster_GUID :param monster_GUID: The monster GUID """ # Load all of the currently available spells for our character available_spells: set() = get_available_spells(character) will_end_turn = True # Dictates if we are going to count the iteration of the loop as a turn character.enter_combat() monster.enter_combat() if monster.gossip: # if the monster has gossip monster.say_gossip() sleep(2) while character.is_in_combat(): # We start off the combat with the monster dealing the first blow if not will_end_turn: # skip attack if the turn has not ended # skip turn based things will_end_turn = True else: monster.start_turn_update() character.start_turn_update() if monster.is_alive(): monster.attack(character) else: # monster has died, most probably from a DoT handle_monster_death(character, monster, alive_monsters, guid_name_set, monster_GUID) break if not character.is_alive(): monster.leave_combat() print(f'{monster.name} has slain character {character.name}') prompt_revive(character) break command = input() # check if the command does not end the turn, if it doesn't the same command gets returned command = route_in_combat_non_ending_turn_commands(command, character, monster) if command == 'attack': character.attack(monster) elif command in available_spells: # try to execute the spell and return if it managed to or not successful_cast = character.spell_handler(command, monster) if not successful_cast: # skip the next attack, don't count this iteration as a turn and load a command again will_end_turn = False if will_end_turn: monster.end_turn_update() character.end_turn_update() if not monster.is_alive(): handle_monster_death(character, monster, alive_monsters, guid_name_set, monster_GUID) break
def engage_combat(character: Character, monster: Monster, alive_monsters: dict, guid_name_set: set, monster_GUID: int): """ This is where we handle the turn based combat of the game available_spells - set of string commands that enable our character to use the spells he has available. First we get both parties to enter combat. We start the loop and have the monster attack and immediately check if the character is not dead from the blow. If not, we take his command and if said command is one that does not end the turn (ie. wants to print some information about the fight) we enter an inner loop handling such commands and which continues to take commands until it gets one that does end the turn. We handle the command (which is most likely a spell or auto attack) and check if the monster is dead. :param character: the player :param monster: the monster that the player has attacked Parameters below are used solely to delete the monster from the dict & set once he's dead :param alive_monsters: Dictionary with the alive monsters in the subzone the player is in :param guid_name_set: Set which holds the name of each monster_GUID :param monster_GUID: The monster GUID """ # Load all of the currently available spells for our character available_spells: set() = get_available_spells(character) will_end_turn = True # Dictates if we are going to count the iteration of the loop as a turn character.enter_combat() monster.enter_combat() if monster.gossip: # if the monster has gossip monster.say_gossip() sleep(2) while character.is_in_combat(): # We start off the combat with the monster dealing the first blow if not will_end_turn: # skip attack if the turn has not ended # skip turn based things will_end_turn = True else: monster.start_turn_update() character.start_turn_update() if monster.is_alive(): monster.attack(character) else: # monster has died, most probably from a DoT handle_monster_death(character, monster, alive_monsters, guid_name_set, monster_GUID) break if not character.is_alive(): monster.leave_combat() print(f'{monster.name} has slain character {character.name}') prompt_revive(character) break command = input() # check if the command does not end the turn, if it doesn't the same command gets returned command = route_in_combat_non_ending_turn_commands( command, character, monster) if command == 'attack': character.attack(monster) elif command in available_spells: # try to execute the spell and return if it managed to or not successful_cast = character.spell_handler(command, monster) if not successful_cast: # skip the next attack, don't count this iteration as a turn and load a command again will_end_turn = False if will_end_turn: monster.end_turn_update() character.end_turn_update() if not monster.is_alive(): handle_monster_death(character, monster, alive_monsters, guid_name_set, monster_GUID) break
def create_monster(self): MONSTER_MAX_HEALTH = 100 monster_name = 'potwór_'+str(uuid.uuid4())[0:8] return Monster(monster_name, MONSTER_MAX_HEALTH)