initial: character creation
This commit is contained in:
parent
454a8c7028
commit
40f9d117f3
8 changed files with 359 additions and 73 deletions
|
|
@ -137,6 +137,33 @@
|
||||||
"flags": ["EQUIP_MELEE", "STRENGTH"],
|
"flags": ["EQUIP_MELEE", "STRENGTH"],
|
||||||
"effects": { "base_damage": "1d6" }
|
"effects": { "base_damage": "1d6" }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "equip_pitchfork",
|
||||||
|
"name": { "name": "pitchfork", "plural": "pitchforks" },
|
||||||
|
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
|
||||||
|
"weight": 2,
|
||||||
|
"value": 5,
|
||||||
|
"flags": ["EQUIP_MELEE", "FINESSE"],
|
||||||
|
"effects": { "base_damage": "1d6" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "equip_sickle",
|
||||||
|
"name": { "name": "sickle", "plural": "sickles" },
|
||||||
|
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
|
||||||
|
"weight": 2,
|
||||||
|
"value": 5,
|
||||||
|
"flags": ["EQUIP_MELEE", "FINESSE"],
|
||||||
|
"effects": { "base_damage": "1d6" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "equip_handaxe",
|
||||||
|
"name": { "name": "handaxe", "plural": "handaxes" },
|
||||||
|
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
|
||||||
|
"weight": 2,
|
||||||
|
"value": 5,
|
||||||
|
"flags": ["EQUIP_MELEE", "FINESSE"],
|
||||||
|
"effects": { "base_damage": "1d6" }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "equip_longsword",
|
"id": "equip_longsword",
|
||||||
"name": { "name": "longsword", "plural": "longswords" },
|
"name": { "name": "longsword", "plural": "longswords" },
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,14 @@
|
||||||
{ "id": "equip_feet_iron", "weight": 2, "difficulty": 4}
|
{ "id": "equip_feet_iron", "weight": 2, "difficulty": 4}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "villager_equipment",
|
||||||
|
"table": [
|
||||||
|
{ "id": "equip_pitchfork", "weight": 1, "difficulty": 1},
|
||||||
|
{ "id": "equip_sickle", "weight": 1, "difficulty": 1},
|
||||||
|
{ "id": "equip_handaxe", "weight": 1, "difficulty": 1}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "potions",
|
"id": "potions",
|
||||||
"table": [
|
"table": [
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,16 @@ use super::{
|
||||||
triggers::{BLESSED, UNCURSED},
|
triggers::{BLESSED, UNCURSED},
|
||||||
EffectSpawner, EffectType,
|
EffectSpawner, EffectType,
|
||||||
};
|
};
|
||||||
use crate::{HungerClock, HungerState};
|
use crate::HungerClock;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
const SATIATED_DURATION: i32 = 200;
|
|
||||||
|
|
||||||
pub fn restore_food(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
pub fn restore_food(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
||||||
let buc = if let EffectType::RestoreNutrition { buc } = effect.effect_type { buc } else { UNCURSED };
|
let buc = if let EffectType::RestoreNutrition { buc } = effect.effect_type { buc } else { UNCURSED };
|
||||||
if let Some(hc) = ecs.write_storage::<HungerClock>().get_mut(target) {
|
if let Some(hc) = ecs.write_storage::<HungerClock>().get_mut(target) {
|
||||||
if buc == BLESSED || buc == UNCURSED {
|
if buc == BLESSED || buc == UNCURSED {
|
||||||
hc.state = HungerState::Satiated;
|
hc.duration += 400;
|
||||||
hc.duration = SATIATED_DURATION;
|
|
||||||
} else {
|
} else {
|
||||||
hc.duration = 0;
|
hc.duration += 200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use super::{Skill, Skills};
|
use super::{Skill, Skills};
|
||||||
|
use crate::gui::Classes;
|
||||||
|
use rltk::prelude::*;
|
||||||
|
|
||||||
/// Returns the attribute bonus for a given attribute score, where every 2 points above
|
/// Returns the attribute bonus for a given attribute score, where every 2 points above
|
||||||
/// or below 10 is an additional +1 or -1.
|
/// or below 10 is an additional +1 or -1.
|
||||||
|
|
@ -71,3 +73,38 @@ pub fn roll_4d6(rng: &mut rltk::RandomNumberGenerator) -> i32 {
|
||||||
|
|
||||||
return roll;
|
return roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles stat distribution for a player character.
|
||||||
|
pub fn get_attribute_rolls(rng: &mut RandomNumberGenerator, class: Classes) -> (i32, i32, i32, i32, i32, i32) {
|
||||||
|
let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class {
|
||||||
|
Classes::Fighter => (10, 10, 10, 10, 10, 10),
|
||||||
|
Classes::Wizard => (10, 10, 10, 10, 10, 10),
|
||||||
|
Classes::Villager => (10, 10, 10, 10, 10, 10),
|
||||||
|
};
|
||||||
|
let remaining_points = 75 - (str + dex + con + int + wis + cha);
|
||||||
|
let improve_chance: [i32; 6] = match class {
|
||||||
|
Classes::Fighter => [30, 20, 30, 6, 7, 7],
|
||||||
|
Classes::Wizard => [10, 20, 20, 30, 10, 10],
|
||||||
|
Classes::Villager => [15, 15, 40, 10, 10, 10],
|
||||||
|
};
|
||||||
|
let improve_table = crate::random_table::RandomTable::new()
|
||||||
|
.add("Strength", improve_chance[0])
|
||||||
|
.add("Dexterity", improve_chance[1])
|
||||||
|
.add("Constitution", improve_chance[2])
|
||||||
|
.add("Intelligence", improve_chance[3])
|
||||||
|
.add("Wisdom", improve_chance[4])
|
||||||
|
.add("Charisma", improve_chance[5]);
|
||||||
|
for _i in 0..remaining_points {
|
||||||
|
let roll = improve_table.roll(rng);
|
||||||
|
match roll.as_str() {
|
||||||
|
"Strength" => str += 1,
|
||||||
|
"Dexterity" => dex += 1,
|
||||||
|
"Constitution" => con += 1,
|
||||||
|
"Intelligence" => int += 1,
|
||||||
|
"Wisdom" => wis += 1,
|
||||||
|
"Charisma" => cha += 1,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (str, dex, con, int, wis, cha);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,34 @@
|
||||||
use super::{
|
use super::{
|
||||||
ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, hunger_system::get_hunger_colour,
|
ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, hunger_system::get_hunger_colour,
|
||||||
hunger_system::get_hunger_state, rex_assets::RexAssets, ArmourClassBonus, Attributes, Burden, Charges, Equipped,
|
rex_assets::RexAssets, ArmourClassBonus, Attributes, Burden, Charges, Equipped, Hidden, HungerClock, HungerState,
|
||||||
Hidden, HungerClock, HungerState, InBackpack, MagicItem, MagicItemClass, Map, MasterDungeonMap, Name,
|
InBackpack, MagicItem, MagicItemClass, Map, MasterDungeonMap, Name, ObfuscatedName, Player, Point, Pools, Position,
|
||||||
ObfuscatedName, Player, Point, Pools, Position, Prop, Renderable, RunState, Skill, Skills, State, Viewshed,
|
Prop, Renderable, RunState, Skill, Skills, State, Viewshed,
|
||||||
};
|
};
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
mod cheat_menu;
|
mod cheat_menu;
|
||||||
mod letter_to_option;
|
mod letter_to_option;
|
||||||
|
mod race_selection;
|
||||||
|
pub use race_selection::*;
|
||||||
mod tooltip;
|
mod tooltip;
|
||||||
pub use cheat_menu::*;
|
pub use cheat_menu::*;
|
||||||
|
|
||||||
|
/// Gives a popup box with a message and a title, and waits for a keypress.
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
|
||||||
|
ctx.print_color_centered(15, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), question);
|
||||||
|
ctx.print_color_centered(17, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "(y)es or (n)o");
|
||||||
|
match ctx.key {
|
||||||
|
None => None,
|
||||||
|
Some(key) => match key {
|
||||||
|
VirtualKeyCode::Y => Some(true),
|
||||||
|
VirtualKeyCode::N => Some(false),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_lerping_bar(
|
pub fn draw_lerping_bar(
|
||||||
ctx: &mut Rltk,
|
ctx: &mut Rltk,
|
||||||
sx: i32,
|
sx: i32,
|
||||||
|
|
|
||||||
229
src/gui/race_selection.rs
Normal file
229
src/gui/race_selection.rs
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
use super::{gamesystem::attr_bonus, gamesystem::get_attribute_rolls, Attributes, Pools, Renderable, RunState, State};
|
||||||
|
use crate::{ai::NORMAL_SPEED, raws, Attribute, Energy, Pool, Skill, Skills, Telepath};
|
||||||
|
use rltk::prelude::*;
|
||||||
|
use specs::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
|
pub enum Races {
|
||||||
|
NULL,
|
||||||
|
Human,
|
||||||
|
Dwarf,
|
||||||
|
Elf,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
|
pub enum Classes {
|
||||||
|
Fighter,
|
||||||
|
Wizard,
|
||||||
|
Villager,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
|
pub enum CharCreateResult {
|
||||||
|
NoSelection { race: Races, class: Classes },
|
||||||
|
Selected { race: Races, class: Classes },
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles the player character creation screen.
|
||||||
|
pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
||||||
|
let runstate = gs.ecs.fetch::<RunState>();
|
||||||
|
|
||||||
|
let mut x = 2;
|
||||||
|
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]");
|
||||||
|
y += 2;
|
||||||
|
|
||||||
|
if let RunState::CharacterCreation { race, class } = *runstate {
|
||||||
|
let selected_fg = RGB::named(GREEN);
|
||||||
|
let unselected_fg = RGB::named(WHITE);
|
||||||
|
let mut fg;
|
||||||
|
let bg = RGB::named(BLACK);
|
||||||
|
|
||||||
|
// Races
|
||||||
|
if race == Races::Human {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y, fg, bg, "h. Human");
|
||||||
|
if race == Races::Elf {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y + 1, fg, bg, "e. Elf");
|
||||||
|
if race == Races::Dwarf {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y + 2, fg, bg, "d. Dwarf");
|
||||||
|
// Classes
|
||||||
|
x += column_width;
|
||||||
|
if class == Classes::Fighter {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y, fg, bg, "f. Fighter");
|
||||||
|
if class == Classes::Wizard {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y + 1, fg, bg, "w. Wizard");
|
||||||
|
if class == Classes::Villager {
|
||||||
|
fg = selected_fg;
|
||||||
|
} else {
|
||||||
|
fg = unselected_fg;
|
||||||
|
}
|
||||||
|
ctx.print_color(x, y + 2, fg, bg, "v. Villager");
|
||||||
|
|
||||||
|
match ctx.key {
|
||||||
|
None => return CharCreateResult::NoSelection { race, class },
|
||||||
|
Some(key) => match key {
|
||||||
|
VirtualKeyCode::Escape => return CharCreateResult::Selected { race: Races::NULL, class },
|
||||||
|
VirtualKeyCode::Return => return CharCreateResult::Selected { race, class },
|
||||||
|
VirtualKeyCode::H => return CharCreateResult::NoSelection { race: Races::Human, class },
|
||||||
|
VirtualKeyCode::E => return CharCreateResult::NoSelection { race: Races::Elf, class },
|
||||||
|
VirtualKeyCode::D => return CharCreateResult::NoSelection { race: Races::Dwarf, class },
|
||||||
|
VirtualKeyCode::F => return CharCreateResult::NoSelection { race, class: Classes::Fighter },
|
||||||
|
VirtualKeyCode::W => return CharCreateResult::NoSelection { race, class: Classes::Wizard },
|
||||||
|
VirtualKeyCode::V => return CharCreateResult::NoSelection { race, class: Classes::Villager },
|
||||||
|
_ => return CharCreateResult::NoSelection { race, class },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CharCreateResult::NoSelection { race: Races::Human, class: Classes::Fighter };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles player race setup.
|
||||||
|
pub fn setup_player_race(ecs: &mut World, race: Races) {
|
||||||
|
let player = ecs.fetch::<Entity>();
|
||||||
|
let mut renderables = ecs.write_storage::<Renderable>();
|
||||||
|
// SKILLS
|
||||||
|
let mut skills = ecs.write_storage::<Skills>();
|
||||||
|
let player_skills = if let Some(skills) = skills.get_mut(*player) {
|
||||||
|
skills
|
||||||
|
} else {
|
||||||
|
skills.insert(*player, Skills { skills: HashMap::new() }).expect("Unable to insert skills component");
|
||||||
|
skills.get_mut(*player).unwrap()
|
||||||
|
};
|
||||||
|
match race {
|
||||||
|
Races::Human => {}
|
||||||
|
Races::Dwarf => {
|
||||||
|
renderables
|
||||||
|
.insert(
|
||||||
|
*player,
|
||||||
|
Renderable {
|
||||||
|
glyph: rltk::to_cp437('h'),
|
||||||
|
fg: RGB::named(rltk::RED),
|
||||||
|
bg: RGB::named(rltk::BLACK),
|
||||||
|
render_order: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to insert renderable component");
|
||||||
|
*player_skills.skills.entry(Skill::Defence).or_insert(0) += 1;
|
||||||
|
}
|
||||||
|
Races::Elf => {
|
||||||
|
renderables
|
||||||
|
.insert(
|
||||||
|
*player,
|
||||||
|
Renderable {
|
||||||
|
glyph: rltk::to_cp437('@'),
|
||||||
|
fg: RGB::named(rltk::GREEN),
|
||||||
|
bg: RGB::named(rltk::BLACK),
|
||||||
|
render_order: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to insert renderable component");
|
||||||
|
let mut telepaths = ecs.write_storage::<Telepath>();
|
||||||
|
telepaths
|
||||||
|
.insert(*player, Telepath { telepath_tiles: Vec::new(), range: 6, dirty: true })
|
||||||
|
.expect("Unable to insert telepath component");
|
||||||
|
let mut speeds = ecs.write_storage::<Energy>();
|
||||||
|
speeds
|
||||||
|
.insert(*player, Energy { current: 0, speed: NORMAL_SPEED + 1 })
|
||||||
|
.expect("Unable to insert energy component");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles player class setup
|
||||||
|
pub fn setup_player_class(ecs: &mut World, class: Classes) {
|
||||||
|
let player = *ecs.fetch::<Entity>();
|
||||||
|
// ATTRIBUTES
|
||||||
|
{
|
||||||
|
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||||
|
let mut attributes = ecs.write_storage::<Attributes>();
|
||||||
|
|
||||||
|
let (str, dex, con, int, wis, cha) = get_attribute_rolls(&mut rng, class);
|
||||||
|
attributes
|
||||||
|
.insert(
|
||||||
|
player,
|
||||||
|
Attributes {
|
||||||
|
strength: Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) },
|
||||||
|
dexterity: Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) },
|
||||||
|
constitution: Attribute { base: con, modifiers: 0, bonus: attr_bonus(con) },
|
||||||
|
intelligence: Attribute { base: int, modifiers: 0, bonus: attr_bonus(int) },
|
||||||
|
wisdom: Attribute { base: wis, modifiers: 0, bonus: attr_bonus(wis) },
|
||||||
|
charisma: Attribute { base: cha, modifiers: 0, bonus: attr_bonus(cha) },
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to insert attributes component");
|
||||||
|
|
||||||
|
let mut pools = ecs.write_storage::<Pools>();
|
||||||
|
pools
|
||||||
|
.insert(
|
||||||
|
player,
|
||||||
|
Pools {
|
||||||
|
hit_points: Pool { current: 10 + attr_bonus(con), max: 10 + attr_bonus(con) },
|
||||||
|
mana: Pool { current: 2 + attr_bonus(int), max: 2 + attr_bonus(int) },
|
||||||
|
xp: 0,
|
||||||
|
level: 1,
|
||||||
|
bac: 10,
|
||||||
|
weight: 0.0,
|
||||||
|
god: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.expect("Unable to insert pools component");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use seeded RNG here
|
||||||
|
let mut rng = RandomNumberGenerator::new();
|
||||||
|
let starts_with = get_starting_inventory(class, &mut rng);
|
||||||
|
for item in starts_with.0.iter() {
|
||||||
|
raws::spawn_named_entity(&raws::RAWS.lock().unwrap(), ecs, item, raws::SpawnType::Equipped { by: player }, 0);
|
||||||
|
}
|
||||||
|
for item in starts_with.1.iter() {
|
||||||
|
raws::spawn_named_entity(&raws::RAWS.lock().unwrap(), ecs, item, raws::SpawnType::Carried { by: player }, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_starting_inventory(class: Classes, rng: &mut RandomNumberGenerator) -> (Vec<String>, Vec<String>) {
|
||||||
|
let mut equipped: Vec<String> = Vec::new();
|
||||||
|
let mut carried: Vec<String> = Vec::new();
|
||||||
|
match class {
|
||||||
|
Classes::Fighter => {
|
||||||
|
equipped = vec![
|
||||||
|
"equip_shortsword".to_string(),
|
||||||
|
"equip_body_ringmail".to_string(),
|
||||||
|
"equip_mediumshield".to_string(),
|
||||||
|
];
|
||||||
|
carried = vec!["food_rations".to_string()];
|
||||||
|
}
|
||||||
|
Classes::Wizard => {
|
||||||
|
equipped = vec!["equip_dagger".to_string(), "equip_back_protection".to_string()];
|
||||||
|
}
|
||||||
|
Classes::Villager => {
|
||||||
|
let rolled_weapon = raws::table_by_name(&raws::RAWS.lock().unwrap(), "villager_equipment", 1).roll(rng);
|
||||||
|
equipped.push(rolled_weapon);
|
||||||
|
carried = vec!["food_rations".to_string(), "food_apple".to_string(), "food_apple".to_string()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (equipped, carried);
|
||||||
|
}
|
||||||
27
src/main.rs
27
src/main.rs
|
|
@ -41,7 +41,7 @@ extern crate lazy_static;
|
||||||
//Consts
|
//Consts
|
||||||
pub const SHOW_MAPGEN: bool = false;
|
pub const SHOW_MAPGEN: bool = false;
|
||||||
pub const LOG_SPAWNING: bool = true;
|
pub const LOG_SPAWNING: bool = true;
|
||||||
pub const LOG_TICKS: bool = false;
|
pub const LOG_TICKS: bool = true;
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
#[derive(PartialEq, Copy, Clone)]
|
||||||
pub enum RunState {
|
pub enum RunState {
|
||||||
|
|
@ -55,6 +55,7 @@ pub enum RunState {
|
||||||
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
||||||
ActionWithDirection { function: fn(i: i32, j: i32, ecs: &mut World) -> RunState },
|
ActionWithDirection { function: fn(i: i32, j: i32, ecs: &mut World) -> RunState },
|
||||||
MainMenu { menu_selection: gui::MainMenuSelection },
|
MainMenu { menu_selection: gui::MainMenuSelection },
|
||||||
|
CharacterCreation { race: gui::Races, class: gui::Classes },
|
||||||
SaveGame,
|
SaveGame,
|
||||||
GameOver,
|
GameOver,
|
||||||
NextLevel,
|
NextLevel,
|
||||||
|
|
@ -209,6 +210,7 @@ impl GameState for State {
|
||||||
|
|
||||||
match new_runstate {
|
match new_runstate {
|
||||||
RunState::MainMenu { .. } => {}
|
RunState::MainMenu { .. } => {}
|
||||||
|
RunState::CharacterCreation { .. } => {}
|
||||||
_ => {
|
_ => {
|
||||||
// Draw map and ui
|
// Draw map and ui
|
||||||
camera::render_camera(&self.ecs, ctx);
|
camera::render_camera(&self.ecs, ctx);
|
||||||
|
|
@ -380,7 +382,10 @@ impl GameState for State {
|
||||||
new_runstate = RunState::MainMenu { menu_selection: selected }
|
new_runstate = RunState::MainMenu { menu_selection: selected }
|
||||||
}
|
}
|
||||||
gui::MainMenuResult::Selected { selected } => match selected {
|
gui::MainMenuResult::Selected { selected } => match selected {
|
||||||
gui::MainMenuSelection::NewGame => new_runstate = RunState::PreRun,
|
gui::MainMenuSelection::NewGame => {
|
||||||
|
new_runstate =
|
||||||
|
RunState::CharacterCreation { race: gui::Races::Human, class: gui::Classes::Fighter }
|
||||||
|
}
|
||||||
gui::MainMenuSelection::LoadGame => {
|
gui::MainMenuSelection::LoadGame => {
|
||||||
saveload_system::load_game(&mut self.ecs);
|
saveload_system::load_game(&mut self.ecs);
|
||||||
new_runstate = RunState::AwaitingInput;
|
new_runstate = RunState::AwaitingInput;
|
||||||
|
|
@ -392,6 +397,23 @@ impl GameState for State {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RunState::CharacterCreation { .. } => {
|
||||||
|
let result = gui::character_creation(self, ctx);
|
||||||
|
match result {
|
||||||
|
gui::CharCreateResult::NoSelection { race, class } => {
|
||||||
|
new_runstate = RunState::CharacterCreation { race, class }
|
||||||
|
}
|
||||||
|
gui::CharCreateResult::Selected { race, class } => {
|
||||||
|
if race == gui::Races::NULL {
|
||||||
|
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame };
|
||||||
|
} else {
|
||||||
|
gui::setup_player_race(&mut self.ecs, race);
|
||||||
|
gui::setup_player_class(&mut self.ecs, class);
|
||||||
|
new_runstate = RunState::PreRun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
RunState::SaveGame => {
|
RunState::SaveGame => {
|
||||||
saveload_system::save_game(&mut self.ecs);
|
saveload_system::save_game(&mut self.ecs);
|
||||||
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::LoadGame };
|
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::LoadGame };
|
||||||
|
|
@ -596,6 +618,7 @@ fn main() -> rltk::BError {
|
||||||
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
gs.ecs.insert(map::MasterDungeonMap::new()); // Master map list
|
||||||
gs.ecs.insert(Map::new(1, 64, 64, 0, "New Map")); // Map
|
gs.ecs.insert(Map::new(1, 64, 64, 0, "New Map")); // Map
|
||||||
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
gs.ecs.insert(Point::new(0, 0)); // Player pos
|
||||||
|
gs.ecs.insert(gui::Races::Dwarf); // Race
|
||||||
let player_entity = spawner::player(&mut gs.ecs, 0, 0);
|
let player_entity = spawner::player(&mut gs.ecs, 0, 0);
|
||||||
gs.ecs.insert(player_entity); // Player entity
|
gs.ecs.insert(player_entity); // Player entity
|
||||||
gs.ecs.insert(RunState::MapGeneration {}); // RunState
|
gs.ecs.insert(RunState::MapGeneration {}); // RunState
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use super::{
|
use super::{
|
||||||
ai::NORMAL_SPEED, gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes,
|
ai::NORMAL_SPEED, random_table::RandomTable, raws, Clock, Energy, EquipmentChanged, Faction, HungerClock,
|
||||||
Clock, Energy, EquipmentChanged, Faction, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect,
|
HungerState, Map, Name, Player, Position, Rect, Renderable, SerializeMe, Skill, Skills, TileType, Viewshed,
|
||||||
Renderable, SerializeMe, Skill, Skills, TileType, Viewshed,
|
|
||||||
};
|
};
|
||||||
use rltk::{RandomNumberGenerator, RGB};
|
use rltk::{RandomNumberGenerator, RGB};
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
@ -15,15 +14,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
skills.skills.insert(Skill::Defence, 0);
|
skills.skills.insert(Skill::Defence, 0);
|
||||||
skills.skills.insert(Skill::Magic, 0);
|
skills.skills.insert(Skill::Magic, 0);
|
||||||
|
|
||||||
let mut rng = ecs.write_resource::<rltk::RandomNumberGenerator>();
|
|
||||||
let str = gamesystem::roll_4d6(&mut rng);
|
|
||||||
let dex = gamesystem::roll_4d6(&mut rng);
|
|
||||||
let con = gamesystem::roll_4d6(&mut rng);
|
|
||||||
let int = gamesystem::roll_4d6(&mut rng);
|
|
||||||
let wis = gamesystem::roll_4d6(&mut rng);
|
|
||||||
let cha = gamesystem::roll_4d6(&mut rng);
|
|
||||||
std::mem::drop(rng);
|
|
||||||
|
|
||||||
// We only create the player once, so create the Clock here for counting turns too.
|
// We only create the player once, so create the Clock here for counting turns too.
|
||||||
ecs.create_entity().with(Clock {}).with(Energy { current: 0, speed: NORMAL_SPEED }).build();
|
ecs.create_entity().with(Clock {}).with(Energy { current: 0, speed: NORMAL_SPEED }).build();
|
||||||
let player = ecs
|
let player = ecs
|
||||||
|
|
@ -40,13 +30,13 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
.with(Viewshed { visible_tiles: Vec::new(), range: 12, dirty: true })
|
||||||
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
.with(Name { name: "you".to_string(), plural: "you".to_string() })
|
||||||
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
|
.with(HungerClock { state: HungerState::Satiated, duration: 1200 })
|
||||||
.with(Attributes {
|
/*.with(Attributes {
|
||||||
strength: Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) },
|
strength: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
dexterity: Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) },
|
dexterity: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
constitution: Attribute { base: con, modifiers: 0, bonus: attr_bonus(con) },
|
constitution: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
intelligence: Attribute { base: int, modifiers: 0, bonus: attr_bonus(int) },
|
intelligence: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
wisdom: Attribute { base: wis, modifiers: 0, bonus: attr_bonus(wis) },
|
wisdom: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
charisma: Attribute { base: cha, modifiers: 0, bonus: attr_bonus(cha) },
|
charisma: Attribute { base: 10, modifiers: 0, bonus: 0 },
|
||||||
})
|
})
|
||||||
.with(Pools {
|
.with(Pools {
|
||||||
hit_points: Pool { current: 10 + attr_bonus(con), max: 10 + attr_bonus(con) },
|
hit_points: Pool { current: 10 + attr_bonus(con), max: 10 + attr_bonus(con) },
|
||||||
|
|
@ -56,20 +46,13 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
bac: 10,
|
bac: 10,
|
||||||
weight: 0.0,
|
weight: 0.0,
|
||||||
god: false,
|
god: false,
|
||||||
})
|
})*/
|
||||||
.with(EquipmentChanged {})
|
.with(EquipmentChanged {})
|
||||||
.with(skills)
|
.with(skills)
|
||||||
.with(Energy { current: 0, speed: NORMAL_SPEED })
|
.with(Energy { current: 0, speed: NORMAL_SPEED })
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"equip_dagger",
|
|
||||||
raws::SpawnType::Equipped { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
raws::spawn_named_entity(
|
raws::spawn_named_entity(
|
||||||
&raws::RAWS.lock().unwrap(),
|
&raws::RAWS.lock().unwrap(),
|
||||||
ecs,
|
ecs,
|
||||||
|
|
@ -77,41 +60,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||||
raws::SpawnType::Carried { by: player },
|
raws::SpawnType::Carried { by: player },
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"food_apple",
|
|
||||||
raws::SpawnType::Carried { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"food_apple",
|
|
||||||
raws::SpawnType::Carried { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"scroll_mass_health",
|
|
||||||
raws::SpawnType::Carried { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"wand_fireball",
|
|
||||||
raws::SpawnType::Carried { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
raws::spawn_named_entity(
|
|
||||||
&raws::RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"wand_fireball",
|
|
||||||
raws::SpawnType::Carried { by: player },
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue