Complete section 5.27

This commit is contained in:
Timothy Warren 2022-01-31 09:48:44 -05:00
parent 5a0f7b2b05
commit 92316bde1b
4 changed files with 158 additions and 8 deletions

View File

@ -78,11 +78,13 @@ pub fn spell_trigger(creator: Option<Entity>, spell: Entity, targets: &Targets,
} }
} }
event_trigger(creator, spell, &targeting, ecs); event_trigger(creator, spell, &targeting, ecs);
if self_destruct && creator.is_some() { if self_destruct {
if let Some(creator) = creator {
ecs.entities() ecs.entities()
.delete(creator.unwrap()) .delete(creator)
.expect("Unable to delete owner"); .expect("Unable to delete owner");
} }
}
} }
pub fn trigger(creator: Option<Entity>, trigger: Entity, targets: &Targets, ecs: &mut World) { pub fn trigger(creator: Option<Entity>, trigger: Entity, targets: &Targets, ecs: &mut World) {

View File

@ -6,6 +6,7 @@ mod prop_structs;
mod rawmaster; mod rawmaster;
mod spawn_table_structs; mod spawn_table_structs;
mod spell_structs; mod spell_structs;
mod weapon_traits;
use std::sync::Mutex; use std::sync::Mutex;
@ -19,6 +20,7 @@ use prop_structs::*;
pub use rawmaster::*; pub use rawmaster::*;
use spawn_table_structs::*; use spawn_table_structs::*;
pub use spell_structs::Spell; pub use spell_structs::Spell;
pub use weapon_traits::*;
#[derive(Deserialize, Default, Debug)] #[derive(Deserialize, Default, Debug)]
pub struct Raws { pub struct Raws {
@ -29,6 +31,7 @@ pub struct Raws {
pub loot_tables: Vec<LootTable>, pub loot_tables: Vec<LootTable>,
pub faction_table: Vec<FactionInfo>, pub faction_table: Vec<FactionInfo>,
pub spells: Vec<Spell>, pub spells: Vec<Spell>,
pub weapon_traits: Vec<WeaponTrait>,
} }
embedded_resource!(RAW_FILE, "../raws/spawns.json"); embedded_resource!(RAW_FILE, "../raws/spawns.json");

View File

@ -5,11 +5,11 @@ use ::rltk::{console, RandomNumberGenerator, RGB};
use ::specs::prelude::*; use ::specs::prelude::*;
use ::specs::saveload::{MarkedBuilder, SimpleMarker}; use ::specs::saveload::{MarkedBuilder, SimpleMarker};
use super::{Raws, Reaction, SpawnTableEntry, RAWS};
use crate::components::*; use crate::components::*;
use crate::gamesystem::{mana_at_level, npc_hp}; use crate::gamesystem::{mana_at_level, npc_hp};
use crate::map::MasterDungeonMap; use crate::map::MasterDungeonMap;
use crate::random_table::{MasterTable, RandomTable}; use crate::random_table::{MasterTable, RandomTable};
use crate::raws::{Raws, Reaction, RAWS};
pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) { pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
lazy_static! { lazy_static! {
@ -51,15 +51,148 @@ pub struct RawMaster {
spell_index: HashMap<String, usize>, spell_index: HashMap<String, usize>,
} }
struct NewMagicItem {
name: String,
bonus: i32,
}
impl RawMaster { impl RawMaster {
pub fn empty() -> RawMaster { pub fn empty() -> RawMaster {
RawMaster::default() RawMaster::default()
} }
fn append_magic_template(items_to_build: &mut Vec<NewMagicItem>, item: &super::Item) {
if let Some(template) = &item.template_magic {
if item.weapon.is_some() || item.wearable.is_some() {
if template.include_cursed {
items_to_build.push(NewMagicItem {
name: item.name.clone(),
bonus: -1,
});
}
for bonus in template.bonus_min..=template.bonus_max {
items_to_build.push(NewMagicItem {
name: item.name.clone(),
bonus,
});
}
} else {
console::log(format!(
"{} is marked as templated, but isn't a weapon or armor.",
item.name
));
}
}
}
fn build_base_magic_item(&self, nmw: &NewMagicItem) -> super::Item {
let base_item_index = self.item_index[&nmw.name];
let mut base_item_copy = self.raws.items[base_item_index].clone();
base_item_copy.vendor_category = None; // Don't sell magic items!
if nmw.bonus == -1 {
base_item_copy.name = format!("{} -1", nmw.name);
} else {
base_item_copy.name = format!("{} +{}", nmw.name, nmw.bonus);
}
base_item_copy.magic = Some(super::MagicItem {
class: match nmw.bonus {
2 | 3 | 4 => "rare",
5 => "legendary",
_ => "common",
}
.to_string(),
naming: base_item_copy
.template_magic
.as_ref()
.unwrap()
.unidentified_name
.clone(),
cursed: if nmw.bonus == -1 { Some(true) } else { None },
});
if let Some(initiative_penalty) = base_item_copy.initiative_penalty.as_mut() {
*initiative_penalty -= nmw.bonus as f32;
}
if let Some(base_value) = base_item_copy.base_value.as_mut() {
*base_value += (nmw.bonus as f32 + 1.0) * 50.0;
}
if let Some(mut weapon) = base_item_copy.weapon.as_mut() {
weapon.hit_bonus += nmw.bonus;
let (n, die, plus) = parse_dice_string(&weapon.base_damage);
let final_bonus = plus + nmw.bonus;
if final_bonus > 0 {
weapon.base_damage = format!("{}d{}+{}", n, die, final_bonus);
} else {
weapon.base_damage = format!("{}d{}-{}", n, die, i32::abs(final_bonus));
}
}
if let Some(mut armor) = base_item_copy.wearable.as_mut() {
armor.armor_class += nmw.bonus as f32;
}
base_item_copy
}
fn build_magic_weapon_or_armor(&mut self, items_to_build: &[NewMagicItem]) {
for nmw in items_to_build.iter() {
let base_item_copy = self.build_base_magic_item(nmw);
let real_name = base_item_copy.name.clone();
self.raws.items.push(base_item_copy);
self.item_index
.insert(real_name.clone(), self.raws.items.len() - 1);
self.raws.spawn_table.push(SpawnTableEntry {
name: real_name.clone(),
weight: 10 - i32::abs(nmw.bonus),
min_depth: 1 + i32::abs((nmw.bonus - 1) * 3),
max_depth: 100,
add_map_depth_to_weight: None,
});
}
}
fn build_traited_weapons(&mut self, items_to_build: &[NewMagicItem]) {
items_to_build
.iter()
.filter(|i| i.bonus > 0)
.for_each(|nmw| {
for wt in self.raws.weapon_traits.iter() {
let mut base_item_copy = self.build_base_magic_item(nmw);
if let Some(mut weapon) = base_item_copy.weapon.as_mut() {
base_item_copy.name = format!("{} {}", wt.name, base_item_copy.name);
if let Some(base_value) = base_item_copy.base_value.as_mut() {
*base_value *= 2.0;
}
weapon.proc_chance = Some(0.25);
weapon.proc_effects = Some(wt.effects.clone());
let real_name = base_item_copy.name.clone();
self.raws.items.push(base_item_copy);
self.item_index
.insert(real_name.clone(), self.raws.items.len() - 1);
self.raws.spawn_table.push(SpawnTableEntry {
name: real_name.clone(),
weight: 9 - i32::abs(nmw.bonus),
min_depth: 2 + i32::abs((nmw.bonus - 1) * 3),
max_depth: 100,
add_map_depth_to_weight: None,
});
}
}
});
}
pub fn load(&mut self, raws: Raws) { pub fn load(&mut self, raws: Raws) {
self.raws = raws; self.raws = raws;
self.item_index = HashMap::new(); self.item_index = HashMap::new();
let mut used_names: HashSet<String> = HashSet::new(); let mut used_names: HashSet<String> = HashSet::new();
let mut items_to_build: Vec<NewMagicItem> = Vec::new();
for (i, item) in self.raws.items.iter().enumerate() { for (i, item) in self.raws.items.iter().enumerate() {
if used_names.contains(&item.name) { if used_names.contains(&item.name) {
console::log(format!( console::log(format!(
@ -69,6 +202,8 @@ impl RawMaster {
} }
self.item_index.insert(item.name.clone(), i); self.item_index.insert(item.name.clone(), i);
used_names.insert(item.name.clone()); used_names.insert(item.name.clone());
RawMaster::append_magic_template(&mut items_to_build, item);
} }
for (i, mob) in self.raws.mobs.iter().enumerate() { for (i, mob) in self.raws.mobs.iter().enumerate() {
if used_names.contains(&mob.name) { if used_names.contains(&mob.name) {
@ -94,7 +229,7 @@ impl RawMaster {
for spawn in self.raws.spawn_table.iter() { for spawn in self.raws.spawn_table.iter() {
if !used_names.contains(&spawn.name) { if !used_names.contains(&spawn.name) {
console::log(format!( console::log(format!(
"WARNING - Spawn tables references unspecified entity {}", "WARNING - Spawn tables references unspecified entity [{}]",
spawn.name spawn.name
)); ));
} }
@ -122,6 +257,9 @@ impl RawMaster {
for (i, spell) in self.raws.spells.iter().enumerate() { for (i, spell) in self.raws.spells.iter().enumerate() {
self.spell_index.insert(spell.name.clone(), i); self.spell_index.insert(spell.name.clone(), i);
} }
self.build_magic_weapon_or_armor(&items_to_build);
self.build_traited_weapons(&items_to_build);
} }
} }
@ -813,8 +951,6 @@ pub fn spawn_named_spell(raws: &RawMaster, ecs: &mut World, key: &str) -> Option
} }
pub fn get_spawn_table_for_depth(raws: &RawMaster, depth: i32) -> MasterTable { pub fn get_spawn_table_for_depth(raws: &RawMaster, depth: i32) -> MasterTable {
use super::SpawnTableEntry;
let available_options: Vec<&SpawnTableEntry> = raws let available_options: Vec<&SpawnTableEntry> = raws
.raws .raws
.spawn_table .spawn_table

View File

@ -0,0 +1,9 @@
use std::collections::HashMap;
use ::serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct WeaponTrait {
pub name: String,
pub effects: HashMap<String, String>,
}