This commit is contained in:
Llywelwyn 2023-08-31 02:00:47 +01:00
parent 45312108af
commit cb7d9082d1
2 changed files with 219 additions and 129 deletions

View file

@ -138,11 +138,18 @@ fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option<bool>) -> (r
fn is_revealed_and_wall(map: &Map, x: i32, y: i32, debug: Option<bool>) -> 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 && (if debug.is_none() { map.revealed_tiles[idx] } else { true }) map.tiles[idx] == TileType::Wall &&
(if debug.is_none() { map.revealed_tiles[idx] } else { true })
} }
fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> 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) || !CONFIG.visuals.use_bitset_walls { if
x < 1 ||
x > map.width - 2 ||
y < 1 ||
y > map.height - (2 as i32) ||
!CONFIG.visuals.use_bitset_walls
{
return 35; return 35;
} }
@ -279,9 +286,19 @@ fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> rltk::FontCharT
} }
} }
fn apply_colour_offset(mut rgb: RGB, map: &Map, idx: usize, offset: (i32, i32, i32), fg: bool) -> RGB { fn apply_colour_offset(
mut rgb: RGB,
map: &Map,
idx: usize,
offset: (i32, i32, i32),
fg: bool
) -> RGB {
let offset_mod = if fg { map.colour_offset[idx].0 } else { map.colour_offset[idx].1 }; let offset_mod = if fg { map.colour_offset[idx].0 } else { map.colour_offset[idx].1 };
let offset = ((offset.0 as f32) * offset_mod.0, (offset.1 as f32) * offset_mod.1, (offset.2 as f32) * offset_mod.2); let offset = (
(offset.0 as f32) * offset_mod.0,
(offset.1 as f32) * offset_mod.1,
(offset.2 as f32) * offset_mod.2,
);
rgb = add_i32_offsets(rgb, offset); rgb = add_i32_offsets(rgb, offset);
return rgb; return rgb;
} }
@ -318,7 +335,12 @@ fn darken_by_distance(pos: Point, other_pos: Point) -> f32 {
let result = let result =
1.0 - 1.0 -
interp_factor * interp_factor *
(1.0 - (if CONFIG.visuals.with_scanlines { MAX_DARKENING_IF_SCANLINES } else { MAX_DARKENING })); (1.0 -
(if CONFIG.visuals.with_scanlines {
MAX_DARKENING_IF_SCANLINES
} else {
MAX_DARKENING
}));
return result; return result;
} }

View file

