better death messages, and morgue file map fix
This commit is contained in:
parent
9ac2adc5d6
commit
9e294a1680
7 changed files with 104 additions and 32 deletions
|
|
@ -35,7 +35,8 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(
|
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(
|
||||||
idx,
|
idx,
|
||||||
&*map,
|
&*map,
|
||||||
Some(*ecs.fetch::<Point>())
|
Some(*ecs.fetch::<Point>()),
|
||||||
|
None
|
||||||
);
|
);
|
||||||
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
|
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +67,12 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
||||||
if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y {
|
if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y {
|
||||||
let mut draw = false;
|
let mut draw = false;
|
||||||
let mut fg = render.fg;
|
let mut fg = render.fg;
|
||||||
let mut bg = crate::map::themes::get_tile_renderables_for_id(idx, &*map, Some(*ecs.fetch::<Point>())).2;
|
let mut bg = crate::map::themes::get_tile_renderables_for_id(
|
||||||
|
idx,
|
||||||
|
&*map,
|
||||||
|
Some(*ecs.fetch::<Point>()),
|
||||||
|
None
|
||||||
|
).2;
|
||||||
// Draw entities on visible tiles
|
// Draw entities on visible tiles
|
||||||
if map.visible_tiles[idx] {
|
if map.visible_tiles[idx] {
|
||||||
draw = true;
|
draw = true;
|
||||||
|
|
@ -124,7 +130,7 @@ pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
|
||||||
if tx >= 0 && tx < map_width && ty >= 0 && ty < map_height {
|
if tx >= 0 && tx < map_width && ty >= 0 && ty < map_height {
|
||||||
let idx = map.xy_idx(tx, ty);
|
let idx = map.xy_idx(tx, ty);
|
||||||
if map.revealed_tiles[idx] {
|
if map.revealed_tiles[idx] {
|
||||||
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None);
|
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None, None);
|
||||||
ctx.set(x, y, fg, bg, glyph);
|
ctx.set(x, y, fg, bg, glyph);
|
||||||
}
|
}
|
||||||
} else if SHOW_BOUNDARIES {
|
} else if SHOW_BOUNDARIES {
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,17 @@ pub const YOU_DROP_ITEM: &str = "You drop the";
|
||||||
pub const YOU_EQUIP_ITEM: &str = "You equip the";
|
pub const YOU_EQUIP_ITEM: &str = "You equip the";
|
||||||
pub const YOU_REMOVE_ITEM: &str = "You unequip your";
|
pub const YOU_REMOVE_ITEM: &str = "You unequip your";
|
||||||
pub const YOU_REMOVE_ITEM_CURSED: &str = "You can't remove the";
|
pub const YOU_REMOVE_ITEM_CURSED: &str = "You can't remove the";
|
||||||
|
|
||||||
|
/// Prefixes death message.
|
||||||
|
pub const PLAYER_DIED: &str = "You died!";
|
||||||
|
/// Death message specifiers. Appended after PLAYER_DIED.
|
||||||
|
pub const PLAYER_DIED_SUICIDE: &str = "You killed yourself";
|
||||||
|
pub const PLAYER_DIED_NAMED_ATTACKER: &str = "You were killed by";
|
||||||
|
pub const PLAYER_DIED_UNKNOWN: &str = "You were killed"; // Ultimately, this should never be used. Slowly include specific messages for any death.
|
||||||
|
/// Death message addendums. Appended at end of death message.
|
||||||
|
pub const PLAYER_DIED_ADDENDUM_FIRST: &str = " ";
|
||||||
|
pub const PLAYER_DIED_ADDENDUM_MID: &str = ", ";
|
||||||
|
pub const PLAYER_DIED_ADDENDUM_LAST: &str = ", and ";
|
||||||
|
pub const STATUS_CONFUSED_STRING: &str = "confused";
|
||||||
|
pub const STATUS_BLIND_STRING: &str = "blinded";
|
||||||
|
// Results in something like: "You died! You were killed by a kobold captain, whilst confused."
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,13 @@ use crate::{
|
||||||
Player,
|
Player,
|
||||||
Pools,
|
Pools,
|
||||||
Name,
|
Name,
|
||||||
|
Blind,
|
||||||
};
|
};
|
||||||
|
use crate::gui::with_article;
|
||||||
use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME };
|
use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME };
|
||||||
use crate::data::messages::LEVELUP_PLAYER;
|
use crate::data::messages::LEVELUP_PLAYER;
|
||||||
use crate::data::events::*;
|
use crate::data::events::*;
|
||||||
|
use crate::data::messages::*;
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use specs::prelude::*;
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
|
@ -135,6 +138,42 @@ fn get_next_level_requirement(level: i32) -> i32 {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_death_message(ecs: &World, source: Entity) -> String {
|
||||||
|
let player = ecs.fetch::<Entity>();
|
||||||
|
let mut result: String = format!("{} ", PLAYER_DIED);
|
||||||
|
// If we killed ourselves,
|
||||||
|
if source == *player {
|
||||||
|
result.push_str(format!("{}", PLAYER_DIED_SUICIDE).as_str());
|
||||||
|
} else if let Some(name) = ecs.read_storage::<Name>().get(source) {
|
||||||
|
result.push_str(format!("{} {}", PLAYER_DIED_NAMED_ATTACKER, with_article(name.name.clone())).as_str());
|
||||||
|
} else {
|
||||||
|
result.push_str(format!("{}", PLAYER_DIED_UNKNOWN).as_str());
|
||||||
|
}
|
||||||
|
// Status effects
|
||||||
|
{
|
||||||
|
let mut addendums: Vec<&str> = Vec::new();
|
||||||
|
if let Some(_confused) = ecs.read_storage::<Confusion>().get(*player) {
|
||||||
|
addendums.push(STATUS_CONFUSED_STRING);
|
||||||
|
}
|
||||||
|
if let Some(_blind) = ecs.read_storage::<Blind>().get(*player) {
|
||||||
|
addendums.push(STATUS_BLIND_STRING);
|
||||||
|
}
|
||||||
|
if !addendums.is_empty() {
|
||||||
|
result.push_str(" whilst");
|
||||||
|
for (i, addendum) in addendums.iter().enumerate() {
|
||||||
|
if i == 0 {
|
||||||
|
result.push_str(format!("{}{}", PLAYER_DIED_ADDENDUM_FIRST, addendum).as_str());
|
||||||
|
} else if i == addendums.len() {
|
||||||
|
result.push_str(format!("{}{}", PLAYER_DIED_ADDENDUM_LAST, addendum).as_str());
|
||||||
|
} else {
|
||||||
|
result.push_str(format!("{}{}", PLAYER_DIED_ADDENDUM_MID, addendum).as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles EntityDeath effects.
|
/// Handles EntityDeath effects.
|
||||||
pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
||||||
let mut xp_gain = 0;
|
let mut xp_gain = 0;
|
||||||
|
|
@ -150,9 +189,7 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
||||||
if let Some(source) = effect.source {
|
if let Some(source) = effect.source {
|
||||||
// If the target was the player, game over, and record source of death.
|
// If the target was the player, game over, and record source of death.
|
||||||
if target == *player {
|
if target == *player {
|
||||||
if let Some(src_name) = names.get(source) {
|
gamelog::record_event(EVENT::PLAYER_DIED(get_death_message(ecs, source)));
|
||||||
gamelog::record_event(EVENT::PLAYER_DIED(src_name.name.clone()));
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// If the player was the source, record the kill.
|
// If the player was the source, record the kill.
|
||||||
|
|
|
||||||
|
|
@ -126,13 +126,9 @@ pub fn record_event(event: EVENT) {
|
||||||
EVENT::IDENTIFIED(name) => {
|
EVENT::IDENTIFIED(name) => {
|
||||||
new_event = format!("Identified {}", name);
|
new_event = format!("Identified {}", name);
|
||||||
}
|
}
|
||||||
EVENT::PLAYER_DIED(name) => {
|
EVENT::PLAYER_DIED(str) => {
|
||||||
if name == "you" {
|
// Generating the String is handled in the death effect, to avoid passing the ecs here.
|
||||||
new_event = format!("You died! Killed by... yourself.");
|
new_event = format!("{}", str);
|
||||||
} else {
|
|
||||||
// TODO: Use correct article here - or don't include article at all.
|
|
||||||
new_event = format!("You died, killed by {}", name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1195,3 +1195,16 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_article(name: String) -> String {
|
||||||
|
// If first letter is a capital
|
||||||
|
if name.chars().nth(0).unwrap().is_uppercase() {
|
||||||
|
return format!("{}", name);
|
||||||
|
}
|
||||||
|
// a/an
|
||||||
|
let vowels = ['a', 'e', 'i', 'o', 'u'];
|
||||||
|
if vowels.contains(&name.chars().nth(0).unwrap()) {
|
||||||
|
return format!("an {}", name);
|
||||||
|
}
|
||||||
|
format!("a {}", name)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,16 @@ use crate::config::CONFIG;
|
||||||
use rltk::prelude::*;
|
use rltk::prelude::*;
|
||||||
use std::ops::{ Add, Mul };
|
use std::ops::{ Add, Mul };
|
||||||
|
|
||||||
pub fn get_tile_renderables_for_id(idx: usize, map: &Map, other_pos: Option<Point>) -> (rltk::FontCharType, RGB, RGB) {
|
/// Gets the renderables for a tile, with darkening/offset/post-processing/etc. Passing a val for "debug" will ignore viewshed.
|
||||||
|
pub fn get_tile_renderables_for_id(
|
||||||
|
idx: usize,
|
||||||
|
map: &Map,
|
||||||
|
other_pos: Option<Point>,
|
||||||
|
debug: Option<bool>
|
||||||
|
) -> (rltk::FontCharType, RGB, RGB) {
|
||||||
let (glyph, mut fg, mut bg) = match map.id {
|
let (glyph, mut fg, mut bg) = match map.id {
|
||||||
2 => get_forest_theme_renderables(idx, map),
|
2 => get_forest_theme_renderables(idx, map, debug),
|
||||||
_ => get_default_theme_renderables(idx, map),
|
_ => get_default_theme_renderables(idx, map, debug),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If one of the colours was left blank, make them the same.
|
// If one of the colours was left blank, make them the same.
|
||||||
|
|
@ -54,7 +60,7 @@ pub fn get_tile_renderables_for_id(idx: usize, map: &Map, other_pos: Option<Poin
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn get_default_theme_renderables(idx: usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) {
|
pub fn get_default_theme_renderables(idx: usize, map: &Map, debug: Option<bool>) -> (rltk::FontCharType, RGB, RGB) {
|
||||||
let glyph: rltk::FontCharType;
|
let glyph: rltk::FontCharType;
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
let mut fg: RGB = RGB::new();
|
let mut fg: RGB = RGB::new();
|
||||||
|
|
@ -65,7 +71,7 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map) -> (rltk::FontCharTy
|
||||||
TileType::Floor => { glyph = rltk::to_cp437(FLOOR_GLYPH); fg = RGB::named(FLOOR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
TileType::Floor => { glyph = rltk::to_cp437(FLOOR_GLYPH); fg = RGB::named(FLOOR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
||||||
TileType::WoodFloor => { glyph = rltk::to_cp437(WOOD_FLOOR_GLYPH); bg = RGB::named(WOOD_FLOOR_COLOUR); }
|
TileType::WoodFloor => { glyph = rltk::to_cp437(WOOD_FLOOR_GLYPH); bg = RGB::named(WOOD_FLOOR_COLOUR); }
|
||||||
TileType::Fence => { glyph = rltk::to_cp437(FENCE_GLYPH); fg = RGB::named(FENCE_FG_COLOUR); bg = RGB::named(FENCE_COLOUR); }
|
TileType::Fence => { glyph = rltk::to_cp437(FENCE_GLYPH); fg = RGB::named(FENCE_FG_COLOUR); bg = RGB::named(FENCE_COLOUR); }
|
||||||
TileType::Wall => { let x = idx as i32 % map.width; let y = idx as i32 / map.width; glyph = wall_glyph(&*map, x, y); fg = RGB::named(WALL_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
TileType::Wall => { let x = idx as i32 % map.width; let y = idx as i32 / map.width; glyph = wall_glyph(&*map, x, y, debug); fg = RGB::named(WALL_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
||||||
TileType::DownStair => { glyph = rltk::to_cp437(DOWN_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
TileType::DownStair => { glyph = rltk::to_cp437(DOWN_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
||||||
TileType::UpStair => { glyph = rltk::to_cp437(UP_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
TileType::UpStair => { glyph = rltk::to_cp437(UP_STAIR_GLYPH); fg = RGB::named(STAIR_COLOUR); bg = RGB::named(DEFAULT_BG_COLOUR); }
|
||||||
TileType::Bridge => { glyph = rltk::to_cp437(BRIDGE_GLYPH); bg = RGB::named(BRIDGE_COLOUR); }
|
TileType::Bridge => { glyph = rltk::to_cp437(BRIDGE_GLYPH); bg = RGB::named(BRIDGE_COLOUR); }
|
||||||
|
|
@ -83,7 +89,7 @@ pub fn get_default_theme_renderables(idx: usize, map: &Map) -> (rltk::FontCharTy
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn get_forest_theme_renderables(idx:usize, map: &Map) -> (rltk::FontCharType, RGB, RGB) {
|
fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option<bool>) -> (rltk::FontCharType, RGB, RGB) {
|
||||||
let glyph;
|
let glyph;
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
let mut fg = RGB::new();
|
let mut fg = RGB::new();
|
||||||
|
|
@ -94,55 +100,55 @@ fn get_forest_theme_renderables(idx:usize, map: &Map) -> (rltk::FontCharType, RG
|
||||||
TileType::Wall => { glyph = rltk::to_cp437(FOREST_WALL_GLYPH); fg = RGB::named(FOREST_WALL_COLOUR); bg = RGB::named(GRASS_COLOUR) }
|
TileType::Wall => { glyph = rltk::to_cp437(FOREST_WALL_GLYPH); fg = RGB::named(FOREST_WALL_COLOUR); bg = RGB::named(GRASS_COLOUR) }
|
||||||
TileType::Road => { glyph = rltk::to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); }
|
TileType::Road => { glyph = rltk::to_cp437(ROAD_GLYPH); bg = RGB::named(ROAD_COLOUR); }
|
||||||
TileType::ShallowWater => { glyph = rltk::to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); }
|
TileType::ShallowWater => { glyph = rltk::to_cp437(SHALLOW_WATER_GLYPH); bg = RGB::named(SHALLOW_WATER_COLOUR); }
|
||||||
_ => { (glyph, fg, _) = get_default_theme_renderables(idx, map); bg = RGB::named(GRASS_COLOUR) }
|
_ => { (glyph, fg, _) = get_default_theme_renderables(idx, map, debug); bg = RGB::named(GRASS_COLOUR) }
|
||||||
}
|
}
|
||||||
|
|
||||||
(glyph, fg, bg)
|
(glyph, fg, bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_revealed_and_wall(map: &Map, x: i32, y: i32) -> bool {
|
fn is_revealed_and_wall(map: &Map, x: i32, y: i32, debug: Option<bool>) -> bool {
|
||||||
let idx = map.xy_idx(x, y);
|
let idx = map.xy_idx(x, y);
|
||||||
map.tiles[idx] == TileType::Wall && map.revealed_tiles[idx]
|
map.tiles[idx] == TileType::Wall && (if debug.is_none() { map.revealed_tiles[idx] } else { true })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wall_glyph(map: &Map, x: i32, y: i32) -> rltk::FontCharType {
|
fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> rltk::FontCharType {
|
||||||
if x < 1 || x > map.width - 2 || y < 1 || y > map.height - (2 as i32) {
|
if x < 1 || x > map.width - 2 || y < 1 || y > map.height - (2 as i32) {
|
||||||
return 35;
|
return 35;
|
||||||
}
|
}
|
||||||
let mut mask: u8 = 0;
|
let mut mask: u8 = 0;
|
||||||
let diagonals_matter: Vec<u8> = vec![7, 11, 13, 14, 15];
|
let diagonals_matter: Vec<u8> = vec![7, 11, 13, 14, 15];
|
||||||
|
|
||||||
if is_revealed_and_wall(map, x, y - 1) {
|
if is_revealed_and_wall(map, x, y - 1, debug) {
|
||||||
// N
|
// N
|
||||||
mask += 1;
|
mask += 1;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x, y + 1) {
|
if is_revealed_and_wall(map, x, y + 1, debug) {
|
||||||
// S
|
// S
|
||||||
mask += 2;
|
mask += 2;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x - 1, y) {
|
if is_revealed_and_wall(map, x - 1, y, debug) {
|
||||||
// W
|
// W
|
||||||
mask += 4;
|
mask += 4;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x + 1, y) {
|
if is_revealed_and_wall(map, x + 1, y, debug) {
|
||||||
// E
|
// E
|
||||||
mask += 8;
|
mask += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if diagonals_matter.contains(&mask) {
|
if diagonals_matter.contains(&mask) {
|
||||||
if is_revealed_and_wall(map, x + 1, y - 1) {
|
if is_revealed_and_wall(map, x + 1, y - 1, debug) {
|
||||||
// Top right
|
// Top right
|
||||||
mask += 16;
|
mask += 16;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x - 1, y - 1) {
|
if is_revealed_and_wall(map, x - 1, y - 1, debug) {
|
||||||
// Top left
|
// Top left
|
||||||
mask += 32;
|
mask += 32;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x + 1, y + 1) {
|
if is_revealed_and_wall(map, x + 1, y + 1, debug) {
|
||||||
// Bottom right
|
// Bottom right
|
||||||
mask += 64;
|
mask += 64;
|
||||||
}
|
}
|
||||||
if is_revealed_and_wall(map, x - 1, y + 1) {
|
if is_revealed_and_wall(map, x - 1, y + 1, debug) {
|
||||||
// Bottom left
|
// Bottom left
|
||||||
mask += 128;
|
mask += 128;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ fn draw_map(ecs: &World) -> String {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
glyph_u16 = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None).0;
|
glyph_u16 = crate::map::themes::get_tile_renderables_for_id(idx, &*map, None, Some(true)).0;
|
||||||
}
|
}
|
||||||
let char = to_char((glyph_u16 & 0xff) as u8);
|
let char = to_char((glyph_u16 & 0xff) as u8);
|
||||||
result.push_str(&char.to_string());
|
result.push_str(&char.to_string());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue