Finish split

This commit is contained in:
hodasemi 2024-08-24 15:36:58 +02:00
parent 89023a8e6f
commit 9225c94160
21 changed files with 197 additions and 186 deletions

View file

@ -1,13 +1,2 @@
pub mod abilities;
pub mod attributes;
pub mod experience;
pub mod items;
pub mod mobs;
pub mod save_game;
pub use abilities::*;
pub use attributes::*;
pub use experience::*;
pub use items::*;
pub use mobs::*;
pub use save_game::*;

View file

@ -7,27 +7,16 @@ pub mod selfcast;
use anyhow::Result;
use cgmath::Vector2;
use engine::prelude::*;
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::*, game::GameHandle};
use crate::game::content::prelude::*;
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,

View file

@ -2,6 +2,7 @@ use crate::*;
use anyhow::Result;
use cgmath::{Deg, Vector3};
use rpg_components::{components::abilityloader::AbilityLoader, damage_type::DamageType};
pub struct ArcInfo {
pub radius: f32,
@ -32,13 +33,16 @@ impl OnHitParticles {
}
fn spawn(&self, scene: &mut SceneContents<'_>, game_handle: &GameHandle) -> Result<()> {
let game = game_handle.upgrade();
let mut entity = AbilityLoader::create_on_hit_particles(
game.engine(),
self.particle_system_info.clone(),
&self.collision_sound,
&game_handle.upgrade(),
self.position,
self.offset,
scene.particle_system_vulkan_objects(),
|s| game.build_data_path(s),
)?;
if let Some(arc_info) = &self.arc_info {

View file

@ -1,3 +1,5 @@
use rpg_components::components::abilityloader::AbilityLoader;
use crate::*;
#[derive(Debug, Clone, Copy)]

View file

@ -1,11 +1,4 @@
pub use super::{Ability, AbilityType};
pub use super::projectile::{Projectile, ProjectileMarker};
pub use super::selfcast::SelfCast;
// pub use super::slide::{Slide, SlideCreateInfo};
pub use super::ability_addon::{AbilityAddon, AbilityAddonCollection, AbilityAddonTypes};
pub use super::ability_book::AbilityBook;
pub use super::on_hit_particles::{ArcInfo, OnHitParticles};
pub use super::particle_spawn::{ParticleSpawn, ParticleSpawnExecutor};
pub use super::projectile::{Projectile, ProjectileMarker};
pub use super::selfcast::SelfCast;

View file

@ -1,4 +1,9 @@
use engine::prelude::*;
use rpg_components::{
components::{abilityloader::AbilityLoader, statistics::Statistics},
damage_type::DamageType,
items::{ability_addon::AbilityAddonCollection, ability_book::AbilityBook},
};
use crate::game::content::abilities::handle_npc_death;
@ -55,15 +60,9 @@ impl ComponentDebug for ProjectileMarker {
}
#[derive(Clone)]
pub struct Projectile {
data: AbilityLoader,
}
pub struct Projectile;
impl Projectile {
pub fn new(data: AbilityLoader) -> Result<Self> {
Ok(Projectile { data })
}
fn hit_event(
me: Entity,
collider: Entity,
@ -232,17 +231,9 @@ impl Projectile {
}
}
impl Ability for Projectile {
fn data(&self) -> &AbilityLoader {
&self.data
}
fn name(&self) -> &str {
self.data.name()
}
fn execute(
&self,
impl Projectile {
pub fn execute(
ability: &AbilityLoader,
_owner: Entity,
owner_components: &mut MultiMut<'_>,
direction: Vector2<f32>,
@ -268,7 +259,7 @@ impl Ability for Projectile {
let projectile_size = book.addons().size();
let projectile_speed = book.addons().projectile_speed();
let projectile_distance = self.data.settings.parameter.distance + book.addons().distance();
let projectile_distance = ability.settings.parameter.distance + book.addons().distance();
let ability_data = book.ability().data();
@ -281,7 +272,7 @@ impl Ability for Projectile {
let mut projectile_entity = game
.entity_manager()
.load_entity(game.engine().assets(), &self.data.settings.meta.entity)?;
.load_entity(game.engine().assets(), &ability.settings.meta.entity)?;
{
// alter the hitbox parameters
@ -332,7 +323,7 @@ impl Ability for Projectile {
));
let mut projectile_movement = Movement::new(
self.data.settings.parameter.speed + projectile_speed,
ability.settings.parameter.speed + projectile_speed,
projectile_entity.get_component_mut::<Audio>().ok(),
);
@ -363,7 +354,7 @@ impl Ability for Projectile {
}
projectile_entity.insert_component(ability_location_info);
projectile_entity.insert_component(self.data.clone());
projectile_entity.insert_component(ability.clone());
projectile_entity.insert_component(projectile_movement);
projectile_entity.insert_component(ProjectileMarker);
Faction::copy(owner_components, &mut projectile_entity);

View file

@ -2,6 +2,10 @@
use anyhow::Result;
use engine::prelude::*;
use rpg_components::{
components::{abilityloader::AbilityLoader, statistics::Statistics},
items::ability_book::AbilityBook,
};
use crate::game::{
content::prelude::*,
@ -13,27 +17,11 @@ use std::sync::{Arc, Mutex, MutexGuard};
use super::particle_spawn::ParticleSpawn;
pub struct SelfCast {
data: AbilityLoader,
}
pub struct SelfCast;
impl SelfCast {
pub fn new(data: AbilityLoader) -> Result<Self> {
Ok(SelfCast { data })
}
}
impl Ability for SelfCast {
fn data(&self) -> &AbilityLoader {
&self.data
}
fn name(&self) -> &str {
self.data.name()
}
fn execute(
&self,
pub fn execute(
ability: &AbilityLoader,
owner: Entity,
owner_components: &mut MultiMut<'_>,
direction: Vector2<f32>,
@ -46,18 +34,18 @@ impl Ability for SelfCast {
let owner_stats = owner_components.get::<Statistics>()?;
let hit_box = owner_components.get::<HitBox>()?;
let mut base_damage = self.data.damage(book.level(), book.addons(), owner_stats);
let mut base_damage = ability.damage(book.level(), book.addons(), owner_stats);
let range = self.data.settings.parameter.radius * book.addons().size();
let range = ability.settings.parameter.radius * book.addons().size();
let (mut entity_object, particle_spawn) = AreaOfEffect::new(
direction,
location.position(),
Deg(self.data.settings.parameter.arc),
Deg(ability.settings.parameter.arc),
range,
hit_box.height() * 0.75,
owner,
self.data.clone(),
ability.clone(),
base_damage,
game_handle.clone(),
)?;

View file

@ -4,6 +4,10 @@ use crate::Result;
use engine::prelude::*;
use cgmath::{vec2, InnerSpace, Vector2, Vector3};
use rpg_components::ability_type::AbilityType;
use rpg_components::components::ability_slots::AbilitySlots;
use rpg_components::components::character_status::CharacterStatus;
use rpg_components::damage_type::DamageType;
// space between user and ai hitbox
const SAFETY_RADIUS: f32 = 0.3;
@ -59,15 +63,27 @@ impl SimpleAI {
let now = scene_contents.now();
// check if ability can be cast
if book.validate_use(
now,
animation,
draw,
animation_info,
character_status,
// movement,
location,
)? {
if !animation_info.is_locked()
&& book.validate_use(now, character_status, location)?
{
{
// TODO: further separation of animation types (bows, ...)
let animation_type =
match book.ability().data().settings.parameter.damage_type {
DamageType::Physical => AnimationType::Attack,
_ => AnimationType::Cast,
};
animation_info.set_animation(
animation,
draw,
Some(animation_type),
now,
true,
false,
)?;
}
let owner = unsafe {
scene_contents.entities.entity_mut_unchecked(self.owner)?
};
@ -76,14 +92,20 @@ impl SimpleAI {
// actually cast the ability
println!("ai casts ability");
book.execute(
&mut multi_mut,
self.owner,
location.direction(),
game,
&mut scene_contents.entities,
&mut scene_contents.events,
)?;
match book.ability().data().settings.parameter.ability_type {
AbilityType::Projectile => Projectile::execute(
book.ability().data(),
self.owner,
&mut multi_mut,
location.direction(),
book,
game,
&mut scene_contents.entities,
&mut scene_contents.events,
)?,
AbilityType::SelfCast => todo!(),
}
can_move = false;

View file

@ -1,5 +1,6 @@
use anyhow::Result;
use cgmath::{Deg, Vector2, Vector3};
use rpg_components::components::abilityloader::AbilityLoader;
use std::collections::HashSet;
use std::time::Duration;

View file

@ -2,6 +2,10 @@ use std::{collections::HashSet, time::Duration};
use cgmath::{vec2, Deg, InnerSpace, Matrix2, Vector2};
use engine::prelude::*;
use rpg_components::{
components::{abilityloader::AbilityLoader, statistics::Statistics},
damage_type::DamageType,
};
use crate::*;

View file

@ -1,4 +1,5 @@
use cgmath::Vector3;
use rpg_components::damage_type::DamageType;
use crate::*;

View file

@ -3,6 +3,10 @@ use crate::*;
use anyhow::Result;
use cgmath::Vector3;
use engine::prelude::*;
use rpg_components::{
components::{level::Level, npc_type::NPCType},
items::Loot,
};
use std::sync::Arc;

View file

@ -3,7 +3,6 @@ pub mod hitbox;
pub mod movement;
mod ability_location_info;
mod abilityloader;
pub mod ai;
mod aoe;
pub mod aoe_arc;
@ -13,34 +12,21 @@ mod ghost;
pub mod health_bar;
mod loot_stash;
mod npc_name;
mod npc_type;
pub use self::{ai::*, aoe_arc::AreaOfEffectArc};
pub use self::{
ability_location_info::*,
ability_slots::*,
abilityloader::AbilityLoader,
animation_info::AnimationInfo,
aoe::*,
attributes::*,
character_status::CharacterStatus,
crafting_materials::*,
damage_number::*,
entity_faction::*,
ghost::*,
health_bar::*,
hitbox::{CollisionEventType, HitBox},
inventory::*,
item_slots::*,
level::*,
loot_stash::*,
macros::AttributeAssociation,
movement::Movement,
npc_name::NPCName,
npc_type::*,
statistic_types::*,
statistics::*,
};
use serde::{Deserialize, Serialize};

View file

@ -1,6 +1,5 @@
pub mod abilities;
pub mod components;
pub mod mechanics;
pub mod objects;
pub mod lightning;

View file

@ -2,11 +2,30 @@ use anyhow::Result;
use assetpath::AssetPath;
use cgmath::{vec2, Vector2};
use engine::prelude::*;
use rpg_components::components::{crafting_materials::CraftingMaterials, statistics::Statistics};
use rpg_components::{
ability_type::AbilityType,
components::{
ability_slots::AbilitySlots,
attributes::Attributes,
character_status::CharacterStatus,
crafting_materials::CraftingMaterials,
inventory::Inventory,
item_slots::ItemSlotContainer,
level::{Level, LevelUpEvent},
statistics::Statistics,
},
config::{
attributes::AttributeSettings,
experience::ExperienceSettings,
save_game::{save_game_dir, SaveGame},
},
damage_type::DamageType,
items::{ItemSystem, Rarities},
};
use super::super::prelude::*;
use crate::{game::configloader::*, GameHandle};
use crate::GameHandle;
use std::{sync::Arc, time::Duration};
@ -246,19 +265,59 @@ impl Hero {
let direction = location.direction();
if let Some(ability_book) = abilities.book_mut(index) {
if ability_book.validate_use(
time,
animation,
draw,
animation_info,
character_status,
location,
)? {
if !animation_info.is_locked()
&& ability_book.validate_use(time, character_status, location)?
{
unsafe {
multi_mut.clear_all_usages();
}
ability_book.execute(multi_mut, hero, direction, game_handle, entities, events)?;
{
// TODO: further separation of animation types (bows, ...)
let animation_type =
match ability_book.ability().data().settings.parameter.damage_type {
DamageType::Physical => AnimationType::Attack,
_ => AnimationType::Cast,
};
animation_info.set_animation(
animation,
draw,
Some(animation_type),
time,
true,
false,
)?;
}
match ability_book
.ability()
.data()
.settings
.parameter
.ability_type
{
AbilityType::Projectile => Projectile::execute(
ability_book.ability().data(),
hero,
multi_mut,
direction,
&ability_book,
game_handle,
entities,
events,
)?,
AbilityType::SelfCast => SelfCast::execute(
ability_book.ability().data(),
hero,
multi_mut,
direction,
&ability_book,
game_handle,
entities,
events,
)?,
};
}
}
@ -280,7 +339,8 @@ impl Hero {
pub fn save(&self, scene: &Scene) -> Result<()> {
let mut save_game = SaveGame::default();
save_game.file_name = AssetPath::from((save_game_dir(), format!("{}.savegame", self.name)));
save_game.file_name =
AssetPath::from((save_game_dir("gavania"), format!("{}.savegame", self.name)));
let entity = scene.entity(self.entity)?;
@ -341,15 +401,17 @@ impl Hero {
let mut multi_mut = entity_object.multi_mut();
let draw = multi_mut.get::<Draw>().unwrap();
let game = game_handle.upgrade();
let mut items = match hero_create_type {
HeroCreateType::SaveGame(save_game) => ItemSlotContainer::load(
save_game,
game_handle,
game.item_settings.clone(),
draw,
multi_mut.get::<ItemSlotContainer>()?.item_meshes().clone(),
&game.item_system(),
)?,
HeroCreateType::New(_) => ItemSlotContainer::empty(game_handle, draw)?,
HeroCreateType::New(_) => ItemSlotContainer::empty(game.item_settings.clone(), draw)?,
};
items.set_item_change_callback(draw, multi_mut.get::<Location>()?)?;
@ -371,10 +433,14 @@ impl Hero {
hero_create_type: &HeroCreateType,
game_handle: GameHandle,
) -> Result<AbilitySlots> {
let game = game_handle.upgrade();
match hero_create_type {
HeroCreateType::SaveGame(save_game) => AbilitySlots::load(save_game, game_handle),
HeroCreateType::SaveGame(save_game) => {
AbilitySlots::load(game.item_system(), save_game)
}
HeroCreateType::New(_) => {
let mut abilities = AbilitySlots::empty(game_handle.clone());
let mut abilities = AbilitySlots::empty(game.item_system());
let book = game_handle.upgrade().item_system().ability_book(
"Basic Attack",

View file

@ -4,12 +4,23 @@ use std::{
};
use crate::game::content::prelude::*;
use crate::{game::game::GameHandle, Rarities};
use crate::game::game::GameHandle;
use anyhow::Result;
use assetpath::AssetPath;
use cgmath::{vec3, Deg, InnerSpace, Vector3, Zero};
use engine::prelude::*;
use rpg_components::{
components::{
ability_slots::AbilitySlots,
attributes::Attributes,
character_status::CharacterStatus,
level::Level,
npc_type::{NPCBoss, NPCElite, NPCNormal, NPCType},
statistics::Statistics,
},
items::Rarities,
};
const NPC_BASE_STATS: u32 = 2;
@ -339,8 +350,9 @@ impl NPCFactory {
let ai = SimpleAI::new(6.0, 9.0, entity_object.as_entity());
// abilities
let abilities =
AbilitySlots::load_for_npc(level.level(), npc_settings, game_handle.clone())?;
// TODO
// let abilities =
// AbilitySlots::load_for_npc(level.level(), npc_settings, game_handle.clone())?;
// ========== insert components ==========
entity_object.insert_component(movement);
@ -348,7 +360,7 @@ impl NPCFactory {
entity_object.insert_component(stats);
entity_object.insert_component(character_status);
entity_object.insert_component(level);
entity_object.insert_component(abilities);
// entity_object.insert_component(abilities);
entity_object.insert_component(npc_name);
entity_object.insert_component(ai);

View file

@ -1,10 +1,7 @@
pub use super::objects::hero::{Hero, MainUser};
pub use super::abilities::prelude::*;
pub use super::mechanics::prelude::*;
pub use super::components::*;
pub use super::lightning::{Lightning, LightningMarker};
pub use super::objects::hero::{Hero, MainUser};
pub use super::objects::{
entity_manager::EntityManager,
entity_tags::EntityTags,
@ -13,5 +10,3 @@ pub use super::objects::{
},
npc::{NPCAbilitySlot, NPCFactory, NPCSettings},
};
pub use super::lightning::{Lightning, LightningMarker};

View file

@ -7,6 +7,11 @@ use assetpath::AssetPath;
use anyhow::Result;
use lua_wrapper::LuaFunction;
use rpg_components::config::abilities::AbilitySettings;
use rpg_components::config::attributes::AttributeSettings;
use rpg_components::config::experience::ExperienceSettings;
use rpg_components::config::items::ItemSettings;
use rpg_components::items::ItemSystem;
// std
use std::collections::HashMap;

View file

@ -47,42 +47,6 @@ macro_rules! load {
};
}
macro_rules! load_npc {
($me: ident, $save_game:ident, $level:ident, $($index:literal,)+) => {
paste::expr! {
$(
if $save_game.[<ability_ $index>].used {
let item_system = $me.game_handle.upgrade().item_system();
let ability = &$save_game.[<ability_ $index>];
let mut addons = Vec::new();
for addon in ability.addons.iter() {
let mut split = addon.split('|');
let rarity = Rarities::from_str(&split.nth(0).unwrap())?;
let addon_type = AbilityAddonTypes::from_str(&split.nth(0).unwrap())?;
addons.push(Some(item_system.addon(rarity, addon_type)));
}
let ability_level = ($level as f32 * ability.level).ceil() as u32;
let book = item_system.ability_book(
&ability.name,
ability.rarity,
addons,
ability_level,
);
$me.abilities[$index] = Some(book);
}
)+
}
};
}
macro_rules! store {
($me: ident, $save_game:ident, $($index:literal,)+) => {
paste::expr! {

View file

@ -5,17 +5,17 @@ use crate::items::{ItemAffix, Rarities};
use std::env::var;
#[cfg(target_os = "windows")]
pub fn save_game_dir() -> String {
pub fn save_game_dir(game: &str) -> String {
let b = var("LOCALAPPDATA").expect("couldn't get local appdata variable");
format!("{}\\gavania\\saves\\", b)
format!("{b}\\{game}\\saves\\")
}
#[cfg(target_os = "linux")]
pub fn save_game_dir() -> String {
pub fn save_game_dir(game: &str) -> String {
let b = var("HOME").expect("couldn't get HOME variable");
format!("{}/.local/share/gavania/saves/", b)
format!("{b}/.local/share/{game}/saves/")
}
create_settings_section!(

View file

@ -120,10 +120,6 @@ impl AbilityBook {
) -> Result<bool> {
// don't allow anything while being animation locked
// if animation_info.is_locked() {
// return Ok(false);
// }
if let Some(cast_information) = &self.last_cast {
let total_cool_down = Duration::from_secs_f32({
let d: Duration = self.ability.data().settings.parameter.cool_down.into();