@ -33,7 +33,6 @@ use super::{
WantsToPickupItem, WantsToPickupItem,
get_dest, get_dest,
Destination, Destination,
Bleeds,
}; };
use rltk::prelude::*; use rltk::prelude::*;
use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode }; use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode };
@ -59,7 +58,12 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut result = RunState::AwaitingInput; let mut result = RunState::AwaitingInput;
let mut door_pos: Option<Point> = None; let mut door_pos: Option<Point> = None;
for (_entity, _player, pos, attributes) in (&entities, &mut players, &mut positions, &attributes).join() { for (_entity, _player, pos, attributes) in (
&entities,
&mut players,
&mut positions,
&attributes,
).join() {
let delta_x = i; let delta_x = i;
let delta_y = j; let delta_y = j;
@ -171,7 +175,12 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut result = RunState::AwaitingInput; let mut result = RunState::AwaitingInput;
let mut door_pos: Option<Point> = None; let mut door_pos: Option<Point> = None;
for (_entity, _player, pos, attributes) in (&entities, &mut players, &mut positions, &attributes).join() { for (_entity, _player, pos, attributes) in (
&entities,
&mut players,
&mut positions,
&attributes,
).join() {
let delta_x = i; let delta_x = i;
let delta_y = j; let delta_y = j;
@ -260,7 +269,12 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
let names = ecs.read_storage::<Name>(); let names = ecs.read_storage::<Name>();
let mut rng = ecs.write_resource::<RandomNumberGenerator>(); let mut rng = ecs.write_resource::<RandomNumberGenerator>();
for (entity, _player, pos, attributes) in (&entities, &mut players, &mut positions, &attributes).join() { for (entity, _player, pos, attributes) in (
&entities,
&mut players,
&mut positions,
&attributes,
).join() {
let delta_x = i; let delta_x = i;
let delta_y = j; let delta_y = j;
@ -276,8 +290,15 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
if !crate::spatial::has_tile_content(destination_idx) { if !crate::spatial::has_tile_content(destination_idx) {
if rng.roll_dice(1, 20) == 20 { if rng.roll_dice(1, 20) == 20 {
add_effect(None, EffectType::Damage { amount: 1 }, Targets::Entity { target: entity }); add_effect(
gamelog::Logger::new().append("Ouch! You kick the open air, and pull something.").log(); None,
EffectType::Damage { amount: 1 },
Targets::Entity { target: entity }
);
gamelog::Logger
::new()
.append("Ouch! You kick the open air, and pull something.")
.log();
break; break;
} else { } else {
// If there's nothing at all, just kick the air and waste a turn. // If there's nothing at all, just kick the air and waste a turn.
@ -288,61 +309,75 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut last_non_door_target: Option<Entity> = None; let mut last_non_door_target: Option<Entity> = None;
let mut target_name = "thing"; let mut target_name = "thing";
let mut colour = WHITE; let mut colour = WHITE;
crate::spatial::for_each_tile_content_with_bool(destination_idx, |potential_target| { crate::spatial::for_each_tile_content_with_bool(
if let Some(name) = names.get(potential_target) { destination_idx,
target_name = &name.name; |potential_target| {
} if let Some(name) = names.get(potential_target) {
let items = ecs.read_storage::<Item>(); target_name = &name.name;
colour = if let Some(_) = items.get(potential_target) { }
item_colour_ecs(ecs, potential_target) let items = ecs.read_storage::<Item>();
} else { colour = if let Some(_) = items.get(potential_target) {
renderable_colour_ecs(ecs, potential_target) item_colour_ecs(ecs, potential_target)
}; } else {
renderable_colour_ecs(ecs, potential_target)
};
// If it's a door, // If it's a door,
let door = doors.get_mut(potential_target); let door = doors.get_mut(potential_target);
if let Some(door) = door { if let Some(door) = door {
// If the door is closed, // If the door is closed,
if door.open == false { if door.open == false {
let mut particle_builder = ecs.write_resource::<ParticleBuilder>(); add_effect(
particle_builder.kick(pos.x + delta_x, pos.y + delta_y); None,
// ~33% chance of breaking it down + str EffectType::Particle {
if rng.roll_dice(1, 10) + attributes.strength.bonus > 6 { glyph: to_cp437('‼'),
gamelog::Logger fg: RGB::named(CHOCOLATE),
::new() bg: RGB::named(BLACK),
.append("As you kick the") lifespan: 150.0,
.colour(colour) delay: 0.0,
.append_n(obfuscate_name_ecs(ecs, potential_target).0) },
.colour(WHITE) Targets::Entity { target: potential_target }
.append(", it crashes open!") );
.log(); // ~33% chance of breaking it down + str
something_was_destroyed = Some(potential_target); if rng.roll_dice(1, 10) + attributes.strength.bonus > 6 {
destroyed_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); gamelog::Logger
gamelog::record_event(EVENT::BROKE_DOOR(1)); ::new()
return false; .append("As you kick the")
// 66% chance of just kicking it. .colour(colour)
} else { .append_n(obfuscate_name_ecs(ecs, potential_target).0)
gamelog::Logger .colour(WHITE)
::new() .append(", it crashes open!")
.append("You kick the") .log();
.colour(colour) something_was_destroyed = Some(potential_target);
.append_n(obfuscate_name_ecs(ecs, potential_target).0) destroyed_pos = Some(
.colour(WHITE) Point::new(pos.x + delta_x, pos.y + delta_y)
.period() );
.log(); gamelog::record_event(EVENT::BROKE_DOOR(1));
return false;
// 66% chance of just kicking it.
} else {
gamelog::Logger
::new()
.append("You kick the")
.colour(colour)
.append_n(obfuscate_name_ecs(ecs, potential_target).0)
.colour(WHITE)
.period()
.log();
return false;
}
// If the door is open and there's nothing else on the tile,
} else if crate::spatial::length(destination_idx) == 1 {
// Just kick the air.
gamelog::Logger::new().append("You kick the open air.").log();
return false; return false;
} }
// If the door is open and there's nothing else on the tile, } else {
} else if crate::spatial::length(destination_idx) == 1 { last_non_door_target = Some(potential_target);
// Just kick the air.
gamelog::Logger::new().append("You kick the open air.").log();
return false;
} }
} else { return true;
last_non_door_target = Some(potential_target);
} }
return true; );
});
if let Some(e) = last_non_door_target { if let Some(e) = last_non_door_target {
gamelog::Logger gamelog::Logger
::new() ::new()
@ -352,8 +387,17 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
.colour(WHITE) .colour(WHITE)
.period() .period()
.log(); .log();
let mut particle_builder = ecs.write_resource::<ParticleBuilder>(); add_effect(
particle_builder.kick(pos.x + delta_x, pos.y + delta_y); None,
EffectType::Particle {
glyph: to_cp437('‼'),
fg: RGB::named(CHOCOLATE),
bg: RGB::named(BLACK),
lifespan: 150.0,
delay: 0.0,
},
Targets::Entity { target: e }
);
// Do something here if it's anything other than a door. // Do something here if it's anything other than a door.
break; break;
} }
@ -393,7 +437,12 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
let mut swap_entities: Vec<(Entity, i32, i32)> = Vec::new(); let mut swap_entities: Vec<(Entity, i32, i32)> = Vec::new();
let mut result: Option<RunState>; let mut result: Option<RunState>;
for (entity, _player, pos, viewshed) in (&entities, &mut players, &mut positions, &mut viewsheds).join() { for (entity, _player, pos, viewshed) in (
&entities,
&mut players,
&mut positions,
&mut viewsheds,
).join() {
if if
pos.x + delta_x < 0 || pos.x + delta_x < 0 ||
pos.x + delta_x > map.width - 1 || pos.x + delta_x > map.width - 1 ||
@ -404,64 +453,69 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
} }
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y); let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
result = crate::spatial::for_each_tile_content_with_runstate(destination_idx, |potential_target| { result = crate::spatial::for_each_tile_content_with_runstate(
let mut hostile = true; destination_idx,
if pools.get(potential_target).is_some() { |potential_target| {
// We get the reaction of the target to this entity -- let mut hostile = true;
// i.e. in reverse to usual. We want to know if the target if pools.get(potential_target).is_some() {
// is hostile to us. If it isn't, we can swap places. // We get the reaction of the target to this entity --
let result = crate::raws::get_reactions( // i.e. in reverse to usual. We want to know if the target
potential_target, // is hostile to us. If it isn't, we can swap places.
entity, let result = crate::raws::get_reactions(
&factions, potential_target,
&ancestries, entity,
&crate::raws::RAWS.lock().unwrap() &factions,
); &ancestries,
if result != Reaction::Attack { &crate::raws::RAWS.lock().unwrap()
hostile = false; );
} if result != Reaction::Attack {
} hostile = false;
if !hostile {
swap_entities.push((potential_target, pos.x, pos.y));
pos.x = min(map.width - 1, max(0, pos.x + delta_x));
pos.y = min(map.height - 1, max(0, pos.y + delta_y));
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
viewshed.dirty = true;
let mut ppos = ecs.write_resource::<Point>();
ppos.x = pos.x;
ppos.y = pos.y;
} else {
let target = pools.get(potential_target);
if let Some(_target) = target {
wants_to_melee
.insert(entity, WantsToMelee { target: potential_target })
.expect("Add target failed.");
return Some(RunState::Ticking);
}
}
let door = doors.get_mut(potential_target);
if let Some(door) = door {
if door.open == false {
if let Some(name) = names.get(potential_target) {
let colour = if let Some(_) = ecs.read_storage::<Item>().get(potential_target) {
item_colour_ecs(ecs, potential_target)
} else {
renderable_colour_ecs(ecs, potential_target)
};
gamelog::Logger
::new()
.append("The")
.colour(colour)
.append_n(&name.name)
.colour(WHITE)
.append("is in your way.")
.log();
} }
return Some(RunState::AwaitingInput);
} }
if !hostile {
swap_entities.push((potential_target, pos.x, pos.y));
pos.x = min(map.width - 1, max(0, pos.x + delta_x));
pos.y = min(map.height - 1, max(0, pos.y + delta_y));
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert marker");
viewshed.dirty = true;
let mut ppos = ecs.write_resource::<Point>();
ppos.x = pos.x;
ppos.y = pos.y;
} else {
let target = pools.get(potential_target);
if let Some(_target) = target {
wants_to_melee
.insert(entity, WantsToMelee { target: potential_target })
.expect("Add target failed.");
return Some(RunState::Ticking);
}
}
let door = doors.get_mut(potential_target);
if let Some(door) = door {
if door.open == false {
if let Some(name) = names.get(potential_target) {
let colour = if
let Some(_) = ecs.read_storage::<Item>().get(potential_target)
{
item_colour_ecs(ecs, potential_target)
} else {
renderable_colour_ecs(ecs, potential_target)
};
gamelog::Logger
::new()
.append("The")
.colour(colour)
.append_n(&name.name)
.colour(WHITE)
.append("is in your way.")
.log();
}
return Some(RunState::AwaitingInput);
}
}
return None;
} }
return None; );
});
if result.is_some() { if result.is_some() {
return result.unwrap(); return result.unwrap();
@ -509,7 +563,10 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
if i > 0 && i < seen_items.len() { if i > 0 && i < seen_items.len() {
logger = logger.append(", a"); logger = logger.append(", a");
} }
logger = logger.colour(seen_items[i].1).append_n(&seen_items[i].0).colour(WHITE); logger = logger
.colour(seen_items[i].1)
.append_n(&seen_items[i].0)
.colour(WHITE);
} }
logger.period().log(); logger.period().log();
} }
@ -628,11 +685,15 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk, on_overmap: bool) -> RunStat
// If we have no destination, do nothing. // If we have no destination, do nothing.
Destination::None => RunState::AwaitingInput, Destination::None => RunState::AwaitingInput,
// If we want to go to the next level, go to the up-stair tile of id + 1. // If we want to go to the next level, go to the up-stair tile of id + 1.
Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), Destination::NextLevel =>
RunState::GoToLevel(curr_map_id + 1, TileType::UpStair),
// If we want to go to the previous level, go to the down-stair tile of id - 1. // If we want to go to the previous level, go to the down-stair tile of id - 1.
Destination::PreviousLevel => RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), Destination::PreviousLevel =>
Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), RunState::GoToLevel(curr_map_id - 1, TileType::DownStair),
Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)), Destination::ToLocal(id) =>
RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)),
Destination::ToOvermap(id) =>
RunState::GoToLevel(id, TileType::ToOvermap(id)),
}; };
} else { } else {
return skip_turn(&mut gs.ecs); // (Wait a turn) return skip_turn(&mut gs.ecs); // (Wait a turn)
@ -644,10 +705,14 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk, on_overmap: bool) -> RunStat
let curr_map_id = gs.ecs.fetch::<Map>().id; let curr_map_id = gs.ecs.fetch::<Map>().id;
return match dest { return match dest {
Destination::None => RunState::AwaitingInput, Destination::None => RunState::AwaitingInput,
Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), Destination::NextLevel =>
Destination::PreviousLevel => RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), RunState::GoToLevel(curr_map_id + 1, TileType::UpStair),
Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), Destination::PreviousLevel =>
Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)), RunState::GoToLevel(curr_map_id - 1, TileType::DownStair),
Destination::ToLocal(id) =>
RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)),
Destination::ToOvermap(id) =>
RunState::GoToLevel(id, TileType::ToOvermap(id)),
}; };
} }
} }
@ -696,7 +761,10 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk, on_overmap: bool) -> RunStat
return RunState::SaveGame; return RunState::SaveGame;
} }
VirtualKeyCode::X => { VirtualKeyCode::X => {
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs, ctx); let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(
&gs.ecs,
ctx
);
let ppos = gs.ecs.fetch::<Point>(); let ppos = gs.ecs.fetch::<Point>();
let (x, y) = (ppos.x + x_offset - min_x, ppos.y + y_offset - min_y); let (x, y) = (ppos.x + x_offset - min_x, ppos.y + y_offset - min_y);
return RunState::Farlook { x, y }; return RunState::Farlook { x, y };