Compare commits

..

14 commits

Author SHA1 Message Date
Llywelwyn
2d55f83bb3 del spritesheet test grid 2023-09-23 20:54:49 +01:00
Llywelwyn
670b365def refining the sprites 2023-09-23 19:35:51 +01:00
Llywelwyn
d58614b106 optional sprites for entities 2023-09-23 19:01:39 +01:00
Llywelwyn
cee4d02ce2 sprites init 2023-09-23 18:02:51 +01:00
Llywelwyn
8337f202cf tile clipping fixes 2023-09-23 11:58:34 +01:00
Llywelwyn
141d4b63d2 fixes infini-dungeon difficulty 2023-09-23 11:14:32 +01:00
Llywelwyn
ddcfd72318 fixing up some post-merge errors 2023-09-23 10:43:32 +01:00
Llywelwyn
441b22439f Merge branch 'master' into switching_to_draw_batches 2023-09-23 10:12:26 +01:00
Llywelwyn
a29a7f5be4 formatting 2023-09-03 22:47:59 +01:00
Llywelwyn
ae3e061ce8 back to curses -- still needs tweaking
box drawing glyphs are misaligned, etc
2023-09-03 08:42:10 +01:00
Llywelwyn
ebcce3183b fixes off-by-one pixels with a small gutter
not sure why this fixes it - but it does. needs some testing.
2023-09-03 06:56:05 +01:00
Llywelwyn
1bea2c0026 testing resizing
strange artifacts with this size of font. seems to be an OpenGL issue (on specific hardware?) - issue is present on two different devices, with different screen resolutions, but disappears when running the WASM build. might be easiest to return to something which doesn't have this issue.
2023-09-03 06:40:27 +01:00
Llywelwyn
4e0ed95a22 infinite font variations for testing - huge wip 2023-09-03 05:10:17 +01:00
Llywelwyn
2a3c59ad33 first steps - extreme wip
1. need to finish curses12x24 first of all
2. bind everything to the viewport, and make scalable
2023-09-03 01:45:18 +01:00
64 changed files with 1928 additions and 1157 deletions

View file

