i did some stuff, honestly it starts to build pretty well if i might sayy

This commit is contained in:
Rusty Striker 2024-09-28 20:13:11 +03:00
parent 22319e84a1
commit 9189d9cd88
Signed by: RustyStriker
GPG key ID: 87E4D691632DFF15
22 changed files with 689 additions and 176 deletions

View file

@ -0,0 +1,80 @@
use serde::{Deserialize, Serialize};
use crate::game::{action::GameEntry, chat_message::ChatMessage};
#[derive(Serialize, Deserialize)]
pub enum PEntry {
Weapon(Weapon),
Consumable(Consumable),
Spell(Spell),
}
impl GameEntry for PEntry {
fn display_name(&self) -> String {
match self {
PEntry::Weapon(weapon) => weapon.name.clone(),
PEntry::Consumable(consumable) => consumable.name.clone(),
PEntry::Spell(spell) => spell.name.clone(),
}
}
fn load(entry: &str) -> Option<PEntry> {
println!("loading {}", entry);
let json = std::fs::read_to_string(format!("assets/pf2r/{}.json", entry)).ok()?;
println!("{}", &json);
if entry.starts_with("weapon/") {
serde_json::from_str::<Weapon>(&json).map(|w| PEntry::Weapon(w)).ok()
}
else if entry.starts_with("spell/") {
serde_json::from_str::<Spell>(&json).map(|s| PEntry::Spell(s)).ok()
}
else if entry.starts_with("consumable/") {
serde_json::from_str::<Consumable>(&json).map(|s| PEntry::Consumable(s)).ok()
}
else {
None
}
}
fn to_chat(&self, source: &str) -> ChatMessage {
ChatMessage {
text: format!("{} - it might be a {{weapon/short_bow}} it might not", self.display_name()),
roll: None,
roll_target: None,
actions: None,
source: String::from(source),
targets: None,
}
}
fn all(_filter: Option<&str>) -> Vec<String> {
todo!()
}
}
#[derive(Serialize, Deserialize, Default)]
pub struct Weapon {
pub name: String,
pub two_handed: bool,
pub one_handed: bool,
pub melee_reach: i32,
pub ranged_reach: i32,
// this is a weird thing but suffices for now, as it is expected as a string of `1d4 2 2d6`
pub damage: String,
}
#[derive(Serialize, Deserialize, Default)]
pub struct Consumable {
name: String,
traits: Vec<String>,
/// Price in copper
price: i32,
bulk: i32,
desc: String,
}
#[derive(Serialize, Deserialize, Default)]
pub struct Spell {
name: String,
actions: i32,
damage: String,
damage_type: String,
}

View file

@ -1,13 +1,17 @@
use crate::game::{action::{ActionDefinition, ActionResult, GameEntry}, character_sheet::*, chat_message::{ChatMessage, RollDialogOption}};
use tavern_macros::CharacterSheet;
use crate::game::character_sheet::*;
pub mod entry;
use entry::{PEntry, Weapon};
#[derive(Default, CharacterSheet)]
pub struct Pathfinder2rCharacterSheet {
// Genral stuff
#[Input("Name")]
name: String,
#[Input("Items")]
items: String,
#[Input("Weapons")]
#[InputExpr(set_items, get_items)]
weapon: [Option<Weapon>; 2],
// Attributes
#[Seperator]
#[Input("Strength")]
@ -42,3 +46,81 @@ pub struct Pathfinder2rCharacterSheet {
// TODO: Add more skills
// TODO: Also add all the rest of the sheet items
}
impl Pathfinder2rCharacterSheet {
fn set_items(&mut self, entry: EntryType) {
if let EntryType::Array(a) = entry {
let ws: Vec<PEntry> = a
.iter()
.map(|e| PEntry::load(&e.as_text()))
.flatten()
.collect();
self.weapon = [None, None];
for w in ws {
if let PEntry::Weapon(w) = w {
if self.weapon[0].is_none() {
self.weapon[0] = Some(w);
} else if self.weapon[1].is_none() {
self.weapon[1] = Some(w);
break;
}
}
}
}
else {
let s = entry.as_text();
if let Some(PEntry::Weapon(w)) = PEntry::load(&s) {
self.weapon[0] = Some(w);
self.weapon[1] = None;
}
}
}
fn get_items(&self) -> EntryType {
EntryType::Array(
self.weapon
.iter()
.flatten()
.map(|w| EntryType::Text(w.name.clone()))
.collect(),
)
}
}
impl Character<PEntry> for Pathfinder2rCharacterSheet {
fn use_action(&mut self, entry: &PEntry, action: &ActionResult) -> ChatMessage {
match entry {
PEntry::Weapon(_) => ChatMessage {
text: String::from("Attack"),
roll: Some(vec![RollDialogOption { name: String::from("pierce"), dice_type: 4, dice_amount: 1, constant: 0, extra: String::new(), enabled: true }]),
roll_target: Some(10),
actions: Some(vec!["damage".to_string(), "double".to_string()]),
source: self.name.clone(),
targets: None,
},
PEntry::Consumable(_consumable) => if action.name == "consume" {
ChatMessage {
text: "Heal".to_string(),
roll: Some(vec![RollDialogOption { name: "heal".to_string(), dice_type: 6, dice_amount: 1, constant: 0, extra: String::new(), enabled: true }]),
roll_target: None,
actions: Some(vec!["heal".to_string()]),
source: self.name.clone(),
targets: None,
}
} else { todo!() },
PEntry::Spell(_spell) => todo!(),
}
}
fn actions(&self, entry: &PEntry) -> Vec<ActionDefinition> {
let v;
match entry {
PEntry::Weapon(_) =>
// should technically check if the item is in the user's packpack or something
// but for now just return a constant list
v = vec![ ("wield", 0), ("attack", 1), ("drop", 0), ("stow", 0) ],
PEntry::Consumable(_) => v = vec![("consume", 0), ("stow", 0), ("drop", 0)],
PEntry::Spell(_) => v = vec![("cast", 1)],
};
v.iter()
.map(|s| ActionDefinition { name: s.0.to_string(), targets: s.1 })
.collect()
}
}