diff --git a/raws/mobs.json b/raws/mobs.json
index 43e3266..16768c5 100644
--- a/raws/mobs.json
+++ b/raws/mobs.json
@@ -2,7 +2,7 @@
{
"id": "npc_barkeep",
"name": "barkeep",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#EE82EE", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#EE82EE", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"quips": ["Drink?", "Something to eat?", "Don't go out on an empty stomach."]
@@ -10,7 +10,7 @@
{
"id": "npc_townsperson",
"name": "townsperson",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#9fa86c", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#9fa86c", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "RANDOM_PATH", "IS_HUMAN"],
"vision_range": 4,
"quips": ["Hello!", "Good morning.", ""]
@@ -18,7 +18,7 @@
{
"id": "npc_drunk",
"name": "drunk",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#a0a83c", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#a0a83c", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"quips": ["Hic!", "H-Hic'.", "Get me 'nother, would you?"]
@@ -26,7 +26,7 @@
{
"id": "npc_fisher",
"name": "fisher",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#3ca3a8", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#3ca3a8", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"quips": ["Hey."]
@@ -34,7 +34,7 @@
{
"id": "npc_dockworker",
"name": "dock worker",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#68d8de", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#68d8de", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"quips": ["No boat for a few days.", "Not much for us to do."]
@@ -42,7 +42,7 @@
{
"id": "npc_priest",
"name": "priest",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#FFFFFF", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#FFFFFF", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"quips": ["Light's givings.", "", "Bless you."]
@@ -50,7 +50,7 @@
{
"id": "npc_miner",
"name": "miner",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#946123", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#946123", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "IS_HUMAN"],
"vision_range": 4,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d8" }],
@@ -59,7 +59,7 @@
{
"id": "npc_guard",
"name": "smalltown guard",
- "renderable": { "glyph": "@", "sprite": "@", "fg": "#034efc", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "@", "sprite": { "id": "@" }, "fg": "#034efc", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL", "RANDOM_PATH", "IS_HUMAN"],
"level": 2,
"attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d8" }],
@@ -69,7 +69,7 @@
{
"id": "rat",
"name": "rat",
- "renderable": { "glyph": "r", "sprite": "r", "fg": "#aa6000", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "r", "sprite": { "id": "r" }, "fg": "#aa6000", "bg": "#000000", "order": 1 },
"flags": [],
"bac": 6,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }],
@@ -78,7 +78,7 @@
{
"id": "chicken",
"name": "chicken",
- "renderable": { "glyph": "c", "sprite": "c", "fg": "#BB6000", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "c", "sprite": { "id": "c" }, "fg": "#BB6000", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 8,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
@@ -86,7 +86,7 @@
{
"id": "deer_little",
"name": "fawn",
- "renderable": { "glyph": "q", "sprite": "q", "fg": "#a57037", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "q", "sprite": { "id": "q" }, "fg": "#a57037", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 8,
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
@@ -94,7 +94,7 @@
{
"id": "sheep_little",
"name": "lamb",
- "renderable": { "glyph": "q", "sprite": "q", "fg": "#e7e7e7", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "q", "sprite": { "id": "q" }, "fg": "#e7e7e7", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE", "SMALL_GROUP"],
"bac": 10,
"attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }]
@@ -102,7 +102,7 @@
{
"id": "chicken_little",
"name": "chick",
- "renderable": { "glyph": "c", "sprite": "c", "fg": "#fae478", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "c", "sprite": { "id": "c" }, "fg": "#fae478", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE"],
"bac": 10,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
@@ -110,7 +110,7 @@
{
"id": "horse_little",
"name": "pony",
- "renderable": { "glyph": "u", "sprite": "u", "fg": "#b36c29", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "u", "sprite": { "id": "u" }, "fg": "#b36c29", "bg": "#000000", "order": 1 },
"flags": ["HERBIVORE", "MULTIATTACK"],
"level": 3,
"bac": 6,
@@ -124,7 +124,7 @@
{
"id": "horse",
"name": "horse",
- "renderable": { "glyph": "u", "sprite": "u", "fg": "#744d29", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "u", "sprite": { "id": "u" }, "fg": "#744d29", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 5,
"bac": 5,
@@ -137,7 +137,7 @@
{
"id": "horse_large",
"name": "warhorse",
- "renderable": { "glyph": "u", "sprite": "u", "fg": "#8a3520", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "u", "sprite": { "id": "u" }, "fg": "#8a3520", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 7,
"bac": 4,
@@ -150,7 +150,7 @@
{
"id": "rat_giant",
"name": "giant rat",
- "renderable": { "glyph": "r", "sprite": "r", "fg": "#bb8000", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "r", "sprite": { "id": "r" }, "fg": "#bb8000", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 1,
"bac": 7,
@@ -160,7 +160,7 @@
{
"id": "dog_little",
"name": "little dog",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#FFFFFF", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#FFFFFF", "bg": "#000000", "order": 1 },
"flags": ["NEUTRAL"],
"level": 2,
"bac": 6,
@@ -171,7 +171,7 @@
{
"id": "dog",
"name": "dog",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#EEEEEE", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#EEEEEE", "bg": "#000000", "order": 1 },
"flags": [],
"level": 4,
"bac": 5,
@@ -181,7 +181,7 @@
{
"id": "dog_large",
"name": "large dog",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#DDDDDD", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#DDDDDD", "bg": "#000000", "order": 1 },
"flags": [],
"level": 6,
"bac": 4,
@@ -191,7 +191,7 @@
{
"id": "gnome",
"name": "gnome",
- "renderable": { "glyph": "G", "sprite": "g2", "fg": "#AA5500", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "G", "sprite": { "id": "g2" }, "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP", "IS_GNOME"],
"level": 1,
"speed": 6,
@@ -201,7 +201,7 @@
{
"id": "zombie_gnome",
"name": "gnome zombie",
- "renderable": { "glyph": "z", "sprite": "z", "fg": "#AA5500", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "z", "sprite": { "id": "z" }, "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": ["MINDLESS"],
"level": 1,
"speed": 6,
@@ -212,7 +212,7 @@
{
"id": "goblin",
"name": "goblin",
- "renderable": { "glyph": "g", "sprite": "g", "fg": "#00FF00", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "g", "sprite": { "id": "g" }, "fg": "#00FF00", "bg": "#000000", "order": 1 },
"flags": [],
"level": 1,
"speed": 9,
@@ -221,7 +221,7 @@
{
"id": "kobold",
"name": "kobold",
- "renderable": { "glyph": "k", "sprite": "k", "fg": "#AA5500", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "k", "sprite": { "id": "k" }, "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": [],
"level": 1,
"speed": 6,
@@ -231,7 +231,7 @@
{
"id": "zombie_kobold",
"name": "kobold zombie",
- "renderable": { "glyph": "z", "sprite": "z", "fg": "#AA5500", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "z", "sprite": { "id": "z" }, "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": ["MINDLESS"],
"level": 1,
"speed": 6,
@@ -242,7 +242,7 @@
{
"id": "kobold_large",
"name": "large kobold",
- "renderable": { "glyph": "k", "sprite": "k", "fg": "#70461b", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "k", "sprite": { "id": "k" }, "fg": "#70461b", "bg": "#000000", "order": 1 },
"flags": [],
"level": 1,
"speed": 6,
@@ -253,7 +253,7 @@
{
"id": "zombie_orc",
"name": "orc zombie",
- "renderable": { "glyph": "z", "sprite": "z", "fg": "#dbd830", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "z", "sprite": { "id": "z" }, "fg": "#dbd830", "bg": "#000000", "order": 1 },
"flags": ["MINDLESS"],
"level": 2,
"bac": 9,
@@ -265,7 +265,7 @@
{
"id": "dwarf",
"name": "dwarf",
- "renderable": { "glyph": "h", "sprite": "h", "fg": "#d61b1b", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "h", "sprite": { "id": "h" }, "fg": "#d61b1b", "bg": "#000000", "order": 1 },
"flags": ["IS_DWARF"],
"level": 2,
"bac": 10,
@@ -277,7 +277,7 @@
{
"id": "zombie_dwarf",
"name": "dwarf zombie",
- "renderable": { "glyph": "z", "sprite": "z", "fg": "#d61b1b", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "z", "sprite": { "id": "z" }, "fg": "#d61b1b", "bg": "#000000", "order": 1 },
"flags": ["MINDLESS"],
"level": 2,
"bac": 9,
@@ -289,7 +289,7 @@
{
"id": "kobold_captain",
"name": "kobold captain",
- "renderable": { "glyph": "k", "sprite": "k", "fg": "#9331ac", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "k", "sprite": { "id": "k" }, "fg": "#9331ac", "bg": "#000000", "order": 1 },
"flags": [],
"level": 2,
"speed": 6,
@@ -300,7 +300,7 @@
{
"id": "spider_cave",
"name": "cave spider",
- "renderable": { "glyph": "s", "sprite": "s", "fg": "#6b6b6b", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "s", "sprite": { "id": "s" }, "fg": "#6b6b6b", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 1,
"bac": 3,
@@ -311,7 +311,7 @@
{
"id": "ant_worker",
"name": "worker ant",
- "renderable": { "glyph": "a", "sprite": "a", "fg": "#ca7631", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "a", "sprite": { "id": "a" }, "fg": "#ca7631", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 2,
"bac": 3,
@@ -322,7 +322,7 @@
{
"id": "ant_soldier",
"name": "soldier ant",
- "renderable": { "glyph": "a", "sprite": "a", "fg": "#ca3f26", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "a", "sprite": { "id": "a" }, "fg": "#ca3f26", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP", "POISON_RES"],
"level": 3,
"bac": 3,
@@ -336,7 +336,7 @@
{
"id": "caterpillar_cave",
"name": "caterpillar",
- "renderable": { "glyph": "a", "sprite": "a", "fg": "#6b6b6b", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "a", "sprite": { "id": "a" }, "fg": "#6b6b6b", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 1,
"bac": 3,
@@ -347,7 +347,7 @@
{
"id": "caterpillar_giant",
"name": "giant caterpillar",
- "renderable": { "glyph": "a", "sprite": "a", "fg": "#b9aeae", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "a", "sprite": { "id": "a" }, "fg": "#b9aeae", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 2,
"bac": 7,
@@ -358,7 +358,7 @@
{
"id": "jackal",
"name": "jackal",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#AA5500", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#AA5500", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE", "SMALL_GROUP"],
"bac": 7,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }]
@@ -366,7 +366,7 @@
{
"id": "fox",
"name": "fox",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#FF0000", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#FF0000", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE"],
"bac": 7,
"attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }]
@@ -374,7 +374,7 @@
{
"id": "coyote",
"name": "coyote",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#6E3215", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#6E3215", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE", "SMALL_GROUP"],
"level": 1,
"bac": 7,
@@ -383,7 +383,7 @@
{
"id": "wolf",
"name": "wolf",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#5E4225", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#5E4225", "bg": "#000000", "order": 1 },
"flags": ["CARNIVORE"],
"level": 5,
"bac": 4,
@@ -392,7 +392,7 @@
{
"id": "goblin_chieftain",
"name": "goblin chieftain",
- "renderable": { "glyph": "g", "sprite": "g", "fg": "#9331ac", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "g", "sprite": { "id": "g" }, "fg": "#9331ac", "bg": "#000000", "order": 1 },
"flags": [],
"level": 2,
"speed": 9,
@@ -402,7 +402,7 @@
{
"id": "orc",
"name": "orc",
- "renderable": { "glyph": "o", "sprite": "o", "fg": "#00FF00", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "o", "sprite": { "id": "o" }, "fg": "#00FF00", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 1,
"speed": 9,
@@ -412,7 +412,7 @@
{
"id": "orc_hill",
"name": "hill orc",
- "renderable": { "glyph": "o", "sprite": "o", "fg": "#dbd830", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "o", "sprite": { "id": "o" }, "fg": "#dbd830", "bg": "#000000", "order": 1 },
"flags": ["LARGE_GROUP"],
"level": 2,
"speed": 9,
@@ -422,7 +422,7 @@
{
"id": "orc_captain",
"name": "orc captain",
- "renderable": { "glyph": "o", "sprite": "o", "fg": "#9331ac", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "o", "sprite": { "id": "o" }, "fg": "#9331ac", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 5,
"speed": 5,
@@ -435,7 +435,7 @@
{
"id": "warg",
"name": "warg",
- "renderable": { "glyph": "d", "sprite": "d", "fg": "#8b7164", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "d", "sprite": { "id": "d" }, "fg": "#8b7164", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 7,
"bac": 4,
@@ -446,7 +446,7 @@
{
"id": "jaguar",
"name": "jaguar",
- "renderable": { "glyph": "f", "sprite": "f", "fg": "#d3b947", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "f", "sprite": { "id": "f" }, "fg": "#d3b947", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 4,
"bac": 6,
@@ -461,7 +461,7 @@
{
"id": "lynx",
"name": "lynx",
- "renderable": { "glyph": "f", "sprite": "f", "fg": "#b5d347", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "f", "sprite": { "id": "f" }, "fg": "#b5d347", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 5,
"bac": 6,
@@ -476,7 +476,7 @@
{
"id": "panther",
"name": "panther",
- "renderable": { "glyph": "f", "sprite": "f", "fg": "#58554e", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "f", "sprite": { "id": "f" }, "fg": "#58554e", "bg": "#000000", "order": 1 },
"flags": ["MULTIATTACK"],
"level": 5,
"bac": 6,
@@ -491,7 +491,7 @@
{
"id": "ogre",
"name": "ogre",
- "renderable": { "glyph": "O", "sprite": "o2", "fg": "#10A70d", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "O", "sprite": { "id": "o2" }, "fg": "#10A70d", "bg": "#000000", "order": 1 },
"flags": ["SMALL_GROUP"],
"level": 5,
"bac": 5,
@@ -502,7 +502,7 @@
{
"id": "treant_small",
"name": "treant sapling",
- "renderable": { "glyph": "♠️", "sprite": "spade", "fg": "#10570d", "bg": "#000000", "order": 1 },
+ "renderable": { "glyph": "♠️", "sprite": { "id": "spade" }, "fg": "#10570d", "bg": "#000000", "order": 1 },
"flags": ["LARGE_GROUP", "GREEN_BLOOD", "FIRE_WEAK"],
"level": 2,
"bac": 12,
diff --git a/raws/props.json b/raws/props.json
index 7f75da7..f708b9f 100644
--- a/raws/props.json
+++ b/raws/props.json
@@ -2,13 +2,19 @@
{
"id": "door",
"name": "door",
- "renderable": { "glyph": "+", "sprite": "door_wood_h_closed", "colour_sprite": false, "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "+", "sprite": { "id": "door_wood_h_closed", "alt": "door_wood_h_open", "colour": false }, "fg": "#00FFFF", "bg": "#000000", "order": 2 },
+ "flags": ["DOOR"]
+ },
+ {
+ "id": "trapdoor",
+ "name": "trapdoor",
+ "renderable": { "glyph": "+", "sprite": { "id": "trapdoor_closed", "alt": "trapdoor_open2", "colour": false, "alt_y": 1.0 }, "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"flags": ["DOOR"]
},
{
"id": "prop_altar",
"name": "altar",
- "renderable": { "glyph": "_", "sprite": "tombstone", "colour_sprite": false, "fg": "#FFFFFF", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "_", "sprite": { "id": "tombstone", "colour": false }, "fg": "#FFFFFF", "bg": "#000000", "order": 2 },
"flags": ["ENTRY_TRIGGER"],
"effects": { "heal": "8d8" }
},
@@ -21,64 +27,64 @@
{
"id": "prop_table",
"name": "table",
- "renderable": { "glyph": "-", "sprite": "table", "colour_sprite": false, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "-", "sprite": { "id": "table", "colour": false }, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "prop_hay",
"name": "hay",
- "renderable": { "glyph": "%", "sprite": "%", "fg": "#c7ad39", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "%", "sprite": { "id": "%" }, "fg": "#c7ad39", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "prop_statue",
"name": "statue",
- "renderable": { "glyph": "@", "sprite": "statue_warrior", "colour_sprite": false, "fg": "#ffffff", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "@", "sprite": { "id": "statue_warrior", "colour": false }, "fg": "#ffffff", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "prop_bed",
"name": "bed",
- "renderable": { "glyph": "=", "sprite": "bed", "colour_sprite": false, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "=", "sprite": { "id": "bed", "colour": false }, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "prop_chair",
"name": "chair",
- "renderable": { "glyph": "└", "sprite": "chair", "colour_sprite": false, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "└", "sprite": { "id": "chair", "colour": false }, "fg": "#AAAAAA", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "prop_candle",
"name": "candle",
- "renderable": { "glyph": "Ä", "sprite": "candles_a1", "colour_sprite": false, "fg": "#FFA500", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "Ä", "sprite": { "id": "candles_a1", "colour": false }, "fg": "#FFA500", "bg": "#000000", "order": 2 },
"flags": []
},
{
"id": "trap_bear",
"name": "bear trap",
- "renderable": { "glyph": "^", "sprite": "trap", "colour_sprite": false, "fg": "#e6e6e6", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "^", "sprite": { "id": "trap", "colour": false }, "fg": "#e6e6e6", "bg": "#000000", "order": 2 },
"flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"],
"effects": { "damage": "2d4" }
},
{
"id": "trap_mini_mine",
"name": "mini-mine",
- "renderable": { "glyph": "^", "sprite": "^", "fg": "#ff1e00", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "^", "sprite": { "id": "^" }, "fg": "#ff1e00", "bg": "#000000", "order": 2 },
"flags": ["ENTRY_TRIGGER", "SINGLE_ACTIVATION"],
"effects": { "damage": "2d4", "aoe": "3" }
},
{
"id": "trap_stonefall",
"name": "stonefall trap",
- "renderable": { "glyph": "^", "sprite": "^", "fg": "#beb5a7", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "^", "sprite": { "id": "^" }, "fg": "#beb5a7", "bg": "#000000", "order": 2 },
"flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"],
"effects": { "damage": "2d10" }
},
{
"id": "trap_confusion",
"name": "magic trap",
- "renderable": { "glyph": "^", "sprite": "magic_e1", "colour_sprite": false, "fg": "#df07df", "bg": "#000000", "order": 2 },
+ "renderable": { "glyph": "^", "sprite": { "id": "magic_e1", "colour": false }, "fg": "#df07df", "bg": "#000000", "order": 2 },
"flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"],
"effects": { "confusion": "3" }
}
diff --git a/src/components.rs b/src/components.rs
index bd9e4a1..ada13c5 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -38,11 +38,53 @@ pub struct OtherLevelPosition {
pub id: i32,
}
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct SpriteInfo {
+ pub id: String,
+ pub recolour: bool,
+ pub alt: Option,
+ pub offset: (f32, f32),
+ pub alt_offset: (f32, f32),
+}
+
+impl SpriteInfo {
+ pub fn new(id: &str) -> Self {
+ Self {
+ id: id.to_string(),
+ recolour: false,
+ alt: None,
+ offset: (0.0, 0.0),
+ alt_offset: (0.0, 0.0),
+ }
+ }
+ pub fn colourable(id: &str) -> Self {
+ Self {
+ id: id.to_string(),
+ recolour: true,
+ alt: None,
+ offset: (0.0, 0.0),
+ alt_offset: (0.0, 0.0),
+ }
+ }
+ pub fn swap(&self) -> Self {
+ if let Some(alt_sprite) = &self.alt {
+ Self {
+ id: alt_sprite.clone(),
+ recolour: self.recolour,
+ alt: Some(self.id.clone()),
+ offset: self.alt_offset,
+ alt_offset: self.offset,
+ }
+ } else {
+ unreachable!("Tried to call .swap() on a sprite with no alt: {:?}", self);
+ }
+ }
+}
+
#[derive(Component, ConvertSaveload, Clone)]
pub struct Renderable {
pub glyph: FontCharType,
- pub sprite: Option,
- pub colour_sprite: bool,
+ pub sprite: Option,
pub fg: RGB,
pub bg: RGB,
pub render_order: i32,
diff --git a/src/gui/character_creation.rs b/src/gui/character_creation.rs
index a1f245d..55b0517 100644
--- a/src/gui/character_creation.rs
+++ b/src/gui/character_creation.rs
@@ -275,7 +275,6 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
.insert(*player, Renderable {
glyph: to_cp437(DWARF_GLYPH),
sprite: None, // TODO: Dwarf sprite
- colour_sprite: true,
fg: RGB::named(DWARF_COLOUR),
bg: RGB::named(BLACK),
render_order: 0,
@@ -288,7 +287,6 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
.insert(*player, Renderable {
glyph: to_cp437(ELF_GLYPH),
sprite: None, // TODO: Elf sprite
- colour_sprite: true,
fg: RGB::named(ELF_COLOUR),
bg: RGB::named(BLACK),
render_order: 0,
@@ -315,7 +313,6 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) {
.insert(*player, Renderable {
glyph: to_cp437(CATFOLK_GLYPH),
sprite: None, // TODO: Catfolk sprite
- colour_sprite: true,
fg: RGB::named(CATFOLK_COLOUR),
bg: RGB::named(BLACK),
render_order: 0,
diff --git a/src/gui/mod.rs b/src/gui/mod.rs
index 97b4c6a..4d719ff 100644
--- a/src/gui/mod.rs
+++ b/src/gui/mod.rs
@@ -126,7 +126,7 @@ fn draw_bar(
let fill_width = (percent * (w as f32)) as i32;
for x in 0..w {
let suffix = if x == 0 { "1" } else if x == w - 1 { "3" } else { "2" };
- let fill = if x <= fill_width { "full" } else { "empty" };
+ let fill = if x < fill_width { "full" } else { "empty" };
let sprite = if let Some(sprite) = atlas.get(&format!("{}_{}_{}", sprite, fill, suffix)) {
sprite
} else {
diff --git a/src/main.rs b/src/main.rs
index 06fc592..b904ffa 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -253,16 +253,19 @@ fn draw_camera(
}
// TODO: Use sprites here, not text drawing. Put bitmap font into atlas.
let renderable = renderables.get(entry.1.e).unwrap();
- if let Some(sprite_id) = &renderable.sprite {
- let sprite = if let Some(sprite) = atlas.get(sprite_id) {
+ if let Some(spriteinfo) = &renderable.sprite {
+ let id = if let Some(sprite) = atlas.get(&spriteinfo.id) {
sprite
} else {
- panic!("No entity sprite found for ID: {}", sprite_id);
+ panic!("No entity sprite found for ID: {}", spriteinfo.id);
};
- draw.image(sprite)
- .position((entry.0.x as f32) * TILESIZE, (entry.0.y as f32) * TILESIZE)
+ draw.image(id)
+ .position(
+ ((entry.0.x as f32) + spriteinfo.offset.0) * TILESIZE,
+ ((entry.0.y as f32) + spriteinfo.offset.1) * TILESIZE
+ )
.color(
- if renderable.colour_sprite {
+ if spriteinfo.recolour {
Color::from_rgb(
renderable.fg.r,
renderable.fg.g,
@@ -293,16 +296,19 @@ fn draw_camera(
DrawType::VisibleAndRemember => {
// TODO: PUT THIS INTO A FUNCTION!
let renderable = renderables.get(entry.1.e).unwrap();
- if let Some(sprite_id) = &renderable.sprite {
- let sprite = if let Some(sprite) = atlas.get(sprite_id) {
+ if let Some(spriteinfo) = &renderable.sprite {
+ let id = if let Some(sprite) = atlas.get(&spriteinfo.id) {
sprite
} else {
- panic!("No entity sprite found for ID: {}", sprite_id);
+ panic!("No entity sprite found for ID: {}", spriteinfo.id);
};
- draw.image(sprite)
- .position((entry.0.x as f32) * TILESIZE, (entry.0.y as f32) * TILESIZE)
+ draw.image(id)
+ .position(
+ ((entry.0.x as f32) + spriteinfo.offset.0) * TILESIZE,
+ ((entry.0.y as f32) + spriteinfo.offset.1) * TILESIZE
+ )
.color(
- if renderable.colour_sprite {
+ if spriteinfo.recolour {
Color::from_rgb(
renderable.fg.r,
renderable.fg.g,
diff --git a/src/map/themes.rs b/src/map/themes.rs
index a5f1a00..2698eda 100644
--- a/src/map/themes.rs
+++ b/src/map/themes.rs
@@ -9,7 +9,7 @@ use notan::prelude::*;
pub fn get_sprite_for_id(idx: usize, map: &Map, other_pos: Option) -> (&str, Color) {
let f = map.colour_offset[idx].0.0; // Using offset as a source of random.
let sprite = match map.tiles[idx] {
- TileType::Wall => map.tiles[idx].sprite(check_if_base(idx, map), f),
+ TileType::Wall => map.tiles[idx].sprite(check_if_base(TileType::Wall, idx, map), f),
_ => map.tiles[idx].sprite(false, f),
};
let tint = if !map.visible_tiles[idx] {
@@ -150,18 +150,23 @@ fn get_forest_theme_renderables(idx:usize, map: &Map, debug: Option) -> (F
return (glyph, fg, bg, offsets, bg_offsets);
}
-fn is_revealed_and_wall(map: &Map, x: i32, y: i32, debug: Option) -> bool {
+fn is_revealed_and(tt: TileType, map: &Map, x: i32, y: i32, debug: Option) -> bool {
let idx = map.xy_idx(x, y);
- map.tiles[idx] == TileType::Wall &&
- (if debug.is_none() { map.revealed_tiles[idx] } else { true })
+ map.tiles[idx] == tt && (if debug.is_none() { map.revealed_tiles[idx] } else { true })
}
-fn check_if_base(idx: usize, map: &Map) -> bool {
+fn check_if_base(tt: TileType, idx: usize, map: &Map) -> bool {
let x = (idx as i32) % map.width;
let y = (idx as i32) / map.width;
- if is_revealed_and_wall(map, x, y + 1, None) {
+ // If we're on the edge, it can only be a base sprite.
+ if y > map.height - 2 {
+ return true;
+ }
+ // If the tile below is a revealed wall, we're not the base.
+ if is_revealed_and(tt, map, x, y + 1, None) {
return false;
}
+ // If the tile below isn't a revealed wall, we're the base.
return true;
}
@@ -179,37 +184,37 @@ fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option) -> FontCharType {
let mut mask: u8 = 0;
let diagonals_matter: Vec = vec![7, 11, 13, 14, 15];
- if is_revealed_and_wall(map, x, y - 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x, y - 1, debug) {
// N
mask += 1;
}
- if is_revealed_and_wall(map, x, y + 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x, y + 1, debug) {
// S
mask += 2;
}
- if is_revealed_and_wall(map, x - 1, y, debug) {
+ if is_revealed_and(TileType::Wall, map, x - 1, y, debug) {
// W
mask += 4;
}
- if is_revealed_and_wall(map, x + 1, y, debug) {
+ if is_revealed_and(TileType::Wall, map, x + 1, y, debug) {
// E
mask += 8;
}
if diagonals_matter.contains(&mask) {
- if is_revealed_and_wall(map, x + 1, y - 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x + 1, y - 1, debug) {
// Top right
mask += 16;
}
- if is_revealed_and_wall(map, x - 1, y - 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x - 1, y - 1, debug) {
// Top left
mask += 32;
}
- if is_revealed_and_wall(map, x + 1, y + 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x + 1, y + 1, debug) {
// Bottom right
mask += 64;
}
- if is_revealed_and_wall(map, x - 1, y + 1, debug) {
+ if is_revealed_and(TileType::Wall, map, x - 1, y + 1, debug) {
// Bottom left
mask += 128;
}
diff --git a/src/particle_system.rs b/src/particle_system.rs
index 0ff6baa..11e9ed7 100644
--- a/src/particle_system.rs
+++ b/src/particle_system.rs
@@ -83,7 +83,6 @@ fn create_delayed_particles(ecs: &mut World, ctx: &App) {
renderables
.insert(p, Renderable {
sprite: None, // TODO: Particle sprite
- colour_sprite: false,
fg: handled.fg,
bg: handled.bg,
glyph: handled.glyph,
@@ -309,8 +308,7 @@ impl<'a> System<'a> for ParticleSpawnSystem {
.expect("Could not insert position");
renderables
.insert(p, Renderable {
- sprite: None, // TODO: Particle sprite
- colour_sprite: false,
+ sprite: None, // TODO: Particle sprites
fg: new_particle.fg,
bg: new_particle.bg,
glyph: new_particle.glyph,
diff --git a/src/player.rs b/src/player.rs
index b88bd48..9bb80d8 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -135,8 +135,9 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState {
std::mem::drop(renderables);
let mut renderables = ecs.write_storage::();
let render_data = renderables.get_mut(potential_target).unwrap();
- render_data.glyph = to_cp437('+'); // Nethack open door, maybe just use '/' instead.
- render_data.sprite = Some("door_wood_h_closed".to_string()); // TODO: Enum
+ if let Some(sprite) = &mut render_data.sprite {
+ *sprite = sprite.swap();
+ }
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
}
result = RunState::Ticking;
@@ -233,8 +234,9 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState {
std::mem::drop(renderables);
let mut renderables = ecs.write_storage::();
let render_data = renderables.get_mut(potential_target).unwrap();
- render_data.glyph = to_cp437('▓'); // Nethack open door, maybe just use '/' instead.
- render_data.sprite = Some("door_wood_h_open".to_string()); // TODO: Enum
+ if let Some(sprite) = &mut render_data.sprite {
+ *sprite = sprite.swap();
+ }
door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y));
}
result = RunState::Ticking;
diff --git a/src/raws/item_structs.rs b/src/raws/item_structs.rs
index ee74a69..d77034e 100644
--- a/src/raws/item_structs.rs
+++ b/src/raws/item_structs.rs
@@ -27,11 +27,21 @@ pub struct Equippable {
pub to_hit: Option,
}
+#[derive(Deserialize, Debug)]
+pub struct SpriteInfo {
+ pub id: String,
+ pub alt: Option,
+ pub colour: Option,
+ pub x: Option,
+ pub y: Option,
+ pub alt_x: Option,
+ pub alt_y: Option,
+}
+
#[derive(Deserialize, Debug)]
pub struct Renderable {
pub glyph: String,
- pub sprite: Option,
- pub colour_sprite: Option,
+ pub sprite: Option,
pub fg: String,
pub bg: String,
pub order: i32,
diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs
index f9c9e37..7fbdeb9 100644
--- a/src/raws/rawmaster.rs
+++ b/src/raws/rawmaster.rs
@@ -691,11 +691,24 @@ fn get_renderable_component(
) -> crate::components::Renderable {
crate::components::Renderable {
glyph: to_cp437(renderable.glyph.chars().next().unwrap()),
- sprite: renderable.sprite.clone(),
- colour_sprite: if renderable.colour_sprite.is_some() {
- renderable.colour_sprite.clone().unwrap()
+ sprite: if let Some(spriteinfo) = &renderable.sprite {
+ let x = spriteinfo.x.unwrap_or(0.0);
+ let y = spriteinfo.y.unwrap_or(0.0);
+ let alt_x = spriteinfo.alt_x.unwrap_or(0.0);
+ let alt_y = spriteinfo.alt_y.unwrap_or(0.0);
+ Some(SpriteInfo {
+ id: spriteinfo.id.clone(),
+ recolour: if let Some(colour) = spriteinfo.colour {
+ colour
+ } else {
+ false
+ },
+ alt: spriteinfo.alt.clone(),
+ offset: (x, y),
+ alt_offset: (x, y),
+ })
} else {
- true
+ None
},
fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"),
bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"),
diff --git a/src/spawner.rs b/src/spawner.rs
index 1340936..07add86 100644
--- a/src/spawner.rs
+++ b/src/spawner.rs
@@ -29,6 +29,7 @@ use super::{
Intrinsics,
HasAncestry,
HasClass,
+ SpriteInfo,
};
use crate::gui::{ Ancestry, Class };
use crate::consts::entity;
@@ -57,8 +58,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
.with(BlocksTile {})
.with(Renderable {
glyph: to_cp437('@'),
- sprite: Some("@".to_string()), // TODO: Player sprite
- colour_sprite: true,
+ sprite: Some(SpriteInfo::colourable("@")),
fg: RGB::named(YELLOW),
bg: RGB::named(BLACK),
render_order: 0,