more framework for spells
This commit is contained in:
parent
76c74df028
commit
02a4f33d11
8 changed files with 95 additions and 36 deletions
|
|
@ -200,9 +200,16 @@ pub struct KnownSpell {
|
|||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct KnownSpells {
|
||||
pub spells: Vec<KnownSpell>,
|
||||
pub list: Vec<KnownSpell>,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct GrantsSpell {
|
||||
pub spell: String,
|
||||
}
|
||||
|
||||
// TODO: GrantsIntrinsic, Intrinsics, etc. ? Done the same way as spells?
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Attributes {
|
||||
pub strength: Attribute,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// --- GUI ---
|
||||
pub const CHAR_CREATE_HEADER: &str = "Who are you? [Aa-Zz]";
|
||||
pub const ANCESTRY_INFO_HEADER: &str = "Your ancestry grants...";
|
||||
pub const CLASS_INFO_HEADER: &str = "Your class grants...";
|
||||
// --- ANCESTRY RENDERABLES ---
|
||||
|
|
@ -13,13 +14,35 @@ pub const ELF_SPEED_BONUS: i32 = 1;
|
|||
pub const ELF_TELEPATH_RANGE: i32 = 6;
|
||||
pub const DWARF_DEFENCE_MOD: i32 = 1;
|
||||
pub const CATFOLK_SPEED_BONUS: i32 = 2;
|
||||
// --- CLASS STARTING ITEMS ---
|
||||
// --- ANCESTRY ATTRIBUTE MAXIMUMS ---
|
||||
pub const TOTAL_ATTRIBUTE_POINTS_MAXIMUM: i32 = 75;
|
||||
pub const HUMAN_MAX_ATTR: [i32; 6] = [19, 19, 19, 19, 19, 19];
|
||||
pub const ELF_MAX_ATTR: [i32; 6] = [15, 18, 15, 20, 20, 18];
|
||||
pub const DWARF_MAX_ATTR: [i32; 6] = [19, 17, 20, 16, 16, 16];
|
||||
pub const GNOME_MAX_ATTR: [i32; 6] = [16, 18, 16, 20, 18, 18];
|
||||
pub const CATFOLK_MAX_ATTR: [i32; 6] = [16, 20, 16, 16, 18, 20];
|
||||
pub const UNKNOWN_MAX_ATTR: [i32; 6] = [18, 18, 18, 18, 18, 18];
|
||||
// --- CLASS MIN ATTRIBUTES ---
|
||||
pub const FIGHTER_MIN_ATTR: (i32, i32, i32, i32, i32, i32) = (10, 8, 10, 6, 6, 8);
|
||||
pub const ROGUE_MIN_ATTR: (i32, i32, i32, i32, i32, i32) = (8, 10, 8, 6, 8, 10);
|
||||
pub const WIZARD_MIN_ATTR: (i32, i32, i32, i32, i32, i32) = (6, 8, 6, 10, 10, 8);
|
||||
pub const VILLAGER_MIN_ATTR: (i32, i32, i32, i32, i32, i32) = (6, 6, 6, 6, 6, 6);
|
||||
// --- CLASS ATTRIBUTE IMPROVE CHANCES ---
|
||||
pub const FIGHTER_IMPR_CHANCE: [i32; 6] = [30, 20, 30, 6, 7, 7];
|
||||
pub const ROGUE_IMPR_CHANCE: [i32; 6] = [18, 30, 20, 9, 8, 15];
|
||||
pub const WIZARD_IMPR_CHANCE: [i32; 6] = [10, 15, 20, 30, 15, 10];
|
||||
pub const VILLAGER_IMPR_CHANCE: [i32; 6] = [15, 15, 25, 15, 15, 15];
|
||||
// --- CLASS STARTING ITEMS --- ## If any of these are changed, update ancestry infotext in src/gui/character_creation.rs.
|
||||
pub const FIGHTER_STARTING_FOOD: &str = "1d2+1";
|
||||
pub const FIGHTER_STARTING_WEAPON: &str = "equip_shortsword";
|
||||
pub const FIGHTER_STARTING_ARMOUR: &str = "equip_body_ringmail";
|
||||
pub const FIGHTER_STARTING_SHIELD: &str = "equip_mediumshield";
|
||||
pub const ROGUE_STARTING_FOOD: &str = "1d2+2";
|
||||
pub const ROGUE_STARTING_WEAPON: &str = "equip_rapier";
|
||||
pub const ROGUE_STARTING_ARMOUR: &str = "equip_body_weakleather";
|
||||
pub const WIZARD_STARTING_FOOD: &str = "1d2+1";
|
||||
pub const WIZARD_STARTING_WEAPON: &str = "equip_dagger";
|
||||
pub const WIZARD_STARTING_ARMOUR: &str = "equip_back_protection";
|
||||
pub const WIZARD_MAX_SCROLL_LVL: i32 = 3;
|
||||
pub const WIZARD_SCROLL_AMOUNT: &str = "1d3";
|
||||
pub const WIZARD_POTION_AMOUNT: &str = "1d3-1";
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ use crate::{
|
|||
RunState,
|
||||
SingleActivation,
|
||||
BUC,
|
||||
GrantsSpell,
|
||||
KnownSpell,
|
||||
KnownSpells,
|
||||
};
|
||||
use crate::config::messages::*;
|
||||
use rltk::prelude::*;
|
||||
|
|
@ -93,13 +96,22 @@ fn event_trigger(source: Option<Entity>, entity: Entity, target: &Targets, ecs:
|
|||
particles::handle_line_particles(ecs, entity, &target);
|
||||
let (logger, restored_nutrition) = handle_restore_nutrition(ecs, &mut event, logger);
|
||||
let (logger, magic_mapped) = handle_magic_mapper(ecs, &mut event, logger);
|
||||
let (logger, granted_spell) = handle_grant_spell(ecs, &mut event, logger);
|
||||
let (logger, removed_curse) = handle_remove_curse(ecs, &mut event, logger);
|
||||
let (logger, identified) = handle_identify(ecs, &mut event, logger);
|
||||
let (logger, healed) = handle_healing(ecs, &mut event, logger);
|
||||
let (logger, damaged) = handle_damage(ecs, &mut event, logger);
|
||||
let (logger, confused) = handle_confusion(ecs, &mut event, logger);
|
||||
//let (logger, dug) = handle_dig(ecs, &mut event, logger); -- NYI i.e. Wand of Digging
|
||||
did_something |= restored_nutrition || magic_mapped || healed || damaged || confused || removed_curse || identified;
|
||||
did_something |=
|
||||
restored_nutrition ||
|
||||
magic_mapped ||
|
||||
granted_spell ||
|
||||
healed ||
|
||||
damaged ||
|
||||
confused ||
|
||||
removed_curse ||
|
||||
identified;
|
||||
|
||||
if event.log {
|
||||
logger.log();
|
||||
|
|
@ -145,6 +157,17 @@ fn handle_magic_mapper(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
|||
return (logger, false);
|
||||
}
|
||||
|
||||
fn handle_grant_spell(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
||||
if let Some(granted_spell) = ecs.read_storage::<GrantsSpell>().get(event.entity) {
|
||||
if let Some(known_spells) = ecs.write_storage::<KnownSpells>().get_mut(event.source.unwrap()) {
|
||||
// TODO: Check if the player knows *this* spell, and add it if not.
|
||||
} else {
|
||||
// TODO: Grant the KnownSpells component, and then add the spell.
|
||||
}
|
||||
}
|
||||
return (logger, false);
|
||||
}
|
||||
|
||||
fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> (gamelog::Logger, bool) {
|
||||
if let Some(healing_item) = ecs.read_storage::<ProvidesHealing>().get(event.entity) {
|
||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||
|
|
@ -255,21 +278,23 @@ fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::
|
|||
}
|
||||
let mut to_identify: Vec<(Entity, String)> = Vec::new();
|
||||
let mut beatitudes = ecs.write_storage::<Beatitude>();
|
||||
for (e, _i, _bp, _o, name) in (
|
||||
let obfuscated = ecs.read_storage::<ObfuscatedName>();
|
||||
for (e, _i, _bp, name) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Item>(),
|
||||
&ecs.read_storage::<InBackpack>(),
|
||||
&ecs.read_storage::<ObfuscatedName>(),
|
||||
&ecs.read_storage::<Name>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_e, _i, bp, _o, name)| {
|
||||
bp.owner == event.source.unwrap() &&
|
||||
(!dm.identified_items.contains(&name.name.clone()) ||
|
||||
!beatitudes
|
||||
.filter(|(e, _i, bp, name)| {
|
||||
let in_this_backpack = bp.owner == event.source.unwrap();
|
||||
let has_obfuscated_name = obfuscated.get(*e).is_some();
|
||||
let already_identified = dm.identified_items.contains(&name.name.clone());
|
||||
let known_beatitude = beatitudes
|
||||
.get(event.source.unwrap())
|
||||
.map(|beatitude| beatitude.known)
|
||||
.unwrap_or(true))
|
||||
.map(|b| b.known)
|
||||
.unwrap_or(true);
|
||||
return in_this_backpack && (has_obfuscated_name || !already_identified || !known_beatitude);
|
||||
}) {
|
||||
to_identify.push((e, name.name.clone()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use super::{ Skill, Skills };
|
||||
use crate::gui::{ Ancestry, Class };
|
||||
use crate::config::entity;
|
||||
use crate::config::char_create::*;
|
||||
use rltk::prelude::*;
|
||||
use std::cmp::max;
|
||||
|
||||
|
|
@ -84,25 +85,25 @@ pub fn get_attribute_rolls(
|
|||
ancestry: Ancestry
|
||||
) -> (i32, i32, i32, i32, i32, i32) {
|
||||
let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class {
|
||||
Class::Fighter => (10, 8, 10, 6, 6, 8),
|
||||
Class::Rogue => (8, 10, 8, 6, 8, 10),
|
||||
Class::Wizard => (6, 8, 6, 10, 10, 8),
|
||||
Class::Villager => (6, 6, 6, 6, 6, 6),
|
||||
Class::Fighter => FIGHTER_MIN_ATTR,
|
||||
Class::Rogue => ROGUE_MIN_ATTR,
|
||||
Class::Wizard => WIZARD_MIN_ATTR,
|
||||
Class::Villager => VILLAGER_MIN_ATTR,
|
||||
};
|
||||
let mut remaining_points = 75 - (str + dex + con + int + wis + cha);
|
||||
let mut remaining_points = TOTAL_ATTRIBUTE_POINTS_MAXIMUM - (str + dex + con + int + wis + cha);
|
||||
let improve_chance: [i32; 6] = match class {
|
||||
Class::Fighter => [30, 20, 30, 6, 7, 7],
|
||||
Class::Rogue => [18, 30, 20, 9, 8, 15],
|
||||
Class::Wizard => [10, 15, 20, 30, 15, 10],
|
||||
Class::Villager => [15, 15, 25, 15, 15, 15],
|
||||
Class::Fighter => FIGHTER_IMPR_CHANCE,
|
||||
Class::Rogue => ROGUE_IMPR_CHANCE,
|
||||
Class::Wizard => WIZARD_IMPR_CHANCE,
|
||||
Class::Villager => VILLAGER_IMPR_CHANCE,
|
||||
};
|
||||
let ancestry_maximums: [i32; 6] = match ancestry {
|
||||
Ancestry::Human => [19, 19, 19, 19, 19, 19], // 114
|
||||
Ancestry::Elf => [15, 18, 15, 20, 20, 18], // 106
|
||||
Ancestry::Dwarf => [19, 17, 20, 16, 16, 16], // 106
|
||||
Ancestry::Gnome => [16, 18, 16, 20, 18, 18], // 106
|
||||
Ancestry::Catfolk => [16, 20, 16, 16, 18, 20], // 106
|
||||
_ => [18, 18, 18, 18, 18, 18],
|
||||
Ancestry::Human => HUMAN_MAX_ATTR, // 114
|
||||
Ancestry::Elf => ELF_MAX_ATTR, // 106
|
||||
Ancestry::Dwarf => DWARF_MAX_ATTR, // 106
|
||||
Ancestry::Gnome => GNOME_MAX_ATTR, // 106
|
||||
Ancestry::Catfolk => CATFOLK_MAX_ATTR, // 106
|
||||
_ => UNKNOWN_MAX_ATTR,
|
||||
};
|
||||
let improve_table = crate::random_table::RandomTable
|
||||
::new()
|
||||
|
|
|
|||
|
|
@ -64,25 +64,25 @@ lazy_static! {
|
|||
m.insert(
|
||||
"fighter".to_string(),
|
||||
vec![
|
||||
"a longsword, ring mail, and 1d2+1 food".to_string(),
|
||||
format!("a longsword, ring mail, and {} food", FIGHTER_STARTING_FOOD),
|
||||
"10 str, 8 dex, 10 con, 6 int, 6 wis, 8 cha".to_string(),
|
||||
"and 27 random stat points".to_string()]);
|
||||
m.insert(
|
||||
"rogue".to_string(),
|
||||
vec![
|
||||
"a rapier, leather armour, and 1d2+2 food".to_string(),
|
||||
format!("a rapier, leather armour, and {} food", ROGUE_STARTING_FOOD),
|
||||
"8 str, 10 dex, 8 con, 6 int, 8 wis, 10 cha".to_string(),
|
||||
"and 35 random stat points".to_string()]);
|
||||
m.insert(
|
||||
"wizard".to_string(),
|
||||
vec![
|
||||
"a dagger, random scrolls/potions, and 1d2+1 food".to_string(),
|
||||
format!("a dagger, random scrolls/potions, and {} food", WIZARD_STARTING_FOOD),
|
||||
"6 str, 8 dex, 6 con, 10 int, 10 wis, 8 cha".to_string(),
|
||||
"and 17 random stat points".to_string()]);
|
||||
m.insert(
|
||||
"villager".to_string(),
|
||||
vec![
|
||||
"the first weapon you could find, and 1d3+2 food".to_string(),
|
||||
format!("the first weapon you could find, and {} food", VILLAGER_STARTING_FOOD),
|
||||
"6 str, 6 dex, 6 con, 6 int, 6 wis, 6 cha".to_string(),
|
||||
"and 39 random stat points".to_string()]);
|
||||
return m;
|
||||
|
|
@ -109,7 +109,7 @@ pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
|||
let mut y = 11;
|
||||
let column_width = 20;
|
||||
|
||||
ctx.print_color(x, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Who are you? [Aa-Zz]");
|
||||
ctx.print_color(x, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), CHAR_CREATE_HEADER);
|
||||
y += 2;
|
||||
|
||||
if let RunState::CharacterCreation { ancestry, class } = *runstate {
|
||||
|
|
@ -313,7 +313,7 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
|||
let mut spells = ecs.write_storage::<KnownSpells>();
|
||||
spells
|
||||
.insert(player, KnownSpells {
|
||||
spells: vec![KnownSpell { display_name: "zap".to_string(), mana_cost: 1 }],
|
||||
list: vec![KnownSpell { display_name: "zap".to_string(), mana_cost: 1 }],
|
||||
})
|
||||
.expect("Unable to insert known spells component");
|
||||
}
|
||||
|
|
@ -386,12 +386,12 @@ fn get_starting_inventory(class: Class, rng: &mut RandomNumberGenerator) -> (Vec
|
|||
}
|
||||
Class::Rogue => {
|
||||
starting_food = ROGUE_STARTING_FOOD;
|
||||
equipped = vec!["equip_rapier".to_string(), "equip_body_weakleather".to_string()];
|
||||
equipped = vec![ROGUE_STARTING_WEAPON.to_string(), ROGUE_STARTING_ARMOUR.to_string()];
|
||||
carried = vec!["equip_dagger".to_string(), "equip_dagger".to_string()];
|
||||
}
|
||||
Class::Wizard => {
|
||||
starting_food = WIZARD_STARTING_FOOD;
|
||||
equipped = vec!["equip_dagger".to_string(), "equip_back_protection".to_string()];
|
||||
equipped = vec![WIZARD_STARTING_WEAPON.to_string(), WIZARD_STARTING_ARMOUR.to_string()];
|
||||
pick_random_table_item(rng, &mut carried, "scrolls", WIZARD_SCROLL_AMOUNT, Some(WIZARD_MAX_SCROLL_LVL));
|
||||
pick_random_table_item(rng, &mut carried, "potions", WIZARD_POTION_AMOUNT, Some(WIZARD_MAX_SCROLL_LVL));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Known Spells");
|
||||
y += 1;
|
||||
let mut index = 1;
|
||||
for spell in known_spells.spells.iter() {
|
||||
for spell in known_spells.list.iter() {
|
||||
ctx.print_color(72, y, RGB::named(YELLOW), RGB::named(BLACK), &format!("{}", index));
|
||||
ctx.print_color(
|
||||
74,
|
||||
|
|
|
|||
|
|
@ -700,6 +700,7 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.register::<ProvidesRemoveCurse>();
|
||||
gs.ecs.register::<ProvidesIdentify>();
|
||||
gs.ecs.register::<KnownSpells>();
|
||||
gs.ecs.register::<GrantsSpell>();
|
||||
gs.ecs.register::<ParticleLifetime>();
|
||||
gs.ecs.register::<SpawnParticleSimple>();
|
||||
gs.ecs.register::<SpawnParticleBurst>();
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ pub fn save_game(ecs: &mut World) {
|
|||
Equippable,
|
||||
Equipped,
|
||||
Faction,
|
||||
GrantsSpell,
|
||||
GrantsXP,
|
||||
HasAncestry,
|
||||
HasClass,
|
||||
|
|
@ -203,6 +204,7 @@ pub fn load_game(ecs: &mut World) {
|
|||
Equippable,
|
||||
Equipped,
|
||||
Faction,
|
||||
GrantsSpell,
|
||||
GrantsXP,
|
||||
HasAncestry,
|
||||
HasClass,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue