def _get_reward_for_hero(game_state: GameState) -> ItemId:
    hero_id = game_state.player_state.hero_id
    if hero_id == HeroId.MAGE:
        return randomized_item_id(ItemType.STAFF_OF_FIRE)
    elif hero_id == HeroId.ROGUE:
        return randomized_item_id(ItemType.THIEFS_MASK)
    elif hero_id == HeroId.WARRIOR:
        return randomized_item_id(ItemType.CLEAVER)
    else:
        return randomized_item_id(ItemType.LEATHER_ARMOR)
Beispiel #2
0
    def _put_loot_on_ground(self, enemy_death_position: Tuple[int, int],
                            loot: List[LootEntry]):
        for loot_entry in loot:
            if len(loot) > 1:
                position_offset = (random.randint(-20,
                                                  20), random.randint(-20, 20))
            else:
                position_offset = (0, 0)
            loot_position = sum_of_vectors(enemy_death_position,
                                           position_offset)

            if isinstance(loot_entry, MoneyLootEntry):
                money_pile_on_ground = create_money_pile_on_ground(
                    loot_entry.amount, loot_position)
                self.game_state.money_piles_on_ground.append(
                    money_pile_on_ground)
            elif isinstance(loot_entry, ItemLootEntry):
                item_id = randomized_item_id(loot_entry.item_type)
                item_on_ground = create_item_on_ground(item_id, loot_position)
                self.game_state.items_on_ground.append(item_on_ground)
            elif isinstance(loot_entry, SuffixedItemLootEntry):
                item_id = randomized_suffixed_item_id(loot_entry.item_type,
                                                      loot_entry.suffix_id)
                item_on_ground = create_item_on_ground(item_id, loot_position)
                self.game_state.items_on_ground.append(item_on_ground)
            elif isinstance(loot_entry, ConsumableLootEntry):
                consumable_on_ground = create_consumable_on_ground(
                    loot_entry.consumable_type, loot_position)
                self.game_state.consumables_on_ground.append(
                    consumable_on_ground)
