sorry - swapping from rustfmt to prettier-rust
This commit is contained in:
parent
281396f9ce
commit
c2c7e0bd52
93 changed files with 2797 additions and 2021 deletions
3
.prettierrc.json
Normal file
3
.prettierrc.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"printWidth": 120
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ use rltk::RGB;
|
|||
// third alternative is directly setting the desaturated value, if it
|
||||
// is known in advance.
|
||||
fn nonvisible_benchmark(c: &mut Criterion) {
|
||||
let bg = black_box(RGB::from_f32(0.4, 0., 0.));
|
||||
let bg = black_box(RGB::from_f32(0.4, 0.0, 0.0));
|
||||
|
||||
c.bench_function("rgb -> greyscale", |b| b.iter(|| bg.to_greyscale()));
|
||||
c.bench_function("rgb -> desaturate", |b| b.iter(|| bg.desaturate()));
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
"renderable": { "glyph": "@", "fg": "#034efc", "bg": "#000000", "order": 1 },
|
||||
"flags": ["NEUTRAL", "RANDOM_PATH", "IS_HUMAN"],
|
||||
"level": 2,
|
||||
"vision_range": 4,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d8" }],
|
||||
"equipped": ["equip_shortsword", "equip_body_leather"],
|
||||
"quips": ["You wont catch me down the mine.", "Staying out of trouble?"]
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
"renderable": { "glyph": "r", "fg": "#aa6000", "bg": "#000000", "order": 1 },
|
||||
"flags": [],
|
||||
"bac": 6,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }],
|
||||
"loot": { "table": "food", "chance": 0.1 }
|
||||
},
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
"renderable": { "glyph": "c", "fg": "#BB6000", "bg": "#000000", "order": 1 },
|
||||
"flags": ["HERBIVORE"],
|
||||
"bac": 8,
|
||||
"vision_range": 4,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
"renderable": { "glyph": "q", "fg": "#a57037", "bg": "#000000", "order": 1 },
|
||||
"flags": ["HERBIVORE"],
|
||||
"bac": 8,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -101,7 +101,7 @@
|
|||
"renderable": { "glyph": "q", "fg": "#e7e7e7", "bg": "#000000", "order": 1 },
|
||||
"flags": ["HERBIVORE", "SMALL_GROUP"],
|
||||
"bac": 10,
|
||||
"vision_range": 4,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -110,7 +110,7 @@
|
|||
"renderable": { "glyph": "c", "fg": "#fae478", "bg": "#000000", "order": 1 },
|
||||
"flags": ["HERBIVORE"],
|
||||
"bac": 10,
|
||||
"vision_range": 4,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
"level": 3,
|
||||
"bac": 6,
|
||||
"speed": 16,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [
|
||||
{ "name": "kicks", "hit_bonus": 0, "damage": "1d6" },
|
||||
{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
"level": 5,
|
||||
"bac": 5,
|
||||
"speed": 20,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [
|
||||
{ "name": "kicks", "hit_bonus": 0, "damage": "1d8" },
|
||||
{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
"level": 7,
|
||||
"bac": 4,
|
||||
"speed": 24,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [
|
||||
{ "name": "kicks", "hit_bonus": 0, "damage": "1d10" },
|
||||
{ "name": "bites", "hit_bonus": 0, "damage": "1d4" }
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
"flags": ["SMALL_GROUP"],
|
||||
"level": 1,
|
||||
"bac": 7,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }],
|
||||
"loot": { "table": "scrolls", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -175,7 +175,7 @@
|
|||
"level": 2,
|
||||
"bac": 6,
|
||||
"speed": 18,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"quips": ["<woof!>", "<bark!>", "<grrr..>"],
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d6" }]
|
||||
},
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
"level": 4,
|
||||
"bac": 5,
|
||||
"speed": 16,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d6" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
"level": 6,
|
||||
"bac": 4,
|
||||
"speed": 15,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "2d4" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
"flags": ["SMALL_GROUP", "IS_GNOME"],
|
||||
"level": 1,
|
||||
"speed": 6,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "wands", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -219,7 +219,7 @@
|
|||
"flags": ["MINDLESS"],
|
||||
"level": 1,
|
||||
"speed": 6,
|
||||
"vision_range": 7,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d4" }],
|
||||
"loot": { "table": "wands", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -230,7 +230,7 @@
|
|||
"flags": [],
|
||||
"level": 1,
|
||||
"speed": 9,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d4" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -240,7 +240,7 @@
|
|||
"flags": [],
|
||||
"level": 1,
|
||||
"speed": 6,
|
||||
"vision_range": 7,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d4" }],
|
||||
"loot": { "table": "food", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -251,7 +251,7 @@
|
|||
"flags": ["MINDLESS"],
|
||||
"level": 1,
|
||||
"speed": 6,
|
||||
"vision_range": 7,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d4" }],
|
||||
"loot": { "table": "scrolls", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -262,7 +262,7 @@
|
|||
"flags": [],
|
||||
"level": 1,
|
||||
"speed": 6,
|
||||
"vision_range": 8,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "food", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
"level": 2,
|
||||
"bac": 9,
|
||||
"speed": 6,
|
||||
"vision_range": 8,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "potions", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -286,7 +286,7 @@
|
|||
"level": 2,
|
||||
"bac": 10,
|
||||
"speed": 6,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hacks", "hit_bonus": 0, "damage": "1d8" }],
|
||||
"equipped": ["equip_feet_iron"],
|
||||
"loot": { "table": "equipment", "chance": 0.05 }
|
||||
|
|
@ -299,7 +299,7 @@
|
|||
"level": 2,
|
||||
"bac": 9,
|
||||
"speed": 6,
|
||||
"vision_range": 8,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "equipment", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -310,7 +310,7 @@
|
|||
"flags": [],
|
||||
"level": 2,
|
||||
"speed": 6,
|
||||
"vision_range": 7,
|
||||
"vision_range": 12,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "2d4" }],
|
||||
"loot": { "table": "food", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -322,7 +322,7 @@
|
|||
"level": 1,
|
||||
"bac": 3,
|
||||
"speed": 12,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }],
|
||||
"loot": { "table": "scrolls", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -332,7 +332,7 @@
|
|||
"renderable": { "glyph": "d", "fg": "#AA5500", "bg": "#000000", "order": 1 },
|
||||
"flags": ["CARNIVORE", "SMALL_GROUP"],
|
||||
"bac": 7,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -341,7 +341,7 @@
|
|||
"renderable": { "glyph": "d", "fg": "#FF0000", "bg": "#000000", "order": 1 },
|
||||
"flags": ["CARNIVORE"],
|
||||
"bac": 7,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -351,7 +351,7 @@
|
|||
"flags": ["CARNIVORE", "SMALL_GROUP"],
|
||||
"level": 1,
|
||||
"bac": 7,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d4" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -361,7 +361,7 @@
|
|||
"flags": ["CARNIVORE"],
|
||||
"level": 5,
|
||||
"bac": 4,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "2d4" }]
|
||||
},
|
||||
{
|
||||
|
|
@ -371,7 +371,7 @@
|
|||
"flags": [],
|
||||
"level": 2,
|
||||
"speed": 9,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d8" }],
|
||||
"loot": { "table": "wands", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -382,7 +382,7 @@
|
|||
"flags": ["SMALL_GROUP"],
|
||||
"level": 1,
|
||||
"speed": 9,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "equipment", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -393,7 +393,7 @@
|
|||
"flags": ["LARGE_GROUP"],
|
||||
"level": 2,
|
||||
"speed": 9,
|
||||
"vision_range": 11,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }],
|
||||
"loot": { "table": "equipment", "chance": 0.05 }
|
||||
},
|
||||
|
|
@ -404,7 +404,7 @@
|
|||
"flags": ["MULTIATTACK"],
|
||||
"level": 5,
|
||||
"speed": 5,
|
||||
"vision_range": 12,
|
||||
"vision_range": 16,
|
||||
"attacks": [
|
||||
{ "name": "hits", "hit_bonus": 0, "damage": "2d4" },
|
||||
{ "name": "hits", "hit_bonus": 0, "damage": "2d4" }
|
||||
|
|
@ -419,7 +419,7 @@
|
|||
"level": 5,
|
||||
"bac": 5,
|
||||
"speed": 10,
|
||||
"vision_range": 8,
|
||||
"vision_range": 16,
|
||||
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "2d5" }],
|
||||
"loot": { "table": "food", "chance": 0.05 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,22 +34,22 @@ impl<'a> System<'a> for AdjacentAI {
|
|||
evaluate(entity, idx + 1, &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y > 0 {
|
||||
evaluate(entity, idx - w as usize, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx - (w as usize), &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y < h - 1 {
|
||||
evaluate(entity, idx + w as usize, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx + (w as usize), &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y > 0 && pos.x > 0 {
|
||||
evaluate(entity, (idx - w as usize) - 1, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx - (w as usize) - 1, &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y > 0 && pos.x < w - 1 {
|
||||
evaluate(entity, (idx - w as usize) + 1, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx - (w as usize) + 1, &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y < h - 1 && pos.x > 0 {
|
||||
evaluate(entity, (idx + w as usize) - 1, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx + (w as usize) - 1, &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
if pos.y < h - 1 && pos.x < w - 1 {
|
||||
evaluate(entity, (idx + w as usize) + 1, &ancestries, &factions, &mut reactions);
|
||||
evaluate(entity, idx + (w as usize) + 1, &ancestries, &factions, &mut reactions);
|
||||
}
|
||||
|
||||
let mut done = false;
|
||||
|
|
@ -79,7 +79,7 @@ fn evaluate(
|
|||
idx: usize,
|
||||
ancestries: &ReadStorage<HasAncestry>,
|
||||
factions: &ReadStorage<Faction>,
|
||||
reactions: &mut Vec<(Entity, Reaction)>,
|
||||
reactions: &mut Vec<(Entity, Reaction)>
|
||||
) {
|
||||
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
||||
let result = crate::raws::get_reactions(
|
||||
|
|
@ -87,7 +87,7 @@ fn evaluate(
|
|||
other_entity,
|
||||
&factions,
|
||||
&ancestries,
|
||||
&crate::raws::RAWS.lock().unwrap(),
|
||||
&crate::raws::RAWS.lock().unwrap()
|
||||
);
|
||||
reactions.push((other_entity, result));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,19 +29,23 @@ impl<'a> System<'a> for ApproachAI {
|
|||
entities,
|
||||
) = data;
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, mut pos, approach, mut viewshed, _turn) in
|
||||
(&entities, &mut positions, &wants_to_approach, &mut viewsheds, &turns).join()
|
||||
{
|
||||
for (entity, mut pos, approach, mut viewshed, _turn) in (
|
||||
&entities,
|
||||
&mut positions,
|
||||
&wants_to_approach,
|
||||
&mut viewsheds,
|
||||
&turns,
|
||||
).join() {
|
||||
turn_done.push(entity);
|
||||
let path = a_star_search(
|
||||
map.xy_idx(pos.x, pos.y) as i32,
|
||||
map.xy_idx(approach.idx % map.width, approach.idx / map.width) as i32,
|
||||
&mut *map,
|
||||
&mut *map
|
||||
);
|
||||
if path.success && path.steps.len() > 1 {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
pos.x = path.steps[1] as i32 % map.width;
|
||||
pos.y = path.steps[1] as i32 / map.width;
|
||||
pos.x = (path.steps[1] as i32) % map.width;
|
||||
pos.y = (path.steps[1] as i32) / map.width;
|
||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
crate::spatial::move_entity(entity, idx, new_idx);
|
||||
|
|
|
|||
|
|
@ -48,20 +48,24 @@ impl<'a> System<'a> for ChaseAI {
|
|||
// stored in the HashMap. If successful, follow the path. If not, remove
|
||||
// the chasing component.
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, _turn, mut pos, _chase, mut viewshed) in
|
||||
(&entities, &turns, &mut positions, &chasing, &mut viewsheds).join()
|
||||
{
|
||||
for (entity, _turn, mut pos, _chase, mut viewshed) in (
|
||||
&entities,
|
||||
&turns,
|
||||
&mut positions,
|
||||
&chasing,
|
||||
&mut viewsheds,
|
||||
).join() {
|
||||
turn_done.push(entity);
|
||||
let target_pos = targets[&entity];
|
||||
let path = a_star_search(
|
||||
map.xy_idx(pos.x, pos.y) as i32,
|
||||
map.xy_idx(target_pos.0, target_pos.1) as i32,
|
||||
&mut *map,
|
||||
&mut *map
|
||||
);
|
||||
if path.success && path.steps.len() > 1 && path.steps.len() < MAX_CHASE_DISTANCE {
|
||||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
pos.x = path.steps[1] as i32 % map.width;
|
||||
pos.y = path.steps[1] as i32 / map.width;
|
||||
pos.x = (path.steps[1] as i32) % map.width;
|
||||
pos.y = (path.steps[1] as i32) / map.width;
|
||||
entity_moved.insert(entity, EntityMoved {}).expect("Failed to insert EntityMoved");
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
crate::spatial::move_entity(entity, idx, new_idx);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,13 @@ impl<'a> System<'a> for DefaultAI {
|
|||
entities,
|
||||
) = data;
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, _turn, mut pos, mut move_mode, mut viewshed) in
|
||||
(&entities, &turns, &mut positions, &mut move_mode, &mut viewsheds).join()
|
||||
{
|
||||
for (entity, _turn, mut pos, mut move_mode, mut viewshed) in (
|
||||
&entities,
|
||||
&turns,
|
||||
&mut positions,
|
||||
&mut move_mode,
|
||||
&mut viewsheds,
|
||||
).join() {
|
||||
turn_done.push(entity);
|
||||
match &mut move_mode.mode {
|
||||
Movement::Static => {}
|
||||
|
|
@ -44,25 +48,33 @@ impl<'a> System<'a> for DefaultAI {
|
|||
let mut y = pos.y;
|
||||
let move_roll = rng.roll_dice(1, 8 + CHANCE_OF_REMAINING_STATIONARY);
|
||||
match move_roll {
|
||||
1 => x -= 1,
|
||||
2 => x += 1,
|
||||
3 => y -= 1,
|
||||
4 => y += 1,
|
||||
1 => {
|
||||
x -= 1;
|
||||
}
|
||||
2 => {
|
||||
x += 1;
|
||||
}
|
||||
3 => {
|
||||
y -= 1;
|
||||
}
|
||||
4 => {
|
||||
y += 1;
|
||||
}
|
||||
5 => {
|
||||
x -= 1;
|
||||
y -= 1
|
||||
y -= 1;
|
||||
}
|
||||
6 => {
|
||||
x += 1;
|
||||
y -= 1
|
||||
y -= 1;
|
||||
}
|
||||
7 => {
|
||||
x -= 1;
|
||||
y += 1
|
||||
y += 1;
|
||||
}
|
||||
8 => {
|
||||
x += 1;
|
||||
y += 1
|
||||
y += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -88,8 +100,8 @@ impl<'a> System<'a> for DefaultAI {
|
|||
let idx = map.xy_idx(pos.x, pos.y);
|
||||
if path.len() > 1 {
|
||||
if !crate::spatial::is_blocked(path[1] as usize) {
|
||||
pos.x = path[1] as i32 % map.width;
|
||||
pos.y = path[1] as i32 / map.width;
|
||||
pos.x = (path[1] as i32) % map.width;
|
||||
pos.y = (path[1] as i32) / map.width;
|
||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
||||
let new_idx = map.xy_idx(pos.x, pos.y);
|
||||
crate::spatial::move_entity(entity, idx, new_idx);
|
||||
|
|
@ -110,10 +122,12 @@ impl<'a> System<'a> for DefaultAI {
|
|||
let path = rltk::a_star_search(
|
||||
map.xy_idx(pos.x, pos.y) as i32,
|
||||
map.xy_idx(target_x, target_y) as i32,
|
||||
&mut *map,
|
||||
&mut *map
|
||||
);
|
||||
if path.success && path.steps.len() > 1 {
|
||||
move_mode.mode = Movement::RandomWaypoint { path: Some(path.steps) };
|
||||
move_mode.mode = Movement::RandomWaypoint {
|
||||
path: Some(path.steps),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl<'a> System<'a> for EncumbranceSystem {
|
|||
if let Some(attr) = attributes.get(*entity) {
|
||||
let carry_capacity_lbs =
|
||||
(attr.strength.base + attr.strength.modifiers) * CARRY_CAPACITY_PER_STRENGTH;
|
||||
if pool.weight as i32 > 3 * carry_capacity_lbs {
|
||||
if (pool.weight as i32) > 3 * carry_capacity_lbs {
|
||||
// Overloaded
|
||||
burdened
|
||||
.insert(*entity, Burden { level: crate::BurdenLevel::Overloaded })
|
||||
|
|
@ -60,7 +60,7 @@ impl<'a> System<'a> for EncumbranceSystem {
|
|||
if *entity == *player {
|
||||
gamelog::Logger::new().append("You're overloaded!").log();
|
||||
}
|
||||
} else if pool.weight as i32 > 2 * carry_capacity_lbs {
|
||||
} else if (pool.weight as i32) > 2 * carry_capacity_lbs {
|
||||
// Strained
|
||||
burdened
|
||||
.insert(*entity, Burden { level: crate::BurdenLevel::Strained })
|
||||
|
|
@ -68,7 +68,7 @@ impl<'a> System<'a> for EncumbranceSystem {
|
|||
if *entity == *player {
|
||||
gamelog::Logger::new().append("You're strained.").log();
|
||||
}
|
||||
} else if pool.weight as i32 > carry_capacity_lbs {
|
||||
} else if (pool.weight as i32) > carry_capacity_lbs {
|
||||
// Burdened
|
||||
burdened
|
||||
.insert(*entity, Burden { level: crate::BurdenLevel::Burdened })
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl<'a> System<'a> for EnergySystem {
|
|||
1.0
|
||||
};
|
||||
// Every entity has a POTENTIAL equal to their speed.
|
||||
let mut energy_potential: i32 = (energy.speed as f32 * burden_modifier) as i32;
|
||||
let mut energy_potential: i32 = ((energy.speed as f32) * burden_modifier) as i32;
|
||||
// Increment current energy by NORMAL_SPEED for every
|
||||
// whole number of NORMAL_SPEEDS in their POTENTIAL.
|
||||
while energy_potential >= NORMAL_SPEED {
|
||||
|
|
@ -103,10 +103,9 @@ impl<'a> System<'a> for EnergySystem {
|
|||
turns.insert(entity, TakingTurn {}).expect("Unable to insert turn.");
|
||||
if LOG_TICKS {
|
||||
let name = if let Some(name) = names.get(entity) { &name.name } else { "Unknown entity" };
|
||||
console::log(format!(
|
||||
"ENERGY SYSTEM: {} granted a turn. [leftover energy: {}].",
|
||||
name, energy.current
|
||||
));
|
||||
console::log(
|
||||
format!("ENERGY SYSTEM: {} granted a turn. [leftover energy: {}].", name, energy.current)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,13 @@ impl<'a> System<'a> for FleeAI {
|
|||
entities,
|
||||
) = data;
|
||||
let mut turn_done: Vec<Entity> = Vec::new();
|
||||
for (entity, _turn, mut pos, fleeing, mut viewshed) in
|
||||
(&entities, &turns, &mut positions, &wants_to_flee, &mut viewsheds).join()
|
||||
{
|
||||
for (entity, _turn, mut pos, fleeing, mut viewshed) in (
|
||||
&entities,
|
||||
&turns,
|
||||
&mut positions,
|
||||
&wants_to_flee,
|
||||
&mut viewsheds,
|
||||
).join() {
|
||||
turn_done.push(entity);
|
||||
let my_idx = map.xy_idx(pos.x, pos.y);
|
||||
map.populate_blocked();
|
||||
|
|
@ -44,8 +48,8 @@ impl<'a> System<'a> for FleeAI {
|
|||
if let Some(is_telepath) = telepaths.get_mut(entity) {
|
||||
is_telepath.dirty = true;
|
||||
}
|
||||
pos.x = flee_target as i32 % map.width;
|
||||
pos.y = flee_target as i32 / map.width;
|
||||
pos.x = (flee_target as i32) % map.width;
|
||||
pos.y = (flee_target as i32) / map.width;
|
||||
entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ impl<'a> System<'a> for QuipSystem {
|
|||
} else {
|
||||
(rng.roll_dice(1, quip.available.len() as i32) - 1) as usize
|
||||
};
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity))
|
||||
.append(&name.name)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
use crate::{
|
||||
gamelog, gui::Class, Attributes, Clock, HasClass, Player, Pools, Position, RandomNumberGenerator, TakingTurn,
|
||||
gamelog,
|
||||
gui::Class,
|
||||
Attributes,
|
||||
Clock,
|
||||
HasClass,
|
||||
Player,
|
||||
Pools,
|
||||
Position,
|
||||
RandomNumberGenerator,
|
||||
TakingTurn,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -55,8 +64,8 @@ impl<'a> System<'a> for RegenSystem {
|
|||
for (e, _p, pool) in (&entities, &positions, &mut pools).join() {
|
||||
let is_wizard = if let Some(class) = classes.get(e) { class.name == Class::Wizard } else { false };
|
||||
let numerator = if is_wizard { WIZARD_MP_REGEN_MOD } else { NONWIZARD_MP_REGEN_MOD };
|
||||
let multiplier: f32 = numerator as f32 / MP_REGEN_DIVISOR as f32;
|
||||
let mp_regen_tick = ((MP_REGEN_BASE - pool.level) as f32 * multiplier) as i32;
|
||||
let multiplier: f32 = (numerator as f32) / (MP_REGEN_DIVISOR as f32);
|
||||
let mp_regen_tick = (((MP_REGEN_BASE - pool.level) as f32) * multiplier) as i32;
|
||||
if current_turn % mp_regen_tick == 0 {
|
||||
try_mana_regen_tick(pool, rng.roll_dice(1, get_mana_regen_per_tick(e, &attributes)));
|
||||
}
|
||||
|
|
@ -66,7 +75,7 @@ impl<'a> System<'a> for RegenSystem {
|
|||
|
||||
fn get_player_hp_regen_turn(level: i32) -> i32 {
|
||||
if level < 10 {
|
||||
return (42 / (level + 2)) + 1;
|
||||
return 42 / (level + 2) + 1;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
|
|
@ -86,7 +95,7 @@ fn try_hp_regen_tick(pool: &mut Pools, amount: i32) {
|
|||
|
||||
fn get_mana_regen_per_tick(e: Entity, attributes: &ReadStorage<Attributes>) -> i32 {
|
||||
let regen = if let Some(attributes) = attributes.get(e) {
|
||||
((attributes.intelligence.bonus + attributes.wisdom.bonus) / 2) + MIN_MP_REGEN_PER_TURN
|
||||
(attributes.intelligence.bonus + attributes.wisdom.bonus) / 2 + MIN_MP_REGEN_PER_TURN
|
||||
} else {
|
||||
MIN_MP_REGEN_PER_TURN
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ use crate::{
|
|||
effects::{ add_effect, EffectType, Targets },
|
||||
gamelog,
|
||||
gui::renderable_colour,
|
||||
Clock, Confusion, Name, Renderable, TakingTurn,
|
||||
Clock,
|
||||
Confusion,
|
||||
Name,
|
||||
Renderable,
|
||||
TakingTurn,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -63,7 +67,7 @@ impl<'a> System<'a> for TurnStatusSystem {
|
|||
lifespan: 200.0,
|
||||
delay: 0.0,
|
||||
},
|
||||
Targets::Entity { target: entity },
|
||||
Targets::Entity { target: entity }
|
||||
);
|
||||
} else {
|
||||
not_my_turn.push(entity);
|
||||
|
|
@ -93,7 +97,7 @@ impl<'a> System<'a> for TurnStatusSystem {
|
|||
lifespan: 200.0,
|
||||
delay: 0.0,
|
||||
},
|
||||
Targets::Entity { target: entity },
|
||||
Targets::Entity { target: entity }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
use crate::{
|
||||
raws::Reaction, Chasing, Faction, HasAncestry, Map, Mind, Position, TakingTurn, Telepath, Viewshed,
|
||||
WantsToApproach, WantsToFlee,
|
||||
raws::Reaction,
|
||||
Chasing,
|
||||
Faction,
|
||||
HasAncestry,
|
||||
Map,
|
||||
Mind,
|
||||
Position,
|
||||
TakingTurn,
|
||||
Telepath,
|
||||
Viewshed,
|
||||
WantsToApproach,
|
||||
WantsToFlee,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -70,10 +80,10 @@ impl<'a> System<'a> for VisibleAI {
|
|||
}
|
||||
}
|
||||
reactions.sort_by(|(a, _, _), (b, _, _)| {
|
||||
let (a_x, a_y) = (a % map.width as usize, a / map.width as usize);
|
||||
let (a_x, a_y) = (a % (map.width as usize), a / (map.width as usize));
|
||||
let dist_a = DistanceAlg::PythagorasSquared.distance2d(Point::new(a_x, a_y), Point::new(pos.x, pos.y));
|
||||
let dist_a_estimate = dist_a as i32;
|
||||
let (b_x, b_y) = (b % map.width as usize, b / map.width as usize);
|
||||
let (b_x, b_y) = (b % (map.width as usize), b / (map.width as usize));
|
||||
let dist_b = DistanceAlg::PythagorasSquared.distance2d(Point::new(b_x, b_y), Point::new(pos.x, pos.y));
|
||||
let dist_b_estimate = dist_b as i32;
|
||||
return dist_b_estimate.cmp(&dist_a_estimate);
|
||||
|
|
@ -110,7 +120,7 @@ fn evaluate(
|
|||
ancestries: &ReadStorage<HasAncestry>,
|
||||
factions: &ReadStorage<Faction>,
|
||||
reactions: &mut Vec<(usize, Reaction, Entity)>,
|
||||
minds: Option<&ReadStorage<Mind>>,
|
||||
minds: Option<&ReadStorage<Mind>>
|
||||
) {
|
||||
crate::spatial::for_each_tile_content(idx, |other_entity| {
|
||||
let mut check = true;
|
||||
|
|
@ -129,7 +139,7 @@ fn evaluate(
|
|||
other_entity,
|
||||
&factions,
|
||||
&ancestries,
|
||||
&crate::raws::RAWS.lock().unwrap(),
|
||||
&crate::raws::RAWS.lock().unwrap()
|
||||
),
|
||||
other_entity,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ pub fn get_screen_bounds(ecs: &World, _ctx: &mut Rltk) -> (i32, i32, i32, i32, i
|
|||
|
||||
let min_x = player_pos.x - centre_x;
|
||||
let min_y = player_pos.y - centre_y;
|
||||
let max_x = min_x + x_chars as i32;
|
||||
let max_y = min_y + y_chars as i32;
|
||||
let max_x = min_x + (x_chars as i32);
|
||||
let max_y = min_y + (y_chars as i32);
|
||||
|
||||
(min_x, max_x, min_y, max_y, x_offset, y_offset)
|
||||
}
|
||||
|
|
@ -33,8 +33,11 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) {
|
|||
if t_x >= 0 && t_x < map.width && t_y >= 0 && t_y < map.height {
|
||||
let idx = map.xy_idx(t_x, t_y);
|
||||
if map.revealed_tiles[idx] {
|
||||
let (glyph, fg, bg) =
|
||||
crate::map::themes::get_tile_renderables_for_id(idx, &*map, Some(*ecs.fetch::<Point>()));
|
||||
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(
|
||||
idx,
|
||||
&*map,
|
||||
Some(*ecs.fetch::<Point>())
|
||||
);
|
||||
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
|
||||
}
|
||||
} else if SHOW_BOUNDARIES {
|
||||
|
|
@ -108,9 +111,9 @@ pub fn render_debug_map(map: &Map, ctx: &mut Rltk) {
|
|||
let center_y = (y_chars / 2) as i32;
|
||||
|
||||
let min_x = player_pos.x - center_x;
|
||||
let max_x = min_x + x_chars as i32;
|
||||
let max_x = min_x + (x_chars as i32);
|
||||
let min_y = player_pos.y - center_y;
|
||||
let max_y = min_y + y_chars as i32;
|
||||
let max_y = min_y + (y_chars as i32);
|
||||
|
||||
let map_width = map.width;
|
||||
let map_height = map.height;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@ pub struct Faction {
|
|||
pub enum Movement {
|
||||
Static,
|
||||
Random,
|
||||
RandomWaypoint { path: Option<Vec<usize>> },
|
||||
RandomWaypoint {
|
||||
path: Option<Vec<usize>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// prettier-ignore
|
||||
#[rustfmt::skip]
|
||||
pub const DEFAULT_VIEWSHED_STANDARD: i32 = 16; // Standard viewshed radius for almost all entities.
|
||||
|
||||
pub const NORMAL_SPEED: i32 = 12; // Normal speed for almost all entities.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
use super::{
|
||||
gamelog, gui::renderable_colour, Equipped, InBackpack, Item, LootTable, Name, Player, Pools, Position, Renderable,
|
||||
gamelog,
|
||||
gui::renderable_colour,
|
||||
Equipped,
|
||||
InBackpack,
|
||||
Item,
|
||||
LootTable,
|
||||
Name,
|
||||
Player,
|
||||
Pools,
|
||||
Position,
|
||||
Renderable,
|
||||
RunState,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
|
|
@ -24,7 +34,8 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
if let Some(victim_name) = victim_name {
|
||||
let item = items.get(entity);
|
||||
if let Some(_item) = item {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity))
|
||||
.append(&victim_name.name)
|
||||
|
|
@ -32,7 +43,8 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
.append("is destroyed!")
|
||||
.log();
|
||||
} else {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity))
|
||||
.append(&victim_name.name)
|
||||
|
|
@ -41,7 +53,7 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
.log();
|
||||
}
|
||||
}
|
||||
dead.push(entity)
|
||||
dead.push(entity);
|
||||
}
|
||||
// The player died, go to GameOver.
|
||||
Some(_) => {
|
||||
|
|
@ -60,7 +72,7 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
&loot.0,
|
||||
None,
|
||||
crate::raws::SpawnType::AtPosition { x: loot.1.x, y: loot.1.y },
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
for item in items_to_delete {
|
||||
|
|
@ -104,8 +116,11 @@ fn handle_dead_entity_items(ecs: &mut World, dead: &Vec<Entity>) -> (Vec<Entity>
|
|||
if let Some(table) = loot_tables.get(*victim) {
|
||||
let roll: f32 = rng.rand();
|
||||
if roll < table.chance {
|
||||
let potential_drop =
|
||||
crate::raws::roll_on_loot_table(&crate::raws::RAWS.lock().unwrap(), &mut rng, &table.table);
|
||||
let potential_drop = crate::raws::roll_on_loot_table(
|
||||
&crate::raws::RAWS.lock().unwrap(),
|
||||
&mut rng,
|
||||
&table.table
|
||||
);
|
||||
if let Some(id) = potential_drop {
|
||||
if let Some(pos) = pos {
|
||||
to_spawn.push((id, pos.clone()));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ use super::{add_effect, targeting, EffectSpawner, EffectType, Entity, Targets, W
|
|||
use crate::{
|
||||
gamelog,
|
||||
gamesystem::{ hp_per_level, mana_per_level },
|
||||
Attributes, Confusion, Destructible, GrantsXP, Map, Player, Pools, DEFAULT_PARTICLE_LIFETIME,
|
||||
Attributes,
|
||||
Confusion,
|
||||
Destructible,
|
||||
GrantsXP,
|
||||
Map,
|
||||
Player,
|
||||
Pools,
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
LONG_PARTICLE_LIFETIME,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
|
|
@ -24,7 +31,7 @@ pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
|||
lifespan: DEFAULT_PARTICLE_LIFETIME,
|
||||
delay: 0.0,
|
||||
},
|
||||
Targets::Entity { target },
|
||||
Targets::Entity { target }
|
||||
);
|
||||
if target_pool.hit_points.current < 1 {
|
||||
super::DEAD_ENTITIES.lock().unwrap().push_back(target);
|
||||
|
|
@ -57,7 +64,7 @@ pub fn heal_damage(ecs: &mut World, heal: &EffectSpawner, target: Entity) {
|
|||
lifespan: DEFAULT_PARTICLE_LIFETIME,
|
||||
delay: 0.0,
|
||||
},
|
||||
Targets::Entity { target },
|
||||
Targets::Entity { target }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +105,7 @@ pub fn bloodstain(ecs: &mut World, target: usize) {
|
|||
// - If we're in bounds and the tile is unbloodied, bloody it and return.
|
||||
// - If we ever leave bounds, return.
|
||||
// - Roll a dice on each failed attempt, with an increasing change to return (soft-capping max spread)
|
||||
if spread > 0 && spread < (map.height * map.width) {
|
||||
if spread > 0 && spread < map.height * map.width {
|
||||
if !map.bloodstains.contains(&(spread as usize)) {
|
||||
map.bloodstains.insert(spread as usize);
|
||||
return;
|
||||
|
|
@ -117,9 +124,9 @@ fn get_next_level_requirement(level: i32) -> i32 {
|
|||
if level == 0 {
|
||||
return 5;
|
||||
} else if level < 10 {
|
||||
return 20 * 2_i32.pow(level as u32 - 1);
|
||||
return 20 * (2_i32).pow((level as u32) - 1);
|
||||
} else if level < 20 {
|
||||
return 10000 * 2_i32.pow(level as u32 - 10);
|
||||
return 10000 * (2_i32).pow((level as u32) - 10);
|
||||
} else if level < 30 {
|
||||
return 10000000 * (level - 19);
|
||||
}
|
||||
|
|
@ -155,7 +162,8 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
// If it was the PLAYER that levelled up:
|
||||
if ecs.read_storage::<Player>().get(source).is_some() {
|
||||
gamelog::record_event("player_level", 1);
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("Welcome to experience level")
|
||||
.append(source_pools.level)
|
||||
.append(".")
|
||||
|
|
@ -171,9 +179,9 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
fg: RGB::named(GOLD),
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: LONG_PARTICLE_LIFETIME,
|
||||
delay: i as f32 * 100.0,
|
||||
delay: (i as f32) * 100.0,
|
||||
},
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x, player_pos.y - i) },
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x, player_pos.y - i) }
|
||||
);
|
||||
if i > 2 {
|
||||
add_effect(
|
||||
|
|
@ -183,9 +191,9 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
fg: RGB::named(GOLD),
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: LONG_PARTICLE_LIFETIME,
|
||||
delay: i as f32 * 100.0,
|
||||
delay: (i as f32) * 100.0,
|
||||
},
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x + (i - 2), player_pos.y - i) },
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x + (i - 2), player_pos.y - i) }
|
||||
);
|
||||
add_effect(
|
||||
None,
|
||||
|
|
@ -194,9 +202,9 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
fg: RGB::named(GOLD),
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: LONG_PARTICLE_LIFETIME,
|
||||
delay: i as f32 * 100.0,
|
||||
delay: (i as f32) * 100.0,
|
||||
},
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x - (i - 2), player_pos.y - i) },
|
||||
Targets::Tile { target: map.xy_idx(player_pos.x - (i - 2), player_pos.y - i) }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -208,11 +216,11 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||
let hp_gained = hp_per_level(
|
||||
&mut rng,
|
||||
source_attributes.constitution.base + source_attributes.constitution.modifiers,
|
||||
source_attributes.constitution.base + source_attributes.constitution.modifiers
|
||||
);
|
||||
let mana_gained = mana_per_level(
|
||||
&mut rng,
|
||||
source_attributes.intelligence.base + source_attributes.intelligence.modifiers,
|
||||
source_attributes.intelligence.base + source_attributes.intelligence.modifiers
|
||||
);
|
||||
source_pools.hit_points.max += hp_gained;
|
||||
source_pools.hit_points.current += hp_gained;
|
||||
|
|
|
|||
|
|
@ -23,24 +23,51 @@ lazy_static! {
|
|||
}
|
||||
|
||||
pub enum EffectType {
|
||||
Damage { amount: i32 },
|
||||
Healing { amount: i32, increment_max: bool },
|
||||
Confusion { turns: i32 },
|
||||
Damage {
|
||||
amount: i32,
|
||||
},
|
||||
Healing {
|
||||
amount: i32,
|
||||
increment_max: bool,
|
||||
},
|
||||
Confusion {
|
||||
turns: i32,
|
||||
},
|
||||
Bloodstain,
|
||||
Particle { glyph: FontCharType, fg: RGB, bg: RGB, lifespan: f32, delay: f32 },
|
||||
Particle {
|
||||
glyph: FontCharType,
|
||||
fg: RGB,
|
||||
bg: RGB,
|
||||
lifespan: f32,
|
||||
delay: f32,
|
||||
},
|
||||
EntityDeath,
|
||||
ItemUse { item: Entity },
|
||||
ModifyNutrition { amount: i32 },
|
||||
TriggerFire { trigger: Entity },
|
||||
ItemUse {
|
||||
item: Entity,
|
||||
},
|
||||
ModifyNutrition {
|
||||
amount: i32,
|
||||
},
|
||||
TriggerFire {
|
||||
trigger: Entity,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Targets {
|
||||
Entity { target: Entity },
|
||||
EntityList { targets: Vec<Entity> },
|
||||
Tile { target: usize },
|
||||
TileList { targets: Vec<usize> },
|
||||
Entity {
|
||||
target: Entity,
|
||||
},
|
||||
EntityList {
|
||||
targets: Vec<Entity>,
|
||||
},
|
||||
Tile {
|
||||
target: usize,
|
||||
},
|
||||
TileList {
|
||||
targets: Vec<usize>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct EffectSpawner {
|
||||
|
|
@ -61,7 +88,9 @@ pub fn run_effects_queue(ecs: &mut World) {
|
|||
loop {
|
||||
let dead_entity: Option<Entity> = DEAD_ENTITIES.lock().unwrap().pop_front();
|
||||
if let Some(dead_entity) = dead_entity {
|
||||
EFFECT_QUEUE.lock().unwrap().retain(|x| x.source != Some(dead_entity));
|
||||
EFFECT_QUEUE.lock()
|
||||
.unwrap()
|
||||
.retain(|x| x.source != Some(dead_entity));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -147,9 +176,5 @@ fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
|
|||
}
|
||||
|
||||
pub fn get_noncursed(buc: &BUC) -> bool {
|
||||
if buc == &BUC::Cursed {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
if buc == &BUC::Cursed { false } else { true }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub fn handle_simple_particles(ecs: &World, entity: Entity, target: &Targets) {
|
|||
lifespan: part.lifetime_ms,
|
||||
delay: 0.0,
|
||||
},
|
||||
target.clone(),
|
||||
target.clone()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,33 +39,33 @@ pub fn handle_burst_particles(ecs: &World, entity: Entity, target: &Targets) {
|
|||
ecs,
|
||||
start_pos,
|
||||
end_pos,
|
||||
&SpawnParticleLine {
|
||||
&(SpawnParticleLine {
|
||||
glyph: part.head_glyph,
|
||||
tail_glyph: part.tail_glyph,
|
||||
colour: part.colour,
|
||||
trail_colour: part.trail_colour,
|
||||
lifetime_ms: part.trail_lifetime_ms, // 75.0 is good here.
|
||||
trail_lifetime_ms: part.trail_lifetime_ms,
|
||||
},
|
||||
})
|
||||
);
|
||||
let map = ecs.fetch::<Map>();
|
||||
let line = line2d(
|
||||
LineAlg::Bresenham,
|
||||
Point::new(start_pos % map.width, start_pos / map.width),
|
||||
Point::new(end_pos % map.width, end_pos / map.width),
|
||||
Point::new(end_pos % map.width, end_pos / map.width)
|
||||
);
|
||||
let burst_delay = line.len() as f32 * part.trail_lifetime_ms;
|
||||
let burst_delay = (line.len() as f32) * part.trail_lifetime_ms;
|
||||
for i in 0..10 {
|
||||
add_effect(
|
||||
None,
|
||||
EffectType::Particle {
|
||||
glyph: part.glyph,
|
||||
fg: part.colour.lerp(part.lerp, i as f32 * 0.1),
|
||||
fg: part.colour.lerp(part.lerp, (i as f32) * 0.1),
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: part.lifetime_ms / 10.0, // ~50-80 is good here.
|
||||
delay: burst_delay + (i as f32 * part.lifetime_ms / 10.0), // above + burst_delay
|
||||
delay: burst_delay + ((i as f32) * part.lifetime_ms) / 10.0, // above + burst_delay
|
||||
},
|
||||
target.clone(),
|
||||
target.clone()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -74,27 +74,31 @@ pub fn handle_burst_particles(ecs: &World, entity: Entity, target: &Targets) {
|
|||
|
||||
fn get_centre(ecs: &World, target: &Targets) -> i32 {
|
||||
match target {
|
||||
Targets::Tile { target } => return *target as i32,
|
||||
Targets::Tile { target } => {
|
||||
return *target as i32;
|
||||
}
|
||||
Targets::TileList { targets } => {
|
||||
let map = ecs.fetch::<Map>();
|
||||
let (mut count, mut sum_x, mut sum_y) = (0, 0, 0);
|
||||
for target in targets {
|
||||
sum_x += *target as i32 % map.width;
|
||||
sum_y += *target as i32 / map.width;
|
||||
sum_x += (*target as i32) % map.width;
|
||||
sum_y += (*target as i32) / map.width;
|
||||
count += 1;
|
||||
}
|
||||
let (mean_x, mean_y) = (sum_x / count, sum_y / count);
|
||||
let centre = map.xy_idx(mean_x, mean_y);
|
||||
return centre as i32;
|
||||
}
|
||||
Targets::Entity { target } => return targeting::entity_position(ecs, *target).unwrap() as i32,
|
||||
Targets::Entity { target } => {
|
||||
return targeting::entity_position(ecs, *target).unwrap() as i32;
|
||||
}
|
||||
Targets::EntityList { targets } => {
|
||||
let map = ecs.fetch::<Map>();
|
||||
let (mut count, mut sum_x, mut sum_y) = (0, 0, 0);
|
||||
for target in targets {
|
||||
if let Some(pos) = targeting::entity_position(ecs, *target) {
|
||||
sum_x += pos as i32 % map.width;
|
||||
sum_y += pos as i32 / map.width;
|
||||
sum_x += (pos as i32) % map.width;
|
||||
sum_y += (pos as i32) / map.width;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +122,8 @@ pub fn handle_line_particles(ecs: &World, entity: Entity, target: &Targets) {
|
|||
spawn_line_particles(ecs, start_pos, end_pos as i32, part);
|
||||
}
|
||||
}
|
||||
Targets::EntityList { targets } => targets.iter().for_each(|target| {
|
||||
Targets::EntityList { targets } =>
|
||||
targets.iter().for_each(|target| {
|
||||
if let Some(end_pos) = targeting::entity_position(ecs, *target) {
|
||||
spawn_line_particles(ecs, start_pos, end_pos as i32, part);
|
||||
}
|
||||
|
|
@ -141,9 +146,9 @@ fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleL
|
|||
fg: part.colour,
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: part.lifetime_ms,
|
||||
delay: i as f32 * part.lifetime_ms,
|
||||
delay: (i as f32) * part.lifetime_ms,
|
||||
},
|
||||
Targets::Tile { target: map.xy_idx(pt.x, pt.y) },
|
||||
Targets::Tile { target: map.xy_idx(pt.x, pt.y) }
|
||||
);
|
||||
if i > 0 {
|
||||
add_effect(
|
||||
|
|
@ -153,9 +158,9 @@ fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleL
|
|||
fg: part.trail_colour,
|
||||
bg: RGB::named(BLACK),
|
||||
lifespan: part.trail_lifetime_ms,
|
||||
delay: i as f32 * part.lifetime_ms,
|
||||
delay: (i as f32) * part.lifetime_ms,
|
||||
},
|
||||
Targets::Tile { target: map.xy_idx(line[i - 1].x, line[i - 1].y) },
|
||||
Targets::Tile { target: map.xy_idx(line[i - 1].x, line[i - 1].y) }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,34 @@
|
|||
use super::{ add_effect, get_noncursed, messages::*, particles, spatial, EffectType, Entity, Targets, World };
|
||||
use crate::{
|
||||
gamelog, gui::item_colour_ecs, gui::obfuscate_name_ecs, gui::renderable_colour, Beatitude, Charges, Confusion,
|
||||
Consumable, Destructible, Equipped, Hidden, InBackpack, InflictsDamage, Item, MagicMapper, MasterDungeonMap, Name,
|
||||
ObfuscatedName, Player, Prop, ProvidesHealing, ProvidesIdentify, ProvidesNutrition, ProvidesRemoveCurse,
|
||||
RandomNumberGenerator, Renderable, RunState, SingleActivation, BUC,
|
||||
gamelog,
|
||||
gui::item_colour_ecs,
|
||||
gui::obfuscate_name_ecs,
|
||||
gui::renderable_colour,
|
||||
Beatitude,
|
||||
Charges,
|
||||
Confusion,
|
||||
Consumable,
|
||||
Destructible,
|
||||
Equipped,
|
||||
Hidden,
|
||||
InBackpack,
|
||||
InflictsDamage,
|
||||
Item,
|
||||
MagicMapper,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Player,
|
||||
Prop,
|
||||
ProvidesHealing,
|
||||
ProvidesIdentify,
|
||||
ProvidesNutrition,
|
||||
ProvidesRemoveCurse,
|
||||
RandomNumberGenerator,
|
||||
Renderable,
|
||||
RunState,
|
||||
SingleActivation,
|
||||
BUC,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -85,7 +110,7 @@ fn event_trigger(source: Option<Entity>, entity: Entity, target: &Targets, ecs:
|
|||
fn handle_restore_nutrition(
|
||||
ecs: &mut World,
|
||||
event: &mut EventInfo,
|
||||
mut logger: gamelog::Logger,
|
||||
mut logger: gamelog::Logger
|
||||
) -> (gamelog::Logger, bool) {
|
||||
if ecs.read_storage::<ProvidesNutrition>().get(event.entity).is_some() {
|
||||
let amount = match event.buc {
|
||||
|
|
@ -131,7 +156,7 @@ fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::L
|
|||
add_effect(
|
||||
event.source,
|
||||
EffectType::Healing { amount: roll, increment_max: get_noncursed(&event.buc) },
|
||||
event.target.clone(),
|
||||
event.target.clone()
|
||||
);
|
||||
for target in get_entity_targets(&event.target) {
|
||||
if ecs.read_storage::<Prop>().get(target).is_some() || ecs.read_storage::<Item>().get(target).is_some() {
|
||||
|
|
@ -238,11 +263,13 @@ fn handle_identify(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::
|
|||
)
|
||||
.join()
|
||||
.filter(|(_e, _i, bp, _o, name)| {
|
||||
bp.owner == event.source.unwrap()
|
||||
&& (!dm.identified_items.contains(&name.name.clone())
|
||||
|| !beatitudes.get(event.source.unwrap()).map(|beatitude| beatitude.known).unwrap_or(true))
|
||||
})
|
||||
{
|
||||
bp.owner == event.source.unwrap() &&
|
||||
(!dm.identified_items.contains(&name.name.clone()) ||
|
||||
!beatitudes
|
||||
.get(event.source.unwrap())
|
||||
.map(|beatitude| beatitude.known)
|
||||
.unwrap_or(true))
|
||||
}) {
|
||||
to_identify.push((e, name.name.clone()));
|
||||
}
|
||||
for item in to_identify {
|
||||
|
|
@ -276,8 +303,7 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
|||
&ecs.read_storage::<Beatitude>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_e, _i, bp, b)| bp.owner == event.source.unwrap() && b.buc == BUC::Cursed)
|
||||
{
|
||||
.filter(|(_e, _i, bp, b)| bp.owner == event.source.unwrap() && b.buc == BUC::Cursed) {
|
||||
to_decurse.push(entity);
|
||||
}
|
||||
}
|
||||
|
|
@ -291,14 +317,15 @@ fn handle_remove_curse(ecs: &mut World, event: &mut EventInfo, mut logger: gamel
|
|||
&ecs.read_storage::<Beatitude>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_e, _i, e, b)| e.owner == event.source.unwrap() && b.buc == BUC::Cursed)
|
||||
{
|
||||
.filter(|(_e, _i, e, b)| e.owner == event.source.unwrap() && b.buc == BUC::Cursed) {
|
||||
to_decurse.push(entity);
|
||||
}
|
||||
if to_decurse.len() == 0 {
|
||||
match event.buc {
|
||||
BUC::Uncursed => select_single(ecs, RunState::ShowRemoveCurse),
|
||||
BUC::Blessed => logger = logger.append(REMOVECURSE_BLESSED_FAILED),
|
||||
BUC::Blessed => {
|
||||
logger = logger.append(REMOVECURSE_BLESSED_FAILED);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return (logger, true);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,12 @@ pub fn print_log(console: &mut Box<dyn Console>, pos: Point, _descending: bool,
|
|||
let mut y = pos.y;
|
||||
let mut x = pos.x;
|
||||
// Reverse the log, take the number we want to show, and iterate through them
|
||||
LOG.lock().unwrap().iter().rev().take(len).for_each(|log| {
|
||||
LOG.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.rev()
|
||||
.take(len)
|
||||
.for_each(|log| {
|
||||
let mut entry_len = -2;
|
||||
// Iterate through each message fragment, and get the total length
|
||||
// in lines, by adding the length of every fragment and dividing it
|
||||
|
|
@ -47,15 +52,15 @@ pub fn print_log(console: &mut Box<dyn Console>, pos: Point, _descending: bool,
|
|||
break;
|
||||
}
|
||||
i += 1;
|
||||
if x + part.len() as i32 > pos.x + maximum_len {
|
||||
if y > pos.y - len as i32 {
|
||||
if x + (part.len() as i32) > pos.x + maximum_len {
|
||||
if y > pos.y - (len as i32) {
|
||||
console.print(x, y, "-");
|
||||
}
|
||||
y += 1;
|
||||
x = pos.x;
|
||||
}
|
||||
// Stay within bounds
|
||||
if y > pos.y - len as i32 {
|
||||
if y > pos.y - (len as i32) {
|
||||
console.print_color(x, y, frag.colour.into(), RGB::named(rltk::BLACK).into(), part);
|
||||
}
|
||||
x += part.len() as i32;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ pub fn roll_4d6(rng: &mut rltk::RandomNumberGenerator) -> i32 {
|
|||
pub fn get_attribute_rolls(
|
||||
rng: &mut RandomNumberGenerator,
|
||||
class: Class,
|
||||
ancestry: Ancestry,
|
||||
ancestry: Ancestry
|
||||
) -> (i32, i32, i32, i32, i32, i32) {
|
||||
let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class {
|
||||
Class::Fighter => (10, 8, 10, 6, 6, 8),
|
||||
|
|
@ -103,7 +103,8 @@ pub fn get_attribute_rolls(
|
|||
Ancestry::Catfolk => [16, 20, 16, 16, 18, 20], // 106
|
||||
_ => [18, 18, 18, 18, 18, 18],
|
||||
};
|
||||
let improve_table = crate::random_table::RandomTable::new()
|
||||
let improve_table = crate::random_table::RandomTable
|
||||
::new()
|
||||
.add("Strength", improve_chance[0])
|
||||
.add("Dexterity", improve_chance[1])
|
||||
.add("Constitution", improve_chance[2])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
use super::{ gamesystem::attr_bonus, gamesystem::get_attribute_rolls, Attributes, Pools, Renderable, RunState, State };
|
||||
use crate::config::entity::NORMAL_SPEED;
|
||||
use crate::{
|
||||
raws, Attribute, Energy, HasAncestry, HasClass, KnownSpell, KnownSpells, Pool, Skill, Skills, Telepath, BUC,
|
||||
raws,
|
||||
Attribute,
|
||||
Energy,
|
||||
HasAncestry,
|
||||
HasClass,
|
||||
KnownSpell,
|
||||
KnownSpells,
|
||||
Pool,
|
||||
Skill,
|
||||
Skills,
|
||||
Telepath,
|
||||
BUC,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use serde::{ Deserialize, Serialize };
|
||||
|
|
@ -79,8 +90,14 @@ lazy_static! {
|
|||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum CharCreateResult {
|
||||
NoSelection { ancestry: Ancestry, class: Class },
|
||||
Selected { ancestry: Ancestry, class: Class },
|
||||
NoSelection {
|
||||
ancestry: Ancestry,
|
||||
class: Class,
|
||||
},
|
||||
Selected {
|
||||
ancestry: Ancestry,
|
||||
class: Class,
|
||||
},
|
||||
}
|
||||
|
||||
/// Handles the player character creation screen.
|
||||
|
|
@ -177,20 +194,45 @@ pub fn character_creation(gs: &mut State, ctx: &mut Rltk) -> CharCreateResult {
|
|||
}
|
||||
|
||||
match ctx.key {
|
||||
None => return CharCreateResult::NoSelection { ancestry, class },
|
||||
Some(key) => match key {
|
||||
VirtualKeyCode::Escape => return CharCreateResult::Selected { ancestry: Ancestry::NULL, class },
|
||||
VirtualKeyCode::Return => return CharCreateResult::Selected { ancestry, class },
|
||||
VirtualKeyCode::H => return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class },
|
||||
VirtualKeyCode::E => return CharCreateResult::NoSelection { ancestry: Ancestry::Elf, class },
|
||||
VirtualKeyCode::D => return CharCreateResult::NoSelection { ancestry: Ancestry::Dwarf, class },
|
||||
VirtualKeyCode::C => return CharCreateResult::NoSelection { ancestry: Ancestry::Catfolk, class },
|
||||
VirtualKeyCode::F => return CharCreateResult::NoSelection { ancestry, class: Class::Fighter },
|
||||
VirtualKeyCode::R => return CharCreateResult::NoSelection { ancestry, class: Class::Rogue },
|
||||
VirtualKeyCode::W => return CharCreateResult::NoSelection { ancestry, class: Class::Wizard },
|
||||
VirtualKeyCode::V => return CharCreateResult::NoSelection { ancestry, class: Class::Villager },
|
||||
_ => return CharCreateResult::NoSelection { ancestry, class },
|
||||
},
|
||||
None => {
|
||||
return CharCreateResult::NoSelection { ancestry, class };
|
||||
}
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => {
|
||||
return CharCreateResult::Selected { ancestry: Ancestry::NULL, class };
|
||||
}
|
||||
VirtualKeyCode::Return => {
|
||||
return CharCreateResult::Selected { ancestry, class };
|
||||
}
|
||||
VirtualKeyCode::H => {
|
||||
return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class };
|
||||
}
|
||||
VirtualKeyCode::E => {
|
||||
return CharCreateResult::NoSelection { ancestry: Ancestry::Elf, class };
|
||||
}
|
||||
VirtualKeyCode::D => {
|
||||
return CharCreateResult::NoSelection { ancestry: Ancestry::Dwarf, class };
|
||||
}
|
||||
VirtualKeyCode::C => {
|
||||
return CharCreateResult::NoSelection { ancestry: Ancestry::Catfolk, class };
|
||||
}
|
||||
VirtualKeyCode::F => {
|
||||
return CharCreateResult::NoSelection { ancestry, class: Class::Fighter };
|
||||
}
|
||||
VirtualKeyCode::R => {
|
||||
return CharCreateResult::NoSelection { ancestry, class: Class::Rogue };
|
||||
}
|
||||
VirtualKeyCode::W => {
|
||||
return CharCreateResult::NoSelection { ancestry, class: Class::Wizard };
|
||||
}
|
||||
VirtualKeyCode::V => {
|
||||
return CharCreateResult::NoSelection { ancestry, class: Class::Villager };
|
||||
}
|
||||
_ => {
|
||||
return CharCreateResult::NoSelection { ancestry, class };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class: Class::Fighter };
|
||||
|
|
@ -214,29 +256,23 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
|
|||
Ancestry::Human => {}
|
||||
Ancestry::Dwarf => {
|
||||
renderables
|
||||
.insert(
|
||||
*player,
|
||||
Renderable {
|
||||
.insert(*player, Renderable {
|
||||
glyph: rltk::to_cp437('h'),
|
||||
fg: RGB::named(rltk::RED),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 0,
|
||||
},
|
||||
)
|
||||
})
|
||||
.expect("Unable to insert renderable component");
|
||||
*player_skills.skills.entry(Skill::Defence).or_insert(0) += 1;
|
||||
}
|
||||
Ancestry::Elf => {
|
||||
renderables
|
||||
.insert(
|
||||
*player,
|
||||
Renderable {
|
||||
.insert(*player, Renderable {
|
||||
glyph: rltk::to_cp437('@'),
|
||||
fg: RGB::named(rltk::GREEN),
|
||||
bg: RGB::named(rltk::BLACK),
|
||||
render_order: 0,
|
||||
},
|
||||
)
|
||||
})
|
||||
.expect("Unable to insert renderable component");
|
||||
let mut telepaths = ecs.write_storage::<Telepath>();
|
||||
telepaths
|
||||
|
|
@ -267,34 +303,28 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
|||
if class == Class::Wizard {
|
||||
let mut spells = ecs.write_storage::<KnownSpells>();
|
||||
spells
|
||||
.insert(
|
||||
player,
|
||||
KnownSpells { spells: vec![KnownSpell { display_name: "zap".to_string(), mana_cost: 1 }] },
|
||||
)
|
||||
.insert(player, KnownSpells {
|
||||
spells: vec![KnownSpell { display_name: "zap".to_string(), mana_cost: 1 }],
|
||||
})
|
||||
.expect("Unable to insert known spells component");
|
||||
}
|
||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||
let mut attributes = ecs.write_storage::<Attributes>();
|
||||
let (str, dex, con, int, wis, cha) = get_attribute_rolls(&mut rng, class, ancestry);
|
||||
attributes
|
||||
.insert(
|
||||
player,
|
||||
Attributes {
|
||||
.insert(player, Attributes {
|
||||
strength: Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) },
|
||||
dexterity: Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) },
|
||||
constitution: Attribute { base: con, modifiers: 0, bonus: attr_bonus(con) },
|
||||
intelligence: Attribute { base: int, modifiers: 0, bonus: attr_bonus(int) },
|
||||
wisdom: Attribute { base: wis, modifiers: 0, bonus: attr_bonus(wis) },
|
||||
charisma: Attribute { base: cha, modifiers: 0, bonus: attr_bonus(cha) },
|
||||
},
|
||||
)
|
||||
})
|
||||
.expect("Unable to insert attributes component");
|
||||
|
||||
let mut pools = ecs.write_storage::<Pools>();
|
||||
pools
|
||||
.insert(
|
||||
player,
|
||||
Pools {
|
||||
.insert(player, Pools {
|
||||
hit_points: Pool { current: 8 + attr_bonus(con), max: 8 + attr_bonus(con) },
|
||||
mana: Pool { current: 1 + attr_bonus(int), max: 1 + attr_bonus(int) },
|
||||
xp: 0,
|
||||
|
|
@ -302,8 +332,7 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
|||
bac: 10,
|
||||
weight: 0.0,
|
||||
god: false,
|
||||
},
|
||||
)
|
||||
})
|
||||
.expect("Unable to insert pools component");
|
||||
}
|
||||
|
||||
|
|
@ -318,7 +347,7 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
|||
item,
|
||||
buc,
|
||||
raws::SpawnType::Equipped { by: player },
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
for item in starts_with.1.iter() {
|
||||
|
|
@ -328,7 +357,7 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) {
|
|||
item,
|
||||
None,
|
||||
raws::SpawnType::Carried { by: player },
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -343,7 +372,7 @@ fn get_starting_inventory(class: Class, rng: &mut RandomNumberGenerator) -> (Vec
|
|||
equipped = vec![
|
||||
"equip_shortsword".to_string(),
|
||||
"equip_body_ringmail".to_string(),
|
||||
"equip_mediumshield".to_string(),
|
||||
"equip_mediumshield".to_string()
|
||||
];
|
||||
}
|
||||
Class::Rogue => {
|
||||
|
|
@ -371,7 +400,7 @@ fn pick_random_table_item(
|
|||
push_to: &mut Vec<String>,
|
||||
table: &'static str,
|
||||
dice: &'static str,
|
||||
difficulty: Option<i32>,
|
||||
difficulty: Option<i32>
|
||||
) {
|
||||
let (n, d, m) = raws::parse_dice_string(dice);
|
||||
for _i in 0..rng.roll_dice(n, d) + m {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pub fn show_cheat_menu(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::RED),
|
||||
RGB::named(rltk::BLACK),
|
||||
"DEBUG MENU! [aA-zZ][Esc.]",
|
||||
"DEBUG MENU! [aA-zZ][Esc.]"
|
||||
);
|
||||
let x = 1 + x_offset;
|
||||
let mut y = 3 + y_offset;
|
||||
|
|
@ -50,7 +50,8 @@ pub fn show_cheat_menu(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
|||
// Match keys
|
||||
match ctx.key {
|
||||
None => CheatMenuResult::NoResponse,
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::A => CheatMenuResult::Ascend,
|
||||
VirtualKeyCode::D => CheatMenuResult::Descend,
|
||||
VirtualKeyCode::H => CheatMenuResult::Heal,
|
||||
|
|
@ -58,6 +59,6 @@ pub fn show_cheat_menu(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
|||
VirtualKeyCode::G => CheatMenuResult::GodMode,
|
||||
VirtualKeyCode::Escape => CheatMenuResult::Cancel,
|
||||
_ => CheatMenuResult::NoResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,24 @@
|
|||
use super::{
|
||||
get_max_inventory_width, item_colour_ecs, obfuscate_name_ecs, print_options, renderable_colour, ItemMenuResult,
|
||||
get_max_inventory_width,
|
||||
item_colour_ecs,
|
||||
obfuscate_name_ecs,
|
||||
print_options,
|
||||
renderable_colour,
|
||||
ItemMenuResult,
|
||||
UniqueInventoryItem,
|
||||
};
|
||||
use crate::{
|
||||
gamelog, Beatitude, Entity, Equipped, InBackpack, Item, MasterDungeonMap, Name, ObfuscatedName, Renderable, State,
|
||||
gamelog,
|
||||
Beatitude,
|
||||
Entity,
|
||||
Equipped,
|
||||
InBackpack,
|
||||
Item,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Renderable,
|
||||
State,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -41,8 +56,12 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
|||
return false;
|
||||
}
|
||||
// If not obfuscated, or already identified, return false.
|
||||
if (!obfuscated.get(*item_entity).is_some() || dm.identified_items.contains(&n.name))
|
||||
&& beatitudes.get(*item_entity).map(|beatitude| beatitude.known).unwrap_or(true)
|
||||
if
|
||||
(!obfuscated.get(*item_entity).is_some() || dm.identified_items.contains(&n.name)) &&
|
||||
beatitudes
|
||||
.get(*item_entity)
|
||||
.map(|beatitude| beatitude.known)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -60,7 +79,8 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
|||
// If only one item, return it.
|
||||
if count == 1 {
|
||||
let item = build_identify_iterator().nth(0).unwrap().0;
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You identify the")
|
||||
.colour(item_colour_ecs(&gs.ecs, item))
|
||||
.append_n(obfuscate_name_ecs(&gs.ecs, item).0)
|
||||
|
|
@ -81,7 +101,9 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
|||
glyph: renderable.glyph,
|
||||
name: name.name.clone(),
|
||||
})
|
||||
.and_modify(|count| *count += 1)
|
||||
.and_modify(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.or_insert(1);
|
||||
inventory_ids.entry(singular).or_insert(entity);
|
||||
}
|
||||
|
|
@ -95,20 +117,25 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Identify which item? [aA-zZ][Esc.]",
|
||||
"Identify which item? [aA-zZ][Esc.]"
|
||||
);
|
||||
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
||||
print_options(player_inventory, x + 1, y + 1, ctx);
|
||||
// Input
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
if selection > -1 && selection < count as i32 {
|
||||
let item = inventory_ids.iter().nth(selection as usize).unwrap().1;
|
||||
gamelog::Logger::new()
|
||||
if selection > -1 && selection < (count as i32) {
|
||||
let item = inventory_ids
|
||||
.iter()
|
||||
.nth(selection as usize)
|
||||
.unwrap().1;
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You identify the")
|
||||
.colour(item_colour_ecs(&gs.ecs, *item))
|
||||
.append_n(obfuscate_name_ecs(&gs.ecs, *item).0)
|
||||
|
|
@ -119,6 +146,6 @@ pub fn identify(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entit
|
|||
}
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
339
src/gui/mod.rs
339
src/gui/mod.rs
|
|
@ -1,8 +1,38 @@
|
|||
use super::{
|
||||
ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, hunger_system::get_hunger_colour,
|
||||
rex_assets::RexAssets, ArmourClassBonus, Attributes, Beatitude, Burden, Charges, Equipped, Hidden, HungerClock,
|
||||
HungerState, InBackpack, KnownSpells, MagicItem, Map, MasterDungeonMap, Name, ObfuscatedName, Player, Point, Pools,
|
||||
Position, Prop, Renderable, RunState, Skill, Skills, State, Viewshed, BUC,
|
||||
ai::CARRY_CAPACITY_PER_STRENGTH,
|
||||
camera,
|
||||
gamelog,
|
||||
gamesystem,
|
||||
hunger_system::get_hunger_colour,
|
||||
rex_assets::RexAssets,
|
||||
ArmourClassBonus,
|
||||
Attributes,
|
||||
Beatitude,
|
||||
Burden,
|
||||
Charges,
|
||||
Equipped,
|
||||
Hidden,
|
||||
HungerClock,
|
||||
HungerState,
|
||||
InBackpack,
|
||||
KnownSpells,
|
||||
MagicItem,
|
||||
Map,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Player,
|
||||
Point,
|
||||
Pools,
|
||||
Position,
|
||||
Prop,
|
||||
Renderable,
|
||||
RunState,
|
||||
Skill,
|
||||
Skills,
|
||||
State,
|
||||
Viewshed,
|
||||
BUC,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -25,11 +55,12 @@ pub fn yes_no(ctx: &mut Rltk, question: String) -> Option<bool> {
|
|||
ctx.print_color_centered(17, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "(y)es or (n)o");
|
||||
match ctx.key {
|
||||
None => None,
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Y => Some(true),
|
||||
VirtualKeyCode::N => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,10 +72,10 @@ pub fn draw_lerping_bar(
|
|||
n: i32,
|
||||
max: i32,
|
||||
full_colour: RGB,
|
||||
empty_colour: RGB,
|
||||
empty_colour: RGB
|
||||
) {
|
||||
let percent = n as f32 / max as f32;
|
||||
let fill_width = (percent * width as f32) as i32;
|
||||
let percent = (n as f32) / (max as f32);
|
||||
let fill_width = (percent * (width as f32)) as i32;
|
||||
let bg = empty_colour.lerp(full_colour, percent);
|
||||
let fg = RGB::named(rltk::BLACK);
|
||||
for x in 0..width {
|
||||
|
|
@ -78,7 +109,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
stats.hit_points.current,
|
||||
stats.hit_points.max,
|
||||
RGB::from_u8(0, 255, 0),
|
||||
RGB::from_u8(255, 0, 0),
|
||||
RGB::from_u8(255, 0, 0)
|
||||
);
|
||||
draw_lerping_bar(
|
||||
ctx,
|
||||
|
|
@ -88,7 +119,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
stats.mana.current,
|
||||
stats.mana.max,
|
||||
RGB::named(rltk::BLUE),
|
||||
RGB::named(rltk::BLACK),
|
||||
RGB::named(rltk::BLACK)
|
||||
);
|
||||
// Draw AC
|
||||
let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*skills);
|
||||
|
|
@ -101,7 +132,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
armour_ac_bonus += ac.amount;
|
||||
}
|
||||
}
|
||||
let armour_class = stats.bac - (attributes.dexterity.bonus / 2) - skill_ac_bonus - armour_ac_bonus;
|
||||
let armour_class = stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus;
|
||||
ctx.print_color(26, 53, RGB::named(rltk::PINK), RGB::named(rltk::BLACK), "AC");
|
||||
ctx.print_color(28, 53, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), armour_class);
|
||||
// Draw level
|
||||
|
|
@ -110,7 +141,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
54,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
format!("XP{}/{}", stats.level, stats.xp),
|
||||
format!("XP{}/{}", stats.level, stats.xp)
|
||||
);
|
||||
// Draw attributes
|
||||
let x = 38;
|
||||
|
|
@ -129,33 +160,33 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
// Draw hunger
|
||||
match hunger.state {
|
||||
HungerState::Satiated => {
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Satiated")
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Satiated");
|
||||
}
|
||||
HungerState::Normal => {}
|
||||
HungerState::Hungry => {
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Hungry")
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Hungry");
|
||||
}
|
||||
HungerState::Weak => {
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Weak")
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Weak");
|
||||
}
|
||||
HungerState::Fainting => {
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Fainting")
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Fainting");
|
||||
}
|
||||
HungerState::Starving => {
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Starving")
|
||||
ctx.print_color_right(70, 53, get_hunger_colour(hunger.state), RGB::named(rltk::BLACK), "Starving");
|
||||
}
|
||||
}
|
||||
// Burden
|
||||
if let Some(burden) = burden.get(*player_entity) {
|
||||
match burden.level {
|
||||
crate::BurdenLevel::Burdened => {
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::BROWN1), RGB::named(rltk::BLACK), "Burdened")
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::BROWN1), RGB::named(rltk::BLACK), "Burdened");
|
||||
}
|
||||
crate::BurdenLevel::Strained => {
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "Strained")
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::ORANGE), RGB::named(rltk::BLACK), "Strained");
|
||||
}
|
||||
crate::BurdenLevel::Overloaded => {
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "Overloaded")
|
||||
ctx.print_color_right(70, 50, RGB::named(rltk::RED), RGB::named(rltk::BLACK), "Overloaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,9 +197,9 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
let renderables = ecs.read_storage::<Renderable>();
|
||||
let mut equipment: Vec<(String, RGB, RGB, rltk::FontCharType)> = Vec::new();
|
||||
let entities = ecs.entities();
|
||||
for (entity, _equipped, renderable) in
|
||||
(&entities, &equipped, &renderables).join().filter(|item| item.1.owner == *player_entity)
|
||||
{
|
||||
for (entity, _equipped, renderable) in (&entities, &equipped, &renderables)
|
||||
.join()
|
||||
.filter(|item| item.1.owner == *player_entity) {
|
||||
equipment.push((
|
||||
obfuscate_name_ecs(ecs, entity).0,
|
||||
RGB::named(item_colour_ecs(ecs, entity)),
|
||||
|
|
@ -182,7 +213,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
let mut j = 0;
|
||||
for item in equipment {
|
||||
y += 1;
|
||||
ctx.set(72, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + j as rltk::FontCharType);
|
||||
ctx.set(72, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
||||
j += 1;
|
||||
ctx.set(74, y, item.2, RGB::named(rltk::BLACK), item.3);
|
||||
ctx.print_color(76, y, item.1, RGB::named(rltk::BLACK), &item.0);
|
||||
|
|
@ -202,7 +233,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
"[{:.1}/{} lbs]",
|
||||
stats.weight,
|
||||
(attributes.strength.base + attributes.strength.modifiers) * CARRY_CAPACITY_PER_STRENGTH
|
||||
),
|
||||
)
|
||||
);
|
||||
y += 1;
|
||||
let (player_inventory, _inventory_ids) = get_player_inventory(&ecs);
|
||||
|
|
@ -222,7 +253,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
y,
|
||||
RGB::named(CYAN),
|
||||
RGB::named(BLACK),
|
||||
&format!("{} ({})", "Force Bolt - NYI!", spell.mana_cost),
|
||||
&format!("{} ({})", "Force Bolt - NYI!", spell.mana_cost)
|
||||
);
|
||||
index += 1;
|
||||
y += 1;
|
||||
|
|
@ -298,7 +329,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
54,
|
||||
RGB::named(rltk::YELLOW),
|
||||
RGB::named(rltk::BLACK),
|
||||
&format!("T{}", crate::gamelog::get_event_count("turns")),
|
||||
&format!("T{}", crate::gamelog::get_event_count("turns"))
|
||||
);
|
||||
|
||||
// Boxes and tooltips last, so they draw over everything else.
|
||||
|
|
@ -312,7 +343,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||
pub fn get_input_direction(
|
||||
ecs: &mut World,
|
||||
ctx: &mut Rltk,
|
||||
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState,
|
||||
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState
|
||||
) -> RunState {
|
||||
let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs, ctx);
|
||||
|
||||
|
|
@ -321,24 +352,47 @@ pub fn get_input_direction(
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"In what direction? [0-9]/[YUHJKLBN]",
|
||||
"In what direction? [0-9]/[YUHJKLBN]"
|
||||
);
|
||||
match ctx.key {
|
||||
None => return RunState::ActionWithDirection { function },
|
||||
Some(key) => match key {
|
||||
VirtualKeyCode::Escape => return RunState::AwaitingInput,
|
||||
None => {
|
||||
return RunState::ActionWithDirection { function };
|
||||
}
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => {
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
// Cardinals
|
||||
VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => return function(-1, 0, ecs),
|
||||
VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L => return function(1, 0, ecs),
|
||||
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => return function(0, -1, ecs),
|
||||
VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => return function(0, 1, ecs),
|
||||
VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => {
|
||||
return function(-1, 0, ecs);
|
||||
}
|
||||
VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L => {
|
||||
return function(1, 0, ecs);
|
||||
}
|
||||
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => {
|
||||
return function(0, -1, ecs);
|
||||
}
|
||||
VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => {
|
||||
return function(0, 1, ecs);
|
||||
}
|
||||
// Diagonals
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::U => return function(1, -1, ecs),
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => return function(-1, -1, ecs),
|
||||
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => return function(1, 1, ecs),
|
||||
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => return function(-1, 1, ecs),
|
||||
_ => return RunState::ActionWithDirection { function },
|
||||
},
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::U => {
|
||||
return function(1, -1, ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => {
|
||||
return function(-1, -1, ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => {
|
||||
return function(1, 1, ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => {
|
||||
return function(-1, 1, ecs);
|
||||
}
|
||||
_ => {
|
||||
return RunState::ActionWithDirection { function };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +407,7 @@ pub fn print_options(
|
|||
inventory: BTreeMap<UniqueInventoryItem, i32>,
|
||||
mut x: i32,
|
||||
mut y: i32,
|
||||
ctx: &mut Rltk,
|
||||
ctx: &mut Rltk
|
||||
) -> (i32, i32) {
|
||||
let mut j = 0;
|
||||
let initial_x: i32 = x;
|
||||
|
|
@ -362,10 +416,10 @@ pub fn print_options(
|
|||
x = initial_x;
|
||||
// Print the character required to access this item. i.e. (a)
|
||||
if j < 26 {
|
||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + j as rltk::FontCharType);
|
||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
||||
} else {
|
||||
// If we somehow have more than 26, start using capitals
|
||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 65 - 26 + j as rltk::FontCharType);
|
||||
ctx.set(x, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 65 - 26 + (j as rltk::FontCharType));
|
||||
}
|
||||
|
||||
x += 2;
|
||||
|
|
@ -380,15 +434,14 @@ pub fn print_options(
|
|||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item_count);
|
||||
x += 2;
|
||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item.display_name.plural.to_string());
|
||||
let this_width = x - initial_x + item.display_name.plural.len() as i32;
|
||||
let this_width = x - initial_x + (item.display_name.plural.len() as i32);
|
||||
width = if width > this_width { width } else { this_width };
|
||||
} else {
|
||||
if item.display_name.singular.to_lowercase().ends_with("s") {
|
||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), "some");
|
||||
x += 5;
|
||||
} else if ['a', 'e', 'i', 'o', 'u']
|
||||
.iter()
|
||||
.any(|&v| item.display_name.singular.to_lowercase().starts_with(v))
|
||||
} else if
|
||||
['a', 'e', 'i', 'o', 'u'].iter().any(|&v| item.display_name.singular.to_lowercase().starts_with(v))
|
||||
{
|
||||
// If one and starts with a vowel, print 'an'
|
||||
// i.e. (a) an apple
|
||||
|
|
@ -401,7 +454,7 @@ pub fn print_options(
|
|||
x += 2;
|
||||
}
|
||||
ctx.print_color(x, y, fg, RGB::named(rltk::BLACK), item.display_name.singular.to_string());
|
||||
let this_width = x - initial_x + item.display_name.singular.len() as i32;
|
||||
let this_width = x - initial_x + (item.display_name.singular.len() as i32);
|
||||
width = if width > this_width { width } else { this_width };
|
||||
}
|
||||
|
||||
|
|
@ -442,7 +495,7 @@ pub fn obfuscate_name(
|
|||
obfuscated_names: &ReadStorage<ObfuscatedName>,
|
||||
beatitudes: &ReadStorage<Beatitude>,
|
||||
dm: &MasterDungeonMap,
|
||||
wand: Option<&ReadStorage<Charges>>,
|
||||
wand: Option<&ReadStorage<Charges>>
|
||||
) -> (String, String) {
|
||||
let (mut singular, mut plural) = ("nameless item (bug)".to_string(), "nameless items (bug)".to_string());
|
||||
if let Some(name) = names.get(item) {
|
||||
|
|
@ -537,9 +590,15 @@ pub fn item_colour_ecs(ecs: &World, item: Entity) -> (u8, u8, u8) {
|
|||
if let Some(beatitude) = ecs.read_storage::<Beatitude>().get(item) {
|
||||
if beatitude.known {
|
||||
match beatitude.buc {
|
||||
BUC::Blessed => return GREEN,
|
||||
BUC::Uncursed => return WHITE,
|
||||
BUC::Cursed => return RED,
|
||||
BUC::Blessed => {
|
||||
return GREEN;
|
||||
}
|
||||
BUC::Uncursed => {
|
||||
return WHITE;
|
||||
}
|
||||
BUC::Cursed => {
|
||||
return RED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Unidentified magic item
|
||||
|
|
@ -554,9 +613,15 @@ pub fn item_colour(item: Entity, beatitudes: &ReadStorage<Beatitude>) -> (u8, u8
|
|||
if let Some(beatitude) = beatitudes.get(item) {
|
||||
if beatitude.known {
|
||||
match beatitude.buc {
|
||||
BUC::Blessed => return GREEN,
|
||||
BUC::Uncursed => return WHITE,
|
||||
BUC::Cursed => return RED,
|
||||
BUC::Blessed => {
|
||||
return GREEN;
|
||||
}
|
||||
BUC::Uncursed => {
|
||||
return WHITE;
|
||||
}
|
||||
BUC::Cursed => {
|
||||
return RED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Unidentified magic item
|
||||
|
|
@ -601,7 +666,8 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
|||
|
||||
match ctx.key {
|
||||
None => YesNoResult::NoSelection,
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => YesNoResult::Yes,
|
||||
VirtualKeyCode::Slash => {
|
||||
if ctx.shift {
|
||||
|
|
@ -610,7 +676,7 @@ pub fn show_help(ctx: &mut Rltk) -> YesNoResult {
|
|||
return YesNoResult::NoSelection;
|
||||
}
|
||||
_ => YesNoResult::NoSelection,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,13 +704,16 @@ pub fn get_player_inventory(ecs: &World) -> (BTreeMap<UniqueInventoryItem, i32>,
|
|||
|
||||
let mut inventory_ids: BTreeMap<String, Entity> = BTreeMap::new();
|
||||
let mut player_inventory: BTreeMap<UniqueInventoryItem, i32> = BTreeMap::new();
|
||||
for (entity, _pack, name, renderable) in
|
||||
(&entities, &backpack, &names, &renderables).join().filter(|item| item.1.owner == *player_entity)
|
||||
{
|
||||
for (entity, _pack, name, renderable) in (&entities, &backpack, &names, &renderables)
|
||||
.join()
|
||||
.filter(|item| item.1.owner == *player_entity) {
|
||||
// RGB can't be used as a key. This is converting the RGB (tuple of f32) into a tuple of u8s.
|
||||
let item_colour = item_colour_ecs(ecs, entity);
|
||||
let renderables =
|
||||
((renderable.fg.r * 255.0) as u8, (renderable.fg.g * 255.0) as u8, (renderable.fg.b * 255.0) as u8);
|
||||
let renderables = (
|
||||
(renderable.fg.r * 255.0) as u8,
|
||||
(renderable.fg.g * 255.0) as u8,
|
||||
(renderable.fg.b * 255.0) as u8,
|
||||
);
|
||||
let (singular, plural) = obfuscate_name_ecs(ecs, entity);
|
||||
player_inventory
|
||||
.entry(UniqueInventoryItem {
|
||||
|
|
@ -654,7 +723,9 @@ pub fn get_player_inventory(ecs: &World) -> (BTreeMap<UniqueInventoryItem, i32>,
|
|||
glyph: renderable.glyph,
|
||||
name: name.name.clone(),
|
||||
})
|
||||
.and_modify(|count| *count += 1)
|
||||
.and_modify(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.or_insert(1);
|
||||
inventory_ids.entry(singular).or_insert(entity);
|
||||
}
|
||||
|
|
@ -673,7 +744,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Interact with what item? [aA-zZ][Esc.]",
|
||||
"Interact with what item? [aA-zZ][Esc.]"
|
||||
);
|
||||
|
||||
let x = 1 + x_offset;
|
||||
|
|
@ -684,16 +755,25 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||
_ => {
|
||||
let selection = letter_to_option::letter_to_option(key, ctx.shift);
|
||||
if selection > -1 && selection < count as i32 {
|
||||
return (ItemMenuResult::Selected, Some(*inventory_ids.iter().nth(selection as usize).unwrap().1));
|
||||
if selection > -1 && selection < (count as i32) {
|
||||
return (
|
||||
ItemMenuResult::Selected,
|
||||
Some(
|
||||
*inventory_ids
|
||||
.iter()
|
||||
.nth(selection as usize)
|
||||
.unwrap().1
|
||||
),
|
||||
);
|
||||
}
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +788,7 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Drop what? [aA-zZ][Esc.]",
|
||||
"Drop what? [aA-zZ][Esc.]"
|
||||
);
|
||||
|
||||
let x = 1 + x_offset;
|
||||
|
|
@ -719,16 +799,25 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
if selection > -1 && selection < count as i32 {
|
||||
return (ItemMenuResult::Selected, Some(*inventory_ids.iter().nth(selection as usize).unwrap().1));
|
||||
if selection > -1 && selection < (count as i32) {
|
||||
return (
|
||||
ItemMenuResult::Selected,
|
||||
Some(
|
||||
*inventory_ids
|
||||
.iter()
|
||||
.nth(selection as usize)
|
||||
.unwrap().1
|
||||
),
|
||||
);
|
||||
}
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -746,7 +835,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Unequip what? [aA-zZ][Esc.]",
|
||||
"Unequip what? [aA-zZ][Esc.]"
|
||||
);
|
||||
|
||||
let mut equippable: Vec<(Entity, String)> = Vec::new();
|
||||
|
|
@ -772,7 +861,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
|||
} else {
|
||||
(RGB::named(rltk::WHITE), rltk::to_cp437('-'))
|
||||
};
|
||||
ctx.set(x + 1, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + j as rltk::FontCharType);
|
||||
ctx.set(x + 1, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97 + (j as rltk::FontCharType));
|
||||
ctx.set(x + 3, y, fg, RGB::named(rltk::BLACK), glyph);
|
||||
fg = RGB::named(item_colour_ecs(&gs.ecs, *e));
|
||||
ctx.print_color(x + 5, y, fg, RGB::named(rltk::BLACK), name);
|
||||
|
|
@ -782,16 +871,17 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
|||
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
if selection > -1 && selection < count as i32 {
|
||||
if selection > -1 && selection < (count as i32) {
|
||||
return (ItemMenuResult::Selected, Some(equippable[selection as usize].0));
|
||||
}
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -806,7 +896,7 @@ pub fn ranged_target(gs: &mut State, ctx: &mut Rltk, range: i32, aoe: i32) -> (I
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Targeting which tile? [mouse input]",
|
||||
"Targeting which tile? [mouse input]"
|
||||
);
|
||||
|
||||
// Highlight available cells
|
||||
|
|
@ -816,10 +906,10 @@ pub fn ranged_target(gs: &mut State, ctx: &mut Rltk, range: i32, aoe: i32) -> (I
|
|||
// We have a viewshed
|
||||
for idx in visible.visible_tiles.iter() {
|
||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(*player_pos, *idx);
|
||||
if distance <= range as f32 {
|
||||
if distance <= (range as f32) {
|
||||
let screen_x = idx.x - min_x;
|
||||
let screen_y = idx.y - min_y;
|
||||
if screen_x > 1 && screen_x < (max_x - min_x) - 1 && screen_y > 1 && screen_y < (max_y - min_y) - 1 {
|
||||
if screen_x > 1 && screen_x < max_x - min_x - 1 && screen_y > 1 && screen_y < max_y - min_y - 1 {
|
||||
ctx.set_bg(screen_x + x_offset, screen_y + y_offset, RGB::named(rltk::BLUE));
|
||||
available_cells.push(idx);
|
||||
}
|
||||
|
|
@ -845,8 +935,11 @@ pub fn ranged_target(gs: &mut State, ctx: &mut Rltk, range: i32, aoe: i32) -> (I
|
|||
if aoe > 0 {
|
||||
// We adjust for camera position when getting FOV, but then we need to adjust back
|
||||
// when iterating through the tiles themselves, by taking away min_x/min_y.
|
||||
let mut blast_tiles =
|
||||
rltk::field_of_view(Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1), aoe, &*map);
|
||||
let mut blast_tiles = rltk::field_of_view(
|
||||
Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1),
|
||||
aoe,
|
||||
&*map
|
||||
);
|
||||
blast_tiles.retain(|p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1);
|
||||
for tile in blast_tiles.iter() {
|
||||
ctx.set_bg(tile.x - min_x + x_offset, tile.y - min_y + y_offset, RGB::named(rltk::DARKCYAN));
|
||||
|
|
@ -875,8 +968,12 @@ pub enum MainMenuSelection {
|
|||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum MainMenuResult {
|
||||
NoSelection { selected: MainMenuSelection },
|
||||
Selected { selected: MainMenuSelection },
|
||||
NoSelection {
|
||||
selected: MainMenuSelection,
|
||||
},
|
||||
Selected {
|
||||
selected: MainMenuSelection,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
||||
|
|
@ -924,19 +1021,32 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||
}
|
||||
|
||||
match ctx.key {
|
||||
None => return MainMenuResult::NoSelection { selected: selection },
|
||||
Some(key) => match key {
|
||||
VirtualKeyCode::Escape | VirtualKeyCode::C => {
|
||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::Quit }
|
||||
None => {
|
||||
return MainMenuResult::NoSelection { selected: selection };
|
||||
}
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape | VirtualKeyCode::C => {
|
||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::Quit };
|
||||
}
|
||||
VirtualKeyCode::N => {
|
||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame };
|
||||
}
|
||||
VirtualKeyCode::L => {
|
||||
return MainMenuResult::NoSelection { selected: MainMenuSelection::LoadGame };
|
||||
}
|
||||
VirtualKeyCode::N => return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame },
|
||||
VirtualKeyCode::L => return MainMenuResult::NoSelection { selected: MainMenuSelection::LoadGame },
|
||||
VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => {
|
||||
let mut new_selection;
|
||||
match selection {
|
||||
MainMenuSelection::NewGame => new_selection = MainMenuSelection::LoadGame,
|
||||
MainMenuSelection::LoadGame => new_selection = MainMenuSelection::Quit,
|
||||
MainMenuSelection::Quit => new_selection = MainMenuSelection::NewGame,
|
||||
MainMenuSelection::NewGame => {
|
||||
new_selection = MainMenuSelection::LoadGame;
|
||||
}
|
||||
MainMenuSelection::LoadGame => {
|
||||
new_selection = MainMenuSelection::Quit;
|
||||
}
|
||||
MainMenuSelection::Quit => {
|
||||
new_selection = MainMenuSelection::NewGame;
|
||||
}
|
||||
}
|
||||
if new_selection == MainMenuSelection::LoadGame && !save_exists {
|
||||
new_selection = MainMenuSelection::NewGame;
|
||||
|
|
@ -946,9 +1056,15 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||
VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => {
|
||||
let mut new_selection;
|
||||
match selection {
|
||||
MainMenuSelection::NewGame => new_selection = MainMenuSelection::Quit,
|
||||
MainMenuSelection::LoadGame => new_selection = MainMenuSelection::NewGame,
|
||||
MainMenuSelection::Quit => new_selection = MainMenuSelection::LoadGame,
|
||||
MainMenuSelection::NewGame => {
|
||||
new_selection = MainMenuSelection::Quit;
|
||||
}
|
||||
MainMenuSelection::LoadGame => {
|
||||
new_selection = MainMenuSelection::NewGame;
|
||||
}
|
||||
MainMenuSelection::Quit => {
|
||||
new_selection = MainMenuSelection::LoadGame;
|
||||
}
|
||||
}
|
||||
if new_selection == MainMenuSelection::LoadGame && !save_exists {
|
||||
new_selection = MainMenuSelection::Quit;
|
||||
|
|
@ -956,10 +1072,12 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||
return MainMenuResult::NoSelection { selected: new_selection };
|
||||
}
|
||||
VirtualKeyCode::Return | VirtualKeyCode::NumpadEnter => {
|
||||
return MainMenuResult::Selected { selected: selection }
|
||||
return MainMenuResult::Selected { selected: selection };
|
||||
}
|
||||
_ => {
|
||||
return MainMenuResult::NoSelection { selected: selection };
|
||||
}
|
||||
}
|
||||
_ => return MainMenuResult::NoSelection { selected: selection },
|
||||
},
|
||||
}
|
||||
}
|
||||
MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame }
|
||||
|
|
@ -986,7 +1104,7 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
|||
y,
|
||||
RGB::named(rltk::GREEN),
|
||||
RGB::named(rltk::BLACK),
|
||||
format!("You survived for {} turns.", crate::gamelog::get_event_count("turns")),
|
||||
format!("You survived for {} turns.", crate::gamelog::get_event_count("turns"))
|
||||
);
|
||||
y += 2;
|
||||
ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), format!("And in the process, you"));
|
||||
|
|
@ -997,7 +1115,7 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
|||
y,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
format!("- descended {} floor(s)", crate::gamelog::get_event_count("descended")),
|
||||
format!("- descended {} floor(s)", crate::gamelog::get_event_count("descended"))
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
|
|
@ -1011,7 +1129,7 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
|||
"- kicked {} time(s), breaking {} object(s)",
|
||||
crate::gamelog::get_event_count("kick_count"),
|
||||
crate::gamelog::get_event_count("broken_doors")
|
||||
),
|
||||
)
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
|
|
@ -1021,7 +1139,7 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
|||
y,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
format!("- slew {} other creature(s)", crate::gamelog::get_event_count("death_count")),
|
||||
format!("- slew {} other creature(s)", crate::gamelog::get_event_count("death_count"))
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
|
|
@ -1031,15 +1149,16 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult {
|
|||
y,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count("looked_for_help")),
|
||||
format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count("looked_for_help"))
|
||||
);
|
||||
}
|
||||
|
||||
match ctx.key {
|
||||
None => YesNoResult::NoSelection,
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => YesNoResult::Yes,
|
||||
_ => YesNoResult::NoSelection,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
use super::{
|
||||
get_max_inventory_width, item_colour_ecs, obfuscate_name_ecs, print_options, renderable_colour, ItemMenuResult,
|
||||
get_max_inventory_width,
|
||||
item_colour_ecs,
|
||||
obfuscate_name_ecs,
|
||||
print_options,
|
||||
renderable_colour,
|
||||
ItemMenuResult,
|
||||
UniqueInventoryItem,
|
||||
};
|
||||
use crate::{ gamelog, Beatitude, Entity, Equipped, InBackpack, Item, Name, Renderable, State, BUC };
|
||||
|
|
@ -58,7 +63,8 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
|||
// If only one item, return it.
|
||||
if count == 1 {
|
||||
let item = build_cursed_iterator().nth(0).unwrap().0;
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You decurse the")
|
||||
.colour(item_colour_ecs(&gs.ecs, item))
|
||||
.append_n(obfuscate_name_ecs(&gs.ecs, item).0)
|
||||
|
|
@ -79,7 +85,9 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
|||
glyph: renderable.glyph,
|
||||
name: name.name.clone(),
|
||||
})
|
||||
.and_modify(|count| *count += 1)
|
||||
.and_modify(|count| {
|
||||
*count += 1;
|
||||
})
|
||||
.or_insert(1);
|
||||
inventory_ids.entry(singular).or_insert(entity);
|
||||
}
|
||||
|
|
@ -93,20 +101,25 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
|||
1 + y_offset,
|
||||
RGB::named(rltk::WHITE),
|
||||
RGB::named(rltk::BLACK),
|
||||
"Decurse which item? [aA-zZ][Esc.]",
|
||||
"Decurse which item? [aA-zZ][Esc.]"
|
||||
);
|
||||
ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
|
||||
print_options(player_inventory, x + 1, y + 1, ctx);
|
||||
// Input
|
||||
match ctx.key {
|
||||
None => (ItemMenuResult::NoResponse, None),
|
||||
Some(key) => match key {
|
||||
Some(key) =>
|
||||
match key {
|
||||
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
|
||||
_ => {
|
||||
let selection = rltk::letter_to_option(key);
|
||||
if selection > -1 && selection < count as i32 {
|
||||
let item = inventory_ids.iter().nth(selection as usize).unwrap().1;
|
||||
gamelog::Logger::new()
|
||||
if selection > -1 && selection < (count as i32) {
|
||||
let item = inventory_ids
|
||||
.iter()
|
||||
.nth(selection as usize)
|
||||
.unwrap().1;
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You decurse the")
|
||||
.colour(item_colour_ecs(&gs.ecs, *item))
|
||||
.append_n(obfuscate_name_ecs(&gs.ecs, *item).0)
|
||||
|
|
@ -117,6 +130,6 @@ pub fn remove_curse(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<E
|
|||
}
|
||||
(ItemMenuResult::NoResponse, None)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@ impl Tooltip {
|
|||
max = s.0.len();
|
||||
}
|
||||
}
|
||||
return max as i32 + 2i32;
|
||||
return (max as i32) + 2i32;
|
||||
}
|
||||
fn height(&self) -> i32 {
|
||||
return self.lines.len() as i32 + 2i32;
|
||||
return (self.lines.len() as i32) + 2i32;
|
||||
}
|
||||
fn render(&self, ctx: &mut Rltk, x: i32, y: i32) {
|
||||
ctx.draw_box(x, y, self.width() - 1, self.height() - 1, RGB::named(WHITE), RGB::named(BLACK));
|
||||
for (i, s) in self.lines.iter().enumerate() {
|
||||
ctx.print_color(x + 1, y + i as i32 + 1, s.1, RGB::named(BLACK), &s.0);
|
||||
ctx.print_color(x + 1, y + (i as i32) + 1, s.1, RGB::named(BLACK), &s.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
use super::{
|
||||
effects::{ add_effect, EffectType, Targets },
|
||||
gamelog, Clock, HungerClock, HungerState, TakingTurn, LOG_TICKS,
|
||||
gamelog,
|
||||
Clock,
|
||||
HungerClock,
|
||||
HungerState,
|
||||
TakingTurn,
|
||||
LOG_TICKS,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -74,10 +79,9 @@ impl<'a> System<'a> for HungerSystem {
|
|||
add_effect(None, EffectType::Damage { amount: 1 }, Targets::Entity { target: entity });
|
||||
}
|
||||
if LOG_TICKS && entity == *player_entity {
|
||||
rltk::console::log(format!(
|
||||
"HUNGER SYSTEM: Ticked for player entity. [clock: {}]",
|
||||
hunger_clock.duration
|
||||
));
|
||||
rltk::console::log(
|
||||
format!("HUNGER SYSTEM: Ticked for player entity. [clock: {}]", hunger_clock.duration)
|
||||
);
|
||||
}
|
||||
if hunger_clock.state == initial_state {
|
||||
continue;
|
||||
|
|
@ -87,7 +91,9 @@ impl<'a> System<'a> for HungerSystem {
|
|||
}
|
||||
// Things which only happen to the player.
|
||||
match hunger_clock.state {
|
||||
HungerState::Satiated => gamelog::Logger::new()
|
||||
HungerState::Satiated =>
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You feel")
|
||||
.colour(get_hunger_colour(hunger_clock.state))
|
||||
.append_n("satiated")
|
||||
|
|
@ -95,28 +101,36 @@ impl<'a> System<'a> for HungerSystem {
|
|||
.period()
|
||||
.log(),
|
||||
HungerState::Normal => {}
|
||||
HungerState::Hungry => gamelog::Logger::new()
|
||||
HungerState::Hungry =>
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You feel")
|
||||
.colour(get_hunger_colour(hunger_clock.state))
|
||||
.append_n("hungry")
|
||||
.colour(WHITE)
|
||||
.period()
|
||||
.log(),
|
||||
HungerState::Weak => gamelog::Logger::new()
|
||||
HungerState::Weak =>
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You feel")
|
||||
.colour(get_hunger_colour(hunger_clock.state))
|
||||
.append_n("weak with hunger")
|
||||
.colour(WHITE)
|
||||
.period()
|
||||
.log(),
|
||||
HungerState::Fainting => gamelog::Logger::new()
|
||||
HungerState::Fainting =>
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You feel")
|
||||
.colour(get_hunger_colour(hunger_clock.state))
|
||||
.append_n("hungry enough to faint")
|
||||
.colour(WHITE)
|
||||
.period()
|
||||
.log(),
|
||||
_ => gamelog::Logger::new()
|
||||
_ =>
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.colour(get_hunger_colour(hunger_clock.state))
|
||||
.append_n("You can't go on without food!")
|
||||
.log(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
use crate::{
|
||||
gamelog, gui::obfuscate_name, Beatitude, Charges, EquipmentChanged, InBackpack, MagicItem, MasterDungeonMap, Name,
|
||||
ObfuscatedName, Position, WantsToPickupItem,
|
||||
gamelog,
|
||||
gui::obfuscate_name,
|
||||
Beatitude,
|
||||
Charges,
|
||||
EquipmentChanged,
|
||||
InBackpack,
|
||||
MagicItem,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Position,
|
||||
WantsToPickupItem,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -45,9 +55,11 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
|||
.expect("Unable to insert EquipmentChanged.");
|
||||
|
||||
if pickup.collected_by == *player_entity {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You pick up the")
|
||||
.item_name_n(format!(
|
||||
.item_name_n(
|
||||
format!(
|
||||
"{}",
|
||||
obfuscate_name(
|
||||
pickup.item,
|
||||
|
|
@ -57,9 +69,9 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
|||
&beatitudes,
|
||||
&dm,
|
||||
Some(&wands)
|
||||
).0
|
||||
)
|
||||
)
|
||||
.0
|
||||
))
|
||||
.period()
|
||||
.log();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
use crate::{
|
||||
gamelog, gui::obfuscate_name, Beatitude, Charges, EquipmentChanged, InBackpack, MagicItem, MasterDungeonMap, Name,
|
||||
ObfuscatedName, Position, WantsToDropItem,
|
||||
gamelog,
|
||||
gui::obfuscate_name,
|
||||
Beatitude,
|
||||
Charges,
|
||||
EquipmentChanged,
|
||||
InBackpack,
|
||||
MagicItem,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
Position,
|
||||
WantsToDropItem,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -53,9 +63,11 @@ impl<'a> System<'a> for ItemDropSystem {
|
|||
backpack.remove(to_drop.item);
|
||||
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You drop the")
|
||||
.item_name_n(format!(
|
||||
.item_name_n(
|
||||
format!(
|
||||
"{}",
|
||||
obfuscate_name(
|
||||
to_drop.item,
|
||||
|
|
@ -65,9 +77,9 @@ impl<'a> System<'a> for ItemDropSystem {
|
|||
&beatitudes,
|
||||
&dm,
|
||||
Some(&wands)
|
||||
).0
|
||||
)
|
||||
)
|
||||
.0
|
||||
))
|
||||
.period()
|
||||
.log();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,19 @@
|
|||
use crate::{
|
||||
gamelog,
|
||||
gui::{ item_colour, obfuscate_name },
|
||||
Beatitude, EquipmentChanged, Equippable, Equipped, IdentifiedBeatitude, IdentifiedItem, InBackpack, MagicItem,
|
||||
MasterDungeonMap, Name, ObfuscatedName, WantsToUseItem, BUC,
|
||||
Beatitude,
|
||||
EquipmentChanged,
|
||||
Equippable,
|
||||
Equipped,
|
||||
IdentifiedBeatitude,
|
||||
IdentifiedItem,
|
||||
InBackpack,
|
||||
MagicItem,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
WantsToUseItem,
|
||||
BUC,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -70,9 +81,8 @@ impl<'a> System<'a> for ItemEquipSystem {
|
|||
&obfuscated_names,
|
||||
&beatitudes,
|
||||
&dm,
|
||||
None,
|
||||
)
|
||||
.0,
|
||||
None
|
||||
).0
|
||||
)
|
||||
.colour(rltk::WHITE)
|
||||
.append("!");
|
||||
|
|
@ -96,8 +106,7 @@ impl<'a> System<'a> for ItemEquipSystem {
|
|||
.append("You remove your")
|
||||
.colour(item_colour(*item, &beatitudes))
|
||||
.append_n(
|
||||
obfuscate_name(*item, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None)
|
||||
.0,
|
||||
obfuscate_name(*item, &names, &magic_items, &obfuscated_names, &beatitudes, &dm, None).0
|
||||
)
|
||||
.colour(rltk::WHITE)
|
||||
.period();
|
||||
|
|
@ -121,18 +130,16 @@ impl<'a> System<'a> for ItemEquipSystem {
|
|||
&obfuscated_names,
|
||||
&beatitudes,
|
||||
&dm,
|
||||
None,
|
||||
)
|
||||
.0,
|
||||
None
|
||||
).0
|
||||
)
|
||||
.colour(rltk::WHITE)
|
||||
.period();
|
||||
logger.log();
|
||||
identified_items
|
||||
.insert(
|
||||
target,
|
||||
IdentifiedItem { name: names.get(wants_to_use_item.item).unwrap().name.clone() },
|
||||
)
|
||||
.insert(target, IdentifiedItem {
|
||||
name: names.get(wants_to_use_item.item).unwrap().name.clone(),
|
||||
})
|
||||
.expect("Unable to insert IdentifiedItem");
|
||||
identified_beatitude
|
||||
.insert(wants_to_use_item.item, IdentifiedBeatitude {})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ mod identification_system;
|
|||
mod remove_system;
|
||||
mod use_system;
|
||||
|
||||
pub use {
|
||||
collection_system::ItemCollectionSystem, drop_system::ItemDropSystem, equip_system::ItemEquipSystem,
|
||||
identification_system::ItemIdentificationSystem, remove_system::ItemRemoveSystem, use_system::ItemUseSystem,
|
||||
pub use self::{
|
||||
collection_system::ItemCollectionSystem,
|
||||
drop_system::ItemDropSystem,
|
||||
equip_system::ItemEquipSystem,
|
||||
identification_system::ItemIdentificationSystem,
|
||||
remove_system::ItemRemoveSystem,
|
||||
use_system::ItemUseSystem,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,15 @@
|
|||
use crate::{
|
||||
gamelog,
|
||||
gui::{ item_colour, obfuscate_name },
|
||||
Beatitude, Equipped, InBackpack, MagicItem, MasterDungeonMap, Name, ObfuscatedName, WantsToRemoveItem, BUC,
|
||||
Beatitude,
|
||||
Equipped,
|
||||
InBackpack,
|
||||
MagicItem,
|
||||
MasterDungeonMap,
|
||||
Name,
|
||||
ObfuscatedName,
|
||||
WantsToRemoveItem,
|
||||
BUC,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -43,7 +51,8 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
|||
// If cursed, can't remove!
|
||||
if beatitude.buc == BUC::Cursed {
|
||||
can_remove = false;
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You can't remove the")
|
||||
.colour(item_colour(to_remove.item, &beatitudes))
|
||||
.append_n(
|
||||
|
|
@ -54,9 +63,8 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
|||
&obfuscated_names,
|
||||
&beatitudes,
|
||||
&dm,
|
||||
None,
|
||||
)
|
||||
.0,
|
||||
None
|
||||
).0
|
||||
)
|
||||
.colour(WHITE)
|
||||
.append("!")
|
||||
|
|
@ -70,7 +78,8 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
|||
equipped.remove(to_remove.item);
|
||||
if let Some(_) = names.get(to_remove.item) {
|
||||
if entity == *player_entity {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You unequip the")
|
||||
.colour(item_colour(to_remove.item, &beatitudes))
|
||||
.append_n(
|
||||
|
|
@ -81,9 +90,8 @@ impl<'a> System<'a> for ItemRemoveSystem {
|
|||
&obfuscated_names,
|
||||
&beatitudes,
|
||||
&dm,
|
||||
None,
|
||||
)
|
||||
.0,
|
||||
None
|
||||
).0
|
||||
)
|
||||
.colour(WHITE)
|
||||
.period()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
use crate::{
|
||||
effects::{ add_effect, aoe_tiles, EffectType, Targets },
|
||||
EquipmentChanged, IdentifiedItem, Map, Name, WantsToUseItem, AOE,
|
||||
EquipmentChanged,
|
||||
IdentifiedItem,
|
||||
Map,
|
||||
Name,
|
||||
WantsToUseItem,
|
||||
AOE,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -32,10 +37,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
.expect("Unable to insert");
|
||||
}
|
||||
// Call the effects system
|
||||
add_effect(
|
||||
Some(entity),
|
||||
EffectType::ItemUse { item: useitem.item },
|
||||
match useitem.target {
|
||||
add_effect(Some(entity), EffectType::ItemUse { item: useitem.item }, match useitem.target {
|
||||
None => Targets::Entity { target: *player_entity },
|
||||
Some(target) => {
|
||||
if let Some(aoe) = aoe.get(useitem.item) {
|
||||
|
|
@ -44,8 +46,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
Targets::Tile { target: map.xy_idx(target.x, target.y) }
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
wants_use.clear();
|
||||
}
|
||||
|
|
|
|||
101
src/main.rs
101
src/main.rs
|
|
@ -53,18 +53,32 @@ pub enum RunState {
|
|||
ShowInventory,
|
||||
ShowDropItem,
|
||||
ShowRemoveItem,
|
||||
ShowTargeting { range: i32, item: Entity, aoe: i32 },
|
||||
ShowTargeting {
|
||||
range: i32,
|
||||
item: Entity,
|
||||
aoe: i32,
|
||||
},
|
||||
ShowRemoveCurse,
|
||||
ShowIdentify,
|
||||
ActionWithDirection { function: fn(i: i32, j: i32, ecs: &mut World) -> RunState },
|
||||
MainMenu { menu_selection: gui::MainMenuSelection },
|
||||
CharacterCreation { ancestry: gui::Ancestry, class: gui::Class },
|
||||
ActionWithDirection {
|
||||
function: fn(i: i32, j: i32, ecs: &mut World) -> RunState,
|
||||
},
|
||||
MainMenu {
|
||||
menu_selection: gui::MainMenuSelection,
|
||||
},
|
||||
CharacterCreation {
|
||||
ancestry: gui::Ancestry,
|
||||
class: gui::Class,
|
||||
},
|
||||
SaveGame,
|
||||
GameOver,
|
||||
NextLevel,
|
||||
PreviousLevel,
|
||||
HelpScreen,
|
||||
MagicMapReveal { row: i32, cursed: bool }, // Animates magic mapping effect
|
||||
MagicMapReveal {
|
||||
row: i32,
|
||||
cursed: bool,
|
||||
}, // Animates magic mapping effect
|
||||
MapGeneration,
|
||||
}
|
||||
|
||||
|
|
@ -260,20 +274,30 @@ impl GameState for State {
|
|||
self.ecs.maintain();
|
||||
try_spawn_interval(&mut self.ecs);
|
||||
match *self.ecs.fetch::<RunState>() {
|
||||
RunState::AwaitingInput => new_runstate = RunState::AwaitingInput,
|
||||
RunState::MagicMapReveal { row, cursed } => {
|
||||
new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed }
|
||||
RunState::AwaitingInput => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
RunState::MagicMapReveal { row, cursed } => {
|
||||
new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed };
|
||||
}
|
||||
RunState::ShowRemoveCurse => {
|
||||
new_runstate = RunState::ShowRemoveCurse;
|
||||
}
|
||||
RunState::ShowIdentify => {
|
||||
new_runstate = RunState::ShowIdentify;
|
||||
}
|
||||
_ => {
|
||||
new_runstate = RunState::Ticking;
|
||||
}
|
||||
RunState::ShowRemoveCurse => new_runstate = RunState::ShowRemoveCurse,
|
||||
RunState::ShowIdentify => new_runstate = RunState::ShowIdentify,
|
||||
_ => new_runstate = RunState::Ticking,
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowCheatMenu => {
|
||||
let result = gui::show_cheat_menu(self, ctx);
|
||||
match result {
|
||||
gui::CheatMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::CheatMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::CheatMenuResult::NoResponse => {}
|
||||
gui::CheatMenuResult::Ascend => {
|
||||
self.goto_level(-1);
|
||||
|
|
@ -312,7 +336,9 @@ impl GameState for State {
|
|||
RunState::ShowInventory => {
|
||||
let result = gui::show_inventory(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
|
|
@ -326,10 +352,13 @@ impl GameState for State {
|
|||
range: ranged_item.range,
|
||||
item: item_entity,
|
||||
aoe: aoe_item.radius,
|
||||
}
|
||||
};
|
||||
} else {
|
||||
new_runstate =
|
||||
RunState::ShowTargeting { range: ranged_item.range, item: item_entity, aoe: 0 }
|
||||
new_runstate = RunState::ShowTargeting {
|
||||
range: ranged_item.range,
|
||||
item: item_entity,
|
||||
aoe: 0,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
|
|
@ -344,7 +373,9 @@ impl GameState for State {
|
|||
RunState::ShowDropItem => {
|
||||
let result = gui::drop_item_menu(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
|
|
@ -359,7 +390,9 @@ impl GameState for State {
|
|||
RunState::ShowRemoveItem => {
|
||||
let result = gui::remove_item_menu(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
|
|
@ -374,7 +407,9 @@ impl GameState for State {
|
|||
RunState::ShowTargeting { range, item, aoe } => {
|
||||
let result = gui::ranged_target(self, ctx, range, aoe);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let mut intent = self.ecs.write_storage::<WantsToUseItem>();
|
||||
|
|
@ -388,7 +423,9 @@ impl GameState for State {
|
|||
RunState::ShowRemoveCurse => {
|
||||
let result = gui::remove_curse(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
|
|
@ -403,7 +440,9 @@ impl GameState for State {
|
|||
RunState::ShowIdentify => {
|
||||
let result = gui::identify(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => new_runstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::Cancel => {
|
||||
new_runstate = RunState::AwaitingInput;
|
||||
}
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
|
|
@ -425,14 +464,15 @@ impl GameState for State {
|
|||
let result = gui::main_menu(self, ctx);
|
||||
match result {
|
||||
gui::MainMenuResult::NoSelection { selected } => {
|
||||
new_runstate = RunState::MainMenu { menu_selection: selected }
|
||||
new_runstate = RunState::MainMenu { menu_selection: selected };
|
||||
}
|
||||
gui::MainMenuResult::Selected { selected } => match selected {
|
||||
gui::MainMenuResult::Selected { selected } =>
|
||||
match selected {
|
||||
gui::MainMenuSelection::NewGame => {
|
||||
new_runstate = RunState::CharacterCreation {
|
||||
ancestry: gui::Ancestry::Human,
|
||||
class: gui::Class::Fighter,
|
||||
}
|
||||
};
|
||||
}
|
||||
gui::MainMenuSelection::LoadGame => {
|
||||
saveload_system::load_game(&mut self.ecs);
|
||||
|
|
@ -442,14 +482,14 @@ impl GameState for State {
|
|||
gui::MainMenuSelection::Quit => {
|
||||
::std::process::exit(0);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::CharacterCreation { .. } => {
|
||||
let result = gui::character_creation(self, ctx);
|
||||
match result {
|
||||
gui::CharCreateResult::NoSelection { ancestry, class } => {
|
||||
new_runstate = RunState::CharacterCreation { ancestry, class }
|
||||
new_runstate = RunState::CharacterCreation { ancestry, class };
|
||||
}
|
||||
gui::CharCreateResult::Selected { ancestry, class } => {
|
||||
if ancestry == gui::Ancestry::NULL {
|
||||
|
|
@ -473,8 +513,9 @@ impl GameState for State {
|
|||
gui::YesNoResult::Yes => {
|
||||
self.game_over_cleanup();
|
||||
new_runstate = RunState::MapGeneration;
|
||||
self.mapgen_next_state =
|
||||
Some(RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame });
|
||||
self.mapgen_next_state = Some(RunState::MainMenu {
|
||||
menu_selection: gui::MainMenuSelection::NewGame,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -508,7 +549,7 @@ impl GameState for State {
|
|||
if x % 2 == 0 {
|
||||
idx = map.xy_idx(x as i32, row);
|
||||
} else {
|
||||
idx = map.xy_idx(x as i32, (map.height as i32 - 1) - (row));
|
||||
idx = map.xy_idx(x as i32, (map.height as i32) - 1 - row);
|
||||
}
|
||||
if !cursed {
|
||||
map.revealed_tiles[idx] = true;
|
||||
|
|
@ -527,7 +568,7 @@ impl GameState for State {
|
|||
}
|
||||
}
|
||||
|
||||
if row as usize == map.height as usize - 1 {
|
||||
if (row as usize) == (map.height as usize) - 1 {
|
||||
new_runstate = RunState::Ticking;
|
||||
} else {
|
||||
new_runstate = RunState::MagicMapReveal { row: row + 1, cursed: cursed };
|
||||
|
|
|
|||
|
|
@ -108,18 +108,42 @@ fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String {
|
|||
}
|
||||
|
||||
const POTION_COLOURS: &[&str] = &[
|
||||
"red", "orange", "yellow", "green", "blue", "indigo", "violet", "black", "white", "silver", "gold", "rainbow",
|
||||
"blood", "purple", "cyan", "brown", "grey", "octarine",
|
||||
"red",
|
||||
"orange",
|
||||
"yellow",
|
||||
"green",
|
||||
"blue",
|
||||
"indigo",
|
||||
"violet",
|
||||
"black",
|
||||
"white",
|
||||
"silver",
|
||||
"gold",
|
||||
"rainbow",
|
||||
"blood",
|
||||
"purple",
|
||||
"cyan",
|
||||
"brown",
|
||||
"grey",
|
||||
"octarine",
|
||||
];
|
||||
const POTION_ADJECTIVES: &[&str] = &[
|
||||
"swirling",
|
||||
"viscous",
|
||||
"effervescent",
|
||||
"slimy",
|
||||
"oily",
|
||||
"metallic",
|
||||
"prismatic",
|
||||
"goopy",
|
||||
];
|
||||
const POTION_ADJECTIVES: &[&str] =
|
||||
&["swirling", "viscous", "effervescent", "slimy", "oily", "metallic", "prismatic", "goopy"];
|
||||
|
||||
fn make_potion_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
||||
loop {
|
||||
let mut name: String =
|
||||
POTION_ADJECTIVES[rng.roll_dice(1, POTION_ADJECTIVES.len() as i32) as usize - 1].to_string();
|
||||
POTION_ADJECTIVES[(rng.roll_dice(1, POTION_ADJECTIVES.len() as i32) as usize) - 1].to_string();
|
||||
name += " ";
|
||||
name += POTION_COLOURS[rng.roll_dice(1, POTION_COLOURS.len() as i32) as usize - 1];
|
||||
name += POTION_COLOURS[(rng.roll_dice(1, POTION_COLOURS.len() as i32) as usize) - 1];
|
||||
name += " potion";
|
||||
|
||||
if !used_names.contains(&name) {
|
||||
|
|
@ -153,7 +177,7 @@ const WAND_TYPES: &[&str] = &[
|
|||
|
||||
fn make_wand_name(rng: &mut RandomNumberGenerator, used_names: &mut HashSet<String>) -> String {
|
||||
loop {
|
||||
let mut name: String = WAND_TYPES[rng.roll_dice(1, WAND_TYPES.len() as i32) as usize - 1].to_string();
|
||||
let mut name: String = WAND_TYPES[(rng.roll_dice(1, WAND_TYPES.len() as i32) as usize) - 1].to_string();
|
||||
name += " wand";
|
||||
|
||||
if !used_names.contains(&name) {
|
||||
|
|
@ -189,12 +213,12 @@ fn transition_to_existing_map(ecs: &mut World, new_id: i32, offset: i32) {
|
|||
for (idx, tt) in map.tiles.iter().enumerate() {
|
||||
if *tt == stair_type {
|
||||
let mut player_position = ecs.write_resource::<Point>();
|
||||
*player_position = Point::new(idx as i32 % w, idx as i32 / w);
|
||||
*player_position = Point::new((idx as i32) % w, (idx as i32) / w);
|
||||
let mut position_components = ecs.write_storage::<Position>();
|
||||
let player_pos_component = position_components.get_mut(*player_entity);
|
||||
if let Some(player_pos_component) = player_pos_component {
|
||||
player_pos_component.x = idx as i32 % w;
|
||||
player_pos_component.y = idx as i32 / w;
|
||||
player_pos_component.x = (idx as i32) % w;
|
||||
player_pos_component.y = (idx as i32) / w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ fn spawn_random_mob_in_free_nonvisible_tile(ecs: &mut World) {
|
|||
let roll = raws::get_mob_spawn_amount(&mut rng, &spawn_type, player_level);
|
||||
for _i in 0..roll {
|
||||
let idx = get_random_idx_from_tiles(&mut rng, &mut available_tiles);
|
||||
spawn_locations.push((idx as i32 % map.width, idx as i32 / map.width));
|
||||
spawn_locations.push(((idx as i32) % map.width, (idx as i32) / map.width));
|
||||
}
|
||||
// Dropping resources for borrow-checker.
|
||||
std::mem::drop(map);
|
||||
|
|
@ -64,7 +64,7 @@ fn spawn_random_mob_in_free_nonvisible_tile(ecs: &mut World) {
|
|||
&key,
|
||||
None,
|
||||
raws::SpawnType::AtPosition { x: idx.0, y: idx.1 },
|
||||
difficulty,
|
||||
difficulty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ impl Map {
|
|||
let mut rng = rltk::RandomNumberGenerator::new();
|
||||
|
||||
for idx in 0..map.colour_offset.len() {
|
||||
let red_roll: f32 = (rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32 / 100f32 + 1.0;
|
||||
let green_roll: f32 = (rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32 / 100f32 + 1.0;
|
||||
let blue_roll: f32 = (rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32 / 100f32 + 1.0;
|
||||
let red_roll: f32 = ((rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32) / 100f32 + 1.0;
|
||||
let green_roll: f32 = ((rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32) / 100f32 + 1.0;
|
||||
let blue_roll: f32 = ((rng.roll_dice(1, TWICE_OFFSET - 1) + 1 - OFFSET_PERCENT) as f32) / 100f32 + 1.0;
|
||||
map.colour_offset[idx] = (red_roll, green_roll, blue_roll);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub fn get_tile_renderables_for_id(idx: usize, map: &Map, other_pos: Option<Poin
|
|||
|
||||
// If one of the colours was left blank, make them the same.
|
||||
if fg == RGB::new() {
|
||||
fg = bg
|
||||
fg = bg;
|
||||
} else if bg == RGB::new() {
|
||||
bg = fg;
|
||||
}
|
||||
|
|
@ -22,8 +22,10 @@ pub fn get_tile_renderables_for_id(idx: usize, map: &Map, other_pos: Option<Poin
|
|||
bg = apply_bloodstain_if_necessary(bg, map, idx);
|
||||
(fg, bg) = darken_if_not_visible(fg, bg, map, idx);
|
||||
if other_pos.is_some() && DARKEN_TILES_BY_DISTANCE {
|
||||
let distance =
|
||||
darken_by_distance(Point::new(idx as i32 % map.width, idx as i32 / map.width), other_pos.unwrap());
|
||||
let distance = darken_by_distance(
|
||||
Point::new((idx as i32) % map.width, (idx as i32) / map.width),
|
||||
other_pos.unwrap()
|
||||
);
|
||||
(fg, bg) = (fg.mul(distance), bg.mul(distance));
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ fn is_revealed_and_wall(map: &Map, x: i32, y: i32) -> bool {
|
|||
}
|
||||
|
||||
fn wall_glyph(map: &Map, x: i32, y: i32) -> 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;
|
||||
}
|
||||
let mut mask: u8 = 0;
|
||||
|
|
@ -251,8 +253,9 @@ pub fn multiply_by_float(rgb: rltk::RGB, offsets: (f32, f32, f32)) -> RGB {
|
|||
|
||||
fn darken_by_distance(pos: Point, other_pos: Point) -> f32 {
|
||||
let distance = DistanceAlg::Pythagoras.distance2d(pos, other_pos) as f32; // Get distance in tiles.
|
||||
let interp_factor = (distance - START_DARKEN_AT_N_TILES)
|
||||
/ (MAX_DARKEN_AT_N_TILES * crate::config::entity::DEFAULT_VIEWSHED_STANDARD as f32 - START_DARKEN_AT_N_TILES);
|
||||
let interp_factor =
|
||||
(distance - START_DARKEN_AT_N_TILES) /
|
||||
(MAX_DARKEN_AT_N_TILES * (crate::config::entity::DEFAULT_VIEWSHED_STANDARD as f32) - START_DARKEN_AT_N_TILES);
|
||||
let interp_factor = interp_factor.max(0.0).min(1.0); // Clamp [0-1]
|
||||
return 1.0 - interp_factor * (1.0 - MAX_DARKENING);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub enum TileType {
|
|||
|
||||
pub fn tile_walkable(tt: TileType) -> bool {
|
||||
match tt {
|
||||
TileType::Floor
|
||||
| TileType::Floor
|
||||
| TileType::WoodFloor
|
||||
| TileType::Gravel
|
||||
| TileType::Road
|
||||
|
|
|
|||
|
|
@ -37,14 +37,26 @@ impl AreaStartingPosition {
|
|||
let seed_y;
|
||||
|
||||
match self.x {
|
||||
XStart::LEFT => seed_x = 1,
|
||||
XStart::CENTRE => seed_x = build_data.map.width / 2,
|
||||
XStart::RIGHT => seed_x = build_data.map.width - 2,
|
||||
XStart::LEFT => {
|
||||
seed_x = 1;
|
||||
}
|
||||
XStart::CENTRE => {
|
||||
seed_x = build_data.map.width / 2;
|
||||
}
|
||||
XStart::RIGHT => {
|
||||
seed_x = build_data.map.width - 2;
|
||||
}
|
||||
}
|
||||
match self.y {
|
||||
YStart::TOP => seed_y = 1,
|
||||
YStart::CENTRE => seed_y = build_data.map.height / 2,
|
||||
YStart::BOTTOM => seed_y = build_data.map.height - 2,
|
||||
YStart::TOP => {
|
||||
seed_y = 1;
|
||||
}
|
||||
YStart::CENTRE => {
|
||||
seed_y = build_data.map.height / 2;
|
||||
}
|
||||
YStart::BOTTOM => {
|
||||
seed_y = build_data.map.height - 2;
|
||||
}
|
||||
}
|
||||
|
||||
let mut available_floors: Vec<(usize, f32)> = Vec::new();
|
||||
|
|
@ -53,8 +65,8 @@ impl AreaStartingPosition {
|
|||
available_floors.push((
|
||||
idx,
|
||||
rltk::DistanceAlg::PythagorasSquared.distance2d(
|
||||
rltk::Point::new(idx as i32 % build_data.map.width, idx as i32 / build_data.map.width),
|
||||
rltk::Point::new(seed_x, seed_y),
|
||||
rltk::Point::new((idx as i32) % build_data.map.width, (idx as i32) / build_data.map.width),
|
||||
rltk::Point::new(seed_x, seed_y)
|
||||
),
|
||||
));
|
||||
}
|
||||
|
|
@ -65,8 +77,8 @@ impl AreaStartingPosition {
|
|||
|
||||
available_floors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||
|
||||
let start_x = available_floors[0].0 as i32 % build_data.map.width;
|
||||
let start_y = available_floors[0].0 as i32 / build_data.map.width;
|
||||
let start_x = (available_floors[0].0 as i32) % build_data.map.width;
|
||||
let start_y = (available_floors[0].0 as i32) / build_data.map.width;
|
||||
|
||||
build_data.starting_position = Some(Position { x: start_x, y: start_y });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl BspInteriorBuilder {
|
|||
for y in room.y1..room.y2 {
|
||||
for x in room.x1..room.x2 {
|
||||
let idx = build_data.map.xy_idx(x, y);
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize {
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height - 1) as usize) {
|
||||
build_data.map.tiles[idx] = TileType::Floor;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ impl CellularAutomataBuilder {
|
|||
let roll = rng.roll_dice(1, 100);
|
||||
let idx = build_data.map.xy_idx(x, y);
|
||||
if roll > 55 {
|
||||
build_data.map.tiles[idx] = TileType::Floor
|
||||
build_data.map.tiles[idx] = TileType::Floor;
|
||||
} else {
|
||||
build_data.map.tiles[idx] = TileType::Wall
|
||||
build_data.map.tiles[idx] = TileType::Wall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,22 +58,22 @@ impl CellularAutomataBuilder {
|
|||
if build_data.map.tiles[idx + 1] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx - build_data.map.width as usize] == TileType::Wall {
|
||||
if build_data.map.tiles[idx - (build_data.map.width as usize)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx + build_data.map.width as usize] == TileType::Wall {
|
||||
if build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx - (build_data.map.width as usize - 1)] == TileType::Wall {
|
||||
if build_data.map.tiles[idx - ((build_data.map.width as usize) - 1)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx - (build_data.map.width as usize + 1)] == TileType::Wall {
|
||||
if build_data.map.tiles[idx - ((build_data.map.width as usize) + 1)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx + (build_data.map.width as usize - 1)] == TileType::Wall {
|
||||
if build_data.map.tiles[idx + ((build_data.map.width as usize) - 1)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx + (build_data.map.width as usize + 1)] == TileType::Wall {
|
||||
if build_data.map.tiles[idx + ((build_data.map.width as usize) + 1)] == TileType::Wall {
|
||||
neighbors += 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl CullUnreachable {
|
|||
build_data.map.height as usize,
|
||||
&map_starts,
|
||||
&build_data.map,
|
||||
1000.0,
|
||||
1000.0
|
||||
);
|
||||
for (i, tile) in build_data.map.tiles.iter_mut().enumerate() {
|
||||
if *tile == TileType::Floor {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ impl DistantExit {
|
|||
build_data.map.height as usize,
|
||||
&map_starts,
|
||||
&build_data.map,
|
||||
1000.0,
|
||||
1000.0
|
||||
);
|
||||
let mut exit_tile = (0, 0.0f32);
|
||||
for (i, tile) in build_data.map.tiles.iter_mut().enumerate() {
|
||||
|
|
|
|||
|
|
@ -100,13 +100,16 @@ impl DLABuilder {
|
|||
build_data.map.tiles[start_idx] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx - 1] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx + 1] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx - build_data.map.width as usize] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx + build_data.map.width as usize] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx - (build_data.map.width as usize)] = TileType::Floor;
|
||||
build_data.map.tiles[start_idx + (build_data.map.width as usize)] = TileType::Floor;
|
||||
|
||||
// Random walker
|
||||
let total_tiles = build_data.map.width * build_data.map.height;
|
||||
let desired_floor_tiles = (self.floor_percent * total_tiles as f32) as usize;
|
||||
let mut floor_tile_count = build_data.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
|
||||
let desired_floor_tiles = (self.floor_percent * (total_tiles as f32)) as usize;
|
||||
let mut floor_tile_count = build_data.map.tiles
|
||||
.iter()
|
||||
.filter(|a| **a == TileType::Floor)
|
||||
.count();
|
||||
while floor_tile_count < desired_floor_tiles {
|
||||
match self.algorithm {
|
||||
DLAAlgorithm::WalkInwards => {
|
||||
|
|
@ -189,7 +192,7 @@ impl DLABuilder {
|
|||
let mut path = rltk::line2d(
|
||||
rltk::LineAlg::Bresenham,
|
||||
rltk::Point::new(digger_x, digger_y),
|
||||
rltk::Point::new(starting_position.x, starting_position.y),
|
||||
rltk::Point::new(starting_position.x, starting_position.y)
|
||||
);
|
||||
|
||||
while build_data.map.tiles[digger_idx] == TileType::Wall && !path.is_empty() {
|
||||
|
|
@ -206,7 +209,10 @@ impl DLABuilder {
|
|||
|
||||
build_data.take_snapshot();
|
||||
|
||||
floor_tile_count = build_data.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
|
||||
floor_tile_count = build_data.map.tiles
|
||||
.iter()
|
||||
.filter(|a| **a == TileType::Floor)
|
||||
.count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,27 +45,35 @@ impl DoorPlacement {
|
|||
}
|
||||
}
|
||||
|
||||
let x = idx % build_data.map.width as usize;
|
||||
let y = idx / build_data.map.width as usize;
|
||||
let x = idx % (build_data.map.width as usize);
|
||||
let y = idx / (build_data.map.width as usize);
|
||||
|
||||
// Check for east-west door possibility
|
||||
if build_data.map.tiles[idx] == TileType::Floor
|
||||
&& (x > 1 && build_data.map.tiles[idx - 1] == TileType::Floor)
|
||||
&& (x < build_data.map.width as usize - 2 && build_data.map.tiles[idx + 1] == TileType::Floor)
|
||||
&& (y > 1 && build_data.map.tiles[idx - build_data.map.width as usize] == TileType::Wall)
|
||||
&& (y < build_data.map.height as usize - 2
|
||||
&& build_data.map.tiles[idx + build_data.map.width as usize] == TileType::Wall)
|
||||
if
|
||||
build_data.map.tiles[idx] == TileType::Floor &&
|
||||
x > 1 &&
|
||||
build_data.map.tiles[idx - 1] == TileType::Floor &&
|
||||
x < (build_data.map.width as usize) - 2 &&
|
||||
build_data.map.tiles[idx + 1] == TileType::Floor &&
|
||||
y > 1 &&
|
||||
build_data.map.tiles[idx - (build_data.map.width as usize)] == TileType::Wall &&
|
||||
y < (build_data.map.height as usize) - 2 &&
|
||||
build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Wall
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for north-south door possibility
|
||||
if build_data.map.tiles[idx] == TileType::Floor
|
||||
&& (x > 1 && build_data.map.tiles[idx - 1] == TileType::Wall)
|
||||
&& (x < build_data.map.width as usize - 2 && build_data.map.tiles[idx + 1] == TileType::Wall)
|
||||
&& (y > 1 && build_data.map.tiles[idx - build_data.map.width as usize] == TileType::Floor)
|
||||
&& (y < build_data.map.height as usize - 2
|
||||
&& build_data.map.tiles[idx + build_data.map.width as usize] == TileType::Floor)
|
||||
if
|
||||
build_data.map.tiles[idx] == TileType::Floor &&
|
||||
x > 1 &&
|
||||
build_data.map.tiles[idx - 1] == TileType::Wall &&
|
||||
x < (build_data.map.width as usize) - 2 &&
|
||||
build_data.map.tiles[idx + 1] == TileType::Wall &&
|
||||
y > 1 &&
|
||||
build_data.map.tiles[idx - (build_data.map.width as usize)] == TileType::Floor &&
|
||||
y < (build_data.map.height as usize) - 2 &&
|
||||
build_data.map.tiles[idx + (build_data.map.width as usize)] == TileType::Floor
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,8 +112,11 @@ impl DrunkardsWalkBuilder {
|
|||
build_data.map.tiles[start_idx] = TileType::Floor;
|
||||
|
||||
let total_tiles = build_data.map.width * build_data.map.height;
|
||||
let desired_floor_tiles = (self.settings.floor_percent * total_tiles as f32) as usize;
|
||||
let mut floor_tile_count = build_data.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
|
||||
let desired_floor_tiles = (self.settings.floor_percent * (total_tiles as f32)) as usize;
|
||||
let mut floor_tile_count = build_data.map.tiles
|
||||
.iter()
|
||||
.filter(|a| **a == TileType::Floor)
|
||||
.count();
|
||||
let mut digger_count = 0;
|
||||
while floor_tile_count < desired_floor_tiles {
|
||||
let mut did_something = false;
|
||||
|
|
@ -180,7 +183,10 @@ impl DrunkardsWalkBuilder {
|
|||
*t = TileType::Floor;
|
||||
}
|
||||
}
|
||||
floor_tile_count = build_data.map.tiles.iter().filter(|a| **a == TileType::Floor).count();
|
||||
floor_tile_count = build_data.map.tiles
|
||||
.iter()
|
||||
.filter(|a| **a == TileType::Floor)
|
||||
.count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
use super::{
|
||||
AreaStartingPosition, BuilderChain, BuilderMap, CellularAutomataBuilder, CullUnreachable, MetaMapBuilder, TileType,
|
||||
VoronoiSpawning, XStart, YStart,
|
||||
AreaStartingPosition,
|
||||
BuilderChain,
|
||||
BuilderMap,
|
||||
CellularAutomataBuilder,
|
||||
CullUnreachable,
|
||||
MetaMapBuilder,
|
||||
TileType,
|
||||
VoronoiSpawning,
|
||||
XStart,
|
||||
YStart,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
|
||||
|
|
@ -10,7 +18,7 @@ pub fn forest_builder(
|
|||
width: i32,
|
||||
height: i32,
|
||||
difficulty: i32,
|
||||
initial_player_level: i32,
|
||||
initial_player_level: i32
|
||||
) -> BuilderChain {
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "the woods", initial_player_level);
|
||||
chain.start_with(CellularAutomataBuilder::new());
|
||||
|
|
@ -44,8 +52,8 @@ impl RoadExit {
|
|||
available_floors.push((
|
||||
idx,
|
||||
DistanceAlg::PythagorasSquared.distance2d(
|
||||
Point::new(idx as i32 % build_data.map.width, idx as i32 / build_data.map.width),
|
||||
Point::new(seed_x, seed_y),
|
||||
Point::new((idx as i32) % build_data.map.width, (idx as i32) / build_data.map.width),
|
||||
Point::new(seed_x, seed_y)
|
||||
),
|
||||
));
|
||||
}
|
||||
|
|
@ -54,8 +62,8 @@ impl RoadExit {
|
|||
panic!("No valid floors to start on.");
|
||||
}
|
||||
available_floors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||
let end_x = available_floors[0].0 as i32 % build_data.map.width;
|
||||
let end_y = available_floors[0].0 as i32 / build_data.map.width;
|
||||
let end_x = (available_floors[0].0 as i32) % build_data.map.width;
|
||||
let end_y = (available_floors[0].0 as i32) / build_data.map.width;
|
||||
return (end_x, end_y);
|
||||
}
|
||||
|
||||
|
|
@ -78,8 +86,8 @@ impl RoadExit {
|
|||
|
||||
let path = a_star_search(start_idx, end_idx, &mut build_data.map);
|
||||
for idx in path.steps.iter() {
|
||||
let x = *idx as i32 % build_data.map.width;
|
||||
let y = *idx as i32 / build_data.map.width;
|
||||
let x = (*idx as i32) % build_data.map.width;
|
||||
let y = (*idx as i32) / build_data.map.width;
|
||||
self.paint_road(build_data, x, y);
|
||||
self.paint_road(build_data, x - 1, y);
|
||||
self.paint_road(build_data, x + 1, y);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl MazeBuilder {
|
|||
#[allow(clippy::map_entry)]
|
||||
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||
// Maze gen
|
||||
let mut maze = Grid::new((build_data.map.width / 2) - 2, (build_data.map.height / 2) - 2, rng);
|
||||
let mut maze = Grid::new(build_data.map.width / 2 - 2, build_data.map.height / 2 - 2, rng);
|
||||
maze.generate_maze(build_data);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ impl<'a> Grid<'a> {
|
|||
if row < 0 || column < 0 || column > self.width - 1 || row > self.height - 1 {
|
||||
-1
|
||||
} else {
|
||||
column + (row * self.width)
|
||||
column + row * self.width
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,16 +178,16 @@ impl<'a> Grid<'a> {
|
|||
|
||||
map.tiles[idx] = TileType::Floor;
|
||||
if !cell.walls[TOP] {
|
||||
map.tiles[idx - map.width as usize] = TileType::Floor
|
||||
map.tiles[idx - (map.width as usize)] = TileType::Floor;
|
||||
}
|
||||
if !cell.walls[RIGHT] {
|
||||
map.tiles[idx + 1] = TileType::Floor
|
||||
map.tiles[idx + 1] = TileType::Floor;
|
||||
}
|
||||
if !cell.walls[BOTTOM] {
|
||||
map.tiles[idx + map.width as usize] = TileType::Floor
|
||||
map.tiles[idx + (map.width as usize)] = TileType::Floor;
|
||||
}
|
||||
if !cell.walls[LEFT] {
|
||||
map.tiles[idx - 1] = TileType::Floor
|
||||
map.tiles[idx - 1] = TileType::Floor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl BuilderChain {
|
|||
height: i32,
|
||||
difficulty: i32,
|
||||
name: S,
|
||||
initial_player_level: i32,
|
||||
initial_player_level: i32
|
||||
) -> BuilderChain {
|
||||
BuilderChain {
|
||||
starter: None,
|
||||
|
|
@ -122,7 +122,9 @@ impl BuilderChain {
|
|||
|
||||
pub fn start_with(&mut self, starter: Box<dyn InitialMapBuilder>) {
|
||||
match self.starter {
|
||||
None => self.starter = Some(starter),
|
||||
None => {
|
||||
self.starter = Some(starter);
|
||||
}
|
||||
Some(_) => panic!("You can only have one starting builder."),
|
||||
};
|
||||
}
|
||||
|
|
@ -168,17 +170,29 @@ fn random_start_position(rng: &mut rltk::RandomNumberGenerator) -> (XStart, YSta
|
|||
let x;
|
||||
let xroll = rng.roll_dice(1, 3);
|
||||
match xroll {
|
||||
1 => x = XStart::LEFT,
|
||||
2 => x = XStart::CENTRE,
|
||||
_ => x = XStart::RIGHT,
|
||||
1 => {
|
||||
x = XStart::LEFT;
|
||||
}
|
||||
2 => {
|
||||
x = XStart::CENTRE;
|
||||
}
|
||||
_ => {
|
||||
x = XStart::RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
let y;
|
||||
let yroll = rng.roll_dice(1, 3);
|
||||
match yroll {
|
||||
1 => y = YStart::BOTTOM,
|
||||
2 => y = YStart::CENTRE,
|
||||
_ => y = YStart::TOP,
|
||||
1 => {
|
||||
y = YStart::BOTTOM;
|
||||
}
|
||||
2 => {
|
||||
y = YStart::CENTRE;
|
||||
}
|
||||
_ => {
|
||||
y = YStart::TOP;
|
||||
}
|
||||
}
|
||||
|
||||
(x, y)
|
||||
|
|
@ -305,7 +319,7 @@ pub fn random_builder(
|
|||
width: i32,
|
||||
height: i32,
|
||||
difficulty: i32,
|
||||
initial_player_level: i32,
|
||||
initial_player_level: i32
|
||||
) -> BuilderChain {
|
||||
rltk::console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
|
||||
let mut builder = BuilderChain::new(new_id, width, height, difficulty, "the dungeon", initial_player_level);
|
||||
|
|
@ -313,7 +327,9 @@ pub fn random_builder(
|
|||
let mut want_doors = true;
|
||||
match type_roll {
|
||||
1 => random_room_builder(rng, &mut builder),
|
||||
_ => want_doors = random_shape_builder(rng, &mut builder),
|
||||
_ => {
|
||||
want_doors = random_shape_builder(rng, &mut builder);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -354,7 +370,7 @@ pub fn level_builder(
|
|||
rng: &mut rltk::RandomNumberGenerator,
|
||||
width: i32,
|
||||
height: i32,
|
||||
initial_player_level: i32,
|
||||
initial_player_level: i32
|
||||
) -> BuilderChain {
|
||||
// TODO: With difficulty and ID/depth decoupled, this can be used for branches later.
|
||||
let difficulty = new_id;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl RoomBasedSpawner {
|
|||
rng,
|
||||
room,
|
||||
&mut build_data.spawn_list,
|
||||
build_data.initial_player_level,
|
||||
build_data.initial_player_level
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ impl RoomCornerRounder {
|
|||
if x > 0 && build_data.map.tiles[idx - 1] == TileType::Wall {
|
||||
neighbour_walls += 1;
|
||||
}
|
||||
if y > 0 && build_data.map.tiles[idx - w as usize] == TileType::Wall {
|
||||
if y > 0 && build_data.map.tiles[idx - (w as usize)] == TileType::Wall {
|
||||
neighbour_walls += 1;
|
||||
}
|
||||
if x < w - 2 && build_data.map.tiles[idx + 1] == TileType::Wall {
|
||||
neighbour_walls += 1;
|
||||
}
|
||||
if y < h - 2 && build_data.map.tiles[idx + w as usize] == TileType::Wall {
|
||||
if y < h - 2 && build_data.map.tiles[idx + (w as usize)] == TileType::Wall {
|
||||
neighbour_walls += 1;
|
||||
}
|
||||
if neighbour_walls == 2 {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl RoomDrawer {
|
|||
for y in room.y1 + 1..=room.y2 {
|
||||
for x in room.x1 + 1..=room.x2 {
|
||||
let idx = build_data.map.xy_idx(x, y);
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize {
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height - 1) as usize) {
|
||||
build_data.map.tiles[idx] = TileType::Floor;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,15 +27,14 @@ impl RoomDrawer {
|
|||
}
|
||||
|
||||
fn circle(&mut self, build_data: &mut BuilderMap, room: &Rect) {
|
||||
let radius = i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32 / 2.0;
|
||||
let radius = (i32::min(room.x2 - room.x1, room.y2 - room.y1) as f32) / 2.0;
|
||||
let center = room.centre();
|
||||
let center_pt = rltk::Point::new(center.0, center.1);
|
||||
for y in room.y1..=room.y2 {
|
||||
for x in room.x1..=room.x2 {
|
||||
let idx = build_data.map.xy_idx(x, y);
|
||||
let distance = rltk::DistanceAlg::Pythagoras.distance2d(center_pt, rltk::Point::new(x, y));
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height) - 1) as usize && distance <= radius
|
||||
{
|
||||
if idx > 0 && idx < ((build_data.map.width * build_data.map.height - 1) as usize) && distance <= radius {
|
||||
build_data.map.tiles[idx] = TileType::Floor;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,32 @@ impl RoomSorter {
|
|||
|
||||
fn sorter(&mut self, _rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
||||
match self.sort_by {
|
||||
RoomSort::LEFTMOST => build_data.rooms.as_mut().unwrap().sort_by(|a, b| a.x1.cmp(&b.x1)),
|
||||
RoomSort::RIGHTMOST => build_data.rooms.as_mut().unwrap().sort_by(|a, b| b.x2.cmp(&a.x2)),
|
||||
RoomSort::TOPMOST => build_data.rooms.as_mut().unwrap().sort_by(|a, b| a.y1.cmp(&b.y1)),
|
||||
RoomSort::BOTTOMMOST => build_data.rooms.as_mut().unwrap().sort_by(|a, b| b.y2.cmp(&a.y2)),
|
||||
RoomSort::LEFTMOST =>
|
||||
build_data.rooms
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.sort_by(|a, b| a.x1.cmp(&b.x1)),
|
||||
RoomSort::RIGHTMOST =>
|
||||
build_data.rooms
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.sort_by(|a, b| b.x2.cmp(&a.x2)),
|
||||
RoomSort::TOPMOST =>
|
||||
build_data.rooms
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.sort_by(|a, b| a.y1.cmp(&b.y1)),
|
||||
RoomSort::BOTTOMMOST =>
|
||||
build_data.rooms
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.sort_by(|a, b| b.y2.cmp(&a.y2)),
|
||||
RoomSort::CENTRAL => {
|
||||
let map_centre = rltk::Point::new(build_data.map.width / 2, build_data.map.height / 2);
|
||||
build_data.rooms.as_mut().unwrap().sort_by(|a: &Rect, b: &Rect| {
|
||||
build_data.rooms
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.sort_by(|a: &Rect, b: &Rect| {
|
||||
let a_centre_pt = rltk::Point::new(a.centre().0, a.centre().1);
|
||||
let b_centre_pt = rltk::Point::new(b.centre().0, b.centre().1);
|
||||
let distance_a = rltk::DistanceAlg::Pythagoras.distance2d(a_centre_pt, map_centre);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl BresenhamCorridors {
|
|||
let line = rltk::line2d(
|
||||
rltk::LineAlg::Bresenham,
|
||||
room_centre_pt,
|
||||
rltk::Point::new(dest_centre.0, dest_centre.1),
|
||||
rltk::Point::new(dest_centre.0, dest_centre.1)
|
||||
);
|
||||
let mut corridor = Vec::new();
|
||||
for cell in line.iter() {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ impl DoglegCorridors {
|
|||
for (i, room) in rooms.iter().enumerate() {
|
||||
if i > 0 {
|
||||
let (new_x, new_y) = room.centre();
|
||||
let (prev_x, prev_y) = rooms[i as usize - 1].centre();
|
||||
let (prev_x, prev_y) = rooms[(i as usize) - 1].centre();
|
||||
if rng.range(0, 2) == 1 {
|
||||
let mut c1 = apply_horizontal_tunnel(&mut build_data.map, prev_x, new_x, prev_y);
|
||||
let mut c2 = apply_vertical_tunnel(&mut build_data.map, prev_y, new_y, new_x);
|
||||
|
|
|
|||
|
|
@ -43,8 +43,13 @@ impl NearestCorridors {
|
|||
if !room_distance.is_empty() {
|
||||
room_distance.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
||||
let dest_centre = rooms[room_distance[0].0].centre();
|
||||
let corridor =
|
||||
draw_corridor(&mut build_data.map, room_centre.0, room_centre.1, dest_centre.0, dest_centre.1);
|
||||
let corridor = draw_corridor(
|
||||
&mut build_data.map,
|
||||
room_centre.0,
|
||||
room_centre.1,
|
||||
dest_centre.0,
|
||||
dest_centre.1
|
||||
);
|
||||
connected.insert(i);
|
||||
build_data.take_snapshot();
|
||||
corridors.push(corridor);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl CorridorSpawner {
|
|||
rng,
|
||||
&corridor,
|
||||
&mut build_data.spawn_list,
|
||||
build_data.initial_player_level,
|
||||
build_data.initial_player_level
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ impl SimpleMapBuilder {
|
|||
let (max_rooms, min_size, max_size);
|
||||
|
||||
if let Some(room_params) = room_params {
|
||||
(max_rooms, min_size, max_size) = (room_params.0, room_params.1, room_params.2)
|
||||
(max_rooms, min_size, max_size) = (room_params.0, room_params.1, room_params.2);
|
||||
} else {
|
||||
(max_rooms, min_size, max_size) = (DEFAULT_MAX_ROOMS, DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE)
|
||||
(max_rooms, min_size, max_size) = (DEFAULT_MAX_ROOMS, DEFAULT_MIN_SIZE, DEFAULT_MAX_SIZE);
|
||||
}
|
||||
|
||||
Box::new(SimpleMapBuilder { room_params: (max_rooms, min_size, max_size) })
|
||||
|
|
@ -42,7 +42,7 @@ impl SimpleMapBuilder {
|
|||
let mut ok = true;
|
||||
for other_room in rooms.iter() {
|
||||
if new_room.intersect(other_room) {
|
||||
ok = false
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub fn town_builder(
|
|||
width: i32,
|
||||
height: i32,
|
||||
difficulty: i32,
|
||||
initial_player_level: i32,
|
||||
initial_player_level: i32
|
||||
) -> BuilderChain {
|
||||
rltk::console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
|
||||
let mut chain = BuilderChain::new(new_id, width, height, difficulty, "the town", initial_player_level);
|
||||
|
|
@ -78,7 +78,7 @@ impl TownBuilder {
|
|||
building_size[2].2 = BuildingTag::Mine;
|
||||
building_size[3].2 = BuildingTag::PlayerHouse;
|
||||
for b in building_size.iter_mut().skip(4) {
|
||||
b.2 = BuildingTag::NPCHouse
|
||||
b.2 = BuildingTag::NPCHouse;
|
||||
}
|
||||
let last_idx = building_size.len() - 1;
|
||||
building_size[last_idx].2 = BuildingTag::Abandoned;
|
||||
|
|
@ -91,7 +91,7 @@ impl TownBuilder {
|
|||
rng: &mut rltk::RandomNumberGenerator,
|
||||
build_data: &mut BuilderMap,
|
||||
buildings: &[(i32, i32, i32, i32)],
|
||||
building_index: &[(usize, i32, BuildingTag)],
|
||||
building_index: &[(usize, i32, BuildingTag)]
|
||||
) {
|
||||
for (i, building) in buildings.iter().enumerate() {
|
||||
let build_tag = &building_index[i].2;
|
||||
|
|
@ -123,7 +123,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
available_building_tiles: &mut HashSet<usize>,
|
||||
available_building_tiles: &mut HashSet<usize>
|
||||
) {
|
||||
for idx in available_building_tiles.iter() {
|
||||
if rng.roll_dice(1, 40) == 1 {
|
||||
|
|
@ -161,15 +161,16 @@ impl TownBuilder {
|
|||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
to_place: &mut Vec<&str>,
|
||||
avoid_tile: usize,
|
||||
avoid_tile: usize
|
||||
) {
|
||||
for y in building.1..building.1 + building.3 {
|
||||
for x in building.0..building.0 + building.2 {
|
||||
let idx = build_data.map.xy_idx(x, y);
|
||||
if build_data.map.tiles[idx] == TileType::WoodFloor
|
||||
&& idx != avoid_tile
|
||||
&& rng.roll_dice(1, 3) == 1
|
||||
&& !to_place.is_empty()
|
||||
if
|
||||
build_data.map.tiles[idx] == TileType::WoodFloor &&
|
||||
idx != avoid_tile &&
|
||||
rng.roll_dice(1, 3) == 1 &&
|
||||
!to_place.is_empty()
|
||||
{
|
||||
let entity_tag = to_place[0];
|
||||
to_place.remove(0);
|
||||
|
|
@ -183,12 +184,14 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
// Place player
|
||||
build_data.starting_position =
|
||||
Some(Position { x: building.0 + (building.2 / 2), y: building.1 + (building.3 / 2) });
|
||||
let player_idx = build_data.map.xy_idx(building.0 + (building.2 / 2), building.1 + (building.3 / 2));
|
||||
build_data.starting_position = Some(Position {
|
||||
x: building.0 + building.2 / 2,
|
||||
y: building.1 + building.3 / 2,
|
||||
});
|
||||
let player_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
||||
|
||||
// Place other items
|
||||
let mut to_place: Vec<&str> = vec![
|
||||
|
|
@ -200,7 +203,7 @@ impl TownBuilder {
|
|||
"prop_table",
|
||||
"prop_table",
|
||||
"prop_chair",
|
||||
"prop_chair",
|
||||
"prop_chair"
|
||||
];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, player_idx);
|
||||
}
|
||||
|
|
@ -209,7 +212,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
let mut to_place: Vec<&str> = vec![
|
||||
"npc_priest",
|
||||
|
|
@ -220,7 +223,7 @@ impl TownBuilder {
|
|||
"prop_table",
|
||||
"prop_table",
|
||||
"prop_candle",
|
||||
"prop_candle",
|
||||
"prop_candle"
|
||||
];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0)
|
||||
}
|
||||
|
|
@ -229,10 +232,10 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
// Place exit
|
||||
let exit_idx = build_data.map.xy_idx(building.0 + (building.2 / 2), building.1 + (building.3 / 2));
|
||||
let exit_idx = build_data.map.xy_idx(building.0 + building.2 / 2, building.1 + building.3 / 2);
|
||||
build_data.map.tiles[exit_idx] = TileType::DownStair;
|
||||
let mut to_place: Vec<&str> = vec!["npc_miner", "npc_miner", "npc_guard", "prop_chair"];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, exit_idx)
|
||||
|
|
@ -242,7 +245,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
let mut to_place: Vec<&str> = vec!["prop_bed", "prop_table", "dog_little", "prop_chair", "prop_chair"];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||
|
|
@ -252,7 +255,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
let mut to_place: Vec<&str> = vec!["npc_townsperson", "prop_bed", "prop_table", "prop_chair"];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||
|
|
@ -262,7 +265,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
building: &(i32, i32, i32, i32),
|
||||
build_data: &mut BuilderMap,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
rng: &mut rltk::RandomNumberGenerator
|
||||
) {
|
||||
let mut to_place: Vec<&str> = vec!["rat", "rat", "rat", "prop_table", "prop_chair"];
|
||||
self.random_building_spawn(building, build_data, rng, &mut to_place, 0);
|
||||
|
|
@ -285,7 +288,7 @@ impl TownBuilder {
|
|||
let sand_width = shallow_width + 4;
|
||||
|
||||
for y in 0..build_data.height {
|
||||
let n_water = (f32::sin(n) * variance as f32) as i32 + minimum_width + rng.roll_dice(1, 2);
|
||||
let n_water = ((f32::sin(n) * (variance as f32)) as i32) + minimum_width + rng.roll_dice(1, 2);
|
||||
water_width.push(n_water);
|
||||
n += 0.1;
|
||||
for x in 0..n_water {
|
||||
|
|
@ -323,10 +326,10 @@ impl TownBuilder {
|
|||
|
||||
let start_roll = rng.roll_dice(1, 4);
|
||||
let largest_water_width;
|
||||
if water_width[y as usize] > water_width[y as usize + 1] {
|
||||
if water_width[y as usize] > water_width[(y as usize) + 1] {
|
||||
largest_water_width = water_width[y as usize];
|
||||
} else {
|
||||
largest_water_width = water_width[y as usize + 1];
|
||||
largest_water_width = water_width[(y as usize) + 1];
|
||||
}
|
||||
|
||||
// Make pier length
|
||||
|
|
@ -360,7 +363,7 @@ impl TownBuilder {
|
|||
fn town_walls(
|
||||
&mut self,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
build_data: &mut BuilderMap,
|
||||
build_data: &mut BuilderMap
|
||||
) -> (HashSet<usize>, i32) {
|
||||
let mut available_building_tiles: HashSet<usize> = HashSet::new();
|
||||
|
||||
|
|
@ -370,7 +373,7 @@ impl TownBuilder {
|
|||
const HALF_PATH_THICKNESS: i32 = 3;
|
||||
|
||||
let wall_gap_y =
|
||||
(build_data.height / 2) + rng.roll_dice(1, PATH_OFFSET_FROM_CENTRE * 2) - 1 - PATH_OFFSET_FROM_CENTRE;
|
||||
build_data.height / 2 + rng.roll_dice(1, PATH_OFFSET_FROM_CENTRE * 2) - 1 - PATH_OFFSET_FROM_CENTRE;
|
||||
|
||||
for y in BORDER..build_data.height - BORDER {
|
||||
if !(y > wall_gap_y - HALF_PATH_THICKNESS && y < wall_gap_y + HALF_PATH_THICKNESS) {
|
||||
|
|
@ -384,14 +387,19 @@ impl TownBuilder {
|
|||
let gravel_idx = build_data.map.xy_idx(x, y);
|
||||
let roll = rng.roll_dice(1, 6);
|
||||
match roll {
|
||||
1 => build_data.map.tiles[gravel_idx] = TileType::Foliage,
|
||||
2 => build_data.map.tiles[gravel_idx] = TileType::HeavyFoliage,
|
||||
1 => {
|
||||
build_data.map.tiles[gravel_idx] = TileType::Foliage;
|
||||
}
|
||||
2 => {
|
||||
build_data.map.tiles[gravel_idx] = TileType::HeavyFoliage;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if y > BORDER + 1
|
||||
&& y < build_data.height - BORDER - 1
|
||||
&& x > OFFSET_FROM_LEFT + 2
|
||||
&& x < build_data.width - BORDER - 1
|
||||
if
|
||||
y > BORDER + 1 &&
|
||||
y < build_data.height - BORDER - 1 &&
|
||||
x > OFFSET_FROM_LEFT + 2 &&
|
||||
x < build_data.width - BORDER - 1
|
||||
{
|
||||
available_building_tiles.insert(gravel_idx);
|
||||
}
|
||||
|
|
@ -420,7 +428,7 @@ impl TownBuilder {
|
|||
&mut self,
|
||||
rng: &mut rltk::RandomNumberGenerator,
|
||||
build_data: &mut BuilderMap,
|
||||
available_building_tiles: &mut HashSet<usize>,
|
||||
available_building_tiles: &mut HashSet<usize>
|
||||
) -> Vec<(i32, i32, i32, i32)> {
|
||||
let mut buildings: Vec<(i32, i32, i32, i32)> = Vec::new();
|
||||
let mut n_buildings = 0;
|
||||
|
|
@ -458,9 +466,9 @@ impl TownBuilder {
|
|||
build_data.map.tiles[idx] = TileType::WoodFloor;
|
||||
available_building_tiles.remove(&idx);
|
||||
available_building_tiles.remove(&(idx + 1));
|
||||
available_building_tiles.remove(&(idx + build_data.width as usize));
|
||||
available_building_tiles.remove(&(idx + (build_data.width as usize)));
|
||||
available_building_tiles.remove(&(idx - 1));
|
||||
available_building_tiles.remove(&(idx - build_data.width as usize));
|
||||
available_building_tiles.remove(&(idx - (build_data.width as usize)));
|
||||
}
|
||||
}
|
||||
build_data.take_snapshot();
|
||||
|
|
@ -480,10 +488,10 @@ impl TownBuilder {
|
|||
if build_data.map.tiles[idx + 1] != TileType::WoodFloor {
|
||||
neighbours += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx - build_data.width as usize] != TileType::WoodFloor {
|
||||
if build_data.map.tiles[idx - (build_data.width as usize)] != TileType::WoodFloor {
|
||||
neighbours += 1;
|
||||
}
|
||||
if build_data.map.tiles[idx + build_data.width as usize] != TileType::WoodFloor {
|
||||
if build_data.map.tiles[idx + (build_data.width as usize)] != TileType::WoodFloor {
|
||||
neighbours += 1;
|
||||
}
|
||||
if neighbours > 0 {
|
||||
|
|
@ -503,12 +511,12 @@ impl TownBuilder {
|
|||
rng: &mut rltk::RandomNumberGenerator,
|
||||
build_data: &mut BuilderMap,
|
||||
buildings: &mut Vec<(i32, i32, i32, i32)>,
|
||||
wall_gap_y: i32,
|
||||
wall_gap_y: i32
|
||||
) -> Vec<usize> {
|
||||
let mut doors = Vec::new();
|
||||
for building in buildings.iter() {
|
||||
let door_x = building.0 + 1 + rng.roll_dice(1, building.2 - 3);
|
||||
let cy = building.1 + (building.3 / 2);
|
||||
let cy = building.1 + building.3 / 2;
|
||||
let idx = if cy > wall_gap_y {
|
||||
// Door on north wall
|
||||
build_data.map.xy_idx(door_x, building.1)
|
||||
|
|
@ -529,7 +537,7 @@ impl TownBuilder {
|
|||
tiles: &[usize],
|
||||
tiletype: TileType,
|
||||
new_road_tiletype: TileType,
|
||||
include_new_tiles: bool,
|
||||
include_new_tiles: bool
|
||||
) {
|
||||
let mut roads = self.find_tiletype(build_data, tiletype);
|
||||
|
||||
|
|
@ -537,15 +545,15 @@ impl TownBuilder {
|
|||
for tile_idx in tiles.iter() {
|
||||
let mut nearest_tiletype: Vec<(usize, f32)> = Vec::new();
|
||||
let tile_pt = rltk::Point::new(
|
||||
*tile_idx as i32 % build_data.map.width as i32,
|
||||
*tile_idx as i32 / build_data.map.width as i32,
|
||||
(*tile_idx as i32) % (build_data.map.width as i32),
|
||||
(*tile_idx as i32) / (build_data.map.width as i32)
|
||||
);
|
||||
for r in roads.iter() {
|
||||
nearest_tiletype.push((
|
||||
*r,
|
||||
rltk::DistanceAlg::Manhattan.distance2d(
|
||||
tile_pt,
|
||||
rltk::Point::new(*r as i32 % build_data.map.width, *r as i32 / build_data.map.width),
|
||||
rltk::Point::new((*r as i32) % build_data.map.width, (*r as i32) / build_data.map.width)
|
||||
),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ impl VoronoiBuilder {
|
|||
let mut voronoi_distance = vec![(0, 0.0f32); self.n_seeds];
|
||||
let mut voronoi_membership: Vec<i32> = vec![0; build_data.map.width as usize * build_data.map.height as usize];
|
||||
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
|
||||
let x = i as i32 % build_data.map.width;
|
||||
let y = i as i32 / build_data.map.width;
|
||||
let x = (i as i32) % build_data.map.width;
|
||||
let y = (i as i32) / build_data.map.width;
|
||||
|
||||
for (seed, pos) in voronoi_seeds.iter().enumerate() {
|
||||
let distance;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl VoronoiSpawning {
|
|||
rng,
|
||||
area.1,
|
||||
&mut build_data.spawn_list,
|
||||
build_data.initial_player_level,
|
||||
build_data.initial_player_level
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,27 @@
|
|||
use super::{
|
||||
effects::{ add_effect, EffectType, Targets },
|
||||
gamelog, gamesystem,
|
||||
gamelog,
|
||||
gamesystem,
|
||||
gui::renderable_colour,
|
||||
ArmourClassBonus, Attributes, Blind, EquipmentSlot, Equipped, HungerClock, HungerState, MeleeWeapon, MultiAttack,
|
||||
Name, NaturalAttacks, ParticleBuilder, Pools, Position, Renderable, Skill, Skills, ToHitBonus, WantsToMelee,
|
||||
ArmourClassBonus,
|
||||
Attributes,
|
||||
Blind,
|
||||
EquipmentSlot,
|
||||
Equipped,
|
||||
HungerClock,
|
||||
HungerState,
|
||||
MeleeWeapon,
|
||||
MultiAttack,
|
||||
Name,
|
||||
NaturalAttacks,
|
||||
ParticleBuilder,
|
||||
Pools,
|
||||
Position,
|
||||
Renderable,
|
||||
Skill,
|
||||
Skills,
|
||||
ToHitBonus,
|
||||
WantsToMelee,
|
||||
WeaponAttribute,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
|
|
@ -74,9 +92,14 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
let mut logger = gamelog::Logger::new();
|
||||
let mut something_to_log = false;
|
||||
|
||||
for (entity, wants_melee, name, attacker_attributes, attacker_skills, attacker_pools) in
|
||||
(&entities, &wants_melee, &names, &attributes, &skills, &pools).join()
|
||||
{
|
||||
for (entity, wants_melee, name, attacker_attributes, attacker_skills, attacker_pools) in (
|
||||
&entities,
|
||||
&wants_melee,
|
||||
&names,
|
||||
&attributes,
|
||||
&skills,
|
||||
&pools,
|
||||
).join() {
|
||||
// Create blank vector of attacks being attempted.
|
||||
let mut attacks: Vec<(MeleeWeapon, String)> = Vec::new();
|
||||
let mut multi_attack = false;
|
||||
|
|
@ -136,7 +159,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
let mut status_hit_bonus = 0;
|
||||
if let Some(_) = blind_entities.get(entity) {
|
||||
status_hit_bonus -= 4;
|
||||
};
|
||||
}
|
||||
let hc = hunger_clock.get(entity);
|
||||
if let Some(hc) = hc {
|
||||
match hc.state {
|
||||
|
|
@ -153,12 +176,13 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
}
|
||||
}
|
||||
// Total to-hit bonus
|
||||
let attacker_bonuses = 1 // +1 for being in melee combat
|
||||
+ attacker_pools.level // + level
|
||||
+ attribute_hit_bonus // +- str/dex bonus depending on weapon used
|
||||
+ skill_hit_bonus // +- relevant skill modifier
|
||||
+ equipment_hit_bonus // +- any other to-hit modifiers from equipment
|
||||
+ status_hit_bonus; // +- any to-hit modifiers from status effects
|
||||
let attacker_bonuses =
|
||||
1 + // +1 for being in melee combat
|
||||
attacker_pools.level + // + level
|
||||
attribute_hit_bonus + // +- str/dex bonus depending on weapon used
|
||||
skill_hit_bonus + // +- relevant skill modifier
|
||||
equipment_hit_bonus + // +- any other to-hit modifiers from equipment
|
||||
status_hit_bonus; // +- any to-hit modifiers from status effects
|
||||
|
||||
// Get armour class
|
||||
let bac = target_pools.bac;
|
||||
|
|
@ -187,7 +211,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
|
||||
let target_name = names.get(wants_melee.target).unwrap();
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"ATTACKLOG: {} *{}* {}: rolled ({}) 1d20 vs. {} ({} + {}AC + {}to-hit)",
|
||||
&name.name,
|
||||
attack_verb,
|
||||
|
|
@ -197,7 +222,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
monster_v_player_bonus,
|
||||
armour_class_roll,
|
||||
attacker_bonuses
|
||||
));
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if d20 < target_number {
|
||||
|
|
@ -206,8 +232,12 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
let skill_damage_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills);
|
||||
let mut attribute_damage_bonus = weapon_info.damage_bonus;
|
||||
match weapon_info.attribute {
|
||||
WeaponAttribute::Dexterity => attribute_damage_bonus += attacker_attributes.dexterity.bonus,
|
||||
WeaponAttribute::Strength => attribute_damage_bonus += attacker_attributes.strength.bonus,
|
||||
WeaponAttribute::Dexterity => {
|
||||
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
||||
}
|
||||
WeaponAttribute::Strength => {
|
||||
attribute_damage_bonus += attacker_attributes.strength.bonus;
|
||||
}
|
||||
WeaponAttribute::Finesse => {
|
||||
if attacker_attributes.dexterity.bonus > attacker_attributes.strength.bonus {
|
||||
attribute_damage_bonus += attacker_attributes.dexterity.bonus;
|
||||
|
|
@ -219,7 +249,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
let mut damage = i32::max(0, base_damage + skill_damage_bonus + attribute_damage_bonus);
|
||||
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"ATTACKLOG: {} HIT for {} ({}[{}d{}]+{}[skill]+{}[attr])",
|
||||
&name.name,
|
||||
damage,
|
||||
|
|
@ -228,28 +259,33 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
weapon_info.damage_die_type,
|
||||
skill_damage_bonus,
|
||||
attribute_damage_bonus
|
||||
));
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if actual_armour_class < 0 {
|
||||
let ac_damage_reduction = rng.roll_dice(1, -actual_armour_class);
|
||||
damage = i32::min(1, damage - ac_damage_reduction);
|
||||
if COMBAT_LOGGING {
|
||||
rltk::console::log(format!(
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"ATTACKLOG: {} reduced their damage taken by {} (1dAC), and took {} hp damage.",
|
||||
&target_name.name, ac_damage_reduction, damage
|
||||
));
|
||||
&target_name.name,
|
||||
ac_damage_reduction,
|
||||
damage
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.damage_taken(pos.x, pos.y)
|
||||
particle_builder.damage_taken(pos.x, pos.y);
|
||||
}
|
||||
add_effect(
|
||||
Some(entity),
|
||||
EffectType::Damage { amount: damage },
|
||||
Targets::Entity { target: wants_melee.target },
|
||||
Targets::Entity { target: wants_melee.target }
|
||||
);
|
||||
if entity == *player_entity {
|
||||
something_to_log = true;
|
||||
|
|
@ -269,7 +305,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
.append(attack_verb)
|
||||
.append("you!");
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
gamelog::Logger
|
||||
::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity))
|
||||
.append(&name.name)
|
||||
|
|
@ -289,7 +326,7 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
|
||||
let pos = positions.get(wants_melee.target);
|
||||
if let Some(pos) = pos {
|
||||
particle_builder.attack_miss(pos.x, pos.y)
|
||||
particle_builder.attack_miss(pos.x, pos.y);
|
||||
}
|
||||
if entity == *player_entity {
|
||||
something_to_log = true;
|
||||
|
|
@ -304,7 +341,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
.colour(WHITE)
|
||||
.append("misses!");
|
||||
} else {
|
||||
gamelog::Logger::new() // <name> misses the <target>.
|
||||
gamelog::Logger
|
||||
::new() // <name> misses the <target>.
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity))
|
||||
.append(&name.name)
|
||||
|
|
@ -330,7 +368,7 @@ fn get_natural_attacks(
|
|||
rng: &mut rltk::RandomNumberGenerator,
|
||||
nat: NaturalAttacks,
|
||||
multi_attack: bool,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>
|
||||
) {
|
||||
if !nat.attacks.is_empty() {
|
||||
if multi_attack {
|
||||
|
|
@ -347,8 +385,11 @@ fn get_natural_attacks(
|
|||
));
|
||||
}
|
||||
} else {
|
||||
let attack_index =
|
||||
if nat.attacks.len() == 1 { 0 } else { rng.roll_dice(1, nat.attacks.len() as i32) as usize - 1 };
|
||||
let attack_index = if nat.attacks.len() == 1 {
|
||||
0
|
||||
} else {
|
||||
(rng.roll_dice(1, nat.attacks.len() as i32) as usize) - 1
|
||||
};
|
||||
attacks.push((
|
||||
MeleeWeapon {
|
||||
attribute: WeaponAttribute::Strength,
|
||||
|
|
@ -367,7 +408,7 @@ fn get_weapon_attack(
|
|||
wielded: &Equipped,
|
||||
melee: &MeleeWeapon,
|
||||
entity: Entity,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>,
|
||||
attacks: &mut Vec<(MeleeWeapon, String)>
|
||||
) -> bool {
|
||||
if wielded.owner == entity && wielded.slot == EquipmentSlot::Melee {
|
||||
attacks.push((melee.clone(), "hits".to_string()));
|
||||
|
|
|
|||
|
|
@ -69,7 +69,10 @@ fn create_delayed_particles(ecs: &mut World, ctx: &Rltk) {
|
|||
let mut renderables = ecs.write_storage::<Renderable>();
|
||||
let mut particles = ecs.write_storage::<ParticleLifetime>();
|
||||
for handled in handled_particles {
|
||||
let index = particle_builder.delayed_requests.iter().position(|x| x.particle == handled).unwrap();
|
||||
let index = particle_builder.delayed_requests
|
||||
.iter()
|
||||
.position(|x| x.particle == handled)
|
||||
.unwrap();
|
||||
particle_builder.delayed_requests.remove(index);
|
||||
let p = entities.create();
|
||||
positions.insert(p, Position { x: handled.x, y: handled.y }).expect("Could not insert position");
|
||||
|
|
@ -113,8 +116,10 @@ impl ParticleBuilder {
|
|||
}
|
||||
|
||||
pub fn delay(&mut self, x: i32, y: i32, fg: RGB, bg: RGB, glyph: rltk::FontCharType, lifetime: f32, delay: f32) {
|
||||
self.delayed_requests
|
||||
.push(DelayedParticleRequest { delay: delay, particle: ParticleRequest { x, y, fg, bg, glyph, lifetime } });
|
||||
self.delayed_requests.push(DelayedParticleRequest {
|
||||
delay: delay,
|
||||
particle: ParticleRequest { x, y, fg, bg, glyph, lifetime },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn damage_taken(&mut self, x: i32, y: i32) {
|
||||
|
|
@ -124,7 +129,7 @@ impl ParticleBuilder {
|
|||
rltk::RGB::named(rltk::ORANGE),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('‼'),
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
DEFAULT_PARTICLE_LIFETIME
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +140,7 @@ impl ParticleBuilder {
|
|||
rltk::RGB::named(rltk::CYAN),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('‼'),
|
||||
DEFAULT_PARTICLE_LIFETIME,
|
||||
DEFAULT_PARTICLE_LIFETIME
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +151,7 @@ impl ParticleBuilder {
|
|||
rltk::RGB::named(rltk::CHOCOLATE),
|
||||
rltk::RGB::named(rltk::BLACK),
|
||||
rltk::to_cp437('‼'),
|
||||
SHORT_PARTICLE_LIFETIME,
|
||||
SHORT_PARTICLE_LIFETIME
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +165,7 @@ impl ParticleBuilder {
|
|||
bg: RGB,
|
||||
glyph: rltk::FontCharType,
|
||||
lifetime: f32,
|
||||
secondary_fg: RGB,
|
||||
secondary_fg: RGB
|
||||
) {
|
||||
let eighth_l = lifetime / 8.0;
|
||||
let quarter_l = eighth_l * 2.0;
|
||||
|
|
@ -231,10 +236,12 @@ impl<'a> System<'a> for ParticleSpawnSystem {
|
|||
let p = entities.create();
|
||||
positions.insert(p, Position { x: new_particle.x, y: new_particle.y }).expect("Could not insert position");
|
||||
renderables
|
||||
.insert(
|
||||
p,
|
||||
Renderable { fg: new_particle.fg, bg: new_particle.bg, glyph: new_particle.glyph, render_order: 0 },
|
||||
)
|
||||
.insert(p, Renderable {
|
||||
fg: new_particle.fg,
|
||||
bg: new_particle.bg,
|
||||
glyph: new_particle.glyph,
|
||||
render_order: 0,
|
||||
})
|
||||
.expect("Could not insert renderables");
|
||||
particles
|
||||
.insert(p, ParticleLifetime { lifetime_ms: new_particle.lifetime })
|
||||
|
|
|
|||
156
src/player.rs
156
src/player.rs
|
|
@ -4,9 +4,31 @@ use super::{
|
|||
gui::obfuscate_name_ecs,
|
||||
gui::renderable_colour,
|
||||
raws::Reaction,
|
||||
Attributes, BlocksTile, BlocksVisibility, Door, EntityMoved, Faction, HasAncestry, Hidden, HungerClock,
|
||||
HungerState, Item, Map, Name, ParticleBuilder, Player, Pools, Position, Renderable, RunState, State, Telepath,
|
||||
TileType, Viewshed, WantsToMelee, WantsToPickupItem,
|
||||
Attributes,
|
||||
BlocksTile,
|
||||
BlocksVisibility,
|
||||
Door,
|
||||
EntityMoved,
|
||||
Faction,
|
||||
HasAncestry,
|
||||
Hidden,
|
||||
HungerClock,
|
||||
HungerState,
|
||||
Item,
|
||||
Map,
|
||||
Name,
|
||||
ParticleBuilder,
|
||||
Player,
|
||||
Pools,
|
||||
Position,
|
||||
Renderable,
|
||||
RunState,
|
||||
State,
|
||||
Telepath,
|
||||
TileType,
|
||||
Viewshed,
|
||||
WantsToMelee,
|
||||
WantsToPickupItem,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode };
|
||||
|
|
@ -35,10 +57,13 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
let delta_x = i;
|
||||
let delta_y = j;
|
||||
|
||||
if !(pos.x + delta_x < 0
|
||||
|| pos.x + delta_x > map.width - 1
|
||||
|| pos.y + delta_y < 0
|
||||
|| pos.y + delta_y > map.height - 1)
|
||||
if
|
||||
!(
|
||||
pos.x + delta_x < 0 ||
|
||||
pos.x + delta_x > map.width - 1 ||
|
||||
pos.y + delta_y < 0 ||
|
||||
pos.y + delta_y > map.height - 1
|
||||
)
|
||||
{
|
||||
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
|
||||
|
||||
|
|
@ -120,10 +145,13 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
let delta_x = i;
|
||||
let delta_y = j;
|
||||
|
||||
if !(pos.x + delta_x < 0
|
||||
|| pos.x + delta_x > map.width - 1
|
||||
|| pos.y + delta_y < 0
|
||||
|| pos.y + delta_y > map.height - 1)
|
||||
if
|
||||
!(
|
||||
pos.x + delta_x < 0 ||
|
||||
pos.x + delta_x > map.width - 1 ||
|
||||
pos.y + delta_y < 0 ||
|
||||
pos.y + delta_y > map.height - 1
|
||||
)
|
||||
{
|
||||
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
|
||||
|
||||
|
|
@ -190,10 +218,13 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
let delta_x = i;
|
||||
let delta_y = j;
|
||||
|
||||
if !(pos.x + delta_x < 0
|
||||
|| pos.x + delta_x > map.width - 1
|
||||
|| pos.y + delta_y < 0
|
||||
|| pos.y + delta_y > map.height - 1)
|
||||
if
|
||||
!(
|
||||
pos.x + delta_x < 0 ||
|
||||
pos.x + delta_x > map.width - 1 ||
|
||||
pos.y + delta_y < 0 ||
|
||||
pos.y + delta_y > map.height - 1
|
||||
)
|
||||
{
|
||||
let destination_idx = map.xy_idx(pos.x + delta_x, pos.y + delta_y);
|
||||
|
||||
|
|
@ -224,7 +255,8 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
particle_builder.kick(pos.x + delta_x, pos.y + delta_y);
|
||||
// ~33% chance of breaking it down + str
|
||||
if rng.roll_dice(1, 10) + attributes.strength.bonus > 6 {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("As you kick the")
|
||||
.item_name_n(target_name)
|
||||
.append(", it crashes open!")
|
||||
|
|
@ -235,7 +267,8 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState {
|
|||
return false;
|
||||
// 66% chance of just kicking it.
|
||||
} else {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You kick the")
|
||||
.item_name_n(target_name)
|
||||
.period()
|
||||
|
|
@ -297,10 +330,11 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
|
|||
let mut result: Option<RunState>;
|
||||
|
||||
for (entity, _player, pos, viewshed) in (&entities, &mut players, &mut positions, &mut viewsheds).join() {
|
||||
if pos.x + delta_x < 0
|
||||
|| pos.x + delta_x > map.width - 1
|
||||
|| pos.y + delta_y < 0
|
||||
|| pos.y + delta_y > map.height - 1
|
||||
if
|
||||
pos.x + delta_x < 0 ||
|
||||
pos.x + delta_x > map.width - 1 ||
|
||||
pos.y + delta_y < 0 ||
|
||||
pos.y + delta_y > map.height - 1
|
||||
{
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
|
|
@ -317,7 +351,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
|
|||
entity,
|
||||
&factions,
|
||||
&ancestries,
|
||||
&crate::raws::RAWS.lock().unwrap(),
|
||||
&crate::raws::RAWS.lock().unwrap()
|
||||
);
|
||||
if result != Reaction::Attack {
|
||||
hostile = false;
|
||||
|
|
@ -408,7 +442,8 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
|
|||
for m in swap_entities.iter() {
|
||||
if let Some(name) = names.get(m.0) {
|
||||
let renderables = ecs.read_storage::<Renderable>();
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You swap places with the")
|
||||
.colour(renderable_colour(&renderables, m.0))
|
||||
.append_n(&name.name)
|
||||
|
|
@ -459,11 +494,14 @@ fn get_item(ecs: &mut World) -> RunState {
|
|||
|
||||
pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
||||
match ctx.key {
|
||||
None => return RunState::AwaitingInput,
|
||||
Some(key) => match key {
|
||||
None => {
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
Some(key) =>
|
||||
match key {
|
||||
// Cardinals
|
||||
VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => {
|
||||
return try_move_player(-1, 0, &mut gs.ecs)
|
||||
return try_move_player(-1, 0, &mut gs.ecs);
|
||||
}
|
||||
VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L => {
|
||||
return try_move_player(1, 0, &mut gs.ecs);
|
||||
|
|
@ -475,10 +513,18 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
|||
return try_move_player(0, 1, &mut gs.ecs);
|
||||
}
|
||||
// Diagonals
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::U => return try_move_player(1, -1, &mut gs.ecs),
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => return try_move_player(-1, -1, &mut gs.ecs),
|
||||
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => return try_move_player(1, 1, &mut gs.ecs),
|
||||
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => return try_move_player(-1, 1, &mut gs.ecs),
|
||||
VirtualKeyCode::Numpad9 | VirtualKeyCode::U => {
|
||||
return try_move_player(1, -1, &mut gs.ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => {
|
||||
return try_move_player(-1, -1, &mut gs.ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => {
|
||||
return try_move_player(1, 1, &mut gs.ecs);
|
||||
}
|
||||
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => {
|
||||
return try_move_player(-1, 1, &mut gs.ecs);
|
||||
}
|
||||
// id
|
||||
VirtualKeyCode::Period => {
|
||||
if ctx.shift {
|
||||
|
|
@ -508,22 +554,38 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
|
|||
}
|
||||
|
||||
// Items
|
||||
VirtualKeyCode::C => return RunState::ActionWithDirection { function: try_door },
|
||||
VirtualKeyCode::O => return RunState::ActionWithDirection { function: open },
|
||||
VirtualKeyCode::F => return RunState::ActionWithDirection { function: kick },
|
||||
VirtualKeyCode::C => {
|
||||
return RunState::ActionWithDirection { function: try_door };
|
||||
}
|
||||
VirtualKeyCode::O => {
|
||||
return RunState::ActionWithDirection { function: open };
|
||||
}
|
||||
VirtualKeyCode::F => {
|
||||
return RunState::ActionWithDirection { function: kick };
|
||||
}
|
||||
VirtualKeyCode::G => {
|
||||
return get_item(&mut gs.ecs);
|
||||
}
|
||||
VirtualKeyCode::I => return RunState::ShowInventory,
|
||||
VirtualKeyCode::D => return RunState::ShowDropItem,
|
||||
VirtualKeyCode::R => return RunState::ShowRemoveItem,
|
||||
VirtualKeyCode::I => {
|
||||
return RunState::ShowInventory;
|
||||
}
|
||||
VirtualKeyCode::D => {
|
||||
return RunState::ShowDropItem;
|
||||
}
|
||||
VirtualKeyCode::R => {
|
||||
return RunState::ShowRemoveItem;
|
||||
}
|
||||
// Other
|
||||
VirtualKeyCode::Minus => return RunState::ShowCheatMenu,
|
||||
VirtualKeyCode::Escape => return RunState::SaveGame,
|
||||
VirtualKeyCode::Minus => {
|
||||
return RunState::ShowCheatMenu;
|
||||
}
|
||||
VirtualKeyCode::Escape => {
|
||||
return RunState::SaveGame;
|
||||
}
|
||||
_ => {
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
return RunState::AwaitingInput;
|
||||
}
|
||||
|
|
@ -573,7 +635,7 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
entity_id,
|
||||
&factions,
|
||||
&ancestries,
|
||||
&crate::raws::RAWS.lock().unwrap(),
|
||||
&crate::raws::RAWS.lock().unwrap()
|
||||
);
|
||||
if result == Reaction::Attack {
|
||||
can_heal = false;
|
||||
|
|
@ -587,9 +649,15 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
let player_hunger_clock = hunger_clocks.get(*player_entity);
|
||||
if let Some(clock) = player_hunger_clock {
|
||||
match clock.state {
|
||||
HungerState::Hungry => can_heal = false,
|
||||
HungerState::Weak => can_heal = false,
|
||||
HungerState::Fainting => can_heal = false,
|
||||
HungerState::Hungry => {
|
||||
can_heal = false;
|
||||
}
|
||||
HungerState::Weak => {
|
||||
can_heal = false;
|
||||
}
|
||||
HungerState::Fainting => {
|
||||
can_heal = false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -599,7 +667,7 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
let pools = health_components.get_mut(*player_entity).unwrap();
|
||||
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
|
||||
let roll = rng.roll_dice(1, 6);
|
||||
if (roll == 6) && pools.hit_points.current < pools.hit_points.max {
|
||||
if roll == 6 && pools.hit_points.current < pools.hit_points.max {
|
||||
pools.hit_points.current += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,6 @@ macro_rules! impl_ParseJson {
|
|||
return serde_json::from_str(&raw_string).expect("Failed to convert &str to json");
|
||||
}
|
||||
})*
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_ParseJson!(for Vec<Item>, Vec<Mob>, Vec<Prop>, Vec<SpawnTable>, Vec<LootTable>, Vec<FactionData>, Vec<AncestryData>);
|
||||
|
|
|
|||
|
|
@ -103,9 +103,16 @@ macro_rules! apply_flags {
|
|||
}
|
||||
|
||||
pub enum SpawnType {
|
||||
AtPosition { x: i32, y: i32 },
|
||||
Equipped { by: Entity },
|
||||
Carried { by: Entity },
|
||||
AtPosition {
|
||||
x: i32,
|
||||
y: i32,
|
||||
},
|
||||
Equipped {
|
||||
by: Entity,
|
||||
},
|
||||
Carried {
|
||||
by: Entity,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct RawMaster {
|
||||
|
|
@ -164,27 +171,24 @@ impl RawMaster {
|
|||
self.table_index.insert(table.id.clone(), i);
|
||||
used_names.insert(table.id.clone());
|
||||
for entry in table.table.iter() {
|
||||
check_for_unspecified_entity(&used_names, &entry.id)
|
||||
check_for_unspecified_entity(&used_names, &entry.id);
|
||||
}
|
||||
}
|
||||
for (i, loot_table) in self.raws.loot_tables.iter().enumerate() {
|
||||
check_for_duplicate_entries(&used_names, &loot_table.id);
|
||||
self.loot_index.insert(loot_table.id.clone(), i);
|
||||
for entry in loot_table.table.iter() {
|
||||
check_for_unspecified_entity(&used_names, &entry.id)
|
||||
check_for_unspecified_entity(&used_names, &entry.id);
|
||||
}
|
||||
}
|
||||
for faction in self.raws.factions.iter() {
|
||||
let mut reactions: HashMap<String, Reaction> = HashMap::new();
|
||||
for other in faction.responses.iter() {
|
||||
reactions.insert(
|
||||
other.0.clone(),
|
||||
match other.1.as_str() {
|
||||
reactions.insert(other.0.clone(), match other.1.as_str() {
|
||||
"flee" => Reaction::Flee,
|
||||
"attack" => Reaction::Attack,
|
||||
_ => Reaction::Ignore,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
self.faction_index.insert(faction.id.clone(), reactions);
|
||||
}
|
||||
|
|
@ -213,7 +217,7 @@ pub fn spawn_named_entity(
|
|||
key: &str,
|
||||
buc: Option<BUC>,
|
||||
pos: SpawnType,
|
||||
map_difficulty: i32,
|
||||
map_difficulty: i32
|
||||
) -> Option<Entity> {
|
||||
if raws.item_index.contains_key(key) {
|
||||
return spawn_named_item(raws, ecs, key, buc, pos);
|
||||
|
|
@ -230,7 +234,7 @@ pub fn spawn_named_item(
|
|||
ecs: &mut World,
|
||||
key: &str,
|
||||
buc: Option<BUC>,
|
||||
pos: SpawnType,
|
||||
pos: SpawnType
|
||||
) -> Option<Entity> {
|
||||
if raws.item_index.contains_key(key) {
|
||||
let item_template = &raws.raws.items[raws.item_index[key]];
|
||||
|
|
@ -245,18 +249,10 @@ pub fn spawn_named_item(
|
|||
let player_entity = ecs.fetch::<Entity>();
|
||||
let known_beatitude = match pos {
|
||||
SpawnType::Equipped { by } => {
|
||||
if by == *player_entity {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if by == *player_entity { true } else { false }
|
||||
}
|
||||
SpawnType::Carried { by } => {
|
||||
if by == *player_entity {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if by == *player_entity { true } else { false }
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
|
@ -310,25 +306,25 @@ pub fn spawn_named_item(
|
|||
let singular = scroll_names[&item_template.name.name].clone();
|
||||
let mut plural = singular.clone();
|
||||
plural += "s";
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural })
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural });
|
||||
}
|
||||
"potion" => {
|
||||
let singular = potion_names[&item_template.name.name].clone();
|
||||
let mut plural = singular.clone();
|
||||
plural += "s";
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural })
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural });
|
||||
}
|
||||
"wand" => {
|
||||
let singular = wand_names[&item_template.name.name].clone();
|
||||
let mut plural = singular.clone();
|
||||
plural += "s";
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural })
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural });
|
||||
}
|
||||
_ => {
|
||||
let singular = magic_item.naming.clone();
|
||||
let mut plural = singular.clone();
|
||||
plural += "s";
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural })
|
||||
eb = eb.with(ObfuscatedName { name: singular, plural: plural });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -362,7 +358,7 @@ pub fn spawn_named_mob(
|
|||
ecs: &mut World,
|
||||
key: &str,
|
||||
pos: SpawnType,
|
||||
map_difficulty: i32,
|
||||
map_difficulty: i32
|
||||
) -> Option<Entity> {
|
||||
if raws.mob_index.contains_key(key) {
|
||||
let mob_template = &raws.raws.mobs[raws.mob_index[key]];
|
||||
|
|
@ -462,7 +458,7 @@ pub fn spawn_named_mob(
|
|||
mob_level += (player_level - base_mob_level) / 4;
|
||||
}
|
||||
// If the resulting mob level is more than 1.5x the base, lower it to that number
|
||||
mob_level = i32::min(mob_level, (1.5 * base_mob_level as f32).trunc() as i32);
|
||||
mob_level = i32::min(mob_level, (1.5 * (base_mob_level as f32)).trunc() as i32);
|
||||
|
||||
// Should really use existing RNG here
|
||||
let mut rng = rltk::RandomNumberGenerator::new();
|
||||
|
|
@ -549,10 +545,20 @@ pub fn spawn_named_mob(
|
|||
}
|
||||
|
||||
if LOG_SPAWNING {
|
||||
rltk::console::log(format!(
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"SPAWNLOG: {} ({}HP, {}MANA, {}BAC) spawned at level {} ({}[base], {}[map difficulty], {}[player level]), worth {} XP",
|
||||
&mob_template.name, mob_hp, mob_mana, mob_bac, mob_level, base_mob_level, map_difficulty, player_level, xp_value
|
||||
));
|
||||
&mob_template.name,
|
||||
mob_hp,
|
||||
mob_mana,
|
||||
mob_bac,
|
||||
mob_level,
|
||||
base_mob_level,
|
||||
map_difficulty,
|
||||
player_level,
|
||||
xp_value
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let new_mob = eb.build();
|
||||
|
|
@ -605,11 +611,15 @@ fn spawn_position<'a>(pos: SpawnType, new_entity: EntityBuilder<'a>, tag: &str,
|
|||
let mut eb = new_entity;
|
||||
|
||||
match pos {
|
||||
SpawnType::AtPosition { x, y } => eb = eb.with(Position { x, y }),
|
||||
SpawnType::Carried { by } => eb = eb.with(InBackpack { owner: by }),
|
||||
SpawnType::AtPosition { x, y } => {
|
||||
eb = eb.with(Position { x, y });
|
||||
}
|
||||
SpawnType::Carried { by } => {
|
||||
eb = eb.with(InBackpack { owner: by });
|
||||
}
|
||||
SpawnType::Equipped { by } => {
|
||||
let slot = find_slot_for_equippable_item(tag, raws);
|
||||
eb = eb.with(Equipped { owner: by, slot })
|
||||
eb = eb.with(Equipped { owner: by, slot });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -641,8 +651,7 @@ pub fn table_by_name(raws: &RawMaster, key: &str, optional_difficulty: Option<i3
|
|||
|
||||
use super::SpawnTableEntry;
|
||||
|
||||
let available_options: Vec<&SpawnTableEntry> = spawn_table
|
||||
.table
|
||||
let available_options: Vec<&SpawnTableEntry> = spawn_table.table
|
||||
.iter()
|
||||
.filter(|entry| entry.difficulty >= lower_bound && entry.difficulty <= upper_bound)
|
||||
.collect();
|
||||
|
|
@ -656,10 +665,15 @@ pub fn table_by_name(raws: &RawMaster, key: &str, optional_difficulty: Option<i3
|
|||
return rt;
|
||||
}
|
||||
}
|
||||
rltk::console::log(format!(
|
||||
rltk::console::log(
|
||||
format!(
|
||||
"DEBUGINFO: Something went wrong when trying to spawn {} @ map difficulty {} [upper bound: {}, lower bound: {}]. Returned debug entry.",
|
||||
key, difficulty, upper_bound, lower_bound
|
||||
));
|
||||
key,
|
||||
difficulty,
|
||||
upper_bound,
|
||||
lower_bound
|
||||
)
|
||||
);
|
||||
return RandomTable::new().add("debug", 1);
|
||||
}
|
||||
|
||||
|
|
@ -693,14 +707,30 @@ fn find_slot_for_equippable_item(tag: &str, raws: &RawMaster) -> EquipmentSlot {
|
|||
if let Some(flags) = &item.flags {
|
||||
for flag in flags {
|
||||
match flag.as_str() {
|
||||
"EQUIP_MELEE" => return EquipmentSlot::Melee,
|
||||
"EQUIP_SHIELD" => return EquipmentSlot::Shield,
|
||||
"EQUIP_BODY" => return EquipmentSlot::Body,
|
||||
"EQUIP_HEAD" => return EquipmentSlot::Head,
|
||||
"EQUIP_FEET" => return EquipmentSlot::Feet,
|
||||
"EQUIP_NECK" => return EquipmentSlot::Neck,
|
||||
"EQUIP_BACK" => return EquipmentSlot::Back,
|
||||
"EQUIP_HANDS" => return EquipmentSlot::Hands,
|
||||
"EQUIP_MELEE" => {
|
||||
return EquipmentSlot::Melee;
|
||||
}
|
||||
"EQUIP_SHIELD" => {
|
||||
return EquipmentSlot::Shield;
|
||||
}
|
||||
"EQUIP_BODY" => {
|
||||
return EquipmentSlot::Body;
|
||||
}
|
||||
"EQUIP_HEAD" => {
|
||||
return EquipmentSlot::Head;
|
||||
}
|
||||
"EQUIP_FEET" => {
|
||||
return EquipmentSlot::Feet;
|
||||
}
|
||||
"EQUIP_NECK" => {
|
||||
return EquipmentSlot::Neck;
|
||||
}
|
||||
"EQUIP_BACK" => {
|
||||
return EquipmentSlot::Back;
|
||||
}
|
||||
"EQUIP_HANDS" => {
|
||||
return EquipmentSlot::Hands;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -745,8 +775,12 @@ pub fn get_mob_spawn_type(raws: &RawMaster, key: &str) -> SpawnsAs {
|
|||
if let Some(flags) = &mob_template.flags {
|
||||
for flag in flags {
|
||||
match flag.as_str() {
|
||||
"SMALL_GROUP" => return SpawnsAs::SmallGroup,
|
||||
"LARGE_GROUP" => return SpawnsAs::LargeGroup,
|
||||
"SMALL_GROUP" => {
|
||||
return SpawnsAs::SmallGroup;
|
||||
}
|
||||
"LARGE_GROUP" => {
|
||||
return SpawnsAs::LargeGroup;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -761,29 +795,27 @@ pub fn get_mob_spawn_amount(rng: &mut RandomNumberGenerator, spawn_type: &Spawns
|
|||
SpawnsAs::Single => 1,
|
||||
// Small groups either spawn alone or as a small group (2-4).
|
||||
SpawnsAs::SmallGroup => {
|
||||
if rng.roll_dice(1, 2) == 1 {
|
||||
1
|
||||
} else {
|
||||
4
|
||||
}
|
||||
if rng.roll_dice(1, 2) == 1 { 1 } else { 4 }
|
||||
}
|
||||
// Large groups either spawn in a small group or as a large group (2-11).
|
||||
SpawnsAs::LargeGroup => {
|
||||
if rng.roll_dice(1, 2) == 1 {
|
||||
4
|
||||
} else {
|
||||
11
|
||||
}
|
||||
if rng.roll_dice(1, 2) == 1 { 4 } else { 11 }
|
||||
}
|
||||
};
|
||||
let roll = if n == 1 { 1 } else { rng.roll_dice(2, n) };
|
||||
// We want to constrain group sizes depending on player's level, so
|
||||
// we don't get large groups of mobs when the player is unequipped.
|
||||
match player_level {
|
||||
0..=2 => return i32::max(1, roll / 4),
|
||||
3..=4 => return i32::max(1, roll / 2),
|
||||
_ => return roll,
|
||||
};
|
||||
0..=2 => {
|
||||
return i32::max(1, roll / 4);
|
||||
}
|
||||
3..=4 => {
|
||||
return i32::max(1, roll / 2);
|
||||
}
|
||||
_ => {
|
||||
return roll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_scroll_tags() -> Vec<String> {
|
||||
|
|
@ -879,7 +911,7 @@ pub fn get_reactions(
|
|||
other_entity: Entity,
|
||||
factions: &ReadStorage<Faction>,
|
||||
ancestries: &ReadStorage<HasAncestry>,
|
||||
raws: &RawMaster,
|
||||
raws: &RawMaster
|
||||
) -> Reaction {
|
||||
if let Some(this_ancestry) = ancestries.get(this_entity) {
|
||||
if let Some(other_ancestry) = ancestries.get(other_entity) {
|
||||
|
|
@ -899,12 +931,24 @@ pub fn get_reactions(
|
|||
|
||||
fn get_ancestry_string(ancestry: Ancestry) -> &'static str {
|
||||
match ancestry {
|
||||
Ancestry::Human => return "human",
|
||||
Ancestry::Elf => return "elf",
|
||||
Ancestry::Dwarf => return "dwarf",
|
||||
Ancestry::Catfolk => return "catfolk",
|
||||
Ancestry::Gnome => return "gnome",
|
||||
Ancestry::NULL => return "NULL",
|
||||
Ancestry::Human => {
|
||||
return "human";
|
||||
}
|
||||
Ancestry::Elf => {
|
||||
return "elf";
|
||||
}
|
||||
Ancestry::Dwarf => {
|
||||
return "dwarf";
|
||||
}
|
||||
Ancestry::Catfolk => {
|
||||
return "catfolk";
|
||||
}
|
||||
Ancestry::Gnome => {
|
||||
return "gnome";
|
||||
}
|
||||
Ancestry::NULL => {
|
||||
return "NULL";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,11 @@ pub fn save_game(ecs: &mut World) {
|
|||
// Create helper
|
||||
let mapcopy = ecs.get_mut::<super::map::Map>().unwrap().clone();
|
||||
let dungeon_master = ecs.get_mut::<super::map::MasterDungeonMap>().unwrap().clone();
|
||||
let savehelper =
|
||||
ecs.create_entity().with(SerializationHelper { map: mapcopy }).marked::<SimpleMarker<SerializeMe>>().build();
|
||||
let savehelper = ecs
|
||||
.create_entity()
|
||||
.with(SerializationHelper { map: mapcopy })
|
||||
.marked::<SimpleMarker<SerializeMe>>()
|
||||
.build();
|
||||
let savehelper2 = ecs
|
||||
.create_entity()
|
||||
.with(DMSerializationHelper {
|
||||
|
|
|
|||
|
|
@ -94,10 +94,7 @@ pub fn is_blocked(idx: usize) -> bool {
|
|||
}
|
||||
|
||||
/// Calls a function on every entity within a given tile idx.
|
||||
pub fn for_each_tile_content<F>(idx: usize, mut f: F)
|
||||
where
|
||||
F: FnMut(Entity),
|
||||
{
|
||||
pub fn for_each_tile_content<F>(idx: usize, mut f: F) where F: FnMut(Entity) {
|
||||
let lock = SPATIAL_MAP.lock().unwrap();
|
||||
for entity in lock.tile_content[idx].iter() {
|
||||
f(entity.0);
|
||||
|
|
@ -107,8 +104,7 @@ where
|
|||
/// Calls a function on every entity within a given tile idx, with the
|
||||
/// added ability to return a RunState mid-calc.
|
||||
pub fn for_each_tile_content_with_runstate<F>(idx: usize, mut f: F) -> Option<RunState>
|
||||
where
|
||||
F: FnMut(Entity) -> Option<RunState>,
|
||||
where F: FnMut(Entity) -> Option<RunState>
|
||||
{
|
||||
let lock = SPATIAL_MAP.lock().unwrap();
|
||||
for entity in lock.tile_content[idx].iter() {
|
||||
|
|
@ -121,10 +117,7 @@ where
|
|||
|
||||
/// Calls a function on every entity within a given tile idx, breaking if
|
||||
/// the closure ever returns false.
|
||||
pub fn for_each_tile_content_with_bool<F>(idx: usize, mut f: F)
|
||||
where
|
||||
F: FnMut(Entity) -> bool,
|
||||
{
|
||||
pub fn for_each_tile_content_with_bool<F>(idx: usize, mut f: F) where F: FnMut(Entity) -> bool {
|
||||
let lock = SPATIAL_MAP.lock().unwrap();
|
||||
for entity in lock.tile_content[idx].iter() {
|
||||
if !f(entity.0) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,28 @@
|
|||
use super::{
|
||||
random_table::RandomTable, raws, Attribute, Attributes, Clock, Energy, EquipmentChanged, Faction, HungerClock,
|
||||
HungerState, Map, Mind, Name, Player, Pool, Pools, Position, Rect, Renderable, SerializeMe, Skill, Skills,
|
||||
TileType, Viewshed,
|
||||
random_table::RandomTable,
|
||||
raws,
|
||||
Attribute,
|
||||
Attributes,
|
||||
Clock,
|
||||
Energy,
|
||||
EquipmentChanged,
|
||||
Faction,
|
||||
HungerClock,
|
||||
HungerState,
|
||||
Map,
|
||||
Mind,
|
||||
Name,
|
||||
Player,
|
||||
Pool,
|
||||
Pools,
|
||||
Position,
|
||||
Rect,
|
||||
Renderable,
|
||||
SerializeMe,
|
||||
Skill,
|
||||
Skills,
|
||||
TileType,
|
||||
Viewshed,
|
||||
};
|
||||
use crate::config::entity;
|
||||
use crate::gamesystem::*;
|
||||
|
|
@ -68,7 +89,7 @@ pub fn spawn_room(
|
|||
rng: &mut RandomNumberGenerator,
|
||||
room: &Rect,
|
||||
spawn_list: &mut Vec<(usize, String)>,
|
||||
player_level: i32,
|
||||
player_level: i32
|
||||
) {
|
||||
let mut possible_targets: Vec<usize> = Vec::new();
|
||||
{
|
||||
|
|
@ -91,7 +112,7 @@ pub fn spawn_region(
|
|||
rng: &mut RandomNumberGenerator,
|
||||
area: &[usize],
|
||||
spawn_list: &mut Vec<(usize, String)>,
|
||||
player_level: i32,
|
||||
player_level: i32
|
||||
) {
|
||||
let mut spawn_points: HashMap<usize, String> = HashMap::new();
|
||||
let mut areas: Vec<usize> = Vec::from(area);
|
||||
|
|
@ -143,13 +164,16 @@ fn entity_to_spawn_list(
|
|||
rng: &mut RandomNumberGenerator,
|
||||
possible_areas: &mut Vec<usize>,
|
||||
key: String,
|
||||
spawn_points: &mut HashMap<usize, String>,
|
||||
spawn_points: &mut HashMap<usize, String>
|
||||
) {
|
||||
if possible_areas.len() == 0 {
|
||||
return;
|
||||
}
|
||||
let array_idx =
|
||||
if possible_areas.len() == 1 { 0usize } else { (rng.roll_dice(1, possible_areas.len() as i32) - 1) as usize };
|
||||
let array_idx = if possible_areas.len() == 1 {
|
||||
0usize
|
||||
} else {
|
||||
(rng.roll_dice(1, possible_areas.len() as i32) - 1) as usize
|
||||
};
|
||||
let map_idx = possible_areas[array_idx];
|
||||
spawn_points.insert(map_idx, key);
|
||||
possible_areas.remove(array_idx);
|
||||
|
|
@ -170,7 +194,7 @@ pub fn spawn_entity(ecs: &mut World, spawn: &(&usize, &String)) {
|
|||
&spawn.1,
|
||||
None,
|
||||
raws::SpawnType::AtPosition { x, y },
|
||||
map_difficulty,
|
||||
map_difficulty
|
||||
);
|
||||
if spawn_result.is_some() {
|
||||
return;
|
||||
|
|
@ -191,12 +215,24 @@ fn debug_table() -> RandomTable {
|
|||
fn get_random_item_category(rng: &mut RandomNumberGenerator, difficulty: Option<i32>) -> RandomTable {
|
||||
let item_category = item_category_table().roll(rng);
|
||||
match item_category.as_ref() {
|
||||
"equipment" => return equipment_table(difficulty),
|
||||
"food" => return food_table(difficulty),
|
||||
"potion" => return potion_table(difficulty),
|
||||
"scroll" => return scroll_table(difficulty),
|
||||
"wand" => return wand_table(difficulty),
|
||||
_ => return debug_table(),
|
||||
"equipment" => {
|
||||
return equipment_table(difficulty);
|
||||
}
|
||||
"food" => {
|
||||
return food_table(difficulty);
|
||||
}
|
||||
"potion" => {
|
||||
return potion_table(difficulty);
|
||||
}
|
||||
"scroll" => {
|
||||
return scroll_table(difficulty);
|
||||
}
|
||||
"wand" => {
|
||||
return wand_table(difficulty);
|
||||
}
|
||||
_ => {
|
||||
return debug_table();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ use super::{
|
|||
effects::{ add_effect, aoe_tiles, EffectType, Targets },
|
||||
gamelog,
|
||||
gui::renderable_colour,
|
||||
EntityMoved, EntryTrigger, Map, Name, Point, Position, Renderable, AOE,
|
||||
EntityMoved,
|
||||
EntryTrigger,
|
||||
Map,
|
||||
Name,
|
||||
Point,
|
||||
Position,
|
||||
Renderable,
|
||||
AOE,
|
||||
};
|
||||
use rltk::prelude::*;
|
||||
use specs::prelude::*;
|
||||
|
|
@ -34,7 +41,8 @@ impl<'a> System<'a> for TriggerSystem {
|
|||
Some(_trigger) => {
|
||||
if map.visible_tiles[idx] == true {
|
||||
if let Some(name) = names.get(entity_id) {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("The")
|
||||
.colour(renderable_colour(&renderables, entity_id))
|
||||
.append(&name.name)
|
||||
|
|
@ -43,17 +51,15 @@ impl<'a> System<'a> for TriggerSystem {
|
|||
.log();
|
||||
}
|
||||
}
|
||||
add_effect(
|
||||
Some(entity_id),
|
||||
EffectType::TriggerFire { trigger: entity_id },
|
||||
if let Some(aoe) = aoes.get(entity_id) {
|
||||
add_effect(Some(entity_id), EffectType::TriggerFire { trigger: entity_id }, if
|
||||
let Some(aoe) = aoes.get(entity_id)
|
||||
{
|
||||
Targets::TileList {
|
||||
targets: aoe_tiles(&*map, Point::new(pos.x, pos.y), aoe.radius),
|
||||
}
|
||||
} else {
|
||||
Targets::Tile { target: idx }
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
let origin = Point::new(pos.x, pos.y);
|
||||
viewshed.visible_tiles = SymmetricShadowcasting.field_of_view(origin, range, &*map);
|
||||
viewshed.visible_tiles.retain(|p| {
|
||||
p.x >= 0
|
||||
&& p.x < map.width
|
||||
&& p.y >= 0
|
||||
&& p.y < map.height
|
||||
&& (map.lit_tiles[map.xy_idx(p.x, p.y)] == true
|
||||
|| rltk::DistanceAlg::Pythagoras.distance2d(Point::new(p.x, p.y), origin) < 1.5)
|
||||
p.x >= 0 &&
|
||||
p.x < map.width &&
|
||||
p.y >= 0 &&
|
||||
p.y < map.height &&
|
||||
(map.lit_tiles[map.xy_idx(p.x, p.y)] == true ||
|
||||
rltk::DistanceAlg::Pythagoras.distance2d(Point::new(p.x, p.y), origin) < 1.5)
|
||||
});
|
||||
|
||||
// If this is the player, reveal what they can see
|
||||
|
|
@ -75,7 +75,8 @@ impl<'a> System<'a> for VisibilitySystem {
|
|||
if rng.roll_dice(1, 12) == 1 {
|
||||
let name = names.get(e);
|
||||
if let Some(name) = name {
|
||||
gamelog::Logger::new()
|
||||
gamelog::Logger
|
||||
::new()
|
||||
.append("You spot a")
|
||||
.item_name_n(&name.name)
|
||||
.period()
|
||||
|
|
@ -121,11 +122,11 @@ pub fn fast_fov(p_x: i32, p_y: i32, r: i32) -> Vec<Point> {
|
|||
|
||||
let mut i = 0;
|
||||
while i <= 360 {
|
||||
let x: f32 = f32::cos(i as f32 * 0.01745 as f32);
|
||||
let y: f32 = f32::sin(i as f32 * 0.01745 as f32);
|
||||
let x: f32 = f32::cos((i as f32) * (0.01745 as f32));
|
||||
let y: f32 = f32::sin((i as f32) * (0.01745 as f32));
|
||||
|
||||
let mut ox: f32 = p_x as f32 + 0.5 as f32;
|
||||
let mut oy: f32 = p_y as f32 + 0.5 as f32;
|
||||
let mut ox: f32 = (p_x as f32) + (0.5 as f32);
|
||||
let mut oy: f32 = (p_y as f32) + (0.5 as f32);
|
||||
for _i in 0..r {
|
||||
visible_tiles.push(Point::new(ox as i32, oy as i32));
|
||||
ox += x;
|
||||
|
|
|
|||
|
|
@ -316,16 +316,22 @@ function __wbg_get_imports() {
|
|||
const ret = typeof (v) === 'boolean' ? (v ? 1 : 0) : 2;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_randomFillSync_bf67eeddb65b346b = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
imports.wbg.__wbg_randomFillSync_bf67eeddb65b346b = function () {
|
||||
return handleError(function (arg0, arg1, arg2) {
|
||||
getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getRandomValues_f6c9b08ef5448767 = function() { return handleError(function (arg0, arg1) {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_getRandomValues_f6c9b08ef5448767 = function () {
|
||||
return handleError(function (arg0, arg1) {
|
||||
getObject(arg0).getRandomValues(getObject(arg1));
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_self_1c2814d86e6e51e3 = function() { return handleError(function () {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_self_1c2814d86e6e51e3 = function () {
|
||||
return handleError(function () {
|
||||
const ret = self.self;
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_crypto_70532d614bc7e028 = function (arg0) {
|
||||
const ret = getObject(arg0).crypto;
|
||||
return addHeapObject(ret);
|
||||
|
|
@ -342,10 +348,12 @@ function __wbg_get_imports() {
|
|||
const ret = module;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_require_9ace3ae680954e98 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
imports.wbg.__wbg_require_9ace3ae680954e98 = function () {
|
||||
return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_instanceof_WebGl2RenderingContext_f921526c513bf717 = function (arg0) {
|
||||
let result;
|
||||
try {
|
||||
|
|
@ -366,9 +374,11 @@ function __wbg_get_imports() {
|
|||
const ret = getObject(arg0).createVertexArray();
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_texImage2D_07240affd06971e9 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
|
||||
imports.wbg.__wbg_texImage2D_07240affd06971e9 = function () {
|
||||
return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
|
||||
getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9));
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_attachShader_47256b6b3d42a22e = function (arg0, arg1, arg2) {
|
||||
getObject(arg0).attachShader(getObject(arg1), getObject(arg2));
|
||||
};
|
||||
|
|
@ -435,10 +445,12 @@ function __wbg_get_imports() {
|
|||
const ret = getObject(arg0).getError();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_getExtension_77909f6d51d49d4d = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
imports.wbg.__wbg_getExtension_77909f6d51d49d4d = function () {
|
||||
return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = getObject(arg0).getExtension(getStringFromWasm0(arg1, arg2));
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_getProgramInfoLog_b81bc53188e286fa = function (arg0, arg1, arg2) {
|
||||
const ret = getObject(arg1).getProgramInfoLog(getObject(arg2));
|
||||
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
|
|
@ -506,10 +518,12 @@ function __wbg_get_imports() {
|
|||
imports.wbg.__wbg_setheight_a747d440760fe5aa = function (arg0, arg1) {
|
||||
getObject(arg0).height = arg1 >>> 0;
|
||||
};
|
||||
imports.wbg.__wbg_getContext_7c5944ea807bf5d3 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
imports.wbg.__wbg_getContext_7c5944ea807bf5d3 = function () {
|
||||
return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = getObject(arg0).getContext(getStringFromWasm0(arg1, arg2));
|
||||
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_offsetX_5a58f16f6c3a41b6 = function (arg0) {
|
||||
const ret = getObject(arg0).offsetX;
|
||||
return ret;
|
||||
|
|
@ -565,10 +579,12 @@ function __wbg_get_imports() {
|
|||
imports.wbg.__wbg_setonkeyup_0dfb23e81d0afdde = function (arg0, arg1) {
|
||||
getObject(arg0).onkeyup = getObject(arg1);
|
||||
};
|
||||
imports.wbg.__wbg_requestAnimationFrame_d082200514b6674d = function() { return handleError(function (arg0, arg1) {
|
||||
imports.wbg.__wbg_requestAnimationFrame_d082200514b6674d = function () {
|
||||
return handleError(function (arg0, arg1) {
|
||||
const ret = getObject(arg0).requestAnimationFrame(getObject(arg1));
|
||||
return ret;
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_setonmousedown_4f38d9c057bbfcbd = function (arg0, arg1) {
|
||||
getObject(arg0).onmousedown = getObject(arg1);
|
||||
};
|
||||
|
|
@ -581,9 +597,11 @@ function __wbg_get_imports() {
|
|||
imports.wbg.__wbg_bufferData_a11a9f65f31e7256 = function (arg0, arg1, arg2, arg3) {
|
||||
getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0);
|
||||
};
|
||||
imports.wbg.__wbg_texImage2D_6175916e58c59bc7 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
|
||||
imports.wbg.__wbg_texImage2D_6175916e58c59bc7 = function () {
|
||||
return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) {
|
||||
getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9));
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_attachShader_b65b695055670cb5 = function (arg0, arg1, arg2) {
|
||||
getObject(arg0).attachShader(getObject(arg1), getObject(arg2));
|
||||
};
|
||||
|
|
@ -708,30 +726,42 @@ function __wbg_get_imports() {
|
|||
const ret = new Function(getStringFromWasm0(arg0, arg1));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) {
|
||||
imports.wbg.__wbg_get_97b561fb56f034b5 = function () {
|
||||
return handleError(function (arg0, arg1) {
|
||||
const ret = Reflect.get(getObject(arg0), getObject(arg1));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_call_cb65541d95d71282 = function () {
|
||||
return handleError(function (arg0, arg1) {
|
||||
const ret = getObject(arg0).call(getObject(arg1));
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_self_1ff1d729e9aae938 = function () {
|
||||
return handleError(function () {
|
||||
const ret = self.self;
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_window_5f4faef6c12b79ec = function () {
|
||||
return handleError(function () {
|
||||
const ret = window.window;
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_globalThis_1d39714405582d3c = function () {
|
||||
return handleError(function () {
|
||||
const ret = globalThis.globalThis;
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () {
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_global_651f05c6a0944d1c = function () {
|
||||
return handleError(function () {
|
||||
const ret = global.global;
|
||||
return addHeapObject(ret);
|
||||
}, arguments) };
|
||||
}, arguments)
|
||||
};
|
||||
imports.wbg.__wbg_now_9c5990bda04c7e53 = function () {
|
||||
const ret = Date.now();
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue