def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._update_attack_interval() self._time_since_attack = 0 self._update_path_interval = 900 self._time_since_updated_path = random.randint(0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._attack_interval = 1000 self._time_since_attack = self._attack_interval self._update_path_interval = 900 self._time_since_updated_path = random.randint(0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval def control_npc(self, game_state: GameState, npc: NonPlayerCharacter, player_entity: WorldEntity, is_player_invisible: bool, time_passed: Millis): self._time_since_updated_path += time_passed self._time_since_reevaluated += time_passed self._time_since_attack += time_passed summon_entity = npc.world_entity if self._time_since_updated_path > self._update_path_interval: self._time_since_updated_path = 0 nearby_enemies = game_state.game_world.get_enemies_within_x_y_distance_of(300, npc.world_entity.get_position()) if nearby_enemies: target_entity = nearby_enemies[0].world_entity else: target_entity = game_state.game_world.player_entity self.pathfinder.update_path_towards_target(summon_entity, game_state, target_entity) new_next_waypoint = self.pathfinder.get_next_waypoint_along_path(summon_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, summon_entity, self.next_waypoint) _move_in_dir(summon_entity, direction) else: summon_entity.set_not_moving() if self._time_since_attack > self._attack_interval: self._time_since_attack = 0 nearby_enemies = game_state.game_world.get_enemies_within_x_y_distance_of(100, summon_entity.get_position()) if nearby_enemies: damage_amount = 3 target = nearby_enemies[0] deal_npc_damage_to_npc(game_state, target, damage_amount) game_state.game_world.visual_effects.append( VisualLine((220, 0, 0), summon_entity.get_center_position(), target.world_entity.get_center_position(), Millis(100), damage_amount))
def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._update_path_interval = 900 self._time_since_updated_path = random.randint(0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval self._shoot_fireball_trait = EnemyShootProjectileTrait( create_projectile=create_projectile, projectile_size=PROJECTILE_SIZE, cooldown_interval=(Millis(500), Millis(5000)), chance_to_shoot_other_direction=0.3, sound_id=SoundId.ENEMY_ATTACK_GOBLIN_WARLOCK)
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._update_path_interval = 900 self._time_since_updated_path = random.randint(0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval self._shoot_fireball_trait = EnemyShootProjectileTrait( create_projectile=create_projectile, projectile_size=PROJECTILE_SIZE, cooldown_interval=(Millis(500), Millis(5000)), chance_to_shoot_other_direction=0.3, sound_id=SoundId.ENEMY_ATTACK_GOBLIN_WARLOCK) 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_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() self._shoot_fireball_trait.update(npc, game_state, time_passed)
def __init__(self, global_path_finder: GlobalPathFinder, attack_interval: Millis, damage_amount: int, chance_to_stray_from_path: float, update_path_interval: Millis): super().__init__(global_path_finder) self._base_attack_interval = attack_interval self._attack_interval = None self.randomize_attack_interval() self._time_since_attack = self._attack_interval self._update_path_interval = update_path_interval self._time_since_updated_path = self._update_path_interval self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval self.damage_amount = damage_amount self.chance_to_stray_from_path = chance_to_stray_from_path self._is_in_melee_with_target = False
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._base_attack_interval = 3000 self._attack_interval = None self.randomize_attack_interval() self._time_since_attack = self._attack_interval self._update_path_interval = 600 self._time_since_updated_path = self._update_path_interval self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval def randomize_attack_interval(self): self._attack_interval = self._base_attack_interval + random.randint( -250, 250) 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) _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.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)) ] game_state.player_state.gain_buff_effect( get_buff_effect(SLOW_BUFF_TYPE), Millis(1500))
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._attack_interval = 1000 self._time_since_attack = self._attack_interval self._update_path_interval = 900 self._time_since_updated_path = random.randint( 0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval self._shield_interval = 13000 self._shield_duration = 5000 self._time_since_shield = 7000 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 self._time_since_shield += time_passed enemy_entity = npc.world_entity if self._time_since_updated_path > self._update_path_interval: self._time_since_updated_path = 0 self.pathfinder.update_path_towards_target( enemy_entity, game_state, game_state.player_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.1 and direction: direction = random.choice( get_perpendicular_directions(direction)) _move_in_dir(enemy_entity, direction) else: enemy_entity.set_not_moving() enemy_center_pos = enemy_entity.get_center_position() if self._time_since_attack > self._attack_interval: self._time_since_attack = 0 game_state.visual_effects.append( VisualCircle((100, 100, 100), enemy_center_pos, 180, 180, Millis(self._attack_interval), 1, enemy_entity)) if not is_player_invisible: player_center_pos = game_state.player_entity.get_center_position( ) if is_x_and_y_within_distance(enemy_center_pos, player_center_pos, 160): deal_damage_to_player(game_state, 3, DamageType.MAGIC, npc) game_state.visual_effects += [ VisualCircle((0, 0, 0), enemy_center_pos, 25, 50, Millis(200), 2, enemy_entity), VisualLine((0, 100, 0), enemy_center_pos, player_center_pos, Millis(200), 2), VisualCircle((0, 100, 0), player_center_pos, 20, 40, Millis(150), 2, player_entity), VisualCircle((0, 150, 0), player_center_pos, 25, 50, Millis(200), 2, player_entity), VisualCircle((0, 200, 0), player_center_pos, 30, 60, Millis(300), 2, player_entity), ] if self._time_since_shield > self._shield_interval: self._time_since_shield = 0 game_state.visual_effects.append( VisualCircle((0, 0, 150), enemy_center_pos, 60, 20, Millis(self._shield_duration), 2, enemy_entity)) npc.gain_buff_effect(get_buff_effect(BUFF_TYPE_INVULN), Millis(self._shield_duration))
class NpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder): super().__init__(global_path_finder) self._update_attack_interval() self._time_since_attack = 0 self._update_path_interval = 900 self._time_since_updated_path = random.randint( 0, self._update_path_interval) self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval 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 _update_attack_interval(self): self._attack_interval = 500 + random.random() * 4500
class MeleeEnemyNpcMind(AbstractNpcMind): def __init__(self, global_path_finder: GlobalPathFinder, attack_interval: Millis, damage_amount: int, chance_to_stray_from_path: float, update_path_interval: Millis): super().__init__(global_path_finder) self._base_attack_interval = attack_interval self._attack_interval = None self.randomize_attack_interval() self._time_since_attack = self._attack_interval self._update_path_interval = update_path_interval self._time_since_updated_path = self._update_path_interval self.pathfinder = NpcPathfinder(global_path_finder) self.next_waypoint = None self._reevaluate_next_waypoint_direction_interval = 1000 self._time_since_reevaluated = self._reevaluate_next_waypoint_direction_interval self.damage_amount = damage_amount self.chance_to_stray_from_path = chance_to_stray_from_path self._is_in_melee_with_target = False def randomize_attack_interval(self): self._attack_interval = self._base_attack_interval + random.randint( -250, 250) 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( ) < self.chance_to_stray_from_path 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: 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, 80): self._time_since_attack = 0 self.randomize_attack_interval() deal_npc_damage(self.damage_amount, DamageType.PHYSICAL, game_state, enemy_entity, npc, target)