def apply_wall_collision(self, game_state: GameState, projectile: Projectile): game_state.game_world.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
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_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.game_world.visual_effects.append( VisualCircle(self._color, game_state.game_world.player_entity.get_center_position(), 25, 35, 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.game_world.visual_effects.append( VisualCircle(self._color, npc.world_entity.get_center_position(), 25, 35, Millis(100), 0)) projectile.has_collided_and_should_be_removed = True
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 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 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._summon_trait.update(npc, game_state, time_passed) self._random_walk_trait.update(npc, game_state, time_passed) self._time_since_healing += time_passed self._time_since_shoot += time_passed if self._time_since_healing > self._healing_cooldown: self._time_since_healing = 0 self._healing_cooldown = self._random_healing_cooldown() necro_center_pos = npc.world_entity.get_center_position() nearby_hurt_enemies = [ e for e in game_state.game_world.non_player_characters if e.is_enemy and is_x_and_y_within_distance( necro_center_pos, e.world_entity.get_center_position(), 200) and e != npc and not e.health_resource.is_at_max() ] if nearby_hurt_enemies: healing_target = nearby_hurt_enemies[0] healing_target.health_resource.gain(5) healing_target_pos = healing_target.world_entity.get_center_position( ) visual_line = VisualLine((80, 200, 150), necro_center_pos, healing_target_pos, Millis(350), 3) game_state.game_world.visual_effects.append(visual_line) play_sound(SoundId.ENEMY_NECROMANCER_HEAL) if self._time_since_shoot > self._shoot_cooldown: self._time_since_shoot = 0 self._shoot_cooldown = self._random_shoot_cooldown() npc.world_entity.direction = get_directions_to_position( npc.world_entity, player_entity.get_position())[0] 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.2 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_ATTACK_NECRO)
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 control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): 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) if random.random() < 0.5 and direction: direction = random.choice(get_perpendicular_directions(direction)) _move_in_dir(enemy_entity, direction) else: enemy_entity.set_not_moving() if self._time_since_attack > self._attack_interval: self._time_since_attack = 0 self._update_attack_interval() directions_to_player = get_directions_to_position(npc.world_entity, player_entity.get_position()) new_direction = directions_to_player[0] if random.random() < 0.3 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.11 projectile_entity = WorldEntity(projectile_pos, PROJECTILE_SIZE, PROJECTILE_SPRITE, npc.world_entity.direction, projectile_speed) projectile = Projectile(projectile_entity, create_projectile_controller(PROJECTILE_TYPE)) game_state.projectile_entities.append(projectile) play_sound(SoundId.ENEMY_ATTACK_GOBLIN_WARLOCK)
def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, _is_player_invisible: bool, time_passed: Millis): self._time_since_decision += time_passed self._time_since_healing += time_passed self._time_since_shoot += time_passed if self._time_since_healing > self._healing_cooldown: self._time_since_healing = 0 self._healing_cooldown = self._random_healing_cooldown() if not npc.health_resource.is_at_max(): healing_amount = random.randint(10, 20) npc.health_resource.gain(healing_amount) circle_effect = VisualCircle( (80, 200, 150), npc.world_entity.get_center_position(), 30, 50, Millis(350), 3) game_state.visual_effects.append(circle_effect) number_effect = create_visual_healing_text( npc.world_entity, healing_amount) game_state.visual_effects.append(number_effect) play_sound(SoundId.ENEMY_SKELETON_MAGE_HEAL) if self._time_since_shoot > self._shoot_cooldown: self._time_since_shoot = 0 self._shoot_cooldown = self._random_shoot_cooldown() npc.world_entity.direction = get_directions_to_position( npc.world_entity, player_entity.get_position())[0] 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.2 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.projectile_entities.append(projectile) play_sound(SoundId.ENEMY_ATTACK_SKELETON_MAGE) if self._time_since_decision > self._decision_interval: self._time_since_decision = 0 if random.random() < 0.2: direction = random_direction() npc.world_entity.set_moving_in_dir(direction) else: npc.world_entity.set_not_moving()
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: player_entity = game_state.game_world.player_entity distance_from_player = 35 projectile_pos = translate_in_direction( get_position_from_center_position(player_entity.get_center_position(), PROJECTILE_SIZE), player_entity.direction, distance_from_player) projectile_speed = 0.2 entity = WorldEntity(projectile_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) effect_position = (projectile_pos[0] + PROJECTILE_SIZE[0] // 2, projectile_pos[1] + PROJECTILE_SIZE[1] // 2) game_state.game_world.visual_effects.append(VisualCircle((250, 150, 50), effect_position, 9, 18, Millis(80), 0)) return AbilityWasUsedSuccessfully()
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 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)
def _apply_ability(game_state: GameState) -> AbilityResult: player_entity = game_state.player_entity distance_from_player = 35 projectile_pos = translate_in_direction( get_position_from_center_position(player_entity.get_center_position(), PROJECTILE_SIZE), player_entity.direction, distance_from_player) projectile_speed = 0.3 entity = WorldEntity(projectile_pos, PROJECTILE_SIZE, Sprite.PROJECTILE_PLAYER_FIREBALL, player_entity.direction, projectile_speed) projectile = Projectile( entity, create_projectile_controller(ProjectileType.PLAYER_FIREBALL)) game_state.projectile_entities.append(projectile) effect_position = (projectile_pos[0] + PROJECTILE_SIZE[0] // 2, projectile_pos[1] + PROJECTILE_SIZE[1] // 2) game_state.visual_effects.append( VisualCircle((250, 150, 50), effect_position, 15, 5, Millis(300), 0)) 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 control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, _is_player_invisible: bool, time_passed: Millis): self._time_since_decision += time_passed self._time_since_summoning += time_passed self._time_since_healing += time_passed self._time_since_shoot += time_passed if self._time_since_summoning > self._summoning_cooldown: necro_center_pos = npc.world_entity.get_center_position() self._time_since_summoning = 0 self._alive_summons = [summon for summon in self._alive_summons if summon in game_state.non_player_characters] if len(self._alive_summons) < 3: relative_pos_from_summoner = (random.randint(-150, 150), random.randint(-150, 150)) summon_center_pos = sum_of_vectors(necro_center_pos, relative_pos_from_summoner) summon_type = random.choice([NpcType.ZOMBIE, NpcType.MUMMY]) summon_size = NON_PLAYER_CHARACTERS[summon_type].size summon_pos = game_state.get_within_world( get_position_from_center_position(summon_center_pos, summon_size), summon_size) summon_enemy = create_npc(summon_type, summon_pos) is_wall_blocking = game_state.walls_state.does_rect_intersect_with_wall( rect_from_corners(necro_center_pos, summon_center_pos)) is_position_blocked = game_state.would_entity_collide_if_new_pos(summon_enemy.world_entity, summon_pos) if not is_wall_blocking and not is_position_blocked: self._summoning_cooldown = self._random_summoning_cooldown() game_state.add_non_player_character(summon_enemy) self._alive_summons.append(summon_enemy) game_state.visual_effects.append( VisualCircle((80, 150, 100), necro_center_pos, 40, 70, Millis(120), 3)) game_state.visual_effects.append( VisualCircle((80, 150, 100), summon_center_pos, 40, 70, Millis(120), 3)) play_sound(SoundId.ENEMY_NECROMANCER_SUMMON) else: # Failed to summon, so try again without waiting full duration self._summoning_cooldown = 500 else: self._summoning_cooldown = self._random_summoning_cooldown() if self._time_since_healing > self._healing_cooldown: self._time_since_healing = 0 self._healing_cooldown = self._random_healing_cooldown() necro_center_pos = npc.world_entity.get_center_position() nearby_hurt_enemies = [ e for e in game_state.non_player_characters if e.is_enemy and is_x_and_y_within_distance(necro_center_pos, e.world_entity.get_center_position(), 200) and e != npc and not e.health_resource.is_at_max() ] if nearby_hurt_enemies: healing_target = nearby_hurt_enemies[0] healing_target.health_resource.gain(5) healing_target_pos = healing_target.world_entity.get_center_position() visual_line = VisualLine((80, 200, 150), necro_center_pos, healing_target_pos, Millis(350), 3) game_state.visual_effects.append(visual_line) play_sound(SoundId.ENEMY_NECROMANCER_HEAL) if self._time_since_shoot > self._shoot_cooldown: self._time_since_shoot = 0 self._shoot_cooldown = self._random_shoot_cooldown() npc.world_entity.direction = get_directions_to_position(npc.world_entity, player_entity.get_position())[0] 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.2 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.projectile_entities.append(projectile) play_sound(SoundId.ENEMY_ATTACK_NECRO) if self._time_since_decision > self._decision_interval: self._time_since_decision = 0 if random.random() < 0.2: direction = random_direction() npc.world_entity.set_moving_in_dir(direction) else: npc.world_entity.set_not_moving()
def notify_time_passed(self, _game_state: GameState, projectile: Projectile, time_passed: Millis): self._age += time_passed if self._age > self._max_age: projectile.has_expired = True
def create_projectile(pos: Tuple[int, int], direction: Direction): world_entity = WorldEntity(pos, PROJECTILE_SIZE, Sprite.NONE, direction, 0.2) return Projectile(world_entity, create_projectile_controller(PROJECTILE_TYPE))
def apply_wall_collision(self, game_state: GameState, projectile: Projectile): _create_visual_splash(projectile.world_entity.get_center_position(), game_state) play_sound(SoundId.ABILITY_FIREBALL_HIT) projectile.has_collided_and_should_be_removed = True