pub mod on_hit_particles; pub mod particle_spawn; pub mod prelude; pub mod projectile; pub mod selfcast; use anyhow::Result; use cgmath::Vector2; use engine::prelude::*; use entity_manager::*; use rpg_components::components::character_status::CharacterStatus; use rpg_components::components::level::{Level, LevelUpEvent}; use rpg_components::components::npc_type::{NPCBoss, NPCElite, NPCNormal, NPCType}; use rpg_components::components::statistics::Statistics; use rpg_components::damage_type::DamageType; use crate::game::content::prelude::*; use crate::Game; pub fn handle_npc_death<'a>( game: &Game, s: &mut impl SceneEntities, collider: Entity, mut collider_components: MultiMut<'a>, ) -> Result<()> { // check if collider is dead, if so potentially create a loot chest and destroy the entity if let Ok(collider_status) = collider_components.get::() { if collider_status.is_dead() { let collider_level = collider_components.get::()?; let collider_location = collider_components.get::()?; if collider_components.get::().is_ok() { let npc_movement = collider_components.get::()?; npc_movement.set_direction(Vector2::zero()); let mut grave_stone = game .entity_manager() .load_entity(game.engine().assets(), "Grave Stone")?; #[cfg(debug_assertions)] { grave_stone.debug_name = Some(format!("Player Grave Stone ({})", collider)); } Location::new_and_setup(&mut grave_stone)? .set_position(collider_location.position()); s.add_entity(grave_stone)?; } else if collider_components.get::().is_ok() { let npc_hitbox = collider_components.get::()?; let ghost = Ghost::new( &game, collider_location, npc_hitbox.radius(), npc_hitbox.height(), s.now(), )?; s.add_entity(ghost)?; s.remove_entity(collider)?; if let Some(loot_chest) = LootStash::handle_npc_death( &game, collider_level, collider_location, if collider_components.get::().is_ok() { NPCType::Normal } else if collider_components.get::().is_ok() { NPCType::Elite } else if collider_components.get::().is_ok() { NPCType::Boss } else { unreachable!("missing component!"); }, )? { s.add_entity(loot_chest)?; } } } } Ok(()) } pub fn damage_and_experience( base_damage: u32, damage_type: DamageType, collider_multi_mut: &mut MultiMut<'_>, mut owner_components: MultiMut<'_>, scene: &mut SceneContents<'_>, ) -> Result<()> { if let Ok(collider_current_status) = collider_multi_mut.get::() { if let Ok(collider_stats) = collider_multi_mut.get::() { if let Ok(collider_level) = collider_multi_mut.get::() { let resistance = collider_stats.calculate_resistance(damage_type); if resistance < base_damage { let damage = base_damage - resistance; let owner_status = owner_components.get::()?; collider_current_status.apply_damage(damage as f32); scene.write_event(DamageEvent { damage, damage_type, position: collider_multi_mut.get::()?.position(), }); if collider_current_status.is_dead() { if owner_components.get::().is_ok() { if !owner_status.is_dead() { let level = owner_components.get::()?; if level.add_experience( collider_level.level(), if collider_multi_mut.get::().is_ok() { NPCType::Normal } else if collider_multi_mut.get::().is_ok() { NPCType::Elite } else if collider_multi_mut.get::().is_ok() { NPCType::Boss } else { unreachable!("missing component!"); }, )? { scene.write_event(LevelUpEvent); } } } } } } } } Ok(()) }