def create_item_on_ground(item_id: ItemId, pos: Tuple[int, int]) -> ItemOnGround: item_type = item_id.item_type entity = WorldEntity(pos, ITEM_ENTITY_SIZE, get_item_data_by_type(item_type).entity_sprite) entity.view_z = 1 # It should be rendered below all other entities return ItemOnGround(entity, item_id)
def create_money_pile_on_ground(amount: int, pos: Tuple[int, int]) -> MoneyPileOnGround: if amount == 1: sprite = Sprite.COINS_1 elif amount == 2: sprite = Sprite.COINS_2 else: sprite = Sprite.COINS_5 return MoneyPileOnGround(WorldEntity(pos, ITEM_ENTITY_SIZE, sprite), amount)
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_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 create_npc(npc_type: NpcType, pos: Tuple[int, int]) -> NonPlayerCharacter: data: NpcData = NON_PLAYER_CHARACTERS[npc_type] entity = WorldEntity(pos, data.size, data.sprite, Direction.LEFT, data.speed) # TODO is this global pathfinder a problem for handling dungeons that exist in parallel with the main map? global_path_finder = get_global_path_finder() npc_mind = create_npc_mind(npc_type, global_path_finder) health_resource = HealthOrManaResource(data.max_health, data.health_regen) return NonPlayerCharacter(npc_type, entity, health_resource, npc_mind, data.npc_category, data.enemy_loot_table, data.death_sound_id, data.max_distance_allowed_from_start_position, is_boss=data.is_boss)
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_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.game_world.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.game_world.player_entity.direction, PROJECTILE_SPEED) projectile = Projectile( entity, create_projectile_controller( ProjectileType.PLAYER_ARCANE_FIRE)) game_state.game_world.projectile_entities.append(projectile) game_state.game_world.visual_effects.append( VisualRect((250, 0, 250), player_center_position, 45, 60, Millis(250), 1))
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.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.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, 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 create_warp_point(center_pos: Tuple[int, int], size: Tuple[int, int]) -> WarpPoint: entity = WorldEntity(get_position_from_center_position(center_pos, size), size, Sprite.WARP_POINT) entity.visible = False # Warp points start out invisible and are later made visible return WarpPoint(entity)
def create_chest(pos: Tuple[int, int]) -> Chest: # TODO Allow for other loot in chests (Currently all chests are equal) return Chest(WorldEntity(pos, CHEST_ENTITY_SIZE, Sprite.CHEST), LootTableId.CHEST)
def create_consumable_on_ground(consumable_type: ConsumableType, pos: Tuple[int, int]) -> ConsumableOnGround: entity = WorldEntity(pos, POTION_ENTITY_SIZE, CONSUMABLES[consumable_type].entity_sprite) entity.view_z = 1 # It should be rendered below all other entities return ConsumableOnGround(entity, consumable_type)
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 create_hero_world_entity(hero_id: HeroId, pos: Tuple[int, int]) -> WorldEntity: data = HEROES[hero_id] return WorldEntity(pos, data.entity_size, data.sprite, Direction.RIGHT, data.entity_speed)
def create_wall(wall_type: WallType, pos: Tuple[int, int]) -> Wall: entity = WorldEntity(pos, WALLS[wall_type].size, WALLS[wall_type].sprite) return Wall(wall_type, entity)
def create_dungeon_entrance(pos: Tuple[int, int]) -> DungeonEntrance: return DungeonEntrance( WorldEntity(pos, DUNGEON_ENTRANCE_ENTITY_SIZE, Sprite.DUNGEON_ENTRANCE))
def create_shrine(pos: Tuple[int, int]) -> Shrine: return Shrine(WorldEntity(pos, SHRINE_ENTITY_SIZE, Sprite.SHRINE), False)
def create_portal(portal_id: PortalId, pos: Tuple[int, int]) -> Portal: data = PORTALS[portal_id] return Portal(WorldEntity(pos, data.entity_size, data.sprite), portal_id, data.starts_enabled, data.leads_to)