blindness improves telepathy, and reduces to-hit

This commit is contained in:
Llywelwyn 2023-08-22 16:16:56 +01:00
parent 0208dcac4c
commit 1714b94397
5 changed files with 45 additions and 15 deletions

View file

@ -63,7 +63,7 @@ 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 bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) { let mut bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) {
crate::map::themes::get_tile_renderables_for_id(idx, &*map).2 crate::map::themes::get_tile_renderables_for_id(idx, &*map).2
} else { } else {
render.bg render.bg
@ -76,10 +76,15 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
// We don't darken BG, because get_tile_renderables_for_id handles this. // We don't darken BG, because get_tile_renderables_for_id handles this.
} }
// Draw entities with minds within telepath range // Draw entities with minds within telepath range
if map.telepath_tiles[idx] { if !draw {
let has_mind = minds.get(*ent); if map.telepath_tiles[idx] {
if let Some(_) = has_mind { let has_mind = minds.get(*ent);
draw = true; if let Some(_) = has_mind {
draw = true;
if !map.revealed_tiles[idx] {
bg = RGB::named(BLACK);
}
}
} }
} }
// Draw all props // Draw all props

View file

@ -361,6 +361,9 @@ pub struct Confusion {
pub turns: i32, pub turns: i32,
} }
#[derive(Component, Serialize, Deserialize, Clone)]
pub struct Blind {}
#[derive(Component, Serialize, Deserialize, Clone)] #[derive(Component, Serialize, Deserialize, Clone)]
pub struct MagicMapper {} pub struct MagicMapper {}

View file

