123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- extern crate rltk;
- use rltk::{ RGB, RandomNumberGenerator };
- extern crate specs;
- use specs::prelude::*;
- use super::{CombatStats, Player, Renderable, Name, Position, Viewshed, Monster, BlocksTile, Rect, Item,
- Consumable, Ranged, ProvidesHealing, map::MAPWIDTH, InflictsDamage, AreaOfEffect, Confusion};
- /// Spawns the player and returns his/her entity object.
- pub fn player(ecs : &mut World, player_x : i32, player_y : i32) -> Entity {
- ecs
- .create_entity()
- .with(Position { x: player_x, y: player_y })
- .with(Renderable {
- glyph: rltk::to_cp437('@'),
- fg: RGB::named(rltk::YELLOW),
- bg: RGB::named(rltk::BLACK),
- render_order: 0
- })
- .with(Player{})
- .with(Viewshed{ visible_tiles : Vec::new(), range: 8, dirty: true })
- .with(Name{name: "Player".to_string() })
- .with(CombatStats{ max_hp: 30, hp: 30, defense: 2, power: 5 })
- .build()
- }
- const MAX_MONSTERS : i32 = 4;
- const MAX_ITEMS : i32 = 2;
- /// Fills a room with stuff!
- pub fn spawn_room(ecs: &mut World, room : &Rect) {
- let mut monster_spawn_points : Vec<usize> = Vec::new();
- let mut item_spawn_points : Vec<usize> = Vec::new();
- // Scope to keep the borrow checker happy
- {
- let mut rng = ecs.write_resource::<RandomNumberGenerator>();
- let num_monsters = rng.roll_dice(1, MAX_MONSTERS + 2) - 3;
- let num_items = rng.roll_dice(1, MAX_ITEMS + 2) - 3;
- for _i in 0 .. num_monsters {
- let mut added = false;
- while !added {
- let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
- let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
- let idx = (y * MAPWIDTH) + x;
- if !monster_spawn_points.contains(&idx) {
- monster_spawn_points.push(idx);
- added = true;
- }
- }
- }
- for _i in 0 .. num_items {
- let mut added = false;
- while !added {
- let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
- let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
- let idx = (y * MAPWIDTH) + x;
- if !item_spawn_points.contains(&idx) {
- item_spawn_points.push(idx);
- added = true;
- }
- }
- }
- }
- // Actually spawn the monsters
- for idx in monster_spawn_points.iter() {
- let x = *idx % MAPWIDTH;
- let y = *idx / MAPWIDTH;
- random_monster(ecs, x as i32, y as i32);
- }
- // Actually spawn the items
- for idx in item_spawn_points.iter() {
- let x = *idx % MAPWIDTH;
- let y = *idx / MAPWIDTH;
- random_item(ecs, x as i32, y as i32);
- }
- }
- fn random_monster(ecs: &mut World, x: i32, y: i32) {
- let roll :i32;
- {
- let mut rng = ecs.write_resource::<RandomNumberGenerator>();
- roll = rng.roll_dice(1, 2);
- }
- match roll {
- 1 => { orc(ecs, x, y) }
- _ => { goblin(ecs, x, y) }
- }
- }
- fn random_item(ecs: &mut World, x: i32, y: i32) {
- let roll :i32;
- {
- let mut rng = ecs.write_resource::<RandomNumberGenerator>();
- roll = rng.roll_dice(1, 4);
- }
- match roll {
- 1 => { health_potion(ecs, x, y) }
- 2 => { fireball_scroll(ecs, x, y) }
- 3 => { confusion_scroll(ecs, x, y) }
- _ => { magic_missile_scroll(ecs, x, y) }
- }
- }
- fn orc(ecs: &mut World, x: i32, y: i32) { monster(ecs, x, y, rltk::to_cp437('o'), "Orc"); }
- fn goblin(ecs: &mut World, x: i32, y: i32) { monster(ecs, x, y, rltk::to_cp437('g'), "Goblin"); }
- fn monster<S : ToString>(ecs: &mut World, x: i32, y: i32, glyph : u8, name : S) {
- ecs.create_entity()
- .with(Position{ x, y })
- .with(Renderable{
- glyph,
- fg: RGB::named(rltk::RED),
- bg: RGB::named(rltk::BLACK),
- render_order: 1
- })
- .with(Viewshed{ visible_tiles : Vec::new(), range: 8, dirty: true })
- .with(Monster{})
- .with(Name{ name : name.to_string() })
- .with(BlocksTile{})
- .with(CombatStats{ max_hp: 16, hp: 16, defense: 1, power: 4 })
- .build();
- }
- fn health_potion(ecs: &mut World, x: i32, y: i32) {
- ecs.create_entity()
- .with(Position{ x, y })
- .with(Renderable{
- glyph: rltk::to_cp437('¡'),
- fg: RGB::named(rltk::MAGENTA),
- bg: RGB::named(rltk::BLACK),
- render_order: 2
- })
- .with(Name{ name : "Health Potion".to_string() })
- .with(Item{})
- .with(Consumable{})
- .with(ProvidesHealing{ heal_amount: 8 })
- .build();
- }
- fn magic_missile_scroll(ecs: &mut World, x: i32, y: i32) {
- ecs.create_entity()
- .with(Position{ x, y })
- .with(Renderable{
- glyph: rltk::to_cp437(')'),
- fg: RGB::named(rltk::CYAN),
- bg: RGB::named(rltk::BLACK),
- render_order: 2
- })
- .with(Name{ name : "Magic Missile Scroll".to_string() })
- .with(Item{})
- .with(Consumable{})
- .with(Ranged{ range: 6 })
- .with(InflictsDamage{ damage: 20 })
- .build();
- }
- fn fireball_scroll(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 : "Fireball Scroll".to_string() })
- .with(Item{})
- .with(Consumable{})
- .with(Ranged{ range: 6 })
- .with(InflictsDamage{ damage: 20 })
- .with(AreaOfEffect{ radius: 3 })
- .build();
- }
- fn confusion_scroll(ecs: &mut World, x: i32, y: i32) {
- ecs.create_entity()
- .with(Position{ x, y })
- .with(Renderable{
- glyph: rltk::to_cp437(')'),
- fg: RGB::named(rltk::PINK),
- bg: RGB::named(rltk::BLACK),
- render_order: 2
- })
- .with(Name{ name : "Confusion Scroll".to_string() })
- .with(Item{})
- .with(Consumable{})
- .with(Ranged{ range: 6 })
- .with(Confusion{ turns: 4 })
- .build();
- }
|