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 mobs;
pub mod save_game;
pub use abilities::*;
pub use attributes::*;
pub use experience::*;
pub use items::*;
pub use mobs::*; pub use mobs::*;
pub use save_game::*;

View file

@ -7,27 +7,16 @@ pub mod selfcast;
use anyhow::Result; use anyhow::Result;
use cgmath::Vector2; use cgmath::Vector2;
use engine::prelude::*; 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; 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>( pub fn handle_npc_death<'a>(
game: &Game, game: &Game,
s: &mut impl SceneEntities, s: &mut impl SceneEntities,

View file

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

View file

@ -1,3 +1,5 @@
use rpg_components::components::abilityloader::AbilityLoader;
use crate::*; use crate::*;
#[derive(Debug, Clone, Copy)] #[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::on_hit_particles::{ArcInfo, OnHitParticles};
pub use super::particle_spawn::{ParticleSpawn, ParticleSpawnExecutor}; 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 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; use crate::game::content::abilities::handle_npc_death;
@ -55,15 +60,9 @@ impl ComponentDebug for ProjectileMarker {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Projectile { pub struct Projectile;
data: AbilityLoader,
}
impl Projectile { impl Projectile {
pub fn new(data: AbilityLoader) -> Result<Self> {
Ok(Projectile { data })
}
fn hit_event( fn hit_event(
me: Entity, me: Entity,
collider: Entity, collider: Entity,
@ -232,17 +231,9 @@ impl Projectile {
} }
} }
impl Ability for Projectile { impl Projectile {
fn data(&self) -> &AbilityLoader { pub fn execute(
&self.data ability: &AbilityLoader,
}
fn name(&self) -> &str {
self.data.name()
}
fn execute(
&self,
_owner: Entity, _owner: Entity,
owner_components: &mut MultiMut<'_>, owner_components: &mut MultiMut<'_>,
direction: Vector2<f32>, direction: Vector2<f32>,
@ -268,7 +259,7 @@ impl Ability for Projectile {
let projectile_size = book.addons().size(); let projectile_size = book.addons().size();
let projectile_speed = book.addons().projectile_speed(); 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(); let ability_data = book.ability().data();
@ -281,7 +272,7 @@ impl Ability for Projectile {
let mut projectile_entity = game let mut projectile_entity = game
.entity_manager() .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 // alter the hitbox parameters
@ -332,7 +323,7 @@ impl Ability for Projectile {
)); ));
let mut projectile_movement = Movement::new( 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(), 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(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(projectile_movement);
projectile_entity.insert_component(ProjectileMarker); projectile_entity.insert_component(ProjectileMarker);
Faction::copy(owner_components, &mut projectile_entity); Faction::copy(owner_components, &mut projectile_entity);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,11 +2,30 @@ use anyhow::Result;
use assetpath::AssetPath; use assetpath::AssetPath;
use cgmath::{vec2, Vector2}; use cgmath::{vec2, Vector2};
use engine::prelude::*; 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 super::super::prelude::*;
use crate::{game::configloader::*, GameHandle}; use crate::GameHandle;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
@ -246,19 +265,59 @@ impl Hero {
let direction = location.direction(); let direction = location.direction();
if let Some(ability_book) = abilities.book_mut(index) { if let Some(ability_book) = abilities.book_mut(index) {
if ability_book.validate_use( if !animation_info.is_locked()
time, && ability_book.validate_use(time, character_status, location)?
animation, {
draw,
animation_info,
character_status,
location,
)? {
unsafe { unsafe {
multi_mut.clear_all_usages(); 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<()> { pub fn save(&self, scene: &Scene) -> Result<()> {
let mut save_game = SaveGame::default(); 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)?; let entity = scene.entity(self.entity)?;
@ -341,15 +401,17 @@ impl Hero {
let mut multi_mut = entity_object.multi_mut(); let mut multi_mut = entity_object.multi_mut();
let draw = multi_mut.get::<Draw>().unwrap(); let draw = multi_mut.get::<Draw>().unwrap();
let game = game_handle.upgrade();
let mut items = match hero_create_type { let mut items = match hero_create_type {
HeroCreateType::SaveGame(save_game) => ItemSlotContainer::load( HeroCreateType::SaveGame(save_game) => ItemSlotContainer::load(
save_game, save_game,
game_handle, game.item_settings.clone(),
draw, draw,
multi_mut.get::<ItemSlotContainer>()?.item_meshes().clone(), 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>()?)?; items.set_item_change_callback(draw, multi_mut.get::<Location>()?)?;
@ -371,10 +433,14 @@ impl Hero {
hero_create_type: &HeroCreateType, hero_create_type: &HeroCreateType,
game_handle: GameHandle, game_handle: GameHandle,
) -> Result<AbilitySlots> { ) -> Result<AbilitySlots> {
let game = game_handle.upgrade();
match hero_create_type { 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(_) => { 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( let book = game_handle.upgrade().item_system().ability_book(
"Basic Attack", "Basic Attack",

View file

@ -4,12 +4,23 @@ use std::{
}; };
use crate::game::content::prelude::*; use crate::game::content::prelude::*;
use crate::{game::game::GameHandle, Rarities}; use crate::game::game::GameHandle;
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath; use assetpath::AssetPath;
use cgmath::{vec3, Deg, InnerSpace, Vector3, Zero}; use cgmath::{vec3, Deg, InnerSpace, Vector3, Zero};
use engine::prelude::*; 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; const NPC_BASE_STATS: u32 = 2;
@ -339,8 +350,9 @@ impl NPCFactory {
let ai = SimpleAI::new(6.0, 9.0, entity_object.as_entity()); let ai = SimpleAI::new(6.0, 9.0, entity_object.as_entity());
// abilities // abilities
let abilities = // TODO
AbilitySlots::load_for_npc(level.level(), npc_settings, game_handle.clone())?; // let abilities =
// AbilitySlots::load_for_npc(level.level(), npc_settings, game_handle.clone())?;
// ========== insert components ========== // ========== insert components ==========
entity_object.insert_component(movement); entity_object.insert_component(movement);
@ -348,7 +360,7 @@ impl NPCFactory {
entity_object.insert_component(stats); entity_object.insert_component(stats);
entity_object.insert_component(character_status); entity_object.insert_component(character_status);
entity_object.insert_component(level); 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(npc_name);
entity_object.insert_component(ai); 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::abilities::prelude::*;
pub use super::mechanics::prelude::*;
pub use super::components::*; pub use super::components::*;
pub use super::lightning::{Lightning, LightningMarker};
pub use super::objects::hero::{Hero, MainUser};
pub use super::objects::{ pub use super::objects::{
entity_manager::EntityManager, entity_manager::EntityManager,
entity_tags::EntityTags, entity_tags::EntityTags,
@ -13,5 +10,3 @@ pub use super::objects::{
}, },
npc::{NPCAbilitySlot, NPCFactory, NPCSettings}, npc::{NPCAbilitySlot, NPCFactory, NPCSettings},
}; };
pub use super::lightning::{Lightning, LightningMarker};

View file

@ -7,6 +7,11 @@ use assetpath::AssetPath;
use anyhow::Result; use anyhow::Result;
use lua_wrapper::LuaFunction; 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 // std
use std::collections::HashMap; 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 { macro_rules! store {
($me: ident, $save_game:ident, $($index:literal,)+) => { ($me: ident, $save_game:ident, $($index:literal,)+) => {
paste::expr! { paste::expr! {

View file

@ -5,17 +5,17 @@ use crate::items::{ItemAffix, Rarities};
use std::env::var; use std::env::var;
#[cfg(target_os = "windows")] #[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"); let b = var("LOCALAPPDATA").expect("couldn't get local appdata variable");
format!("{}\\gavania\\saves\\", b) format!("{b}\\{game}\\saves\\")
} }
#[cfg(target_os = "linux")] #[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"); 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!( create_settings_section!(

View file

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