Fix majority of rpg component stuff

This commit is contained in:
hodasemi 2024-08-24 09:01:49 +02:00
parent af8ef272ff
commit 53fdd899bd
25 changed files with 225 additions and 157 deletions

View file

@ -1,26 +1,3 @@
#[macro_use]
pub mod create_section {
macro_rules! impl_from_rarity {
($struct_name:ident, $data_type:ty) => {
impl $struct_name {
pub fn from_rarity(
&self,
rarity: crate::game::content::prelude::Rarities,
) -> $data_type {
match rarity {
crate::game::content::prelude::Rarities::Common => self.common,
crate::game::content::prelude::Rarities::Uncommon => self.uncommon,
crate::game::content::prelude::Rarities::Magical => self.magical,
crate::game::content::prelude::Rarities::Rare => self.rare,
crate::game::content::prelude::Rarities::Epic => self.epic,
crate::game::content::prelude::Rarities::Legendary => self.legendary,
}
}
}
};
}
}
pub mod abilities;
pub mod attributes;
pub mod experience;

View file

@ -1,5 +1,3 @@
pub mod ability_addon;
pub mod ability_book;
pub mod on_hit_particles;
pub mod particle_spawn;
pub mod prelude;
@ -149,45 +147,3 @@ pub fn damage_and_experience(
Ok(())
}
pub fn check_mana(book: &AbilityBook, character_status: &mut CharacterStatus) -> Result<bool> {
let mana_costs = book.mana_cost();
Ok(character_status.use_ability(mana_costs as f32))
}
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum AbilityType {
Projectile,
SelfCast,
}
impl Default for AbilityType {
fn default() -> Self {
Self::Projectile
}
}
impl std::str::FromStr for AbilityType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"Projectile" => Ok(AbilityType::Projectile),
"Self-Cast" => Ok(AbilityType::SelfCast),
_ => Err(anyhow::Error::msg(format!(
"Failed parsing AbilityType from {}",
s
))),
}
}
}
impl std::fmt::Display for AbilityType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
AbilityType::Projectile => write!(f, "Projectile"),
AbilityType::SelfCast => write!(f, "Self-Cast"),
}
}
}

View file

@ -1,5 +0,0 @@
pub mod damage_type;
pub mod items;
pub mod prelude;

View file

@ -1,2 +0,0 @@
pub use super::damage_type::DamageType;
pub use super::items::*;

View file

@ -0,0 +1,38 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum AbilityType {
Projectile,
SelfCast,
}
impl Default for AbilityType {
fn default() -> Self {
Self::Projectile
}
}
impl std::str::FromStr for AbilityType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"Projectile" => Ok(AbilityType::Projectile),
"Self-Cast" => Ok(AbilityType::SelfCast),
_ => Err(anyhow::Error::msg(format!(
"Failed parsing AbilityType from {}",
s
))),
}
}
}
impl std::fmt::Display for AbilityType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
AbilityType::Projectile => write!(f, "Projectile"),
AbilityType::SelfCast => write!(f, "Self-Cast"),
}
}
}

View file

