1
0
Fork 0
roguelike-game/src/gui/hud.rs

277 lines
8.8 KiB
Rust

use std::cmp::Ordering;
use ::rltk::prelude::*;
use ::rltk::{Point, Rltk};
use ::specs::prelude::*;
use super::{draw_tooltips, get_item_color, get_item_display_name};
use crate::components::{
Attribute, Attributes, Consumable, Duration, Equipped, HungerClock, HungerState, InBackpack,
KnownSpells, Name, Pools, StatusEffect, Weapon,
};
use crate::{colors, gamelog, Map};
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
ctx.draw_hollow_box(0, 0, 79, 59, colors::BOX_GRAY, colors::BLACK); // Overall box
ctx.draw_hollow_box(0, 0, 49, 45, colors::BOX_GRAY, colors::BLACK); // Map box
ctx.draw_hollow_box(0, 45, 79, 14, colors::BOX_GRAY, colors::BLACK); // Log box
ctx.draw_hollow_box(49, 0, 30, 8, colors::BOX_GRAY, colors::BLACK); // Top-right panel
ctx.set(0, 45, colors::BOX_GRAY, colors::BLACK, to_cp437('├'));
ctx.set(49, 8, colors::BOX_GRAY, colors::BLACK, to_cp437('├'));
ctx.set(49, 0, colors::BOX_GRAY, colors::BLACK, to_cp437('┬'));
ctx.set(49, 45, colors::BOX_GRAY, colors::BLACK, to_cp437('┴'));
ctx.set(79, 8, colors::BOX_GRAY, colors::BLACK, to_cp437('┤'));
ctx.set(79, 45, colors::BOX_GRAY, colors::BLACK, to_cp437('┤'));
// Draw the town name
let map = ecs.fetch::<Map>();
let name_length = map.name.len() + 2;
let x_pos = (22 - (name_length / 2)) as i32;
ctx.set(x_pos, 0, colors::BOX_GRAY, colors::BLACK, to_cp437('┤'));
ctx.set(
x_pos + name_length as i32,
0,
colors::BOX_GRAY,
colors::BLACK,
to_cp437('├'),
);
ctx.print_color(x_pos + 1, 0, colors::WHITE, colors::BLACK, &map.name);
std::mem::drop(map);
// Draw stats
let player_entity = ecs.fetch::<Entity>();
let pools = ecs.read_storage::<Pools>();
let player_pools = pools.get(*player_entity).unwrap();
let health = format!(
"Health: {}/{}",
player_pools.hit_points.current, player_pools.hit_points.max
);
let mana = format!(
"Mana: {}/{}",
player_pools.mana.current, player_pools.mana.max
);
let xp = format!("Level: {}", player_pools.level);
ctx.print_color(50, 1, colors::WHITE, colors::BLACK, &health);
ctx.print_color(50, 2, colors::WHITE, colors::BLACK, &mana);
ctx.print_color(50, 3, colors::WHITE, colors::BLACK, &xp);
ctx.draw_bar_horizontal(
64,
1,
14,
player_pools.hit_points.current,
player_pools.hit_points.max,
colors::RED,
colors::BLACK,
);
ctx.draw_bar_horizontal(
64,
2,
14,
player_pools.mana.current,
player_pools.mana.max,
colors::BLUE,
colors::BLACK,
);
let xp_level_start = (player_pools.level - 1) * 1000;
ctx.draw_bar_horizontal(
64,
3,
14,
player_pools.xp - xp_level_start,
1000,
colors::GOLD,
colors::BLACK,
);
// Attributes
let attributes = ecs.read_storage::<Attributes>();
let attr = attributes.get(*player_entity).unwrap();
draw_attribute("Might:", &attr.might, 4, ctx);
draw_attribute("Quickness:", &attr.quickness, 5, ctx);
draw_attribute("Fitness:", &attr.fitness, 6, ctx);
draw_attribute("Intelligence:", &attr.intelligence, 7, ctx);
// Initiative and weight
ctx.print_color(
50,
9,
colors::WHITE,
colors::BLACK,
&format!(
"{:.0} lbs ({} lbs max)",
player_pools.total_weight,
(attr.might.base + attr.might.modifiers) * 15
),
);
ctx.print_color(
50,
10,
colors::WHITE,
colors::BLACK,
&format!(
"Initiative Penalty: {:.0}",
player_pools.total_initiative_penalty
),
);
ctx.print_color(
50,
11,
colors::GOLD,
colors::BLACK,
&format!("Gold: {:.1}", player_pools.gold),
);
// Equipped
let mut y = 13;
let entities = ecs.entities();
let equipped = ecs.read_storage::<Equipped>();
let weapon = ecs.read_storage::<Weapon>();
for (entity, equipped_by) in (&entities, &equipped).join() {
if equipped_by.owner == *player_entity {
let name = get_item_display_name(ecs, entity);
ctx.print_color(50, y, get_item_color(ecs, entity), colors::BLACK, &name);
y += 1;
if let Some(weapon) = weapon.get(entity) {
let mut weapon_info = match weapon.damage_bonus.cmp(&0) {
Ordering::Less => {
format!(
"{} ({}d{}{})",
&name,
weapon.damage_n_dice,
weapon.damage_die_type,
weapon.damage_bonus
)
}
Ordering::Equal => {
format!(
"{} ({}d{})",
&name, weapon.damage_n_dice, weapon.damage_die_type
)
}
Ordering::Greater => {
format!(
"{} ({}d{}+{})",
&name,
weapon.damage_n_dice,
weapon.damage_die_type,
weapon.damage_bonus
)
}
};
if let Some(range) = weapon.range {
weapon_info += &format!(" (range: {}, F to fire, V cycle targets)", range);
}
weapon_info += "";
ctx.print_color(3, 45, colors::YELLOW, colors::BLACK, &weapon_info);
}
}
}
// Consumables
y += 1;
let consumables = ecs.read_storage::<Consumable>();
let backpack = ecs.read_storage::<InBackpack>();
let mut index = 1;
for (entity, carried_by, _consumable) in (&entities, &backpack, &consumables).join() {
if carried_by.owner == *player_entity && index < 10 {
ctx.print_color(50, y, colors::YELLOW, colors::BLACK, &format!("{}", index));
ctx.print_color(
53,
y,
get_item_color(ecs, entity),
colors::BLACK,
&get_item_display_name(ecs, entity),
);
y += 1;
index += 1;
}
}
// Spells
y += 1;
let known_spells_storage = ecs.read_storage::<KnownSpells>();
let known_spells = &known_spells_storage.get(*player_entity).unwrap().spells;
let mut index = 1;
for spell in known_spells.iter() {
ctx.print_color(50, y, colors::CYAN, colors::BLACK, &format!("^{}", index));
ctx.print_color(
53,
y,
colors::CYAN,
colors::BLACK,
&format!("{} ({})", spell.display_name, spell.mana_cost),
);
index += 1;
y += 1;
}
// Status
y = 44;
let hunger = ecs.read_storage::<HungerClock>();
let hc = hunger.get(*player_entity).unwrap();
match hc.state {
HungerState::WellFed => {
ctx.print_color(50, y, colors::GREEN, colors::BLACK, "Well Fed");
y -= 1;
}
HungerState::Normal => {}
HungerState::Hungry => {
ctx.print_color(50, y, colors::ORANGE, colors::BLACK, "Hungry");
y -= 1;
}
HungerState::Starving => {
ctx.print_color(50, y, colors::RED, colors::BLACK, "Starving");
y -= 1;
}
}
let statuses = ecs.read_storage::<StatusEffect>();
let durations = ecs.read_storage::<Duration>();
let names = ecs.read_storage::<Name>();
for (status, duration, name) in (&statuses, &durations, &names).join() {
if status.target == *player_entity {
ctx.print_color(
50,
y,
colors::RED,
colors::BLACK,
&format!("{} ({})", name.name, duration.turns),
);
y -= 1;
}
}
// Draw the log
gamelog::print_log(
&mut ::rltk::BACKEND_INTERNAL.lock().consoles[1].console,
Point::new(1, 23),
);
draw_tooltips(ecs, ctx);
}
fn draw_attribute(name: &str, attribute: &Attribute, y: i32, ctx: &mut Rltk) {
ctx.print_color(50, y, colors::ATTR_GRAY, colors::BLACK, name);
let color = match attribute.modifiers.cmp(&0) {
Ordering::Less => colors::RED,
Ordering::Equal => colors::WHITE,
Ordering::Greater => colors::GREEN,
};
ctx.print_color(
67,
y,
color,
colors::BLACK,
&format!("{}", attribute.base + attribute.modifiers),
);
ctx.print_color(73, y, color, colors::BLACK, &format!("{}", attribute.bonus));
if attribute.bonus > 0 {
ctx.set(72, y, color, colors::BLACK, rltk::to_cp437('+'));
}
}