@ -12,7 +12,7 @@ env:
jobs: jobs:
build: build:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rust-rl" name = "rust-rl"
version = "0.1.4" version = "0.1.1"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -2,18 +2,18 @@
#### using _rltk/bracket-lib_, and _specs_ #### using _rltk/bracket-lib_, and _specs_
[![Rust](https://github.com/Llywelwyn/rust-rl/actions/workflows/cargo-build-test.yml/badge.svg)](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 of your choice](https://github.com/Llywelwyn/rust-rl/releases), or build manually with:
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`, `git clone https://github.com/Llywelwyn/rust-rl/ && cd rust-rl && cargo build --release`,
![image](https://github.com/Llywelwyn/rust-rl/assets/82828093/b05e4f0b-2062-4abe-9fee-c679f9ef420d) ![image](https://github.com/Llywelwyn/rust-rl/assets/82828093/b05e4f0b-2062-4abe-9fee-c679f9ef420d)
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.
i'm also working on translating over my progress into blog entries on my site @ [llyw.co.uk](https://llyw.co.uk/), with a larger focus on some of the more interesting implementation details.
--- ---
<details>
<summary>boring details about the sprint where this project started</summary>
<details> <details>
<summary>week 1</summary> <summary>week 1</summary>
@ -157,4 +157,3 @@ check out the page in the header for the wasm version, pick [a release](https://
![squares](https://github.com/Llywelwyn/rust-rl/assets/82828093/b752e1cb-340d-475d-84ae-68fdb4977a80) ![squares](https://github.com/Llywelwyn/rust-rl/assets/82828093/b752e1cb-340d-475d-84ae-68fdb4977a80)
</details> </details>
</details>

View file

@ -49,7 +49,3 @@ Complex example, with negative AC:
bloodstains: if starts on bloodied tile, remove blood + heal, gain xp, grow (little dog -> dog), etc. 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. - 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. - 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.

View file

@ -3,10 +3,9 @@
"id": "potion_health", "id": "potion_health",
"name": { "name": "potion of health", "plural": "potions of health" }, "name": { "name": "potion of health", "plural": "potions of health" },
"renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 },
"class": "potion",
"weight": 1, "weight": 1,
"value": 50, "value": 50,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "heal": "4d4+2" }, "effects": { "heal": "4d4+2" },
"magic": { "class": "uncommon", "naming": "potion" } "magic": { "class": "uncommon", "naming": "potion" }
}, },
@ -14,10 +13,9 @@
"id": "potion_health_weak", "id": "potion_health_weak",
"name": { "name": "potion of lesser health", "plural": "potions of lesser health" }, "name": { "name": "potion of lesser health", "plural": "potions of lesser health" },
"renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 },
"class": "potion",
"weight": 1, "weight": 1,
"value": 25, "value": 25,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "heal": "2d4+2" }, "effects": { "heal": "2d4+2" },
"magic": { "class": "uncommon", "naming": "potion" } "magic": { "class": "uncommon", "naming": "potion" }
}, },
@ -25,30 +23,27 @@
"id": "scroll_identify", "id": "scroll_identify",
"name": { "name": "scroll of identify", "plural": "scrolls of identify" }, "name": { "name": "scroll of identify", "plural": "scrolls of identify" },
"renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 100, "value": 100,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "IDENTIFY"], "flags": ["CONSUMABLE", "DESTRUCTIBLE", "IDENTIFY"],
"magic": { "class": "uncommon", "naming": "scroll" } "magic": { "class": "uncommon", "naming": "scroll" }
}, },
{ {
"id": "scroll_removecurse", "id": "scroll_removecurse",
"name": { "name": "scroll of remove curse", "plural": "scrolls of remove curse" }, "name": { "name": "scroll of remove curse", "plural": "scrolls of remove curse" },
"renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 200, "value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "REMOVE_CURSE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE", "REMOVE_CURSE"],
"magic": { "class": "rare", "naming": "scroll" } "magic": { "class": "rare", "naming": "scroll" }
}, },
{ {
"id": "scroll_health", "id": "scroll_health",
"name": { "name": "scroll of healing word", "plural": "scrolls of healing word" }, "name": { "name": "scroll of healing word", "plural": "scrolls of healing word" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 50, "value": 50,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle_line": "*;-;#53f06d;75.0;#f9ff9f;100.0", "ranged": "12", "heal": "1d4+2" }, "effects": { "particle_line": "*;-;#53f06d;75.0;#f9ff9f;100.0", "ranged": "12", "heal": "1d4+2" },
"magic": { "class": "uncommon", "naming": "scroll" } "magic": { "class": "uncommon", "naming": "scroll" }
}, },
@ -56,10 +51,9 @@
"id": "scroll_mass_health", "id": "scroll_mass_health",
"name": { "name": "scroll of mass healing word", "plural": "scrolls of mass healing word" }, "name": { "name": "scroll of mass healing word", "plural": "scrolls of mass healing word" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 200, "value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle": "*;#53f06d;200.0", "ranged": "12", "aoe": "3", "heal": "1d4+2" }, "effects": { "particle": "*;#53f06d;200.0", "ranged": "12", "aoe": "3", "heal": "1d4+2" },
"magic": { "class": "rare", "naming": "scroll" } "magic": { "class": "rare", "naming": "scroll" }
}, },
@ -67,10 +61,9 @@
"id": "scroll_magicmissile", "id": "scroll_magicmissile",
"name": { "name": "scroll of magic missile", "plural": "scrolls of magic missile" }, "name": { "name": "scroll of magic missile", "plural": "scrolls of magic missile" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 50, "value": 50,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle_line": "*;-;#00b7ff;75.0;#f4fc83;100.0", "ranged": "12", "damage": "3d4+3;magic" }, "effects": { "particle_line": "*;-;#00b7ff;75.0;#f4fc83;100.0", "ranged": "12", "damage": "3d4+3;magic" },
"magic": { "class": "uncommon", "naming": "scroll" } "magic": { "class": "uncommon", "naming": "scroll" }
}, },
@ -78,10 +71,9 @@
"id": "scroll_embers", "id": "scroll_embers",
"name": { "name": "scroll of embers", "plural": "scrolls of embers" }, "name": { "name": "scroll of embers", "plural": "scrolls of embers" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 100, "value": 100,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle": "*;#FFA500;200.0", "ranged": "10", "damage": "4d6;fire", "aoe": "2" }, "effects": { "particle": "*;#FFA500;200.0", "ranged": "10", "damage": "4d6;fire", "aoe": "2" },
"magic": { "class": "uncommon", "naming": "scroll" } "magic": { "class": "uncommon", "naming": "scroll" }
}, },
@ -89,10 +81,9 @@
"id": "scroll_fireball", "id": "scroll_fireball",
"name": { "name": "scroll of fireball", "plural": "scrolls of fireball" }, "name": { "name": "scroll of fireball", "plural": "scrolls of fireball" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 200, "value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "effects": {
"particle_burst": "▓;*;~;#FFA500;#000000;500.0;#ffd381;60.0", "particle_burst": "▓;*;~;#FFA500;#000000;500.0;#ffd381;60.0",
"ranged": "10", "ranged": "10",
@ -105,10 +96,9 @@
"id": "scroll_confusion", "id": "scroll_confusion",
"name": { "name": "scroll of confusion", "plural": "scrolls of confusion" }, "name": { "name": "scroll of confusion", "plural": "scrolls of confusion" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 100, "value": 100,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle_line": "*;-;#ad56a6;75.0;#cacaca;100.0", "ranged": "10", "confusion": "4" }, "effects": { "particle_line": "*;-;#ad56a6;75.0;#cacaca;100.0", "ranged": "10", "confusion": "4" },
"magic": { "class": "uncommon", "naming": "scroll" } "magic": { "class": "uncommon", "naming": "scroll" }
}, },
@ -116,10 +106,9 @@
"id": "scroll_mass_confusion", "id": "scroll_mass_confusion",
"name": { "name": "scroll of mass confusion", "plural": "scrolls of mass confusion" }, "name": { "name": "scroll of mass confusion", "plural": "scrolls of mass confusion" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 200, "value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "particle": "*;#ad56a6;200.0", "ranged": "10", "aoe": "3", "confusion": "3" }, "effects": { "particle": "*;#ad56a6;200.0", "ranged": "10", "aoe": "3", "confusion": "3" },
"magic": { "class": "veryrare", "naming": "scroll" } "magic": { "class": "veryrare", "naming": "scroll" }
}, },
@ -127,10 +116,9 @@
"id": "scroll_magicmap", "id": "scroll_magicmap",
"name": { "name": "scroll of magic mapping", "plural": "scrolls of magic mapping" }, "name": { "name": "scroll of magic mapping", "plural": "scrolls of magic mapping" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "scroll",
"weight": 0.5, "weight": 0.5,
"value": 50, "value": 50,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE", "MAGICMAP"], "flags": ["CONSUMABLE", "DESTRUCTIBLE", "MAGICMAP"],
"effects": {}, "effects": {},
"magic": { "class": "common", "naming": "scroll" } "magic": { "class": "common", "naming": "scroll" }
}, },
@ -138,7 +126,6 @@
"id": "equip_dagger", "id": "equip_dagger",
"name": { "name": "dagger", "plural": "daggers" }, "name": { "name": "dagger", "plural": "daggers" },
"renderable": { "glyph": ")", "fg": "#808080", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#808080", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 1, "weight": 1,
"value": 2, "value": 2,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -148,7 +135,6 @@
"id": "equip_shortsword", "id": "equip_shortsword",
"name": { "name": "shortsword", "plural": "shortswords" }, "name": { "name": "shortsword", "plural": "shortswords" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 2, "weight": 2,
"value": 10, "value": 10,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -158,7 +144,6 @@
"id": "equip_rapier", "id": "equip_rapier",
"name": { "name": "rapier", "plural": "rapiers" }, "name": { "name": "rapier", "plural": "rapiers" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 2, "weight": 2,
"value": 10, "value": 10,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -168,7 +153,6 @@
"id": "equip_pitchfork", "id": "equip_pitchfork",
"name": { "name": "pitchfork", "plural": "pitchforks" }, "name": { "name": "pitchfork", "plural": "pitchforks" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 2, "weight": 2,
"value": 5, "value": 5,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -178,7 +162,6 @@
"id": "equip_sickle", "id": "equip_sickle",
"name": { "name": "sickle", "plural": "sickles" }, "name": { "name": "sickle", "plural": "sickles" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 2, "weight": 2,
"value": 5, "value": 5,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -188,7 +171,6 @@
"id": "equip_handaxe", "id": "equip_handaxe",
"name": { "name": "handaxe", "plural": "handaxes" }, "name": { "name": "handaxe", "plural": "handaxes" },
"renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 2, "weight": 2,
"value": 5, "value": 5,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -198,7 +180,6 @@
"id": "equip_longsword", "id": "equip_longsword",
"name": { "name": "longsword", "plural": "longswords" }, "name": { "name": "longsword", "plural": "longswords" },
"renderable": { "glyph": ")", "fg": "#FFF8DC", "bg": "#000000", "order": 2 }, "renderable": { "glyph": ")", "fg": "#FFF8DC", "bg": "#000000", "order": 2 },
"class": "weapon",
"weight": 3, "weight": 3,
"value": 15, "value": 15,
"flags": ["EQUIP_MELEE"], "flags": ["EQUIP_MELEE"],
@ -208,7 +189,6 @@
"id": "equip_smallshield", "id": "equip_smallshield",
"name": { "name": "buckler", "plural": "bucklers" }, "name": { "name": "buckler", "plural": "bucklers" },
"renderable": { "glyph": "[", "fg": "#808080", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#808080", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 2, "weight": 2,
"value": 5, "value": 5,
"flags": ["EQUIP_SHIELD"], "flags": ["EQUIP_SHIELD"],
@ -218,7 +198,6 @@
"id": "equip_mediumshield", "id": "equip_mediumshield",
"name": { "name": "medium shield", "plural": "medium shields" }, "name": { "name": "medium shield", "plural": "medium shields" },
"renderable": { "glyph": "[", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#C0C0C0", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 6, "weight": 6,
"value": 10, "value": 10,
"flags": ["EQUIP_SHIELD"], "flags": ["EQUIP_SHIELD"],
@ -228,7 +207,6 @@
"id": "equip_largeshield", "id": "equip_largeshield",
"name": { "name": "large shield", "plural": "large shields" }, "name": { "name": "large shield", "plural": "large shields" },
"renderable": { "glyph": "[", "fg": "#FFF8DC", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#FFF8DC", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 12, "weight": 12,
"value": 35, "value": 35,
"flags": ["EQUIP_SHIELD"], "flags": ["EQUIP_SHIELD"],
@ -238,7 +216,6 @@
"id": "equip_body_weakleather", "id": "equip_body_weakleather",
"name": { "name": "leather jacket", "plural": "leather jackets" }, "name": { "name": "leather jacket", "plural": "leather jackets" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 8, "weight": 8,
"value": 5, "value": 5,
"flags": ["EQUIP_BODY"], "flags": ["EQUIP_BODY"],
@ -248,7 +225,6 @@
"id": "equip_body_leather", "id": "equip_body_leather",
"name": { "name": "leather chestpiece", "plural": "leather chestpiece" }, "name": { "name": "leather chestpiece", "plural": "leather chestpiece" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 10, "weight": 10,
"value": 10, "value": 10,
"flags": ["EQUIP_BODY"], "flags": ["EQUIP_BODY"],
@ -258,7 +234,6 @@
"id": "equip_body_studdedleather", "id": "equip_body_studdedleather",
"name": { "name": "studded leather chestpiece", "plural": "studded leather chestpieces" }, "name": { "name": "studded leather chestpiece", "plural": "studded leather chestpieces" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 13, "weight": 13,
"value": 45, "value": 45,
"flags": ["EQUIP_BODY"], "flags": ["EQUIP_BODY"],
@ -268,7 +243,6 @@
"id": "equip_body_ringmail_o", "id": "equip_body_ringmail_o",
"name": { "name": "orcish ring mail", "plural": "orcish ring mail" }, "name": { "name": "orcish ring mail", "plural": "orcish ring mail" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 45, "weight": 45,
"value": 50, "value": 50,
"flags": ["EQUIP_BODY"], "flags": ["EQUIP_BODY"],
@ -278,7 +252,6 @@
"id": "equip_body_ringmail", "id": "equip_body_ringmail",
"name": { "name": "ring mail", "plural": "ring mail" }, "name": { "name": "ring mail", "plural": "ring mail" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 45, "weight": 45,
"value": 70, "value": 70,
"flags": ["EQUIP_BODY"], "flags": ["EQUIP_BODY"],
@ -288,7 +261,6 @@
"id": "equip_head_leather", "id": "equip_head_leather",
"name": { "name": "leather cap", "plural": "leather caps" }, "name": { "name": "leather cap", "plural": "leather caps" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 2, "weight": 2,
"value": 10, "value": 10,
"flags": ["EQUIP_HEAD"], "flags": ["EQUIP_HEAD"],
@ -298,7 +270,6 @@
"id": "equip_head_elvish", "id": "equip_head_elvish",
"name": { "name": "elvish leather helm", "plural": "elvish leather helms" }, "name": { "name": "elvish leather helm", "plural": "elvish leather helms" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 2, "weight": 2,
"value": 25, "value": 25,
"flags": ["EQUIP_HEAD"], "flags": ["EQUIP_HEAD"],
@ -308,7 +279,6 @@
"id": "equip_head_o", "id": "equip_head_o",
"name": { "name": "orcish helm", "plural": "orcish helm" }, "name": { "name": "orcish helm", "plural": "orcish helm" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 6, "weight": 6,
"value": 25, "value": 25,
"flags": ["EQUIP_HEAD"], "flags": ["EQUIP_HEAD"],
@ -318,7 +288,6 @@
"id": "equip_head_iron", "id": "equip_head_iron",
"name": { "name": "iron helm", "plural": "iron helm" }, "name": { "name": "iron helm", "plural": "iron helm" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 10, "weight": 10,
"value": 45, "value": 45,
"flags": ["EQUIP_HEAD"], "flags": ["EQUIP_HEAD"],
@ -328,7 +297,6 @@
"id": "equip_feet_leather", "id": "equip_feet_leather",
"name": { "name": "leather shoes", "plural": "leather shoes" }, "name": { "name": "leather shoes", "plural": "leather shoes" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 2, "weight": 2,
"value": 10, "value": 10,
"flags": ["EQUIP_FEET"] "flags": ["EQUIP_FEET"]
@ -337,7 +305,6 @@
"id": "equip_feet_elvish", "id": "equip_feet_elvish",
"name": { "name": "elvish leather shoes", "plural": "elvish leather shoes" }, "name": { "name": "elvish leather shoes", "plural": "elvish leather shoes" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 2, "weight": 2,
"value": 25, "value": 25,
"flags": ["EQUIP_FEET"], "flags": ["EQUIP_FEET"],
@ -347,7 +314,6 @@
"id": "equip_feet_o", "id": "equip_feet_o",
"name": { "name": "orcish boots", "plural": "orcish boots" }, "name": { "name": "orcish boots", "plural": "orcish boots" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 6, "weight": 6,
"value": 25, "value": 25,
"flags": ["EQUIP_FEET"], "flags": ["EQUIP_FEET"],
@ -357,7 +323,6 @@
"id": "equip_feet_iron", "id": "equip_feet_iron",
"name": { "name": "iron boots", "plural": "iron boots" }, "name": { "name": "iron boots", "plural": "iron boots" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 10, "weight": 10,
"value": 45, "value": 45,
"flags": ["EQUIP_FEET"], "flags": ["EQUIP_FEET"],
@ -367,7 +332,6 @@
"id": "equip_neck_protection", "id": "equip_neck_protection",
"name": { "name": "amulet of protection", "plural": "amulets of protection" }, "name": { "name": "amulet of protection", "plural": "amulets of protection" },
"renderable": { "glyph": "\"", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "\"", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "amulet",
"weight": 1, "weight": 1,
"value": 200, "value": 200,
"flags": ["EQUIP_NECK"], "flags": ["EQUIP_NECK"],
@ -377,7 +341,6 @@
"id": "equip_back_protection", "id": "equip_back_protection",
"name": { "name": "cloak of protection", "plural": "cloaks of protection" }, "name": { "name": "cloak of protection", "plural": "cloaks of protection" },
"renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 },
"class": "armour",
"weight": 1, "weight": 1,
"value": 200, "value": 200,
"flags": ["EQUIP_BACK"], "flags": ["EQUIP_BACK"],
@ -387,7 +350,6 @@
"id": "wand_magicmissile", "id": "wand_magicmissile",
"name": { "name": "wand of magic missile", "plural": "wands of magic missile" }, "name": { "name": "wand of magic missile", "plural": "wands of magic missile" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "wand",
"weight": 2, "weight": 2,
"value": 100, "value": 100,
"flags": ["CHARGES"], "flags": ["CHARGES"],
@ -398,7 +360,6 @@
"id": "wand_fireball", "id": "wand_fireball",
"name": { "name": "wand of fireball", "plural": "wands of fireball" }, "name": { "name": "wand of fireball", "plural": "wands of fireball" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "wand",
"weight": 2, "weight": 2,
"value": 300, "value": 300,
"flags": ["CHARGES"], "flags": ["CHARGES"],
@ -409,7 +370,6 @@
"id": "wand_confusion", "id": "wand_confusion",
"name": { "name": "wand of confusion", "plural": "wands of confusion" }, "name": { "name": "wand of confusion", "plural": "wands of confusion" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "wand",
"weight": 2, "weight": 2,
"value": 200, "value": 200,
"flags": ["CHARGES"], "flags": ["CHARGES"],
@ -420,7 +380,6 @@
"id": "wand_digging", "id": "wand_digging",
"name": { "name": "wand of digging", "plural": "wands of digging" }, "name": { "name": "wand of digging", "plural": "wands of digging" },
"renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"class": "wand",
"weight": 2, "weight": 2,
"value": 300, "value": 300,
"flags": ["CHARGES", "DIGGER"], "flags": ["CHARGES", "DIGGER"],
@ -431,18 +390,16 @@
"id": "food_rations", "id": "food_rations",
"name": { "name": "rations", "plural": "rations" }, "name": { "name": "rations", "plural": "rations" },
"renderable": { "glyph": "%", "fg": "#FFA07A", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "%", "fg": "#FFA07A", "bg": "#000000", "order": 2 },
"class": "comestible",
"weight": 1, "weight": 1,
"value": 1, "value": 1,
"flags": ["FOOD", "CONSUMABLE", "STACKABLE"] "flags": ["FOOD", "CONSUMABLE"]
}, },
{ {
"id": "food_apple", "id": "food_apple",
"name": { "name": "apple", "plural": "apples" }, "name": { "name": "apple", "plural": "apples" },
"renderable": { "glyph": "%", "fg": "#00FF00", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "%", "fg": "#00FF00", "bg": "#000000", "order": 2 },
"class": "comestible",
"weight": 0.5, "weight": 0.5,
"value": 1, "value": 1,
"flags": ["FOOD", "CONSUMABLE", "STACKABLE"] "flags": ["FOOD", "CONSUMABLE"]
} }
] ]

View file

@ -2,7 +2,7 @@
{ {
"id": "door", "id": "door",
"name": "door", "name": "door",
"renderable": { "glyph": "+", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "+", "sprite": 17, "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"flags": ["DOOR"] "flags": ["DOOR"]
}, },
{ {
@ -21,7 +21,7 @@
{ {
"id": "prop_table", "id": "prop_table",
"name": "table", "name": "table",
"renderable": { "glyph": "-", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "-", "sprite": 52, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": [] "flags": []
}, },
{ {
@ -33,25 +33,25 @@
{ {
"id": "prop_statue", "id": "prop_statue",
"name": "statue", "name": "statue",
"renderable": { "glyph": "@", "fg": "#ffffff", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "@", "sprite": 29, "fg": "#ffffff", "bg": "#000000", "order": 2 },
"flags": [] "flags": []
}, },
{ {
"id": "prop_bed", "id": "prop_bed",
"name": "bed", "name": "bed",
"renderable": { "glyph": "=", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "=", "sprite": 50, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": [] "flags": []
}, },
{ {
"id": "prop_chair", "id": "prop_chair",
"name": "chair", "name": "chair",
"renderable": { "glyph": "└", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "└", "sprite": 51, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": [] "flags": []
}, },
{ {
"id": "prop_candle", "id": "prop_candle",
"name": "candle", "name": "candle",
"renderable": { "glyph": "Ä", "fg": "#FFA500", "bg": "#000000", "order": 2 }, "renderable": { "glyph": "Ä", "sprite": 3, "fg": "#FFA500", "bg": "#000000", "order": 2 },
"flags": [] "flags": []
}, },
{ {

BIN
resources/curses11x20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
resources/curses12x24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
resources/curses16x16.pdn Normal file

Binary file not shown.

BIN
resources/curses16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
resources/curses8x16.pdn Normal file

Binary file not shown.

BIN
resources/curses8x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
resources/healthbar11x2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

BIN
resources/healthbar22x2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
resources/nagidal24x24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
resources/vga8x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
resources/world16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -45,6 +45,7 @@ impl<'a> System<'a> for ApproachAI {
continue; continue;
}; };
let mut path: Option<NavigationPath> = None; let mut path: Option<NavigationPath> = None;
let mut curr_abs_diff = 100;
let idx = map.xy_idx(pos.x, pos.y); let idx = map.xy_idx(pos.x, pos.y);
for tar_idx in target_idxs { for tar_idx in target_idxs {
let potential_path = a_star_search(idx, tar_idx, &mut *map); let potential_path = a_star_search(idx, tar_idx, &mut *map);
@ -54,6 +55,17 @@ impl<'a> System<'a> for ApproachAI {
potential_path.steps.len() < path.as_ref().unwrap().steps.len() potential_path.steps.len() < path.as_ref().unwrap().steps.len()
{ {
path = Some(potential_path); path = Some(potential_path);
let (x1, y1) = (pos.x, pos.y);
let (x2, y2) = ((tar_idx as i32) % map.width, (tar_idx as i32) / map.width);
curr_abs_diff = i32::abs(x2 - x1) + i32::abs(y2 - y1);
} else if potential_path.steps.len() == path.as_ref().unwrap().steps.len() {
let (x1, y1) = (pos.x, pos.y);
let (x2, y2) = ((tar_idx as i32) % map.width, (tar_idx as i32) / map.width);
let abs_diff = i32::abs(x2 - x1) + i32::abs(y2 - y1);
if abs_diff < curr_abs_diff {
path = Some(potential_path);
curr_abs_diff = abs_diff;
}
} }
} }
} }

View file

@ -65,7 +65,9 @@ impl<'a> System<'a> for TurnStatusSystem {
not_confused.push(entity); not_confused.push(entity);
if entity == *player_entity { if entity == *player_entity {
logger = logger logger = logger
.colour(renderable_colour(&renderables, entity))
.append("You") .append("You")
.colour(WHITE)
.append("snap out of it."); .append("snap out of it.");
log = true; log = true;
} else { } else {
@ -92,7 +94,9 @@ impl<'a> System<'a> for TurnStatusSystem {
not_my_turn.push(entity); not_my_turn.push(entity);
if entity == *player_entity { if entity == *player_entity {
logger = logger logger = logger
.colour(renderable_colour(&renderables, entity))
.append("You") .append("You")
.colour(WHITE)
.append("are confused!"); .append("are confused!");
log = true; log = true;
gamelog::record_event(EVENT::PlayerConfused(1)); gamelog::record_event(EVENT::PlayerConfused(1));

View file

@ -1,14 +1,16 @@
use super::{ Hidden, Map, Mind, Position, Prop, Renderable }; use super::{ Hidden, Map, Mind, Position, Prop, Renderable, Pools };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
use std::ops::Mul; use std::ops::Mul;
use super::data::visuals::{ VIEWPORT_W, VIEWPORT_H };
use super::data::prelude::*;
const SHOW_BOUNDARIES: bool = false; const SHOW_BOUNDARIES: bool = false;
pub fn get_screen_bounds(ecs: &World, _ctx: &mut BTerm) -> (i32, i32, i32, i32, i32, i32) { pub fn get_screen_bounds(ecs: &World, _ctx: &mut BTerm) -> (i32, i32, i32, i32, i32, i32) {
let player_pos = ecs.fetch::<Point>(); let player_pos = ecs.fetch::<Point>();
let map = ecs.fetch::<Map>(); let map = ecs.fetch::<Map>();
let (x_chars, y_chars, mut x_offset, mut y_offset) = (69, 41, 1, 10); let (x_chars, y_chars, mut x_offset, mut y_offset) = (VIEWPORT_W, VIEWPORT_H, 1, 10);
let centre_x = (x_chars / 2) as i32; let centre_x = (x_chars / 2) as i32;
let centre_y = (y_chars / 2) as i32; let centre_y = (y_chars / 2) as i32;
@ -43,13 +45,29 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
if t_x >= 0 && t_x < map.width && t_y >= 0 && t_y < map.height { if t_x >= 0 && t_x < map.width && t_y >= 0 && t_y < map.height {
let idx = map.xy_idx(t_x, t_y); let idx = map.xy_idx(t_x, t_y);
if map.revealed_tiles[idx] { if map.revealed_tiles[idx] {
let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id( if 1 == 2 {
idx, let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id(
&*map, idx,
Some(*ecs.fetch::<Point>()), &*map,
None Some(*ecs.fetch::<Point>()),
); None
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph); );
ctx.set(x + x_offset, y + y_offset, fg, bg, glyph);
} else {
ctx.set_active_console(0);
let (id, tint) = crate::map::themes::get_sprite_for_id(
idx,
&*map,
Some(*ecs.fetch::<Point>())
);
ctx.add_sprite(
Rect::with_size(x * 16 + x_offset * 16, y * 16 + y_offset * 16, 16, 16),
0,
tint,
id
);
ctx.set_active_console(TILE_LAYER);
}
} }
} else if SHOW_BOUNDARIES { } else if SHOW_BOUNDARIES {
ctx.set( ctx.set(
@ -67,8 +85,11 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
// Render entities // Render entities
{ {
ctx.set_active_console(ENTITY_LAYER);
let positions = ecs.read_storage::<Position>(); let positions = ecs.read_storage::<Position>();
let renderables = ecs.read_storage::<Renderable>(); let renderables = ecs.read_storage::<Renderable>();
let pools = ecs.read_storage::<Pools>();
let minds = ecs.read_storage::<Mind>(); let minds = ecs.read_storage::<Mind>();
let hidden = ecs.read_storage::<Hidden>(); let hidden = ecs.read_storage::<Hidden>();
let props = ecs.write_storage::<Prop>(); let props = ecs.write_storage::<Prop>();
@ -84,12 +105,7 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y { if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y {
let mut draw = false; let mut draw = false;
let mut fg = render.fg; let mut fg = render.fg;
let mut bg = crate::map::themes::get_tile_renderables_for_id( let bg = BLACK;
idx,
&*map,
Some(*ecs.fetch::<Point>()),
None
).2;
// Draw entities on visible tiles // Draw entities on visible tiles
if map.visible_tiles[idx] { if map.visible_tiles[idx] {
draw = true; draw = true;
@ -104,9 +120,6 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
let has_mind = minds.get(*ent); let has_mind = minds.get(*ent);
if let Some(_) = has_mind { if let Some(_) = has_mind {
draw = true; draw = true;
if !map.revealed_tiles[idx] {
bg = RGB::named(BLACK);
}
} }
} }
} }
@ -118,16 +131,51 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) {
} }
} }
if draw { if draw {
ctx.set( if let Some(sprite) = render.sprite {
entity_offset_x + x_offset, ctx.set_active_console(0);
entity_offset_y + y_offset, ctx.add_sprite(
fg, Rect::with_size(
bg, entity_offset_x * 16 + x_offset * 16,
render.glyph entity_offset_y * 16 + y_offset * 16,
); 16,
16
),
render.render_order,
RGBA::named(WHITE),
sprite
);
ctx.set_active_console(ENTITY_LAYER);
} else {
ctx.set(
entity_offset_x + x_offset,
entity_offset_y + y_offset,
fg,
bg,
render.glyph
);
}
if let Some(pool) = pools.get(*ent) {
if pool.hit_points.current < pool.hit_points.max {
ctx.set_active_console(HP_BAR_LAYER);
crate::gui::draw_lerping_bar(
ctx,
(entity_offset_x + x_offset) * 16 + 2,
(entity_offset_y + y_offset) * 16 - 1,
14,
pool.hit_points.current,
pool.hit_points.max,
RGB::named(GREEN),
RGB::named(RED),
false,
false
);
ctx.set_active_console(ENTITY_LAYER);
}
}
} }
} }
} }
ctx.set_active_console(TILE_LAYER);
} }
} }

View file

@ -41,6 +41,7 @@ pub struct OtherLevelPosition {
#[derive(Component, ConvertSaveload, Clone)] #[derive(Component, ConvertSaveload, Clone)]
pub struct Renderable { pub struct Renderable {
pub glyph: FontCharType, pub glyph: FontCharType,
pub sprite: Option<usize>,
pub fg: RGB, pub fg: RGB,
pub bg: RGB, pub bg: RGB,
pub render_order: i32, pub render_order: i32,
@ -243,55 +244,16 @@ pub enum BUC {
Blessed, Blessed,
} }
impl BUC {
pub fn noncursed(&self) -> bool {
match self {
BUC::Cursed => false,
_ => true,
}
}
}
#[derive(Component, Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone)] #[derive(Component, Debug, Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
pub struct Beatitude { pub struct Beatitude {
pub buc: BUC, pub buc: BUC,
pub known: bool, pub known: bool,
} }
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
pub enum ItemType {
Amulet,
Weapon,
Armour,
Comestible,
Scroll,
Spellbook,
Potion,
Ring,
Wand,
}
impl ItemType {
pub fn string(&self) -> &str {
match self {
ItemType::Amulet => "Amulets",
ItemType::Weapon => "Weapons",
ItemType::Armour => "Armour",
ItemType::Comestible => "Comestibles",
ItemType::Scroll => "Scrolls",
ItemType::Spellbook => "Spellbooks",
ItemType::Potion => "Potions",
ItemType::Ring => "Rings",
ItemType::Wand => "Wands",
}
}
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)] #[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Item { pub struct Item {
pub weight: f32, // in lbs pub weight: f32, // in lbs
pub value: f32, // base pub value: f32, // base
pub category: ItemType,
} }
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
@ -466,45 +428,11 @@ pub enum Intrinsic {
Speed, // 4/3x speed multiplier Speed, // 4/3x speed multiplier
} }
impl Intrinsic {
pub fn describe(&self) -> &str {
match self {
Intrinsic::Regeneration => "regenerates health",
Intrinsic::Speed => "is hasted",
}
}
}
#[derive(Component, Serialize, Deserialize, Debug, Clone)] #[derive(Component, Serialize, Deserialize, Debug, Clone)]
pub struct Intrinsics { pub struct Intrinsics {
pub list: HashSet<Intrinsic>, pub list: HashSet<Intrinsic>,
} }
impl Intrinsics {
pub fn describe(&self) -> String {
let mut descriptions = Vec::new();
for intrinsic in &self.list {
descriptions.push(intrinsic.describe());
}
match descriptions.len() {
0 =>
unreachable!("describe() should never be called on an empty Intrinsics component."),
1 => format!("It {}.", descriptions[0]),
_ => {
let last = descriptions.pop().unwrap();
let joined = descriptions.join(", ");
format!("It {}, and {}.", joined, last)
}
}
}
}
#[derive(Component, Serialize, Deserialize, Debug, Clone)]
pub struct IntrinsicChanged {
pub gained: HashSet<Intrinsic>,
pub lost: HashSet<Intrinsic>,
}
#[derive(Component, Debug, ConvertSaveload, Clone)] #[derive(Component, Debug, ConvertSaveload, Clone)]
pub struct InflictsDamage { pub struct InflictsDamage {
pub damage_type: DamageType, pub damage_type: DamageType,
@ -648,20 +576,3 @@ pub struct EntityMoved {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)] #[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct MultiAttack {} pub struct MultiAttack {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Stackable {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct WantsToRemoveKey {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct WantsToDelete {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Key {
pub idx: usize,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct WantsToAssignKey {}

View file

@ -11,8 +11,6 @@ use super::{
Position, Position,
Renderable, Renderable,
RunState, RunState,
WantsToRemoveKey,
WantsToDelete,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
@ -67,17 +65,7 @@ pub fn delete_the_dead(ecs: &mut World) {
} }
} }
} }
let (mut items_to_delete, loot_to_spawn) = handle_dead_entity_items(ecs, &dead); let (items_to_delete, loot_to_spawn) = handle_dead_entity_items(ecs, &dead);
{
let entities = ecs.entities();
let removekeys = ecs.read_storage::<WantsToRemoveKey>();
let delete = ecs.read_storage::<WantsToDelete>();
// Add items marked for deletion to the list, but only if they've already had their
// key assignments handled, to ensurew we don't leave any dangling references behind.
for (e, _d, _r) in (&entities, &delete, !&removekeys).join() {
items_to_delete.push(e);
}
}
for loot in loot_to_spawn { for loot in loot_to_spawn {
crate::raws::spawn_named_entity( crate::raws::spawn_named_entity(
&crate::raws::RAWS.lock().unwrap(), &crate::raws::RAWS.lock().unwrap(),
@ -94,7 +82,6 @@ pub fn delete_the_dead(ecs: &mut World) {
// For everything that died, increment the event log, and delete. // For everything that died, increment the event log, and delete.
for victim in dead { for victim in dead {
gamelog::record_event(events::EVENT::Turn(1)); gamelog::record_event(events::EVENT::Turn(1));
// TODO: Delete stuff from inventory? This should be handled elsewhere.
ecs.delete_entity(victim).expect("Unable to delete."); ecs.delete_entity(victim).expect("Unable to delete.");
} }
} }

View file

@ -25,7 +25,6 @@ pub const NUTRITION_BLESSED: &str = "Delicious";
pub const LEVELUP_PLAYER: &str = "Welcome to experience level"; pub const LEVELUP_PLAYER: &str = "Welcome to experience level";
pub const YOU_PICKUP_ITEM: &str = "You pick up the"; pub const YOU_PICKUP_ITEM: &str = "You pick up the";
pub const NO_MORE_KEYS: &str = "Your backpack cannot accomodate any more items";
pub const YOU_DROP_ITEM: &str = "You drop the"; pub const YOU_DROP_ITEM: &str = "You drop the";
pub const YOU_EQUIP_ITEM: &str = "You equip the"; pub const YOU_EQUIP_ITEM: &str = "You equip the";
pub const YOU_REMOVE_ITEM: &str = "You unequip your"; pub const YOU_REMOVE_ITEM: &str = "You unequip your";

View file

@ -5,3 +5,8 @@ pub mod char_create;
pub mod events; pub mod events;
pub mod ids; pub mod ids;
pub mod names; pub mod names;
pub mod sprites;
pub mod prelude {
pub use super::visuals::{ TILE_LAYER, ENTITY_LAYER, TEXT_LAYER, HP_BAR_LAYER };
}

119
src/data/sprites.rs Normal file
View file

@ -0,0 +1,119 @@
// Row 1
pub const UNKN: usize = 0;
pub const UNKN2: usize = 1;
pub const UNKN3: usize = 2;
pub const CANDLE: usize = 3;
pub const CANDLE2: usize = 4;
pub const CANDLE3: usize = 5;
pub const CANDLE4: usize = 6;
pub const CANDLE5: usize = 7;
pub const CANDLE6: usize = 8;
pub const CAULDRON: usize = 9;
pub const CAULDRON2: usize = 10;
pub const POTS: usize = 11;
pub const POTS2: usize = 12;
pub const POT: usize = 13;
pub const SPIKES: usize = 14;
pub const SPIKES2: usize = 15;
// Row 2
pub const WINDOW: usize = 16;
pub const DOOR: usize = 17;
pub const DOOR_OPEN: usize = 18;
pub const ROOF_BASE: usize = 19;
pub const ROOF_BASE2: usize = 20;
pub const ROOF: usize = 21;
pub const ROOF2: usize = 22;
pub const ROOF_CHIMNEY: usize = 23;
pub const SIGN: usize = 24;
pub const SIGN_BLACKSMITH: usize = 25;
pub const SIGN_POTION: usize = 26;
pub const SIGN_FURNITURE: usize = 27;
pub const WINDOW_LIT: usize = 28;
pub const STATUE_ANGEL: usize = 29;
pub const STATUE: usize = 30;
pub const STATUE_SPIDER: usize = 31;
// Row 3
pub const UNKN4: usize = 32;
pub const UNKN5: usize = 33;
pub const UNKN6: usize = 34;
pub const UNKN7: usize = 35;
pub const UNKN8: usize = 36;
pub const TREE: usize = 37;
pub const TREE2: usize = 38;
pub const PATH_GRASS: usize = 39;
pub const PATH_GRASS_QUAD: usize = 40;
pub const PATH_GRASS_QUAD2: usize = 41;
pub const PATH_GRASS_QUAD3: usize = 42;
pub const CAMPFIRE: usize = 43;
pub const CAMPFIRE_LIT: usize = 44;
pub const CAMPFIRE_LIT2: usize = 45; // ANIMATE WITH % 2 AND SOMETHING TO DO WITH FRAME TIME
pub const THRONE: usize = 46;
pub const THRONE2: usize = 47;
// Row 4
pub const BOOKSHELF: usize = 48;
pub const BOOKSHELF_EMPTY: usize = 49;
pub const BED: usize = 50;
pub const CHAIR: usize = 51;
pub const TABLE: usize = 52;
pub const TABLE_L: usize = 53;
pub const TABLE_M: usize = 54;
pub const TABLE_R: usize = 55;
pub const CHAIR_AT_TABLE_L: usize = 56;
pub const TABLE_M_PARCHMENT: usize = 57;
pub const CHAIR_AT_TABLE_R: usize = 58;
pub const TABLE_DARK: usize = 59;
pub const TABLE_DARK_SKULL: usize = 60;
pub const TABLE_DARK_L: usize = 61;
pub const TABLE_DARK_M: usize = 62;
pub const TABLE_DARK_R: usize = 63;
// Row 5
pub const GRASS: usize = 64;
pub const GRASS2: usize = 65;
pub const GRASS3: usize = 66;
pub const GRASS4: usize = 67;
pub const GRASS5: usize = 68;
pub const MUSHROOM: usize = 69;
pub const MUSHROOM_PURPLE: usize = 70;
pub const MUSHROOM_ORANGE: usize = 71;
pub const LILYPAD: usize = 72;
pub const LILYPAD2: usize = 73;
pub const LILYPAD3: usize = 74;
pub const LILYPAD4: usize = 75;
pub const LILYPAD5: usize = 76;
pub const LILYPAD6: usize = 77;
pub const LILYPAD7: usize = 78;
pub const LILYPAD8: usize = 79;
// Row 6 (80-95)
// Row 7 (96-111)
// Row 8 (112-127)
pub const FLOOR_WOOD: usize = 124;
// Row 9 (128-143)
// Row 10 (144-159)
// Row 11 (160-175)
pub const WATER_DEEP: usize = 164;
// Row 12 (176-191)
// Row 13 (192-207)
// Row 14 (208-223)
pub const FLOOR_GRASS: usize = 216;
// Row 15 (224-239)
pub const FLOOR: usize = 224;
// Row 16 (240-255)
// Row 17 (256-271)
// Row 18 (272-287)
// Row 19 (288-303)
pub const WALL_BASE: usize = 288;
pub const WALL_BASE2: usize = 289;
pub const WALL_BASE3: usize = 290;
pub const WALL_BASE4: usize = 291;
pub const WALL_CLOTH_BASE: usize = 292;
pub const WALL_CRACKED_BASE: usize = 293;
pub const WALL: usize = 294;
pub const WALL2: usize = 295;
pub const WALL3: usize = 296;
pub const WALL4: usize = 297;
pub const WALL_CRACKED: usize = 298;
pub const WALL_CLOTH_H: usize = 299;
pub const STAIR_D: usize = 300;
pub const STAIR_A: usize = 301;
pub const BASIN: usize = 302;
pub const BASIN_EMPTY: usize = 303;

View file

@ -2,6 +2,13 @@ use bracket_lib::prelude::*;
// POST-PROCESSING // POST-PROCESSING
pub const WITH_DARKEN_BY_DISTANCE: bool = true; // If further away tiles should get darkened, instead of a harsh transition to non-visible. pub const WITH_DARKEN_BY_DISTANCE: bool = true; // If further away tiles should get darkened, instead of a harsh transition to non-visible.
pub const VIEWPORT_W: i32 = 69;
pub const VIEWPORT_H: i32 = 41;
pub const TILE_LAYER: usize = 1;
pub const ENTITY_LAYER: usize = 2;
pub const TEXT_LAYER: usize = 3;
pub const HP_BAR_LAYER: usize = 4;
pub const BRIGHTEN_FG_COLOUR_BY: i32 = 16; pub const BRIGHTEN_FG_COLOUR_BY: i32 = 16;
pub const GLOBAL_OFFSET_MIN_CLAMP: f32 = -0.5; pub const GLOBAL_OFFSET_MIN_CLAMP: f32 = -0.5;

View file

@ -184,7 +184,7 @@ fn get_death_message(ecs: &World, source: Entity) -> String {
result.push_str(format!("{}", PLAYER_DIED_SUICIDE).as_str()); result.push_str(format!("{}", PLAYER_DIED_SUICIDE).as_str());
} else if let Some(name) = ecs.read_storage::<Name>().get(source) { } else if let Some(name) = ecs.read_storage::<Name>().get(source) {
result.push_str( result.push_str(
format!("{} {}", PLAYER_DIED_NAMED_ATTACKER, with_article(name.name.clone())).as_str() format!("{} {}", PLAYER_DIED_NAMED_ATTACKER, with_article(&name.name)).as_str()
); );
} else { } else {
result.push_str(format!("{}", PLAYER_DIED_UNKNOWN).as_str()); result.push_str(format!("{}", PLAYER_DIED_UNKNOWN).as_str());

View file

@ -1,11 +0,0 @@
use super::{ EffectSpawner, EffectType };
use specs::prelude::*;
pub fn add_intrinsic(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
let intrinsic = if let EffectType::AddIntrinsic { intrinsic } = &effect.effect_type {
intrinsic
} else {
unreachable!("add_intrinsic() called with the wrong EffectType")
};
add_intr!(ecs, target, *intrinsic);
}

View file

@ -4,14 +4,13 @@ use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::Mutex; use std::sync::Mutex;
use crate::components::*; use crate::components::DamageType;
mod damage; mod damage;
mod hunger; mod hunger;
mod particles; mod particles;
mod targeting; mod targeting;
mod triggers; mod triggers;
mod intrinsics;
pub use targeting::aoe_tiles; pub use targeting::aoe_tiles;
@ -52,9 +51,6 @@ pub enum EffectType {
ModifyNutrition { ModifyNutrition {
amount: i32, amount: i32,
}, },
AddIntrinsic {
intrinsic: Intrinsic,
},
TriggerFire { TriggerFire {
trigger: Entity, trigger: Entity,
}, },
@ -157,7 +153,6 @@ fn tile_effect_hits_entities(effect: &EffectType) -> bool {
EffectType::Healing { .. } => true, EffectType::Healing { .. } => true,
EffectType::ModifyNutrition { .. } => true, EffectType::ModifyNutrition { .. } => true,
EffectType::Confusion { .. } => true, EffectType::Confusion { .. } => true,
EffectType::AddIntrinsic { .. } => true,
_ => false, _ => false,
} }
} }
@ -180,7 +175,6 @@ fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
} }
EffectType::EntityDeath => damage::entity_death(ecs, effect, target), EffectType::EntityDeath => damage::entity_death(ecs, effect, target),
EffectType::ModifyNutrition { .. } => hunger::modify_nutrition(ecs, effect, target), EffectType::ModifyNutrition { .. } => hunger::modify_nutrition(ecs, effect, target),
EffectType::AddIntrinsic { .. } => intrinsics::add_intrinsic(ecs, effect, target),
_ => {} _ => {}
} }
} }

View file

@ -1,4 +1,4 @@
use super::{ add_effect, particles, spatial, EffectType, Entity, Targets, World }; use super::{ add_effect, get_noncursed, particles, spatial, EffectType, Entity, Targets, World };
use crate::{ use crate::{
gamelog, gamelog,
gui::item_colour_ecs, gui::item_colour_ecs,
@ -33,8 +33,6 @@ use crate::{
KnownSpells, KnownSpells,
Position, Position,
Viewshed, Viewshed,
WantsToRemoveKey,
WantsToDelete,
}; };
use crate::data::messages::*; use crate::data::messages::*;
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
@ -59,10 +57,7 @@ pub fn item_trigger(source: Option<Entity>, item: Entity, target: &Targets, ecs:
let did_something = event_trigger(source, item, target, ecs); let did_something = event_trigger(source, item, target, ecs);
// If it's a consumable, delete it // If it's a consumable, delete it
if did_something && ecs.read_storage::<Consumable>().get(item).is_some() { if did_something && ecs.read_storage::<Consumable>().get(item).is_some() {
let mut removekey = ecs.write_storage::<WantsToRemoveKey>(); ecs.entities().delete(item).expect("Failed to delete item");
removekey.insert(item, WantsToRemoveKey {}).expect("Unable to insert WantsToRemoveKey");
let mut delete = ecs.write_storage::<WantsToDelete>();
delete.insert(item, WantsToDelete {}).expect("Unable to insert WantsToDelete");
} }
} }
@ -210,7 +205,7 @@ fn handle_healing(
healing_item.modifier; healing_item.modifier;
add_effect( add_effect(
event.source, event.source,
EffectType::Healing { amount: roll, increment_max: event.buc.noncursed() }, EffectType::Healing { amount: roll, increment_max: get_noncursed(&event.buc) },
event.target.clone() event.target.clone()
); );
for target in get_entity_targets(&event.target) { for target in get_entity_targets(&event.target) {
@ -223,7 +218,9 @@ fn handle_healing(
let renderables = ecs.read_storage::<Renderable>(); let renderables = ecs.read_storage::<Renderable>();
if ecs.read_storage::<Player>().get(target).is_some() { if ecs.read_storage::<Player>().get(target).is_some() {
logger = logger logger = logger
.colour(renderable_colour(&renderables, target))
.append("You") .append("You")
.colour(WHITE)
.append(HEAL_PLAYER_HIT) .append(HEAL_PLAYER_HIT)
.buc(event.buc.clone(), None, Some(HEAL_PLAYER_HIT_BLESSED)); .buc(event.buc.clone(), None, Some(HEAL_PLAYER_HIT_BLESSED));
} else { } else {
@ -265,7 +262,9 @@ fn handle_damage(
let player_viewshed = viewsheds.get(*ecs.fetch::<Entity>()).unwrap(); let player_viewshed = viewsheds.get(*ecs.fetch::<Entity>()).unwrap();
if ecs.read_storage::<Player>().get(target).is_some() { if ecs.read_storage::<Player>().get(target).is_some() {
logger = logger logger = logger
.colour(renderable_colour(&renderables, target))
.append("You") .append("You")
.colour(WHITE)
.append(DAMAGE_PLAYER_HIT); .append(DAMAGE_PLAYER_HIT);
event.log = true; event.log = true;
} else if } else if

View file

@ -126,7 +126,7 @@ pub fn record_event(event: EVENT) {
new_event = format!("Discovered {}", name); new_event = format!("Discovered {}", name);
} }
EVENT::Identified(name) => { EVENT::Identified(name) => {
new_event = format!("Identified {}", crate::gui::with_article(name)); new_event = format!("Identified {}", name);
} }
EVENT::PlayerDied(str) => { EVENT::PlayerDied(str) => {
// Generating the String is handled in the death effect, to avoid passing the ecs here. // Generating the String is handled in the death effect, to avoid passing the ecs here.

View file

@ -28,6 +28,7 @@ use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize }; use serde::{ Deserialize, Serialize };
use specs::prelude::*; use specs::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use crate::data::prelude::*;
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)] #[derive(Serialize, Deserialize, Copy, Clone, PartialEq)]
pub enum Ancestry { pub enum Ancestry {
@ -112,6 +113,7 @@ pub enum CharCreateResult {
/// Handles the player character creation screen. /// Handles the player character creation screen.
pub fn character_creation(gs: &mut State, ctx: &mut BTerm) -> CharCreateResult { pub fn character_creation(gs: &mut State, ctx: &mut BTerm) -> CharCreateResult {
ctx.set_active_console(TEXT_LAYER);
let runstate = gs.ecs.fetch::<RunState>(); let runstate = gs.ecs.fetch::<RunState>();
let mut x = 2; let mut x = 2;
@ -245,6 +247,7 @@ pub fn character_creation(gs: &mut State, ctx: &mut BTerm) -> CharCreateResult {
} }
} }
} }
ctx.set_active_console(TILE_LAYER);
return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class: Class::Fighter }; return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class: Class::Fighter };
} }
@ -270,6 +273,7 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
renderables renderables
.insert(*player, Renderable { .insert(*player, Renderable {
glyph: to_cp437(DWARF_GLYPH), glyph: to_cp437(DWARF_GLYPH),
sprite: None, // TODO: Dwarf sprite
fg: RGB::named(DWARF_COLOUR), fg: RGB::named(DWARF_COLOUR),
bg: RGB::named(BLACK), bg: RGB::named(BLACK),
render_order: 0, render_order: 0,
@ -281,6 +285,7 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
renderables renderables
.insert(*player, Renderable { .insert(*player, Renderable {
glyph: to_cp437(ELF_GLYPH), glyph: to_cp437(ELF_GLYPH),
sprite: None, // TODO: Elf sprite
fg: RGB::named(ELF_COLOUR), fg: RGB::named(ELF_COLOUR),
bg: RGB::named(BLACK), bg: RGB::named(BLACK),
render_order: 0, render_order: 0,
@ -306,6 +311,7 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
renderables renderables
.insert(*player, Renderable { .insert(*player, Renderable {
glyph: to_cp437(CATFOLK_GLYPH), glyph: to_cp437(CATFOLK_GLYPH),
sprite: None, // TODO: Catfolk sprite
fg: RGB::named(CATFOLK_COLOUR), fg: RGB::named(CATFOLK_COLOUR),
bg: RGB::named(BLACK), bg: RGB::named(BLACK),
render_order: 0, render_order: 0,

View file

@ -1,4 +1,11 @@
use super::{ State, RunState, tooltip::draw_tooltips, camera::get_screen_bounds }; use super::{
State,
RunState,
tooltip::draw_tooltips,
camera::get_screen_bounds,
VIEWPORT_H,
VIEWPORT_W,
};
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
#[derive(PartialEq, Copy, Clone)] #[derive(PartialEq, Copy, Clone)]
@ -23,9 +30,8 @@ pub fn show_farlook(gs: &mut State, ctx: &mut BTerm) -> FarlookResult {
); );
if let RunState::Farlook { x, y } = *runstate { if let RunState::Farlook { x, y } = *runstate {
let (screen_x, screen_y) = (69, 41); let x = x.clamp(x_offset, x_offset - 1 + VIEWPORT_W);
let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32)); let y = y.clamp(y_offset, y_offset - 1 + VIEWPORT_H);
let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32));
ctx.set(x, y, RGB::named(WHITE), RGB::named(BLACK), to_cp437('X')); ctx.set(x, y, RGB::named(WHITE), RGB::named(BLACK), to_cp437('X'));
draw_tooltips(&gs.ecs, ctx, Some((x, y))); draw_tooltips(&gs.ecs, ctx, Some((x, y)));

View file

@ -3,10 +3,10 @@ use super::{
item_colour_ecs, item_colour_ecs,
obfuscate_name_ecs, obfuscate_name_ecs,
print_options, print_options,
unique_ecs, renderable_colour,
check_key,
letter_to_option,
ItemMenuResult, ItemMenuResult,
UniqueInventoryItem,
BUC,
}; };
use crate::{ use crate::{
gamelog, gamelog,
@ -19,12 +19,11 @@ use crate::{
Name, Name,
ObfuscatedName, ObfuscatedName,
Renderable, Renderable,
Key,
states::state::*, states::state::*,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
use std::collections::HashMap; use std::collections::BTreeMap;
/// Handles the Identify menu. /// Handles the Identify menu.
pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) { pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
@ -38,41 +37,38 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Enti
let names = gs.ecs.read_storage::<Name>(); let names = gs.ecs.read_storage::<Name>();
let renderables = gs.ecs.read_storage::<Renderable>(); let renderables = gs.ecs.read_storage::<Renderable>();
let beatitudes = gs.ecs.read_storage::<Beatitude>(); let beatitudes = gs.ecs.read_storage::<Beatitude>();
let keys = gs.ecs.read_storage::<Key>();
let build_identify_iterator = || { let build_identify_iterator = || {
(&entities, &items, &renderables, &names, &keys) (&entities, &items, &renderables, &names).join().filter(|(item_entity, _i, _r, n)| {
.join() // If not owned by the player, return false.
.filter(|(item_entity, _i, _r, n, _k)| { let mut keep = false;
// If not owned by the player, return false. if let Some(bp) = backpack.get(*item_entity) {
let mut keep = false; if bp.owner == *player_entity {
if let Some(bp) = backpack.get(*item_entity) { keep = true;
if bp.owner == *player_entity {
keep = true;
}
} }
// If not equipped by the player, return false. }
if let Some(equip) = equipped.get(*item_entity) { // If not equipped by the player, return false.
if equip.owner == *player_entity { if let Some(equip) = equipped.get(*item_entity) {
keep = true; if equip.owner == *player_entity {
} keep = true;
} }
if !keep { }
return false; if !keep {
} return false;
// If not obfuscated, or already identified, return false. }
if // If not obfuscated, or already identified, return false.
(!obfuscated.get(*item_entity).is_some() || if
dm.identified_items.contains(&n.name)) && (!obfuscated.get(*item_entity).is_some() ||
beatitudes dm.identified_items.contains(&n.name)) &&
.get(*item_entity) beatitudes
.map(|beatitude| beatitude.known) .get(*item_entity)
.unwrap_or(true) .map(|beatitude| beatitude.known)
{ .unwrap_or(true)
return false; {
} return false;
return true; }
}) return true;
})
}; };
// Build list of items to display // Build list of items to display
@ -95,15 +91,34 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Enti
.log(); .log();
return (ItemMenuResult::Selected, Some(build_identify_iterator().nth(0).unwrap().0)); return (ItemMenuResult::Selected, Some(build_identify_iterator().nth(0).unwrap().0));
} }
let mut player_inventory: super::PlayerInventory = HashMap::new(); let mut player_inventory: super::PlayerInventory = BTreeMap::new();
for (entity, _i, _r, _n, key) in build_identify_iterator() { for (entity, _i, renderable, name) in build_identify_iterator() {
let unique_item = unique_ecs(&gs.ecs, entity); let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
let beatitude_status = if
let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity)
{
match beatitude.buc {
BUC::Blessed => 1,
BUC::Uncursed => 2,
BUC::Cursed => 3,
}
} else {
0
};
let unique_item = UniqueInventoryItem {
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() },
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
beatitude_status: beatitude_status,
name: name.name.clone(),
};
player_inventory player_inventory
.entry(unique_item) .entry(unique_item)
.and_modify(|slot| { .and_modify(|(_e, count)| {
slot.count += 1; *count += 1;
}) })
.or_insert(super::InventorySlot { item: entity, count: 1, idx: key.idx }); .or_insert((entity, 1));
} }
// Get display args // Get display args
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
@ -118,7 +133,7 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Enti
"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)); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
print_options(&gs.ecs, &player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
// Input // Input
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -126,17 +141,21 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Enti
match key { match key {
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None), VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
_ => { _ => {
let selection = letter_to_option::letter_to_option(key, ctx.shift); let selection = letter_to_option(key);
if selection != -1 && check_key(selection as usize) { if selection > -1 && selection < (count as i32) {
// Get the first entity with a Key {} component that has an idx matching "selection". let item = player_inventory
let entities = gs.ecs.entities(); .iter()
let keyed_items = gs.ecs.read_storage::<Key>(); .nth(selection as usize)
let backpack = gs.ecs.read_storage::<InBackpack>(); .unwrap().1.0;
for (e, key, _b) in (&entities, &keyed_items, &backpack).join() { gamelog::Logger
if key.idx == (selection as usize) { ::new()
return (ItemMenuResult::Selected, Some(e)); .append("You identify the")
} .colour(item_colour_ecs(&gs.ecs, item))
} .append_n(obfuscate_name_ecs(&gs.ecs, item).0)
.colour(WHITE)
.append("!")
.log();
return (ItemMenuResult::Selected, Some(item));
} }
(ItemMenuResult::NoResponse, None) (ItemMenuResult::NoResponse, None)
} }

File diff suppressed because it is too large Load diff

View file

@ -3,11 +3,9 @@ use super::{
item_colour_ecs, item_colour_ecs,
obfuscate_name_ecs, obfuscate_name_ecs,
print_options, print_options,
unique_ecs, renderable_colour,
check_key,
letter_to_option,
ItemMenuResult, ItemMenuResult,
InventorySlot, UniqueInventoryItem,
}; };
use crate::{ use crate::{
gamelog, gamelog,
@ -20,11 +18,10 @@ use crate::{
Renderable, Renderable,
states::state::*, states::state::*,
BUC, BUC,
Key,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
use std::collections::HashMap; use std::collections::BTreeMap;
/// Handles the Remove Curse menu. /// Handles the Remove Curse menu.
pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) { pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<Entity>) {
@ -36,12 +33,11 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<
let beatitudes = gs.ecs.read_storage::<Beatitude>(); let beatitudes = gs.ecs.read_storage::<Beatitude>();
let names = gs.ecs.read_storage::<Name>(); let names = gs.ecs.read_storage::<Name>();
let renderables = gs.ecs.read_storage::<Renderable>(); let renderables = gs.ecs.read_storage::<Renderable>();
let keys = gs.ecs.read_storage::<Key>();
let build_cursed_iterator = || { let build_cursed_iterator = || {
(&entities, &items, &beatitudes, &renderables, &names, &keys) (&entities, &items, &beatitudes, &renderables, &names)
.join() .join()
.filter(|(item_entity, _i, b, _r, _n, _k)| { .filter(|(item_entity, _i, b, _r, _n)| {
// Set all items to FALSE initially. // Set all items to FALSE initially.
let mut keep = false; let mut keep = false;
// If found in the player's backpack, set to TRUE // If found in the player's backpack, set to TRUE
@ -90,19 +86,34 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<
.log(); .log();
return (ItemMenuResult::Selected, Some(item)); return (ItemMenuResult::Selected, Some(item));
} }
let mut player_inventory: super::PlayerInventory = HashMap::new(); let mut player_inventory: super::PlayerInventory = BTreeMap::new();
for (entity, _i, _b, _r, _n, key) in build_cursed_iterator() { for (entity, _i, _b, renderable, name) in build_cursed_iterator() {
let unique_item = unique_ecs(&gs.ecs, entity); let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity);
let beatitude_status = if
let Some(beatitude) = gs.ecs.read_storage::<Beatitude>().get(entity)
{
match beatitude.buc {
BUC::Blessed => 1,
BUC::Uncursed => 2,
BUC::Cursed => 3,
}
} else {
0
};
let unique_item = UniqueInventoryItem {
display_name: super::DisplayName { singular: singular.clone(), plural: plural.clone() },
rgb: item_colour_ecs(&gs.ecs, entity),
renderables: renderable_colour(&renderables, entity),
glyph: renderable.glyph,
beatitude_status: beatitude_status,
name: name.name.clone(),
};
player_inventory player_inventory
.entry(unique_item) .entry(unique_item)
.and_modify(|slot| { .and_modify(|(_e, count)| {
slot.count += 1; *count += 1;
}) })
.or_insert(InventorySlot { .or_insert((entity, 1));
item: entity,
count: 1,
idx: key.idx,
});
} }
// Get display args // Get display args
let width = get_max_inventory_width(&player_inventory); let width = get_max_inventory_width(&player_inventory);
@ -117,7 +128,7 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<
"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)); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK));
print_options(&gs.ecs, &player_inventory, x + 1, y + 1, ctx); print_options(&player_inventory, x + 1, y + 1, ctx);
// Input // Input
match ctx.key { match ctx.key {
None => (ItemMenuResult::NoResponse, None), None => (ItemMenuResult::NoResponse, None),
@ -125,17 +136,21 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option<
match key { match key {
VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None), VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None),
_ => { _ => {
let selection = letter_to_option::letter_to_option(key, ctx.shift); let selection = letter_to_option(key);
if selection != -1 && check_key(selection as usize) { if selection > -1 && selection < (count as i32) {
// Get the first entity with a Key {} component that has an idx matching "selection". let item = player_inventory
let entities = gs.ecs.entities(); .iter()
let keyed_items = gs.ecs.read_storage::<Key>(); .nth(selection as usize)
let backpack = gs.ecs.read_storage::<InBackpack>(); .unwrap().1.0;
for (e, key, _b) in (&entities, &keyed_items, &backpack).join() { gamelog::Logger
if key.idx == (selection as usize) { ::new()
return (ItemMenuResult::Selected, Some(e)); .append("You decurse the")
} .colour(item_colour_ecs(&gs.ecs, item))
} .append_n(obfuscate_name_ecs(&gs.ecs, item).0)
.colour(WHITE)
.append("!")
.log();
return (ItemMenuResult::Selected, Some(item));
} }
(ItemMenuResult::NoResponse, None) (ItemMenuResult::NoResponse, None)
} }

View file

@ -12,6 +12,7 @@ use super::{
}; };
use crate::TileType; use crate::TileType;
use crate::data::ids::*; use crate::data::ids::*;
use crate::data::prelude::*;
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use specs::prelude::*; use specs::prelude::*;
@ -45,6 +46,7 @@ impl Tooltip {
return (self.lines.len() as i32) + 2i32; return (self.lines.len() as i32) + 2i32;
} }
fn render(&self, ctx: &mut BTerm, x: i32, y: i32) { fn render(&self, ctx: &mut BTerm, x: i32, y: i32) {
ctx.set_active_console(TEXT_LAYER);
ctx.draw_box( ctx.draw_box(
x, x,
y, y,
@ -56,6 +58,7 @@ impl Tooltip {
for (i, s) in self.lines.iter().enumerate() { 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);
} }
ctx.set_active_console(TILE_LAYER);
} }
} }
@ -111,12 +114,6 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) {
if position.x == mouse_pos_adjusted.0 && position.y == mouse_pos_adjusted.1 { if position.x == mouse_pos_adjusted.0 && position.y == mouse_pos_adjusted.1 {
let mut tip = Tooltip::new(); let mut tip = Tooltip::new();
tip.add(crate::gui::obfuscate_name_ecs(ecs, entity).0, renderable.fg); tip.add(crate::gui::obfuscate_name_ecs(ecs, entity).0, renderable.fg);
let intrinsics = ecs.read_storage::<crate::components::Intrinsics>();
if let Some(intrinsics) = intrinsics.get(entity) {
if !intrinsics.list.is_empty() {
tip.add(intrinsics.describe(), RGB::named(WHITE));
}
}
// Attributes // Attributes
let attr = attributes.get(entity); let attr = attributes.get(entity);
if let Some(a) = attr { if let Some(a) = attr {
@ -175,13 +172,15 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) {
if mouse_pos.0 > 35 { if mouse_pos.0 > 35 {
// Render to the left // Render to the left
arrow = to_cp437('→'); arrow = to_cp437('→');
arrow_x = mouse_pos.0 - 1; arrow_x = mouse_pos.0 * 2 - 1;
} else { } else {
// Render to the right // Render to the right
arrow = to_cp437('←'); arrow = to_cp437('←');
arrow_x = mouse_pos.0 + 1; arrow_x = (mouse_pos.0 + 1) * 2;
} }
ctx.set_active_console(TEXT_LAYER);
ctx.set(arrow_x, arrow_y, white, RGB::named(BLACK), arrow); ctx.set(arrow_x, arrow_y, white, RGB::named(BLACK), arrow);
ctx.set_active_console(TILE_LAYER);
let mut total_height = 0; let mut total_height = 0;
for t in tooltips.iter() { for t in tooltips.iter() {
@ -195,9 +194,9 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) {
for t in tooltips.iter() { for t in tooltips.iter() {
let x = if mouse_pos.0 > 35 { let x = if mouse_pos.0 > 35 {
mouse_pos.0 - (1 + t.width()) (mouse_pos.0 * 2) - (1 + t.width())
} else { } else {
mouse_pos.0 + (1 + 1) (mouse_pos.0 * 2) + 2 + 1
}; };
t.render(ctx, x, y); t.render(ctx, x, y);
y += t.height(); y += t.height();

View file

@ -12,7 +12,6 @@ use crate::{
ObfuscatedName, ObfuscatedName,
Position, Position,
WantsToPickupItem, WantsToPickupItem,
WantsToAssignKey,
}; };
use specs::prelude::*; use specs::prelude::*;
use crate::data::messages; use crate::data::messages;
@ -34,7 +33,6 @@ impl<'a> System<'a> for ItemCollectionSystem {
ReadStorage<'a, Beatitude>, ReadStorage<'a, Beatitude>,
ReadExpect<'a, MasterDungeonMap>, ReadExpect<'a, MasterDungeonMap>,
ReadStorage<'a, Charges>, ReadStorage<'a, Charges>,
ReadStorage<'a, WantsToAssignKey>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
@ -50,11 +48,17 @@ impl<'a> System<'a> for ItemCollectionSystem {
beatitudes, beatitudes,
dm, dm,
wands, wands,
wants_key,
) = data; ) = data;
let mut to_remove: Vec<Entity> = Vec::new();
// For every item that wants to be picked up that *isn't* waiting on a key assignment. for pickup in wants_pickup.join() {
for (pickup, _key) in (&wants_pickup, !&wants_key).join() { positions.remove(pickup.item);
backpack
.insert(pickup.item, InBackpack { owner: pickup.collected_by })
.expect("Unable to pickup item.");
equipment_changed
.insert(pickup.collected_by, EquipmentChanged {})
.expect("Unable to insert EquipmentChanged.");
if pickup.collected_by == *player_entity { if pickup.collected_by == *player_entity {
gamelog::Logger gamelog::Logger
::new() ::new()
@ -78,17 +82,8 @@ impl<'a> System<'a> for ItemCollectionSystem {
.period() .period()
.log(); .log();
} }
positions.remove(pickup.item);
backpack
.insert(pickup.item, InBackpack { owner: pickup.collected_by })
.expect("Unable to pickup item");
equipment_changed
.insert(pickup.collected_by, EquipmentChanged {})
.expect("Unable to insert EquipmentChanged");
to_remove.push(pickup.collected_by);
}
for item in to_remove.iter() {
wants_pickup.remove(*item);
} }
wants_pickup.clear();
} }
} }

View file

@ -12,7 +12,6 @@ use crate::{
ObfuscatedName, ObfuscatedName,
Position, Position,
WantsToDropItem, WantsToDropItem,
WantsToRemoveKey,
}; };
use specs::prelude::*; use specs::prelude::*;
use crate::data::messages; use crate::data::messages;
@ -35,7 +34,6 @@ impl<'a> System<'a> for ItemDropSystem {
ReadStorage<'a, ObfuscatedName>, ReadStorage<'a, ObfuscatedName>,
ReadExpect<'a, MasterDungeonMap>, ReadExpect<'a, MasterDungeonMap>,
ReadStorage<'a, Charges>, ReadStorage<'a, Charges>,
WriteStorage<'a, WantsToRemoveKey>,
); );
fn run(&mut self, data: Self::SystemData) { fn run(&mut self, data: Self::SystemData) {
@ -52,7 +50,6 @@ impl<'a> System<'a> for ItemDropSystem {
obfuscated_names, obfuscated_names,
dm, dm,
wands, wands,
mut keys,
) = data; ) = data;
for (entity, to_drop) in (&entities, &wants_drop).join() { for (entity, to_drop) in (&entities, &wants_drop).join() {
@ -71,9 +68,6 @@ impl<'a> System<'a> for ItemDropSystem {
backpack.remove(to_drop.item); backpack.remove(to_drop.item);
if entity == *player_entity { if entity == *player_entity {
keys.insert(to_drop.item, WantsToRemoveKey {}).expect(
"Unable to insert WantsToRemoveKey"
);
gamelog::Logger gamelog::Logger
::new() ::new()
.append(messages::YOU_DROP_ITEM) .append(messages::YOU_DROP_ITEM)

View file

@ -1,153 +0,0 @@
use crate::{
gamelog,
gui::unique,
Beatitude,
Charges,
MagicItem,
MasterDungeonMap,
Name,
ObfuscatedName,
Stackable,
Renderable,
WantsToAssignKey,
WantsToRemoveKey,
Key,
};
use specs::prelude::*;
use crate::data::messages;
use bracket_lib::prelude::*;
use crate::invkeys::*;
pub struct KeyHandling {}
const DEBUG_KEYHANDLING: bool = true;
impl<'a> System<'a> for KeyHandling {
#[allow(clippy::type_complexity)]
type SystemData = (
Entities<'a>,
WriteStorage<'a, WantsToAssignKey>,
WriteStorage<'a, WantsToRemoveKey>,
WriteStorage<'a, Key>,
ReadStorage<'a, Stackable>,
ReadStorage<'a, Name>,
ReadStorage<'a, ObfuscatedName>,
ReadStorage<'a, Renderable>,
ReadStorage<'a, Beatitude>,
ReadStorage<'a, MagicItem>,
ReadStorage<'a, Charges>,
ReadExpect<'a, MasterDungeonMap>,
);
fn run(&mut self, data: Self::SystemData) {
let (
entities,
mut wants_keys,
mut wants_removekey,
mut keys,
stackable,
names,
obfuscated_names,
renderables,
beatitudes,
magic_items,
wands,
dm,
) = data;
// For every entity that wants to be picked up, that still needs a key assigned.
for (e, _wants_key) in (&entities, &wants_keys).join() {
if DEBUG_KEYHANDLING {
console::log(&format!("KEYHANDLING: Assigning key to {:?}", e));
}
let (stacks, mut handled, unique) = (
if let Some(_) = stackable.get(e) { true } else { false },
false,
unique(
e,
&names,
&obfuscated_names,
&renderables,
&beatitudes,
&magic_items,
Some(&wands),
&dm
),
);
if stacks {
console::log(&format!("KEYHANDLING: Item is stackable."));
let maybe_key = item_exists(&unique);
if maybe_key.is_some() {
console::log(&format!("KEYHANDLING: Existing stack found for this item."));
let key = maybe_key.unwrap();
keys.insert(e, Key { idx: key }).expect("Unable to insert Key.");
console::log(&format!("KEYHANDLING: Assigned key idx {} to item.", key));
handled = true;
}
}
if !handled {
console::log(
&format!("KEYHANDLING: Item is not stackable, or no existing stack found.")
);
if let Some(idx) = assign_next_available() {
console::log(
&format!("KEYHANDLING: Assigned next available index {} to item.", idx)
);
keys.insert(e, Key { idx }).expect("Unable to insert Key.");
register_stackable(stacks, unique, idx);
} else {
console::log(&format!("KEYHANDLING: No more keys available."));
gamelog::Logger
::new()
.append(messages::NO_MORE_KEYS)
.colour(WHITE)
.period()
.log();
}
}
}
for (e, _wants_key) in (&entities, &wants_removekey).join() {
let idx = keys.get(e).unwrap().idx;
if DEBUG_KEYHANDLING {
console::log(&format!("KEYHANDLING: Removing key from {:?}", e));
}
// If the item is *not* stackable, then we can just remove the key and clear the index.
if let None = stackable.get(e) {
console::log(
&format!("KEYHANDLING: Item is not stackable, clearing index {}.", idx)
);
clear_idx(idx);
keys.remove(e);
continue;
}
// If the item *is* stackable, then we need to check if there are any other items that
// share this key assignment, before clearing the index.
console::log(
&format!(
"KEYHANDLING: Item is stackable, checking if any other items share this key."
)
);
let mut sole_item_with_key = true;
for (entity, key) in (&entities, &keys).join() {
if entity != e && key.idx == idx {
console::log(&format!("KEYHANDLING: Another item shares index {}", idx));
sole_item_with_key = false;
break;
}
}
// If no other items shared this key, free up the index.
if sole_item_with_key {
console::log(
&format!("KEYHANDLING: No other items found, clearing index {}.", idx)
);
clear_idx(idx);
}
// Either way, remove the key component from this item, because we're dropping it.
console::log(&format!("KEYHANDLING: Removing key component from item."));
keys.remove(e);
}
wants_removekey.clear();
wants_keys.clear();
}
}

View file

@ -4,7 +4,6 @@ mod equip_system;
mod identification_system; mod identification_system;
mod remove_system; mod remove_system;
mod use_system; mod use_system;
mod keyhandling;
pub use self::{ pub use self::{
collection_system::ItemCollectionSystem, collection_system::ItemCollectionSystem,
@ -13,5 +12,4 @@ pub use self::{
identification_system::ItemIdentificationSystem, identification_system::ItemIdentificationSystem,
remove_system::ItemRemoveSystem, remove_system::ItemRemoveSystem,
use_system::ItemUseSystem, use_system::ItemUseSystem,
keyhandling::KeyHandling,
}; };

View file

@ -1,59 +0,0 @@
use std::sync::Mutex;
use std::collections::HashMap;
use crate::gui::UniqueInventoryItem;
lazy_static! {
pub static ref INVKEYS: Mutex<HashMap<UniqueInventoryItem, usize>> = Mutex::new(HashMap::new());
pub static ref ASSIGNEDKEYS: Mutex<Vec<bool>> = Mutex::new(vec![false; 52]);
}
/// For (de)serialization.
pub fn clone_invkeys() -> HashMap<UniqueInventoryItem, usize> {
let invkeys = INVKEYS.lock().unwrap();
invkeys.clone()
}
pub fn restore_invkeys(invkeys: HashMap<UniqueInventoryItem, usize>) {
INVKEYS.lock().unwrap().clear();
INVKEYS.lock().unwrap().extend(invkeys);
}
pub fn check_key(idx: usize) -> bool {
let lock = ASSIGNEDKEYS.lock().unwrap();
lock[idx]
}
pub fn item_exists(item: &UniqueInventoryItem) -> Option<usize> {
let invkeys = INVKEYS.lock().unwrap();
use bracket_lib::prelude::*;
console::log(&format!("{:?}", item));
if invkeys.contains_key(item) {
Some(*invkeys.get(item).unwrap())
} else {
None
}
}
pub fn assign_next_available() -> Option<usize> {
let mut lock = ASSIGNEDKEYS.lock().unwrap();
for (i, key) in lock.iter_mut().enumerate() {
if !*key {
*key = true;
return Some(i);
}
}
None
}
pub fn register_stackable(stacks: bool, item: UniqueInventoryItem, idx: usize) {
if stacks {
let mut invkeys = INVKEYS.lock().unwrap();
invkeys.insert(item, idx);
}
}
pub fn clear_idx(idx: usize) {
let mut lock = ASSIGNEDKEYS.lock().unwrap();
lock[idx] = false;
let mut invkeys = INVKEYS.lock().unwrap();
invkeys.retain(|_k, v| *v != idx);
}

View file

@ -8,9 +8,6 @@ extern crate serde;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
pub mod macros;
pub mod camera; pub mod camera;
pub mod components; pub mod components;
pub mod raws; pub mod raws;
@ -38,7 +35,6 @@ pub mod rex_assets;
pub mod spatial; pub mod spatial;
pub mod morgue; pub mod morgue;
pub mod states; pub mod states;
pub mod invkeys;
pub use components::*; pub use components::*;
use particle_system::ParticleBuilder; use particle_system::ParticleBuilder;

View file

@ -1,93 +0,0 @@
// macros/mod.rs
#[macro_export]
/// Used to check if the player has a given component.
macro_rules! player_has_component {
($ecs:expr, $component:ty) => {
{
let player = $ecs.fetch::<Entity>();
let component = $ecs.read_storage::<$component>();
if let Some(player_component) = component.get(*player) {
true
} else {
false
}
}
};
}
#[macro_export]
/// Used to check if a given entity has a given Intrinsic.
macro_rules! has {
($ecs:expr, $entity:expr, $intrinsic:expr) => {
{
let intrinsics = $ecs.read_storage::<crate::Intrinsics>();
if let Some(has_intrinsics) = intrinsics.get($entity) {
has_intrinsics.list.contains(&$intrinsic)
} else {
false
}
}
};
}
#[macro_export]
/// Used to check if the player has a given Intrinsic.
macro_rules! player_has {
($ecs:expr, $intrinsic:expr) => {
{
let player = $ecs.fetch::<Entity>();
let intrinsics = $ecs.read_storage::<crate::Intrinsics>();
if let Some(player_intrinsics) = intrinsics.get(*player) {
player_intrinsics.list.contains(&$intrinsic)
} else {
false
}
}
};
}
#[macro_export]
/// Handles adding an Intrinsic to the player, and adding it to the IntrinsicChanged component.
macro_rules! add_intr {
($ecs:expr, $entity:expr, $intrinsic:expr) => {
{
let mut intrinsics = $ecs.write_storage::<crate::Intrinsics>();
if let Some(player_intrinsics) = intrinsics.get_mut($entity) {
if !player_intrinsics.list.contains(&$intrinsic) {
player_intrinsics.list.insert($intrinsic);
let mut intrinsic_changed = $ecs.write_storage::<crate::IntrinsicChanged>();
if let Some(this_intrinsic_changed) = intrinsic_changed.get_mut($entity) {
this_intrinsic_changed.gained.insert($intrinsic);
} else {
intrinsic_changed.insert($entity, crate::IntrinsicChanged {
gained: {
let mut m = std::collections::HashSet::new();
m.insert($intrinsic);
m
},
lost: std::collections::HashSet::new()
}).expect("Failed to insert IntrinsicChanged component.");
}
}
} else {
intrinsics.insert($entity, crate::Intrinsics {
list: {
let mut m = std::collections::HashSet::new();
m.insert($intrinsic);
m
}
}).expect("Failed to insert Intrinsics component.");
let mut intrinsic_changed = $ecs.write_storage::<crate::IntrinsicChanged>();
intrinsic_changed.insert($entity, crate::IntrinsicChanged {
gained: {
let mut m = std::collections::HashSet::new();
m.insert($intrinsic);
m
},
lost: std::collections::HashSet::new()
}).expect("Failed to insert IntrinsicChanged component.");
}
}
};
}

View file

@ -3,22 +3,43 @@ use specs::prelude::*;
use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator }; use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
const DISPLAYWIDTH: i32 = 105; const DISPLAYWIDTH: i32 = 100;
const DISPLAYHEIGHT: i32 = 56; const DISPLAYHEIGHT: i32 = 56;
fn main() -> BError { fn main() -> BError {
// Embedded resources for use in wasm build // Embedded resources for use in wasm build
const CURSES_14_16_BYTES: &[u8] = include_bytes!("../resources/curses14x16.png"); {
EMBED.lock().add_resource("resources/curses14x16.png".to_string(), CURSES_14_16_BYTES); const WORLD_16_16_BYTES: &[u8] = include_bytes!("../resources/world16x16.png");
const CURSES_16_16_BYTES: &[u8] = include_bytes!("../resources/curses16x16.png");
const CURSES_8_16_BYTES: &[u8] = include_bytes!("../resources/curses8x16.png");
const SINGLE_1_1_BYTES: &[u8] = include_bytes!("../resources/healthbar22x2.png");
let mut lock = bracket_lib::terminal::EMBED.lock();
lock.add_resource("resources/world16x16.png".to_string(), WORLD_16_16_BYTES);
lock.add_resource("resources/curses16x16.png".to_string(), CURSES_16_16_BYTES);
lock.add_resource("resources/curses8x16.png".to_string(), CURSES_8_16_BYTES);
lock.add_resource("resources/healthbar22x2.png".to_string(), SINGLE_1_1_BYTES);
}
//link_resource!(CURSES14X16, "../resources/curses_14x16.png"); let world_sheet = SpriteSheet {
filename: "resources/world16x16.png".to_string(),
sprites: register_spritesheet(16, 16, 19, 16),
backing: None,
};
let mut context = BTermBuilder::new() let mut context = BTermBuilder::new()
.with_title("rust-rl") .with_title("rust-rl")
.with_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT) .with_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT)
.with_font("curses14x16.png", 14, 16) .with_font("curses16x16.png", 16, 16)
.with_tile_dimensions(14, 16) .with_font("curses8x16.png", 8, 16)
.with_simple_console(DISPLAYWIDTH, DISPLAYHEIGHT, "curses14x16.png") .with_font("healthbar22x2.png", 1, 1)
.with_tile_dimensions(16, 16)
.with_gutter(2)
.with_sprite_console(DISPLAYWIDTH * 16, DISPLAYHEIGHT * 16, 0)
.with_sprite_sheet(world_sheet)
.with_simple_console_no_bg(DISPLAYWIDTH, DISPLAYHEIGHT, "curses16x16.png")
.with_simple_console_no_bg(DISPLAYWIDTH, DISPLAYHEIGHT, "curses16x16.png")
.with_sparse_console(DISPLAYWIDTH * 2, DISPLAYHEIGHT, "curses8x16.png")
.with_sparse_console(DISPLAYWIDTH * 16, DISPLAYHEIGHT * 16, "healthbar22x2.png")
.build()?; .build()?;
if config::CONFIG.visuals.with_scanlines { if config::CONFIG.visuals.with_scanlines {
context.with_post_scanlines(config::CONFIG.visuals.with_screen_burn); context.with_post_scanlines(config::CONFIG.visuals.with_screen_burn);
@ -111,12 +132,6 @@ fn main() -> BError {
gs.ecs.register::<SpawnParticleLine>(); gs.ecs.register::<SpawnParticleLine>();
gs.ecs.register::<HasDamageModifiers>(); gs.ecs.register::<HasDamageModifiers>();
gs.ecs.register::<Intrinsics>(); gs.ecs.register::<Intrinsics>();
gs.ecs.register::<IntrinsicChanged>();
gs.ecs.register::<Stackable>();
gs.ecs.register::<WantsToAssignKey>();
gs.ecs.register::<Key>();
gs.ecs.register::<WantsToRemoveKey>();
gs.ecs.register::<WantsToDelete>();
gs.ecs.register::<SimpleMarker<SerializeMe>>(); gs.ecs.register::<SimpleMarker<SerializeMe>>();
gs.ecs.register::<SerializationHelper>(); gs.ecs.register::<SerializationHelper>();
gs.ecs.register::<DMSerializationHelper>(); gs.ecs.register::<DMSerializationHelper>();
@ -142,3 +157,15 @@ fn main() -> BError {
main_loop(context, gs) main_loop(context, gs)
} }
fn register_spritesheet(width: i32, height: i32, rows: i32, columns: i32) -> Vec<Sprite> {
let mut sprites: Vec<Sprite> = Vec::new();
for y in 0..rows {
for x in 0..columns {
sprites.push(
Sprite::new(Rect::with_size(x * width + 1, y * height + 1, width, height))
);
}
}
sprites
}

View file

@ -112,26 +112,7 @@ fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String {
return name; return name;
} }
const POTION_COLOURS: &[&str] = &[ const POTION_COLOURS: &[&str] = &["blue", "red", "green", "yellow", "black"];
"red",
"orange",
"yellow",
"green",
"blue",
"indigo",
"violet",
"black",
"white",
"silver",
"gold",
"rainbow",
"blood",
"purple",
"cyan",
"brown",
"grey",
"octarine",
];
const POTION_ADJECTIVES: &[&str] = &[ const POTION_ADJECTIVES: &[&str] = &[
"swirling", "swirling",
"viscous", "viscous",

View file

@ -2,7 +2,15 @@ use bracket_lib::prelude::*;
use serde::{ Deserialize, Serialize }; use serde::{ Deserialize, Serialize };
use std::collections::{ HashSet, HashMap }; use std::collections::{ HashSet, HashMap };
mod tiletype; mod tiletype;
pub use tiletype::{ tile_cost, tile_opaque, tile_walkable, TileType, get_dest, Destination }; pub use tiletype::{
tile_cost,
tile_opaque,
tile_walkable,
tile_blocks_telepathy,
TileType,
get_dest,
Destination,
};
mod interval_spawning_system; mod interval_spawning_system;
pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval }; pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval };
pub mod dungeon; pub mod dungeon;

View file

@ -5,6 +5,22 @@ use crate::data::ids::*;
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use std::ops::{ Add, Mul }; use std::ops::{ Add, Mul };
pub fn get_sprite_for_id(idx: usize, map: &Map, other_pos: Option<Point>) -> (usize, RGBA) {
let x = (idx as i32) % map.width;
let y = (idx as i32) / map.width;
let tile = map.tiles[idx];
let base = match tile {
TileType::Wall => wall_sprite(tile.sprite(), map, x, y),
_ => tile.sprite(),
};
let sprite_id = pick_variant(base, tile.variants(), idx, map);
let tint = if !map.visible_tiles[idx] {
RGBA::from_f32(0.75, 0.75, 0.75, 1.0)
} else {
RGBA::named(WHITE)
};
return (sprite_id, tint);
}
/// Gets the renderables for a tile, with darkening/offset/post-processing/etc. Passing a val for "debug" will ignore viewshed. /// Gets the renderables for a tile, with darkening/offset/post-processing/etc. Passing a val for "debug" will ignore viewshed.
pub fn get_tile_renderables_for_id( pub fn get_tile_renderables_for_id(
idx: usize, idx: usize,
@ -142,6 +158,20 @@ fn is_revealed_and_wall(map: &Map, x: i32, y: i32, debug: Option<bool>) -> bool
(if debug.is_none() { map.revealed_tiles[idx] } else { true }) (if debug.is_none() { map.revealed_tiles[idx] } else { true })
} }
fn wall_sprite(id: usize, map: &Map, x: i32, y: i32) -> usize {
if y > map.height - (2 as i32) {
return id;
}
if is_revealed_and_wall(map, x, y + 1, None) {
return id + 6;
}
return id;
}
fn pick_variant(base: usize, variants: usize, idx: usize, map: &Map) -> usize {
return base + ((map.colour_offset[idx].0.0 * (variants as f32)) as usize);
}
fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> FontCharType { fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option<bool>) -> FontCharType {
if if
x < 1 || x < 1 ||

View file

@ -1,4 +1,5 @@
use serde::{ Deserialize, Serialize }; use serde::{ Deserialize, Serialize };
use crate::data::sprites::*;
#[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug)] #[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug)]
pub enum TileType { pub enum TileType {
@ -27,9 +28,64 @@ pub enum TileType {
ToOvermap(i32), ToOvermap(i32),
ToLocal(i32), ToLocal(i32),
} }
impl TileType {
pub fn sprite(&self) -> usize {
match self {
TileType::ImpassableMountain => STATUE,
TileType::Wall => WALL_BASE,
TileType::DeepWater => WATER_DEEP,
TileType::Fence => WALL_BASE,
TileType::Bars => WALL_BASE,
TileType::Floor => FLOOR,
TileType::WoodFloor => FLOOR_WOOD,
TileType::Gravel => FLOOR,
TileType::Road => PATH_GRASS,
TileType::Grass => FLOOR_GRASS,
TileType::Foliage => FLOOR_GRASS,
TileType::HeavyFoliage => FLOOR_GRASS,
TileType::Sand => FLOOR,
TileType::ShallowWater => WATER_DEEP,
TileType::Bridge => FLOOR,
TileType::DownStair => STAIR_D,
TileType::UpStair => STAIR_A,
TileType::ToLocal(_) => MUSHROOM,
TileType::ToOvermap(_) => MUSHROOM_ORANGE,
}
}
pub fn variants(&self) -> usize {
match self {
TileType::ImpassableMountain => 1,
TileType::Wall => 4,
TileType::DeepWater => 2,
TileType::Fence => 1,
TileType::Bars => 1,
TileType::Floor => 6,
TileType::WoodFloor => 3,
TileType::Gravel => 1,
TileType::Road => 4,
TileType::Grass => 6,
TileType::Foliage => 1,
TileType::HeavyFoliage => 1,
TileType::Sand => 1,
TileType::ShallowWater => 2,
TileType::Bridge => 1,
TileType::DownStair => 1,
TileType::UpStair => 1,
TileType::ToLocal(_) => 1,
TileType::ToOvermap(_) => 1,
}
}
}
pub fn tile_walkable(tt: TileType) -> bool { pub fn tile_walkable(tt: TileType) -> bool {
match tt { match tt {
TileType::ImpassableMountain | TileType::Wall | TileType::DeepWater | TileType::Fence | TileType::Bars => false, | TileType::ImpassableMountain
| TileType::Wall
| TileType::DeepWater
| TileType::Fence
| TileType::Bars => false,
_ => true, _ => true,
} }
} }
@ -40,6 +96,11 @@ pub fn tile_opaque(tt: TileType) -> bool {
_ => false, _ => false,
} }
} }
pub fn tile_blocks_telepathy(tt: TileType) -> bool {
match tt {
_ => false,
}
}
pub fn tile_cost(tt: TileType) -> f32 { pub fn tile_cost(tt: TileType) -> f32 {
match tt { match tt {
TileType::Road => 0.75, TileType::Road => 0.75,

View file

@ -81,6 +81,7 @@ fn create_delayed_particles(ecs: &mut World, ctx: &BTerm) {
.expect("Could not insert position"); .expect("Could not insert position");
renderables renderables
.insert(p, Renderable { .insert(p, Renderable {
sprite: None, // TODO: Particle sprite
fg: handled.fg, fg: handled.fg,
bg: handled.bg, bg: handled.bg,
glyph: handled.glyph, glyph: handled.glyph,
@ -306,6 +307,7 @@ impl<'a> System<'a> for ParticleSpawnSystem {
.expect("Could not insert position"); .expect("Could not insert position");
renderables renderables
.insert(p, Renderable { .insert(p, Renderable {
sprite: None, // TODO: Particle sprite
fg: new_particle.fg, fg: new_particle.fg,
bg: new_particle.bg, bg: new_particle.bg,
glyph: new_particle.glyph, glyph: new_particle.glyph,

View file

@ -30,7 +30,6 @@ use super::{
Viewshed, Viewshed,
WantsToMelee, WantsToMelee,
WantsToPickupItem, WantsToPickupItem,
WantsToAssignKey,
get_dest, get_dest,
Destination, Destination,
DamageType, DamageType,
@ -40,6 +39,7 @@ use specs::prelude::*;
use std::cmp::{ max, min }; use std::cmp::{ max, min };
use crate::data::events::*; use crate::data::events::*;
use crate::data::ids::*; use crate::data::ids::*;
use crate::gui::with_article;
pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut positions = ecs.write_storage::<Position>(); let mut positions = ecs.write_storage::<Position>();
@ -134,6 +134,7 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut renderables = ecs.write_storage::<Renderable>(); let mut renderables = ecs.write_storage::<Renderable>();
let render_data = renderables.get_mut(potential_target).unwrap(); let render_data = renderables.get_mut(potential_target).unwrap();
render_data.glyph = to_cp437('+'); // Nethack open door, maybe just use '/' instead. render_data.glyph = to_cp437('+'); // Nethack open door, maybe just use '/' instead.
render_data.sprite = Some(17); // TODO: Enum
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
} }
result = RunState::Ticking; result = RunState::Ticking;
@ -231,6 +232,7 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
let mut renderables = ecs.write_storage::<Renderable>(); let mut renderables = ecs.write_storage::<Renderable>();
let render_data = renderables.get_mut(potential_target).unwrap(); let render_data = renderables.get_mut(potential_target).unwrap();
render_data.glyph = to_cp437('▓'); // Nethack open door, maybe just use '/' instead. render_data.glyph = to_cp437('▓'); // Nethack open door, maybe just use '/' instead.
render_data.sprite = Some(18); // TODO: Enum
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
} }
result = RunState::Ticking; result = RunState::Ticking;
@ -561,11 +563,11 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState
let mut logger = gamelog::Logger::new().append("You see"); let mut logger = gamelog::Logger::new().append("You see");
for i in 0..seen_items.len() { for i in 0..seen_items.len() {
if i > 0 && i < seen_items.len() { if i > 0 && i < seen_items.len() {
logger = logger.append(", a"); logger = logger.append(", ");
} }
logger = logger logger = logger
.colour(seen_items[i].1) .colour(seen_items[i].1)
.append_n(&seen_items[i].0) .append_n(with_article(&seen_items[i].0))
.colour(WHITE); .colour(WHITE);
} }
logger.period().log(); logger.period().log();
@ -634,9 +636,7 @@ fn get_item(ecs: &mut World) -> RunState {
return RunState::AwaitingInput; return RunState::AwaitingInput;
} }
Some(item) => { Some(item) => {
let mut assignkey = ecs.write_storage::<WantsToAssignKey>();
let mut pickup = ecs.write_storage::<WantsToPickupItem>(); let mut pickup = ecs.write_storage::<WantsToPickupItem>();
assignkey.insert(item, WantsToAssignKey {}).expect("Unable to insert WantsToAssignKey");
pickup pickup
.insert(*player_entity, WantsToPickupItem { collected_by: *player_entity, item }) .insert(*player_entity, WantsToPickupItem { collected_by: *player_entity, item })
.expect("Unable to insert want to pickup item."); .expect("Unable to insert want to pickup item.");

View file

@ -6,7 +6,6 @@ pub struct Item {
pub id: String, pub id: String,
pub name: Name, pub name: Name,
pub renderable: Option<Renderable>, pub renderable: Option<Renderable>,
pub class: String,
pub weight: Option<f32>, pub weight: Option<f32>,
pub value: Option<f32>, pub value: Option<f32>,
pub equip: Option<Equippable>, pub equip: Option<Equippable>,
@ -31,6 +30,7 @@ pub struct Equippable {
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Renderable { pub struct Renderable {
pub glyph: String, pub glyph: String,
pub sprite: Option<usize>,
pub fg: String, pub fg: String,
pub bg: String, pub bg: String,
pub order: i32, pub order: i32,

View file

@ -66,7 +66,6 @@ macro_rules! apply_flags {
"IDENTIFY" => $eb = $eb.with(ProvidesIdentify {}), "IDENTIFY" => $eb = $eb.with(ProvidesIdentify {}),
"DIGGER" => $eb = $eb.with(Digger {}), "DIGGER" => $eb = $eb.with(Digger {}),
"MAGICMAP" => $eb = $eb.with(MagicMapper {}), "MAGICMAP" => $eb = $eb.with(MagicMapper {}),
"STACKABLE" => $eb = $eb.with(Stackable {}),
// CAN BE DESTROYED BY DAMAGE // CAN BE DESTROYED BY DAMAGE
"DESTRUCTIBLE" => $eb = $eb.with(Destructible {}), "DESTRUCTIBLE" => $eb = $eb.with(Destructible {}),
// --- EQUIP SLOTS --- // --- EQUIP SLOTS ---
@ -282,7 +281,6 @@ pub fn spawn_named_item(
if known_beatitude && !identified_items.contains(&item_template.name.name) { if known_beatitude && !identified_items.contains(&item_template.name.name) {
dm.identified_items.insert(item_template.name.name.clone()); dm.identified_items.insert(item_template.name.name.clone());
} }
let needs_key = is_player_owned(&player_entity, &pos);
std::mem::drop(player_entity); std::mem::drop(player_entity);
std::mem::drop(dm); std::mem::drop(dm);
// -- DROP EVERYTHING THAT INVOLVES THE ECS BEFORE THIS POINT --- // -- DROP EVERYTHING THAT INVOLVES THE ECS BEFORE THIS POINT ---
@ -295,23 +293,9 @@ pub fn spawn_named_item(
eb = eb.with(Item { eb = eb.with(Item {
weight: item_template.weight.unwrap_or(0.0), weight: item_template.weight.unwrap_or(0.0),
value: item_template.value.unwrap_or(0.0), value: item_template.value.unwrap_or(0.0),
category: match item_template.class.as_str() {
"amulet" => ItemType::Amulet,
"weapon" => ItemType::Weapon,
"armour" => ItemType::Armour,
"comestible" => ItemType::Comestible,
"scroll" => ItemType::Scroll,
"spellbook" => ItemType::Spellbook,
"potion" => ItemType::Potion,
"ring" => ItemType::Ring,
"wand" => ItemType::Wand,
_ => unreachable!("Unknown item type."),
},
}); });
eb = spawn_position(pos, eb, key, raws); eb = spawn_position(pos, eb, key, raws);
if needs_key {
eb = eb.with(WantsToAssignKey {});
}
if let Some(renderable) = &item_template.renderable { if let Some(renderable) = &item_template.renderable {
eb = eb.with(get_renderable_component(renderable)); eb = eb.with(get_renderable_component(renderable));
} }
@ -408,7 +392,6 @@ pub fn spawn_named_mob(
if raws.mob_index.contains_key(key) { if raws.mob_index.contains_key(key) {
let mob_template = &raws.raws.mobs[raws.mob_index[key]]; let mob_template = &raws.raws.mobs[raws.mob_index[key]];
let mut player_level = 1; let mut player_level = 1;
let needs_key;
{ {
let pools = ecs.read_storage::<Pools>(); let pools = ecs.read_storage::<Pools>();
let player_entity = ecs.fetch::<Entity>(); let player_entity = ecs.fetch::<Entity>();
@ -416,15 +399,12 @@ pub fn spawn_named_mob(
if let Some(pool) = player_pool { if let Some(pool) = player_pool {
player_level = pool.level; player_level = pool.level;
} }
needs_key = is_player_owned(&player_entity, &pos);
} }
let mut eb; let mut eb;
// New entity with a position, name, combatstats, and viewshed // New entity with a position, name, combatstats, and viewshed
eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>(); eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
eb = spawn_position(pos, eb, key, raws); eb = spawn_position(pos, eb, key, raws);
if needs_key {
eb = eb.with(WantsToAssignKey {});
}
eb = eb.with(Name { name: mob_template.name.clone(), plural: mob_template.name.clone() }); eb = eb.with(Name { name: mob_template.name.clone(), plural: mob_template.name.clone() });
eb = eb.with(Viewshed { eb = eb.with(Viewshed {
visible_tiles: Vec::new(), visible_tiles: Vec::new(),
@ -652,18 +632,10 @@ pub fn spawn_named_prop(
pos: SpawnType pos: SpawnType
) -> Option<Entity> { ) -> Option<Entity> {
if raws.prop_index.contains_key(key) { if raws.prop_index.contains_key(key) {
let needs_key;
{
let player_entity = ecs.fetch::<Entity>();
needs_key = is_player_owned(&player_entity, &pos);
}
// ENTITY BUILDER PREP // ENTITY BUILDER PREP
let prop_template = &raws.raws.props[raws.prop_index[key]]; let prop_template = &raws.raws.props[raws.prop_index[key]];
let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>(); let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
eb = spawn_position(pos, eb, key, raws); eb = spawn_position(pos, eb, key, raws);
if needs_key {
eb = eb.with(WantsToAssignKey {});
}
// APPLY MANDATORY COMPONENTS FOR A PROP: // APPLY MANDATORY COMPONENTS FOR A PROP:
// - Name // - Name
// - Prop {} // - Prop {}
@ -714,28 +686,16 @@ fn spawn_position<'a>(
eb eb
} }
fn is_player_owned(player: &Entity, pos: &SpawnType) -> bool {
match pos {
SpawnType::Carried { by } => {
if by == player {
return true;
}
}
SpawnType::Equipped { by } => {
if by == player {
return true;
}
}
_ => {}
}
false
}
fn get_renderable_component( fn get_renderable_component(
renderable: &super::item_structs::Renderable renderable: &super::item_structs::Renderable
) -> crate::components::Renderable { ) -> crate::components::Renderable {
crate::components::Renderable { crate::components::Renderable {
glyph: to_cp437(renderable.glyph.chars().next().unwrap()), glyph: to_cp437(renderable.glyph.chars().next().unwrap()),
sprite: if let Some(sprite) = &renderable.sprite {
Some(sprite.clone())
} else {
None
},
fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"), fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"), bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
render_order: renderable.order, render_order: renderable.order,

View file

@ -9,7 +9,6 @@ use specs::saveload::{
SimpleMarker, SimpleMarker,
SimpleMarkerAllocator, SimpleMarkerAllocator,
}; };
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;
@ -96,10 +95,8 @@ pub fn save_game(ecs: &mut World) {
IdentifiedItem, IdentifiedItem,
InBackpack, InBackpack,
InflictsDamage, InflictsDamage,
IntrinsicChanged,
Intrinsics, Intrinsics,
Item, Item,
Key,
KnownSpells, KnownSpells,
LootTable, LootTable,
MagicItem, MagicItem,
@ -129,21 +126,17 @@ pub fn save_game(ecs: &mut World) {
SpawnParticleBurst, SpawnParticleBurst,
SpawnParticleLine, SpawnParticleLine,
SpawnParticleSimple, SpawnParticleSimple,
Stackable,
TakingTurn, TakingTurn,
Telepath, Telepath,
ToHitBonus, ToHitBonus,
Viewshed, Viewshed,
Charges, Charges,
WantsToApproach, WantsToApproach,
WantsToAssignKey,
WantsToDelete,
WantsToDropItem, WantsToDropItem,
WantsToFlee, WantsToFlee,
WantsToMelee, WantsToMelee,
WantsToPickupItem, WantsToPickupItem,
WantsToRemoveItem, WantsToRemoveItem,
WantsToRemoveKey,
WantsToUseItem, WantsToUseItem,
SerializationHelper, SerializationHelper,
DMSerializationHelper DMSerializationHelper
@ -234,10 +227,8 @@ pub fn load_game(ecs: &mut World) {
IdentifiedItem, IdentifiedItem,
InBackpack, InBackpack,
InflictsDamage, InflictsDamage,
IntrinsicChanged,
Intrinsics, Intrinsics,
Item, Item,
Key,
KnownSpells, KnownSpells,
LootTable, LootTable,
MagicItem, MagicItem,
@ -267,21 +258,17 @@ pub fn load_game(ecs: &mut World) {
SpawnParticleBurst, SpawnParticleBurst,
SpawnParticleLine, SpawnParticleLine,
SpawnParticleSimple, SpawnParticleSimple,
Stackable,
TakingTurn, TakingTurn,
Telepath, Telepath,
ToHitBonus, ToHitBonus,
Viewshed, Viewshed,
Charges, Charges,
WantsToApproach, WantsToApproach,
WantsToAssignKey,
WantsToDelete,
WantsToDropItem, WantsToDropItem,
WantsToFlee, WantsToFlee,
WantsToMelee, WantsToMelee,
WantsToPickupItem, WantsToPickupItem,
WantsToRemoveItem, WantsToRemoveItem,
WantsToRemoveKey,
WantsToUseItem, WantsToUseItem,
SerializationHelper, SerializationHelper,
DMSerializationHelper DMSerializationHelper

View file

@ -54,6 +54,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
.with(BlocksTile {}) .with(BlocksTile {})
.with(Renderable { .with(Renderable {
glyph: to_cp437('@'), glyph: to_cp437('@'),
sprite: None, // TODO: Player sprite
fg: RGB::named(YELLOW), fg: RGB::named(YELLOW),
bg: RGB::named(BLACK), bg: RGB::named(BLACK),
render_order: 0, render_order: 0,

View file

@ -23,6 +23,7 @@ use crate::camera;
use crate::saveload_system; use crate::saveload_system;
use crate::morgue; use crate::morgue;
use crate::damage_system; use crate::damage_system;
use crate::data::prelude::*;
pub struct State { pub struct State {
pub ecs: World, pub ecs: World,
@ -64,13 +65,12 @@ impl State {
fn resolve_entity_decisions(&mut self) { fn resolve_entity_decisions(&mut self) {
let mut trigger_system = trigger_system::TriggerSystem {}; let mut trigger_system = trigger_system::TriggerSystem {};
let mut inventory_system = inventory::ItemCollectionSystem {};
let mut item_equip_system = inventory::ItemEquipSystem {}; let mut item_equip_system = inventory::ItemEquipSystem {};
let mut item_use_system = inventory::ItemUseSystem {}; let mut item_use_system = inventory::ItemUseSystem {};
let mut item_drop_system = inventory::ItemDropSystem {}; let mut item_drop_system = inventory::ItemDropSystem {};
let mut item_remove_system = inventory::ItemRemoveSystem {}; let mut item_remove_system = inventory::ItemRemoveSystem {};
let mut inventory_system = inventory::ItemCollectionSystem {};
let mut item_id_system = inventory::ItemIdentificationSystem {}; let mut item_id_system = inventory::ItemIdentificationSystem {};
let mut key_system = inventory::KeyHandling {};
let mut melee_system = MeleeCombatSystem {}; let mut melee_system = MeleeCombatSystem {};
trigger_system.run_now(&self.ecs); trigger_system.run_now(&self.ecs);
inventory_system.run_now(&self.ecs); inventory_system.run_now(&self.ecs);
@ -79,7 +79,6 @@ impl State {
item_drop_system.run_now(&self.ecs); item_drop_system.run_now(&self.ecs);
item_remove_system.run_now(&self.ecs); item_remove_system.run_now(&self.ecs);
item_id_system.run_now(&self.ecs); item_id_system.run_now(&self.ecs);
key_system.run_now(&self.ecs);
melee_system.run_now(&self.ecs); melee_system.run_now(&self.ecs);
effects::run_effects_queue(&mut self.ecs); effects::run_effects_queue(&mut self.ecs);
@ -166,6 +165,15 @@ impl GameState for State {
new_runstate = *runstate; new_runstate = *runstate;
} }
// Clear screen // Clear screen
ctx.set_active_console(0);
ctx.cls();
ctx.set_active_console(HP_BAR_LAYER);
ctx.cls();
ctx.set_active_console(TEXT_LAYER);
ctx.cls();
ctx.set_active_console(ENTITY_LAYER);
ctx.cls();
ctx.set_active_console(TILE_LAYER);
ctx.cls(); ctx.cls();
particle_system::particle_ticker(&mut self.ecs, ctx); particle_system::particle_ticker(&mut self.ecs, ctx);
@ -344,11 +352,7 @@ impl GameState for State {
gui::ItemMenuResult::NoResponse => {} gui::ItemMenuResult::NoResponse => {}
gui::ItemMenuResult::Selected => { gui::ItemMenuResult::Selected => {
let item_entity = result.1.unwrap(); let item_entity = result.1.unwrap();
let mut removekey = self.ecs.write_storage::<WantsToRemoveKey>();
let mut intent = self.ecs.write_storage::<WantsToDropItem>(); let mut intent = self.ecs.write_storage::<WantsToDropItem>();
removekey
.insert(item_entity, WantsToRemoveKey {})
.expect("Unable to insert WantsToRemoveKey");
intent intent
.insert(*self.ecs.fetch::<Entity>(), WantsToDropItem { .insert(*self.ecs.fetch::<Entity>(), WantsToDropItem {
item: item_entity, item: item_entity,
@ -565,6 +569,15 @@ impl GameState for State {
new_runstate = self.mapgen_next_state.unwrap(); new_runstate = self.mapgen_next_state.unwrap();
} }
if self.mapgen_history.len() != 0 { if self.mapgen_history.len() != 0 {
ctx.set_active_console(0);
ctx.cls();
ctx.set_active_console(HP_BAR_LAYER);
ctx.cls();
ctx.set_active_console(TEXT_LAYER);
ctx.cls();
ctx.set_active_console(ENTITY_LAYER);
ctx.cls();
ctx.set_active_console(TILE_LAYER);
ctx.cls(); ctx.cls();
camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx); camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx);

View file

@ -11,6 +11,7 @@ use super::{
Viewshed, Viewshed,
Renderable, Renderable,
gui::renderable_colour, gui::renderable_colour,
tile_blocks_telepathy,
}; };
use bracket_lib::prelude::*; use bracket_lib::prelude::*;
use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting; use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting;
@ -120,7 +121,7 @@ impl<'a> System<'a> for VisibilitySystem {
if let Some(_is_blind) = blind_entities.get(ent) { if let Some(_is_blind) = blind_entities.get(ent) {
range *= BLIND_TELEPATHY_RANGE_MULTIPLIER; range *= BLIND_TELEPATHY_RANGE_MULTIPLIER;
} }
telepath.telepath_tiles = fast_fov(pos.x, pos.y, range); telepath.telepath_tiles = fast_fov(pos.x, pos.y, range, &map);
telepath.telepath_tiles.retain( telepath.telepath_tiles.retain(
|p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height |p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height
); );
@ -141,7 +142,7 @@ impl<'a> System<'a> for VisibilitySystem {
} }
} }
pub fn fast_fov(p_x: i32, p_y: i32, r: i32) -> Vec<Point> { pub fn fast_fov(p_x: i32, p_y: i32, r: i32, map: &WriteExpect<Map>) -> Vec<Point> {
let mut visible_tiles: Vec<Point> = Vec::new(); let mut visible_tiles: Vec<Point> = Vec::new();
let mut i = 0; let mut i = 0;
@ -152,7 +153,17 @@ pub fn fast_fov(p_x: i32, p_y: i32, r: i32) -> Vec<Point> {
let mut ox: f32 = (p_x 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); let mut oy: f32 = (p_y as f32) + (0.5 as f32);
for _i in 0..r { for _i in 0..r {
visible_tiles.push(Point::new(ox as i32, oy as i32)); let (ox_i32, oy_i32) = (ox as i32, oy as i32);
visible_tiles.push(Point::new(ox_i32, oy_i32));
if
ox_i32 >= 0 &&
ox_i32 < map.width &&
oy_i32 >= 0 &&
oy_i32 < map.height &&
tile_blocks_telepathy(map.tiles[map.xy_idx(ox_i32, oy_i32)])
{
break;
}
ox += x; ox += x;
oy += y; oy += y;
} }

View file

@ -212,11 +212,11 @@ function makeMutClosure(arg0, arg1, dtor, f) {
return real; return real;
} }
function __wbg_adapter_20(arg0, arg1) { function __wbg_adapter_20(arg0, arg1) {
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb6c6b1cd103d974c(arg0, arg1); wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h66b665bcfa5ccc10(arg0, arg1);
} }
function __wbg_adapter_23(arg0, arg1, arg2) { function __wbg_adapter_23(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h02b9f16709be0849(arg0, arg1, addHeapObject(arg2)); wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h7f980deb71f217f3(arg0, arg1, addHeapObject(arg2));
} }
function handleError(f, args) { function handleError(f, args) {
@ -817,16 +817,16 @@ function __wbg_get_imports() {
const ret = wasm.memory; const ret = wasm.memory;
return addHeapObject(ret); return addHeapObject(ret);
}; };
imports.wbg.__wbindgen_closure_wrapper258 = function(arg0, arg1, arg2) { imports.wbg.__wbindgen_closure_wrapper257 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 15, __wbg_adapter_20); const ret = makeMutClosure(arg0, arg1, 14, __wbg_adapter_20);
return addHeapObject(ret); return addHeapObject(ret);
}; };
imports.wbg.__wbindgen_closure_wrapper2954 = function(arg0, arg1, arg2) { imports.wbg.__wbindgen_closure_wrapper2960 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 696, __wbg_adapter_23); const ret = makeMutClosure(arg0, arg1, 698, __wbg_adapter_23);
return addHeapObject(ret); return addHeapObject(ret);
}; };
imports.wbg.__wbindgen_closure_wrapper2956 = function(arg0, arg1, arg2) { imports.wbg.__wbindgen_closure_wrapper2962 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 696, __wbg_adapter_23); const ret = makeMutClosure(arg0, arg1, 698, __wbg_adapter_23);
return addHeapObject(ret); return addHeapObject(ret);
}; };

Binary file not shown.

887
web/rust-rl.js Normal file
View file

@ -0,0 +1,887 @@
let wasm_bindgen;
(function() {
const __exports = {};
let script_src;
if (typeof document !== 'undefined' && document.currentScript !== null) {
script_src = new URL(document.currentScript.src, location.href).toString();
}
let wasm = undefined;
const heap = new Array(128).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 132) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let WASM_VECTOR_LEN = 0;
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
? function (arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function (arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
});
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
const ptr = malloc(buf.length, 1) >>> 0;
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr;
}
let len = arg.length;
let ptr = malloc(len, 1) >>> 0;
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 0x7F) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
function isLikeNone(x) {
return x === undefined || x === null;
}
let cachedInt32Memory0 = null;
function getInt32Memory0() {
if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachedInt32Memory0;
}
function debugString(val) {
// primitive types
const type = typeof val;
if (type == 'number' || type == 'boolean' || val == null) {
return `${val}`;
}
if (type == 'string') {
return `"${val}"`;
}
if (type == 'symbol') {
const description = val.description;
if (description == null) {
return 'Symbol';
} else {
return `Symbol(${description})`;
}
}
if (type == 'function') {
const name = val.name;
if (typeof name == 'string' && name.length > 0) {
return `Function(${name})`;
} else {
return 'Function';
}
}
// objects
if (Array.isArray(val)) {
const length = val.length;
let debug = '[';
if (length > 0) {
debug += debugString(val[0]);
}
for(let i = 1; i < length; i++) {
debug += ', ' + debugString(val[i]);
}
debug += ']';
return debug;
}
// Test for built-in
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
let className;
if (builtInMatches.length > 1) {
className = builtInMatches[1];
} else {
// Failed to match the standard '[object ClassName]'
return toString.call(val);
}
if (className == 'Object') {
// we're a user defined class or Object
// JSON.stringify avoids problems with cycles, and is generally much
// easier than looping through ownProperties of `val`.
try {
return 'Object(' + JSON.stringify(val) + ')';
} catch (_) {
return 'Object';
}
}
// errors
if (val instanceof Error) {
return `${val.name}: ${val.message}\n${val.stack}`;
}
// TODO we could test for more things here, like `Set`s and `Map`s.
return className;
}
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function makeMutClosure(arg0, arg1, dtor, f) {
const state = { a: arg0, b: arg1, cnt: 1, dtor };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
const a = state.a;
state.a = 0;
try {
return f(a, state.b, ...args);
} finally {
if (--state.cnt === 0) {
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
} else {
state.a = a;
}
}
};
real.original = state;
return real;
}
function __wbg_adapter_20(arg0, arg1) {
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h66b665bcfa5ccc10(arg0, arg1);
}
function __wbg_adapter_23(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h7f980deb71f217f3(arg0, arg1, addHeapObject(arg2));
}
function handleError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
wasm.__wbindgen_exn_store(addHeapObject(e));
}
}
function getArrayU8FromWasm0(ptr, len) {
ptr = ptr >>> 0;
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}
async function __wbg_load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_cb_drop = function(arg0) {
const obj = takeObject(arg0).original;
if (obj.cnt-- == 1) {
obj.a = 0;
return true;
}
const ret = false;
return ret;
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_log_0e24d345b14995ec = function(arg0, arg1) {
console.log(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
const ret = getObject(arg0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
const ret = new Error();
return addHeapObject(ret);
};
imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
const ret = getObject(arg1).stack;
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
let deferred0_0;
let deferred0_1;
try {
deferred0_0 = arg0;
deferred0_1 = arg1;
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
}
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbindgen_boolean_get = function(arg0) {
const v = getObject(arg0);
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
return ret;
};
imports.wbg.__wbg_instanceof_WebGl2RenderingContext_f921526c513bf717 = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof WebGL2RenderingContext;
} catch {
result = false;
}
const ret = result;
return ret;
};
imports.wbg.__wbg_bindVertexArray_8863a216d7b0a339 = function(arg0, arg1) {
getObject(arg0).bindVertexArray(getObject(arg1));
};
imports.wbg.__wbg_bufferData_21334671c4ba6004 = function(arg0, arg1, arg2, arg3) {
getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0);
};
imports.wbg.__wbg_createVertexArray_51d51e1e1e13e9f6 = function(arg0) {
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) {
getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9));
}, arguments) };
imports.wbg.__wbg_attachShader_47256b6b3d42a22e = function(arg0, arg1, arg2) {
getObject(arg0).attachShader(getObject(arg1), getObject(arg2));
};
imports.wbg.__wbg_bindBuffer_24f6010e273fa400 = function(arg0, arg1, arg2) {
getObject(arg0).bindBuffer(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_bindFramebuffer_a9573e340dab20fe = function(arg0, arg1, arg2) {
getObject(arg0).bindFramebuffer(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_bindTexture_92d6d7f8bff9531e = function(arg0, arg1, arg2) {
getObject(arg0).bindTexture(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_blendFunc_533de6de45b80a09 = function(arg0, arg1, arg2) {
getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0);
};
imports.wbg.__wbg_clear_2db2efe323bfdf68 = function(arg0, arg1) {
getObject(arg0).clear(arg1 >>> 0);
};
imports.wbg.__wbg_clearColor_7a7d04702f7e38e5 = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).clearColor(arg1, arg2, arg3, arg4);
};
imports.wbg.__wbg_compileShader_6bf78b425d5c98e1 = function(arg0, arg1) {
getObject(arg0).compileShader(getObject(arg1));
};
imports.wbg.__wbg_createBuffer_323425af422748ac = function(arg0) {
const ret = getObject(arg0).createBuffer();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createFramebuffer_1684a99697ac9563 = function(arg0) {
const ret = getObject(arg0).createFramebuffer();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createProgram_4eaf3b97b5747a62 = function(arg0) {
const ret = getObject(arg0).createProgram();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createShader_429776c9dd6fb87b = function(arg0, arg1) {
const ret = getObject(arg0).createShader(arg1 >>> 0);
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createTexture_1bf4d6fec570124b = function(arg0) {
const ret = getObject(arg0).createTexture();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_disable_e02106ca6c7002d6 = function(arg0, arg1) {
getObject(arg0).disable(arg1 >>> 0);
};
imports.wbg.__wbg_drawArrays_c91ce3f736bf1f2a = function(arg0, arg1, arg2, arg3) {
getObject(arg0).drawArrays(arg1 >>> 0, arg2, arg3);
};
imports.wbg.__wbg_drawElements_a9529eefaf2008bd = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).drawElements(arg1 >>> 0, arg2, arg3 >>> 0, arg4);
};
imports.wbg.__wbg_enable_195891416c520019 = function(arg0, arg1) {
getObject(arg0).enable(arg1 >>> 0);
};
imports.wbg.__wbg_enableVertexAttribArray_8804480c2ea0bb72 = function(arg0, arg1) {
getObject(arg0).enableVertexAttribArray(arg1 >>> 0);
};
imports.wbg.__wbg_framebufferTexture2D_e88fcbd7f8523bb8 = function(arg0, arg1, arg2, arg3, arg4, arg5) {
getObject(arg0).framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4), arg5);
};
imports.wbg.__wbg_getError_7191ad6ea53607fe = function(arg0) {
const ret = getObject(arg0).getError();
return ret;
};
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) };
imports.wbg.__wbg_getParameter_55b36a787dbbfb74 = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).getParameter(arg1 >>> 0);
return addHeapObject(ret);
}, 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);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_getProgramParameter_35522a0bfdfaad27 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getProgramParameter(getObject(arg1), arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_getShaderInfoLog_968b93e75477d725 = function(arg0, arg1, arg2) {
const ret = getObject(arg1).getShaderInfoLog(getObject(arg2));
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_getShaderParameter_ac2727ae4fe7648e = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getShaderParameter(getObject(arg1), arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_getSupportedExtensions_fafc31aab913037d = function(arg0) {
const ret = getObject(arg0).getSupportedExtensions();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_getUniformLocation_9f6eb60c560a347b = function(arg0, arg1, arg2, arg3) {
const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3));
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_linkProgram_33998194075d71fb = function(arg0, arg1) {
getObject(arg0).linkProgram(getObject(arg1));
};
imports.wbg.__wbg_shaderSource_1cb7c64dc7d1a500 = function(arg0, arg1, arg2, arg3) {
getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3));
};
imports.wbg.__wbg_texParameteri_85dad939f62a15aa = function(arg0, arg1, arg2, arg3) {
getObject(arg0).texParameteri(arg1 >>> 0, arg2 >>> 0, arg3);
};
imports.wbg.__wbg_uniform1i_d2e61a6a43889648 = function(arg0, arg1, arg2) {
getObject(arg0).uniform1i(getObject(arg1), arg2);
};
imports.wbg.__wbg_uniform3f_8364a0959b6c1570 = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).uniform3f(getObject(arg1), arg2, arg3, arg4);
};
imports.wbg.__wbg_useProgram_3683cf6f60939dcd = function(arg0, arg1) {
getObject(arg0).useProgram(getObject(arg1));
};
imports.wbg.__wbg_vertexAttribPointer_316ffe2f0458fde7 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
getObject(arg0).vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6);
};
imports.wbg.__wbg_getElementById_cc0e0d931b0d9a28 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2));
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_instanceof_HtmlCanvasElement_da5f9efa0688cf6d = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof HTMLCanvasElement;
} catch {
result = false;
}
const ret = result;
return ret;
};
imports.wbg.__wbg_setwidth_a667a942dba6656e = function(arg0, arg1) {
getObject(arg0).width = arg1 >>> 0;
};
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) {
const ret = getObject(arg0).getContext(getStringFromWasm0(arg1, arg2));
return isLikeNone(ret) ? 0 : addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_offsetX_5a58f16f6c3a41b6 = function(arg0) {
const ret = getObject(arg0).offsetX;
return ret;
};
imports.wbg.__wbg_offsetY_c45b4956f6429a95 = function(arg0) {
const ret = getObject(arg0).offsetY;
return ret;
};
imports.wbg.__wbg_now_0cfdc90c97d0c24b = function(arg0) {
const ret = getObject(arg0).now();
return ret;
};
imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof Window;
} catch {
result = false;
}
const ret = result;
return ret;
};
imports.wbg.__wbg_charCode_75cea1a3a6d66388 = function(arg0) {
const ret = getObject(arg0).charCode;
return ret;
};
imports.wbg.__wbg_keyCode_dfa86be31f5ef90c = function(arg0) {
const ret = getObject(arg0).keyCode;
return ret;
};
imports.wbg.__wbg_code_96d6322b968b2d17 = function(arg0, arg1) {
const ret = getObject(arg1).code;
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_getModifierState_5102ee8843516d2f = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getModifierState(getStringFromWasm0(arg1, arg2));
return ret;
};
imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) {
const ret = getObject(arg0).document;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_performance_2c295061c8b01e0b = function(arg0) {
const ret = getObject(arg0).performance;
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_setonkeydown_933cca3c9000a932 = function(arg0, arg1) {
getObject(arg0).onkeydown = getObject(arg1);
};
imports.wbg.__wbg_setonkeyup_0dfb23e81d0afdde = function(arg0, arg1) {
getObject(arg0).onkeyup = getObject(arg1);
};
imports.wbg.__wbg_requestAnimationFrame_d082200514b6674d = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).requestAnimationFrame(getObject(arg1));
return ret;
}, arguments) };
imports.wbg.__wbg_setonmousedown_4f38d9c057bbfcbd = function(arg0, arg1) {
getObject(arg0).onmousedown = getObject(arg1);
};
imports.wbg.__wbg_setonmousemove_c0b17753786f3544 = function(arg0, arg1) {
getObject(arg0).onmousemove = getObject(arg1);
};
imports.wbg.__wbg_setonmouseup_4b447fa380e33802 = function(arg0, arg1) {
getObject(arg0).onmouseup = getObject(arg1);
};
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) {
getObject(arg0).texImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9));
}, arguments) };
imports.wbg.__wbg_attachShader_b65b695055670cb5 = function(arg0, arg1, arg2) {
getObject(arg0).attachShader(getObject(arg1), getObject(arg2));
};
imports.wbg.__wbg_bindBuffer_313561e5bc0e533f = function(arg0, arg1, arg2) {
getObject(arg0).bindBuffer(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_bindFramebuffer_56bf6536a4ced0ec = function(arg0, arg1, arg2) {
getObject(arg0).bindFramebuffer(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_bindTexture_9cb5c770d1ba2cca = function(arg0, arg1, arg2) {
getObject(arg0).bindTexture(arg1 >>> 0, getObject(arg2));
};
imports.wbg.__wbg_blendFunc_fbe9d3a688fe71c3 = function(arg0, arg1, arg2) {
getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0);
};
imports.wbg.__wbg_clear_2ccea1f65b510c97 = function(arg0, arg1) {
getObject(arg0).clear(arg1 >>> 0);
};
imports.wbg.__wbg_clearColor_de587608b28bc7ed = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).clearColor(arg1, arg2, arg3, arg4);
};
imports.wbg.__wbg_compileShader_d88d0a8cd9b72b4d = function(arg0, arg1) {
getObject(arg0).compileShader(getObject(arg1));
};
imports.wbg.__wbg_createBuffer_59051f4461e7c5e2 = function(arg0) {
const ret = getObject(arg0).createBuffer();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createFramebuffer_223c1212ad76affc = function(arg0) {
const ret = getObject(arg0).createFramebuffer();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createProgram_88dbe21c0b682e1a = function(arg0) {
const ret = getObject(arg0).createProgram();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createShader_9d7d388633caad18 = function(arg0, arg1) {
const ret = getObject(arg0).createShader(arg1 >>> 0);
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_createTexture_9d0bb4d741b8ad76 = function(arg0) {
const ret = getObject(arg0).createTexture();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_disable_5cf2070641fa2ed7 = function(arg0, arg1) {
getObject(arg0).disable(arg1 >>> 0);
};
imports.wbg.__wbg_drawArrays_d5c7dc2b2376c85a = function(arg0, arg1, arg2, arg3) {
getObject(arg0).drawArrays(arg1 >>> 0, arg2, arg3);
};
imports.wbg.__wbg_drawElements_3316ee0cd1117c2a = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).drawElements(arg1 >>> 0, arg2, arg3 >>> 0, arg4);
};
imports.wbg.__wbg_enable_8965e69c596f0a94 = function(arg0, arg1) {
getObject(arg0).enable(arg1 >>> 0);
};
imports.wbg.__wbg_enableVertexAttribArray_2b0475db43533cf2 = function(arg0, arg1) {
getObject(arg0).enableVertexAttribArray(arg1 >>> 0);
};
imports.wbg.__wbg_framebufferTexture2D_953e69a8bec22fa9 = function(arg0, arg1, arg2, arg3, arg4, arg5) {
getObject(arg0).framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4), arg5);
};
imports.wbg.__wbg_getError_1e5ec1ec9e58b323 = function(arg0) {
const ret = getObject(arg0).getError();
return ret;
};
imports.wbg.__wbg_getProgramInfoLog_0b7af4ad85fa52a4 = function(arg0, arg1, arg2) {
const ret = getObject(arg1).getProgramInfoLog(getObject(arg2));
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_getProgramParameter_2a3735278367f8bc = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getProgramParameter(getObject(arg1), arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_getShaderInfoLog_979aafa403ffb252 = function(arg0, arg1, arg2) {
const ret = getObject(arg1).getShaderInfoLog(getObject(arg2));
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_getShaderParameter_e8054f1d9026fb70 = function(arg0, arg1, arg2) {
const ret = getObject(arg0).getShaderParameter(getObject(arg1), arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_getUniformLocation_688976233799a45a = function(arg0, arg1, arg2, arg3) {
const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3));
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_linkProgram_9a2d12d120d99917 = function(arg0, arg1) {
getObject(arg0).linkProgram(getObject(arg1));
};
imports.wbg.__wbg_shaderSource_f435f9b74440bb54 = function(arg0, arg1, arg2, arg3) {
getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3));
};
imports.wbg.__wbg_texParameteri_1f17358e51eb8069 = function(arg0, arg1, arg2, arg3) {
getObject(arg0).texParameteri(arg1 >>> 0, arg2 >>> 0, arg3);
};
imports.wbg.__wbg_uniform1i_9f94ef0ba6b3cc66 = function(arg0, arg1, arg2) {
getObject(arg0).uniform1i(getObject(arg1), arg2);
};
imports.wbg.__wbg_uniform3f_c682f4b32f713d1a = function(arg0, arg1, arg2, arg3, arg4) {
getObject(arg0).uniform3f(getObject(arg1), arg2, arg3, arg4);
};
imports.wbg.__wbg_useProgram_019eb6df066fabf5 = function(arg0, arg1) {
getObject(arg0).useProgram(getObject(arg1));
};
imports.wbg.__wbg_vertexAttribPointer_ca11984ee8843c0a = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
getObject(arg0).vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6);
};
imports.wbg.__wbg_bindVertexArrayOES_b7d9da7e073aa6b5 = function(arg0, arg1) {
getObject(arg0).bindVertexArrayOES(getObject(arg1));
};
imports.wbg.__wbg_createVertexArrayOES_6a3c3a5a68201f8f = function(arg0) {
const ret = getObject(arg0).createVertexArrayOES();
return isLikeNone(ret) ? 0 : addHeapObject(ret);
};
imports.wbg.__wbg_self_1c2814d86e6e51e3 = function() { return handleError(function () {
const ret = self.self;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_crypto_70532d614bc7e028 = function(arg0) {
const ret = getObject(arg0).crypto;
return addHeapObject(ret);
};
imports.wbg.__wbg_msCrypto_4e9b4dd0e1abade6 = function(arg0) {
const ret = getObject(arg0).msCrypto;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === undefined;
return ret;
};
imports.wbg.__wbg_static_accessor_MODULE_7781e47b50010688 = function() {
const ret = module;
return addHeapObject(ret);
};
imports.wbg.__wbg_require_9ace3ae680954e98 = function() { return handleError(function (arg0, arg1, arg2) {
const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_getRandomValues_f6c9b08ef5448767 = function() { return handleError(function (arg0, arg1) {
getObject(arg0).getRandomValues(getObject(arg1));
}, arguments) };
imports.wbg.__wbg_randomFillSync_bf67eeddb65b346b = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
}, arguments) };
imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) {
const ret = getObject(arg0)[arg1 >>> 0];
return addHeapObject(ret);
};
imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) {
const ret = new Function(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
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 () {
const ret = self.self;
return addHeapObject(ret);
}, 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 () {
const ret = globalThis.globalThis;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () {
const ret = global.global;
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_now_9c5990bda04c7e53 = function() {
const ret = Date.now();
return ret;
};
imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) {
const ret = getObject(arg0).buffer;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_828b952f0e692245 = function(arg0, arg1, arg2) {
const ret = new Int8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_735ed5ea2ae07fe9 = function(arg0, arg1, arg2) {
const ret = new Int16Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_9f43b22ab631d1d6 = function(arg0, arg1, arg2) {
const ret = new Int32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) {
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) {
const ret = new Uint8Array(getObject(arg0));
return addHeapObject(ret);
};
imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) {
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
};
imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) {
const ret = getObject(arg0).length;
return ret;
};
imports.wbg.__wbg_newwithbyteoffsetandlength_31ff1024ef0c63c7 = function(arg0, arg1, arg2) {
const ret = new Uint16Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_6df0e8c3efd2a5d3 = function(arg0, arg1, arg2) {
const ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithbyteoffsetandlength_69193e31c844b792 = function(arg0, arg1, arg2) {
const ret = new Float32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithlength_e5d69174d6984cd7 = function(arg0) {
const ret = new Uint8Array(arg0 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbg_subarray_13db269f57aa838d = function(arg0, arg1, arg2) {
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
const ret = debugString(getObject(arg1));
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbindgen_memory = function() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper257 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 14, __wbg_adapter_20);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper2960 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 698, __wbg_adapter_23);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper2962 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 698, __wbg_adapter_23);
return addHeapObject(ret);
};
return imports;
}
function __wbg_init_memory(imports, maybe_memory) {
}
function __wbg_finalize_init(instance, module) {
wasm = instance.exports;
__wbg_init.__wbindgen_wasm_module = module;
cachedInt32Memory0 = null;
cachedUint8Memory0 = null;
wasm.__wbindgen_start();
return wasm;
}
function initSync(module) {
if (wasm !== undefined) return wasm;
const imports = __wbg_get_imports();
__wbg_init_memory(imports);
if (!(module instanceof WebAssembly.Module)) {
module = new WebAssembly.Module(module);
}
const instance = new WebAssembly.Instance(module, imports);
return __wbg_finalize_init(instance, module);
}
async function __wbg_init(input) {
if (wasm !== undefined) return wasm;
if (typeof input === 'undefined' && script_src !== 'undefined') {
input = script_src.replace(/\.js$/, '_bg.wasm');
}
const imports = __wbg_get_imports();
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
__wbg_init_memory(imports);
const { instance, module } = await __wbg_load(await input, imports);
return __wbg_finalize_init(instance, module);
}
wasm_bindgen = Object.assign(__wbg_init, { initSync }, __exports);
})();

BIN
web/rust-rl_bg.wasm Normal file

Binary file not shown.