@ -1,6 +1,3 @@
use crate::config::save_game::SaveGame;
use crate::items::Rarities;
use crate::items::{ability_addon::AbilityAddonTypes, ability_book::AbilityBook};
use anyhow::Result;
use cgmath::{Vector2, Zero};
use engine::prelude::*;
@ -11,6 +8,10 @@ use std::{
str::FromStr,
};
use crate::components::inventory::Storable;
use crate::config::save_game::SaveGame;
use crate::items::{ability_addon::AbilityAddonTypes, ability_book::AbilityBook, Rarities};
macro_rules! load {
($me: ident, $save_game:ident, $($index:literal,)+) => {
paste::expr! {

View file

@ -2,13 +2,17 @@ use anyhow::Result;
use assetpath::AssetPath;
use engine::prelude::*;
use crate::Game;
use super::super::prelude::*;
use cgmath::Vector3;
use std::{path::Path, sync::Arc};
use crate::{
ability_type::AbilityType,
damage_type::DamageType,
items::{ability_addon::AbilityAddonCollection, ability_book::Ability},
};
use super::statistics::Statistics;
const ABILITY_SUFFIX: &str = ".abil";
create_settings_section!(
@ -112,13 +116,6 @@ impl AbilityLoader {
)?)
}
pub fn create_ability(self) -> Result<Arc<dyn Ability>> {
match self.settings.parameter.ability_type {
AbilityType::Projectile => Ok(Arc::new(Projectile::new(self)?)),
AbilityType::SelfCast => Ok(Arc::new(SelfCast::new(self)?)),
}
}
pub fn name(&self) -> &str {
&self.name
}
@ -186,7 +183,6 @@ impl AbilityLoader {
pub fn create_on_hit_particles2(
&self,
game: &Game,
position: Vector3<f32>,
offset: Vector3<f32>,
particle_system_vulkan_objects: &ParticleSystemVulkanObjects,
@ -200,7 +196,6 @@ impl AbilityLoader {
Some(Self::create_on_hit_particles(
info,
&self.settings.parameter.on_collision_sound,
game,
position,
offset,
particle_system_vulkan_objects,
@ -211,7 +206,6 @@ impl AbilityLoader {
pub fn create_on_hit_particles(
info: ParticleSystemInfo,
on_collision_sound: &str,
game: &Game,
position: Vector3<f32>,
offset: Vector3<f32>,
particle_system_vulkan_objects: &ParticleSystemVulkanObjects,

View file

@ -3,6 +3,8 @@ use engine::prelude::*;
use crate::config::experience::ExperienceSettings;
use super::npc_type::NPCType;
pub struct LevelUpEvent;
pub struct Level {

View file

@ -2,11 +2,13 @@
pub mod macros;
pub mod ability_slots;
pub mod abilityloader;
pub mod attributes;
pub mod character_status;
pub mod crafting_materials;
pub mod inventory;
pub mod item_slots;
pub mod level;
pub mod npc_type;
pub mod statistic_types;
pub mod statistics;

View file

@ -1,9 +1,9 @@
use std::fmt::Display;
use std::str::FromStr;
use anyhow::anyhow;
use anyhow::{anyhow, Result};
use crate::*;
use engine::prelude::*;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct NPCNormal;

View file

@ -3,7 +3,9 @@ use engine::prelude::*;
use std::fmt;
use super::statistics::*;
use super::{attributes::Attributes, statistics::*};
use crate::components::macros::AttributeAssociation;
use crate::{config::items::ItemSettings, items::Rarities};
macro_rules! apply {
(

View file

@ -1,6 +1,18 @@
use engine::prelude::*;
use super::macros::AttributeAssociation;
use crate::{
config::attributes::{
AgilitySettings, AttributeSettings, IntelligenceSettings, StrengthSettings,
},
damage_type::DamageType,
};
use super::{
attributes::{Agility, Attributes, Intelligence, Strength},
item_slots::ItemSlotContainer,
macros::AttributeAssociation,
statistic_types::StatisticType,
};
// --------------- elements ---------------

View file

@ -1,6 +1,6 @@
use engine::prelude::*;
use crate::Attribute;
use crate::components::attributes::Attribute;
create_settings_section!(
AgilitySettings,

View file

@ -1,6 +1,6 @@
use engine::prelude::*;
use crate::NPCType;
use crate::components::npc_type::NPCType;
create_settings_section!(
ExperienceCurveSettings,

View file

@ -1,3 +1,23 @@
#[macro_use]
pub mod create_section {
macro_rules! impl_from_rarity {
($struct_name:ident, $data_type:ty) => {
impl $struct_name {
pub fn from_rarity(&self, rarity: crate::items::Rarities) -> $data_type {
match rarity {
crate::items::Rarities::Common => self.common,
crate::items::Rarities::Uncommon => self.uncommon,
crate::items::Rarities::Magical => self.magical,
crate::items::Rarities::Rare => self.rare,
crate::items::Rarities::Epic => self.epic,
crate::items::Rarities::Legendary => self.legendary,
}
}
}
};
}
}
pub mod abilities;
pub mod attributes;
pub mod experience;

View file

@ -12,6 +12,12 @@ use std::{
use std::sync::Arc;
use crate::{
ability_type::AbilityType, components::inventory::Storable, config::abilities::AbilitySettings,
};
use super::{ItemSystem, Rarities, ToolTipBuilder, Tooltip};
const COOL_DOWN_REDUCTION_CAP: f32 = 0.7;
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
@ -268,10 +274,13 @@ impl AbilityAddon {
pub fn create_tooltip(
&self,
game_handle: &GameHandle,
tooltip_builder: &impl ToolTipBuilder,
position: (i32, i32),
) -> Result<Tooltip> {
let gui = game_handle.gui_builder("gui/xml/ingame/loot/addon_snippet.xml")?;
let gui = GuiBuilder::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path("gui/xml/ingame/loot/addon_snippet.xml"),
)?;
let icon: Arc<Icon> = gui.element("addon_icon")?;
let rarity_label: Arc<Label> = gui.element("rarity_label")?;
@ -290,7 +299,7 @@ impl AbilityAddon {
Ok(Tooltip::new(
grid,
gui,
game_handle.upgrade().engine().gui_handler().clone(),
tooltip_builder.gui_handler().clone(),
))
}
}

View file

@ -4,6 +4,24 @@ use engine::prelude::*;
use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration};
use crate::{
components::{
abilityloader::AbilityLoader, character_status::CharacterStatus,
crafting_materials::CraftingMaterials, inventory::Storable, statistics::Statistics,
},
config::abilities::{AbilityLevel, AbilitySettings},
};
use super::{
ability_addon::{AbilityAddon, AbilityAddonCollection, AbilityAddonTypes},
ItemSystem, Rarities, ToolTipBuilder, Tooltip,
};
pub trait Ability: Send + Sync {
fn data(&self) -> &AbilityLoader;
fn name(&self) -> &str;
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CastInformation {
time: PersistentDuration,
@ -77,21 +95,24 @@ impl AbilityBook {
}
}
pub fn check_mana(&self, character_status: &mut CharacterStatus) -> Result<bool> {
let mana_costs = self.mana_cost();
Ok(character_status.use_ability(mana_costs as f32))
}
#[allow(clippy::too_many_arguments)]
pub fn validate_use(
&mut self,
now: Duration,
animation: &mut Animation,
draw: &mut Draw,
animation_info: &mut AnimationInfo,
character_status: &mut CharacterStatus,
location: &Location,
) -> Result<bool> {
// don't allow anything while being animation locked
if animation_info.is_locked() {
return Ok(false);
}
// if animation_info.is_locked() {
// return Ok(false);
// }
if let Some(cast_information) = &self.last_cast {
let total_cool_down = Duration::from_secs_f32({
@ -105,46 +126,32 @@ impl AbilityBook {
}
}
if !super::check_mana(self, character_status)? {
if !self.check_mana(character_status)? {
return Ok(false);
}
{
// TODO: further separation of animation types (bows, ...)
let animation_type = match self.ability.data().settings.parameter.damage_type {
DamageType::Physical => AnimationType::Attack,
_ => AnimationType::Cast,
};
// {
// // TODO: further separation of animation types (bows, ...)
// let animation_type = match self.ability.data().settings.parameter.damage_type {
// DamageType::Physical => AnimationType::Attack,
// _ => AnimationType::Cast,
// };
animation_info.set_animation(
animation,
draw,
Some(animation_type),
now,
true,
false,
)?;
}
// animation_info.set_animation(
// animation,
// draw,
// Some(animation_type),
// now,
// true,
// false,
// )?;
// }
self.set_cast(now, location);
Ok(true)
}
pub fn execute(
&self,
components: &mut MultiMut<'_>,
owner: Entity,
direction: Vector2<f32>,
game: &GameHandle,
entities: &mut Entities<'_>,
events: &mut ContentEvents<'_>,
) -> Result<()> {
println!("ability book execute");
self.ability
.execute(owner, components, direction, self, game, entities, events)
}
fn set_cast(&mut self, now: Duration, location: &Location) {
self.last_cast = Some(CastInformation {
time: now.into(),
@ -269,11 +276,14 @@ impl AbilityBook {
pub fn create_tooltip(
&self,
game_handle: &GameHandle,
tooltip_builder: &impl ToolTipBuilder,
statistics: &Statistics,
position: (i32, i32),
) -> Result<Tooltip> {
let gui = game_handle.gui_builder("gui/xml/ingame/loot/book_snippet.xml")?;
let gui = GuiBuilder::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path("gui/xml/ingame/loot/book_snippet.xml"),
)?;
let ability_name: Arc<Label> = gui.element("ability_name")?;
let rarity_label: Arc<Label> = gui.element("rarity_label")?;
@ -313,7 +323,7 @@ impl AbilityBook {
Ok(Tooltip::new(
inspector_grid,
gui,
game_handle.upgrade().engine().gui_handler().clone(),
tooltip_builder.gui_handler().clone(),
))
}
}

View file

@ -1,11 +1,22 @@
use anyhow::Result;
use engine::prelude::*;
use std::str::FromStr;
use std::sync::Arc;
use crate::components::statistic_types::StatisticType;
use crate::{
components::{
attributes::Attributes,
inventory::Storable,
statistic_types::{
AgilityStatisticTypes, IntelligenceStatisticTypes, StatisticType,
StrengthStatisticTypes,
},
},
config::items::ItemSettings,
};
use super::Jewel;
use super::{ItemSlots, ItemSystem, Jewel, Rarities, ToolTipBuilder, Tooltip};
#[derive(Debug, PartialEq, Clone)]
pub enum ItemAffix {
@ -211,15 +222,17 @@ impl Item {
pub fn create_tooltip(
&self,
game_handle: &GameHandle,
tooltip_builder: &impl ToolTipBuilder,
attributes: &Attributes,
position: (i32, i32),
) -> Result<Tooltip> {
let (stats, jewels) = ItemAffix::squash(self.affixes.iter());
let count = stats.len() + jewels.len();
let inspector_snippet =
game_handle.gui_builder(&format!("gui/xml/ingame/loot/items/slots_{}.xml", count))?;
let inspector_snippet = GuiBuilder::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path(&format!("gui/xml/ingame/loot/items/slots_{}.xml", count)),
)?;
let item_icon: Arc<Icon> = inspector_snippet.element("item_icon")?;
let slot_label: Arc<Label> = inspector_snippet.element("slot_label")?;
@ -255,8 +268,10 @@ impl Item {
let mut index = Self::INSPECTOR_OFFSET;
for stat in stats {
let stat_type_snippet =
game_handle.gui_snippet("gui/xml/ingame/loot/snippets/stat_type_snippet.xml")?;
let stat_type_snippet = GuiSnippet::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path("gui/xml/ingame/loot/snippets/stat_type_snippet.xml"),
)?;
let stat_type_label: Arc<Label> = stat_type_snippet.element("stat_type")?;
let stat_value_label: Arc<Label> = stat_type_snippet.element("stat_value")?;
@ -270,8 +285,10 @@ impl Item {
}
for jewel in jewels {
let socket_snippet =
game_handle.gui_snippet("gui/xml/ingame/loot/snippets/item_socket_snippet.xml")?;
let socket_snippet = GuiSnippet::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path("gui/xml/ingame/loot/snippets/item_socket_snippet.xml"),
)?;
let socket_icon: Arc<Icon> = socket_snippet.element("socket_icon")?;
let stat_type: Arc<Label> = socket_snippet.element("stat_type")?;
@ -292,7 +309,7 @@ impl Item {
Ok(Tooltip::new(
inspector_grid,
inspector_snippet,
game_handle.upgrade().engine().gui_handler().clone(),
tooltip_builder.gui_handler().clone(),
))
}
}

View file

@ -4,6 +4,8 @@ use engine::prelude::*;
use std::{fmt, slice::Iter};
use crate::config::items::ItemSettings;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ItemSlots {
Helmet,

View file

@ -7,6 +7,20 @@ use std::sync::{Arc, Mutex};
use image::{imageops::FilterType, DynamicImage, ImageBuffer, Pixel, Rgba, RgbaImage};
use crate::components::abilityloader::AbilityLoader;
use crate::components::attributes::{Attribute, Attributes};
use crate::components::inventory::Storable;
use crate::components::statistic_types::{
AgilityStatisticTypes, IntelligenceStatisticTypes, StatisticType, StrengthStatisticTypes,
};
use crate::config::abilities::AbilitySettings;
use crate::config::attributes::AttributeSettings;
use crate::config::items::ItemSettings;
use super::ability_addon::{AbilityAddon, AbilityAddonTypes};
use super::ability_book::{Ability, AbilityBook};
use super::{Item, ItemAffix, ItemSlots, Jewel, Rarities};
#[derive(Debug, Clone, PartialEq)]
pub enum Loot {
Item(Item),

View file

@ -3,6 +3,15 @@ use std::{
sync::Arc,
};
use anyhow::Result;
use engine::prelude::*;
use super::{Rarities, ToolTipBuilder, Tooltip};
use crate::{
components::{attributes::Attribute, inventory::Storable, statistic_types::StatisticType},
config::items::ItemSettings,
};
#[derive(Clone, Debug)]
pub struct Jewel {
pub rarity: Rarities,
@ -51,10 +60,14 @@ impl Jewel {
pub fn create_tooltip(
&self,
game_handle: &GameHandle,
tooltip_builder: &impl ToolTipBuilder,
item_settings: &ItemSettings,
position: (i32, i32),
) -> Result<Tooltip> {
let inspector_snippet = game_handle.gui_builder("gui/xml/ingame/loot/jewel_tooltip.xml")?;
let inspector_snippet: Arc<GuiBuilder> = GuiBuilder::new(
tooltip_builder.gui_handler(),
&tooltip_builder.asset_path("gui/xml/ingame/loot/jewel_tooltip.xml"),
)?;
let main_grid: Arc<Grid> = inspector_snippet.element("main_grid")?;
main_grid.change_position_unscaled(position.0, position.1)?;
@ -71,9 +84,6 @@ impl Jewel {
jewel_icon.set_icon(&self.icon())?;
rarity_label.set_text(format!("{} ({})", self.rarity, self.level))?;
let game = game_handle.upgrade();
let item_settings = &game.item_settings;
attribute_type.set_text({
let mut s = self.attribute.to_string();
s.replace_range(
@ -98,7 +108,7 @@ impl Jewel {
Ok(Tooltip::new(
main_grid,
inspector_snippet,
game.engine().gui_handler().clone(),
tooltip_builder.gui_handler().clone(),
))
}
}

View file

@ -1,10 +1,11 @@
use std::sync::Arc;
use anyhow::Result;
use engine::prelude::*;
use crate::components::inventory::Storable;
use super::{ItemSystem, Rarities};
use super::{ItemSystem, Rarities, ToolTipBuilder};
#[derive(Clone)]
pub struct MapItem {
@ -26,7 +27,7 @@ impl MapItem {
pub fn create_tooltip(
&self,
_game_handle: &GameHandle,
_tooltip_builder: &impl ToolTipBuilder,
_position: (i32, i32),
) -> Result<Arc<GuiBuilder>> {
todo!()

View file

@ -1,7 +1,13 @@
use anyhow::{bail, Result};
use assetpath::AssetPath;
use engine::prelude::*;
use std::sync::Arc;
pub trait ToolTipBuilder {
fn asset_path(&self, s: &str) -> AssetPath;
fn gui_handler(&self) -> &Arc<GuiHandler>;
}
pub struct FittingResult {
pub fit: bool,
pub start: i32,

View file

@ -1,5 +1,7 @@
#[macro_use]
pub mod components;
pub mod ability_type;
pub mod config;
pub mod damage_type;
pub mod items;