150 lines
5.3 KiB
Rust
150 lines
5.3 KiB
Rust
|
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 crate::game::{content::prelude::*, game::GameHandle};
|
||
|
|
||
|
use crate::Game;
|
||
|
|
||
|
pub trait Ability: Send + Sync {
|
||
|
fn data(&self) -> &AbilityLoader;
|
||
|
fn name(&self) -> &str;
|
||
|
|
||
|
fn execute(
|
||
|
&self,
|
||
|
owner: Entity,
|
||
|
components: &mut MultiMut<'_>,
|
||
|
direction: Vector2<f32>,
|
||
|
book: &AbilityBook,
|
||
|
game: &GameHandle,
|
||
|
entities: &mut Entities<'_>,
|
||
|
events: &mut ContentEvents<'_>,
|
||
|
) -> Result<()>;
|
||
|
}
|
||
|
|
||
|
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::<CharacterStatus>() {
|
||
|
if collider_status.is_dead() {
|
||
|
let collider_level = collider_components.get::<Level>()?;
|
||
|
let collider_location = collider_components.get::<Location>()?;
|
||
|
|
||
|
if collider_components.get::<FactionPlayer>().is_ok() {
|
||
|
let npc_movement = collider_components.get::<Movement>()?;
|
||
|
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::<FactionNPC>().is_ok() {
|
||
|
let npc_hitbox = collider_components.get::<HitBox>()?;
|
||
|
|
||
|
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::<NPCNormal>().is_ok() {
|
||
|
NPCType::Normal
|
||
|
} else if collider_components.get::<NPCElite>().is_ok() {
|
||
|
NPCType::Elite
|
||
|
} else if collider_components.get::<NPCBoss>().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::<CharacterStatus>() {
|
||
|
if let Ok(collider_stats) = collider_multi_mut.get::<Statistics>() {
|
||
|
if let Ok(collider_level) = collider_multi_mut.get::<Level>() {
|
||
|
let resistance = collider_stats.calculate_resistance(damage_type);
|
||
|
|
||
|
if resistance < base_damage {
|
||
|
let damage = base_damage - resistance;
|
||
|
let owner_status = owner_components.get::<CharacterStatus>()?;
|
||
|
|
||
|
collider_current_status.apply_damage(damage as f32);
|
||
|
scene.write_event(DamageEvent {
|
||
|
damage,
|
||
|
damage_type,
|
||
|
position: collider_multi_mut.get::<Location>()?.position(),
|
||
|
});
|
||
|
|
||
|
if collider_current_status.is_dead() {
|
||
|
if owner_components.get::<FactionPlayer>().is_ok() {
|
||
|
if !owner_status.is_dead() {
|
||
|
let level = owner_components.get::<Level>()?;
|
||
|
|
||
|
if level.add_experience(
|
||
|
collider_level.level(),
|
||
|
if collider_multi_mut.get::<NPCNormal>().is_ok() {
|
||
|
NPCType::Normal
|
||
|
} else if collider_multi_mut.get::<NPCElite>().is_ok() {
|
||
|
NPCType::Elite
|
||
|
} else if collider_multi_mut.get::<NPCBoss>().is_ok() {
|
||
|
NPCType::Boss
|
||
|
} else {
|
||
|
unreachable!("missing component!");
|
||
|
},
|
||
|
)? {
|
||
|
scene.write_event(LevelUpEvent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|