@ -619,6 +619,7 @@ fn main() -> rltk::BError {
gs.ecs.register::<AOE>(); gs.ecs.register::<AOE>();
gs.ecs.register::<Digger>(); gs.ecs.register::<Digger>();
gs.ecs.register::<Confusion>(); gs.ecs.register::<Confusion>();
gs.ecs.register::<Blind>();
gs.ecs.register::<MagicMapper>(); gs.ecs.register::<MagicMapper>();
gs.ecs.register::<InBackpack>(); gs.ecs.register::<InBackpack>();
gs.ecs.register::<WantsToApproach>(); gs.ecs.register::<WantsToApproach>();

View file

@ -2,8 +2,8 @@ use super::{
effects::{add_effect, EffectType, Targets}, effects::{add_effect, EffectType, Targets},
gamelog, gamesystem, gamelog, gamesystem,
gui::renderable_colour, gui::renderable_colour,
ArmourClassBonus, Attributes, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon, MultiAttack, Name, ArmourClassBonus, Attributes, Blind, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon, MultiAttack,
NaturalAttacks, ParticleBuilder, Pools, Position, Renderable, Skill, Skills, ToHitBonus, WantsToMelee, Name, NaturalAttacks, ParticleBuilder, Pools, Position, Renderable, Skill, Skills, ToHitBonus, WantsToMelee,
WeaponAttribute, WeaponAttribute,
}; };
use rltk::prelude::*; use rltk::prelude::*;
@ -30,6 +30,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
ReadStorage<'a, ToHitBonus>, ReadStorage<'a, ToHitBonus>,
ReadStorage<'a, HungerClock>, ReadStorage<'a, HungerClock>,
ReadStorage<'a, MultiAttack>, ReadStorage<'a, MultiAttack>,
ReadStorage<'a, Blind>,
WriteExpect<'a, rltk::RandomNumberGenerator>, WriteExpect<'a, rltk::RandomNumberGenerator>,
); );
@ -52,6 +53,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
to_hit, to_hit,
hunger_clock, hunger_clock,
multi_attackers, multi_attackers,
blind_entities,
mut rng, mut rng,
) = data; ) = data;
@ -119,10 +121,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
if target_pools.hit_points.current <= 0 { if target_pools.hit_points.current <= 0 {
break; break;
} }
let weapon_info = attack.0; let weapon_info = attack.0;
let attack_verb = attack.1; let attack_verb = attack.1;
// Get all offensive bonuses // Get all offensive bonuses
let d20 = rng.roll_dice(1, 20); let d20 = rng.roll_dice(1, 20);
let attribute_hit_bonus = attacker_attributes.dexterity.bonus; let attribute_hit_bonus = attacker_attributes.dexterity.bonus;
@ -134,6 +134,9 @@ impl<'a> System<'a> for MeleeCombatSystem {
} }
} }
let mut status_hit_bonus = 0; let mut status_hit_bonus = 0;
if let Some(_) = blind_entities.get(entity) {
status_hit_bonus -= 4;
};
let hc = hunger_clock.get(entity); let hc = hunger_clock.get(entity);
if let Some(hc) = hc { if let Some(hc) = hc {
match hc.state { match hc.state {

View file

@ -1,9 +1,11 @@
use super::{gamelog, BlocksVisibility, Hidden, Map, Name, Player, Position, Telepath, Viewshed}; use super::{gamelog, Blind, BlocksVisibility, Hidden, Map, Name, Player, Position, Telepath, Viewshed};
use rltk::{FieldOfViewAlg::SymmetricShadowcasting, Point}; use rltk::{FieldOfViewAlg::SymmetricShadowcasting, Point};
use specs::prelude::*; use specs::prelude::*;
pub struct VisibilitySystem {} pub struct VisibilitySystem {}
const BLIND_TELEPATHY_RANGE_MULTIPLIER: i32 = 3;
impl<'a> System<'a> for VisibilitySystem { impl<'a> System<'a> for VisibilitySystem {
type SystemData = ( type SystemData = (
WriteExpect<'a, Map>, WriteExpect<'a, Map>,
@ -15,12 +17,24 @@ impl<'a> System<'a> for VisibilitySystem {
ReadStorage<'a, Player>, ReadStorage<'a, Player>,
WriteStorage<'a, Hidden>, WriteStorage<'a, Hidden>,
ReadStorage<'a, Name>, ReadStorage<'a, Name>,
ReadStorage<'a, Blind>,
ReadStorage<'a, BlocksVisibility>, ReadStorage<'a, BlocksVisibility>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
let (mut map, mut rng, entities, mut viewshed, mut telepath, pos, player, mut hidden, names, blocks_visibility) = let (
data; mut map,
mut rng,
entities,
mut viewshed,
mut telepath,
pos,
player,
mut hidden,
names,
blind_entities,
blocks_visibility,
) = data;
map.view_blocked.clear(); map.view_blocked.clear();
for (block_pos, _block) in (&pos, &blocks_visibility).join() { for (block_pos, _block) in (&pos, &blocks_visibility).join() {
@ -31,8 +45,9 @@ impl<'a> System<'a> for VisibilitySystem {
for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() { for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() {
if viewshed.dirty { if viewshed.dirty {
viewshed.dirty = false; viewshed.dirty = false;
let mut range = if let Some(is_blind) = blind_entities.get(ent) { 1 } else { viewshed.range };
let origin = Point::new(pos.x, pos.y); let origin = Point::new(pos.x, pos.y);
viewshed.visible_tiles = SymmetricShadowcasting.field_of_view(origin, viewshed.range, &*map); viewshed.visible_tiles = SymmetricShadowcasting.field_of_view(origin, range, &*map);
viewshed.visible_tiles.retain(|p| { viewshed.visible_tiles.retain(|p| {
p.x >= 0 p.x >= 0
&& p.x < map.width && p.x < map.width
@ -78,8 +93,11 @@ impl<'a> System<'a> for VisibilitySystem {
for (ent, telepath, pos) in (&entities, &mut telepath, &pos).join() { for (ent, telepath, pos) in (&entities, &mut telepath, &pos).join() {
if telepath.dirty { if telepath.dirty {
telepath.dirty = false; telepath.dirty = false;
let mut range = telepath.range;
telepath.telepath_tiles = fast_fov(pos.x, pos.y, telepath.range); if let Some(is_blind) = blind_entities.get(ent) {
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
}
telepath.telepath_tiles = fast_fov(pos.x, pos.y, range);
telepath.telepath_tiles.retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height); telepath.telepath_tiles.retain(|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height);
// If this is the player, reveal what they can see // If this is the player, reveal what they can see