diff --git a/.github/workflows/cargo-build-test.yml b/.github/workflows/cargo-build-test.yml
index d54fa2f..cafaa58 100644
--- a/.github/workflows/cargo-build-test.yml
+++ b/.github/workflows/cargo-build-test.yml
@@ -12,7 +12,7 @@ env:
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
diff --git a/Cargo.toml b/Cargo.toml
index 2febef8..55d7645 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,12 +1,11 @@
[package]
name = "rust-rl"
-version = "0.1.1"
+version = "0.1.4"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rltk = { version = "^0.8.7", features = ["serde"] }
bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git", rev = "851f6f08675444fb6fa088b9e67bee9fd75554c6", features = ["serde"] }
regex = "1.3.6"
specs = { version = "0.16.1", features = ["serde"] }
diff --git a/README.md b/README.md
index 116179a..c1809cf 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,19 @@
-## a roguelike in rust, playable @ [llywelwyn.github.io](https://llywelwyn.github.io/)
+## a roguelike in rust, playable @ [llyw.co.uk/rl/](https://llyw.co.uk/rl/)
#### using _rltk/bracket-lib_, and _specs_
-check out the page in the header for the wasm version, pick [a release of your choice](https://github.com/Llywelwyn/rust-rl/releases), or build manually with:
+[](https://github.com/Llywelwyn/rust-rl/actions/workflows/cargo-build-test.yml)
+
+check out the page in the header for the wasm version, pick [a release](https://github.com/Llywelwyn/rust-rl/releases), or build manually with:
`git clone https://github.com/Llywelwyn/rust-rl/ && cd rust-rl && cargo build --release`,

-this year for roguelikedev does the complete tutorial, i followed along with thebracket's [_roguelike tutorial - in rust_](https://bfnightly.bracketproductions.com). the notes i made during the sprint are being kept below for posterity - further changes since then are noted in [changelog.txt](https://github.com/Llywelwyn/rust-rl/blob/9150ed39e45bee536060cdc769d274e639021012/changelog.txt), and in the release notes.
-
---
+
+ boring details about the sprint where this project started
week 1
@@ -155,3 +157,4 @@ this year for roguelikedev does the complete tutorial, i followed along with the

+
diff --git a/benches/systems_benchmark.rs b/benches/systems_benchmark.rs
index b2acdbc..c750fed 100644
--- a/benches/systems_benchmark.rs
+++ b/benches/systems_benchmark.rs
@@ -1,5 +1,5 @@
use criterion::{ black_box, criterion_group, criterion_main, Criterion };
-use rltk::RGB;
+use bracket_lib::prelude::*;
/// Benchmarks methods from rltk used to desaturate non-visible tiles.
// Greyscale is significantly faster, but generally looks worse - the
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000..4976351
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,20 @@
+## v0.1.4
+### added
+- **overmap**: bare, but exists. player now starts on the overworld, and can move to local maps (like the old starting town) via >. can leave local maps back to the overmap by walking out of the map boundaries.
+- **intrinsics**: speed, regeneration
+- **damage types**: immunities, weaknesses, and resistances
+- **full keyboard support**: examining and targeting can now be done via keyboard only
+- **a config file** read at runtime, unfortunately not compatible with WASM builds yet
+- **morgue files**: y/n prompt to write a morgue file on death to /morgue/foo.txt, or to the console for WASM builds
+- **dungeon features**: just the basics so far. a grassy, forested treant room, some barracks, etc.
+- **named maps**: "Town", "Dungeon"
+- **map messages/hints**: "You hear <...>."
+### changed
+- **colour offsets** are now per-tile (and per-theme) instead of +-% globally. i.e. varying fg/bg offset on a per-tiletype basis
+- **chatlog colours** are now consistent
+### fixed
+- negative starting mana
+- status effects only ticking if mob turn aligned with turnclock turn
+- map params not being saved on map transition
+- mob turns not awaiting the particle queue (mobs moving around mid-animation)
+- mobs not re-pathing if their path was blocked, causing traffic jams
diff --git a/changelog.txt b/changelog.txt
deleted file mode 100644
index 3f8a6e2..0000000
--- a/changelog.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-2-September-2023
-- fixes:
- - negative starting mana
- - confusion/status effects only being run if mob turn aligned with turnclock turn
-
-30-August-2023
-- added dungeon features: grassy forest room, and barracks variants (bunks, squads of mobtypes)
-- added support for map messages: i.e. notifications for present dungeon features logged to chat every now and again
-
-Pre-29-August-2023
-- added overmap: bare, but exists. player now starts on the overworld, and can move to local maps (like the old starting town) via >. can leave local maps back to the overmap by walking out of the map boundaries.
-- mouse begone: support still there if wanted, but targeting/e(x)amining can now be done via keyboard only
-- added config.toml: non-wasm builds read from config.toml at runtime, or generate a new copy if not present in the exe dir. includes options for logging various details to the console, and visual choices like post-processing effects, all-black bgs vs. full-coloured, etc.
-- improved morgue files: y/n prompt to write a morgue file on death (or write to console in the case of wasm), containing a map of the floor the player died on, class/race/attribute/etc. details, a fully identified backpack, and a list of significant events that took place this run w/ turn number
-- refactored colour offsets: now per-tile (and per-theme), instead of global. now can include varying fg/bg offset for every type of tile.
-- consistent chatlog colours: renderables for mobs, beatitude for items
-- dungeon features: framework
-- map identifiers (instead of displaying an incorrect depth) on ui: e.g. D1, D2, Town, Woods, etc.
-- fixes:
- - map params are saved on map transition, instead of only at creation. now bloodstains, vision, etc. will persist when changing between floors
- - mob turns await an empty particle queue - no longer will they move mid-fireball animations
- - fixed traffic jams - 1. mobs will calc the best path to any tile within range of their target, instead of trying to path directly onto the target tile, and 2. if saved path is blocked to a waypoint, mobs will recalc a new path to the same point
\ No newline at end of file
diff --git a/docs/ascii_encyclopedia.txt b/docs/ascii_encyclopedia.txt
index db60dbc..2972c1e 100644
--- a/docs/ascii_encyclopedia.txt
+++ b/docs/ascii_encyclopedia.txt
@@ -1,4 +1,4 @@
-a - A -
+a - insects A -
b - B -
c - chickens C -
d - canines D -
diff --git a/docs/combat_system.txt b/docs/combat_system.txt
index 13a780b..44e2f65 100644
--- a/docs/combat_system.txt
+++ b/docs/combat_system.txt
@@ -49,3 +49,7 @@ Complex example, with negative AC:
bloodstains: if starts on bloodied tile, remove blood + heal, gain xp, grow (little dog -> dog), etc.
- You have negative AC, so you roll 1d14 for damage reduction, and get an 8.
- The total damage is 6 - 8 = -2, but damage can't be negative, so you take 1 point of damage.
+
+tl;dr
+1. Lower AC is better
+2. Aim for 0 AC - it's an important breakpoint. Every point of AC before 0 counts for a lot.
diff --git a/raws/items.json b/raws/items.json
index b1302a6..7599afe 100644
--- a/raws/items.json
+++ b/raws/items.json
@@ -3,9 +3,10 @@
"id": "potion_health",
"name": { "name": "potion of health", "plural": "potions of health" },
"renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 },
+ "class": "potion",
"weight": 1,
"value": 50,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "heal": "4d4+2" },
"magic": { "class": "uncommon", "naming": "potion" }
},
@@ -13,9 +14,10 @@
"id": "potion_health_weak",
"name": { "name": "potion of lesser health", "plural": "potions of lesser health" },
"renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 },
+ "class": "potion",
"weight": 1,
"value": 25,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "heal": "2d4+2" },
"magic": { "class": "uncommon", "naming": "potion" }
},
@@ -23,27 +25,30 @@
"id": "scroll_identify",
"name": { "name": "scroll of identify", "plural": "scrolls of identify" },
"renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 100,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE", "IDENTIFY"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "IDENTIFY"],
"magic": { "class": "uncommon", "naming": "scroll" }
},
{
"id": "scroll_removecurse",
"name": { "name": "scroll of remove curse", "plural": "scrolls of remove curse" },
"renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 200,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE", "REMOVE_CURSE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "REMOVE_CURSE"],
"magic": { "class": "rare", "naming": "scroll" }
},
{
"id": "scroll_health",
"name": { "name": "scroll of healing word", "plural": "scrolls of healing word" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 50,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "particle_line": "*;-;#53f06d;75.0;#f9ff9f;100.0", "ranged": "12", "heal": "1d4+2" },
"magic": { "class": "uncommon", "naming": "scroll" }
},
@@ -51,9 +56,10 @@
"id": "scroll_mass_health",
"name": { "name": "scroll of mass healing word", "plural": "scrolls of mass healing word" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 200,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "particle": "*;#53f06d;200.0", "ranged": "12", "aoe": "3", "heal": "1d4+2" },
"magic": { "class": "rare", "naming": "scroll" }
},
@@ -61,33 +67,36 @@
"id": "scroll_magicmissile",
"name": { "name": "scroll of magic missile", "plural": "scrolls of magic missile" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 50,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
- "effects": { "particle_line": "*;-;#00b7ff;75.0;#f4fc83;100.0", "ranged": "12", "damage": "3d4+3" },
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
+ "effects": { "particle_line": "*;-;#00b7ff;75.0;#f4fc83;100.0", "ranged": "12", "damage": "3d4+3;magic" },
"magic": { "class": "uncommon", "naming": "scroll" }
},
{
"id": "scroll_embers",
"name": { "name": "scroll of embers", "plural": "scrolls of embers" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 100,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
- "effects": { "particle": "*;#FFA500;200.0", "ranged": "10", "damage": "4d6", "aoe": "2" },
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
+ "effects": { "particle": "*;#FFA500;200.0", "ranged": "10", "damage": "4d6;fire", "aoe": "2" },
"magic": { "class": "uncommon", "naming": "scroll" }
},
{
"id": "scroll_fireball",
"name": { "name": "scroll of fireball", "plural": "scrolls of fireball" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 200,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": {
"particle_burst": "▓;*;~;#FFA500;#000000;500.0;#ffd381;60.0",
"ranged": "10",
- "damage": "8d6",
+ "damage": "8d6;fire",
"aoe": "3"
},
"magic": { "class": "rare", "naming": "scroll" }
@@ -96,9 +105,10 @@
"id": "scroll_confusion",
"name": { "name": "scroll of confusion", "plural": "scrolls of confusion" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 100,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "particle_line": "*;-;#ad56a6;75.0;#cacaca;100.0", "ranged": "10", "confusion": "4" },
"magic": { "class": "uncommon", "naming": "scroll" }
},
@@ -106,9 +116,10 @@
"id": "scroll_mass_confusion",
"name": { "name": "scroll of mass confusion", "plural": "scrolls of mass confusion" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 200,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"],
"effects": { "particle": "*;#ad56a6;200.0", "ranged": "10", "aoe": "3", "confusion": "3" },
"magic": { "class": "veryrare", "naming": "scroll" }
},
@@ -116,9 +127,10 @@
"id": "scroll_magicmap",
"name": { "name": "scroll of magic mapping", "plural": "scrolls of magic mapping" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "scroll",
"weight": 0.5,
"value": 50,
- "flags": ["CONSUMABLE", "DESTRUCTIBLE", "MAGICMAP"],
+ "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "MAGICMAP"],
"effects": {},
"magic": { "class": "common", "naming": "scroll" }
},
@@ -126,6 +138,7 @@
"id": "equip_dagger",
"name": { "name": "dagger", "plural": "daggers" },
"renderable": { "glyph": ")", "fg": "#808080", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 1,
"value": 2,
"flags": ["EQUIP_MELEE"],
@@ -135,6 +148,7 @@
"id": "equip_shortsword",
"name": { "name": "shortsword", "plural": "shortswords" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 2,
"value": 10,
"flags": ["EQUIP_MELEE"],
@@ -144,6 +158,7 @@
"id": "equip_rapier",
"name": { "name": "rapier", "plural": "rapiers" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 2,
"value": 10,
"flags": ["EQUIP_MELEE"],
@@ -153,6 +168,7 @@
"id": "equip_pitchfork",
"name": { "name": "pitchfork", "plural": "pitchforks" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 2,
"value": 5,
"flags": ["EQUIP_MELEE"],
@@ -162,6 +178,7 @@
"id": "equip_sickle",
"name": { "name": "sickle", "plural": "sickles" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 2,
"value": 5,
"flags": ["EQUIP_MELEE"],
@@ -171,6 +188,7 @@
"id": "equip_handaxe",
"name": { "name": "handaxe", "plural": "handaxes" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 2,
"value": 5,
"flags": ["EQUIP_MELEE"],
@@ -180,6 +198,7 @@
"id": "equip_longsword",
"name": { "name": "longsword", "plural": "longswords" },
"renderable": { "glyph": ")", "fg": "#FFF8DC", "bg": "#000000", "order": 2 },
+ "class": "weapon",
"weight": 3,
"value": 15,
"flags": ["EQUIP_MELEE"],
@@ -189,6 +208,7 @@
"id": "equip_smallshield",
"name": { "name": "buckler", "plural": "bucklers" },
"renderable": { "glyph": "[", "fg": "#808080", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 2,
"value": 5,
"flags": ["EQUIP_SHIELD"],
@@ -198,6 +218,7 @@
"id": "equip_mediumshield",
"name": { "name": "medium shield", "plural": "medium shields" },
"renderable": { "glyph": "[", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 6,
"value": 10,
"flags": ["EQUIP_SHIELD"],
@@ -207,6 +228,7 @@
"id": "equip_largeshield",
"name": { "name": "large shield", "plural": "large shields" },
"renderable": { "glyph": "[", "fg": "#FFF8DC", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 12,
"value": 35,
"flags": ["EQUIP_SHIELD"],
@@ -216,6 +238,7 @@
"id": "equip_body_weakleather",
"name": { "name": "leather jacket", "plural": "leather jackets" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 8,
"value": 5,
"flags": ["EQUIP_BODY"],
@@ -225,6 +248,7 @@
"id": "equip_body_leather",
"name": { "name": "leather chestpiece", "plural": "leather chestpiece" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 10,
"value": 10,
"flags": ["EQUIP_BODY"],
@@ -234,6 +258,7 @@
"id": "equip_body_studdedleather",
"name": { "name": "studded leather chestpiece", "plural": "studded leather chestpieces" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 13,
"value": 45,
"flags": ["EQUIP_BODY"],
@@ -243,6 +268,7 @@
"id": "equip_body_ringmail_o",
"name": { "name": "orcish ring mail", "plural": "orcish ring mail" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 45,
"value": 50,
"flags": ["EQUIP_BODY"],
@@ -252,6 +278,7 @@
"id": "equip_body_ringmail",
"name": { "name": "ring mail", "plural": "ring mail" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 45,
"value": 70,
"flags": ["EQUIP_BODY"],
@@ -261,6 +288,7 @@
"id": "equip_head_leather",
"name": { "name": "leather cap", "plural": "leather caps" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 2,
"value": 10,
"flags": ["EQUIP_HEAD"],
@@ -270,6 +298,7 @@
"id": "equip_head_elvish",
"name": { "name": "elvish leather helm", "plural": "elvish leather helms" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 2,
"value": 25,
"flags": ["EQUIP_HEAD"],
@@ -279,6 +308,7 @@
"id": "equip_head_o",
"name": { "name": "orcish helm", "plural": "orcish helm" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 6,
"value": 25,
"flags": ["EQUIP_HEAD"],
@@ -288,6 +318,7 @@
"id": "equip_head_iron",
"name": { "name": "iron helm", "plural": "iron helm" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 10,
"value": 45,
"flags": ["EQUIP_HEAD"],
@@ -297,6 +328,7 @@
"id": "equip_feet_leather",
"name": { "name": "leather shoes", "plural": "leather shoes" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 2,
"value": 10,
"flags": ["EQUIP_FEET"]
@@ -305,6 +337,7 @@
"id": "equip_feet_elvish",
"name": { "name": "elvish leather shoes", "plural": "elvish leather shoes" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 2,
"value": 25,
"flags": ["EQUIP_FEET"],
@@ -314,6 +347,7 @@
"id": "equip_feet_o",
"name": { "name": "orcish boots", "plural": "orcish boots" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 6,
"value": 25,
"flags": ["EQUIP_FEET"],
@@ -323,6 +357,7 @@
"id": "equip_feet_iron",
"name": { "name": "iron boots", "plural": "iron boots" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 10,
"value": 45,
"flags": ["EQUIP_FEET"],
@@ -332,6 +367,7 @@
"id": "equip_neck_protection",
"name": { "name": "amulet of protection", "plural": "amulets of protection" },
"renderable": { "glyph": "\"", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "amulet",
"weight": 1,
"value": 200,
"flags": ["EQUIP_NECK"],
@@ -341,6 +377,7 @@
"id": "equip_back_protection",
"name": { "name": "cloak of protection", "plural": "cloaks of protection" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
+ "class": "armour",
"weight": 1,
"value": 200,
"flags": ["EQUIP_BACK"],
@@ -350,26 +387,29 @@
"id": "wand_magicmissile",
"name": { "name": "wand of magic missile", "plural": "wands of magic missile" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "wand",
"weight": 2,
"value": 100,
"flags": ["CHARGES"],
- "effects": { "ranged": "12", "damage": "3d4+3" },
+ "effects": { "ranged": "12", "damage": "3d4+3;magic" },
"magic": { "class": "uncommon", "naming": "wand" }
},
{
"id": "wand_fireball",
"name": { "name": "wand of fireball", "plural": "wands of fireball" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "wand",
"weight": 2,
"value": 300,
"flags": ["CHARGES"],
- "effects": { "ranged": "10", "damage": "8d6", "aoe": "3" },
+ "effects": { "ranged": "10", "damage": "8d6;fire", "aoe": "3" },
"magic": { "class": "rare", "naming": "wand" }
},
{
"id": "wand_confusion",
"name": { "name": "wand of confusion", "plural": "wands of confusion" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "wand",
"weight": 2,
"value": 200,
"flags": ["CHARGES"],
@@ -380,6 +420,7 @@
"id": "wand_digging",
"name": { "name": "wand of digging", "plural": "wands of digging" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "class": "wand",
"weight": 2,
"value": 300,
"flags": ["CHARGES", "DIGGER"],
@@ -390,16 +431,18 @@
"id": "food_rations",
"name": { "name": "rations", "plural": "rations" },
"renderable": { "glyph": "%", "fg": "#FFA07A", "bg": "#000000", "order": 2 },
+ "class": "comestible",
"weight": 1,
"value": 1,
- "flags": ["FOOD", "CONSUMABLE"]
+ "flags": ["FOOD", "CONSUMABLE", "STACKABLE"]
},
{
"id": "food_apple",
"name": { "name": "apple", "plural": "apples" },
"renderable": { "glyph": "%", "fg": "#00FF00", "bg": "#000000", "order": 2 },
+ "class": "comestible",
"weight": 0.5,
"value": 1,
- "flags": ["FOOD", "CONSUMABLE"]
+ "flags": ["FOOD", "CONSUMABLE", "STACKABLE"]
}
]
diff --git a/raws/mobs.json b/raws/mobs.json
index 5137ea4..ddd6556 100644
--- a/raws/mobs.json
+++ b/raws/mobs.json
@@ -62,7 +62,6 @@
"renderable": { "glyph": "@", "fg": "#034efc", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "RANDOM_PATH", "IS_HUMAN"],
"level": 2,
- "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 +72,6 @@
"renderable": { "glyph": "r", "fg": "#aa6000", "bg": "#000000", "order": 1 },
"flags": [],
"bac": 6,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }],
"loot": { "table": "food", "chance": 0.1 }
},
@@ -83,7 +81,6 @@
"renderable": { "glyph": "c", "fg": "#BB6000", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 8,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
},
{
@@ -92,7 +89,6 @@
"renderable": { "glyph": "q", "fg": "#a57037", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 8,
- "vision_range": 16,
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
},
{
@@ -101,7 +97,6 @@
"renderable": { "glyph": "q", "fg": "#e7e7e7", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE", "SMALL_GROUP"],
"bac": 10,
- "vision_range": 16,
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
},
{
@@ -110,7 +105,6 @@
"renderable": { "glyph": "c", "fg": "#fae478", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 10,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
},
{
@@ -121,7 +115,6 @@
"level": 3,
"bac": 6,
"speed": 16,
- "vision_range": 16,
"attacks": [
{ "name": "kicks", "hit_bonus": 0, "damage": "1d6" },
{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }
@@ -136,7 +129,6 @@
"level": 5,
"bac": 5,
"speed": 20,
- "vision_range": 16,
"attacks": [
{ "name": "kicks", "hit_bonus": 0, "damage": "1d8" },
{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }
@@ -150,7 +142,6 @@
"level": 7,
"bac": 4,
"speed": 24,
- "vision_range": 16,
"attacks": [
{ "name": "kicks", "hit_bonus": 0, "damage": "1d10" },
{ "name": "bites", "hit_bonus": 0, "damage": "1d4" }
@@ -163,7 +154,6 @@
"flags": ["SMALL_GROUP"],
"level": 1,
"bac": 7,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }],
"loot": { "table": "scrolls", "chance": 0.05 }
},
@@ -175,7 +165,6 @@
"level": 2,
"bac": 6,
"speed": 18,
- "vision_range": 16,
"quips": ["", "", ""],
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d6" }]
},
@@ -187,7 +176,6 @@
"level": 4,
"bac": 5,
"speed": 16,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d6" }]
},
{
@@ -198,7 +186,6 @@
"level": 6,
"bac": 4,
"speed": 15,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "2d4" }]
},
{
@@ -208,7 +195,6 @@
"flags": ["SMALL_GROUP", "IS_GNOME"],
"level": 1,
"speed": 6,
- "vision_range": 16,
"attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }],
"loot": { "table": "wands", "chance": 0.05 }
},
@@ -230,7 +216,6 @@
"flags": [],
"level": 1,
"speed": 9,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d4" }]
},
{
@@ -240,7 +225,6 @@
"flags": [],
"level": 1,
"speed": 6,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d4" }],
"loot": { "table": "food", "chance": 0.05 }
},
@@ -286,7 +270,6 @@
"level": 2,
"bac": 10,
"speed": 6,
- "vision_range": 16,
"attacks": [{ "name": "hacks", "hit_bonus": 0, "damage": "1d8" }],
"equipped": ["equip_feet_iron"],
"loot": { "table": "equipment", "chance": 0.05 }
@@ -322,17 +305,62 @@
"level": 1,
"bac": 3,
"speed": 12,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }],
"loot": { "table": "scrolls", "chance": 0.05 }
},
+ {
+ "id": "ant_worker",
+ "name": "worker ant",
+ "renderable": { "glyph": "a", "fg": "#ca7631", "bg": "#000000", "order": 1 },
+ "flags": ["SMALL_GROUP"],
+ "level": 2,
+ "bac": 3,
+ "speed": 18,
+ "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d4" }],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "ant_soldier",
+ "name": "soldier ant",
+ "renderable": { "glyph": "a", "fg": "#ca3f26", "bg": "#000000", "order": 1 },
+ "flags": ["SMALL_GROUP", "POISON_RES"],
+ "level": 3,
+ "bac": 3,
+ "speed": 18,
+ "attacks": [
+ { "name": "bites", "hit_bonus": 0, "damage": "2d4" },
+ { "name": "stings", "hit_bonus": 0, "damage": "3d4;poison" }
+ ],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "caterpillar_cave",
+ "name": "caterpillar",
+ "renderable": { "glyph": "a", "fg": "#6b6b6b", "bg": "#000000", "order": 1 },
+ "flags": ["SMALL_GROUP"],
+ "level": 1,
+ "bac": 3,
+ "speed": 9,
+ "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "caterpillar_giant",
+ "name": "giant caterpillar",
+ "renderable": { "glyph": "a", "fg": "#b9aeae", "bg": "#000000", "order": 1 },
+ "flags": ["SMALL_GROUP"],
+ "level": 2,
+ "bac": 7,
+ "speed": 9,
+ "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d6" }],
+ "loot": { "table": "food", "chance": 0.10 }
+ },
{
"id": "jackal",
"name": "jackal",
"renderable": { "glyph": "d", "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE", "SMALL_GROUP"],
"bac": 7,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
},
{
@@ -341,7 +369,6 @@
"renderable": { "glyph": "d", "fg": "#FF0000", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE"],
"bac": 7,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
},
{
@@ -351,7 +378,6 @@
"flags": ["CARNIVORE", "SMALL_GROUP"],
"level": 1,
"bac": 7,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d4" }]
},
{
@@ -361,7 +387,6 @@
"flags": ["CARNIVORE"],
"level": 5,
"bac": 4,
- "vision_range": 16,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "2d4" }]
},
{
@@ -371,7 +396,6 @@
"flags": [],
"level": 2,
"speed": 9,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d8" }],
"loot": { "table": "wands", "chance": 0.05 }
},
@@ -382,7 +406,6 @@
"flags": ["SMALL_GROUP"],
"level": 1,
"speed": 9,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }],
"loot": { "table": "equipment", "chance": 0.05 }
},
@@ -393,7 +416,6 @@
"flags": ["LARGE_GROUP"],
"level": 2,
"speed": 9,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }],
"loot": { "table": "equipment", "chance": 0.05 }
},
@@ -404,13 +426,68 @@
"flags": ["MULTIATTACK"],
"level": 5,
"speed": 5,
- "vision_range": 16,
"attacks": [
{ "name": "hits", "hit_bonus": 0, "damage": "2d4" },
{ "name": "hits", "hit_bonus": 0, "damage": "2d4" }
],
"loot": { "table": "equipment", "chance": 0.05 }
},
+ {
+ "id": "warg",
+ "name": "warg",
+ "renderable": { "glyph": "d", "fg": "#8b7164", "bg": "#000000", "order": 1 },
+ "flags": ["SMALL_GROUP"],
+ "level": 7,
+ "bac": 4,
+ "speed": 12,
+ "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "2d6" }],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "jaguar",
+ "name": "jaguar",
+ "renderable": { "glyph": "f", "fg": "#d3b947", "bg": "#000000", "order": 1 },
+ "flags": ["MULTIATTACK"],
+ "level": 4,
+ "bac": 6,
+ "speed": 15,
+ "attacks": [
+ { "name": "claws", "hit_bonus": 0, "damage": "1d4" },
+ { "name": "claws", "hit_bonus": 0, "damage": "1d4" },
+ { "name": "bites", "hit_bonus": 0, "damage": "1d8" }
+ ],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "lynx",
+ "name": "lynx",
+ "renderable": { "glyph": "f", "fg": "#b5d347", "bg": "#000000", "order": 1 },
+ "flags": ["MULTIATTACK"],
+ "level": 5,
+ "bac": 6,
+ "speed": 15,
+ "attacks": [
+ { "name": "claws", "hit_bonus": 0, "damage": "1d4" },
+ { "name": "claws", "hit_bonus": 0, "damage": "1d4" },
+ { "name": "bites", "hit_bonus": 0, "damage": "1d10" }
+ ],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
+ {
+ "id": "panther",
+ "name": "panther",
+ "renderable": { "glyph": "f", "fg": "#58554e", "bg": "#000000", "order": 1 },
+ "flags": ["MULTIATTACK"],
+ "level": 5,
+ "bac": 6,
+ "speed": 15,
+ "attacks": [
+ { "name": "claws", "hit_bonus": 0, "damage": "1d6" },
+ { "name": "claws", "hit_bonus": 0, "damage": "1d6" },
+ { "name": "bites", "hit_bonus": 0, "damage": "1d10" }
+ ],
+ "loot": { "table": "food", "chance": 0.05 }
+ },
{
"id": "ogre",
"name": "ogre",
@@ -419,7 +496,6 @@
"level": 5,
"bac": 5,
"speed": 10,
- "vision_range": 16,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "2d5" }],
"loot": { "table": "food", "chance": 0.05 }
},
@@ -427,11 +503,10 @@
"id": "treant_small",
"name": "treant sapling",
"renderable": { "glyph": "♠️", "fg": "#10570d", "bg": "#000000", "order": 1 },
- "flags": ["LARGE_GROUP", "GREEN_BLOOD"],
+ "flags": ["LARGE_GROUP", "GREEN_BLOOD", "FIRE_WEAK"],
"level": 2,
"bac": 12,
"speed": 3,
- "vision_range": 16,
"attacks": [{ "name": "lashes", "hit_bonus": 4, "damage": "1d8" }],
"loot": { "table": "scrolls", "chance": 0.05 }
}
diff --git a/raws/spawn_tables.json b/raws/spawn_tables.json
index a1e8d3b..b624a80 100644
--- a/raws/spawn_tables.json
+++ b/raws/spawn_tables.json
@@ -91,6 +91,8 @@
{ "id": "kobold_large", "weight": 1, "difficulty": 2},
{ "id": "rat_giant", "weight": 2, "difficulty": 2},
{ "id": "coyote", "weight": 4, "difficulty": 2},
+ { "id": "caterpillar_cave", "weight": 2, "difficulty": 2},
+ { "id": "caterpillar_giant", "weight": 2, "difficulty": 3},
{ "id": "zombie_orc", "weight": 1, "difficulty": 3},
{ "id": "zombie_dwarf", "weight": 1, "difficulty": 3},
{ "id": "gnome", "weight": 1, "difficulty": 3},
@@ -102,12 +104,18 @@
{ "id": "dwarf", "weight": 3, "difficulty": 4},
{ "id": "orc_hill", "weight": 1, "difficulty": 4},
{ "id": "horse_little", "weight": 2, "difficulty": 4},
+ { "id": "ant_worker", "weight": 3, "difficulty": 4},
{ "id": "dog", "weight": 1, "difficulty": 5},
{ "id": "wolf", "weight": 2, "difficulty": 6},
+ { "id": "jaguar", "weight": 2, "difficulty": 6},
+ { "id": "ant_soldier", "weight": 2, "difficulty": 6},
{ "id": "orc_captain", "weight": 1, "difficulty": 7},
{ "id": "dog_large", "weight": 1, "difficulty": 7},
+ { "id": "lynx", "weight": 1, "difficulty": 7},
+ { "id": "panther", "weight": 1, "difficulty": 7},
{ "id": "horse", "weight": 2, "difficulty": 7},
{ "id": "ogre", "weight": 1, "difficulty": 7},
+ { "id": "warg", "weight": 2, "difficulty": 8},
{ "id": "horse_large", "weight": 2, "difficulty": 9}
]
},
diff --git a/resources/terminal10x10_gs_tc.png b/resources/terminal10x10_gs_tc.png
deleted file mode 100644
index 5e0cdc9..0000000
Binary files a/resources/terminal10x10_gs_tc.png and /dev/null differ
diff --git a/resources/terminal8x8.jpg b/resources/terminal8x8.jpg
deleted file mode 100644
index 9f4d79d..0000000
Binary files a/resources/terminal8x8.jpg and /dev/null differ
diff --git a/resources/terminal_10x16.png b/resources/terminal_10x16.png
deleted file mode 100644
index e40aa99..0000000
Binary files a/resources/terminal_10x16.png and /dev/null differ
diff --git a/resources/vga8x16.png b/resources/vga8x16.png
deleted file mode 100644
index 913e32c..0000000
Binary files a/resources/vga8x16.png and /dev/null differ
diff --git a/src/ai/approach_ai_system.rs b/src/ai/approach_ai_system.rs
index 18bc43d..c3cc2ca 100644
--- a/src/ai/approach_ai_system.rs
+++ b/src/ai/approach_ai_system.rs
@@ -1,5 +1,5 @@
use crate::{ EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed, WantsToApproach };
-use rltk::prelude::*;
+use bracket_lib::prelude::*;
use specs::prelude::*;
pub struct ApproachAI {}
@@ -7,7 +7,6 @@ pub struct ApproachAI {}
impl<'a> System<'a> for ApproachAI {
#[allow(clippy::type_complexity)]
type SystemData = (
- WriteExpect<'a, RandomNumberGenerator>,
WriteStorage<'a, TakingTurn>,
WriteStorage<'a, WantsToApproach>,
WriteStorage<'a, Position>,
@@ -20,7 +19,6 @@ impl<'a> System<'a> for ApproachAI {
fn run(&mut self, data: Self::SystemData) {
let (
- mut rng,
mut turns,
mut wants_to_approach,
mut positions,
@@ -39,7 +37,9 @@ impl<'a> System<'a> for ApproachAI {
&turns,
).join() {
turn_done.push(entity);
- let target_idxs = if let Some(paths) = get_adjacent_unblocked(&map, approach.idx as usize) {
+ let target_idxs = if
+ let Some(paths) = get_adjacent_unblocked(&map, approach.idx as usize)
+ {
paths
} else {
continue;
@@ -47,9 +47,12 @@ impl<'a> System<'a> for ApproachAI {
let mut path: Option = None;
let idx = map.xy_idx(pos.x, pos.y);
for tar_idx in target_idxs {
- let potential_path = rltk::a_star_search(idx, tar_idx, &mut *map);
+ let potential_path = a_star_search(idx, tar_idx, &mut *map);
if potential_path.success && potential_path.steps.len() > 1 {
- if path.is_none() || potential_path.steps.len() < path.as_ref().unwrap().steps.len() {
+ if
+ path.is_none() ||
+ potential_path.steps.len() < path.as_ref().unwrap().steps.len()
+ {
path = Some(potential_path);
}
}
diff --git a/src/ai/chase_ai_system.rs b/src/ai/chase_ai_system.rs
index faf89d4..9fd29bf 100644
--- a/src/ai/chase_ai_system.rs
+++ b/src/ai/chase_ai_system.rs
@@ -1,5 +1,5 @@
use crate::{ Chasing, EntityMoved, Map, Position, TakingTurn, Telepath, Viewshed };
-use rltk::prelude::*;
+use bracket_lib::prelude::*;
use specs::prelude::*;
use std::collections::HashMap;
use super::approach_ai_system::get_adjacent_unblocked;
@@ -26,8 +26,16 @@ impl<'a> System<'a> for ChaseAI {
);
fn run(&mut self, data: Self::SystemData) {
- let (mut turns, mut chasing, mut positions, mut map, mut viewsheds, mut telepaths, mut entity_moved, entities) =
- data;
+ let (
+ mut turns,
+ mut chasing,
+ mut positions,
+ mut map,
+ mut viewsheds,
+ mut telepaths,
+ mut entity_moved,
+ entities,
+ ) = data;
let mut targets: HashMap = HashMap::new();
let mut end_chase: Vec = Vec::new();
// For every chasing entity with a turn, look for a valid target position,
@@ -67,9 +75,12 @@ impl<'a> System<'a> for ChaseAI {
let mut path: Option = None;
let idx = map.xy_idx(pos.x, pos.y);
for tar_idx in target_idxs {
- let potential_path = rltk::a_star_search(idx, tar_idx, &mut *map);
+ let potential_path = a_star_search(idx, tar_idx, &mut *map);
if potential_path.success && potential_path.steps.len() > 1 {
- if path.is_none() || potential_path.steps.len() < path.as_ref().unwrap().steps.len() {
+ if
+ path.is_none() ||
+ potential_path.steps.len() < path.as_ref().unwrap().steps.len()
+ {
path = Some(potential_path);
}
}
diff --git a/src/ai/default_move_system.rs b/src/ai/default_move_system.rs
index b56987c..bd417bd 100644
--- a/src/ai/default_move_system.rs
+++ b/src/ai/default_move_system.rs
@@ -1,5 +1,16 @@
-use crate::{ tile_walkable, EntityMoved, Map, MoveMode, Movement, Position, TakingTurn, Telepath, Viewshed };
+use crate::{
+ tile_walkable,
+ EntityMoved,
+ Map,
+ MoveMode,
+ Movement,
+ Position,
+ TakingTurn,
+ Telepath,
+ Viewshed,
+};
use specs::prelude::*;
+use bracket_lib::prelude::*;
// Rolling a 1d8+x to decide where to move, where x are the number
// of dice rolls in which they will remian stationary. i.e. If this
@@ -16,7 +27,7 @@ impl<'a> System<'a> for DefaultAI {
WriteStorage<'a, Viewshed>,
WriteStorage<'a, Telepath>,
WriteStorage<'a, EntityMoved>,
- WriteExpect<'a, rltk::RandomNumberGenerator>,
+ WriteExpect<'a, RandomNumberGenerator>,
Entities<'a>,
);
@@ -85,7 +96,9 @@ impl<'a> System<'a> for DefaultAI {
let idx = map.xy_idx(pos.x, pos.y);
pos.x = x;
pos.y = y;
- entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
+ entity_moved
+ .insert(entity, EntityMoved {})
+ .expect("Unable to insert EntityMoved");
crate::spatial::move_entity(entity, idx, dest_idx);
viewshed.dirty = true;
if let Some(is_telepath) = telepaths.get_mut(entity) {
@@ -102,7 +115,9 @@ impl<'a> System<'a> for DefaultAI {
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;
- entity_moved.insert(entity, EntityMoved {}).expect("Unable to insert EntityMoved");
+ 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);
viewshed.dirty = true;
@@ -112,7 +127,7 @@ impl<'a> System<'a> for DefaultAI {
path.remove(0);
} else {
// If the path is blocked, recalculate a new path to the same waypoint.
- let path = rltk::a_star_search(
+ let path = a_star_search(
map.xy_idx(pos.x, pos.y) as i32,
map.xy_idx(
(path[path.len() - 1] as i32) % map.width,
@@ -121,7 +136,9 @@ impl<'a> System<'a> for DefaultAI {
&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),
+ };
}
}
} else {
@@ -132,7 +149,7 @@ impl<'a> System<'a> for DefaultAI {
let target_y = rng.roll_dice(1, map.height - 2);
let idx = map.xy_idx(target_x, target_y);
if tile_walkable(map.tiles[idx]) {
- let path = rltk::a_star_search(
+ let path = a_star_search(
map.xy_idx(pos.x, pos.y) as i32,
map.xy_idx(target_x, target_y) as i32,
&mut *map
diff --git a/src/ai/energy_system.rs b/src/ai/energy_system.rs
index b4d3256..da62467 100644
--- a/src/ai/energy_system.rs
+++ b/src/ai/energy_system.rs
@@ -10,8 +10,9 @@ use crate::{
Map,
TakingTurn,
Confusion,
+ Intrinsics,
};
-use rltk::prelude::*;
+use bracket_lib::prelude::*;
use specs::prelude::*;
use crate::config::CONFIG;
use crate::data::events::*;
@@ -36,6 +37,7 @@ impl<'a> System<'a> for EnergySystem {
ReadStorage<'a, Name>,
ReadExpect<'a, Point>,
ReadStorage<'a, Confusion>,
+ ReadStorage<'a, Intrinsics>,
);
fn run(&mut self, data: Self::SystemData) {
@@ -53,6 +55,7 @@ impl<'a> System<'a> for EnergySystem {
names,
player_pos,
confusion,
+ intrinsics,
) = data;
// If not ticking, do nothing.
if *runstate != RunState::Ticking {
@@ -68,7 +71,7 @@ impl<'a> System<'a> for EnergySystem {
.insert(entity, TakingTurn {})
.expect("Unable to insert turn for turn counter.");
energy.current -= TURN_COST;
- crate::gamelog::record_event(EVENT::TURN(1));
+ crate::gamelog::record_event(EVENT::Turn(1));
// Handle spawning mobs each turn
if CONFIG.logging.log_ticks {
console::log(
@@ -87,20 +90,14 @@ impl<'a> System<'a> for EnergySystem {
&positions,
!&confusion,
).join() {
- let burden_modifier = if let Some(burden) = burdens.get(entity) {
- match burden.level {
- BurdenLevel::Burdened => SPEED_MOD_BURDENED,
- BurdenLevel::Strained => SPEED_MOD_STRAINED,
- BurdenLevel::Overloaded => SPEED_MOD_OVERLOADED,
- }
- } else {
- 1.0
- };
- let overmap_mod = if map.overmap { SPEED_MOD_OVERMAP_TRAVEL } else { 1.0 };
+ let burden_modifier = get_burden_modifier(&burdens, entity);
+ let overmap_mod = get_overmap_modifier(&map);
+ let intrinsic_speed = get_intrinsic_speed(&intrinsics, entity);
// Every entity has a POTENTIAL equal to their speed.
let mut energy_potential: i32 = ((energy.speed as f32) *
burden_modifier *
- overmap_mod) as i32;
+ overmap_mod *
+ intrinsic_speed) as i32;
// Increment current energy by NORMAL_SPEED for every
// whole number of NORMAL_SPEEDS in their POTENTIAL.
while energy_potential >= NORMAL_SPEED {
@@ -121,37 +118,61 @@ impl<'a> System<'a> for EnergySystem {
// has enough energy, they take a turn and decrement their energy
// by TURN_COST. If the current entity is the player, await input.
if energy.current >= TURN_COST {
- let mut my_turn = true;
energy.current -= TURN_COST;
if entity == *player {
*runstate = RunState::AwaitingInput;
- } else {
- let distance = rltk::DistanceAlg::Pythagoras.distance2d(
- *player_pos,
- Point::new(pos.x, pos.y)
- );
- if distance > 20.0 {
- my_turn = false;
- }
+ } else if cull_turn_by_distance(&player_pos, pos) {
+ continue;
}
- if my_turn {
- turns.insert(entity, TakingTurn {}).expect("Unable to insert turn.");
- if CONFIG.logging.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
- )
- );
- }
+ turns.insert(entity, TakingTurn {}).expect("Unable to insert turn.");
+ if CONFIG.logging.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
+ )
+ );
}
}
}
}
}
+
+fn get_burden_modifier(burdens: &ReadStorage, entity: Entity) -> f32 {
+ return if let Some(burden) = burdens.get(entity) {
+ match burden.level {
+ BurdenLevel::Burdened => SPEED_MOD_BURDENED,
+ BurdenLevel::Strained => SPEED_MOD_STRAINED,
+ BurdenLevel::Overloaded => SPEED_MOD_OVERLOADED,
+ }
+ } else {
+ 1.0
+ };
+}
+
+fn get_overmap_modifier(map: &ReadExpect