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.player_entity.get_center_position() distance = 80 affected_enemies = game_state.get_enemies_within_x_y_distance_of( distance, hero_center_pos) game_state.visual_effects.append( VisualRect((50, 50, 50), hero_center_pos, distance * 2, int(distance * 2.1), Millis(200), 2, None)) game_state.visual_effects.append( VisualRect((150, 150, 0), hero_center_pos, distance, distance * 2, Millis(150), 3, None)) game_state.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 _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity rect_w = 28 slash_center_pos = translate_in_direction( player_entity.get_center_position(), player_entity.direction, rect_w / 2 + PLAYER_ENTITY_SIZE[0] * 0.25) slash_rect = Rect(int(slash_center_pos[0] - rect_w / 2), int(slash_center_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.game_world.get_enemy_intersecting_rect( slash_rect) if not affected_enemies: return AbilityFailedToExecute(reason="No targets") # Note: Dependency on other ability 'stealth' should_stun = game_state.player_state.has_active_buff(BuffType.STEALTHING) if should_stun: game_state.camera_shake = CameraShake(Millis(50), Millis(150), 4) buff_effect = get_buff_effect(DEBUFF, should_stun) affected_enemies[0].gain_buff_effect(buff_effect, DEBUFF_DURATION) game_state.game_world.visual_effects.append( VisualRect((150, 150, 75), slash_center_pos, rect_w, int(rect_w * 0.7), Millis(200), 2, None)) game_state.game_world.visual_effects.append( VisualCross((100, 100, 70), slash_center_pos, 6, Millis(100), 2)) game_state.player_state.gain_buff_effect( get_buff_effect(BuffType.RECOVERING_AFTER_ABILITY), Millis(250)) return AbilityWasUsedSuccessfully()
def _get_random() -> Tuple[AbstractBuffEffect, str]: return random.choice([ (get_buff_effect(BUFF_DAMAGE), "You feel powerful! (Damage increased)"), (get_buff_effect(BUFF_ARMOR), "You feel protected! (Armor increased)"), (get_buff_effect(BUFF_MAGIC_RESIST), "You feel the spirits' presence! (Resistance increased)"), (get_buff_effect(BUFF_MOVE_SPEED), "You feel swift! (Speed increased)") ])
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity previous_position = player_entity.get_center_position() used_from_stealth = game_state.player_state.has_active_buff( BuffType.STEALTHING) for distance in range(40, 200, 10): new_position = translate_in_direction( (player_entity.x, player_entity.y), player_entity.direction, distance) if game_state.game_world.is_position_within_game_world(new_position) \ and not game_state.game_world.would_entity_collide_if_new_pos(player_entity, new_position): if _would_collide_with_wall(game_state, player_entity, distance): return AbilityFailedToExecute(reason="Wall is blocking") should_regain_mana_and_cd = False enemy_hit = _get_enemy_that_was_hit(game_state, player_entity, distance) if enemy_hit: game_state.camera_shake = CameraShake(Millis(50), Millis(150), 4) deal_player_damage_to_enemy(game_state, enemy_hit, DAMAGE, DamageType.MAGIC) has_reset_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_DASH_KILL_RESET) enemy_died = enemy_hit.health_resource.is_at_or_below_zero() if has_reset_upgrade and enemy_died: should_regain_mana_and_cd = True player_entity.set_position(new_position) new_center_position = player_entity.get_center_position() color = (250, 140, 80) game_state.game_world.visual_effects.append( VisualCircle(color, previous_position, 17, 35, Millis(150), 1)) game_state.game_world.visual_effects.append( VisualLine(color, previous_position, new_center_position, Millis(250), 2)) game_state.game_world.visual_effects.append( VisualRect(color, previous_position, 37, 46, Millis(150), 1)) game_state.game_world.visual_effects.append( VisualCircle(color, new_center_position, 25, 40, Millis(300), 1, player_entity)) has_speed_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_DASH_MOVEMENT_SPEED) if has_speed_upgrade: game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_SPEED), BUFF_SPEED_DURATION) if used_from_stealth: game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_FROM_STEALTH), BUFF_FROM_STEALTH_DURATION) return AbilityWasUsedSuccessfully( should_regain_mana_and_cd=should_regain_mana_and_cd) return AbilityFailedToExecute(reason="No space")
def _apply(game_state: GameState): player_state = game_state.player_state if not (player_state.health_resource.is_at_max() and player_state.mana_resource.is_at_max()): player_state.gain_buff_effect(get_buff_effect(BUFF_TYPE), BUFF_DURATION) return ConsumableWasConsumed() else: return ConsumableFailedToBeConsumed("Already at full health and mana!")
def item_handle_event(self, event: Event, game_state: GameState): if isinstance(event, PlayerDamagedEnemy): if random.random() < PROC_CHANCE: # Compare "source" to prevent the debuff from renewing itself indefinitely if event.damage_source != DAMAGE_SOURCE: event.enemy_npc.gain_buff_effect( get_buff_effect(BUFF_TYPE), Millis(6000))
def _apply_scroll(game_state: GameState): player_entity = game_state.game_world.player_entity summon_size = NON_PLAYER_CHARACTERS[NpcType.PLAYER_SUMMON_DRAGON].size player_size = game_state.game_world.player_entity.pygame_collision_rect.w, game_state.game_world.player_entity.h candidate_relative_positions = [ (0, - summon_size[1]), # top (player_size[0], - summon_size[1]), # top right (player_size[0], 0), # right (player_size[0], player_size[1]), # down right (0, player_size[1]), # down (-summon_size[0], player_size[1]), # down left (-summon_size[0], 0), # left (-summon_size[0], -summon_size[1]) # top left ] for relative_pos in candidate_relative_positions: summon_pos = sum_of_vectors(player_entity.get_position(), relative_pos) summon = create_npc(NpcType.PLAYER_SUMMON_DRAGON, summon_pos) is_valid_pos = not game_state.game_world.would_entity_collide_if_new_pos(summon.world_entity, summon_pos) if is_valid_pos: game_state.game_world.remove_all_player_summons() game_state.game_world.add_non_player_character(summon) summon.gain_buff_effect(get_buff_effect(BuffType.SUMMON_DIE_AFTER_DURATION), DURATION_SUMMON) game_state.game_world.visual_effects.append( VisualCircle((200, 200, 30), player_entity.get_position(), 40, 70, Millis(140), 3)) game_state.game_world.visual_effects.append( VisualCircle((200, 200, 30), summon_pos, 40, 70, Millis(140), 3)) return ConsumableWasConsumed("Summoned dragon") return ConsumableFailedToBeConsumed("No space to summon dragon")
def _apply_ability(game_state: GameState) -> AbilityResult: player_state = game_state.player_state if player_state.health_resource.value <= ABILITY_HEALTH_LOSS: return AbilityFailedToExecute("Using this would kill you!") player_state.health_resource.lose(ABILITY_HEALTH_LOSS) player_state.gain_buff_effect(get_buff_effect(BUFF_TYPE), DURATION) return AbilityWasUsedSuccessfully()
def apply_player_collision(self, game_state: GameState, projectile: Projectile): deal_damage_to_player(game_state, 1, DamageType.MAGIC, None) game_state.player_state.gain_buff_effect(get_buff_effect(BuffType.ENEMY_GOBLIN_WARLOCK_BURNT), Millis(5000)) game_state.game_world.visual_effects.append( VisualCircle((180, 50, 50), game_state.game_world.player_entity.get_center_position(), 25, 50, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity rect_w = 36 # Note: We assume that this ability is used by this specific hero hero_entity_size = HEROES[HeroId.WARRIOR].entity_size slash_pos = translate_in_direction( player_entity.get_center_position(), player_entity.direction, rect_w / 2 + hero_entity_size[0] * 0.25) slash_rect = Rect(int(slash_pos[0] - rect_w / 2), int(slash_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.game_world.get_enemy_intersecting_rect(slash_rect) has_aoe_upgrade = game_state.player_state.has_upgrade(HeroUpgradeId.ABILITY_SLASH_AOE_BONUS_DAMAGE) hit_multiple_enemies = len(affected_enemies) > 1 for enemy in affected_enemies: if has_aoe_upgrade and hit_multiple_enemies: damage: float = MAX_DMG else: damage: float = MIN_DMG + random.random() * (MAX_DMG - MIN_DMG) deal_player_damage_to_enemy(game_state, enemy, damage, DamageType.PHYSICAL) game_state.game_world.visual_effects.append( VisualRect((100, 0, 0), slash_pos, rect_w, int(rect_w * 0.7), Millis(200), 2, None)) game_state.player_state.gain_buff_effect(get_buff_effect(BuffType.RECOVERING_AFTER_ABILITY), Millis(300)) return AbilityWasUsedSuccessfully()
def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): if npc.stun_status.is_stunned(): return self._time_since_attack += time_passed self._time_since_updated_path += time_passed self._time_since_reevaluated += time_passed enemy_entity = npc.world_entity target: EnemyTarget = get_target(enemy_entity, game_state) if self._time_since_updated_path > self._update_path_interval: self._time_since_updated_path = 0 if not is_player_invisible: self.pathfinder.update_path_towards_target( enemy_entity, game_state, target.entity) new_next_waypoint = self.pathfinder.get_next_waypoint_along_path( enemy_entity) should_update_waypoint = self.next_waypoint != new_next_waypoint if self._time_since_reevaluated > self._reevaluate_next_waypoint_direction_interval: self._time_since_reevaluated = 0 should_update_waypoint = True if should_update_waypoint: self.next_waypoint = new_next_waypoint if self.next_waypoint: direction = self.pathfinder.get_dir_towards_considering_collisions( game_state, enemy_entity, self.next_waypoint) _move_in_dir(enemy_entity, direction) else: enemy_entity.set_not_moving() if self._time_since_attack > self._attack_interval: if not is_player_invisible: enemy_position = enemy_entity.get_center_position() target_center_pos = target.entity.get_center_position() if is_x_and_y_within_distance(enemy_position, target_center_pos, 200): self._time_since_attack = 0 self.randomize_attack_interval() play_sound(SoundId.ENEMY_ATTACK_ICE_WITCH) damage = random.randint(DAMAGE_MIN, DAMAGE_MAX) deal_npc_damage(damage, DamageType.MAGIC, game_state, enemy_entity, npc, target) game_state.game_world.visual_effects += [ (VisualLine((100, 100, 200), enemy_position, target_center_pos, Millis(120), 3)), (VisualLine((150, 150, 250), enemy_position, target_center_pos, Millis(240), 2)) ] chance_to_resist_slow = game_state.player_state.get_effective_movement_impairing_resist_chance( ) # TODO It's error-prone that we have to check this for every negative debuff that can slow player if random.random() > chance_to_resist_slow: game_state.player_state.gain_buff_effect( get_buff_effect(SLOW_BUFF_TYPE), Millis(1500))
def _apply_ability(game_state: GameState) -> AbilityResult: game_state.player_state.force_cancel_all_buffs() has_speed_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_STEALTH_MOVEMENT_SPEED) speed_decrease = MOVEMENT_SPEED_DECREASE if not has_speed_upgrade else 0 game_state.player_state.gain_buff_effect( get_buff_effect(BUFF_STEALTH, speed_decrease), DURATION_STEALTH) return AbilityWasUsedSuccessfully()
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.ui_view.info_message.set_message( "Fight through all enemies to get out!") self.ui_view.update_game_mode_string( "Dungeon %i" % self.game_state.player_state.dungeon_difficulty_level)
def apply_middle_effect(self, game_state: GameState, buffed_entity: WorldEntity, buffed_npc: NonPlayerCharacter, time_passed: Millis) -> Optional[bool]: self.time_since_start += time_passed charger_center_pos = buffed_entity.get_center_position() if self.graphics_timer.update_and_check_if_ready(time_passed): visual_circle = VisualCircle((250, 250, 250), charger_center_pos, 15, 25, Millis(120), 2, None) game_state.visual_effects.append(visual_circle) rect_w = 32 # NOTE: We assume that this ability is used by this specific hero hero_entity_size = HEROES[HeroId.WARRIOR].entity_size impact_pos = translate_in_direction( charger_center_pos, buffed_entity.direction, rect_w / 2 + hero_entity_size[0] / 2) impact_rect = Rect(int(impact_pos[0] - rect_w / 2), int(impact_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.get_enemy_intersecting_rect(impact_rect) for enemy in affected_enemies: visual_impact_pos = get_middle_point(charger_center_pos, enemy.world_entity.get_center_position()) damage = MIN_DMG # Talent: Apply damage bonus even if using charge in melee range has_melee_upgrade = game_state.player_state.has_upgrade(HeroUpgradeId.ABILITY_CHARGE_MELEE) damage_increased = self.time_since_start > float(CHARGE_DURATION) * 0.3 or has_melee_upgrade if damage_increased: # TODO Stun target as a bonus here damage = MAX_DMG deal_player_damage_to_enemy(game_state, enemy, damage, DamageType.PHYSICAL, visual_emphasis=damage_increased) game_state.visual_effects.append( VisualRect((250, 170, 0), visual_impact_pos, 45, 25, IMPACT_STUN_DURATION, 2, None)) game_state.visual_effects.append( VisualRect((150, 0, 0), visual_impact_pos, 35, 20, IMPACT_STUN_DURATION, 2, None)) game_state.player_state.gain_buff_effect(get_buff_effect(BUFF_TYPE_STUNNED), IMPACT_STUN_DURATION) enemy.gain_buff_effect(get_buff_effect(BUFF_TYPE_STUNNED), IMPACT_STUN_DURATION) game_state.camera_shake = CameraShake(Millis(50), Millis(150), 12) play_sound(SoundId.ABILITY_CHARGE_HIT) has_stomp_cooldown_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_CHARGE_RESET_STOMP_COOLDOWN) if has_stomp_cooldown_upgrade: game_state.player_state.set_ability_cooldown_to_zero(AbilityType.STOMP) # The buff should end upon impact return True return False
def _apply(game_state: GameState): # TODO Verify that the destination is clear from collisions destination = translate_in_direction(game_state.player_spawn_position, Direction.DOWN, 50) teleport_buff_effect: AbstractBuffEffect = get_buff_effect( BuffType.TELEPORTING_WITH_WARP_STONE, destination) game_state.player_state.gain_buff_effect(teleport_buff_effect, PORTAL_DELAY) return ConsumableWasConsumed()
def use_warp_point(self, warp_point: WarpPoint): destination_warp_point = [ w for w in self.game_state.warp_points if w != warp_point ][0] # It's safe to teleport to warp point's position as hero and warp point entities are the exact same size teleport_buff_effect: AbstractBuffEffect = get_buff_effect( BuffType.TELEPORTING_WITH_WARP_POINT, destination_warp_point.world_entity.get_position()) self.game_state.player_state.gain_buff_effect(teleport_buff_effect, PORTAL_DELAY)
def handle_event(self, event: EngineEvent) -> Optional[SceneTransition]: if event == EngineEvent.PLAYER_DIED: self.game_state.player_entity.set_position(self.game_state.player_spawn_position) self.game_state.player_state.health_resource.set_to_partial_of_max(0.5) self.game_state.player_state.lose_exp_from_death() self.game_state.player_state.force_cancel_all_buffs() self.info_message.set_message("Lost exp from dying") play_sound(SoundId.EVENT_PLAYER_DIED) self.game_state.player_state.gain_buff_effect(get_buff_effect(BuffType.BEING_SPAWNED), Millis(1000)) return None
def apply_player_summon_collision(self, npc: NonPlayerCharacter, game_state: GameState, projectile: Projectile): deal_npc_damage_to_npc(game_state, npc, 1) npc.gain_buff_effect( get_buff_effect(BuffType.ENEMY_GOBLIN_WARLOCK_BURNT), Millis(5000)) game_state.visual_effects.append( VisualCircle((180, 50, 50), npc.world_entity.get_center_position(), 25, 50, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True
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("Hint: " + get_random_hint()) if new_hero_was_created: self.game_state.player_state.consumable_inventory.add_consumable(ConsumableType.HEALTH_LESSER) self.game_state.player_state.consumable_inventory.add_consumable(ConsumableType.HEALTH_LESSER) self.game_state.player_state.consumable_inventory.add_consumable(ConsumableType.MANA_LESSER) self.game_state.player_state.consumable_inventory.add_consumable(ConsumableType.MANA_LESSER) for item_type in HEROES[self.game_state.player_state.hero_id].initial_player_state.starting_items: self.add_starting_item(item_type)
def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): super().control_npc(game_state, npc, player_entity, is_player_invisible, time_passed) self.sprint_cooldown_remaining -= time_passed sprint_distance_limit = 250 if self.sprint_cooldown_remaining <= 0: is_far_away = get_manhattan_distance( npc.world_entity.get_position(), player_entity.get_position()) > sprint_distance_limit if is_far_away: npc.gain_buff_effect(get_buff_effect(BuffType.ENEMY_GOBLIN_SPEARMAN_SPRINT), Millis(2500)) self.sprint_cooldown_remaining = self.random_cooldown()
def apply_enemy_collision(self, npc: NonPlayerCharacter, game_state: GameState, projectile: Projectile): damage_was_dealt = deal_player_damage_to_enemy(game_state, npc, 1, DamageType.MAGIC) if damage_was_dealt: npc.gain_buff_effect(get_buff_effect(BUFF_TYPE), DEBUFF_DURATION) victim_center_pos = npc.world_entity.get_center_position() visual_effect_pos = (victim_center_pos[0] - ENTANGLING_ROOTS_SIZE[0] // 2, victim_center_pos[1] - ENTANGLING_ROOTS_SIZE[1] // 2) debuff_visual_effect = VisualSprite(Sprite.DECORATION_ENTANGLING_ROOTS_EFFECT, visual_effect_pos, DEBUFF_DURATION, npc.world_entity) game_state.game_world.visual_effects.append(debuff_visual_effect) play_sound(SoundId.ABILITY_ENTANGLING_ROOTS_HIT) projectile.has_collided_and_should_be_removed = True
def _apply(game_state: GameState): pos = game_state.game_world.player_entity.get_center_position() effect1 = VisualCircle((100, 150, 100), pos, 40, 120, Millis(2200), 2) effect2 = VisualCircle((100, 150, 100), pos, 40, 130, Millis(2000), 1) game_state.game_world.visual_effects += [effect1, effect2] affected_enemies = game_state.game_world.get_enemies_within_x_y_distance_of( 120, pos) for enemy in affected_enemies: enemy.gain_buff_effect(get_buff_effect(BUFF_TYPE), DEBUFF_DURATION) return ConsumableWasConsumed()
def apply_enemy_collision(self, npc: NonPlayerCharacter, game_state: GameState, projectile: Projectile): damage_amount: float = MIN_DMG + random.random() * (MAX_DMG - MIN_DMG) deal_player_damage_to_enemy(game_state, npc, damage_amount, DamageType.MAGIC) _create_visual_splash(npc.world_entity.get_center_position(), game_state) has_burn_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_FIREBALL_BURN) if has_burn_upgrade: npc.gain_buff_effect(get_buff_effect(BUFF_TYPE), FIREBALL_TALENT_BURN_DURATION) play_sound(SoundId.ABILITY_FIREBALL_HIT) projectile.has_collided_and_should_be_removed = True
def _apply_ability(game_state: GameState) -> AbilityResult: hero_center_pos = game_state.game_world.player_entity.get_center_position() distance = 60 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, 100), hero_center_pos, distance * 2, int(distance * 2.1), Millis(200), 2, None)) game_state.game_world.visual_effects.append( VisualRect((150, 150, 200), hero_center_pos, distance, distance * 2, Millis(150), 3, None)) for enemy in affected_enemies: enemy.gain_buff_effect(get_buff_effect(BUFF_TYPE_STUNNED), STUN_DURATION) return AbilityWasUsedSuccessfully()
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.player_entity rect_w = 28 slash_center_pos = translate_in_direction( player_entity.get_center_position(), player_entity.direction, rect_w / 2 + PLAYER_ENTITY_SIZE[0] * 0.25) slash_rect = Rect(int(slash_center_pos[0] - rect_w / 2), int(slash_center_pos[1] - rect_w / 2), rect_w, rect_w) affected_enemies = game_state.get_enemy_intersecting_rect(slash_rect) is_stealthed = game_state.player_state.has_active_buff(BuffType.STEALTHING) if is_stealthed: play_sound(SoundId.ABILITY_SHIV_STEALTHED) else: play_sound(SoundId.ABILITY_SHIV) for enemy in affected_enemies: damage: float = MIN_DMG + random.random() * (MAX_DMG - MIN_DMG) # Note: Dependency on other ability 'stealth' if is_stealthed: # Talent: increase the damage bonus that Shiv gets from being used while stealthing has_damage_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_SHIV_SNEAK_BONUS_DAMAGE) damage *= SHIV_UPGRADED_STEALTH_DAMAGE_MULTIPLIER if has_damage_upgrade else SHIV_STEALTH_DAMAGE_MULTIPLIER game_state.camera_shake = CameraShake(Millis(50), Millis(150), 4) else: # Talent: if attacking an enemy that's at 100% health while not stealthing, deal bonus damage has_damage_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.ABILITY_SHIV_FULL_HEALTH_BONUS_DAMAGE) if has_damage_upgrade and enemy.health_resource.is_at_max(): damage *= SHIV_TALENT_FULL_HEALTH_DAMAGE_MULTIPLIER deal_player_damage_to_enemy(game_state, enemy, damage, DamageType.PHYSICAL, visual_emphasis=is_stealthed) break game_state.visual_effects.append( VisualRect((150, 150, 75), slash_center_pos, rect_w, int(rect_w * 0.7), Millis(200), 2, None)) game_state.visual_effects.append( VisualCross((100, 100, 70), slash_center_pos, 6, Millis(100), 2)) game_state.player_state.gain_buff_effect( get_buff_effect(BuffType.RECOVERING_AFTER_ABILITY), Millis(250)) return AbilityWasUsedSuccessfully()
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity player_center_pos = player_entity.get_center_position() game_state.game_world.visual_effects.append( VisualCircle((150, 150, 250), player_center_pos, 95, 190, Millis(200), 3)) affected_enemies = game_state.game_world.get_enemies_within_x_y_distance_of(180, player_center_pos) effect_position = get_position_from_center_position(player_center_pos, EFFECT_SPRITE_SIZE) game_state.game_world.visual_effects.append( VisualSprite(Sprite.EFFECT_ABILITY_FROST_NOVA, effect_position, Millis(200), player_entity)) for enemy in affected_enemies: damage_was_dealt = deal_player_damage_to_enemy(game_state, enemy, 5, DamageType.MAGIC ) if damage_was_dealt: enemy.gain_buff_effect(get_buff_effect(BuffType.REDUCED_MOVEMENT_SPEED), Millis(4000)) return AbilityWasUsedSuccessfully()
def interact_with_portal(self, portal: Portal): if portal.is_enabled: destination_portal = [ p for p in self.game_state.portals if p.portal_id == portal.leads_to ][0] destination_portal.activate(portal.world_entity.sprite) destination = translate_in_direction( destination_portal.world_entity.get_position(), Direction.DOWN, 50) teleport_buff_effect: AbstractBuffEffect = get_buff_effect( BuffType.TELEPORTING_WITH_PORTAL, destination) delay = PORTALS[portal.portal_id].teleport_delay self.game_state.player_state.gain_buff_effect( teleport_buff_effect, delay) else: self.info_message.set_message("Hmm... Looks suspicious!")
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.game_world.player_entity aoe_center_pos = translate_in_direction( player_entity.get_center_position(), player_entity.direction, 60) aoe_pos = get_position_from_center_position(aoe_center_pos, PROJECTILE_SIZE) projectile_speed = 0.1 entity = WorldEntity(aoe_pos, PROJECTILE_SIZE, PROJECTILE_SPRITE, player_entity.direction, projectile_speed) projectile = Projectile(entity, create_projectile_controller(PROJECTILE_TYPE)) game_state.game_world.projectile_entities.append(projectile) has_lightfooted_upgrade = game_state.player_state.has_upgrade( HeroUpgradeId.MAGE_LIGHT_FOOTED) if not has_lightfooted_upgrade: game_state.player_state.gain_buff_effect( get_buff_effect(BuffType.RECOVERING_AFTER_ABILITY), Millis(300)) return AbilityWasUsedSuccessfully()
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 = [ItemType.LEATHER_COWL, ItemType.LEATHER_ARMOR, ItemType.WOODEN_SWORD, ItemType.WOODEN_SHIELD] for item_type in items: self._equip_item_on_startup(item_type)
def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): if npc.stun_status.is_stunned(): return super().control_npc(game_state, npc, player_entity, is_player_invisible, time_passed) self._time_since_state_change += time_passed if self._state == State.BASE: if self._time_since_state_change > NpcMind.STATE_DURATION_BASE: self._time_since_state_change -= NpcMind.STATE_DURATION_BASE self._state = State.FIRING npc.gain_buff_effect(get_buff_effect(BUFF_STUNNED), Millis(NpcMind.STATE_DURATION_FIRING)) return elif self._state == State.FIRING: if self._time_since_state_change > NpcMind.STATE_DURATION_FIRING: self._time_since_state_change -= NpcMind.STATE_DURATION_FIRING self._state = State.BASE return self._time_since_fired += time_passed if self._time_since_fired > NpcMind.FIRE_COOLDOWN: self._time_since_fired -= NpcMind.FIRE_COOLDOWN directions_to_player = get_directions_to_position(npc.world_entity, player_entity.get_position()) new_direction = directions_to_player[0] if random.random() < 0.1 and directions_to_player[1] is not None: new_direction = directions_to_player[1] npc.world_entity.direction = new_direction npc.world_entity.set_not_moving() center_position = npc.world_entity.get_center_position() distance_from_enemy = 35 projectile_pos = translate_in_direction( get_position_from_center_position(center_position, PROJECTILE_SIZE), npc.world_entity.direction, distance_from_enemy) projectile_speed = 0.3 projectile_entity = WorldEntity(projectile_pos, PROJECTILE_SIZE, Sprite.NONE, npc.world_entity.direction, projectile_speed) projectile = Projectile(projectile_entity, create_projectile_controller(PROJECTILE_TYPE)) game_state.game_world.projectile_entities.append(projectile) play_sound(SoundId.ENEMY_MAGIC_SKELETON_BOSS)