Beispiel #3
0
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(randomized_item_id(ItemType.GLADIATOR_ARMOR), 20),
        buy_item_option(randomized_item_id(ItemType.HEALING_WAND), 20),
        buy_item_option(randomized_item_id(ItemType.ZULS_AEGIS), 20),
        buy_item_option(randomized_item_id(ItemType.WARLOCKS_COWL), 20),
        buy_item_option(randomized_item_id(ItemType.DRUIDS_RING), 20),
        DialogOptionData("\"Good bye\"", "cancel", None)
    ]
    dialog_text_body = "Choose wisely."
    dialog_data = DialogData("Vendor", 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')
Beispiel #4
0
    def on_startup(self, new_hero_was_created: bool):
        self.game_state.player_state.gain_buff_effect(
            get_buff_effect(BuffType.BEING_SPAWNED), Millis(1000))
        self.info_message.set_message("Challenge starting...")
        if new_hero_was_created:
            self.game_state.player_state.modify_money(100)
            self.game_engine.gain_levels(4)

            consumables = [
                ConsumableType.HEALTH, ConsumableType.HEALTH,
                ConsumableType.MANA, ConsumableType.MANA, ConsumableType.SPEED,
                ConsumableType.POWER
            ]
            for consumable_type in consumables:
                self.game_state.player_state.consumable_inventory.add_consumable(
                    consumable_type)
            items = [
                randomized_item_id(ItemType.LEATHER_COWL),
                randomized_item_id(ItemType.LEATHER_ARMOR),
                randomized_item_id(ItemType.PRACTICE_SWORD),
                randomized_item_id(ItemType.WOODEN_SHIELD)
            ]
            for item_type in items:
                self._equip_item_on_startup(item_type)
Beispiel #5
0
def print_loot():
    for level in range(1, 10):
        consumable_types = get_consumables_with_level(level)
        item_types = get_items_with_level(level)
        if not consumable_types and not item_types:
            continue
        print("LEVEL " + str(level))
        print("- - - - -")
        for c_type in consumable_types:
            print("{:<25}".format(c_type.name) + str(CONSUMABLES[c_type].description))
        for i_type in item_types:
            data = get_item_data_by_type(i_type)
            description_lines = [line.text for line in create_item_description(randomized_item_id(i_type))]
            print("{:<25}".format(data.base_name) + ", ".join(description_lines))
        print("")
Beispiel #6
0
def print_items():
    for category in [c for c in ItemEquipmentCategory] + [None]:
        if category:
            print(category.name + ":")
        else:
            print("PASSIVE:")
        print("- - - - -")
        entries: List[Tuple[ItemType, ItemData, Optional[int]]] = [
            (i_type, i_data, get_optional_item_level(i_type))
            for (i_type, i_data) in get_items_with_category(category)
        ]
        entries.sort(key=lambda entry: entry[2] if entry[2] else 9999)
        for item_type, item_data, item_level in entries:
            level_text = "level {:<10}".format(
                item_level) if item_level else " " * 16
            item_id = randomized_item_id(item_type)
            item_name = build_item_name(item_id)
            print("{:<25}".format(item_name) + level_text +
                  str(create_item_description(item_id)))
        print("")
    def _put_loot_on_ground(self, enemy_death_position: Tuple[int, int],
                            loot: List[LootEntry]):
        for loot_entry in loot:
            if len(loot) > 1:
                position_offset = (random.randint(-20,
                                                  20), random.randint(-20, 20))
            else:
                position_offset = (0, 0)
            loot_position = sum_of_vectors(enemy_death_position,
                                           position_offset)

            if isinstance(loot_entry, MoneyLootEntry):
                money_pile_on_ground = create_money_pile_on_ground(
                    loot_entry.amount, loot_position)
                self.game_state.game_world.money_piles_on_ground.append(
                    money_pile_on_ground)
            elif isinstance(loot_entry, ItemLootEntry):
                item_id = randomized_item_id(loot_entry.item_type)
                item_on_ground = create_item_on_ground(item_id, loot_position)
                self.game_state.game_world.items_on_ground.append(
                    item_on_ground)
            elif isinstance(loot_entry, AffixedItemLootEntry):
                item_id = loot_entry.item_id
                item_on_ground = create_item_on_ground(item_id, loot_position)
                self.game_state.game_world.items_on_ground.append(
                    item_on_ground)
                loot_center_pos = (loot_position[0] + ITEM_ENTITY_SIZE[0] // 2,
                                   loot_position[1] + ITEM_ENTITY_SIZE[1] // 2)
                self.game_state.game_world.visual_effects.append(
                    VisualCircle((170, 200, 170), loot_center_pos, 30, 40,
                                 Millis(500), 2))
                self.game_state.game_world.visual_effects.append(
                    VisualCircle((70, 100, 70), loot_center_pos, 25, 35,
                                 Millis(500), 2))
            elif isinstance(loot_entry, ConsumableLootEntry):
                consumable_on_ground = create_consumable_on_ground(
                    loot_entry.consumable_type, loot_position)
                self.game_state.game_world.consumables_on_ground.append(
                    consumable_on_ground)
Beispiel #8
0
def _get_initial_player_state_warrior() -> InitialPlayerStateData:
    health = 60
    mana = 30
    mana_regen = 2
    health_per_level = 15
    mana_per_level = 5
    armor_per_level = 1
    level_bonus = PlayerLevelBonus(health_per_level, mana_per_level,
                                   armor_per_level)
    armor = 3
    dodge_chance = 0.05
    consumable_slots = {1: [], 2: [], 3: [], 4: [], 5: []}
    abilities = [AbilityType.SWORD_SLASH]
    new_level_abilities = {
        2: AbilityType.CHARGE,
        5: AbilityType.BLOOD_LUST,
        7: AbilityType.STOMP
    }

    talents_state = TalentsConfig({
        3:
        TALENT_CHOICE_ARMOR_DAMAGE,
        4:
        TalentTierConfig(
            TalentTierOptionConfig(
                "Close combat",
                "Your Charge ability deals full damage even when used at close range",
                HeroUpgradeId.ABILITY_CHARGE_MELEE,
                UiIconSprite.ABILITY_CHARGE),
            TalentTierOptionConfig(
                "Brawl",
                "Your Slash ability deals max damage if at least 2 enemies are hit",
                HeroUpgradeId.ABILITY_SLASH_AOE_BONUS_DAMAGE,
                UiIconSprite.ABILITY_SWORD_SLASH)),
        5:
        TALENT_CHOICE_HEALTH_MANA,
        6:
        TalentTierConfig(
            TalentTierOptionConfig(
                "Bloodthirst",
                "The duration of your Bloodlust ability is now increased by " +
                "{:.1f}".format(
                    BLOODLUST_UPGRADED_INCREASED_DURATION_FROM_KILL / 1000) +
                "s on kills", HeroUpgradeId.ABILITY_BLOODLUST_DURATION,
                UiIconSprite.ABILITY_BLOODLUST),
            TalentTierOptionConfig(
                "Berserker", "Reduces the cooldown of your Slash ability to " +
                "{:.1f}".format(ABILITY_SLASH_UPGRADED_COOLDOWN / 1000) + "s",
                HeroUpgradeId.ABILITY_SLASH_CD,
                UiIconSprite.ABILITY_SWORD_SLASH)),
        7:
        TALENT_CHOICE_HEALTH_MANA_REGEN,
        8:
        TalentTierConfig(
            TalentTierOptionConfig(
                "Juggernaut",
                "Hitting an enemy with your Charge ability resets the cooldown of War Stomp",
                HeroUpgradeId.ABILITY_CHARGE_RESET_STOMP_COOLDOWN,
                UiIconSprite.ABILITY_STOMP),
            TalentTierOptionConfig(
                "Retribution", "Increases your block chance by " +
                str(int(BUFF_RETRIBUTION_BONUS_BLOCK_CHANCE * 100)) +
                "%. Blocking an enemy attack gives +" +
                str(int(BUFF_RETRIBUTION_BONUS_DAMAGE * 100)) +
                "% damage for " +
                "{:.1f}".format(BUFF_RETRIBUTION_DURATION / 1000) + "s",
                RetributionHeroUpgrade(HeroUpgradeId.WARRIOR_RETRIBUTION),
                UiIconSprite.ITEM_SKULL_SHIELD)),
    })
    block_chance = 0.2
    return InitialPlayerStateData(
        health, mana, mana_regen, consumable_slots, abilities,
        new_level_abilities, HERO_ID, armor, dodge_chance, level_bonus,
        talents_state, block_chance, [
            randomized_item_id(ItemType.PRACTICE_SWORD),
            randomized_item_id(ItemType.WOODEN_SHIELD)
        ])
def _get_initial_player_state_mage() -> InitialPlayerStateData:
    health = 40
    mana = 60
    mana_regen = 3.5
    health_per_level = 5
    mana_per_level = 10
    armor_per_level = 0.3
    level_bonus = PlayerLevelBonus(health_per_level, mana_per_level, armor_per_level)
    armor = 1
    dodge_chance = 0.05
    consumable_slots = {
        1: [],
        2: [],
        3: [],
        4: [],
        5: []
    }
    abilities = [AbilityType.FIREBALL]
    new_level_abilities = {
        2: AbilityType.WHIRLWIND,
        5: AbilityType.ENTANGLING_ROOTS,
        7: AbilityType.ARCANE_FIRE
    }

    talents_state = TalentsConfig(
        {
            3: TALENT_CHOICE_ARMOR_DAMAGE,
            4: TalentTierConfig(
                TalentTierOptionConfig("Raging fire", "Enemies hit by your fireballs take additional " +
                                       str(FIREBALL_TALENT_BURN_TOTAL_DAMAGE) + " damage over " +
                                       "{:.1f}".format(FIREBALL_TALENT_BURN_DURATION / 1000) + "s",
                                       HeroUpgradeId.ABILITY_FIREBALL_BURN, UiIconSprite.ABILITY_FIREBALL),
                TalentTierOptionConfig("Hurricane", "Whirlwind has a chance to stun affected enemies for " +
                                       "{:.1f}".format(WHIRLWIND_TALENT_STUN_DURATION / 1000) + "s",
                                       HeroUpgradeId.ABILITY_WHIRLWIND_STUN, UiIconSprite.ABILITY_WHIRLWIND)),
            5: TALENT_CHOICE_HEALTH_MANA,
            6: TalentTierConfig(
                TalentTierOptionConfig("Swift justice", "Reduces the cooldown of your Entangling Roots ability to " +
                                       "{:.1f}".format(ENTANGLING_ROOTS_UPGRADED_COOLDOWN / 1000) + "s",
                                       HeroUpgradeId.ABILITY_ENTANGLING_ROOTS_COOLDOWN,
                                       UiIconSprite.ABILITY_ENTANGLING_ROOTS),
                TalentTierOptionConfig("Flamethrower", "Reduces the mana-cost of your Fireball ability to " +
                                       str(FIREBALL_UPGRADED_MANA_COST),
                                       HeroUpgradeId.ABILITY_FIREBALL_MANA_COST, UiIconSprite.ABILITY_FIREBALL)),
            7: TALENT_CHOICE_HEALTH_MANA_REGEN,
            8: TalentTierConfig(
                TalentTierOptionConfig("Power hungry",
                                       "Reduces the cooldown of your Arcane Fire ability to " +
                                       "{:.1f}".format(ARCANE_FIRE_UPGRADED_COOLDOWN / 1000) +
                                       "s, but increases its mana-cost to " + str(ARCANE_FIRE_UPGRADED_MANA_COST),
                                       HeroUpgradeId.ABILITY_ARCANE_FIRE_COOLDOWN,
                                       UiIconSprite.ABILITY_ARCANE_FIRE),
                TalentTierOptionConfig("Light-footed", "Lets you keep moving while casting Fireball and Whirlwind",
                                       HeroUpgradeId.MAGE_LIGHT_FOOTED, UiIconSprite.TALENT_LIGHT_FOOTED)),
            9: TALENT_CHOICE_MOVE_SPEED_MAGIC_RESIST,

        })
    block_chance = 0.1
    return InitialPlayerStateData(
        health, mana, mana_regen, consumable_slots, abilities, new_level_abilities, HERO_ID, armor, dodge_chance,
        level_bonus, talents_state, block_chance, [randomized_item_id(ItemType.NOVICE_WAND)])
Beispiel #10
0
def _get_initial_player_state_rogue() -> InitialPlayerStateData:
    health = 50
    mana = 50
    mana_regen = 2.5
    health_per_level = 10
    mana_per_level = 10
    armor_per_level = 0.7
    level_bonus = PlayerLevelBonus(health_per_level, mana_per_level, armor_per_level)
    armor = 2
    dodge_chance = 0.1
    consumable_slots = {
        1: [],
        2: [],
        3: [],
        4: [],
        5: []
    }
    abilities = [AbilityType.SHIV]
    new_level_abilities = {
        2: AbilityType.STEALTH,
        5: AbilityType.DASH,
        7: AbilityType.INFUSE_DAGGER
    }

    talents_state = TalentsConfig({
        3: TALENT_CHOICE_ARMOR_DAMAGE,
        4: TalentTierConfig(
            TalentTierOptionConfig("Shadowmeld", "Reduces the mana-cost of your Stealth ability to " +
                                   str(STEALTH_UPGRADED_MANA_COST),
                                   HeroUpgradeId.ABILITY_STEALTH_MANA_COST,
                                   UiIconSprite.ABILITY_STEALTH),
            TalentTierOptionConfig("Ambush",
                                   "Increases the damage bonus that Shiv gets from being used from stealth to " +
                                   str(int(SHIV_UPGRADED_STEALTH_DAMAGE_MULTIPLIER * 100)) + "%",
                                   HeroUpgradeId.ABILITY_SHIV_SNEAK_BONUS_DAMAGE,
                                   UiIconSprite.ABILITY_SHIV)),
        5: TALENT_CHOICE_HEALTH_MANA,
        6: TalentTierConfig(
            TalentTierOptionConfig("Acrobatics",
                                   "The cooldown and mana-cost of your dash ability is reset if it kills an enemy",
                                   HeroUpgradeId.ABILITY_DASH_KILL_RESET,
                                   UiIconSprite.ABILITY_DASH),
            TalentTierOptionConfig("First strike",
                                   "Shiv deals " +
                                   str(int(SHIV_TALENT_FULL_HEALTH_DAMAGE_MULTIPLIER * 100)) +
                                   "% damage on enemies that are at full health, unless you're stealthed",
                                   HeroUpgradeId.ABILITY_SHIV_FULL_HEALTH_BONUS_DAMAGE,
                                   UiIconSprite.ABILITY_SHIV)),
        7: TALENT_CHOICE_HEALTH_MANA_REGEN,
        8: TalentTierConfig(
            TalentTierOptionConfig("Master Assassin",
                                   "Stealth doesn't reduce movement speed",
                                   HeroUpgradeId.ABILITY_STEALTH_MOVEMENT_SPEED,
                                   UiIconSprite.ABILITY_STEALTH),
            TalentTierOptionConfig("Leap",
                                   "Dash gives +40% movement speed for 2 seconds",
                                   HeroUpgradeId.ABILITY_DASH_MOVEMENT_SPEED,
                                   UiIconSprite.ABILITY_DASH)),
        9: TALENT_CHOICE_MOVE_SPEED_MAGIC_RESIST,
    })
    block_chance = 0.15
    return InitialPlayerStateData(
        health, mana, mana_regen, consumable_slots, abilities, new_level_abilities, HERO_ID, armor, dodge_chance,
        level_bonus, talents_state, block_chance, [randomized_item_id(ItemType.PRACTICE_SWORD)])
Beispiel #11
0
PYGAME_MOUSE_LEFT_BUTTON = 1
PYGAME_MOUSE_RIGHT_BUTTON = 3

ADVANCED_ENTITIES = [
    MapEditorWorldEntity.smart_floor_tile(Sprite.MAP_EDITOR_SMART_FLOOR_1, 25),
    MapEditorWorldEntity.smart_floor_tile(Sprite.MAP_EDITOR_SMART_FLOOR_2, 50),
    MapEditorWorldEntity.smart_floor_tile(Sprite.MAP_EDITOR_SMART_FLOOR_3, 75),
    MapEditorWorldEntity.smart_floor_tile(Sprite.MAP_EDITOR_SMART_FLOOR_4, 100)
]
WALL_ENTITIES = [
    MapEditorWorldEntity.wall(wall_type) for wall_type in WallType
]
NPC_ENTITIES = [MapEditorWorldEntity.npc(npc_type) for npc_type in NpcType]
ITEM_ENTITIES = [
    MapEditorWorldEntity.item(randomized_item_id(item_type))
    for item_type in ItemType
]
MISC_ENTITIES: List[MapEditorWorldEntity] = \
    [
        MapEditorWorldEntity.player(),
        MapEditorWorldEntity.chest(),
        MapEditorWorldEntity.money(1),
        MapEditorWorldEntity.decoration(Sprite.DECORATION_GROUND_STONE),
        MapEditorWorldEntity.decoration(Sprite.DECORATION_GROUND_STONE_GRAY),
        MapEditorWorldEntity.decoration(Sprite.DECORATION_PLANT),
        MapEditorWorldEntity.shrine(),
        MapEditorWorldEntity.dungeon_entrance()
    ] + \
    [MapEditorWorldEntity.consumable(consumable_type) for consumable_type in ConsumableType] + \
    [MapEditorWorldEntity.portal(portal_id) for portal_id in PortalId]