class QuestGiverNpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder, quest_id: QuestId, quest_item_id: ItemId, quest_min_level: int): super().__init__(global_path_finder) self.timer = PeriodicTimer(Millis(500)) self.quest_timer = PeriodicTimer(Millis(1000)) self.quest_id = quest_id self.quest_item_id = quest_item_id self.quest_min_level = quest_min_level def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): if self.quest_timer.update_and_check_if_ready(time_passed): player_state = game_state.player_state if player_state.has_quest(self.quest_id): if player_state.item_inventory.has_item_in_inventory(self.quest_item_id): npc.quest_giver_state = QuestGiverState.CAN_COMPLETE_QUEST else: npc.quest_giver_state = QuestGiverState.WAITING_FOR_PLAYER elif player_state.has_completed_quest(self.quest_id): npc.quest_giver_state = None elif player_state.level >= self.quest_min_level: npc.quest_giver_state = QuestGiverState.CAN_GIVE_NEW_QUEST else: npc.quest_giver_state = None if self.timer.update_and_check_if_ready(time_passed): if random.random() < 0.8: npc.world_entity.set_not_moving() else: direction = random.choice(get_all_directions()) npc.world_entity.set_moving_in_dir(direction)
class DebuffedByGoatsRing(AbstractBuffEffect): def __init__(self): self.dmg_timer = PeriodicTimer(Millis(1000)) self.graphics_timer = PeriodicTimer(Millis(400)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.dmg_timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, 1, DamageType.MAGIC, damage_source=DAMAGE_SOURCE) if self.graphics_timer.update_and_check_if_ready(time_passed): position = buffed_entity.get_center_position() visual_effect1 = VisualCircle((0, 100, 40), position, 9, 16, Millis(400), 2, buffed_entity) visual_effect2 = VisualCircle((0, 180, 90), position, 9, 16, Millis(500), 2, buffed_entity) game_state.visual_effects.append(visual_effect1) game_state.visual_effects.append(visual_effect2) def get_buff_type(self): return BUFF_TYPE
def __init__(self): super().__init__( BUFF_TYPE, { HeroStat.LIFE_STEAL: LIFE_STEAL_BONUS_RATIO, HeroStat.MOVEMENT_SPEED: SPEED_BONUS }) self.timer = PeriodicTimer(Millis(250))
def __init__(self, global_path_finder: GlobalPathFinder, quest_id: QuestId, quest_item_id: ItemId, quest_min_level: int): super().__init__(global_path_finder) self.timer = PeriodicTimer(Millis(500)) self.quest_timer = PeriodicTimer(Millis(1000)) self.quest_id = quest_id self.quest_item_id = quest_item_id self.quest_min_level = quest_min_level
class ProjectileController(AbstractProjectileController): def __init__(self): super().__init__(2000) self._color = (50, 180, 50) self._timer = PeriodicTimer(Millis(100)) self._min_damage = 8 self._max_damage = 12 def notify_time_passed(self, game_state: GameState, projectile: Projectile, time_passed: Millis): super().notify_time_passed(game_state, projectile, time_passed) if self._timer.update_and_check_if_ready(time_passed): head = VisualCircle(self._color, projectile.world_entity.get_center_position(), 15, 15, Millis(150), 0, projectile.world_entity) tail = VisualCircle(self._color, projectile.world_entity.get_center_position(), 15, 1, Millis(400), 0) game_state.visual_effects += [head, tail] def apply_player_collision(self, game_state: GameState, projectile: Projectile): damage = random.randint(self._min_damage, self._max_damage) deal_damage_to_player(game_state, damage, DamageType.MAGIC, None) game_state.visual_effects.append(VisualCircle(self._color, game_state.player_entity.get_center_position(), 25, 50, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True def apply_player_summon_collision(self, npc: NonPlayerCharacter, game_state: GameState, projectile: Projectile): damage = random.randint(self._min_damage, self._max_damage) deal_npc_damage_to_npc(game_state, npc, damage) game_state.visual_effects.append( VisualCircle(self._color, npc.world_entity.get_center_position(), 25, 50, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True def apply_wall_collision(self, game_state: GameState, projectile: Projectile): game_state.visual_effects.append( VisualCircle(self._color, projectile.world_entity.get_center_position(), 13, 26, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True
class Invisibility(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(320)) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.is_invisible = True def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): game_state.visual_effects.append( VisualRect((0, 0, 250), game_state.player_entity.get_center_position(), 45, 60, Millis(400), 1, game_state.player_entity)) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.is_invisible = False def get_buff_type(self): return BUFF_TYPE
class ItemEffect(AbstractItemEffect): def __init__(self): self.timer = PeriodicTimer(Millis(5000)) def apply_middle_effect(self, game_state: GameState, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): strike_enemies(game_state, 1)
class BuffEffect(AbstractBuffEffect): def __init__(self): self.graphics_timer = PeriodicTimer(Millis(500)) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_entity.add_to_speed_multiplier(SPRINT_SPEED_BONUS) self.create_sprint_visual_effect(buffed_entity, game_state) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.graphics_timer.update_and_check_if_ready(time_passed): self.create_sprint_visual_effect(buffed_entity, game_state) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_entity.add_to_speed_multiplier(-SPRINT_SPEED_BONUS) def get_buff_type(self): return BUFF_SPRINT @staticmethod def create_sprint_visual_effect(buffed_entity: WorldEntity, game_state: GameState): game_state.game_world.visual_effects.append( VisualCircle((150, 50, 0), buffed_entity.get_center_position(), 20, 22, Millis(250), 2, buffed_entity))
class DebuffedByFreezingGauntlet(AbstractBuffEffect): def __init__(self): self.graphics_timer = PeriodicTimer(Millis(400)) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_entity.add_to_speed_multiplier(-SLOW_AMOUNT) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_entity.add_to_speed_multiplier(SLOW_AMOUNT) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.graphics_timer.update_and_check_if_ready(time_passed): position = buffed_entity.get_center_position() visual_effect1 = VisualCircle((0, 40, 100), position, 9, 16, Millis(400), 2, buffed_entity) visual_effect2 = VisualCircle((0, 90, 180), position, 9, 16, Millis(500), 2, buffed_entity) game_state.visual_effects.append(visual_effect1) game_state.visual_effects.append(visual_effect2) def get_buff_type(self): return BUFF_TYPE
class Rooted(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(DEBUFF_DAMAGE_INTERVAL) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_npc.stun_status.add_one() game_state.visual_effects.append( create_visual_stun_text(buffed_entity)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, 1, DamageType.MAGIC) game_state.visual_effects.append( VisualCircle((0, 150, 0), buffed_entity.get_center_position(), 30, 55, Millis(150), 2, buffed_entity)) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): buffed_npc.stun_status.remove_one() def get_buff_type(self): return BUFF_TYPE
class BloodLust(StatModifyingBuffEffect): def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.LIFE_STEAL: LIFE_STEAL_BONUS_RATIO, HeroStat.MOVEMENT_SPEED: SPEED_BONUS}) self.timer = PeriodicTimer(Millis(250)) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): super().apply_start_effect(game_state, buffed_entity, buffed_npc) sword_slash_data = ABILITIES[AbilityType.SWORD_SLASH] sword_slash_data.cooldown -= SWORD_SLASH_CD_BONUS def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): visual_effect = VisualCircle( (250, 0, 0,), buffed_entity.get_center_position(), 25, 30, Millis(350), 1, buffed_entity) game_state.visual_effects.append(visual_effect) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): super().apply_end_effect(game_state, buffed_entity, buffed_npc) sword_slash_data = ABILITIES[AbilityType.SWORD_SLASH] sword_slash_data.cooldown += SWORD_SLASH_CD_BONUS def buff_handle_event(self, event: Event) -> Optional[BuffEventOutcome]: if isinstance(event, EnemyDiedEvent): if has_blood_lust_duration_increase_upgrade: duration_increase = BLOODLUST_UPGRADED_INCREASED_DURATION_FROM_KILL else: duration_increase = BLOODLUST_INCREASED_DURATION_FROM_KILL return BuffEventOutcome.change_remaining_duration(duration_increase)
class DamagedByInfusedDagger(AbstractBuffEffect): def __init__(self, should_stun: bool): self.timer = PeriodicTimer(DAMAGE_TICK_INTERVAL) self.should_stun = should_stun def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): if self.should_stun: buffed_npc.stun_status.add_one() buffed_entity.set_not_moving() game_state.game_world.visual_effects.append( create_visual_stun_text(buffed_entity)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, DAMAGE_PER_TICK, DamageType.PHYSICAL) if self.should_stun: effect_position = buffed_entity.get_center_position() game_state.game_world.visual_effects.append( VisualRect((250, 250, 50), effect_position, 30, 40, Millis(100), 1, buffed_entity)) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): if self.should_stun: buffed_npc.stun_status.remove_one() def get_buff_type(self): return DEBUFF
class Channeling(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(CHANNEL_PROJECTILE_INTERVAL) def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.add_one() game_state.player_entity.set_not_moving() game_state.camera_shake = CameraShake(Millis(50), CHANNEL_DURATION, 5) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): player_center_position = game_state.player_entity.get_center_position() projectile_pos = get_position_from_center_position(player_center_position, PROJECTILE_SIZE) entity = WorldEntity(projectile_pos, PROJECTILE_SIZE, Sprite.PROJECTILE_PLAYER_ARCANE_FIRE, game_state.player_entity.direction, PROJECTILE_SPEED) projectile = Projectile(entity, create_projectile_controller(ProjectileType.PLAYER_ARCANE_FIRE)) game_state.projectile_entities.append(projectile) game_state.visual_effects.append(VisualRect((250, 0, 250), player_center_position, 45, 60, Millis(250), 1)) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.remove_one() def get_buff_type(self): return BuffType.CHANNELING_ARCANE_FIRE
class ItemEffect(AbstractItemEffect): def __init__(self, item_type: ItemType): super().__init__(item_type) self.timer = PeriodicTimer(Millis(5000)) self.min_dmg = 1 self.max_dmg = 3 def apply_middle_effect(self, game_state: GameState, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): player_entity = game_state.player_entity player_center_position = player_entity.get_center_position() close_enemies = game_state.get_enemies_within_x_y_distance_of( 140, player_center_position) if close_enemies: damage_amount: float = self.min_dmg + random.random() * ( self.max_dmg - self.min_dmg) deal_player_damage_to_enemy(game_state, close_enemies[0], damage_amount, DamageType.MAGIC) enemy_center_position = close_enemies[ 0].world_entity.get_center_position() game_state.visual_effects.append( VisualCircle((250, 250, 0), player_center_position, 50, 140, Millis(100), 1, player_entity)) game_state.visual_effects.append( VisualLine((250, 250, 0), player_center_position, enemy_center_position, Millis(80), 3)) def get_description(self): return [ "Periodically deals " + str(self.min_dmg) + "-" + str(self.max_dmg) + " magic damage to nearby enemies" ]
class ProjectileController(AbstractProjectileController): def __init__(self): super().__init__(PROJECTILE_DURATION) self.damage_timer = PeriodicTimer(PROJECTILE_DAMAGE_INTERVAL) self.direction_change_timer = PeriodicTimer(Millis(250)) self._relative_direction = 0 self._rotation_motion = random.choice([-1, 1]) def notify_time_passed(self, game_state: GameState, projectile: Projectile, time_passed: Millis): super().notify_time_passed(game_state, projectile, time_passed) projectile_entity = projectile.world_entity if self.damage_timer.update_and_check_if_ready(time_passed): for enemy in game_state.game_world.get_enemy_intersecting_with( projectile_entity): damage_amount = 1 damage_was_dealt = deal_player_damage_to_enemy( game_state, enemy, damage_amount, DamageType.MAGIC) if damage_was_dealt: has_stun_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_WHIRLWIND_STUN) if has_stun_upgrade and random.random() < 0.2: enemy.gain_buff_effect(get_buff_effect(BUFF_TYPE), WHIRLWIND_TALENT_STUN_DURATION) if self.direction_change_timer.update_and_check_if_ready(time_passed): should_rotate = True # keep going straight ahead sometimes if self._relative_direction == 0 and random.random() < 0.5: should_rotate = False if should_rotate: if self._rotation_motion == 1: projectile_entity.rotate_right() self._relative_direction += 90 elif self._rotation_motion == -1: projectile_entity.rotate_left() self._relative_direction -= 90 if self._relative_direction == 90: self._rotation_motion = -1 elif self._relative_direction == -90: self._rotation_motion = 1
class BuffedFromElixirOfPower(StatModifyingBuffEffect): def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.DAMAGE: DAMAGE_MODIFIER_INCREASE}) self.timer = PeriodicTimer(Millis(300)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): game_state.game_world.visual_effects.append( VisualRect((0, 0, 0), game_state.game_world.player_entity.get_center_position(), 6, 18, Millis(200), 3))
class IncreasedSpeedAfterDash(StatModifyingBuffEffect): def __init__(self): super().__init__(BUFF_SPEED, {HeroStat.MOVEMENT_SPEED: 0.4}) self.timer = PeriodicTimer(Millis(100)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): game_state.visual_effects.append( VisualCircle((150, 200, 250), game_state.player_entity.get_center_position(), 5, 10, Millis(200), 0))
class ChannelingStomp(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(80)) self.graphics_size = 40 def apply_start_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.add_one() game_state.game_world.player_entity.set_not_moving() def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis) -> bool: if self.timer.update_and_check_if_ready(time_passed): visual_effect = VisualCircle( (250, 250, 250), buffed_entity.get_center_position(), self.graphics_size, self.graphics_size + 10, Millis(70), 2, None) self.graphics_size -= 7 game_state.game_world.visual_effects.append(visual_effect) return False def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.stun_status.remove_one() hero_center_pos = game_state.game_world.player_entity.get_center_position( ) distance = 80 affected_enemies = game_state.game_world.get_enemies_within_x_y_distance_of( distance, hero_center_pos) game_state.game_world.visual_effects.append( VisualRect((50, 50, 50), hero_center_pos, distance * 2, int(distance * 2.1), Millis(200), 2, None)) game_state.game_world.visual_effects.append( VisualRect((150, 150, 0), hero_center_pos, distance, distance * 2, Millis(150), 3, None)) game_state.game_world.visual_effects.append( VisualRect((250, 250, 0), hero_center_pos, distance, distance * 2, Millis(100), 4, None)) for enemy in affected_enemies: damage: float = MIN_DMG + random.random() * (MAX_DMG - MIN_DMG) deal_player_damage_to_enemy(game_state, enemy, damage, DamageType.PHYSICAL) enemy.gain_buff_effect(get_buff_effect(STUNNED_BY_STOMP), STUN_DURATION) game_state.player_state.gain_buff_effect( get_buff_effect(BuffType.RECOVERING_AFTER_ABILITY), Millis(300)) play_sound(SoundId.ABILITY_STOMP_HIT) game_state.camera_shake = CameraShake(Millis(50), Millis(200), 12) def get_buff_type(self): return CHANNELING_STOMP
class ProtectedByStoneAmulet(StatModifyingBuffEffect): def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.ARMOR: ARMOR_BONUS}) self.timer = PeriodicTimer(Millis(300)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): game_state.visual_effects.append( VisualCircle((130, 100, 60), buffed_entity.get_center_position(), 20, 40, Millis(100), 1, buffed_entity))
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self.timer = PeriodicTimer(Millis(500)) def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): if random.random() < 0.8: npc.world_entity.set_not_moving() else: direction = random.choice(get_all_directions()) npc.world_entity.set_moving_in_dir(direction)
class RestoringHealthFromBrew(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(600)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): player_receive_healing(3, game_state) player_receive_mana(3, game_state) def get_buff_type(self): return BUFF_TYPE def buff_handle_event(self, event: Event) -> Optional[BuffEventOutcome]: if isinstance(event, PlayerLostHealthEvent): return BuffEventOutcome.cancel_effect()
class BuffEffect(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(DAMAGE_INTERVAL) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, DAMAGE, DamageType.PHYSICAL, damage_source=DAMAGE_SOURCE) def get_buff_type(self): return BUFF_TYPE
class BuffEffect(AbstractBuffEffect): def __init__(self): self._timer = PeriodicTimer(DEBUFF_DAMAGE_INTERVAL) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self._timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, DAMAGE, DamageType.MAGIC) pos = buffed_entity.get_center_position() effect = VisualCircle((100, 150, 100), pos, 40, 50, Millis(500), 1) game_state.game_world.visual_effects += [effect] def get_buff_type(self): return BUFF_TYPE
class BurntByFireball(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(FIREBALL_TALENT_BURN_INTERVAL) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): deal_player_damage_to_enemy(game_state, buffed_npc, 1, DamageType.MAGIC) game_state.visual_effects.append( VisualCircle((180, 50, 50), buffed_npc.world_entity.get_center_position(), 10, 20, Millis(50), 0, buffed_entity)) def get_buff_type(self): return BUFF_TYPE
class AfterStealthing(AbstractBuffEffect): def __init__(self): self.timer = PeriodicTimer(Millis(160)) def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): visual_effect = VisualCircle((250, 150, 250), buffed_entity.get_center_position(), 18, 25, Millis(220), 1, buffed_entity) game_state.visual_effects.append(visual_effect) def apply_end_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter): game_state.player_state.modify_stat(HeroStat.DODGE_CHANCE, -DODGE_CHANCE_BONUS) def get_buff_type(self): return BUFF_POST_STEALTH
def handle_event(self, event: EngineEvent) -> Optional[SceneTransition]: if event == EngineEvent.PLAYER_DIED: # If player has any movement buffs/debuffs that affect the hero entity, and the buff was retained when we # switch back to the old game state, then we'd incorrectly modify the hero entity when it expires self.game_state.player_state.force_cancel_all_buffs() # Player will "die again" outside of the dungeon which will trigger exp loss and respawning at base # TODO spawn animation doesn't work? Maybe we should just set HP to 1 and let hero spawn at entrance return self._transition_out_of_dungeon() elif event == EngineEvent.ENEMY_DIED: num_enemies = len([ npc for npc in self.game_state.game_world.non_player_characters if npc.is_enemy ]) if num_enemies == 0: self.ui_view.info_message.set_message("Dungeon cleared!") self.warp_countdown_timer = PeriodicTimer(Millis(1000)) self.countdown_until_hero_will_be_warped_out_of_dungeon = 5 else: self.ui_view.info_message.set_message( str(num_enemies) + " enemies remaining in dungeon") return None
class ItemEffect(AbstractItemEffect): def __init__(self): self.timer = PeriodicTimer(Millis(5000)) def apply_middle_effect(self, game_state: GameState, time_passed: Millis): if self.timer.update_and_check_if_ready(time_passed): player_entity = game_state.player_entity player_center_position = player_entity.get_center_position() close_enemies = game_state.get_enemies_within_x_y_distance_of( 140, player_center_position) if close_enemies: damage_amount: float = MIN_DMG + random.random() * (MAX_DMG - MIN_DMG) deal_player_damage_to_enemy(game_state, close_enemies[0], damage_amount, DamageType.MAGIC) enemy_center_position = close_enemies[ 0].world_entity.get_center_position() game_state.visual_effects.append( VisualCircle((250, 250, 0), player_center_position, 50, 140, Millis(100), 1, player_entity)) game_state.visual_effects.append( VisualLine((250, 250, 0), player_center_position, enemy_center_position, Millis(80), 3))
def __init__(self): super().__init__(BUFF_TYPE, {HeroStat.ARMOR: ARMOR_BONUS}) self.timer = PeriodicTimer(Millis(300))
def __init__(self): self.timer = PeriodicTimer(Millis(160))
def __init__(self): self.graphics_timer = PeriodicTimer(Millis(40)) self.time_since_start = 0