basic wands and wresting

This commit is contained in:
Llywelwyn 2023-07-12 11:40:56 +01:00
parent 4cd4b638ec
commit 24417fbb05
5 changed files with 96 additions and 22 deletions

View file

@ -200,6 +200,12 @@ pub struct WantsToUseItem {
#[derive(Component, Debug, Serialize, Deserialize, Clone)] #[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Consumable {} pub struct Consumable {}
#[derive(Component, Debug, ConvertSaveload)]
pub struct Wand {
pub uses: i32,
pub max_uses: i32,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)] #[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Destructible {} pub struct Destructible {}

View file

@ -1,8 +1,8 @@
use super::{ use super::{
gamelog, CombatStats, Confusion, Consumable, Cursed, Destructible, Equippable, Equipped, HungerClock, HungerState, gamelog, CombatStats, Confusion, Consumable, Cursed, Destructible, Equippable, Equipped, HungerClock, HungerState,
InBackpack, InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Position, ProvidesHealing, InBackpack, InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Position, ProvidesHealing,
ProvidesNutrition, RunState, SufferDamage, WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, ProvidesNutrition, RandomNumberGenerator, RunState, SufferDamage, Wand, WantsToDropItem, WantsToPickupItem,
AOE, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME, WantsToRemoveItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME,
}; };
use specs::prelude::*; use specs::prelude::*;
@ -44,10 +44,12 @@ impl<'a> System<'a> for ItemUseSystem {
type SystemData = ( type SystemData = (
ReadExpect<'a, Entity>, ReadExpect<'a, Entity>,
ReadExpect<'a, Map>, ReadExpect<'a, Map>,
WriteExpect<'a, RandomNumberGenerator>,
Entities<'a>, Entities<'a>,
WriteStorage<'a, WantsToUseItem>, WriteStorage<'a, WantsToUseItem>,
ReadStorage<'a, Name>, ReadStorage<'a, Name>,
ReadStorage<'a, Consumable>, WriteStorage<'a, Consumable>,
WriteStorage<'a, Wand>,
ReadStorage<'a, Destructible>, ReadStorage<'a, Destructible>,
ReadStorage<'a, Cursed>, ReadStorage<'a, Cursed>,
ReadStorage<'a, ProvidesHealing>, ReadStorage<'a, ProvidesHealing>,
@ -71,10 +73,12 @@ impl<'a> System<'a> for ItemUseSystem {
let ( let (
player_entity, player_entity,
map, map,
mut rng,
entities, entities,
mut wants_to_use, mut wants_to_use,
names, names,
consumables, mut consumables,
mut wands,
destructibles, destructibles,
cursed_items, cursed_items,
provides_healing, provides_healing,
@ -95,13 +99,29 @@ impl<'a> System<'a> for ItemUseSystem {
) = data; ) = data;
for (entity, wants_to_use) in (&entities, &wants_to_use).join() { for (entity, wants_to_use) in (&entities, &wants_to_use).join() {
let mut verb = "use";
let mut used_item = true; let mut used_item = true;
let mut aoe_item = false; let mut aoe_item = false;
let item_being_used = names.get(wants_to_use.item).unwrap(); let item_being_used = names.get(wants_to_use.item).unwrap();
let is_cursed = cursed_items.get(wants_to_use.item); let is_cursed = cursed_items.get(wants_to_use.item);
let wand = wands.get_mut(wants_to_use.item);
let mut verb = "use"; if let Some(wand) = wand {
// If want has no uses, roll 1d121. On a 121, wrest the wand, then delete it.
if wand.uses == 0 {
if rng.roll_dice(1, 121) != 121 {
gamelog::Logger::new().append("The wand does nothing.").log();
break;
}
gamelog::Logger::new()
.colour(rltk::YELLOW)
.append("You wrest one last charge from the worn-out wand.")
.log();
consumables.insert(wants_to_use.item, Consumable {}).expect("Could not insert consumable");
}
verb = "zap";
wand.uses -= 1;
}
let is_edible = provides_nutrition.get(wants_to_use.item); let is_edible = provides_nutrition.get(wants_to_use.item);
if let Some(_) = is_edible { if let Some(_) = is_edible {

View file

@ -283,13 +283,11 @@ impl GameState for State {
} }
RunState::AwaitingInput => { RunState::AwaitingInput => {
new_runstate = player_input(self, ctx); new_runstate = player_input(self, ctx);
if new_runstate != RunState::AwaitingInput {
gamelog::record_event("Turn", 1);
}
} }
RunState::PlayerTurn => { RunState::PlayerTurn => {
self.run_systems(); self.run_systems();
self.ecs.maintain(); self.ecs.maintain();
gamelog::record_event("Turn", 1);
match *self.ecs.fetch::<RunState>() { match *self.ecs.fetch::<RunState>() {
RunState::MagicMapReveal { row, cursed } => { RunState::MagicMapReveal { row, cursed } => {
new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed } new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed }
@ -508,6 +506,7 @@ fn main() -> rltk::BError {
gs.ecs.register::<WantsToRemoveItem>(); gs.ecs.register::<WantsToRemoveItem>();
gs.ecs.register::<WantsToUseItem>(); gs.ecs.register::<WantsToUseItem>();
gs.ecs.register::<Consumable>(); gs.ecs.register::<Consumable>();
gs.ecs.register::<Wand>();
gs.ecs.register::<ProvidesNutrition>(); gs.ecs.register::<ProvidesNutrition>();
gs.ecs.register::<Destructible>(); gs.ecs.register::<Destructible>();
gs.ecs.register::<ParticleLifetime>(); gs.ecs.register::<ParticleLifetime>();

View file

@ -76,6 +76,7 @@ pub fn save_game(ecs: &mut World) {
SufferDamage, SufferDamage,
Telepath, Telepath,
Viewshed, Viewshed,
Wand,
WantsToDropItem, WantsToDropItem,
WantsToMelee, WantsToMelee,
WantsToPickupItem, WantsToPickupItem,
@ -163,6 +164,7 @@ pub fn load_game(ecs: &mut World) {
SufferDamage, SufferDamage,
Telepath, Telepath,
Viewshed, Viewshed,
Wand,
WantsToDropItem, WantsToDropItem,
WantsToMelee, WantsToMelee,
WantsToPickupItem, WantsToPickupItem,

View file

@ -2,7 +2,7 @@ use super::{
random_table::RandomTable, BlocksTile, CombatStats, Confusion, Consumable, Cursed, DefenceBonus, Destructible, random_table::RandomTable, BlocksTile, CombatStats, Confusion, Consumable, Cursed, DefenceBonus, Destructible,
EquipmentSlot, Equippable, HungerClock, HungerState, InflictsDamage, Item, MagicMapper, MeleePowerBonus, Mind, EquipmentSlot, Equippable, HungerClock, HungerState, InflictsDamage, Item, MagicMapper, MeleePowerBonus, Mind,
Monster, Name, Player, Position, ProvidesHealing, ProvidesNutrition, Ranged, Rect, Renderable, SerializeMe, Monster, Name, Player, Position, ProvidesHealing, ProvidesNutrition, Ranged, Rect, Renderable, SerializeMe,
Viewshed, AOE, MAPWIDTH, Viewshed, Wand, AOE, MAPWIDTH,
}; };
use rltk::{console, RandomNumberGenerator, RGB}; use rltk::{console, RandomNumberGenerator, RGB};
use specs::prelude::*; use specs::prelude::*;
@ -135,6 +135,9 @@ pub fn spawn_room(ecs: &mut World, room: &Rect, map_depth: i32) {
"magic missile scroll" => magic_missile_scroll(ecs, x, y), "magic missile scroll" => magic_missile_scroll(ecs, x, y),
"magic map scroll" => magic_map_scroll(ecs, x, y), "magic map scroll" => magic_map_scroll(ecs, x, y),
"cursed magic map scroll" => cursed_magic_map_scroll(ecs, x, y), "cursed magic map scroll" => cursed_magic_map_scroll(ecs, x, y),
// Wands
"magic missile wand" => magic_missile_wand(ecs, x, y),
"fireball wand" => fireball_wand(ecs, x, y),
// Food // Food
"rations" => rations(ecs, x, y), "rations" => rations(ecs, x, y),
_ => console::log("Tried to spawn nothing. Bugfix needed!"), _ => console::log("Tried to spawn nothing. Bugfix needed!"),
@ -164,20 +167,23 @@ fn mob_table(map_depth: i32) -> RandomTable {
fn item_table(_map_depth: i32) -> RandomTable { fn item_table(_map_depth: i32) -> RandomTable {
return RandomTable::new() return RandomTable::new()
// Equipment // Equipment
.add("dagger", 2) .add("dagger", 4)
.add("shortsword", 2) .add("shortsword", 4)
.add("buckler", 2) .add("buckler", 4)
.add("shield", 1) .add("shield", 2)
// Potions // Potions
.add("weak health potion", 7) .add("weak health potion", 14)
.add("health potion", 3) .add("health potion", 6)
// Scrolls // Scrolls
.add("fireball scroll", 1) .add("fireball scroll", 2)
.add("cursed fireball scroll", 1) .add("cursed fireball scroll", 2)
.add("confusion scroll", 2) .add("confusion scroll", 4)
.add("magic missile scroll", 5) .add("magic missile scroll", 10)
.add("magic map scroll", 2) .add("magic map scroll", 4)
.add("cursed magic map scroll", 1); .add("cursed magic map scroll", 2)
// Wands
.add("magic missile wand", 1)
.add("fireball wand", 1);
} }
fn food_table(_map_depth: i32) -> RandomTable { fn food_table(_map_depth: i32) -> RandomTable {
@ -445,3 +451,44 @@ fn rations(ecs: &mut World, x: i32, y: i32) {
.marked::<SimpleMarker<SerializeMe>>() .marked::<SimpleMarker<SerializeMe>>()
.build(); .build();
} }
// WANDS
fn fireball_wand(ecs: &mut World, x: i32, y: i32) {
ecs.create_entity()
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437('/'),
fg: RGB::named(rltk::ORANGE),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name { name: "wand of fireball".to_string() })
.with(Item {})
.with(Wand { uses: 3, max_uses: 3 })
.with(Destructible {})
.with(Ranged { range: 10 })
.with(InflictsDamage { amount: 20 })
.with(AOE { radius: 3 })
.marked::<SimpleMarker<SerializeMe>>()
.build();
}
fn magic_missile_wand(ecs: &mut World, x: i32, y: i32) {
ecs.create_entity()
.with(Position { x, y })
.with(Renderable {
glyph: rltk::to_cp437('?'),
fg: RGB::named(rltk::BLUE),
bg: RGB::named(rltk::BLACK),
render_order: 2,
})
.with(Name { name: "wand of magic missile".to_string() })
.with(Item {})
.with(Wand { uses: 3, max_uses: 3 })
.with(Destructible {})
.with(Ranged { range: 12 }) // Long range - as far as default vision range
.with(InflictsDamage { amount: 10 }) // Low~ damage
.marked::<SimpleMarker<SerializeMe>>()
.build();
}