def register_warpstone_merchant_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_WARPSTONE_MERCHANT npc_type = NpcType.NEUTRAL_WARPSTONE_MERCHANT ui_icon_sprite = PortraitIconSprite.WARPSTONE_MERCHANT movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) introduction = "Hah! I managed to infuse the statues' teleporting powers into these stones. " \ "You can carry them with you and use them any time you want to return to this place!" dialog_options = [ buy_consumable_option(ConsumableType.WARP_STONE, 2), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_data = DialogData(ui_icon_sprite, introduction, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/manga_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 0 y = 0 indices_by_dir = { Direction.DOWN: [(x, y), (x + 1, y), (x + 2, y)], Direction.LEFT: [(x, y + 1), (x + 1, y + 1), (x + 2, y + 1)], Direction.RIGHT: [(x, y + 2), (x + 1, y + 2), (x + 2, y + 2)], Direction.UP: [(x, y + 3), (x + 1, y + 3), (x + 2, y + 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( ui_icon_sprite, 'resources/graphics/portrait_warpstone_merchant_npc.png')
def register_frog_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_FROG movement_speed = 0.03 register_npc_data(NPC_TYPE, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(NPC_TYPE, NpcMind) _register_dialog() sprite_sheet = SpriteSheet( "resources/graphics/characters_midona_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 y = 0 indices_by_dir = { Direction.DOWN: [(x, y), (x + 1, y), (x + 2, y)], Direction.LEFT: [(x, y + 1), (x + 1, y + 1), (x + 2, y + 1)], Direction.RIGHT: [(x, y + 2), (x + 1, y + 2), (x + 2, y + 2)], Direction.UP: [(x, y + 3), (x + 1, y + 3), (x + 2, y + 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-9, -18)) register_portrait_icon_sprite_path( UI_ICON_SPRITE, 'resources/graphics/portrait_frog_npc.png')
def register_ninja_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_NINJA movement_speed = 0.03 register_npc_data(NPC_TYPE, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(NPC_TYPE, NpcMind) _register_dialog() sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x, 0), (x + 1, 0), (x + 2, 0)], Direction.LEFT: [(x, 1), (x + 1, 1), (x + 2, 1)], Direction.RIGHT: [(x, 2), (x + 1, 2), (x + 2, 2)], Direction.UP: [(x, 3), (x + 1, 3), (x + 2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( PORTRAIT_ICON_SPRITE, 'resources/graphics/ninja_portrait.png')
def register_goblin_spearman_enemy(): size = ( 24, 24 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_GOBLIN_SPEARMAN npc_type = NpcType.GOBLIN_SPEARMAN movement_speed = 0.08 health = 21 exp_reward = 14 register_npc_data( npc_type, NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_3, SoundId.DEATH_GOBLIN)) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_2.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) sprite_sheet_x = 9 sprite_sheet_y = 0 indices_by_dir = { Direction.DOWN: [(sprite_sheet_x + i, sprite_sheet_y + 0) for i in range(3)], Direction.LEFT: [(sprite_sheet_x + i, sprite_sheet_y + 1) for i in range(3)], Direction.RIGHT: [(sprite_sheet_x + i, sprite_sheet_y + 2) for i in range(3)], Direction.UP: [(sprite_sheet_x + i, sprite_sheet_y + 3) for i in range(3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-12, -24))
def register_warrior_king_enemy(): size = ( 32, 32 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_WARRIOR_KING npc_type = NpcType.WARRIOR_KING movement_speed = 0.13 health = 240 exp_reward = 90 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.BOSS_WARRIOR_KING, SoundId.DEATH_BOSS, is_boss=True) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (54, 60) x = 9 indices_by_dir = { Direction.DOWN: [(x, 4), (x + 1, 4), (x + 2, 4)], Direction.LEFT: [(x, 5), (x + 1, 5), (x + 2, 5)], Direction.RIGHT: [(x, 6), (x + 1, 6), (x + 2, 6)], Direction.UP: [(x, 7), (x + 1, 7), (x + 2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-11, -23))
def register_ice_witch_enemy(): size = ( 32, 32 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_ICE_WITCH npc_type = NpcType.ICE_WITCH movement_speed = 0.07 health = 50 exp_reward = 40 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_6, SoundId.DEATH_ICE_WITCH) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_ice_witch.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) sheet_x = 0 indices_by_dir = { Direction.DOWN: [(sheet_x, 0), (sheet_x + 1, 0), (sheet_x + 2, 0), (sheet_x + 1, 0)], Direction.LEFT: [(sheet_x, 1), (sheet_x + 1, 1), (sheet_x + 2, 1), (sheet_x + 1, 1)], Direction.RIGHT: [(sheet_x, 2), (sheet_x + 1, 2), (sheet_x + 2, 2), (sheet_x + 1, 2)], Direction.UP: [(sheet_x, 3), (sheet_x + 1, 3), (sheet_x + 2, 3), (sheet_x + 1, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_buff_effect(SLOW_BUFF_TYPE, SlowedByIceWitch) register_buff_text(SLOW_BUFF_TYPE, "Frozen")
def register_goblin_warrior_enemy(): size = (32, 32) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_GOBLIN_WARRIOR npc_type = NpcType.GOBLIN_WARRIOR movement_speed = 0.09 health = 100 exp_reward = 50 loot_table = LootTable( [ LootGroup(2, [LootEntry.item(ItemType.FROG), LootEntry.consumable(ConsumableType.WARP_STONE)], 1), LootGroup(1, LOOT_ITEMS_3 + LOOT_ITEMS_4, 1), LootGroup(1, [LootEntry.money(2), LootEntry.money(3), LootEntry.money(5)], 0.7) ] ) npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, loot_table, SoundId.DEATH_BOSS, is_boss=True) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_2.png") original_sprite_size = (32, 32) scaled_sprite_size = (52, 52) sprite_sheet_x = 3 sprite_sheet_y = 4 indices_by_dir = { Direction.DOWN: [(sprite_sheet_x + i, sprite_sheet_y + 0) for i in range(3)], Direction.LEFT: [(sprite_sheet_x + i, sprite_sheet_y + 1) for i in range(3)], Direction.RIGHT: [(sprite_sheet_x + i, sprite_sheet_y + 2) for i in range(3)], Direction.UP: [(sprite_sheet_x + i, sprite_sheet_y + 3) for i in range(3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-10, -20))
def register_rat_2_enemy(): size = ( 40, 40 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_RAT_2 npc_type = NpcType.RAT_2 movement_speed = 0.08 health = 11 exp_reward = 8 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_2, SoundId.DEATH_RAT) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/gray_rat.png") original_sprite_size = (32, 32) scaled_sprite_size = (50, 50) indices_by_dir = { Direction.DOWN: [(0, 0), (1, 0), (2, 0)], Direction.LEFT: [(0, 1), (1, 1), (2, 1)], Direction.RIGHT: [(0, 2), (1, 2), (2, 2)], Direction.UP: [(0, 3), (1, 3), (2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-5, -5))
def register_zombie_enemy(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_ZOMBIE npc_type = NpcType.ZOMBIE movement_speed = 0.03 health = 15 exp_reward = 10 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_3, SoundId.DEATH_ZOMBIE) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_2.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) indices_by_dir = { Direction.DOWN: [(0, 0), (1, 0), (2, 0)], Direction.LEFT: [(0, 1), (1, 1), (2, 1)], Direction.RIGHT: [(0, 2), (1, 2), (2, 2)], Direction.UP: [(0, 3), (1, 3), (2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-9, -18))
def register_skeleton_mage_enemy(): size = ( 32, 32 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_SKELETON_MAGE npc_type = NpcType.SKELETON_MAGE movement_speed = 0.05 health = 50 exp_reward = 25 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_4, SoundId.DEATH_SKELETON_MAGE) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/monsters_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) sheet_x = 3 indices_by_dir = { Direction.DOWN: [(sheet_x, 0), (sheet_x + 1, 0), (sheet_x + 2, 0), (sheet_x + 1, 0)], Direction.LEFT: [(sheet_x, 1), (sheet_x + 1, 1), (sheet_x + 2, 1), (sheet_x + 1, 1)], Direction.RIGHT: [(sheet_x, 2), (sheet_x + 1, 2), (sheet_x + 2, 2), (sheet_x + 1, 2)], Direction.UP: [(sheet_x, 3), (sheet_x + 1, 3), (sheet_x + 2, 3), (sheet_x + 1, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_projectile_controller(PROJECTILE_TYPE, ProjectileController)
def register_sorcerer_npc(): size = (30, 30) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_SORCERER portrait_icon_sprite = PortraitIconSprite.SORCERER npc_type = NpcType.NEUTRAL_SORCERER movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) dialog_options = [ buy_consumable_option(ConsumableType.HEALTH, 5), buy_consumable_option(ConsumableType.MANA, 5), buy_consumable_option(ConsumableType.SPEED, 5), buy_consumable_option(ConsumableType.POWER, 10), DialogOptionData("\"Good bye\"", "cancel", None)] dialog_text_body = "Greetings. I am glad to see that you have made it this far! However, great danger lies ahead... " \ "Here, see if any of these potions are of interest to you." dialog_data = DialogData(portrait_icon_sprite, dialog_text_body, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 3 indices_by_dir = { Direction.DOWN: [(x, 4), (x + 1, 4), (x + 2, 4)], Direction.LEFT: [(x, 5), (x + 1, 5), (x + 2, 5)], Direction.RIGHT: [(x, 6), (x + 1, 6), (x + 2, 6)], Direction.UP: [(x, 7), (x + 1, 7), (x + 2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path(portrait_icon_sprite, 'resources/graphics/portrait_sorcerer_npc.png')
def register_mummy_enemy(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_MUMMY npc_type = NpcType.MUMMY movement_speed = 0.06 health = 20 health_regen = 2 exp_reward = 15 npc_data = NpcData.enemy(sprite, size, health, health_regen, movement_speed, exp_reward, LOOT_TABLE_3, SoundId.DEATH_ZOMBIE) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_2.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) indices_by_dir = { Direction.DOWN: [(6, 4), (7, 4), (8, 4)], Direction.LEFT: [(6, 5), (7, 5), (8, 5)], Direction.RIGHT: [(6, 6), (7, 6), (8, 6)], Direction.UP: [(6, 7), (7, 7), (8, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-9, -18))
def register_dwarf_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_DWARF npc_type = NpcType.NEUTRAL_DWARF movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) introduction = "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a deal!" dialog_options = [ sell_item_option( ItemType.GOLD_NUGGET, 20, "I'll give you good money for a nugget of pure gold!"), sell_item_option(ItemType.SAPHIRE, 30, "If you find a saphire I can make you real rich!"), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_data = DialogData(PortraitIconSprite.VIKING, introduction, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) indices_by_dir = { Direction.DOWN: [(0, 4), (1, 4), (2, 4)], Direction.LEFT: [(0, 5), (1, 5), (2, 5)], Direction.RIGHT: [(0, 6), (1, 6), (2, 6)], Direction.UP: [(0, 7), (1, 7), (2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( PortraitIconSprite.VIKING, 'resources/graphics/viking_portrait.png')
def register_dark_reaper_enemy(): size = ( 50, 50 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_DARK_REAPER npc_type = NpcType.DARK_REAPER movement_speed = 0.04 health = 80 loot = LootTableId.LEVEL_1 register_npc_data( npc_type, NpcData.enemy(sprite, size, health, 0, movement_speed, 40, loot)) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (50, 50) indices_by_dir = { Direction.DOWN: [(9, 0), (10, 0), (11, 0)], Direction.LEFT: [(9, 1), (10, 1), (11, 1)], Direction.RIGHT: [(9, 2), (10, 2), (11, 2)], Direction.UP: [(9, 3), (10, 3), (11, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (0, 0)) register_buff_effect(BUFF_TYPE_INVULN, Invuln)
def register_veteran_enemy(): size = ( 32, 32 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_VETERAN npc_type = NpcType.VETERAN movement_speed = 0.08 health = 60 exp_reward = 35 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LOOT_TABLE_4, SoundId.DEATH_HUMAN) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_veteran.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) sheet_x = 0 indices_by_dir = { Direction.DOWN: [(sheet_x, 0), (sheet_x + 1, 0), (sheet_x + 2, 0), (sheet_x + 1, 0)], Direction.LEFT: [(sheet_x, 1), (sheet_x + 1, 1), (sheet_x + 2, 1), (sheet_x + 1, 1)], Direction.RIGHT: [(sheet_x, 2), (sheet_x + 1, 2), (sheet_x + 2, 2), (sheet_x + 1, 2)], Direction.UP: [(sheet_x, 3), (sheet_x + 1, 3), (sheet_x + 2, 3), (sheet_x + 1, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16))
def register_warrior_king_enemy(): size = (32, 32) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_WARRIOR_KING npc_type = NpcType.WARRIOR_KING movement_speed = 0.13 health = 190 exp_reward = 75 loot_table = LootTable( [ LootGroup.single(LootEntry.consumable(ConsumableType.WARP_STONE), 1), LootGroup(1, LOOT_ITEMS_4, 1), LootGroup.single(LootEntry.item(ItemType.KEY), 1), ] ) npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, loot_table, SoundId.DEATH_BOSS) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (54, 60) x = 9 indices_by_dir = { Direction.DOWN: [(x, 4), (x + 1, 4), (x + 2, 4)], Direction.LEFT: [(x, 5), (x + 1, 5), (x + 2, 5)], Direction.RIGHT: [(x, 6), (x + 1, 6), (x + 2, 6)], Direction.UP: [(x, 7), (x + 1, 7), (x + 2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-11, -23))
def register_dwarf_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_DWARF npc_type = NpcType.NEUTRAL_DWARF movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) indices_by_dir = { Direction.DOWN: [(0, 4), (1, 4), (2, 4)], Direction.LEFT: [(0, 5), (1, 5), (2, 5)], Direction.RIGHT: [(0, 6), (1, 6), (2, 6)], Direction.UP: [(0, 7), (1, 7), (2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_quest_giver_dialog( npc_name="Gimli", npc_type=npc_type, icon_sprite=UI_ICON_SPRITE, icon_sprite_file_path='resources/graphics/viking_portrait.png', quest=Quest(QUEST_ID, "Corrupted orb", "Defeat the skeleton king and retrieve the magic orb."), quest_min_level=QUEST_MIN_LEVEL, quest_intro= "I've heard tales of a powerful skeleton mage that possesses a very rare magic orb. I think it's " "time that it finds itself a new owner!", boss_npc_type=NpcType.SKELETON_BOSS, quest_item_type=QUEST_ITEM_TYPE, custom_options=[ sell_item_option( plain_item_id(ItemType.GOLD_NUGGET), 20, "I'll give you good money for a nugget of pure gold!"), sell_item_option( plain_item_id(ItemType.SAPPHIRE), 30, "If you find a sapphire I can make you real rich!") ], dialog_before_quest= "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a " "deal!", dialog_give_quest= "Hello there. I'm always looking for treasure. If you find any, we might be able to strike a " "deal!", dialog_during_quest="Hey! Any luck with the orb?", dialog_after_completed="Hi old friend! Got any more good stuff?", reward_item_id=lambda _: random_item_two_affixes(5))
def register_basic_enemy(npc_type: NpcType, npc_data: NpcData, mind_constructor: Type[AbstractNpcMind], spritesheet_path: str, original_sprite_size: Tuple[int, int], scaled_sprite_size: Tuple[int, int], spritesheet_indices: Dict[Direction, List[Tuple[int, int]]], sprite_position_relative_to_entity: Tuple[int, int]): register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, mind_constructor) sprite_sheet = SpriteSheet(spritesheet_path) register_entity_sprite_map(npc_data.sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, spritesheet_indices, sprite_position_relative_to_entity)
def register_nomad_npc(): sprite = Sprite.NEUTRAL_NPC_NOMAD npc_type = NpcType.NEUTRAL_NOMAD register_npc_data( npc_type, NpcData.neutral(sprite=sprite, size=(30, 30), speed=0.03)) register_npc_behavior(npc_type, NpcMind) register_entity_sprite_map( sprite=sprite, sprite_sheet=SpriteSheet( "resources/graphics/enemy_sprite_sheet_3.png"), original_sprite_size=(32, 32), scaled_sprite_size=(48, 48), indices_by_dir={ Direction.DOWN: [(3, 0), (4, 0), (5, 0)], Direction.LEFT: [(3, 1), (4, 1), (5, 1)], Direction.RIGHT: [(3, 2), (4, 2), (5, 2)], Direction.UP: [(3, 3), (4, 3), (5, 3)] }, position_relative_to_entity=(-8, -16)) register_quest_giver_dialog( npc_name="Nomad", npc_type=NpcType.NEUTRAL_NOMAD, icon_sprite=PortraitIconSprite.NOMAD, icon_sprite_file_path='resources/graphics/nomad_portrait.png', quest=QUEST, quest_min_level=QUEST_MIN_LEVEL, quest_intro= "The red baron has caused us great trouble. Get rid of him and I'll be forever " "grateful! Oh, and please bring back anything interesting that he's carrying.", boss_npc_type=NpcType.WARRIOR_KING, quest_item_type=QUEST_ITEM_TYPE, custom_options=[ DialogOptionData("Receive blessing", "gain full health", HealAction()), DialogOptionData("Ask for advice", "see random hint", HintAction()) ], dialog_before_quest= "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!", dialog_give_quest= "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!", dialog_during_quest= "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!", dialog_after_completed= "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!", reward_item_id=lambda _: plain_item_id(ItemType.PORTAL_KEY))
def register_goblin_warlock_enemy(): enemy_size = (24, 24) enemy_sprite = Sprite.ENEMY_GOBLIN_WARLOCK npc_type = NpcType.GOBLIN_WARLOCK health = 21 exp_reward = 14 npc_data = NpcData.enemy(enemy_sprite, enemy_size, health, 0, 0.032, exp_reward, LootTableId.LEVEL_4, SoundId.DEATH_GOBLIN) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) enemy_sprite_sheet = SpriteSheet( "resources/graphics/enemy_sprite_sheet_2.png") enemy_original_sprite_size = (32, 32) enemy_scaled_sprite_size = (48, 48) enemy_indices_by_dir = { Direction.DOWN: [(0, 4), (1, 4), (2, 4)], Direction.LEFT: [(0, 5), (1, 5), (2, 5)], Direction.RIGHT: [(0, 6), (1, 6), (2, 6)], Direction.UP: [(0, 7), (1, 7), (2, 7)] } register_entity_sprite_map(enemy_sprite, enemy_sprite_sheet, enemy_original_sprite_size, enemy_scaled_sprite_size, enemy_indices_by_dir, (-12, -24)) register_projectile_controller(PROJECTILE_TYPE, ProjectileController) projectile_sprite_sheet = SpriteSheet( "resources/graphics/goblin_fireball_entity.png") projectile_original_sprite_size = (132, 156) projectile_scaled_sprite_size = (20, 20) projectile_indices_by_dir = { Direction.DOWN: [(0, 0), (1, 0), (2, 0), (3, 0)] } projectile_sprite = Sprite.PROJECTILE_ENEMY_GOBLIN_WARLOCK register_entity_sprite_map(projectile_sprite, projectile_sprite_sheet, projectile_original_sprite_size, projectile_scaled_sprite_size, projectile_indices_by_dir, (0, 0)) register_buff_effect(BUFF_TYPE, Burnt) register_buff_text(BUFF_TYPE, "Burnt")
def register_young_sorceress_npc(): npc_type = NpcType.NEUTRAL_YOUNG_SORCERESS size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_YOUNG_SORCERESS movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/manga_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x, 4), (x + 1, 4), (x + 2, 4)], Direction.LEFT: [(x, 5), (x + 1, 5), (x + 2, 5)], Direction.RIGHT: [(x, 6), (x + 1, 6), (x + 2, 6)], Direction.UP: [(x, 7), (x + 1, 7), (x + 2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_quest_giver_dialog( npc_name="Mida", npc_type=NpcType.NEUTRAL_YOUNG_SORCERESS, icon_sprite=PortraitIconSprite.YOUNG_SORCERESS, icon_sprite_file_path= 'resources/graphics/portrait_young_sorceress_npc.png', quest=Quest(QUEST_ID, "Lost pet", "Retrieve Mida's pet frog from the goblin king."), quest_min_level=QUEST_MIN_LEVEL, quest_intro= "Will you help me? I'll give you something in return. Promise!", boss_npc_type=NpcType.GOBLIN_WARRIOR, quest_item_type=ItemType.QUEST_FROG, custom_options=[], dialog_before_quest="", dialog_give_quest= "Hey you! Have you seen my pet frog? I bet it was that old green mean goblin king that took " "it!", dialog_during_quest="Hi friend! Any luck?", dialog_after_completed="Thank you for helping me!", reward_item_id=_get_reward_for_hero)
def register_necromancer_enemy(): size = (36, 36) health = 40 exp_reward = 29 npc_data = NpcData.enemy(SPRITE, size, health, 0, 0.02, exp_reward, LOOT_TABLE_4, SoundId.DEATH_NECRO) register_npc_data(ENEMY_TYPE, npc_data) register_npc_behavior(ENEMY_TYPE, NpcMind) enemy_sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") enemy_original_sprite_size = (32, 32) enemy_scaled_sprite_size = (48, 64) enemy_indices_by_dir = { Direction.DOWN: [(x, 0) for x in range(9, 12)], Direction.LEFT: [(x, 1) for x in range(9, 12)], Direction.RIGHT: [(x, 2) for x in range(9, 12)], Direction.UP: [(x, 3) for x in range(9, 12)] } register_entity_sprite_map(SPRITE, enemy_sprite_sheet, enemy_original_sprite_size, enemy_scaled_sprite_size, enemy_indices_by_dir, (-6, -28)) register_projectile_controller(PROJECTILE_TYPE, ProjectileController)
def register_ninja_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_NINJA portrait_icon_sprite = PortraitIconSprite.NINJA npc_type = NpcType.NEUTRAL_NINJA movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) dialog_options = [ buy_consumable_option(ConsumableType.BREW, 2), buy_consumable_option(ConsumableType.HEALTH_LESSER, 3), buy_consumable_option(ConsumableType.MANA_LESSER, 3), buy_consumable_option(ConsumableType.SPEED, 4), buy_consumable_option(ConsumableType.POWER, 10), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_text_body = "Ah.. You're new here, aren't you? Interested in my stock of potions? " \ "They come at a price of course..." dialog_data = DialogData(portrait_icon_sprite, dialog_text_body, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x, 0), (x + 1, 0), (x + 2, 0)], Direction.LEFT: [(x, 1), (x + 1, 1), (x + 2, 1)], Direction.RIGHT: [(x, 2), (x + 1, 2), (x + 2, 2)], Direction.UP: [(x, 3), (x + 1, 3), (x + 2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( portrait_icon_sprite, 'resources/graphics/ninja_portrait.png')
def register_young_sorceress_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_YOUNG_SORCERESS npc_type = NpcType.NEUTRAL_YOUNG_SORCERESS ui_icon_sprite = PortraitIconSprite.YOUNG_SORCERESS movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) introduction = "Hey you! Have you seen my pet frog? I bet it was that old green mean goblin king that took it!" prompt = "> " frog_data = ITEMS[ItemType.FROG] dialog_options = [ DialogOptionData( prompt + frog_data.name, "give", AcceptFrog(), UiIconSprite.ITEM_FROG, frog_data.name, "If you help me get it back, I'll give you something in return!"), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_data = DialogData(ui_icon_sprite, introduction, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/manga_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x, 4), (x + 1, 4), (x + 2, 4)], Direction.LEFT: [(x, 5), (x + 1, 5), (x + 2, 5)], Direction.RIGHT: [(x, 6), (x + 1, 6), (x + 2, 6)], Direction.UP: [(x, 7), (x + 1, 7), (x + 2, 7)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( ui_icon_sprite, 'resources/graphics/portrait_young_sorceress_npc.png')
def register_challenge_starter_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_CHALLENGE_STARTER portrait_icon_sprite = PortraitIconSprite.CHALLENGE_STARTER npc_type = NpcType.NEUTRAL_CHALLENGE_STARTER movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) dialog_options = [ buy_item_option(ItemType.GLADIATOR_ARMOR, 20), buy_item_option(ItemType.HEALING_WAND, 20), buy_item_option(ItemType.ZULS_AEGIS, 20), buy_item_option(ItemType.WARLOCKS_COWL, 20), buy_item_option(ItemType.DRUIDS_RING, 20), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_text_body = "Choose wisely." dialog_data = DialogData(portrait_icon_sprite, dialog_text_body, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) x = 6 indices_by_dir = { Direction.DOWN: [(x, 0), (x + 1, 0), (x + 2, 0)], Direction.LEFT: [(x, 1), (x + 1, 1), (x + 2, 1)], Direction.RIGHT: [(x, 2), (x + 1, 2), (x + 2, 2)], Direction.UP: [(x, 3), (x + 1, 3), (x + 2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( portrait_icon_sprite, 'resources/graphics/ninja_portrait.png')
def register_goblin_warrior_enemy(): size = ( 32, 32 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_GOBLIN_WARRIOR npc_type = NpcType.GOBLIN_WARRIOR movement_speed = 0.09 health = 110 exp_reward = 50 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.BOSS_GOBLIN, SoundId.DEATH_BOSS, is_boss=True) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_2.png") original_sprite_size = (32, 32) scaled_sprite_size = (52, 52) sprite_sheet_x = 3 sprite_sheet_y = 4 indices_by_dir = { Direction.DOWN: [(sprite_sheet_x + i, sprite_sheet_y + 0) for i in range(3)], Direction.LEFT: [(sprite_sheet_x + i, sprite_sheet_y + 1) for i in range(3)], Direction.RIGHT: [(sprite_sheet_x + i, sprite_sheet_y + 2) for i in range(3)], Direction.UP: [(sprite_sheet_x + i, sprite_sheet_y + 3) for i in range(3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-10, -20))
def register_rat_1_enemy(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_RAT_1 npc_type = NpcType.RAT_1 movement_speed = 0.05 health = 6 exp_reward = 4 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LOOT_TABLE_1, SoundId.DEATH_RAT) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/brown_rat.png") original_sprite_size = (32, 32) scaled_sprite_size = (44, 44) indices_by_dir = { Direction.DOWN: [(0, 0), (1, 0), (2, 0)], Direction.LEFT: [(0, 1), (1, 1), (2, 1)], Direction.RIGHT: [(0, 2), (1, 2), (2, 2)], Direction.UP: [(0, 3), (1, 3), (2, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-5, -7))
def register_nomad_npc(): size = ( 30, 30 ) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.NEUTRAL_NPC_NOMAD npc_type = NpcType.NEUTRAL_NOMAD movement_speed = 0.03 register_npc_data(npc_type, NpcData.neutral(sprite, size, movement_speed)) register_npc_behavior(npc_type, NpcMind) text_body = "Greetings. I am here only to serve. Seek me out when you are wounded or need guidance!" dialog_options = [ DialogOptionData("Receive blessing", "gain full health", HealAction()), DialogOptionData("Ask for advice", "see random hint", HintAction()), DialogOptionData( "\"The red baron\"", "give", AcceptKey(), UiIconSprite.ITEM_KEY, "Key", "The red baron... Yes, he has caused us much trouble. He stole from me a key that may" " lead us out of here. You must bring it back to me!"), DialogOptionData("\"Good bye\"", "cancel", None) ] dialog_data = DialogData(PortraitIconSprite.NOMAD, text_body, dialog_options) register_npc_dialog_data(npc_type, dialog_data) sprite_sheet = SpriteSheet("resources/graphics/enemy_sprite_sheet_3.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) indices_by_dir = { Direction.DOWN: [(3, 0), (4, 0), (5, 0)], Direction.LEFT: [(3, 1), (4, 1), (5, 1)], Direction.RIGHT: [(3, 2), (4, 2), (5, 2)], Direction.UP: [(3, 3), (4, 3), (5, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16)) register_portrait_icon_sprite_path( PortraitIconSprite.NOMAD, 'resources/graphics/nomad_portrait.png')
def register_warrior_enemy(): size = (32, 32) # Must not align perfectly with grid cell size (pathfinding issues) sprite = Sprite.ENEMY_WARRIOR npc_type = NpcType.WARRIOR movement_speed = 0.12 health = 32 exp_reward = 25 npc_data = NpcData.enemy(sprite, size, health, 0, movement_speed, exp_reward, LootTableId.LEVEL_5, SoundId.DEATH_HUMAN) register_npc_data(npc_type, npc_data) register_npc_behavior(npc_type, NpcMind) sprite_sheet = SpriteSheet("resources/graphics/human_spritesheet.png") original_sprite_size = (32, 32) scaled_sprite_size = (48, 48) sheet_x = 6 indices_by_dir = { Direction.DOWN: [(sheet_x, 0), (sheet_x + 1, 0), (sheet_x + 2, 0), (sheet_x + 1, 0)], Direction.LEFT: [(sheet_x, 1), (sheet_x + 1, 1), (sheet_x + 2, 1), (sheet_x + 1, 1)], Direction.RIGHT: [(sheet_x, 2), (sheet_x + 1, 2), (sheet_x + 2, 2), (sheet_x + 1, 2)], Direction.UP: [(sheet_x, 3), (sheet_x + 1, 3), (sheet_x + 2, 3), (sheet_x + 1, 3)] } register_entity_sprite_map(sprite, sprite_sheet, original_sprite_size, scaled_sprite_size, indices_by_dir, (-8, -16))
def register_summon_scroll(): consumable_type = ConsumableType.SCROLL_SUMMON_DRAGON sprite = Sprite.CONSUMABLE_SCROLL_SUMMON_DRAGON ui_icon_sprite = UiIconSprite.CONSUMABLE_SCROLL_SUMMON_DRAGON register_consumable_effect(consumable_type, _apply_scroll) image_path = "resources/graphics/icon_scroll_ability_summon.png" register_entity_sprite_initializer(sprite, SpriteInitializer(image_path, POTION_ENTITY_SIZE)) register_ui_icon_sprite_path(ui_icon_sprite, image_path) description = "Summon a dragonling to fight for you (" + str(int(DURATION_SUMMON / 1000)) + "s)" data = ConsumableData(ui_icon_sprite, sprite, "Dragon's scroll", description, ConsumableCategory.OTHER, SoundId.CONSUMABLE_POTION) register_consumable_data(consumable_type, data) summoned_npc_type = NpcType.PLAYER_SUMMON_DRAGON summon_sprite = Sprite.PLAYER_SUMMON_DRAGON health_regen = 0.6 move_speed = 0.14 health = 28 npc_data = NpcData.player_summon(summon_sprite, (32, 32), health, health_regen, move_speed) register_npc_data(summoned_npc_type, npc_data) register_npc_behavior(summoned_npc_type, NpcMind) summon_sprite_sheet = SpriteSheet("resources/graphics/monsters_spritesheet.png") summon_original_size = (32, 32) summon_scaled_sprite_size = (52, 52) summon_indices_by_dir = { Direction.DOWN: [(x, 0) for x in range(9, 12)], Direction.LEFT: [(x, 1) for x in range(9, 12)], Direction.RIGHT: [(x, 2) for x in range(9, 12)], Direction.UP: [(x, 3) for x in range(9, 12)] } register_entity_sprite_map(summon_sprite, summon_sprite_sheet, summon_original_size, summon_scaled_sprite_size, summon_indices_by_dir, (-10, -20)) register_buff_effect(BuffType.SUMMON_DIE_AFTER_DURATION, DieAfterDuration)