diff --git a/.gitignore b/.gitignore index 6d00d4c..e9651ab 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ target wasm/index.css wasm/index.html docs/gifs/* +resources/archived resources # VSCode/IDE config files Cargo.lock @@ -12,7 +13,7 @@ Cargo.lock .prettierrc.json # Save files, morgue files -savegame.json +savegame.bin morgue # A default user config will be written on first run, if not present diff --git a/Cargo.toml b/Cargo.toml index 24b6918..a725d41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,14 +6,16 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +notan = { version = "0.10.0", features = ["text", "audio"] } bracket-lib = { git = "https://github.com/amethyst/bracket-lib.git", rev = "851f6f08675444fb6fa088b9e67bee9fd75554c6", features = ["serde"] } regex = "1.3.6" -specs = { version = "0.16.1", features = ["serde"] } +specs = { version = "0.20.0", features = ["serde"] } specs-derive = "0.4.1" serde = { version = "1.0.93", features = ["derive"]} serde_json = "1.0.39" toml = "0.5" lazy_static = "1.4.0" +bincode = "1.3.3" [dev-dependencies] criterion = { version = "^0.5" } diff --git a/raws/items.json b/raws/items.json index 2c0c678..e2a3d63 100644 --- a/raws/items.json +++ b/raws/items.json @@ -2,27 +2,30 @@ { "id": "potion_health", "name": { "name": "potion of health", "plural": "potions of health" }, - "renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "!", "sprite": "potion", "fg": "#FF00FF", "order": 4 }, + "class": "potion", "weight": 1, "value": 50, - "flags": ["CONSUMABLE", "DESTRUCTIBLE"], + "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "effects": { "heal": "4d4+2" }, "magic": { "class": "uncommon", "naming": "potion" } }, { "id": "potion_health_weak", "name": { "name": "potion of lesser health", "plural": "potions of lesser health" }, - "renderable": { "glyph": "!", "fg": "#FF00FF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "!", "sprite": "potion", "fg": "#FF00FF", "order": 4 }, + "class": "potion", "weight": 1, "value": 25, - "flags": ["CONSUMABLE", "DESTRUCTIBLE"], + "flags": ["CONSUMABLE", "DESTRUCTIBLE", "STACKABLE"], "effects": { "heal": "2d4+2" }, "magic": { "class": "uncommon", "naming": "potion" } }, { "id": "scroll_identify", "name": { "name": "scroll of identify", "plural": "scrolls of identify" }, - "renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#0FFFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 100, "flags": ["CONSUMABLE", "DESTRUCTIBLE", "IDENTIFY"], @@ -31,7 +34,8 @@ { "id": "scroll_removecurse", "name": { "name": "scroll of remove curse", "plural": "scrolls of remove curse" }, - "renderable": { "glyph": "?", "fg": "#0FFFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#0FFFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 200, "flags": ["CONSUMABLE", "DESTRUCTIBLE", "REMOVE_CURSE"], @@ -40,7 +44,8 @@ { "id": "scroll_health", "name": { "name": "scroll of healing word", "plural": "scrolls of healing word" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 50, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -50,7 +55,8 @@ { "id": "scroll_mass_health", "name": { "name": "scroll of mass healing word", "plural": "scrolls of mass healing word" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 200, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -60,7 +66,8 @@ { "id": "scroll_magicmissile", "name": { "name": "scroll of magic missile", "plural": "scrolls of magic missile" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 50, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -70,7 +77,8 @@ { "id": "scroll_embers", "name": { "name": "scroll of embers", "plural": "scrolls of embers" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 100, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -80,7 +88,8 @@ { "id": "scroll_fireball", "name": { "name": "scroll of fireball", "plural": "scrolls of fireball" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 200, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -95,7 +104,8 @@ { "id": "scroll_confusion", "name": { "name": "scroll of confusion", "plural": "scrolls of confusion" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 100, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -105,7 +115,8 @@ { "id": "scroll_mass_confusion", "name": { "name": "scroll of mass confusion", "plural": "scrolls of mass confusion" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 200, "flags": ["CONSUMABLE", "DESTRUCTIBLE"], @@ -115,7 +126,8 @@ { "id": "scroll_magicmap", "name": { "name": "scroll of magic mapping", "plural": "scrolls of magic mapping" }, - "renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "?", "sprite": "scroll_writing", "fg": "#00FFFF", "order": 4 }, + "class": "scroll", "weight": 0.5, "value": 50, "flags": ["CONSUMABLE", "DESTRUCTIBLE", "MAGICMAP"], @@ -125,7 +137,8 @@ { "id": "equip_dagger", "name": { "name": "dagger", "plural": "daggers" }, - "renderable": { "glyph": ")", "fg": "#808080", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "dagger", "fg": "#808080", "order": 4 }, + "class": "weapon", "weight": 1, "value": 2, "flags": ["EQUIP_MELEE"], @@ -134,7 +147,9 @@ { "id": "equip_shortsword", "name": { "name": "shortsword", "plural": "shortswords" }, - "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "shortsword", "fg": "#C0C0C0", "order": 4 }, + "avatar": "a_shortsword", + "class": "weapon", "weight": 2, "value": 10, "flags": ["EQUIP_MELEE"], @@ -143,7 +158,8 @@ { "id": "equip_rapier", "name": { "name": "rapier", "plural": "rapiers" }, - "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "gnome", "fg": "#C0C0C0", "order": 4 }, + "class": "weapon", "weight": 2, "value": 10, "flags": ["EQUIP_MELEE"], @@ -152,7 +168,8 @@ { "id": "equip_pitchfork", "name": { "name": "pitchfork", "plural": "pitchforks" }, - "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "trident", "fg": "#C0C0C0", "order": 4 }, + "class": "weapon", "weight": 2, "value": 5, "flags": ["EQUIP_MELEE"], @@ -161,7 +178,8 @@ { "id": "equip_sickle", "name": { "name": "sickle", "plural": "sickles" }, - "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "gnome", "fg": "#C0C0C0", "order": 4 }, + "class": "weapon", "weight": 2, "value": 5, "flags": ["EQUIP_MELEE"], @@ -170,7 +188,8 @@ { "id": "equip_handaxe", "name": { "name": "handaxe", "plural": "handaxes" }, - "renderable": { "glyph": ")", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "handaxe", "fg": "#C0C0C0", "order": 4 }, + "class": "weapon", "weight": 2, "value": 5, "flags": ["EQUIP_MELEE"], @@ -179,16 +198,29 @@ { "id": "equip_longsword", "name": { "name": "longsword", "plural": "longswords" }, - "renderable": { "glyph": ")", "fg": "#FFF8DC", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": ")", "sprite": "longsword", "fg": "#FFF8DC", "order": 4 }, + "avatar": "a_longsword", + "class": "weapon", "weight": 3, "value": 15, "flags": ["EQUIP_MELEE"], "equip": { "flag": "STRENGTH", "damage": "1d8", "to_hit": 0 } }, + { + "id": "artifact_icingdeath", + "name": { "name": "Icingdeath", "plural": "Icingdeath" }, + "renderable": { "glyph": ")", "sprite": "scimitar", "fg": "#37aecc", "order": 4 }, + "class": "weapon", + "weight": 3, + "value": 300, + "flags": ["EQUIP_MELEE"], + "equip": { "flag": "FINESSE", "damage": "1d8+3;cold", "to_hit": 3 } + }, { "id": "equip_smallshield", "name": { "name": "buckler", "plural": "bucklers" }, - "renderable": { "glyph": "[", "fg": "#808080", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "shield_small", "fg": "#808080", "order": 4 }, + "class": "armour", "weight": 2, "value": 5, "flags": ["EQUIP_SHIELD"], @@ -197,7 +229,9 @@ { "id": "equip_mediumshield", "name": { "name": "medium shield", "plural": "medium shields" }, - "renderable": { "glyph": "[", "fg": "#C0C0C0", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "shield_round", "fg": "#C0C0C0", "order": 4 }, + "avatar": "a_medshield", + "class": "armour", "weight": 6, "value": 10, "flags": ["EQUIP_SHIELD"], @@ -206,7 +240,8 @@ { "id": "equip_largeshield", "name": { "name": "large shield", "plural": "large shields" }, - "renderable": { "glyph": "[", "fg": "#FFF8DC", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "shield_large", "fg": "#FFF8DC", "order": 4 }, + "class": "armour", "weight": 12, "value": 35, "flags": ["EQUIP_SHIELD"], @@ -215,7 +250,8 @@ { "id": "equip_body_weakleather", "name": { "name": "leather jacket", "plural": "leather jackets" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 8, "value": 5, "flags": ["EQUIP_BODY"], @@ -224,7 +260,8 @@ { "id": "equip_body_leather", "name": { "name": "leather chestpiece", "plural": "leather chestpiece" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 10, "value": 10, "flags": ["EQUIP_BODY"], @@ -233,7 +270,8 @@ { "id": "equip_body_studdedleather", "name": { "name": "studded leather chestpiece", "plural": "studded leather chestpieces" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 13, "value": 45, "flags": ["EQUIP_BODY"], @@ -242,7 +280,8 @@ { "id": "equip_body_ringmail_o", "name": { "name": "orcish ring mail", "plural": "orcish ring mail" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 45, "value": 50, "flags": ["EQUIP_BODY"], @@ -251,7 +290,8 @@ { "id": "equip_body_ringmail", "name": { "name": "ring mail", "plural": "ring mail" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 45, "value": 70, "flags": ["EQUIP_BODY"], @@ -260,7 +300,8 @@ { "id": "equip_head_leather", "name": { "name": "leather cap", "plural": "leather caps" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 2, "value": 10, "flags": ["EQUIP_HEAD"], @@ -269,7 +310,8 @@ { "id": "equip_head_elvish", "name": { "name": "elvish leather helm", "plural": "elvish leather helms" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 2, "value": 25, "flags": ["EQUIP_HEAD"], @@ -278,7 +320,8 @@ { "id": "equip_head_o", "name": { "name": "orcish helm", "plural": "orcish helm" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 6, "value": 25, "flags": ["EQUIP_HEAD"], @@ -287,7 +330,8 @@ { "id": "equip_head_iron", "name": { "name": "iron helm", "plural": "iron helm" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 10, "value": 45, "flags": ["EQUIP_HEAD"], @@ -296,7 +340,8 @@ { "id": "equip_feet_leather", "name": { "name": "leather shoes", "plural": "leather shoes" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 2, "value": 10, "flags": ["EQUIP_FEET"] @@ -304,7 +349,8 @@ { "id": "equip_feet_elvish", "name": { "name": "elvish leather shoes", "plural": "elvish leather shoes" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 2, "value": 25, "flags": ["EQUIP_FEET"], @@ -313,7 +359,8 @@ { "id": "equip_feet_o", "name": { "name": "orcish boots", "plural": "orcish boots" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 6, "value": 25, "flags": ["EQUIP_FEET"], @@ -322,7 +369,8 @@ { "id": "equip_feet_iron", "name": { "name": "iron boots", "plural": "iron boots" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 10, "value": 45, "flags": ["EQUIP_FEET"], @@ -331,7 +379,8 @@ { "id": "equip_neck_protection", "name": { "name": "amulet of protection", "plural": "amulets of protection" }, - "renderable": { "glyph": "\"", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "\"", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "amulet", "weight": 1, "value": 200, "flags": ["EQUIP_NECK"], @@ -340,7 +389,8 @@ { "id": "equip_back_protection", "name": { "name": "cloak of protection", "plural": "cloaks of protection" }, - "renderable": { "glyph": "[", "fg": "#aa6000", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "[", "sprite": "body_leather", "fg": "#aa6000", "order": 4 }, + "class": "armour", "weight": 1, "value": 200, "flags": ["EQUIP_BACK"], @@ -349,7 +399,8 @@ { "id": "wand_magicmissile", "name": { "name": "wand of magic missile", "plural": "wands of magic missile" }, - "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "/", "sprite": "body_leather", "fg": "#00FFFF", "order": 4 }, + "class": "wand", "weight": 2, "value": 100, "flags": ["CHARGES"], @@ -359,7 +410,8 @@ { "id": "wand_fireball", "name": { "name": "wand of fireball", "plural": "wands of fireball" }, - "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "/", "sprite": "body_leather", "fg": "#00FFFF", "order": 4 }, + "class": "wand", "weight": 2, "value": 300, "flags": ["CHARGES"], @@ -369,7 +421,8 @@ { "id": "wand_confusion", "name": { "name": "wand of confusion", "plural": "wands of confusion" }, - "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "/", "sprite": "body_leather", "fg": "#00FFFF", "order": 4 }, + "class": "wand", "weight": 2, "value": 200, "flags": ["CHARGES"], @@ -379,7 +432,8 @@ { "id": "wand_digging", "name": { "name": "wand of digging", "plural": "wands of digging" }, - "renderable": { "glyph": "/", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "/", "sprite": "body_leather", "fg": "#00FFFF", "order": 4 }, + "class": "wand", "weight": 2, "value": 300, "flags": ["CHARGES", "DIGGER"], @@ -389,17 +443,19 @@ { "id": "food_rations", "name": { "name": "rations", "plural": "rations" }, - "renderable": { "glyph": "%", "fg": "#FFA07A", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "%", "sprite": "meat", "fg": "#FFA07A", "order": 4 }, + "class": "comestible", "weight": 1, "value": 1, - "flags": ["FOOD", "CONSUMABLE"] + "flags": ["FOOD", "CONSUMABLE", "STACKABLE"] }, { "id": "food_apple", "name": { "name": "apple", "plural": "apples" }, - "renderable": { "glyph": "%", "fg": "#00FF00", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "%", "sprite": "body_leather", "fg": "#00FF00", "order": 4 }, + "class": "comestible", "weight": 0.5, "value": 1, - "flags": ["FOOD", "CONSUMABLE"] + "flags": ["FOOD", "CONSUMABLE", "STACKABLE"] } ] diff --git a/raws/mobs.json b/raws/mobs.json index ddd6556..0d1c427 100644 --- a/raws/mobs.json +++ b/raws/mobs.json @@ -2,7 +2,7 @@ { "id": "npc_barkeep", "name": "barkeep", - "renderable": { "glyph": "@", "fg": "#EE82EE", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#EE82EE", "order": 3 }, "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": "@", "fg": "#9fa86c", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#9fa86c", "order": 3 }, "flags": ["NEUTRAL", "RANDOM_PATH", "IS_HUMAN"], "vision_range": 4, "quips": ["Hello!", "Good morning.", ""] @@ -18,7 +18,7 @@ { "id": "npc_drunk", "name": "drunk", - "renderable": { "glyph": "@", "fg": "#a0a83c", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#a0a83c", "order": 3 }, "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": "@", "fg": "#3ca3a8", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#3ca3a8", "order": 3 }, "flags": ["NEUTRAL", "IS_HUMAN"], "vision_range": 4, "quips": ["Hey."] @@ -34,7 +34,7 @@ { "id": "npc_dockworker", "name": "dock worker", - "renderable": { "glyph": "@", "fg": "#68d8de", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#68d8de", "order": 3 }, "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": "@", "fg": "#FFFFFF", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#FFFFFF", "order": 3 }, "flags": ["NEUTRAL", "IS_HUMAN"], "vision_range": 4, "quips": ["Light's givings.", "", "Bless you."] @@ -50,7 +50,7 @@ { "id": "npc_miner", "name": "miner", - "renderable": { "glyph": "@", "fg": "#946123", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#946123", "order": 3 }, "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": "@", "fg": "#034efc", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "@", "sprite": "gnome", "fg": "#034efc", "order": 3 }, "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", "fg": "#aa6000", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "r", "sprite": "rat", "fg": "#aa6000", "order": 3 }, "flags": [], "bac": 6, "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }], @@ -78,7 +78,7 @@ { "id": "chicken", "name": "chicken", - "renderable": { "glyph": "c", "fg": "#BB6000", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "c", "sprite": "gnome", "fg": "#BB6000", "order": 3 }, "flags": ["HERBIVORE"], "bac": 8, "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }] @@ -86,7 +86,7 @@ { "id": "deer_little", "name": "fawn", - "renderable": { "glyph": "q", "fg": "#a57037", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "q", "sprite": "gnome", "fg": "#a57037", "order": 3 }, "flags": ["HERBIVORE"], "bac": 8, "attacks": [{ "name": "kicks", "hit_bonus": 0, "damage": "1d2" }] @@ -94,7 +94,7 @@ { "id": "sheep_little", "name": "lamb", - "renderable": { "glyph": "q", "fg": "#e7e7e7", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "q", "sprite": "gnome", "fg": "#e7e7e7", "order": 3 }, "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", "fg": "#fae478", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "c", "sprite": "gnome", "fg": "#fae478", "order": 3 }, "flags": ["HERBIVORE"], "bac": 10, "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }] @@ -110,7 +110,7 @@ { "id": "horse_little", "name": "pony", - "renderable": { "glyph": "u", "fg": "#b36c29", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "u", "sprite": "horse", "fg": "#b36c29", "order": 3 }, "flags": ["HERBIVORE", "MULTIATTACK"], "level": 3, "bac": 6, @@ -124,7 +124,7 @@ { "id": "horse", "name": "horse", - "renderable": { "glyph": "u", "fg": "#744d29", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "u", "sprite": "horse", "fg": "#744d29", "order": 3 }, "flags": ["MULTIATTACK"], "level": 5, "bac": 5, @@ -137,7 +137,7 @@ { "id": "horse_large", "name": "warhorse", - "renderable": { "glyph": "u", "fg": "#8a3520", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "u", "sprite": "horse", "fg": "#8a3520", "order": 3 }, "flags": ["MULTIATTACK"], "level": 7, "bac": 4, @@ -150,7 +150,7 @@ { "id": "rat_giant", "name": "giant rat", - "renderable": { "glyph": "r", "fg": "#bb8000", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "r", "sprite": "rat_large", "fg": "#bb8000", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 1, "bac": 7, @@ -160,7 +160,7 @@ { "id": "dog_little", "name": "little dog", - "renderable": { "glyph": "d", "fg": "#FFFFFF", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#FFFFFF", "order": 3 }, "flags": ["NEUTRAL"], "level": 2, "bac": 6, @@ -171,7 +171,7 @@ { "id": "dog", "name": "dog", - "renderable": { "glyph": "d", "fg": "#EEEEEE", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#EEEEEE", "order": 3 }, "flags": [], "level": 4, "bac": 5, @@ -181,7 +181,7 @@ { "id": "dog_large", "name": "large dog", - "renderable": { "glyph": "d", "fg": "#DDDDDD", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#DDDDDD", "order": 3 }, "flags": [], "level": 6, "bac": 4, @@ -191,7 +191,7 @@ { "id": "gnome", "name": "gnome", - "renderable": { "glyph": "G", "fg": "#AA5500", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "G", "sprite": "gnome", "fg": "#AA5500", "order": 3 }, "flags": ["SMALL_GROUP", "IS_GNOME"], "level": 1, "speed": 6, @@ -201,18 +201,17 @@ { "id": "zombie_gnome", "name": "gnome zombie", - "renderable": { "glyph": "z", "fg": "#AA5500", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "z", "sprite": "gnome", "fg": "#AA5500", "order": 3 }, "flags": ["MINDLESS"], "level": 1, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d4" }], "loot": { "table": "wands", "chance": 0.05 } }, { "id": "goblin", "name": "goblin", - "renderable": { "glyph": "g", "fg": "#00FF00", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "g", "sprite": "goblin", "fg": "#00FF00", "order": 3 }, "flags": [], "level": 1, "speed": 9, @@ -221,7 +220,7 @@ { "id": "kobold", "name": "kobold", - "renderable": { "glyph": "k", "fg": "#AA5500", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "k", "sprite": "kobold", "fg": "#AA5500", "order": 3 }, "flags": [], "level": 1, "speed": 6, @@ -231,41 +230,38 @@ { "id": "zombie_kobold", "name": "kobold zombie", - "renderable": { "glyph": "z", "fg": "#AA5500", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "z", "sprite": "kobold", "fg": "#AA5500", "order": 3 }, "flags": ["MINDLESS"], "level": 1, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d4" }], "loot": { "table": "scrolls", "chance": 0.05 } }, { "id": "kobold_large", "name": "large kobold", - "renderable": { "glyph": "k", "fg": "#70461b", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "k", "sprite": "kobold_large", "fg": "#70461b", "order": 3 }, "flags": [], "level": 1, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "1d6" }], "loot": { "table": "food", "chance": 0.05 } }, { "id": "zombie_orc", "name": "orc zombie", - "renderable": { "glyph": "z", "fg": "#dbd830", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "z", "sprite": "orc", "fg": "#dbd830", "order": 3 }, "flags": ["MINDLESS"], "level": 2, "bac": 9, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }], "loot": { "table": "potions", "chance": 0.05 } }, { "id": "dwarf", "name": "dwarf", - "renderable": { "glyph": "h", "fg": "#d61b1b", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "h", "sprite": "dwarf", "fg": "#d61b1b", "order": 3 }, "flags": ["IS_DWARF"], "level": 2, "bac": 10, @@ -277,30 +273,28 @@ { "id": "zombie_dwarf", "name": "dwarf zombie", - "renderable": { "glyph": "z", "fg": "#d61b1b", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "z", "sprite": "dwarf", "fg": "#d61b1b", "order": 3 }, "flags": ["MINDLESS"], "level": 2, "bac": 9, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "claws", "hit_bonus": 0, "damage": "1d6" }], "loot": { "table": "equipment", "chance": 0.05 } }, { "id": "kobold_captain", "name": "kobold captain", - "renderable": { "glyph": "k", "fg": "#9331ac", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "k", "sprite": "kobold_c", "fg": "#9331ac", "order": 3 }, "flags": [], "level": 2, "speed": 6, - "vision_range": 12, "attacks": [{ "name": "hits", "hit_bonus": 0, "damage": "2d4" }], "loot": { "table": "food", "chance": 0.05 } }, { "id": "spider_cave", "name": "cave spider", - "renderable": { "glyph": "s", "fg": "#6b6b6b", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "s", "sprite": "spider", "fg": "#6b6b6b", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 1, "bac": 3, @@ -311,7 +305,7 @@ { "id": "ant_worker", "name": "worker ant", - "renderable": { "glyph": "a", "fg": "#ca7631", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "a", "sprite": "ant", "fg": "#ca7631", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 2, "bac": 3, @@ -322,7 +316,7 @@ { "id": "ant_soldier", "name": "soldier ant", - "renderable": { "glyph": "a", "fg": "#ca3f26", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "a", "sprite": "ant", "fg": "#ca3f26", "order": 3 }, "flags": ["SMALL_GROUP", "POISON_RES"], "level": 3, "bac": 3, @@ -336,7 +330,7 @@ { "id": "caterpillar_cave", "name": "caterpillar", - "renderable": { "glyph": "a", "fg": "#6b6b6b", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "a", "sprite": "caterpillar", "fg": "#6b6b6b", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 1, "bac": 3, @@ -347,7 +341,7 @@ { "id": "caterpillar_giant", "name": "giant caterpillar", - "renderable": { "glyph": "a", "fg": "#b9aeae", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "a", "sprite": "caterpillar", "fg": "#b9aeae", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 2, "bac": 7, @@ -358,7 +352,7 @@ { "id": "jackal", "name": "jackal", - "renderable": { "glyph": "d", "fg": "#AA5500", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#AA5500", "order": 3 }, "flags": ["CARNIVORE", "SMALL_GROUP"], "bac": 7, "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d2" }] @@ -366,7 +360,7 @@ { "id": "fox", "name": "fox", - "renderable": { "glyph": "d", "fg": "#FF0000", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#FF0000", "order": 3 }, "flags": ["CARNIVORE"], "bac": 7, "attacks": [{ "name": "bites", "hit_bonus": 0, "damage": "1d3" }] @@ -374,7 +368,7 @@ { "id": "coyote", "name": "coyote", - "renderable": { "glyph": "d", "fg": "#6E3215", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#6E3215", "order": 3 }, "flags": ["CARNIVORE", "SMALL_GROUP"], "level": 1, "bac": 7, @@ -383,7 +377,7 @@ { "id": "wolf", "name": "wolf", - "renderable": { "glyph": "d", "fg": "#5E4225", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#5E4225", "order": 3 }, "flags": ["CARNIVORE"], "level": 5, "bac": 4, @@ -392,7 +386,7 @@ { "id": "goblin_chieftain", "name": "goblin chieftain", - "renderable": { "glyph": "g", "fg": "#9331ac", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "g", "sprite": "goblin_c", "fg": "#9331ac", "order": 3 }, "flags": [], "level": 2, "speed": 9, @@ -402,7 +396,7 @@ { "id": "orc", "name": "orc", - "renderable": { "glyph": "o", "fg": "#00FF00", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "o", "sprite": "orc", "fg": "#00FF00", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 1, "speed": 9, @@ -412,7 +406,7 @@ { "id": "orc_hill", "name": "hill orc", - "renderable": { "glyph": "o", "fg": "#dbd830", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "o", "sprite": "orc", "fg": "#dbd830", "order": 3 }, "flags": ["LARGE_GROUP"], "level": 2, "speed": 9, @@ -422,7 +416,7 @@ { "id": "orc_captain", "name": "orc captain", - "renderable": { "glyph": "o", "fg": "#9331ac", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "o", "sprite": "orc", "fg": "#9331ac", "order": 3 }, "flags": ["MULTIATTACK"], "level": 5, "speed": 5, @@ -435,7 +429,7 @@ { "id": "warg", "name": "warg", - "renderable": { "glyph": "d", "fg": "#8b7164", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "d", "sprite": "dog", "fg": "#8b7164", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 7, "bac": 4, @@ -446,7 +440,7 @@ { "id": "jaguar", "name": "jaguar", - "renderable": { "glyph": "f", "fg": "#d3b947", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "f", "sprite": "cat_large", "fg": "#d3b947", "order": 3 }, "flags": ["MULTIATTACK"], "level": 4, "bac": 6, @@ -461,7 +455,7 @@ { "id": "lynx", "name": "lynx", - "renderable": { "glyph": "f", "fg": "#b5d347", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "f", "sprite": "cat_large", "fg": "#b5d347", "order": 3 }, "flags": ["MULTIATTACK"], "level": 5, "bac": 6, @@ -476,7 +470,7 @@ { "id": "panther", "name": "panther", - "renderable": { "glyph": "f", "fg": "#58554e", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "f", "sprite": "cat_large", "fg": "#58554e", "order": 3 }, "flags": ["MULTIATTACK"], "level": 5, "bac": 6, @@ -491,7 +485,7 @@ { "id": "ogre", "name": "ogre", - "renderable": { "glyph": "O", "fg": "#10A70d", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "O", "sprite": "ogre", "fg": "#10A70d", "order": 3 }, "flags": ["SMALL_GROUP"], "level": 5, "bac": 5, @@ -502,7 +496,7 @@ { "id": "treant_small", "name": "treant sapling", - "renderable": { "glyph": "♠️", "fg": "#10570d", "bg": "#000000", "order": 1 }, + "renderable": { "glyph": "♠️", "sprite": "gnome", "fg": "#10570d", "order": 3 }, "flags": ["LARGE_GROUP", "GREEN_BLOOD", "FIRE_WEAK"], "level": 2, "bac": 12, diff --git a/raws/props.json b/raws/props.json index 0c48291..4ac454a 100644 --- a/raws/props.json +++ b/raws/props.json @@ -2,83 +2,89 @@ { "id": "door", "name": "door", - "renderable": { "glyph": "+", "fg": "#00FFFF", "bg": "#000000", "order": 2 }, - "flags": ["DOOR"] + "renderable": { "glyph": "+", "sprite": "door", "alt": "door_open", "fg": "#00FFFF", "order": 5 }, + "door": { "open": false, "locked": false, "blocks_vis": true, "blocks_move": true } + }, + { + "id": "trapdoor", + "name": "trapdoor", + "renderable": { "glyph": "+", "sprite": "trapdoor", "alt": "trapdoor_open", "fg": "#00FFFF", "order": 5, "alt_order": 1 }, + "door": { "open": false, "locked": false, "blocks_vis": false, "blocks_move": false } }, { "id": "prop_altar", "name": "altar", - "renderable": { "glyph": "_", "fg": "#FFFFFF", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "_", "sprite": "altar", "fg": "#FFFFFF", "order": 5 }, "flags": ["ENTRY_TRIGGER"], "effects": { "heal": "8d8" } }, { "id": "prop_keg", "name": "keg", - "renderable": { "glyph": "φ", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "φ", "sprite": "gnome", "fg": "#AAAAAA", "order": 5 }, "flags": [] }, { "id": "prop_table", "name": "table", - "renderable": { "glyph": "-", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "-", "sprite": "table", "fg": "#a76d3d", "order": 5 }, "flags": [] }, { "id": "prop_hay", "name": "hay", - "renderable": { "glyph": "%", "fg": "#c7ad39", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "%", "sprite": "plants", "fg": "#e2b82f", "order": 5 }, "flags": [] }, { "id": "prop_statue", "name": "statue", - "renderable": { "glyph": "@", "fg": "#ffffff", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "@", "sprite": "altar", "fg": "#ffffff", "order": 5 }, "flags": [] }, { "id": "prop_bed", "name": "bed", - "renderable": { "glyph": "=", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "=", "sprite": "bed", "fg": "#a55d33", "order": 5 }, "flags": [] }, { "id": "prop_chair", "name": "chair", - "renderable": { "glyph": "└", "fg": "#AAAAAA", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "└", "sprite": "chair_r", "fg": "#a76d3d", "order": 5 }, "flags": [] }, { "id": "prop_candle", "name": "candle", - "renderable": { "glyph": "Ä", "fg": "#FFA500", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "Ä", "sprite": "candelabra", "fg": "#FFA500", "order": 4 }, "flags": [] }, { "id": "trap_bear", "name": "bear trap", - "renderable": { "glyph": "^", "fg": "#e6e6e6", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "^", "sprite": "beartrap", "fg": "#e6e6e6", "order": 5 }, "flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"], "effects": { "damage": "2d4" } }, { "id": "trap_mini_mine", "name": "mini-mine", - "renderable": { "glyph": "^", "fg": "#ff1e00", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "^", "sprite": "minimine", "fg": "#ff1e00", "order": 5 }, "flags": ["ENTRY_TRIGGER", "SINGLE_ACTIVATION"], "effects": { "damage": "2d4", "aoe": "3" } }, { "id": "trap_stonefall", "name": "stonefall trap", - "renderable": { "glyph": "^", "fg": "#beb5a7", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "^", "sprite": "stones", "fg": "#beb5a7", "order": 5 }, "flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"], "effects": { "damage": "2d10" } }, { "id": "trap_confusion", "name": "magic trap", - "renderable": { "glyph": "^", "fg": "#df07df", "bg": "#000000", "order": 2 }, + "renderable": { "glyph": "^", "sprite": "magic_trap", "fg": "#df07df", "order": 5 }, "flags": ["HIDDEN", "ENTRY_TRIGGER", "SINGLE_ACTIVATION"], "effects": { "confusion": "3" } } diff --git a/resources/atlas.json b/resources/atlas.json new file mode 100644 index 0000000..6895a1b --- /dev/null +++ b/resources/atlas.json @@ -0,0 +1,2556 @@ +{"frames": [ + +{ + "filename": "a_buckler", + "frame": {"x":0,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_cloak", + "frame": {"x":16,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_crucifix", + "frame": {"x":32,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_dagger", + "frame": {"x":48,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_dagger2", + "frame": {"x":64,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_dagger_curved", + "frame": {"x":80,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_dagger_curved2", + "frame": {"x":96,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_dagger_jagged", + "frame": {"x":112,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_glaive", + "frame": {"x":128,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_halberd", + "frame": {"x":144,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_longsword", + "frame": {"x":160,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_medshield", + "frame": {"x":176,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_quarterstaff", + "frame": {"x":192,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_scimitar", + "frame": {"x":208,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_scimitar2", + "frame": {"x":224,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_scythe", + "frame": {"x":240,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_shortsword", + "frame": {"x":256,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_spear", + "frame": {"x":272,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_staff", + "frame": {"x":288,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_staff_spiked", + "frame": {"x":304,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_staff_wood", + "frame": {"x":320,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "a_staff_wood2", + "frame": {"x":336,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "altar", + "frame": {"x":352,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "ant", + "frame": {"x":368,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-0", + "frame": {"x":384,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-2", + "frame": {"x":400,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-3", + "frame": {"x":416,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-4", + "frame": {"x":432,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-5", + "frame": {"x":448,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-6", + "frame": {"x":464,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-7", + "frame": {"x":384,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-8", + "frame": {"x":480,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-9", + "frame": {"x":496,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-10", + "frame": {"x":512,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-11", + "frame": {"x":528,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-12", + "frame": {"x":544,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar-13", + "frame": {"x":560,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "avatar", + "frame": {"x":576,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-9", + "frame": {"x":592,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-10", + "frame": {"x":608,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-11", + "frame": {"x":624,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-12", + "frame": {"x":640,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-13", + "frame": {"x":656,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-14", + "frame": {"x":672,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-15", + "frame": {"x":688,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-16", + "frame": {"x":704,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-17", + "frame": {"x":720,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-18", + "frame": {"x":736,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-19", + "frame": {"x":752,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-20", + "frame": {"x":768,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-21", + "frame": {"x":784,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-23", + "frame": {"x":800,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-33", + "frame": {"x":816,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-34", + "frame": {"x":832,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-35", + "frame": {"x":848,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-36", + "frame": {"x":864,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-37", + "frame": {"x":880,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-38", + "frame": {"x":896,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-39", + "frame": {"x":912,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-40", + "frame": {"x":928,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-41", + "frame": {"x":944,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-42", + "frame": {"x":960,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-44", + "frame": {"x":976,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-46", + "frame": {"x":992,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-47", + "frame": {"x":1008,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-48", + "frame": {"x":1024,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-49", + "frame": {"x":1040,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-50", + "frame": {"x":1056,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-51", + "frame": {"x":1072,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-52", + "frame": {"x":1088,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-53", + "frame": {"x":1104,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-54", + "frame": {"x":1120,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-55", + "frame": {"x":1136,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-56", + "frame": {"x":1152,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-57", + "frame": {"x":1168,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-58", + "frame": {"x":1184,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-59", + "frame": {"x":1200,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-60", + "frame": {"x":1216,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-61", + "frame": {"x":1232,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-62", + "frame": {"x":1248,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-63", + "frame": {"x":1264,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-64", + "frame": {"x":1280,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-65", + "frame": {"x":1296,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-66", + "frame": {"x":1312,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-67", + "frame": {"x":1328,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-68", + "frame": {"x":1344,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-69", + "frame": {"x":1360,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-70", + "frame": {"x":1376,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-71", + "frame": {"x":1392,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-72", + "frame": {"x":1408,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-73", + "frame": {"x":1424,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-74", + "frame": {"x":1440,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-76", + "frame": {"x":1456,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-77", + "frame": {"x":1472,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-78", + "frame": {"x":1488,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-79", + "frame": {"x":1504,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-80", + "frame": {"x":1520,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-81", + "frame": {"x":1536,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-82", + "frame": {"x":1552,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "Avatar_Equipment-83", + "frame": {"x":1568,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (1)", + "frame": {"x":1584,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (2)", + "frame": {"x":1600,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (3)", + "frame": {"x":1616,"y":0,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (4)", + "frame": {"x":0,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (5)", + "frame": {"x":16,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (6)", + "frame": {"x":32,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "back (7)", + "frame": {"x":48,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "bars", + "frame": {"x":64,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "beartrap", + "frame": {"x":80,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "bed", + "frame": {"x":96,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-7", + "frame": {"x":112,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-8", + "frame": {"x":128,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-9", + "frame": {"x":144,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-10", + "frame": {"x":160,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-11", + "frame": {"x":176,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-12", + "frame": {"x":192,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood-13", + "frame": {"x":208,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood1", + "frame": {"x":224,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood2", + "frame": {"x":240,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood3", + "frame": {"x":256,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood4", + "frame": {"x":272,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood5", + "frame": {"x":288,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood6", + "frame": {"x":304,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "blood7", + "frame": {"x":320,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (1)", + "frame": {"x":336,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (3)", + "frame": {"x":352,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (4)", + "frame": {"x":368,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (5)", + "frame": {"x":384,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (6)", + "frame": {"x":400,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (7)", + "frame": {"x":416,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (8)", + "frame": {"x":432,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (9)", + "frame": {"x":448,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body (10)", + "frame": {"x":464,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "body_leather", + "frame": {"x":480,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "candelabra", + "frame": {"x":496,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "cat", + "frame": {"x":512,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "cat_large", + "frame": {"x":528,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "caterpillar", + "frame": {"x":544,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "chair_r", + "frame": {"x":560,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "cracked", + "frame": {"x":576,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "dagger", + "frame": {"x":592,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "dog", + "frame": {"x":608,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "door", + "frame": {"x":624,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "door_open", + "frame": {"x":640,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "dot", + "frame": {"x":656,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "dwarf", + "frame": {"x":672,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "explode1", + "frame": {"x":688,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "explode2", + "frame": {"x":704,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "explode3", + "frame": {"x":720,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (1)", + "frame": {"x":736,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (2)", + "frame": {"x":752,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (3)", + "frame": {"x":768,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (4)", + "frame": {"x":784,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (5)", + "frame": {"x":800,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (6)", + "frame": {"x":816,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "feet (7)", + "frame": {"x":832,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "fence", + "frame": {"x":848,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "fluff", + "frame": {"x":864,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "fluff2", + "frame": {"x":880,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-0", + "frame": {"x":896,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-1", + "frame": {"x":912,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-3", + "frame": {"x":928,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-4", + "frame": {"x":944,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-5", + "frame": {"x":656,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-6", + "frame": {"x":960,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-7", + "frame": {"x":976,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-8", + "frame": {"x":656,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-9", + "frame": {"x":992,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-10", + "frame": {"x":1008,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-11", + "frame": {"x":656,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-12", + "frame": {"x":1024,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-13", + "frame": {"x":1040,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-14", + "frame": {"x":1056,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-21", + "frame": {"x":1072,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-22", + "frame": {"x":1088,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-23", + "frame": {"x":1104,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-24", + "frame": {"x":1120,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-25", + "frame": {"x":1136,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-26", + "frame": {"x":1152,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-27", + "frame": {"x":1168,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-28", + "frame": {"x":1184,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-29", + "frame": {"x":1200,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-30", + "frame": {"x":1216,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-31", + "frame": {"x":1232,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-32", + "frame": {"x":1248,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-33", + "frame": {"x":1264,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-34", + "frame": {"x":1280,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-35", + "frame": {"x":1296,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-36", + "frame": {"x":1312,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-37", + "frame": {"x":1328,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-38", + "frame": {"x":1344,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-39", + "frame": {"x":1360,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-40", + "frame": {"x":1376,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-41", + "frame": {"x":1392,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-42", + "frame": {"x":1408,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-43", + "frame": {"x":1424,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-44", + "frame": {"x":1440,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-45", + "frame": {"x":1456,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-46", + "frame": {"x":1472,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-47", + "frame": {"x":1488,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-48", + "frame": {"x":1504,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-49", + "frame": {"x":1520,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-50", + "frame": {"x":1536,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-51", + "frame": {"x":1552,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-52", + "frame": {"x":1568,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-53", + "frame": {"x":1584,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-54", + "frame": {"x":1600,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "general-55", + "frame": {"x":1616,"y":24,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "gnome", + "frame": {"x":0,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "goblin", + "frame": {"x":16,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "goblin_c", + "frame": {"x":32,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "grass", + "frame": {"x":48,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "grass_flower", + "frame": {"x":64,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "grass_small", + "frame": {"x":80,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "handaxe", + "frame": {"x":96,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (1)", + "frame": {"x":112,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (2)", + "frame": {"x":128,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (3)", + "frame": {"x":144,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (4)", + "frame": {"x":160,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (5)", + "frame": {"x":176,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (6)", + "frame": {"x":192,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (7)", + "frame": {"x":208,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (8)", + "frame": {"x":224,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (9)", + "frame": {"x":240,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "head (10)", + "frame": {"x":256,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "horse", + "frame": {"x":272,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "kobold", + "frame": {"x":288,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "kobold_captain", + "frame": {"x":304,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "kobold_large", + "frame": {"x":320,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "legs (1)", + "frame": {"x":336,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "legs (2)", + "frame": {"x":352,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "legs (3)", + "frame": {"x":368,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "legs (4)", + "frame": {"x":384,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "legs (5)", + "frame": {"x":400,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "magic_trap", + "frame": {"x":416,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "meat", + "frame": {"x":432,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "minimine", + "frame": {"x":448,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "neck", + "frame": {"x":464,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "ogre", + "frame": {"x":480,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "orc", + "frame": {"x":496,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "planks", + "frame": {"x":512,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "planks_missing", + "frame": {"x":528,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "planks_missing2", + "frame": {"x":544,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "plants", + "frame": {"x":560,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "potion", + "frame": {"x":576,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "potion_beaker", + "frame": {"x":592,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "potion_conical", + "frame": {"x":608,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "potion_large", + "frame": {"x":624,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-0", + "frame": {"x":640,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-1", + "frame": {"x":656,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-2", + "frame": {"x":672,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-3", + "frame": {"x":688,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-4", + "frame": {"x":704,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-5", + "frame": {"x":720,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-6", + "frame": {"x":736,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-7", + "frame": {"x":752,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-8", + "frame": {"x":768,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-9", + "frame": {"x":784,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-10", + "frame": {"x":800,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-11", + "frame": {"x":816,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-12", + "frame": {"x":832,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-13", + "frame": {"x":848,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-14", + "frame": {"x":864,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-15", + "frame": {"x":880,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-16", + "frame": {"x":896,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-17", + "frame": {"x":912,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-18", + "frame": {"x":928,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-19", + "frame": {"x":944,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-20", + "frame": {"x":960,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-21", + "frame": {"x":960,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-22", + "frame": {"x":960,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-23", + "frame": {"x":960,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-24", + "frame": {"x":960,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-25", + "frame": {"x":976,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-26", + "frame": {"x":976,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-27", + "frame": {"x":976,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-28", + "frame": {"x":976,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "projectiles-29", + "frame": {"x":976,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "rat", + "frame": {"x":992,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "rat_large", + "frame": {"x":1008,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "scimitar", + "frame": {"x":1024,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "scroll", + "frame": {"x":1040,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "scroll_writing", + "frame": {"x":1056,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "select1", + "frame": {"x":1072,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "shield_large", + "frame": {"x":1088,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "shield_round", + "frame": {"x":1104,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "shield_small", + "frame": {"x":1120,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "shortsword", + "frame": {"x":1136,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "slash1", + "frame": {"x":1152,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "slash2", + "frame": {"x":1168,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "slash3", + "frame": {"x":1184,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "spider", + "frame": {"x":1200,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "spider_large", + "frame": {"x":1216,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "stair_down", + "frame": {"x":1232,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "stair_up", + "frame": {"x":1248,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "statue", + "frame": {"x":1264,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "stones", + "frame": {"x":1280,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "table", + "frame": {"x":1296,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "table_l_chair", + "frame": {"x":1312,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "table_r", + "frame": {"x":1328,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles", + "frame": {"x":1344,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles2", + "frame": {"x":1360,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles3", + "frame": {"x":1376,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles4", + "frame": {"x":1392,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing", + "frame": {"x":1408,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing2", + "frame": {"x":1424,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing3", + "frame": {"x":1440,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing4", + "frame": {"x":1456,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing5", + "frame": {"x":1472,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "tiles_missing6", + "frame": {"x":1488,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "trapdoor", + "frame": {"x":1504,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "trapdoor_open", + "frame": {"x":1520,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "trident", + "frame": {"x":1536,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "wall", + "frame": {"x":1552,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "wall_b", + "frame": {"x":1568,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "wall_b_cracked", + "frame": {"x":1584,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "water", + "frame": {"x":1600,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}, +{ + "filename": "water2", + "frame": {"x":1616,"y":48,"w":16,"h":24}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":24}, + "sourceSize": {"w":16,"h":24} +}], +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas.png", + "format": "RGBA8888", + "size": {"w":1632,"h":72}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:c374bf5911369e72338caa541920625e:27c0f39076e478374d6d24a0d676685f:cbce6b53f0f49e0bf15173c25c41f876$" +} +} diff --git a/resources/atlas.png b/resources/atlas.png new file mode 100644 index 0000000..9e66c0c Binary files /dev/null and b/resources/atlas.png differ diff --git a/resources/curses14x16.png b/resources/curses14x16.png deleted file mode 100644 index a06abb6..0000000 Binary files a/resources/curses14x16.png and /dev/null differ diff --git a/resources/fonts/Greybeard-16px-Bold.ttf b/resources/fonts/Greybeard-16px-Bold.ttf new file mode 100644 index 0000000..2572e2e Binary files /dev/null and b/resources/fonts/Greybeard-16px-Bold.ttf differ diff --git a/resources/fonts/Greybeard-16px-Italic.ttf b/resources/fonts/Greybeard-16px-Italic.ttf new file mode 100644 index 0000000..565f839 Binary files /dev/null and b/resources/fonts/Greybeard-16px-Italic.ttf differ diff --git a/resources/fonts/Greybeard-16px.ttf b/resources/fonts/Greybeard-16px.ttf new file mode 100644 index 0000000..9448244 Binary files /dev/null and b/resources/fonts/Greybeard-16px.ttf differ diff --git a/resources/fonts/Swanston-Bold.ttf b/resources/fonts/Swanston-Bold.ttf new file mode 100644 index 0000000..9522db0 Binary files /dev/null and b/resources/fonts/Swanston-Bold.ttf differ diff --git a/resources/fonts/Swanston.ttf b/resources/fonts/Swanston.ttf new file mode 100644 index 0000000..d4eda57 Binary files /dev/null and b/resources/fonts/Swanston.ttf differ diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..eec840a Binary files /dev/null and b/resources/icon.png differ diff --git a/resources/sounds/amb/relaxed.ogg b/resources/sounds/amb/relaxed.ogg new file mode 100644 index 0000000..b153791 Binary files /dev/null and b/resources/sounds/amb/relaxed.ogg differ diff --git a/resources/sounds/door/blocked1.wav b/resources/sounds/door/blocked1.wav new file mode 100644 index 0000000..6fe3643 Binary files /dev/null and b/resources/sounds/door/blocked1.wav differ diff --git a/resources/sounds/door/blocked2.wav b/resources/sounds/door/blocked2.wav new file mode 100644 index 0000000..44885c7 Binary files /dev/null and b/resources/sounds/door/blocked2.wav differ diff --git a/resources/sounds/door/blocked3.wav b/resources/sounds/door/blocked3.wav new file mode 100644 index 0000000..310459b Binary files /dev/null and b/resources/sounds/door/blocked3.wav differ diff --git a/resources/sounds/door/close1.wav b/resources/sounds/door/close1.wav new file mode 100644 index 0000000..0590632 Binary files /dev/null and b/resources/sounds/door/close1.wav differ diff --git a/resources/sounds/door/close2.wav b/resources/sounds/door/close2.wav new file mode 100644 index 0000000..c3b181d Binary files /dev/null and b/resources/sounds/door/close2.wav differ diff --git a/resources/sounds/door/close3.wav b/resources/sounds/door/close3.wav new file mode 100644 index 0000000..604db8e Binary files /dev/null and b/resources/sounds/door/close3.wav differ diff --git a/resources/sounds/door/open1.wav b/resources/sounds/door/open1.wav new file mode 100644 index 0000000..c98b961 Binary files /dev/null and b/resources/sounds/door/open1.wav differ diff --git a/resources/sounds/door/open2.wav b/resources/sounds/door/open2.wav new file mode 100644 index 0000000..38b5bd3 Binary files /dev/null and b/resources/sounds/door/open2.wav differ diff --git a/resources/sounds/door/open3.wav b/resources/sounds/door/open3.wav new file mode 100644 index 0000000..1252ce8 Binary files /dev/null and b/resources/sounds/door/open3.wav differ diff --git a/resources/sounds/hit.wav b/resources/sounds/hit.wav new file mode 100644 index 0000000..44fd686 Binary files /dev/null and b/resources/sounds/hit.wav differ diff --git a/resources/sounds/hit/whoosh1.ogg b/resources/sounds/hit/whoosh1.ogg new file mode 100644 index 0000000..efa1a04 Binary files /dev/null and b/resources/sounds/hit/whoosh1.ogg differ diff --git a/resources/sounds/hit/whoosh2.ogg b/resources/sounds/hit/whoosh2.ogg new file mode 100644 index 0000000..e4dfd54 Binary files /dev/null and b/resources/sounds/hit/whoosh2.ogg differ diff --git a/resources/sounds/hit/whoosh3.ogg b/resources/sounds/hit/whoosh3.ogg new file mode 100644 index 0000000..7ffda42 Binary files /dev/null and b/resources/sounds/hit/whoosh3.ogg differ diff --git a/resources/sounds/hit/whoosh4.ogg b/resources/sounds/hit/whoosh4.ogg new file mode 100644 index 0000000..5e2b4a2 Binary files /dev/null and b/resources/sounds/hit/whoosh4.ogg differ diff --git a/resources/td.json b/resources/td.json new file mode 100644 index 0000000..01b6abf --- /dev/null +++ b/resources/td.json @@ -0,0 +1,7482 @@ +{"frames": [ + +{ + "filename": "!", + "frame": {"x":0,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "#", + "frame": {"x":16,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "$", + "frame": {"x":32,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "%", + "frame": {"x":48,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "&", + "frame": {"x":64,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "'", + "frame": {"x":80,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "(", + "frame": {"x":96,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": ")", + "frame": {"x":112,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "+", + "frame": {"x":128,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": ",", + "frame": {"x":144,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": ".", + "frame": {"x":160,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "0", + "frame": {"x":176,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "1", + "frame": {"x":192,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "2", + "frame": {"x":208,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "3", + "frame": {"x":224,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "4", + "frame": {"x":240,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "5", + "frame": {"x":256,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "6", + "frame": {"x":272,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "7", + "frame": {"x":288,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "8", + "frame": {"x":304,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "9", + "frame": {"x":320,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "12", + "frame": {"x":336,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "13", + "frame": {"x":352,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "14", + "frame": {"x":368,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "15", + "frame": {"x":384,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "16", + "frame": {"x":400,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "17", + "frame": {"x":416,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "18", + "frame": {"x":432,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "19", + "frame": {"x":448,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "20", + "frame": {"x":464,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "21", + "frame": {"x":480,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "22", + "frame": {"x":496,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "23", + "frame": {"x":512,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "24", + "frame": {"x":528,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "25", + "frame": {"x":544,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "26", + "frame": {"x":560,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "27", + "frame": {"x":576,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "28", + "frame": {"x":592,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "29", + "frame": {"x":608,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "30", + "frame": {"x":624,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "43", + "frame": {"x":640,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "56", + "frame": {"x":656,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "57", + "frame": {"x":672,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "58", + "frame": {"x":688,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "60", + "frame": {"x":704,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "122", + "frame": {"x":720,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "124", + "frame": {"x":736,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "125", + "frame": {"x":752,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "126", + "frame": {"x":768,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "127", + "frame": {"x":784,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "128", + "frame": {"x":800,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "129", + "frame": {"x":816,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "130", + "frame": {"x":832,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "131", + "frame": {"x":848,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "132", + "frame": {"x":864,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "133", + "frame": {"x":880,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "134", + "frame": {"x":896,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "135", + "frame": {"x":912,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "136", + "frame": {"x":928,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "137", + "frame": {"x":944,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "138", + "frame": {"x":960,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "139", + "frame": {"x":976,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "140", + "frame": {"x":992,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "141", + "frame": {"x":1008,"y":0,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "142", + "frame": {"x":0,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "143", + "frame": {"x":16,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "144", + "frame": {"x":32,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "145", + "frame": {"x":48,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "146", + "frame": {"x":64,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "147", + "frame": {"x":80,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "148", + "frame": {"x":96,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "149", + "frame": {"x":112,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "150", + "frame": {"x":128,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "151", + "frame": {"x":144,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "152", + "frame": {"x":160,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "153", + "frame": {"x":176,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "154", + "frame": {"x":192,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "155", + "frame": {"x":208,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "156", + "frame": {"x":224,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "157", + "frame": {"x":240,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "158", + "frame": {"x":256,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "159", + "frame": {"x":272,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "160", + "frame": {"x":288,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "161", + "frame": {"x":304,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "162", + "frame": {"x":320,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "163", + "frame": {"x":336,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "164", + "frame": {"x":352,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "165", + "frame": {"x":368,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "166", + "frame": {"x":384,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "167", + "frame": {"x":400,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "168", + "frame": {"x":416,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "169", + "frame": {"x":432,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "170", + "frame": {"x":448,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "171", + "frame": {"x":464,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "172", + "frame": {"x":480,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "173", + "frame": {"x":496,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "174", + "frame": {"x":512,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "175", + "frame": {"x":528,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "176", + "frame": {"x":544,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "178", + "frame": {"x":560,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "179", + "frame": {"x":576,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "180", + "frame": {"x":592,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "181", + "frame": {"x":608,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "182", + "frame": {"x":624,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "183", + "frame": {"x":640,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "184", + "frame": {"x":656,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "185", + "frame": {"x":672,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "186", + "frame": {"x":688,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "187", + "frame": {"x":704,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "188", + "frame": {"x":720,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "191", + "frame": {"x":736,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "192", + "frame": {"x":752,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "193", + "frame": {"x":768,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "195", + "frame": {"x":784,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "196", + "frame": {"x":800,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "197", + "frame": {"x":816,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "198", + "frame": {"x":832,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "199", + "frame": {"x":848,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "200", + "frame": {"x":864,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "201", + "frame": {"x":880,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "202", + "frame": {"x":896,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "203", + "frame": {"x":912,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "204", + "frame": {"x":928,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "205", + "frame": {"x":944,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "206", + "frame": {"x":960,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "207", + "frame": {"x":976,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "208", + "frame": {"x":992,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "209", + "frame": {"x":1008,"y":16,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "210", + "frame": {"x":0,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "211", + "frame": {"x":16,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "212", + "frame": {"x":32,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "213", + "frame": {"x":48,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "214", + "frame": {"x":64,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "217", + "frame": {"x":80,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "218", + "frame": {"x":96,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "219", + "frame": {"x":112,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "220", + "frame": {"x":128,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "221", + "frame": {"x":144,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "222", + "frame": {"x":160,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "223", + "frame": {"x":176,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "224", + "frame": {"x":192,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "225", + "frame": {"x":208,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "226", + "frame": {"x":224,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "227", + "frame": {"x":240,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "228", + "frame": {"x":256,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "229", + "frame": {"x":272,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "230", + "frame": {"x":288,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "231", + "frame": {"x":304,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "232", + "frame": {"x":320,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "233", + "frame": {"x":336,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "234", + "frame": {"x":352,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "235", + "frame": {"x":368,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "236", + "frame": {"x":384,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "237", + "frame": {"x":400,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "238", + "frame": {"x":416,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "239", + "frame": {"x":432,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "240", + "frame": {"x":448,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "241", + "frame": {"x":464,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "242", + "frame": {"x":480,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "243", + "frame": {"x":496,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "244", + "frame": {"x":512,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "245", + "frame": {"x":528,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "246", + "frame": {"x":544,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "247", + "frame": {"x":560,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "248", + "frame": {"x":576,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "249", + "frame": {"x":592,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "250", + "frame": {"x":608,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "251", + "frame": {"x":624,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "252", + "frame": {"x":640,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "=", + "frame": {"x":656,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "@", + "frame": {"x":672,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "[", + "frame": {"x":688,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "]", + "frame": {"x":704,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "^", + "frame": {"x":720,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "_", + "frame": {"x":736,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "`", + "frame": {"x":752,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "a", + "frame": {"x":768,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "a2", + "frame": {"x":784,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid", + "frame": {"x":800,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid_a1", + "frame": {"x":816,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid_a2", + "frame": {"x":832,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid_edge", + "frame": {"x":848,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid_edge_a1", + "frame": {"x":864,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "acid_edge_a2", + "frame": {"x":880,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "amulet_gold", + "frame": {"x":896,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "amulet_magic", + "frame": {"x":912,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "amulet_silver", + "frame": {"x":928,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "arrow", + "frame": {"x":944,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "asterisk", + "frame": {"x":960,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "b", + "frame": {"x":976,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "b2", + "frame": {"x":992,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "backslash", + "frame": {"x":1008,"y":32,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bandage", + "frame": {"x":0,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bed", + "frame": {"x":16,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blank", + "frame": {"x":32,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blood_a", + "frame": {"x":48,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blood_b", + "frame": {"x":64,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blood_bone", + "frame": {"x":80,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blood_c", + "frame": {"x":96,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "blood_d", + "frame": {"x":112,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bolt", + "frame": {"x":128,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bones_a", + "frame": {"x":144,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bones_b", + "frame": {"x":160,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bones_d", + "frame": {"x":176,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "book_black", + "frame": {"x":192,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "book_brown", + "frame": {"x":208,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "book_green", + "frame": {"x":224,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bookshelf_a", + "frame": {"x":240,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "bookshelf_b", + "frame": {"x":256,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "c", + "frame": {"x":272,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "c2", + "frame": {"x":288,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "caltrops", + "frame": {"x":304,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "campfire1", + "frame": {"x":320,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "campfire2", + "frame": {"x":336,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "campfire_stones", + "frame": {"x":352,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_a1", + "frame": {"x":368,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_a2", + "frame": {"x":384,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_b1", + "frame": {"x":400,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_b2", + "frame": {"x":416,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_c1", + "frame": {"x":432,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "candles_c2", + "frame": {"x":448,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cape_leather", + "frame": {"x":464,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cape_magic", + "frame": {"x":480,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cape_purple", + "frame": {"x":496,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cauldron1", + "frame": {"x":512,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cauldron2", + "frame": {"x":528,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "chair", + "frame": {"x":544,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "chest", + "frame": {"x":560,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "chest_empty", + "frame": {"x":576,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "club", + "frame": {"x":592,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "coins_copper", + "frame": {"x":608,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "coins_gold", + "frame": {"x":624,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "coins_silver", + "frame": {"x":640,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "compass", + "frame": {"x":656,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crate", + "frame": {"x":672,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crate_broken", + "frame": {"x":688,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "cross", + "frame": {"x":704,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crown_evil", + "frame": {"x":720,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crown_gold", + "frame": {"x":736,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crown_silver", + "frame": {"x":752,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crystal_empty", + "frame": {"x":768,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "crystal_full", + "frame": {"x":784,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "d", + "frame": {"x":800,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "d2", + "frame": {"x":816,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "darts", + "frame": {"x":832,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "diamond", + "frame": {"x":848,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_h_closed", + "frame": {"x":864,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_h_open", + "frame": {"x":880,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_v_closed1", + "frame": {"x":896,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_v_closed2", + "frame": {"x":912,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_v_open1", + "frame": {"x":928,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_evil_v_open2", + "frame": {"x":944,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_h_closed", + "frame": {"x":960,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_h_open", + "frame": {"x":976,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_v_closed", + "frame": {"x":992,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_v_closed2", + "frame": {"x":1008,"y":48,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_v_open1", + "frame": {"x":0,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_gate_v_open2", + "frame": {"x":16,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_h_closed", + "frame": {"x":32,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_h_open", + "frame": {"x":48,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_v_closed1", + "frame": {"x":64,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_v_closed2", + "frame": {"x":80,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_v_open1", + "frame": {"x":96,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_stone_v_open2", + "frame": {"x":112,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_h_closed", + "frame": {"x":128,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_h_closed2", + "frame": {"x":144,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_h_open", + "frame": {"x":160,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_v_closed1", + "frame": {"x":176,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_v_open1", + "frame": {"x":192,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "door_wood_v_open2", + "frame": {"x":208,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "dot", + "frame": {"x":224,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "dot_outline", + "frame": {"x":240,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "e", + "frame": {"x":256,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "e2", + "frame": {"x":272,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "f", + "frame": {"x":288,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "f2", + "frame": {"x":304,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "feather", + "frame": {"x":320,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "female", + "frame": {"x":336,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "flask_blue", + "frame": {"x":352,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "flask_green", + "frame": {"x":368,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "flask_red", + "frame": {"x":384,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_carpet_a", + "frame": {"x":400,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_carpet_b", + "frame": {"x":416,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_carpet_c", + "frame": {"x":432,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_carpet_d", + "frame": {"x":448,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_carpet_e", + "frame": {"x":464,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_a", + "frame": {"x":480,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_b", + "frame": {"x":496,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_c", + "frame": {"x":512,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_d", + "frame": {"x":528,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_drain", + "frame": {"x":544,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_e", + "frame": {"x":560,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_f", + "frame": {"x":576,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble2_pit_edge", + "frame": {"x":592,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_a-119", + "frame": {"x":608,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_a", + "frame": {"x":624,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_b-120", + "frame": {"x":640,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_b", + "frame": {"x":656,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_c-121", + "frame": {"x":672,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_c", + "frame": {"x":688,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_d-122", + "frame": {"x":704,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_d", + "frame": {"x":720,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_drain", + "frame": {"x":736,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_e-123", + "frame": {"x":752,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_e", + "frame": {"x":768,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_f", + "frame": {"x":784,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_cobble_pit_edge", + "frame": {"x":800,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_a", + "frame": {"x":816,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_b", + "frame": {"x":832,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_c", + "frame": {"x":848,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_d", + "frame": {"x":864,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_e", + "frame": {"x":880,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_f", + "frame": {"x":896,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_hole", + "frame": {"x":912,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_dirt_pit_edge", + "frame": {"x":928,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_a", + "frame": {"x":944,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_b", + "frame": {"x":960,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_c", + "frame": {"x":976,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_d", + "frame": {"x":992,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_e", + "frame": {"x":1008,"y":64,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_f", + "frame": {"x":0,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_hole", + "frame": {"x":16,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_path_a", + "frame": {"x":32,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_path_b", + "frame": {"x":48,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_path_d", + "frame": {"x":64,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_pit_edge", + "frame": {"x":80,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_grass_tile_c", + "frame": {"x":96,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_mossy_a", + "frame": {"x":112,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_mossy_b", + "frame": {"x":128,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_mossy_c", + "frame": {"x":144,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_mossy_d", + "frame": {"x":160,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_mossy_e", + "frame": {"x":176,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_pit", + "frame": {"x":192,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile2_a", + "frame": {"x":208,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile2_b", + "frame": {"x":224,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile2_c", + "frame": {"x":240,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile2_d", + "frame": {"x":256,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile2_e", + "frame": {"x":272,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile3_a", + "frame": {"x":288,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile3_b", + "frame": {"x":304,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile3_c", + "frame": {"x":320,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile3_d", + "frame": {"x":336,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile3_e", + "frame": {"x":352,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile_a", + "frame": {"x":368,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile_b", + "frame": {"x":384,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile_c", + "frame": {"x":400,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile_d", + "frame": {"x":416,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_tile_e", + "frame": {"x":432,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_wood_a", + "frame": {"x":448,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_wood_b", + "frame": {"x":464,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_wood_c", + "frame": {"x":480,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "floor_wood_d", + "frame": {"x":496,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "g", + "frame": {"x":512,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "g2", + "frame": {"x":528,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "gem_amethyst", + "frame": {"x":544,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "gem_garnet", + "frame": {"x":560,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "gem_jade", + "frame": {"x":576,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "gem_ruby", + "frame": {"x":592,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "gem_sapphire", + "frame": {"x":608,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_a", + "frame": {"x":624,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_b", + "frame": {"x":640,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_c", + "frame": {"x":656,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_d", + "frame": {"x":672,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_e", + "frame": {"x":688,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_root_a", + "frame": {"x":704,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_root_b", + "frame": {"x":720,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_root_c", + "frame": {"x":736,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_root_d", + "frame": {"x":752,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "grass_root_e", + "frame": {"x":768,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "h", + "frame": {"x":784,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "h2", + "frame": {"x":800,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "hat_leather", + "frame": {"x":816,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "hat_magic", + "frame": {"x":832,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "hat_purple", + "frame": {"x":848,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "heart", + "frame": {"x":864,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "heart_empty", + "frame": {"x":880,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "heart_full", + "frame": {"x":896,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "herb_gold", + "frame": {"x":912,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "herb_green", + "frame": {"x":928,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "herb_red", + "frame": {"x":944,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_door_closed", + "frame": {"x":960,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_door_open", + "frame": {"x":976,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_roof_a", + "frame": {"x":992,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_roof_b", + "frame": {"x":1008,"y":80,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_roof_c", + "frame": {"x":0,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_roof_edge_a", + "frame": {"x":16,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_roof_edge_b", + "frame": {"x":32,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_wall", + "frame": {"x":48,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "house_wall_lit", + "frame": {"x":64,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "i", + "frame": {"x":80,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "i2", + "frame": {"x":96,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "j", + "frame": {"x":112,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "j2", + "frame": {"x":128,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "k", + "frame": {"x":144,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "k2", + "frame": {"x":160,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "key_gold", + "frame": {"x":176,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "key_magic", + "frame": {"x":192,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "key_skeleton", + "frame": {"x":208,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "l", + "frame": {"x":224,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "l2", + "frame": {"x":240,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava", + "frame": {"x":256,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava_a1", + "frame": {"x":272,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava_a2", + "frame": {"x":288,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava_edge", + "frame": {"x":304,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava_edge_a1", + "frame": {"x":320,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lava_edge_a2", + "frame": {"x":336,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "leather_boot", + "frame": {"x":352,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "leather_chest", + "frame": {"x":368,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "leather_glove", + "frame": {"x":384,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "leather_helm", + "frame": {"x":400,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "leather_pant", + "frame": {"x":416,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "level_right", + "frame": {"x":432,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lever_left", + "frame": {"x":448,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_a1", + "frame": {"x":464,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_a2", + "frame": {"x":480,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_b1", + "frame": {"x":496,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_b2", + "frame": {"x":512,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_c1", + "frame": {"x":528,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_c2", + "frame": {"x":544,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_d1", + "frame": {"x":560,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "lilypad_d2", + "frame": {"x":576,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_1", + "frame": {"x":592,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_2", + "frame": {"x":608,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_3", + "frame": {"x":624,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_4", + "frame": {"x":640,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_6", + "frame": {"x":656,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_7", + "frame": {"x":672,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_8", + "frame": {"x":688,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "line_9", + "frame": {"x":704,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "m", + "frame": {"x":720,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "m2", + "frame": {"x":736,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_a", + "frame": {"x":752,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_b", + "frame": {"x":768,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_boot", + "frame": {"x":784,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_c", + "frame": {"x":800,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_chest", + "frame": {"x":816,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_d", + "frame": {"x":832,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_e1", + "frame": {"x":848,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_e2", + "frame": {"x":864,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_glove", + "frame": {"x":880,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_helm", + "frame": {"x":896,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "magic_pant", + "frame": {"x":912,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "male", + "frame": {"x":928,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "map", + "frame": {"x":944,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mud_a1", + "frame": {"x":960,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mud_a2", + "frame": {"x":976,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mud_edge_a1", + "frame": {"x":992,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mud_edge_a2", + "frame": {"x":1008,"y":96,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "murky_a1", + "frame": {"x":0,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "murky_a2", + "frame": {"x":16,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "murky_edge_a1", + "frame": {"x":32,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "murky_edge_a2", + "frame": {"x":48,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mushroom_pink", + "frame": {"x":64,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mushroom_red", + "frame": {"x":80,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "mushroom_yellow", + "frame": {"x":96,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "n", + "frame": {"x":112,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "n2", + "frame": {"x":128,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "o", + "frame": {"x":144,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "o2", + "frame": {"x":160,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "p", + "frame": {"x":176,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "p2", + "frame": {"x":192,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "potion_black", + "frame": {"x":208,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "potion_blue", + "frame": {"x":224,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "potion_green", + "frame": {"x":240,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "potion_red", + "frame": {"x":256,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "potion_yellow", + "frame": {"x":272,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "q", + "frame": {"x":288,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "q2", + "frame": {"x":304,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "question_mark", + "frame": {"x":320,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "quiver", + "frame": {"x":336,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "quote", + "frame": {"x":352,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "r", + "frame": {"x":368,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "r2", + "frame": {"x":384,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ring", + "frame": {"x":400,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ring_gold", + "frame": {"x":416,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ring_magic", + "frame": {"x":432,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ring_outline", + "frame": {"x":448,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ring_silver", + "frame": {"x":464,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "rope", + "frame": {"x":480,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "s", + "frame": {"x":496,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "s2", + "frame": {"x":512,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "sack", + "frame": {"x":528,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "scroll", + "frame": {"x":544,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shadow", + "frame": {"x":560,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shield_magic", + "frame": {"x":576,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shield_steel", + "frame": {"x":592,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shield_wood", + "frame": {"x":608,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shrub_a", + "frame": {"x":624,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "shrub_b", + "frame": {"x":640,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "sign_blank", + "frame": {"x":656,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "sign_inn", + "frame": {"x":672,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "sign_potions", + "frame": {"x":688,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "sign_weapons", + "frame": {"x":704,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "skull", + "frame": {"x":720,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "skull_gold", + "frame": {"x":736,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slab_a", + "frame": {"x":752,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slab_b", + "frame": {"x":768,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slab_left", + "frame": {"x":784,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slab_middle", + "frame": {"x":800,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slab_right", + "frame": {"x":816,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "slash", + "frame": {"x":832,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "smile", + "frame": {"x":848,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "smile_hollow", + "frame": {"x":864,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "spade", + "frame": {"x":880,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "stalagmite_a", + "frame": {"x":896,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "stalagmite_b", + "frame": {"x":912,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "statue_tentacle", + "frame": {"x":928,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "statue_warrior", + "frame": {"x":944,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "statue_winged", + "frame": {"x":960,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "steel_boot", + "frame": {"x":976,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "steel_chest", + "frame": {"x":992,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "steel_glove", + "frame": {"x":1008,"y":112,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "steel_helm", + "frame": {"x":0,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "steel_pant", + "frame": {"x":16,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "stone", + "frame": {"x":32,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "stone_cave", + "frame": {"x":48,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "stone_grey", + "frame": {"x":64,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp", + "frame": {"x":80,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp_a1", + "frame": {"x":96,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp_a2", + "frame": {"x":112,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp_edge", + "frame": {"x":128,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp_edge_a1", + "frame": {"x":144,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "swamp_edge_a2", + "frame": {"x":160,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "t", + "frame": {"x":176,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "t2", + "frame": {"x":192,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table", + "frame": {"x":208,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_left_a", + "frame": {"x":224,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_left_b", + "frame": {"x":240,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_middle_a", + "frame": {"x":256,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_middle_b", + "frame": {"x":272,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_right_a", + "frame": {"x":288,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "table_right_b", + "frame": {"x":304,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "throne_evil", + "frame": {"x":320,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "throne_wood", + "frame": {"x":336,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "tiny_dungeon_web", + "frame": {"x":352,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "token_copper", + "frame": {"x":368,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "token_gold", + "frame": {"x":384,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "token_silver", + "frame": {"x":400,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "tombstone", + "frame": {"x":416,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "tombstone_broken", + "frame": {"x":432,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch1", + "frame": {"x":448,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch2", + "frame": {"x":464,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch_b1", + "frame": {"x":480,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch_b2", + "frame": {"x":496,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch_light1", + "frame": {"x":512,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "torch_light2", + "frame": {"x":528,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "trap", + "frame": {"x":544,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "trapdoor_closed", + "frame": {"x":560,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "trapdoor_open1", + "frame": {"x":576,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "trapdoor_open2", + "frame": {"x":592,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "turkey", + "frame": {"x":608,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "u", + "frame": {"x":624,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "u2", + "frame": {"x":640,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_scroll_1", + "frame": {"x":656,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_scroll_2", + "frame": {"x":672,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_scroll_3", + "frame": {"x":688,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_scroll_tab", + "frame": {"x":704,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_stone_1", + "frame": {"x":720,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_stone_2", + "frame": {"x":736,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_stone_3", + "frame": {"x":752,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_h_stone_tab", + "frame": {"x":768,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_scroll_1", + "frame": {"x":784,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_scroll_2", + "frame": {"x":800,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_scroll_3", + "frame": {"x":816,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_stone_1", + "frame": {"x":832,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_stone_2", + "frame": {"x":848,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bar_v_stone_3", + "frame": {"x":864,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_1", + "frame": {"x":880,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_2", + "frame": {"x":896,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_3", + "frame": {"x":912,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_4", + "frame": {"x":928,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_5", + "frame": {"x":944,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_6", + "frame": {"x":960,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_7", + "frame": {"x":976,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_8", + "frame": {"x":992,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_9", + "frame": {"x":1008,"y":128,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_l1", + "frame": {"x":0,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_l2", + "frame": {"x":16,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_m1", + "frame": {"x":32,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_m2", + "frame": {"x":48,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_r1", + "frame": {"x":64,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_bubble_arrow_r2", + "frame": {"x":80,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_scroll_1", + "frame": {"x":96,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_scroll_2", + "frame": {"x":112,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_scroll_press_1", + "frame": {"x":128,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_scroll_press_2", + "frame": {"x":144,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_stone_1", + "frame": {"x":160,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_stone_2", + "frame": {"x":176,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_stone_press_1", + "frame": {"x":192,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_button_stone_press_2", + "frame": {"x":208,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_check_scroll", + "frame": {"x":224,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_check_scroll_checked", + "frame": {"x":240,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_check_stone", + "frame": {"x":256,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_check_stone_checked", + "frame": {"x":272,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_close_scroll", + "frame": {"x":288,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_close_scroll_press", + "frame": {"x":304,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_close_stone", + "frame": {"x":320,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_close_stone_press", + "frame": {"x":336,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_crystal_empty", + "frame": {"x":352,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_crystal_full", + "frame": {"x":368,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_arrow_1", + "frame": {"x":384,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_arrow_2", + "frame": {"x":400,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_crosshair2_1", + "frame": {"x":416,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_crosshair2_2", + "frame": {"x":432,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_crosshair_1", + "frame": {"x":448,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_crosshair_2", + "frame": {"x":464,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_finger_1", + "frame": {"x":480,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_finger_2", + "frame": {"x":496,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_grab_1", + "frame": {"x":512,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_grab_2", + "frame": {"x":528,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_hand_1", + "frame": {"x":544,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_hand_2", + "frame": {"x":560,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_magnify_1", + "frame": {"x":576,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_magnify_2", + "frame": {"x":592,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_pointer_1", + "frame": {"x":608,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_pointer_2", + "frame": {"x":624,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_redo_1", + "frame": {"x":640,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_redo_2", + "frame": {"x":656,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_reduce_1", + "frame": {"x":672,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_reduce_2", + "frame": {"x":688,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_target_1", + "frame": {"x":704,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_target_2", + "frame": {"x":720,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_triangle_1", + "frame": {"x":736,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_triangle_2", + "frame": {"x":752,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_undo_1", + "frame": {"x":768,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_undo_2", + "frame": {"x":784,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_watch_1", + "frame": {"x":800,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_cursor_watch_2", + "frame": {"x":816,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_heart_empty", + "frame": {"x":832,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_heart_full", + "frame": {"x":848,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_empty_1", + "frame": {"x":864,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_empty_2", + "frame": {"x":880,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_empty_3", + "frame": {"x":896,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_full_1", + "frame": {"x":912,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_full_2", + "frame": {"x":928,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_hp_full_3", + "frame": {"x":944,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_empty_1", + "frame": {"x":960,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_empty_2", + "frame": {"x":976,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_empty_3", + "frame": {"x":992,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_full_1", + "frame": {"x":1008,"y":144,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_full_2", + "frame": {"x":0,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_mp_full_3", + "frame": {"x":16,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_alert", + "frame": {"x":32,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_alert_press", + "frame": {"x":48,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_attack", + "frame": {"x":64,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_attack_press", + "frame": {"x":80,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_bag", + "frame": {"x":96,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_bag_press", + "frame": {"x":112,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_blank", + "frame": {"x":128,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_blank_press", + "frame": {"x":144,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_cancel", + "frame": {"x":160,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_cancel_press", + "frame": {"x":176,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_defend", + "frame": {"x":192,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_defend_press", + "frame": {"x":208,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_equip", + "frame": {"x":224,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_equip_press", + "frame": {"x":240,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_go", + "frame": {"x":256,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_go_press", + "frame": {"x":272,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_item", + "frame": {"x":288,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_item_press", + "frame": {"x":304,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_magic", + "frame": {"x":320,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_magic_press", + "frame": {"x":336,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_setting", + "frame": {"x":352,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_option_setting_press", + "frame": {"x":368,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_1", + "frame": {"x":384,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_2", + "frame": {"x":400,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_3", + "frame": {"x":416,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_4", + "frame": {"x":432,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_5", + "frame": {"x":448,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_6", + "frame": {"x":464,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_7", + "frame": {"x":480,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_8", + "frame": {"x":496,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_a_9", + "frame": {"x":512,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_1", + "frame": {"x":528,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_2", + "frame": {"x":544,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_3", + "frame": {"x":560,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_4", + "frame": {"x":576,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_5", + "frame": {"x":592,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_6", + "frame": {"x":608,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_7", + "frame": {"x":624,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_8", + "frame": {"x":640,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_scroll_b_9", + "frame": {"x":656,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_1", + "frame": {"x":672,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_2", + "frame": {"x":688,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_3", + "frame": {"x":704,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_4", + "frame": {"x":720,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_5", + "frame": {"x":736,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_6", + "frame": {"x":752,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_7", + "frame": {"x":768,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_8", + "frame": {"x":784,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_a_9", + "frame": {"x":800,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_1", + "frame": {"x":816,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_2", + "frame": {"x":832,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_3", + "frame": {"x":848,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_4", + "frame": {"x":864,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_5", + "frame": {"x":880,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_6", + "frame": {"x":896,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_7", + "frame": {"x":912,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_8", + "frame": {"x":928,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_stone_b_9", + "frame": {"x":944,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_1", + "frame": {"x":960,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_2", + "frame": {"x":976,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_3", + "frame": {"x":992,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_4", + "frame": {"x":1008,"y":160,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_6", + "frame": {"x":0,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_7", + "frame": {"x":16,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_8", + "frame": {"x":32,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_white_9", + "frame": {"x":48,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_1", + "frame": {"x":64,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_2", + "frame": {"x":80,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_3", + "frame": {"x":96,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_4", + "frame": {"x":112,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_5", + "frame": {"x":128,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_6", + "frame": {"x":144,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_7", + "frame": {"x":160,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_8", + "frame": {"x":176,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_panel_window_9", + "frame": {"x":192,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_a1", + "frame": {"x":208,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_a2", + "frame": {"x":224,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_b1", + "frame": {"x":240,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_b2", + "frame": {"x":256,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_c1", + "frame": {"x":272,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_c2", + "frame": {"x":288,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_d1", + "frame": {"x":304,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_d2", + "frame": {"x":320,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_e1", + "frame": {"x":336,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_e2", + "frame": {"x":352,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_f1", + "frame": {"x":368,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "ui_select_f2", + "frame": {"x":384,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "urns_a", + "frame": {"x":400,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "urns_b", + "frame": {"x":416,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "urns_c", + "frame": {"x":432,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "v", + "frame": {"x":448,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "v2", + "frame": {"x":464,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "w", + "frame": {"x":480,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "w2", + "frame": {"x":496,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_a", + "frame": {"x":512,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_b", + "frame": {"x":528,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_c", + "frame": {"x":544,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_crack", + "frame": {"x":560,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_d", + "frame": {"x":576,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_h_e", + "frame": {"x":592,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_pool_empty", + "frame": {"x":608,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_pool_full", + "frame": {"x":624,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_stair_down", + "frame": {"x":640,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_stair_up", + "frame": {"x":656,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_a", + "frame": {"x":672,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_b", + "frame": {"x":688,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_c", + "frame": {"x":704,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_crack", + "frame": {"x":720,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_d", + "frame": {"x":736,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_cave_v_e", + "frame": {"x":752,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_a", + "frame": {"x":768,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_b", + "frame": {"x":784,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_c", + "frame": {"x":800,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_crack", + "frame": {"x":816,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_d", + "frame": {"x":832,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_h_e", + "frame": {"x":848,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_pool_empty", + "frame": {"x":864,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_pool_full", + "frame": {"x":880,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_stair_down", + "frame": {"x":896,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_stair_up", + "frame": {"x":912,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_a", + "frame": {"x":928,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_b", + "frame": {"x":944,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_c", + "frame": {"x":960,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_crack", + "frame": {"x":976,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_d", + "frame": {"x":992,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_crypt_v_e", + "frame": {"x":1008,"y":176,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_a", + "frame": {"x":0,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_b", + "frame": {"x":16,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_c", + "frame": {"x":32,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_crack", + "frame": {"x":48,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_d", + "frame": {"x":64,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_h_e", + "frame": {"x":80,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_pool_empty", + "frame": {"x":96,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_pool_full", + "frame": {"x":112,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_stair_down", + "frame": {"x":128,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_stair_up", + "frame": {"x":144,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_a", + "frame": {"x":160,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_b", + "frame": {"x":176,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_c", + "frame": {"x":192,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_crack", + "frame": {"x":208,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_d", + "frame": {"x":224,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_sewer_v_e", + "frame": {"x":240,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_a", + "frame": {"x":256,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_b", + "frame": {"x":272,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_c", + "frame": {"x":288,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_crack", + "frame": {"x":304,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_d", + "frame": {"x":320,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_h_e", + "frame": {"x":336,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_pool_empty", + "frame": {"x":352,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_pool_full", + "frame": {"x":368,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_stair_down", + "frame": {"x":384,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_stair_up", + "frame": {"x":400,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_a", + "frame": {"x":416,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_b", + "frame": {"x":432,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_c", + "frame": {"x":448,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_crack", + "frame": {"x":464,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_d", + "frame": {"x":480,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "wall_stone_v_e", + "frame": {"x":496,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water", + "frame": {"x":512,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water_a1", + "frame": {"x":528,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water_a2", + "frame": {"x":544,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water_edge", + "frame": {"x":560,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water_edge_a1", + "frame": {"x":576,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "water_edge_a2", + "frame": {"x":592,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_axe", + "frame": {"x":608,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_bow", + "frame": {"x":624,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_club", + "frame": {"x":640,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_crossbow", + "frame": {"x":656,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_dagger", + "frame": {"x":672,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_hammer", + "frame": {"x":688,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_mace", + "frame": {"x":704,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_quarterstaff", + "frame": {"x":720,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_shortsword", + "frame": {"x":736,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_sling", + "frame": {"x":752,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_staff", + "frame": {"x":768,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "weapon_sword", + "frame": {"x":784,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "web_ne", + "frame": {"x":800,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "web_nw", + "frame": {"x":816,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "web_se", + "frame": {"x":832,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "web_sw", + "frame": {"x":848,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "x", + "frame": {"x":864,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "x2", + "frame": {"x":880,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "y", + "frame": {"x":896,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "y2", + "frame": {"x":912,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "z", + "frame": {"x":928,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "z2", + "frame": {"x":944,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "{", + "frame": {"x":960,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "}", + "frame": {"x":976,"y":192,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16}, + "pivot": {"x":0.5,"y":0.5} +}], +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "td.png", + "format": "RGBA8888", + "size": {"w":1024,"h":208}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:07a9ac60f3f803e2bb4cf3274af6e938:211f76101834176fb30513a82f6c6f41:b057e16954bd2c3b14e3adce68b72f2a$" +} +} diff --git a/resources/td.png b/resources/td.png new file mode 100644 index 0000000..0a8358d Binary files /dev/null and b/resources/td.png differ diff --git a/src/ai/approach_ai_system.rs b/src/ai/approach_ai_system.rs index c3cc2ca..6e6e7a8 100644 --- a/src/ai/approach_ai_system.rs +++ b/src/ai/approach_ai_system.rs @@ -45,6 +45,7 @@ impl<'a> System<'a> for ApproachAI { continue; }; let mut path: Option = None; + let mut curr_abs_diff = 100; let idx = map.xy_idx(pos.x, pos.y); for tar_idx in target_idxs { 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() { 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; + } } } } diff --git a/src/ai/encumbrance_system.rs b/src/ai/encumbrance_system.rs index 0244597..5f39f3c 100644 --- a/src/ai/encumbrance_system.rs +++ b/src/ai/encumbrance_system.rs @@ -1,7 +1,7 @@ use crate::{ gamelog, Attributes, Burden, EquipmentChanged, Equipped, InBackpack, Item, Pools }; use specs::prelude::*; use std::collections::HashMap; -use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH; +use crate::consts::entity::CARRY_CAPACITY_PER_STRENGTH; pub struct EncumbranceSystem {} @@ -20,7 +20,17 @@ impl<'a> System<'a> for EncumbranceSystem { ); fn run(&mut self, data: Self::SystemData) { - let (mut equip_dirty, entities, items, backpacks, wielded, mut pools, attributes, player, mut burdened) = data; + let ( + mut equip_dirty, + entities, + items, + backpacks, + wielded, + mut pools, + attributes, + player, + mut burdened, + ) = data; if equip_dirty.is_empty() { return; } @@ -50,7 +60,7 @@ impl<'a> System<'a> for EncumbranceSystem { pool.weight = *weight; if let Some(attr) = attributes.get(*entity) { let carry_capacity_lbs = - (attr.strength.base + attr.strength.modifiers) * CARRY_CAPACITY_PER_STRENGTH; + (attr.strength.base + attr.strength.bonuses) * CARRY_CAPACITY_PER_STRENGTH; if (pool.weight as i32) > 3 * carry_capacity_lbs { // Overloaded burdened diff --git a/src/ai/energy_system.rs b/src/ai/energy_system.rs index da62467..8a68b69 100644 --- a/src/ai/energy_system.rs +++ b/src/ai/energy_system.rs @@ -1,4 +1,4 @@ -use crate::data::entity::*; +use crate::consts::entity::*; use crate::{ Burden, BurdenLevel, @@ -15,7 +15,7 @@ use crate::{ use bracket_lib::prelude::*; use specs::prelude::*; use crate::config::CONFIG; -use crate::data::events::*; +use crate::consts::events::*; pub struct EnergySystem {} diff --git a/src/ai/regen_system.rs b/src/ai/regen_system.rs index 8114c4e..a7ee874 100644 --- a/src/ai/regen_system.rs +++ b/src/ai/regen_system.rs @@ -12,7 +12,7 @@ use crate::{ Intrinsics, }; use specs::prelude::*; -use crate::data::events::*; +use crate::consts::events::*; pub struct RegenSystem {} @@ -121,7 +121,8 @@ fn try_hp_regen_tick(pool: &mut Pools, amount: i32) { fn get_mana_regen_per_tick(e: Entity, attributes: &ReadStorage) -> i32 { let regen = if let Some(attributes) = attributes.get(e) { - (attributes.intelligence.bonus + attributes.wisdom.bonus) / 2 + MIN_MP_REGEN_PER_TURN + (attributes.intelligence.modifier() + attributes.wisdom.modifier()) / 2 + + MIN_MP_REGEN_PER_TURN } else { MIN_MP_REGEN_PER_TURN }; diff --git a/src/ai/turn_status_system.rs b/src/ai/turn_status_system.rs index db3acaa..d26563c 100644 --- a/src/ai/turn_status_system.rs +++ b/src/ai/turn_status_system.rs @@ -12,7 +12,7 @@ use crate::{ }; use bracket_lib::prelude::*; use specs::prelude::*; -use crate::data::events::*; +use crate::consts::events::*; pub struct TurnStatusSystem {} @@ -83,8 +83,8 @@ impl<'a> System<'a> for TurnStatusSystem { None, EffectType::Particle { glyph: to_cp437('!'), + sprite: "gnome".to_string(), // FIXME: REMOVE THE GNOMES fg: RGB::named(LIGHT_BLUE), - bg: RGB::named(BLACK), lifespan: 200.0, delay: 0.0, }, @@ -113,8 +113,8 @@ impl<'a> System<'a> for TurnStatusSystem { None, EffectType::Particle { glyph: to_cp437('?'), + sprite: "gnome".to_string(), // FIXME: REMOVE THE GNOMES fg: RGB::named(MAGENTA), - bg: RGB::named(BLACK), lifespan: 200.0, delay: 0.0, }, diff --git a/src/camera.rs b/src/camera.rs index 00b6869..611d923 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,14 +1,66 @@ -use super::{ Hidden, Map, Mind, Position, Prop, Renderable }; +use super::{ Hidden, Map, Mind, Position, Prop, Renderable, Pools }; use bracket_lib::prelude::*; use specs::prelude::*; use std::ops::Mul; +use super::consts::visuals::{ TILES_IN_VIEWPORT_H, TILES_IN_VIEWPORT_W }; +use super::consts::prelude::*; const SHOW_BOUNDARIES: bool = false; -pub fn get_screen_bounds(ecs: &World, _ctx: &mut BTerm) -> (i32, i32, i32, i32, i32, i32) { - let player_pos = ecs.fetch::(); +pub struct Offsets { + pub x: i32, + pub y: i32, +} + +pub fn get_offset() -> Offsets { + return Offsets { x: 1, y: 8 }; +} + +pub struct ScreenBounds { + pub min_x: i32, + pub max_x: i32, + pub min_y: i32, + pub max_y: i32, + pub x_offset: i32, + pub y_offset: i32, +} + +pub struct ScreenBoundsf32 { + pub min_x: f32, + pub max_x: f32, + pub min_y: f32, + pub max_y: f32, + pub x_offset: f32, + pub y_offset: f32, +} + +impl ScreenBounds { + pub fn to_px(&self) -> ScreenBoundsf32 { + ScreenBoundsf32 { + min_x: (self.min_x as f32) * TILESIZE.sprite_x, + max_x: (self.max_x as f32) * TILESIZE.sprite_x, + min_y: (self.min_y as f32) * TILESIZE.sprite_y, + max_y: (self.max_y as f32) * TILESIZE.sprite_y, + x_offset: (self.x_offset as f32) * TILESIZE.x, + y_offset: (self.y_offset as f32) * TILESIZE.x, + } + } +} + +pub fn get_screen_bounds(ecs: &World, debug: bool) -> ScreenBounds { let map = ecs.fetch::(); - let (x_chars, y_chars, mut x_offset, mut y_offset) = (69, 41, 1, 10); + let player_pos = if !debug { + *ecs.fetch::() + } else { + Point::new(map.width / 2, map.height / 2) + }; + + let (x_chars, y_chars, mut x_offset, mut y_offset) = ( + TILES_IN_VIEWPORT_W, + TILES_IN_VIEWPORT_H, + 1, + 8, + ); let centre_x = (x_chars / 2) as i32; let centre_y = (y_chars / 2) as i32; @@ -28,33 +80,60 @@ pub fn get_screen_bounds(ecs: &World, _ctx: &mut BTerm) -> (i32, i32, i32, i32, let max_x = min_x + (x_chars as i32); let max_y = min_y + (y_chars as i32); - (min_x, max_x, min_y, max_y, x_offset, y_offset) + ScreenBounds { min_x, max_x, min_y, max_y, x_offset, y_offset } +} + +use crate::consts::TILESIZE; + +pub fn in_bounds(x: i32, y: i32, min_x: i32, min_y: i32, upper_x: i32, upper_y: i32) -> bool { + x >= min_x && x < upper_x && y >= min_y && y < upper_y } pub fn render_camera(ecs: &World, ctx: &mut BTerm) { let map = ecs.fetch::(); - let (min_x, max_x, min_y, max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx); + let bounds = get_screen_bounds(ecs, false); // Render map let mut y = 0; - for t_y in min_y..max_y { + for t_y in bounds.min_y..bounds.max_y { let mut x = 0; - for t_x in min_x..max_x { + for t_x in bounds.min_x..bounds.max_x { if t_x >= 0 && t_x < map.width && t_y >= 0 && t_y < map.height { let idx = map.xy_idx(t_x, t_y); if map.revealed_tiles[idx] { - let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id( - idx, - &*map, - Some(*ecs.fetch::()), - None - ); - ctx.set(x + x_offset, y + y_offset, fg, bg, glyph); + if 1 == 2 { + let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id( + idx, + &*map, + Some(*ecs.fetch::()), + None + ); + ctx.set(x + bounds.x_offset, y + bounds.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::()) + ); + ctx.add_sprite( + Rect::with_size( + x * 16 + bounds.x_offset * 16, + y * 16 + bounds.y_offset * 16, + 16, + 16 + ), + 0, + RGBA::named(WHITE), + 0 // Ya + ); + ctx.set_active_console(TILE_LAYER); + } } } else if SHOW_BOUNDARIES { ctx.set( - x + x_offset, - y + y_offset, + x + bounds.x_offset, + y + bounds.y_offset, RGB::named(DARKSLATEGRAY), RGB::named(BLACK), to_cp437('#') @@ -67,8 +146,11 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { // Render entities { + ctx.set_active_console(ENTITY_LAYER); + let positions = ecs.read_storage::(); let renderables = ecs.read_storage::(); + let pools = ecs.read_storage::(); let minds = ecs.read_storage::(); let hidden = ecs.read_storage::(); let props = ecs.write_storage::(); @@ -79,22 +161,22 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order)); for (pos, render, ent, _hidden) in data.iter() { let idx = map.xy_idx(pos.x, pos.y); - let entity_offset_x = pos.x - min_x; - let entity_offset_y = pos.y - min_y; - if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y { + let entity_offset_x = pos.x - bounds.min_x; + let entity_offset_y = pos.y - bounds.min_y; + if + pos.x < bounds.max_x && + pos.y < bounds.max_y && + pos.x >= bounds.min_x && + pos.y >= bounds.min_y + { let mut draw = false; let mut fg = render.fg; - let mut bg = crate::map::themes::get_tile_renderables_for_id( - idx, - &*map, - Some(*ecs.fetch::()), - None - ).2; + let bg = BLACK; // Draw entities on visible tiles if map.visible_tiles[idx] { draw = true; } else { - fg = fg.mul(crate::data::visuals::NON_VISIBLE_MULTIPLIER); + fg = fg.mul(crate::consts::visuals::NON_VISIBLE_MULTIPLIER); // We don't darken BG, because get_tile_renderables_for_id handles this. } @@ -104,9 +186,6 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { let has_mind = minds.get(*ent); if let Some(_) = has_mind { draw = true; - if !map.revealed_tiles[idx] { - bg = RGB::named(BLACK); - } } } } @@ -118,16 +197,51 @@ pub fn render_camera(ecs: &World, ctx: &mut BTerm) { } } if draw { - ctx.set( - entity_offset_x + x_offset, - entity_offset_y + y_offset, - fg, - bg, - render.glyph - ); + /* if let Some(sprite) = render.sprite { + ctx.set_active_console(0); + ctx.add_sprite( + Rect::with_size( + entity_offset_x * 16 + bounds.x_offset * 16, + entity_offset_y * 16 + bounds.y_offset * 16, + 16, + 16 + ), + render.render_order, + RGBA::named(WHITE), + sprite + ); + ctx.set_active_console(ENTITY_LAYER); + } else */ { + ctx.set( + entity_offset_x + bounds.x_offset, + entity_offset_y + bounds.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 + bounds.x_offset) * 16 + 2, + (entity_offset_y + bounds.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); } } diff --git a/src/components.rs b/src/components.rs index 696eab4..2cce335 100644 --- a/src/components.rs +++ b/src/components.rs @@ -20,7 +20,7 @@ pub struct SerializationHelper { #[derive(Component, Serialize, Deserialize, Clone)] pub struct DMSerializationHelper { pub map: super::map::MasterDungeonMap, - pub log: Vec>, + pub log: std::collections::BTreeMap>, pub event_counts: HashMap, pub events: HashMap>, } @@ -38,12 +38,91 @@ pub struct OtherLevelPosition { pub id: i32, } -#[derive(Component, ConvertSaveload, Clone)] +#[derive(Debug, Component, ConvertSaveload, Clone)] pub struct Renderable { - pub glyph: FontCharType, + pub glyph: FontCharType, // Legacy, and for drawing the morgue map. + pub sprite: String, + pub sprite_alt: Option, pub fg: RGB, - pub bg: RGB, + pub fg_alt: Option, pub render_order: i32, + pub render_order_alt: Option, + pub offset: (f32, f32), + pub offset_alt: Option<(f32, f32)>, + // 0 = always on top: particle effects + // 1 = things that should appear infront of the player: railings, etc. + // 2 = the player + // 3 = other mobs + // 4 = interactable items + // 5 = other props: table, etc. +} + +impl Renderable { + pub fn new(glyph: FontCharType, sprite: String, fg: RGB, render_order: i32) -> Self { + Self { + glyph, + sprite, + sprite_alt: None, + fg, + fg_alt: None, + render_order, + render_order_alt: None, + offset: (0.0, 0.0), + offset_alt: None, + } + } + pub fn swap(&mut self) { + let sprite = self.swap_sprite(); + let fg = self.swap_fg(); + let render_order = self.swap_render_order(); + let offset = self.swap_offset(); + let did_something = sprite || fg || render_order || offset; + if !did_something { + unreachable!( + ".swap() was called on a Renderable component, but nothing happened. {:?}", + self + ); + } + } + pub fn swap_sprite(&mut self) -> bool { + if let Some(sprite_alt) = &mut self.sprite_alt { + std::mem::swap(&mut self.sprite, sprite_alt); + return true; + } + false + } + pub fn swap_fg(&mut self) -> bool { + if let Some(fg_alt) = &mut self.fg_alt { + std::mem::swap(&mut self.fg, fg_alt); + return true; + } + false + } + pub fn swap_render_order(&mut self) -> bool { + if let Some(render_order_alt) = &mut self.render_order_alt { + std::mem::swap(&mut self.render_order, render_order_alt); + return true; + } + false + } + pub fn swap_offset(&mut self) -> bool { + if let Some(offset_alt) = &mut self.offset_alt { + std::mem::swap(&mut self.offset, offset_alt); + return true; + } + false + } +} + +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct Avatar { + pub sprite: String, +} + +impl Avatar { + pub fn new(sprite: String) -> Self { + Self { sprite } + } } #[derive(Component, Debug, Serialize, Deserialize, Clone)] @@ -131,6 +210,9 @@ pub struct BlocksVisibility {} #[derive(Component, Debug, Serialize, Deserialize, Clone)] pub struct Door { pub open: bool, + pub locked: bool, + pub blocks_vis: bool, + pub blocks_move: bool, } #[derive(Serialize, Deserialize, Copy, Clone, PartialEq)] @@ -182,8 +264,36 @@ pub struct Pools { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Attribute { pub base: i32, - pub modifiers: i32, - pub bonus: i32, + pub bonuses: i32, + pub exercise: i32, +} + +impl Attribute { + pub fn new(base: i32) -> Self { + Self { + base, + bonuses: 0, + exercise: 0, + } + } + // Raw attribute score. e.g. 10 base, + 4 from armour: 14 strength. + pub fn current(&self) -> i32 { + self.base + self.bonuses + } + // Attribute bonus. e.g. 14 strength = +2, 8 strength = -1 + pub fn modifier(&self) -> i32 { + crate::gamesystem::attr_bonus(self.current()) + } + pub fn improve(&mut self) { + if self.exercise < 50 { + self.exercise += 1; + } + } + pub fn abuse(&mut self) { + if self.exercise > -50 { + self.exercise -= 1; + } + } } #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] @@ -215,7 +325,6 @@ pub struct GrantsSpell { } // TODO: GrantsIntrinsic, Intrinsics, etc. ? Done the same way as spells? - #[derive(Component, Debug, Serialize, Deserialize, Clone)] pub struct Attributes { pub strength: Attribute, @@ -226,6 +335,93 @@ pub struct Attributes { pub charisma: Attribute, } +impl Attributes { + pub const STR: i32 = 0; + pub const DEX: i32 = 1; + pub const CON: i32 = 2; + pub const INT: i32 = 3; + pub const WIS: i32 = 4; + pub const CHA: i32 = 5; + pub fn default() -> Self { + Self { + strength: Attribute::new(10), + dexterity: Attribute::new(10), + constitution: Attribute::new(10), + intelligence: Attribute::new(10), + wisdom: Attribute::new(10), + charisma: Attribute::new(10), + } + } + pub fn with_stats(str: i32, dex: i32, con: i32, int: i32, wis: i32, cha: i32) -> Self { + Self { + strength: Attribute::new(str), + dexterity: Attribute::new(dex), + constitution: Attribute::new(con), + intelligence: Attribute::new(int), + wisdom: Attribute::new(wis), + charisma: Attribute::new(cha), + } + } + pub fn attr_from_index(&self, attr: i32) -> &Attribute { + match attr { + Self::STR => &self.strength, + Self::DEX => &self.dexterity, + Self::CON => &self.constitution, + Self::INT => &self.intelligence, + Self::WIS => &self.wisdom, + Self::CHA => &self.charisma, + _ => unreachable!("Tried to get an attribute that doesn't exist."), + } + } + pub fn exercise(&mut self, attr: i32, improve: bool) { + match attr { + Self::STR => { + if improve { + self.strength.improve(); + } else { + self.strength.abuse(); + } + } + Self::DEX => { + if improve { + self.dexterity.improve(); + } else { + self.dexterity.abuse(); + } + } + Self::CON => { + if improve { + self.constitution.improve(); + } else { + self.constitution.abuse(); + } + } + Self::INT => { + if improve { + self.intelligence.improve(); + } else { + self.intelligence.abuse(); + } + } + Self::WIS => { + if improve { + self.wisdom.improve(); + } else { + self.wisdom.abuse(); + } + } + Self::CHA => { + if improve { + self.charisma.improve(); + } else { + self.charisma.abuse(); + } + } + _ => unreachable!("Tried to exercise an attribute that doesn't exist."), + } + } +} + #[derive(Component, Debug, ConvertSaveload, Clone)] pub struct WantsToMelee { pub target: Entity, @@ -258,10 +454,40 @@ pub struct Beatitude { 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)] pub struct Item { pub weight: f32, // in lbs pub value: f32, // base + pub category: ItemType, } #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] @@ -289,9 +515,23 @@ pub struct IdentifiedItem { pub name: String, } +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct Stackable {} + #[derive(Component, Debug, Serialize, Deserialize, Clone)] pub struct EquipmentChanged {} +#[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(PartialEq, Copy, Clone, Serialize, Deserialize)] pub enum BurdenLevel { Burdened, @@ -509,6 +749,9 @@ pub struct InBackpack { pub owner: Entity, } +#[derive(Component, Serialize, Deserialize, Clone)] +pub struct WantsToAssignKey {} + #[derive(Component, Debug, ConvertSaveload)] pub struct WantsToPickupItem { pub collected_by: Entity, @@ -558,7 +801,9 @@ pub struct Charges { #[derive(Component, Serialize, Deserialize, Clone)] pub struct SpawnParticleLine { pub glyph: FontCharType, + pub sprite: String, pub tail_glyph: FontCharType, + pub tail_sprite: String, pub colour: RGB, pub lifetime_ms: f32, pub trail_colour: RGB, @@ -568,6 +813,7 @@ pub struct SpawnParticleLine { #[derive(Component, Serialize, Deserialize, Clone)] pub struct SpawnParticleSimple { pub glyph: FontCharType, + pub sprite: String, pub colour: RGB, pub lifetime_ms: f32, } @@ -575,8 +821,11 @@ pub struct SpawnParticleSimple { #[derive(Component, Serialize, Deserialize, Clone)] pub struct SpawnParticleBurst { pub glyph: FontCharType, + pub sprite: String, pub head_glyph: FontCharType, + pub head_sprite: String, pub tail_glyph: FontCharType, + pub tail_sprite: String, pub colour: RGB, pub lerp: RGB, pub lifetime_ms: f32, diff --git a/src/config/mod.rs b/src/config/mod.rs index 5309151..ffc11d4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -61,11 +61,11 @@ impl Config { requires_write |= config.logging.apply_values(&parsed_config); requires_write |= config.visuals.apply_values(&parsed_config); if requires_write { + console::log("Parsed config, but some values were changed. Saving new ver."); if let Err(write_err) = config.save_to_file(filename) { console::log(format!("Error writing config: {:?}", write_err)); } } - return config; } } @@ -101,6 +101,8 @@ impl Section for LogConfig { fn apply_values(&mut self, parsed_config: &Value) -> bool { if let Some(section) = parsed_config.get("logging") { let mut missing = false; + apply_bool_value!(self, section, missing, show_mapgen); + apply_bool_value!(self, section, missing, log_combat); apply_bool_value!(self, section, missing, log_spawning); apply_bool_value!(self, section, missing, log_ticks); missing diff --git a/src/data/char_create.rs b/src/consts/char_create.rs similarity index 100% rename from src/data/char_create.rs rename to src/consts/char_create.rs diff --git a/src/data/entity.rs b/src/consts/entity.rs similarity index 92% rename from src/data/entity.rs rename to src/consts/entity.rs index a34c526..c37aae9 100644 --- a/src/data/entity.rs +++ b/src/consts/entity.rs @@ -1,4 +1,4 @@ -pub const DEFAULT_VIEWSHED_STANDARD: i32 = 16; // Standard viewshed radius for almost all entities. +pub const DEFAULT_VIEWSHED_STANDARD: i32 = 7; // Standard viewshed radius for almost all entities. pub const CARRY_CAPACITY_PER_STRENGTH: i32 = 5; // How much weight can be carried per point of strength. pub const NORMAL_SPEED: i32 = 12; // Normal speed for almost all entities. pub const SPEED_MOD_BURDENED: f32 = 0.75; diff --git a/src/data/events.rs b/src/consts/events.rs similarity index 100% rename from src/data/events.rs rename to src/consts/events.rs diff --git a/src/data/ids.rs b/src/consts/ids.rs similarity index 100% rename from src/data/ids.rs rename to src/consts/ids.rs diff --git a/src/data/messages.rs b/src/consts/messages.rs similarity index 96% rename from src/data/messages.rs rename to src/consts/messages.rs index 89e39c8..7175b2a 100644 --- a/src/data/messages.rs +++ b/src/consts/messages.rs @@ -25,6 +25,7 @@ pub const NUTRITION_BLESSED: &str = "Delicious"; pub const LEVELUP_PLAYER: &str = "Welcome to experience level"; 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_EQUIP_ITEM: &str = "You equip the"; pub const YOU_REMOVE_ITEM: &str = "You unequip your"; diff --git a/src/consts/mod.rs b/src/consts/mod.rs new file mode 100644 index 0000000..7da4c53 --- /dev/null +++ b/src/consts/mod.rs @@ -0,0 +1,32 @@ +pub mod entity; +pub mod visuals; +pub mod messages; +pub mod char_create; +pub mod events; +pub mod ids; +pub mod names; +pub mod sprites; + +pub mod prelude { + pub use super::visuals::{ TILE_LAYER, ENTITY_LAYER, TEXT_LAYER, HP_BAR_LAYER }; + pub use super::visuals::{ VIEWPORT_H, VIEWPORT_W }; +} + +pub struct Spritesize { + pub x: f32, + pub y: f32, + pub sprite_x: f32, + pub sprite_y: f32, +} + +pub const TILESIZE: Spritesize = Spritesize { + x: 16.0, + y: 16.0, + sprite_x: 16.0 * ZOOM_FACTOR, + sprite_y: 24.0 * ZOOM_FACTOR, +}; +pub const ZOOM_FACTOR: f32 = 2.0; +pub const FONTSIZE: f32 = 16.0; + +pub const DISPLAYWIDTH: u32 = 120; +pub const DISPLAYHEIGHT: u32 = 67; diff --git a/src/data/names.rs b/src/consts/names.rs similarity index 100% rename from src/data/names.rs rename to src/consts/names.rs diff --git a/src/consts/sprites.rs b/src/consts/sprites.rs new file mode 100644 index 0000000..1b9d7bf --- /dev/null +++ b/src/consts/sprites.rs @@ -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; diff --git a/src/data/visuals.rs b/src/consts/visuals.rs similarity index 79% rename from src/data/visuals.rs rename to src/consts/visuals.rs index 8f59a24..8b66e95 100644 --- a/src/data/visuals.rs +++ b/src/consts/visuals.rs @@ -1,17 +1,34 @@ use bracket_lib::prelude::*; +use super::ZOOM_FACTOR; // 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. +// Counted in 16x16 tiles, because that's how most of the screen is drawn. However, +// the viewport itself uses 16x24 sprites - so this translates to 70x28 tiles drawn. +// It also works nicely for zooming in, displaying 35x14 tiles cleanly onscreen. +pub const VIEWPORT_W: i32 = 70; +pub const VIEWPORT_H: i32 = 54; + +pub const TILES_IN_VIEWPORT_W: i32 = 70 / (ZOOM_FACTOR as i32); +pub const TILES_IN_VIEWPORT_H: i32 = 36 / (ZOOM_FACTOR as i32); + +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 GLOBAL_OFFSET_MIN_CLAMP: f32 = -0.5; -pub const GLOBAL_OFFSET_MAX_CLAMP: f32 = 1.0; +pub const GLOBAL_OFFSET_MAX_CLAMP: f32 = 0.5; +pub const SPRITE_OFFSET_MIN_CLAMP: f32 = 0.85; +pub const SPRITE_OFFSET_MAX_CLAMP: f32 = 1.0; pub const WITH_SCANLINES_BRIGHTEN_AMOUNT: f32 = 0.1; // 0.0 = no brightening, 1.0 = full brightening. -pub const NON_VISIBLE_MULTIPLIER: f32 = 0.3; // 0.0 = black, 1.0 = full colour. +pub const NON_VISIBLE_MULTIPLIER: f32 = 0.1; // 0.0 = black, 1.0 = full colour. pub const NON_VISIBLE_MULTIPLIER_IF_SCANLINES: f32 = 0.8; // as above, but when using scanlines. should be higher. -pub const MAX_DARKENING: f32 = 0.45; // 0.0 = black, 1.0 = full colour - only used if WITH_DARKEN_BY_DISTANCE is true. +pub const MAX_DARKENING: f32 = 0.2; // 0.0 = black, 1.0 = full colour - only used if WITH_DARKEN_BY_DISTANCE is true. pub const MAX_DARKENING_IF_SCANLINES: f32 = 0.9; // as above, but when using scanlines. should be higher. -pub const START_DARKEN_AT_N_TILES: f32 = 8.0; // start darkening at this distance (should always be less than entity::DEFAULT_VIEWSHED_STANDARD). +pub const START_DARKEN_AT_N_TILES: f32 = 1.0; // start darkening at this distance (should always be less than entity::DEFAULT_VIEWSHED_STANDARD). pub const SHORT_PARTICLE_LIFETIME: f32 = 100.0; // in ms pub const DEFAULT_PARTICLE_LIFETIME: f32 = 200.0; @@ -57,6 +74,7 @@ pub const SHALLOW_WATER_OFFSETS: (i32, i32, i32) = (3, 10, 45); pub const DEEP_WATER_COLOUR: (u8, u8, u8) = (18, 33, 63); pub const DEEP_WATER_OFFSETS: (i32, i32, i32) = (5, 10, 32); pub const BARS_COLOUR: (u8, u8, u8) = (100, 100, 100); +pub const BARS_OFFSETS: (i32, i32, i32) = (10, 10, 10); pub const IMPASSABLE_MOUNTAIN_COLOUR: (u8, u8, u8) = (20, 23, 20); pub const IMPASSABLE_MOUNTAIN_OFFSETS: (i32, i32, i32) = (4, 4, 4); // FOREST THEME diff --git a/src/damage_system.rs b/src/damage_system.rs index a4224a7..723863d 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -11,10 +11,12 @@ use super::{ Position, Renderable, RunState, + WantsToRemoveKey, + WantsToDelete, }; use bracket_lib::prelude::*; use specs::prelude::*; -use crate::data::events; +use crate::consts::events; pub fn delete_the_dead(ecs: &mut World) { let mut dead: Vec = Vec::new(); @@ -65,7 +67,17 @@ pub fn delete_the_dead(ecs: &mut World) { } } } - let (items_to_delete, loot_to_spawn) = handle_dead_entity_items(ecs, &dead); + let (mut items_to_delete, loot_to_spawn) = handle_dead_entity_items(ecs, &dead); + { + let entities = ecs.entities(); + let removekeys = ecs.read_storage::(); + let delete = ecs.read_storage::(); + // Add items marked for deletion to the list, but only if they've already had their key + // assignments handled, to ensure 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 { crate::raws::spawn_named_entity( &crate::raws::RAWS.lock().unwrap(), @@ -82,6 +94,7 @@ pub fn delete_the_dead(ecs: &mut World) { // For everything that died, increment the event log, and delete. for victim in dead { 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."); } } diff --git a/src/data/mod.rs b/src/data/mod.rs deleted file mode 100644 index 8abda34..0000000 --- a/src/data/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod entity; -pub mod visuals; -pub mod messages; -pub mod char_create; -pub mod events; -pub mod ids; -pub mod names; diff --git a/src/effects/attr.rs b/src/effects/attr.rs new file mode 100644 index 0000000..65b4b2e --- /dev/null +++ b/src/effects/attr.rs @@ -0,0 +1,32 @@ +use specs::prelude::*; +use bracket_lib::prelude::*; +use super::{ EffectSpawner, EffectType }; +use crate::components::Attributes; + +const ATTRIBUTE_SOFTCAP: i32 = 20; +const ABUSE_CHANCE: i32 = 2; // 1 in this chance of abuse. 2 = 50%, 3 = 33%, etc. + +pub(crate) fn exercise(ecs: &mut World, effect: &EffectSpawner, target: Entity) { + // Unwrap vars from the effect + let (attr, inc) = if let EffectType::Exercise { attribute, increment } = effect.effect_type { + (attribute, increment) + } else { + return; + }; + + // Get target attributes + let mut attributes = ecs.write_storage::(); + if let Some(has_attr) = attributes.get_mut(target) { + // Roll a d20. If we're trying to exercise a stat, we need to roll higher + // than the stat's current value. If we're abusing a stat, flip a coin. + let mut rng = ecs.write_resource::(); + let success = if inc { + rng.roll_dice(1, ATTRIBUTE_SOFTCAP) > has_attr.attr_from_index(attr).current() + } else { + rng.roll_dice(1, ABUSE_CHANCE) == 1 + }; + if success { + has_attr.exercise(attr, inc); + } + } +} diff --git a/src/effects/damage.rs b/src/effects/damage.rs index 80885e2..88342f9 100644 --- a/src/effects/damage.rs +++ b/src/effects/damage.rs @@ -15,12 +15,13 @@ use crate::{ HungerState, Bleeds, HasDamageModifiers, + DamageType, }; use crate::gui::with_article; -use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME }; -use crate::data::messages::LEVELUP_PLAYER; -use crate::data::events::*; -use crate::data::messages::*; +use crate::consts::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME }; +use crate::consts::messages::LEVELUP_PLAYER; +use crate::consts::events::*; +use crate::consts::messages::*; use bracket_lib::prelude::*; use specs::prelude::*; @@ -38,33 +39,88 @@ pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) { }; target_pool.hit_points.current -= ((amount as f32) * mult) as i32; let bleeders = ecs.read_storage::(); + // If the target bleeds, handle bloodstains and use the bleed colour for sfx. if let Some(bleeds) = bleeders.get(target) { - add_effect( - None, - EffectType::Bloodstain { colour: bleeds.colour }, - Targets::Entity { target } - ); - } - add_effect( - None, - EffectType::Particle { - glyph: to_cp437('‼'), - fg: RGB::named(ORANGE), - bg: RGB::named(BLACK), - lifespan: DEFAULT_PARTICLE_LIFETIME, - delay: 0.0, - }, - Targets::Entity { target } - ); - if target_pool.hit_points.current < 1 { - super::DEAD_ENTITIES.lock().unwrap().push_back(target); - add_effect(damage.source, EffectType::EntityDeath, Targets::Entity { target }); + if target_pool.hit_points.current < 1 { + super::DEAD_ENTITIES.lock().unwrap().push_back(target); + add_effect(damage.source, EffectType::EntityDeath, Targets::Entity { + target, + }); + for i in 0..3 { + let sprite = ( + match i { + 0 => "explode1", + 1 => "explode2", + _ => "explode3", + } + ).to_string(); + add_effect( + None, + EffectType::Particle { + glyph: to_cp437('‼'), + sprite, + fg: bleeds.colour, + lifespan: 75.0, + delay: 75.0 * (i as f32), + }, + Targets::Entity { target } + ); + add_effect( + None, + EffectType::Bloodstain { colour: bleeds.colour }, + Targets::Entity { target } + ); + } + } else { + // Regular damage taken effect - use damagetype to determine which one to play. + add_effect( + None, + EffectType::Particle { + glyph: to_cp437('‼'), + sprite: "gnome".to_string(), // FIXME: REMOVE THE GNOMES + fg: RGB::named(ORANGE), + lifespan: DEFAULT_PARTICLE_LIFETIME, + delay: 0.0, + }, + Targets::Entity { target } + ); + add_effect( + None, + EffectType::Bloodstain { colour: bleeds.colour }, + Targets::Entity { target } + ); + } + } else { + // TODO: Damage taken particle effects when the target does not bleed. + // Also damage types, etc. + return; } } } } else if let Some(_destructible) = ecs.read_storage::().get(target) { add_effect(damage.source, EffectType::EntityDeath, Targets::Entity { target }); } + if let EffectType::Damage { amount: _, damage_type } = &damage.effect_type { + get_random_damage_sound(ecs, damage_type, target); + } +} + +fn get_random_damage_sound(ecs: &World, damage_type: &DamageType, target: Entity) { + let mut rng = ecs.write_resource::(); + match damage_type { + DamageType::Physical => { + let sound = ( + match rng.roll_dice(1, 4) { + 1 => "whoosh1", + 2 => "whoosh2", + 3 => "whoosh3", + _ => "whoosh4", + } + ).to_string(); + add_effect(None, EffectType::Sound { sound }, Targets::Entity { target }); + } + _ => {} + } } pub fn heal_damage(ecs: &mut World, heal: &EffectSpawner, target: Entity) { @@ -83,10 +139,10 @@ pub fn heal_damage(ecs: &mut World, heal: &EffectSpawner, target: Entity) { } add_effect( None, - EffectType::Particle { + EffectType::Particle { // GNOMES glyph: to_cp437('♥'), + sprite: "gnome".to_string(), fg: RGB::named(BLUE), - bg: RGB::named(BLACK), lifespan: DEFAULT_PARTICLE_LIFETIME, delay: 0.0, }, @@ -184,7 +240,7 @@ fn get_death_message(ecs: &World, source: Entity) -> String { result.push_str(format!("{}", PLAYER_DIED_SUICIDE).as_str()); } else if let Some(name) = ecs.read_storage::().get(source) { 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 { result.push_str(format!("{}", PLAYER_DIED_UNKNOWN).as_str()); @@ -266,11 +322,11 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) { for i in 0..5 { if player_pos.y - i > 1 { add_effect( - None, + None, // FIXME: REMOVE THE GNOMES EffectType::Particle { glyph: to_cp437('░'), + sprite: "gnome".to_string(), fg: RGB::named(GOLD), - bg: RGB::named(BLACK), lifespan: LONG_PARTICLE_LIFETIME, delay: (i as f32) * 100.0, }, @@ -281,8 +337,8 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) { None, EffectType::Particle { glyph: to_cp437('░'), + sprite: "gnome".to_string(), fg: RGB::named(GOLD), - bg: RGB::named(BLACK), lifespan: LONG_PARTICLE_LIFETIME, delay: (i as f32) * 100.0, }, @@ -297,8 +353,8 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) { None, EffectType::Particle { glyph: to_cp437('░'), + sprite: "gnome".to_string(), fg: RGB::named(GOLD), - bg: RGB::named(BLACK), lifespan: LONG_PARTICLE_LIFETIME, delay: (i as f32) * 100.0, }, @@ -319,11 +375,11 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) { let mut rng = ecs.write_resource::(); let hp_gained = hp_per_level( &mut rng, - source_attributes.constitution.base + source_attributes.constitution.modifiers + source_attributes.constitution.base + source_attributes.constitution.bonuses ); let mana_gained = mana_per_level( &mut rng, - source_attributes.intelligence.base + source_attributes.intelligence.modifiers + source_attributes.intelligence.base + source_attributes.intelligence.bonuses ); source_pools.hit_points.max += hp_gained; source_pools.hit_points.current += hp_gained; diff --git a/src/effects/mod.rs b/src/effects/mod.rs index 5552f5a..c7a0577 100644 --- a/src/effects/mod.rs +++ b/src/effects/mod.rs @@ -2,6 +2,7 @@ use super::BUC; use crate::spatial; use bracket_lib::prelude::*; use specs::prelude::*; +use notan::prelude::*; use std::collections::VecDeque; use std::sync::Mutex; use crate::components::*; @@ -11,7 +12,9 @@ mod hunger; mod particles; mod targeting; mod triggers; +mod attr; mod intrinsics; +pub mod sound; pub use targeting::aoe_tiles; @@ -32,6 +35,10 @@ pub enum EffectType { amount: i32, increment_max: bool, }, + Exercise { + attribute: i32, + increment: bool, + }, Confusion { turns: i32, }, @@ -40,8 +47,8 @@ pub enum EffectType { }, Particle { glyph: FontCharType, + sprite: String, fg: RGB, - bg: RGB, lifespan: f32, delay: f32, }, @@ -58,6 +65,9 @@ pub enum EffectType { TriggerFire { trigger: Entity, }, + Sound { + sound: String, + }, } #[derive(Clone)] @@ -90,7 +100,7 @@ pub fn add_effect(source: Option, effect_type: EffectType, target: Targe } /// Iterates through the effects queue, applying each effect to their target. -pub fn run_effects_queue(ecs: &mut World) { +pub fn run_effects_queue(app: &mut App, ecs: &mut World) { // First removes any effect in the EFFECT_QUEUE with a dead entity as its source. loop { let dead_entity: Option = DEAD_ENTITIES.lock().unwrap().pop_front(); @@ -106,7 +116,7 @@ pub fn run_effects_queue(ecs: &mut World) { loop { let effect: Option = EFFECT_QUEUE.lock().unwrap().pop_front(); if let Some(effect) = effect { - target_applicator(ecs, &effect); + target_applicator(app, ecs, &effect); } else { break; } @@ -114,7 +124,7 @@ pub fn run_effects_queue(ecs: &mut World) { } /// Applies an effect to the correct target(s). -fn target_applicator(ecs: &mut World, effect: &EffectSpawner) { +fn target_applicator(app: &mut App, ecs: &mut World, effect: &EffectSpawner) { // Item use is handled differently - it creates other effects with itself // as the source, passing all effects attached to the item into the queue. if let EffectType::ItemUse { item } = effect.effect_type { @@ -126,25 +136,26 @@ fn target_applicator(ecs: &mut World, effect: &EffectSpawner) { } // Otherwise, just match the effect and enact it directly. match &effect.target { - Targets::Tile { target } => affect_tile(ecs, effect, *target), + Targets::Tile { target } => affect_tile(app, ecs, effect, *target), Targets::TileList { targets } => - targets.iter().for_each(|target| affect_tile(ecs, effect, *target)), - Targets::Entity { target } => affect_entity(ecs, effect, *target), + targets.iter().for_each(|target| affect_tile(app, ecs, effect, *target)), + Targets::Entity { target } => affect_entity(app, ecs, effect, *target), Targets::EntityList { targets } => - targets.iter().for_each(|target| affect_entity(ecs, effect, *target)), + targets.iter().for_each(|target| affect_entity(app, ecs, effect, *target)), } } /// Runs an effect on a given tile index -fn affect_tile(ecs: &mut World, effect: &EffectSpawner, target: usize) { +fn affect_tile(app: &mut App, ecs: &mut World, effect: &EffectSpawner, target: usize) { if tile_effect_hits_entities(&effect.effect_type) { spatial::for_each_tile_content(target, |entity| { - affect_entity(ecs, effect, entity); + affect_entity(app, ecs, effect, entity); }); } match &effect.effect_type { EffectType::Particle { .. } => particles::particle_to_tile(ecs, target as i32, &effect), + EffectType::Sound { .. } => sound::play_sound(app, ecs, &effect, target), _ => {} } // Run the effect @@ -163,10 +174,11 @@ fn tile_effect_hits_entities(effect: &EffectType) -> bool { } /// Runs an effect on a given entity -fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) { +fn affect_entity(app: &mut App, ecs: &mut World, effect: &EffectSpawner, target: Entity) { match &effect.effect_type { EffectType::Damage { .. } => damage::inflict_damage(ecs, effect, target), EffectType::Healing { .. } => damage::heal_damage(ecs, effect, target), + EffectType::Exercise { .. } => attr::exercise(ecs, effect, target), EffectType::Confusion { .. } => damage::add_confusion(ecs, effect, target), EffectType::Bloodstain { colour } => { if let Some(pos) = targeting::entity_position(ecs, target) { @@ -181,6 +193,11 @@ fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) { EffectType::EntityDeath => damage::entity_death(ecs, effect, target), EffectType::ModifyNutrition { .. } => hunger::modify_nutrition(ecs, effect, target), EffectType::AddIntrinsic { .. } => intrinsics::add_intrinsic(ecs, effect, target), + EffectType::Sound { .. } => { + if let Some(pos) = targeting::entity_position(ecs, target) { + sound::play_sound(app, ecs, &effect, pos); + } + } _ => {} } } diff --git a/src/effects/particles.rs b/src/effects/particles.rs index a6170dc..f6e34a5 100644 --- a/src/effects/particles.rs +++ b/src/effects/particles.rs @@ -4,27 +4,27 @@ use bracket_lib::prelude::*; use specs::prelude::*; pub fn particle_to_tile(ecs: &mut World, target: i32, effect: &EffectSpawner) { - if let EffectType::Particle { glyph, fg, bg, lifespan, delay } = effect.effect_type { + if let EffectType::Particle { glyph, sprite, fg, lifespan, delay } = &effect.effect_type { let map = ecs.fetch::(); let mut particle_builder = ecs.fetch_mut::(); - if delay <= 0.0 { + if delay <= &0.0 { particle_builder.request( target % map.width, target / map.width, - fg, - bg, - glyph, - lifespan + *fg, + *glyph, + sprite.clone(), + *lifespan ); } else { particle_builder.delay( target % map.width, target / map.width, - fg, - bg, - glyph, - lifespan, - delay + *fg, + *glyph, + sprite.clone(), + *lifespan, + *delay ); } } @@ -36,8 +36,8 @@ pub fn handle_simple_particles(ecs: &World, entity: Entity, target: &Targets) { None, EffectType::Particle { glyph: part.glyph, + sprite: part.sprite.clone(), fg: part.colour, - bg: RGB::named(BLACK), lifespan: part.lifetime_ms, delay: 0.0, }, @@ -56,7 +56,9 @@ pub fn handle_burst_particles(ecs: &World, entity: Entity, target: &Targets) { end_pos, &(SpawnParticleLine { glyph: part.head_glyph, + sprite: part.head_sprite.clone(), tail_glyph: part.tail_glyph, + tail_sprite: part.tail_sprite.clone(), colour: part.colour, trail_colour: part.trail_colour, lifetime_ms: part.trail_lifetime_ms, // 75.0 is good here. @@ -75,8 +77,8 @@ pub fn handle_burst_particles(ecs: &World, entity: Entity, target: &Targets) { None, EffectType::Particle { glyph: part.glyph, + sprite: part.sprite.clone(), fg: part.colour.lerp(part.lerp, (i as f32) * 0.1), - bg: RGB::named(BLACK), lifespan: part.lifetime_ms / 10.0, // ~50-80 is good here. delay: burst_delay + ((i as f32) * part.lifetime_ms) / 10.0, // above + burst_delay }, @@ -163,8 +165,8 @@ fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleL None, EffectType::Particle { glyph: part.glyph, + sprite: part.sprite.clone(), fg: part.colour, - bg: RGB::named(BLACK), lifespan: part.lifetime_ms, delay: (i as f32) * part.lifetime_ms, }, @@ -175,8 +177,8 @@ fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleL None, EffectType::Particle { glyph: part.tail_glyph, + sprite: part.tail_sprite.clone(), fg: part.trail_colour, - bg: RGB::named(BLACK), lifespan: part.trail_lifetime_ms, delay: (i as f32) * part.lifetime_ms, }, diff --git a/src/effects/sound.rs b/src/effects/sound.rs new file mode 100644 index 0000000..b8c890c --- /dev/null +++ b/src/effects/sound.rs @@ -0,0 +1,145 @@ +use bracket_lib::prelude::*; +use notan::prelude::*; +use specs::prelude::*; +use std::sync::Mutex; +use std::collections::HashMap; +use super::{ EffectSpawner, EffectType, Targets, add_effect }; +use crate::Map; + +lazy_static::lazy_static! { + pub static ref SOUNDS: Mutex> = Mutex::new(HashMap::new()); + pub static ref VOLUME: Mutex = Mutex::new(1.0); + pub static ref AMBIENCE: Mutex> = Mutex::new(None); +} + +#[derive(PartialEq, Copy, Clone)] +pub enum AudioType { + Ambient, + SFX, +} + +const AMBIENCE_VOL_MUL: f32 = 0.8; +const SFX_VOL_MUL: f32 = 1.0; + +pub fn play_sound(app: &mut App, ecs: &mut World, effect: &EffectSpawner, target: usize) { + // Extract sound from the EffectType, or panic if we somehow called this with the wrong effect. + let sound = if let EffectType::Sound { sound } = &effect.effect_type { + sound + } else { + unreachable!("add_intrinsic() called with the wrong EffectType") + }; + // Fetch all the relevant precursors. + let sounds = SOUNDS.lock().unwrap(); + let volume = VOLUME.lock().unwrap(); + let source = sounds.get(sound).unwrap(); + let (vol, repeat) = match source.1 { + AudioType::Ambient => (*volume * AMBIENCE_VOL_MUL, true), + AudioType::SFX => { + let map = ecs.fetch::(); + let ppos = ecs.fetch::(); + // Get a slight variation on sound volume, just so things don't sound too uniform. + let mut rng = ecs.write_resource::(); + let vol_random = rng.range(0.9, 1.1); + // Calc distance from player to target. + let dist = DistanceAlg::PythagorasSquared.distance2d( + *ppos, + Point::new((target as i32) % map.width, (target as i32) / map.width) + ); + // Play sound at volume proportional to distance. + (*volume * SFX_VOL_MUL * vol_random * (1.0 - (dist as f32) / 14.0), false) + } + }; + + // Play the sound. + let sound: Sound = app.audio.play_sound(&source.0, vol, repeat); + if repeat { + replace_ambience(app, &sound); + } +} + +pub fn stop(app: &mut App) { + let mut ambience = AMBIENCE.lock().unwrap(); + if let Some(old) = ambience.take() { + app.audio.stop(&old); + } +} + +pub fn ambience(sound: &str) { + add_effect(None, EffectType::Sound { sound: sound.to_string() }, Targets::Tile { target: 0 }) +} + +pub fn replace_ambience(app: &mut App, sound: &Sound) { + let mut ambience = AMBIENCE.lock().unwrap(); + if let Some(old) = ambience.take() { + app.audio.stop(&old); + } + *ambience = Some(sound.clone()); +} + +pub fn init_sounds(app: &mut App) { + let sound_data: &[(&str, &[u8], AudioType)] = &[ + // (key, file_path, audiotype) + ("a_relax", include_bytes!("../../resources/sounds/amb/relaxed.ogg"), AudioType::Ambient), + ("whoosh1", include_bytes!("../../resources/sounds/hit/whoosh1.ogg"), AudioType::SFX), + ("whoosh2", include_bytes!("../../resources/sounds/hit/whoosh2.ogg"), AudioType::SFX), + ("whoosh3", include_bytes!("../../resources/sounds/hit/whoosh3.ogg"), AudioType::SFX), + ("whoosh4", include_bytes!("../../resources/sounds/hit/whoosh4.ogg"), AudioType::SFX), + ("d_blocked1", include_bytes!("../../resources/sounds/door/blocked1.wav"), AudioType::SFX), + ("d_blocked2", include_bytes!("../../resources/sounds/door/blocked2.wav"), AudioType::SFX), + ("d_blocked3", include_bytes!("../../resources/sounds/door/blocked3.wav"), AudioType::SFX), + ("d_open1", include_bytes!("../../resources/sounds/door/open1.wav"), AudioType::SFX), + ("d_open2", include_bytes!("../../resources/sounds/door/open2.wav"), AudioType::SFX), + ("d_open3", include_bytes!("../../resources/sounds/door/open3.wav"), AudioType::SFX), + ("d_close1", include_bytes!("../../resources/sounds/door/close1.wav"), AudioType::SFX), + ("d_close2", include_bytes!("../../resources/sounds/door/close2.wav"), AudioType::SFX), + ("d_close3", include_bytes!("../../resources/sounds/door/close3.wav"), AudioType::SFX), + ]; + let mut sounds = SOUNDS.lock().unwrap(); + for (k, bytes, audiotype) in sound_data { + sounds.insert(k.to_string(), (app.audio.create_source(bytes).unwrap(), *audiotype)); + } +} + +pub fn set_volume(vol: f32) { + let mut volume = VOLUME.lock().unwrap(); + *volume = vol; +} + +pub fn clean(app: &mut App) { + app.audio.clean(); +} + +// Shorthand functions for adding generic, frequent SFX to the effect queue. +pub fn door_open(idx: usize) { + let mut rng = RandomNumberGenerator::new(); + let sound = ( + match rng.range(0, 3) { + 0 => "d_open1", + 1 => "d_open2", + _ => "d_open3", + } + ).to_string(); + super::add_effect(None, EffectType::Sound { sound }, Targets::Tile { target: idx }); +} +pub fn door_resist(idx: usize) { + let mut rng = RandomNumberGenerator::new(); + let sound = ( + match rng.range(0, 3) { + 0 => "d_blocked1", + 1 => "d_blocked2", + _ => "d_blocked3", + } + ).to_string(); + add_effect(None, EffectType::Sound { sound }, Targets::Tile { target: idx }); +} +pub fn door_close(idx: usize) { + let mut rng = RandomNumberGenerator::new(); + let sound = ( + match rng.range(0, 3) { + 0 => "d_close1", + 1 => "d_close2", + _ => "d_close3", + } + ).to_string(); + add_effect(None, EffectType::Sound { sound }, Targets::Tile { target: idx }); +} diff --git a/src/effects/triggers.rs b/src/effects/triggers.rs index a82496c..686fbec 100644 --- a/src/effects/triggers.rs +++ b/src/effects/triggers.rs @@ -33,8 +33,10 @@ use crate::{ KnownSpells, Position, Viewshed, + WantsToRemoveKey, + WantsToDelete, }; -use crate::data::messages::*; +use crate::consts::messages::*; use bracket_lib::prelude::*; use specs::prelude::*; pub fn item_trigger(source: Option, item: Entity, target: &Targets, ecs: &mut World) { @@ -57,7 +59,10 @@ pub fn item_trigger(source: Option, item: Entity, target: &Targets, ecs: let did_something = event_trigger(source, item, target, ecs); // If it's a consumable, delete it if did_something && ecs.read_storage::().get(item).is_some() { - ecs.entities().delete(item).expect("Failed to delete item"); + let mut removekey = ecs.write_storage::(); + removekey.insert(item, WantsToRemoveKey {}).expect("Unable to insert WantsToRemoveKey"); + let mut delete = ecs.write_storage::(); + delete.insert(item, WantsToDelete {}).expect("Unable to insert WantsToDelete"); } } diff --git a/src/gamelog/builder.rs b/src/gamelog/builder.rs index 50c9375..69e3aa4 100644 --- a/src/gamelog/builder.rs +++ b/src/gamelog/builder.rs @@ -65,6 +65,7 @@ impl Logger { /// Pushes the finished log entry. pub fn log(self) { - return append_entry(self.fragments); + let key = crate::gamelog::get_event_count(crate::consts::events::EVENT::COUNT_TURN); + return append_entry(key, self.fragments); } } diff --git a/src/gamelog/events.rs b/src/gamelog/events.rs index 3e0006f..9e69990 100644 --- a/src/gamelog/events.rs +++ b/src/gamelog/events.rs @@ -1,7 +1,7 @@ use std::collections::{ HashSet, HashMap }; use std::sync::Mutex; -use crate::data::events::EVENT; -use crate::data::names::*; +use crate::consts::events::EVENT; +use crate::consts::names::*; lazy_static! { /// A count of each event that has happened over the run. i.e. "turns", "descended", "ascended" @@ -126,7 +126,7 @@ pub fn record_event(event: EVENT) { new_event = format!("Discovered {}", name); } EVENT::Identified(name) => { - new_event = format!("Identified {}", crate::gui::with_article(name)); + new_event = format!("Identified {}", crate::gui::with_article(&name)); } EVENT::PlayerDied(str) => { // Generating the String is handled in the death effect, to avoid passing the ecs here. diff --git a/src/gamelog/logstore.rs b/src/gamelog/logstore.rs index edea95b..5047fdc 100644 --- a/src/gamelog/logstore.rs +++ b/src/gamelog/logstore.rs @@ -1,91 +1,70 @@ use super::{ events, LogFragment, Logger }; use bracket_lib::prelude::*; use std::sync::Mutex; +use std::collections::BTreeMap; +use notan::prelude::*; +use notan::text::CreateText; +use crate::consts::{ TILESIZE, FONTSIZE }; +use crate::consts::visuals::VIEWPORT_W; +use crate::Fonts; lazy_static! { - static ref LOG: Mutex>> = Mutex::new(Vec::new()); + pub static ref LOG: Mutex>> = Mutex::new(BTreeMap::new()); } -#[allow(dead_code)] -pub fn append_fragment(fragment: LogFragment) { - LOG.lock().unwrap().push(vec![fragment]); +/// Render with specificied params. +pub fn render_log( + draw: &RenderTexture, + gfx: &mut Graphics, + font: &Fonts, + pos: &(f32, f32), + width: f32, + entries: usize +) { + let mut text = gfx.create_text(); + let log = LOG.lock().unwrap(); + let latest: Vec<_> = log.iter().rev().take(entries).collect(); + let mut initialised = false; + let mut y = pos.1; + for (_, entries) in latest { + let mut written_on_line = false; + for frag in entries.iter() { + if !written_on_line { + text.add(&frag.text) + .font(font.n()) + .position(pos.0, y) + .size(FONTSIZE) + .max_width(width) + .color(Color::from_rgb(frag.colour.r, frag.colour.g, frag.colour.b)) + .v_align_bottom(); + written_on_line = true; + initialised = true; + } else { + text.chain(&frag.text) + .color(Color::from_rgb(frag.colour.r, frag.colour.g, frag.colour.b)) + .size(FONTSIZE); + } + } + if initialised { + y = text.last_bounds().min_y(); + } + } + gfx.render_to(draw, &text); } -pub fn append_entry(fragments: Vec) { - LOG.lock().unwrap().push(fragments); +pub fn append_entry(turn: i32, fragments: Vec) { + let mut log = LOG.lock().unwrap(); + if let Some(existing) = log.get_mut(&turn) { + existing.extend(fragments); + } else { + log.insert(turn, fragments); + } } pub fn clear_log() { LOG.lock().unwrap().clear(); } -pub fn print_log( - console: &mut Box, - pos: Point, - _descending: bool, - len: usize, - maximum_len: i32 -) { - let mut y = pos.y; - let mut x = pos.x; - // Reverse the log, take the number we want to show, and iterate through them - LOG.lock() - .unwrap() - .iter() - .rev() - .take(len) - .for_each(|log| { - let mut entry_len = -2; - // Iterate through each message fragment, and get the total length - // in lines, by adding the length of every fragment and dividing it - // by the maximum length we desire. Then shuffle our start-y by that much. - log.iter().for_each(|frag| { - entry_len += frag.text.len() as i32; - }); - let lines = entry_len / maximum_len; - y -= lines; - let mut i = 0; - log.iter().for_each(|frag| { - // Split every fragment up into single characters. - let parts = frag.text.split(""); - for part in parts { - // This is an extremely hacky solution to a problem I don't understand yet. - // -- without this, the lines *here* and the line count *above* wont match. - if part == "" || part == "\\" { - continue; - } - if i > entry_len { - break; - } - i += 1; - if x + (part.len() as i32) > pos.x + maximum_len { - if y > pos.y - (len as i32) { - console.print(x, y, "-"); - } - y += 1; - x = pos.x; - } - // Stay within bounds - if y > pos.y - (len as i32) { - console.print_color( - x, - y, - frag.colour.into(), - RGB::named(BLACK).into(), - part - ); - } - x += part.len() as i32; - } - }); - // Take away one from the y-axis, because we want to start each entry - // on a new line, and go up an additional amount depending on how many - // lines our *previous* entry took. - y -= 1 + lines; - x = pos.x; - }); -} - pub fn setup_log() { clear_log(); events::clear_events(); @@ -98,11 +77,11 @@ pub fn setup_log() { .log(); } -pub fn clone_log() -> Vec> { +pub fn clone_log() -> BTreeMap> { return LOG.lock().unwrap().clone(); } -pub fn restore_log(log: &mut Vec>) { +pub fn restore_log(log: &mut BTreeMap>) { LOG.lock().unwrap().clear(); LOG.lock().unwrap().append(log); } diff --git a/src/gamelog/mod.rs b/src/gamelog/mod.rs index 2289c9f..5ae498d 100644 --- a/src/gamelog/mod.rs +++ b/src/gamelog/mod.rs @@ -2,7 +2,7 @@ mod builder; pub use builder::*; mod logstore; use logstore::*; -pub use logstore::{ clear_log, clone_log, print_log, restore_log, setup_log }; +pub use logstore::{ LOG, clear_log, clone_log, render_log, restore_log, setup_log }; mod events; pub use events::*; diff --git a/src/gamesystem.rs b/src/gamesystem.rs index 6644723..850dbae 100644 --- a/src/gamesystem.rs +++ b/src/gamesystem.rs @@ -1,7 +1,7 @@ use super::{ Skill, Skills }; use crate::gui::{ Ancestry, Class }; -use crate::data::entity; -use crate::data::char_create::*; +use crate::consts::entity; +use crate::consts::char_create::*; use bracket_lib::prelude::*; use std::cmp::max; @@ -85,6 +85,7 @@ pub fn get_attribute_rolls( ancestry: Ancestry ) -> (i32, i32, i32, i32, i32, i32) { let (mut str, mut dex, mut con, mut int, mut wis, mut cha) = match class { + Class::Unset => VILLAGER_MIN_ATTR, Class::Fighter => FIGHTER_MIN_ATTR, Class::Rogue => ROGUE_MIN_ATTR, Class::Wizard => WIZARD_MIN_ATTR, @@ -92,6 +93,7 @@ pub fn get_attribute_rolls( }; let mut remaining_points = TOTAL_ATTRIBUTE_POINTS_MAXIMUM - (str + dex + con + int + wis + cha); let improve_chance: [i32; 6] = match class { + Class::Unset => VILLAGER_IMPR_CHANCE, Class::Fighter => FIGHTER_IMPR_CHANCE, Class::Rogue => ROGUE_IMPR_CHANCE, Class::Wizard => WIZARD_IMPR_CHANCE, diff --git a/src/gui/character_creation.rs b/src/gui/character_creation.rs index da1ecdb..17136f0 100644 --- a/src/gui/character_creation.rs +++ b/src/gui/character_creation.rs @@ -8,8 +8,8 @@ use super::{ RunState, State, }; -use crate::data::entity; -use crate::data::char_create::*; +use crate::consts::entity; +use crate::consts::char_create::*; use crate::{ raws, Attribute, @@ -28,10 +28,11 @@ use bracket_lib::prelude::*; use serde::{ Deserialize, Serialize }; use specs::prelude::*; use std::collections::HashMap; +use crate::consts::prelude::*; -#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)] pub enum Ancestry { - NULL, + Unset, Human, Dwarf, Gnome, @@ -39,8 +40,9 @@ pub enum Ancestry { Catfolk, } -#[derive(Serialize, Deserialize, Copy, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)] pub enum Class { + Unset, Fighter, Rogue, Wizard, @@ -48,48 +50,53 @@ pub enum Class { } lazy_static! { - static ref ANCESTRY_CLASS_DATA: HashMap> = { + static ref ANCESTRYDATA: HashMap> = { let mut m = HashMap::new(); - // Ancestry m.insert( - "human".to_string(), + Ancestry::Human, vec![ "nothing".to_string()]); m.insert( - "dwarf".to_string(), + Ancestry::Dwarf, vec![ "a natural bonus to defence".to_string()]); m.insert( - "elf".to_string(), + Ancestry::Elf, vec![ "minor telepathy".to_string(), "a slightly increased speed".to_string()]); m.insert( - "catfolk".to_string(), + Ancestry::Catfolk, vec![ "increased speed".to_string(), "increased unarmed damage".to_string()]); - // Class + return m; + }; +} + +lazy_static! { + static ref CLASSDATA: HashMap> = { + let mut m = HashMap::new(); m.insert( - "fighter".to_string(), + Class::Fighter, vec![ format!("a longsword, ring mail, and {} food", FIGHTER_STARTING_FOOD), "10 str, 8 dex, 10 con, 6 int, 6 wis, 8 cha".to_string(), "and 27 random stat points".to_string()]); m.insert( - "rogue".to_string(), + Class::Rogue, vec![ format!("a rapier, leather armour, and {} food", ROGUE_STARTING_FOOD), "8 str, 10 dex, 8 con, 6 int, 8 wis, 10 cha".to_string(), "and 35 random stat points".to_string()]); m.insert( - "wizard".to_string(), + Class::Wizard, vec![ format!("a dagger, random scrolls/potions, and {} food", WIZARD_STARTING_FOOD), "6 str, 8 dex, 6 con, 10 int, 10 wis, 8 cha".to_string(), "and 17 random stat points".to_string()]); m.insert( - "villager".to_string(), + Class::Villager, vec![ format!("the first weapon you could find, and {} food", VILLAGER_STARTING_FOOD), "6 str, 6 dex, 6 con, 6 int, 6 wis, 6 cha".to_string(), @@ -110,142 +117,123 @@ pub enum CharCreateResult { }, } -/// Handles the player character creation screen. -pub fn character_creation(gs: &mut State, ctx: &mut BTerm) -> CharCreateResult { - let runstate = gs.ecs.fetch::(); +use notan::prelude::*; +use notan::draw::{ Draw, DrawTextSection }; +use super::{ FONTSIZE, TILESIZE }; +use crate::consts::DISPLAYHEIGHT; +use crate::Fonts; - let mut x = 2; - let mut y = 11; - let column_width = 20; - - ctx.print_color(x, y, RGB::named(WHITE), RGB::named(BLACK), CHAR_CREATE_HEADER); - y += 2; - - if let RunState::CharacterCreation { ancestry, class } = *runstate { - let selected_fg = RGB::named(GREEN); - let unselected_fg = RGB::named(WHITE); - let mut fg; - let bg = RGB::named(BLACK); - - // Ancestry - ctx.print_color(x, y, bg, unselected_fg, "Ancestry"); - ctx.print_color(x + column_width, y, bg, unselected_fg, "Class"); - y += 1; - let mut race_str = "human"; - if ancestry == Ancestry::Human { - fg = selected_fg; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y, fg, bg, "h. Human"); - if ancestry == Ancestry::Elf { - fg = selected_fg; - race_str = "elf"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 1, fg, bg, "e. Elf"); - if ancestry == Ancestry::Dwarf { - fg = selected_fg; - race_str = "dwarf"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 2, fg, bg, "d. Dwarf"); - if ancestry == Ancestry::Catfolk { - fg = selected_fg; - race_str = "catfolk"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 3, fg, bg, "c. Catfolk"); - // Class - let mut class_str = "fighter"; - x += column_width; - if class == Class::Fighter { - fg = selected_fg; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y, fg, bg, "f. Fighter"); - if class == Class::Rogue { - fg = selected_fg; - class_str = "rogue"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 1, fg, bg, "r. Rogue"); - if class == Class::Wizard { - fg = selected_fg; - class_str = "wizard"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 2, fg, bg, "w. Wizard"); - if class == Class::Villager { - fg = selected_fg; - class_str = "villager"; - } else { - fg = unselected_fg; - } - ctx.print_color(x, y + 3, fg, bg, "v. Villager"); - // Selected ancestry/class benefits - x += column_width; - ctx.print_color(x, y, selected_fg, bg, ANCESTRY_INFO_HEADER); - for line in ANCESTRY_CLASS_DATA.get(race_str).unwrap().iter() { - y += 1; - ctx.print_color(x + 1, y, unselected_fg, bg, line); - } - y += 2; - ctx.print_color(x, y, selected_fg, bg, CLASS_INFO_HEADER); - for line in ANCESTRY_CLASS_DATA.get(class_str).unwrap().iter() { - y += 1; - ctx.print_color(x + 1, y, unselected_fg, bg, line); - } - - match ctx.key { - None => { - return CharCreateResult::NoSelection { ancestry, class }; - } - Some(key) => - match key { - VirtualKeyCode::Escape => { - return CharCreateResult::Selected { ancestry: Ancestry::NULL, class }; - } - VirtualKeyCode::Return => { - return CharCreateResult::Selected { ancestry, class }; - } - VirtualKeyCode::H => { - return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class }; - } - VirtualKeyCode::E => { - return CharCreateResult::NoSelection { ancestry: Ancestry::Elf, class }; - } - VirtualKeyCode::D => { - return CharCreateResult::NoSelection { ancestry: Ancestry::Dwarf, class }; - } - VirtualKeyCode::C => { - return CharCreateResult::NoSelection { ancestry: Ancestry::Catfolk, class }; - } - VirtualKeyCode::F => { - return CharCreateResult::NoSelection { ancestry, class: Class::Fighter }; - } - VirtualKeyCode::R => { - return CharCreateResult::NoSelection { ancestry, class: Class::Rogue }; - } - VirtualKeyCode::W => { - return CharCreateResult::NoSelection { ancestry, class: Class::Wizard }; - } - VirtualKeyCode::V => { - return CharCreateResult::NoSelection { ancestry, class: Class::Villager }; - } - _ => { - return CharCreateResult::NoSelection { ancestry, class }; - } - } - } +pub fn draw_charcreation( + ecs: &World, + draw: &mut Draw, + atlas: &HashMap, + font: &Fonts +) { + let runstate = ecs.read_resource::(); + let (class, ancestry) = match *runstate { + RunState::CharacterCreation { class, ancestry } => (class, ancestry), + _ => unreachable!("draw_charcreation() called outside of CharacterCreation runstate."), + }; + let (mut x, mut y) = (2.0 * TILESIZE.x, ((DISPLAYHEIGHT as f32) * TILESIZE.x) / 4.0); + const COLUMN_WIDTH: f32 = 20.0 * TILESIZE.x; + draw.text(&font.ib(), "Who are you?") + .size(FONTSIZE * 2.0) + .position(x, y) + .h_align_left(); + y = draw.last_text_bounds().max_y(); + let initial_y = y; + let ancestries = [ + ("h. Human", Ancestry::Human), + ("e. Elf", Ancestry::Elf), + ("d. Dwarf", Ancestry::Dwarf), + ("c. Catfolk", Ancestry::Catfolk), + ]; + for (k, v) in &ancestries { + draw.text(font.n(), k) + .size(FONTSIZE) + .position(x, y) + .h_align_left() + .color(get_colour(ancestry, *v)); + y = draw.last_text_bounds().max_y(); } - return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class: Class::Fighter }; + y = initial_y; + x += COLUMN_WIDTH; + let classes = [ + ("f. Fighter", Class::Fighter), + ("r. Rogue", Class::Rogue), + ("w. Wizard", Class::Wizard), + ("v. Villager", Class::Villager), + ]; + for (k, v) in &classes { + draw.text(font.n(), k) + .size(FONTSIZE) + .position(x, y) + .h_align_left() + .color(get_colour(class, *v)); + y = draw.last_text_bounds().max_y(); + } + y = initial_y; + x += COLUMN_WIDTH; + for line in ANCESTRYDATA.get(&ancestry).unwrap().iter() { + draw.text(font.n(), line).size(FONTSIZE).position(x, y).h_align_left(); + y = draw.last_text_bounds().max_y(); + } + y += TILESIZE.x; + for line in CLASSDATA.get(&class).unwrap().iter() { + draw.text(font.n(), line).size(FONTSIZE).position(x, y).h_align_left(); + y = draw.last_text_bounds().max_y(); + } +} + +fn get_colour(selected: T, desired: T) -> Color where T: PartialEq { + if selected == desired { Color::from_rgb(0.0, 1.0, 0.0) } else { Color::WHITE } +} + +/// Handles the player character creation screen. +pub fn character_creation(gs: &mut State, ctx: &mut App) -> CharCreateResult { + let runstate = gs.ecs.fetch::(); + let (ancestry, class) = match *runstate { + RunState::CharacterCreation { ancestry, class } => (ancestry, class), + _ => unreachable!("character_creation() called outside of CharacterCreation runstate."), + }; + + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return CharCreateResult::Selected { ancestry: Ancestry::Unset, class }; + } + KeyCode::Return => { + return CharCreateResult::Selected { ancestry, class }; + } + KeyCode::H => { + return CharCreateResult::NoSelection { ancestry: Ancestry::Human, class }; + } + KeyCode::E => { + return CharCreateResult::NoSelection { ancestry: Ancestry::Elf, class }; + } + KeyCode::D => { + return CharCreateResult::NoSelection { ancestry: Ancestry::Dwarf, class }; + } + KeyCode::C => { + return CharCreateResult::NoSelection { ancestry: Ancestry::Catfolk, class }; + } + KeyCode::F => { + return CharCreateResult::NoSelection { ancestry, class: Class::Fighter }; + } + KeyCode::R => { + return CharCreateResult::NoSelection { ancestry, class: Class::Rogue }; + } + KeyCode::W => { + return CharCreateResult::NoSelection { ancestry, class: Class::Wizard }; + } + KeyCode::V => { + return CharCreateResult::NoSelection { ancestry, class: Class::Villager }; + } + _ => {} + }; + } + return CharCreateResult::NoSelection { ancestry, class }; } /// Handles player ancestry setup. @@ -267,25 +255,9 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) { match ancestry { Ancestry::Human => {} Ancestry::Dwarf => { - renderables - .insert(*player, Renderable { - glyph: to_cp437(DWARF_GLYPH), - fg: RGB::named(DWARF_COLOUR), - bg: RGB::named(BLACK), - render_order: 0, - }) - .expect("Unable to insert renderable component"); *player_skills.skills.entry(Skill::Defence).or_insert(0) += DWARF_DEFENCE_MOD; } Ancestry::Elf => { - renderables - .insert(*player, Renderable { - glyph: to_cp437(ELF_GLYPH), - fg: RGB::named(ELF_COLOUR), - bg: RGB::named(BLACK), - render_order: 0, - }) - .expect("Unable to insert renderable component"); let mut telepaths = ecs.write_storage::(); telepaths .insert(*player, Telepath { @@ -303,14 +275,6 @@ pub fn setup_player_ancestry(ecs: &mut World, ancestry: Ancestry) { .expect("Unable to insert energy component"); } Ancestry::Catfolk => { - renderables - .insert(*player, Renderable { - glyph: to_cp437(CATFOLK_GLYPH), - fg: RGB::named(CATFOLK_COLOUR), - bg: RGB::named(BLACK), - render_order: 0, - }) - .expect("Unable to insert renderable component"); let mut speeds = ecs.write_storage::(); speeds .insert(*player, Energy { @@ -342,14 +306,7 @@ pub fn setup_player_class(ecs: &mut World, class: Class, ancestry: Ancestry) { let mut attributes = ecs.write_storage::(); let (str, dex, con, int, wis, cha) = get_attribute_rolls(&mut rng, class, ancestry); attributes - .insert(player, Attributes { - strength: Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) }, - dexterity: Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) }, - constitution: Attribute { base: con, modifiers: 0, bonus: attr_bonus(con) }, - intelligence: Attribute { base: int, modifiers: 0, bonus: attr_bonus(int) }, - wisdom: Attribute { base: wis, modifiers: 0, bonus: attr_bonus(wis) }, - charisma: Attribute { base: cha, modifiers: 0, bonus: attr_bonus(cha) }, - }) + .insert(player, Attributes::with_stats(str, dex, con, int, wis, cha)) .expect("Unable to insert attributes component"); let mut pools = ecs.write_storage::(); @@ -407,6 +364,9 @@ fn get_starting_inventory( let mut carried: Vec = Vec::new(); let starting_food: &str; match class { + Class::Unset => { + starting_food = VILLAGER_STARTING_FOOD; + } Class::Fighter => { starting_food = FIGHTER_STARTING_FOOD; equipped = vec![ @@ -440,7 +400,7 @@ fn get_starting_inventory( } Class::Villager => { starting_food = VILLAGER_STARTING_FOOD; - pick_random_table_item(rng, &mut equipped, "villager_equipment", "1", None); + pick_random_table_item(rng, &mut equipped, "villager_equipment", "1d1", None); } } pick_random_table_item(rng, &mut carried, "food", starting_food, None); @@ -454,7 +414,9 @@ fn pick_random_table_item( dice_str: &'static str, difficulty: Option ) { - let dice = parse_dice_string(dice_str).expect("Error parsing dice"); + let dice = parse_dice_string(dice_str).expect( + format!("Error parsing dice: {}", dice_str).as_str() + ); for _i in 0..rng.roll_dice(dice.n_dice, dice.die_type) + dice.bonus { push_to.push(raws::table_by_name(&raws::RAWS.lock().unwrap(), table, difficulty).roll(rng)); } diff --git a/src/gui/cheat_menu.rs b/src/gui/cheat_menu.rs index eae6f4c..33e55a2 100644 --- a/src/gui/cheat_menu.rs +++ b/src/gui/cheat_menu.rs @@ -1,5 +1,9 @@ -use super::State; +use super::{ State }; use bracket_lib::prelude::*; +use notan::prelude::*; +use notan::draw::DrawTextSection; +use std::collections::HashMap; +use crate::consts::{ TILESIZE, FONTSIZE }; #[derive(PartialEq, Copy, Clone)] pub enum CheatMenuResult { @@ -12,53 +16,50 @@ pub enum CheatMenuResult { GodMode, } -pub fn show_cheat_menu(_gs: &mut State, ctx: &mut BTerm) -> CheatMenuResult { - let (x_offset, y_offset) = (1, 10); - ctx.print_color( - 1 + x_offset, - 1 + y_offset, - RGB::named(RED), - RGB::named(BLACK), - "DEBUG MENU! [aA-zZ][Esc.]" - ); - let x = 1 + x_offset; - let mut y = 3 + y_offset; - let count = 5; - let width = 19; - - ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(RED), RGB::named(BLACK)); - y += 1; - // Asc - ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('a')); - ctx.print(x_offset + 4, y, "ASCEND A FLOOR"); - y += 1; - // Desc - ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('d')); - ctx.print(x_offset + 4, y, "DESCEND A FLOOR"); - y += 1; - // Heal - ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('h')); - ctx.print(x_offset + 4, y, "HEAL TO FULL"); - y += 1; - // Reveal map - ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('m')); - ctx.print(x_offset + 4, y, "MAGIC MAP REVEAL"); - y += 1; - // Godmode - ctx.set(x_offset + 2, y, RGB::named(YELLOW), RGB::named(BLACK), to_cp437('g')); - ctx.print(x_offset + 4, y, "GOD MODE"); - // Match keys - match ctx.key { - None => CheatMenuResult::NoResponse, - Some(key) => - match key { - VirtualKeyCode::A => CheatMenuResult::Ascend, - VirtualKeyCode::D => CheatMenuResult::Descend, - VirtualKeyCode::H => CheatMenuResult::Heal, - VirtualKeyCode::M => CheatMenuResult::MagicMap, - VirtualKeyCode::G => CheatMenuResult::GodMode, - VirtualKeyCode::Escape => CheatMenuResult::Cancel, - _ => CheatMenuResult::NoResponse, +pub fn show_cheat_menu(_gs: &mut State, ctx: &mut App) -> CheatMenuResult { + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::A => { + return CheatMenuResult::Ascend; } + KeyCode::D => { + return CheatMenuResult::Descend; + } + KeyCode::H => { + return CheatMenuResult::Heal; + } + KeyCode::M => { + return CheatMenuResult::MagicMap; + } + KeyCode::G => { + return CheatMenuResult::GodMode; + } + KeyCode::Escape => { + return CheatMenuResult::Cancel; + } + _ => {} + }; } + return CheatMenuResult::NoResponse; +} + +pub fn draw_cheat_menu( + draw: &mut notan::draw::Draw, + _atlas: &HashMap, + font: &crate::Fonts +) { + let offsets = crate::camera::get_offset(); + const DEBUG_MENU: &str = + r#"DEBUG MENU! [aA-zZ][Esc.] + + a - ASCEND A FLOOR + d - DESCEND A FLOOR + h - HEAL TO FULL + m - MAGIC MAP REVEAL + g - GOD MODE"#; + draw.text(&font.n(), DEBUG_MENU) + .position((1.0 + (offsets.x as f32)) * TILESIZE.x, (1.0 + (offsets.y as f32)) * TILESIZE.x) + .color(Color::RED) + .size(FONTSIZE); } diff --git a/src/gui/farlook.rs b/src/gui/farlook.rs index c8f6312..b2e23ca 100644 --- a/src/gui/farlook.rs +++ b/src/gui/farlook.rs @@ -1,5 +1,10 @@ -use super::{ State, RunState, tooltip::draw_tooltips, camera::get_screen_bounds }; +use super::{ State, RunState, World, tooltip::draw_tooltips, camera::get_offset }; use bracket_lib::prelude::*; +use notan::prelude::*; +use notan::draw::{ Draw, DrawImages }; +use std::collections::HashMap; +use crate::consts::visuals::{ TILES_IN_VIEWPORT_H, TILES_IN_VIEWPORT_W }; +use crate::consts::TILESIZE; #[derive(PartialEq, Copy, Clone)] pub enum FarlookResult { @@ -10,45 +15,62 @@ pub enum FarlookResult { Cancel, } -pub fn show_farlook(gs: &mut State, ctx: &mut BTerm) -> FarlookResult { +pub fn show_farlook(gs: &mut State, ctx: &mut App) -> FarlookResult { let runstate = gs.ecs.fetch::(); - let (_min_x, _max_x, _min_y, _max_y, x_offset, y_offset) = get_screen_bounds(&gs.ecs, ctx); - - ctx.print_color( - 1 + x_offset, - 1 + y_offset, - RGB::named(WHITE), - RGB::named(BLACK), - "Look at what? [move keys][Esc.]" - ); - if let RunState::Farlook { x, y } = *runstate { - let (screen_x, screen_y) = (69, 41); - let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32)); - 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')); - draw_tooltips(&gs.ecs, ctx, Some((x, y))); - - return match ctx.key { - None => FarlookResult::NoResponse { x, y }, - Some(key) => - match key { - VirtualKeyCode::Escape | VirtualKeyCode::X => FarlookResult::Cancel, - VirtualKeyCode::Numpad9 => FarlookResult::NoResponse { x: x + 1, y: y - 1 }, - VirtualKeyCode::Numpad8 => FarlookResult::NoResponse { x, y: y - 1 }, - VirtualKeyCode::Numpad7 => FarlookResult::NoResponse { x: x - 1, y: y - 1 }, - VirtualKeyCode::Numpad6 => FarlookResult::NoResponse { x: x + 1, y }, - VirtualKeyCode::Numpad4 => FarlookResult::NoResponse { x: x - 1, y }, - VirtualKeyCode::Numpad3 => FarlookResult::NoResponse { x: x + 1, y: y + 1 }, - VirtualKeyCode::Numpad2 => FarlookResult::NoResponse { x, y: y + 1 }, - VirtualKeyCode::Numpad1 => FarlookResult::NoResponse { x: x - 1, y: y + 1 }, - _ => FarlookResult::NoResponse { x, y }, + let x = x.clamp(0, TILES_IN_VIEWPORT_W - 1); + let y = y.clamp(0, TILES_IN_VIEWPORT_H - 1); + let key = &ctx.keyboard; + // Movement + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape | KeyCode::X => { + return FarlookResult::Cancel; } - }; + KeyCode::Numpad1 => { + return FarlookResult::NoResponse { x: x - 1, y: y + 1 }; + } + KeyCode::Numpad2 => { + return FarlookResult::NoResponse { x, y: y + 1 }; + } + KeyCode::Numpad3 => { + return FarlookResult::NoResponse { x: x + 1, y: y + 1 }; + } + KeyCode::Numpad4 => { + return FarlookResult::NoResponse { x: x - 1, y }; + } + KeyCode::Numpad6 => { + return FarlookResult::NoResponse { x: x + 1, y }; + } + KeyCode::Numpad7 => { + return FarlookResult::NoResponse { x: x - 1, y: y - 1 }; + } + KeyCode::Numpad8 => { + return FarlookResult::NoResponse { x, y: y - 1 }; + } + KeyCode::Numpad9 => { + return FarlookResult::NoResponse { x: x + 1, y: y - 1 }; + } + _ => {} + } + } + return FarlookResult::NoResponse { x, y }; } else { - let ppos = gs.ecs.fetch::(); - // TODO: PPOS + offsets (should get these from screen_bounds()) - return FarlookResult::NoResponse { x: ppos.x + x_offset, y: ppos.x + y_offset }; + return FarlookResult::NoResponse { x: TILES_IN_VIEWPORT_W / 2, y: TILES_IN_VIEWPORT_H / 2 }; } } + +pub fn draw_farlook( + ecs: &World, + x: i32, + y: i32, + draw: &mut Draw, + atlas: &HashMap +) { + let placement = super::viewport_to_px(x, y); + draw.image(atlas.get("select1").unwrap()) + .position(placement.x, placement.y) + .size(TILESIZE.sprite_x, TILESIZE.sprite_y); + let _idx = super::viewport_to_idx(ecs, x, y); + // Get tooltip for idx, etc. +} diff --git a/src/gui/identify_menu.rs b/src/gui/identify_menu.rs index 14e0686..4362a11 100644 --- a/src/gui/identify_menu.rs +++ b/src/gui/identify_menu.rs @@ -3,10 +3,12 @@ use super::{ item_colour_ecs, obfuscate_name_ecs, print_options, + unique_ecs, renderable_colour, ItemMenuResult, UniqueInventoryItem, BUC, + Key, }; use crate::{ gamelog, @@ -23,7 +25,7 @@ use crate::{ }; use bracket_lib::prelude::*; use specs::prelude::*; -use std::collections::BTreeMap; +use std::collections::HashMap; /// Handles the Identify menu. pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option) { @@ -37,38 +39,41 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option(); let renderables = gs.ecs.read_storage::(); let beatitudes = gs.ecs.read_storage::(); + let keys = gs.ecs.read_storage::(); let build_identify_iterator = || { - (&entities, &items, &renderables, &names).join().filter(|(item_entity, _i, _r, n)| { - // If not owned by the player, return false. - let mut keep = false; - if let Some(bp) = backpack.get(*item_entity) { - if bp.owner == *player_entity { - keep = true; + (&entities, &items, &renderables, &names, &keys) + .join() + .filter(|(item_entity, _i, _r, n, _k)| { + // If not owned by the player, return false. + let mut keep = false; + if let Some(bp) = backpack.get(*item_entity) { + if bp.owner == *player_entity { + keep = true; + } } - } - // If not equipped by the player, return false. - if let Some(equip) = equipped.get(*item_entity) { - if equip.owner == *player_entity { - keep = true; + // If not equipped by the player, return false. + if let Some(equip) = equipped.get(*item_entity) { + if equip.owner == *player_entity { + keep = true; + } } - } - if !keep { - return false; - } - // If not obfuscated, or already identified, return false. - if - (!obfuscated.get(*item_entity).is_some() || - dm.identified_items.contains(&n.name)) && - beatitudes - .get(*item_entity) - .map(|beatitude| beatitude.known) - .unwrap_or(true) - { - return false; - } - return true; - }) + if !keep { + return false; + } + // If not obfuscated, or already identified, return false. + if + (!obfuscated.get(*item_entity).is_some() || + dm.identified_items.contains(&n.name)) && + beatitudes + .get(*item_entity) + .map(|beatitude| beatitude.known) + .unwrap_or(true) + { + return false; + } + return true; + }) }; // Build list of items to display @@ -91,51 +96,32 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option().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(), - }; + let mut player_inventory: super::PlayerInventory = HashMap::new(); + for (entity, _i, renderable, name, key) in build_identify_iterator() { + let unique_item = unique_ecs(&gs.ecs, entity); player_inventory .entry(unique_item) - .and_modify(|(_e, count)| { - *count += 1; + .and_modify(|slot| { + slot.count += 1; }) - .or_insert((entity, 1)); + .or_insert(super::InventorySlot { item: entity, count: 1, idx: key.idx }); } // Get display args let width = get_max_inventory_width(&player_inventory); - let (_, _, _, _, x_offset, y_offset) = crate::camera::get_screen_bounds(&gs.ecs, ctx); - let (x, y) = (x_offset + 1, y_offset + 3); + let offsets = crate::camera::get_offset(); + let (x, y) = (offsets.x + 1, offsets.y + 3); // Draw menu ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + offsets.x, + 1 + offsets.y, RGB::named(WHITE), RGB::named(BLACK), "Identify which item? [aA-zZ][Esc.]" ); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK)); - print_options(&player_inventory, x + 1, y + 1, ctx); + // Input - match ctx.key { + /*match ctx.key { None => (ItemMenuResult::NoResponse, None), Some(key) => match key { @@ -161,4 +147,6 @@ pub fn identify(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option Vec { + vec![ + ItemType::Weapon, + ItemType::Armour, + ItemType::Comestible, + ItemType::Potion, + ItemType::Scroll, + ItemType::Spellbook, + ItemType::Wand, + ItemType::Amulet, + ItemType::Ring + ] +} + +pub fn draw_items( + ecs: &World, + draw: &mut Draw, + font: &Fonts, + x: f32, + y: f32, + loc: Location, + itemtypes: Option> +) { + let mut y = y; + if let Some(itemtypes) = itemtypes { + for itemtype in itemtypes { + let filter = match loc { + Location::All => Filter::All(Some(itemtype)), + Location::Backpack => Filter::Backpack(Some(itemtype)), + Location::Equipped => Filter::Equipped, + }; + let inv = items(ecs, filter); + if inv.is_empty() { + continue; + } + draw.text(&font.b(), itemtype.string()) + .position(x, y) + .color(Color::WHITE) + .size(FONTSIZE); + y += TILESIZE.x; + y = print_options(ecs, draw, font, &inv, x, y) + TILESIZE.x; + } + } else { + let filter = match loc { + Location::All => Filter::All(None), + Location::Backpack => Filter::Backpack(None), + Location::Equipped => Filter::Equipped, + }; + let inv = items(ecs, filter); + if inv.is_empty() { + return; + } + y = print_options(ecs, draw, font, &inv, x, y) + TILESIZE.x; + } +} + +pub fn draw_all_items(ecs: &World, draw: &mut Draw, font: &Fonts, x: f32, y: f32) { + draw_items(ecs, draw, font, x, y, Location::All, Some(all_itemtypes())); +} + +pub fn draw_backpack_items(ecs: &World, draw: &mut Draw, font: &Fonts, x: f32, y: f32) { + draw_items(ecs, draw, font, x, y, Location::Backpack, Some(all_itemtypes())); +} diff --git a/src/gui/letter_to_option.rs b/src/gui/letter_to_option.rs index 8b32109..b1f29d9 100644 --- a/src/gui/letter_to_option.rs +++ b/src/gui/letter_to_option.rs @@ -1,65 +1,65 @@ -use bracket_lib::prelude::*; +use notan::prelude::*; -pub fn letter_to_option(key: VirtualKeyCode, shift: bool) -> i32 { +pub fn letter_to_option(key: KeyCode, shift: bool) -> Option { if shift { match key { - VirtualKeyCode::A => 26, - VirtualKeyCode::B => 27, - VirtualKeyCode::C => 28, - VirtualKeyCode::D => 29, - VirtualKeyCode::E => 30, - VirtualKeyCode::F => 31, - VirtualKeyCode::G => 32, - VirtualKeyCode::H => 33, - VirtualKeyCode::I => 34, - VirtualKeyCode::J => 35, - VirtualKeyCode::K => 36, - VirtualKeyCode::L => 37, - VirtualKeyCode::M => 38, - VirtualKeyCode::N => 39, - VirtualKeyCode::O => 40, - VirtualKeyCode::P => 41, - VirtualKeyCode::Q => 42, - VirtualKeyCode::R => 43, - VirtualKeyCode::S => 44, - VirtualKeyCode::T => 45, - VirtualKeyCode::U => 46, - VirtualKeyCode::V => 47, - VirtualKeyCode::W => 48, - VirtualKeyCode::X => 49, - VirtualKeyCode::Y => 50, - VirtualKeyCode::Z => 51, - _ => -1, + KeyCode::A => Some(26), + KeyCode::B => Some(27), + KeyCode::C => Some(28), + KeyCode::D => Some(29), + KeyCode::E => Some(30), + KeyCode::F => Some(31), + KeyCode::G => Some(32), + KeyCode::H => Some(33), + KeyCode::I => Some(34), + KeyCode::J => Some(35), + KeyCode::K => Some(36), + KeyCode::L => Some(37), + KeyCode::M => Some(38), + KeyCode::N => Some(39), + KeyCode::O => Some(40), + KeyCode::P => Some(41), + KeyCode::Q => Some(42), + KeyCode::R => Some(43), + KeyCode::S => Some(44), + KeyCode::T => Some(45), + KeyCode::U => Some(46), + KeyCode::V => Some(47), + KeyCode::W => Some(48), + KeyCode::X => Some(49), + KeyCode::Y => Some(50), + KeyCode::Z => Some(51), + _ => None, } } else { match key { - VirtualKeyCode::A => 0, - VirtualKeyCode::B => 1, - VirtualKeyCode::C => 2, - VirtualKeyCode::D => 3, - VirtualKeyCode::E => 4, - VirtualKeyCode::F => 5, - VirtualKeyCode::G => 6, - VirtualKeyCode::H => 7, - VirtualKeyCode::I => 8, - VirtualKeyCode::J => 9, - VirtualKeyCode::K => 10, - VirtualKeyCode::L => 11, - VirtualKeyCode::M => 12, - VirtualKeyCode::N => 13, - VirtualKeyCode::O => 14, - VirtualKeyCode::P => 15, - VirtualKeyCode::Q => 16, - VirtualKeyCode::R => 17, - VirtualKeyCode::S => 18, - VirtualKeyCode::T => 19, - VirtualKeyCode::U => 20, - VirtualKeyCode::V => 21, - VirtualKeyCode::W => 22, - VirtualKeyCode::X => 23, - VirtualKeyCode::Y => 24, - VirtualKeyCode::Z => 25, - _ => -1, + KeyCode::A => Some(0), + KeyCode::B => Some(1), + KeyCode::C => Some(2), + KeyCode::D => Some(3), + KeyCode::E => Some(4), + KeyCode::F => Some(5), + KeyCode::G => Some(6), + KeyCode::H => Some(7), + KeyCode::I => Some(8), + KeyCode::J => Some(9), + KeyCode::K => Some(10), + KeyCode::L => Some(11), + KeyCode::M => Some(12), + KeyCode::N => Some(13), + KeyCode::O => Some(14), + KeyCode::P => Some(15), + KeyCode::Q => Some(16), + KeyCode::R => Some(17), + KeyCode::S => Some(18), + KeyCode::T => Some(19), + KeyCode::U => Some(20), + KeyCode::V => Some(21), + KeyCode::W => Some(22), + KeyCode::X => Some(23), + KeyCode::Y => Some(24), + KeyCode::Z => Some(25), + _ => None, } } } diff --git a/src/gui/main_menu.rs b/src/gui/main_menu.rs new file mode 100644 index 0000000..0036fb1 --- /dev/null +++ b/src/gui/main_menu.rs @@ -0,0 +1,47 @@ +use notan::prelude::*; +use notan::draw::{ Draw, CreateDraw, DrawTextSection, Font }; +use specs::prelude::*; +use std::collections::HashMap; +use super::{ FONTSIZE, RunState, DISPLAYWIDTH, TILESIZE, MainMenuSelection }; +use crate::consts::DISPLAYHEIGHT; +use crate::Fonts; + +pub fn draw_mainmenu(ecs: &World, draw: &mut Draw, atlas: &HashMap, font: &Fonts) { + let runstate = ecs.read_resource::(); + let selected = match *runstate { + RunState::MainMenu { menu_selection } => menu_selection, + _ => unreachable!("draw_mainmenu() called outside of MainMenu runstate."), + }; + let save_exists = crate::saveload_system::does_save_exist(); + const MID_X: f32 = ((DISPLAYWIDTH as f32) * TILESIZE.x) / 2.0; + + let (x, mut y) = (MID_X, ((DISPLAYHEIGHT as f32) * TILESIZE.x) / 4.0); + draw.text(&font.ib(), "RUST-RL") + .size(FONTSIZE * 2.0) + .position(x, y) + .h_align_center(); + y = draw.last_text_bounds().max_y(); + draw.text(&font.n(), "New Game") + .size(FONTSIZE) + .position(x, y) + .h_align_center() + .color(get_colour(selected, MainMenuSelection::NewGame)); + if save_exists { + y = draw.last_text_bounds().max_y(); + draw.text(font.n(), "Load Game") + .size(FONTSIZE) + .position(x, y) + .h_align_center() + .color(get_colour(selected, MainMenuSelection::LoadGame)); + } + y = draw.last_text_bounds().max_y(); + draw.text(&font.n(), "Quit") + .size(FONTSIZE) + .position(x, y) + .h_align_center() + .color(get_colour(selected, MainMenuSelection::Quit)); +} + +fn get_colour(selected: MainMenuSelection, desired: MainMenuSelection) -> Color { + if selected == desired { Color::from_rgb(0.0, 1.0, 0.0) } else { Color::WHITE } +} diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 13e32d0..bbfdfbf 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -32,18 +32,31 @@ use super::{ Skills, Viewshed, BUC, - data::ids::get_local_col, + Key, + Item, + ItemType, + consts::ids::get_local_col, }; -use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH; -use crate::data::visuals::{ +use crate::consts::prelude::*; +use crate::consts::entity::CARRY_CAPACITY_PER_STRENGTH; +use crate::consts::visuals::{ TARGETING_LINE_COL, TARGETING_CURSOR_COL, TARGETING_AOE_COL, TARGETING_VALID_COL, + VIEWPORT_W, + VIEWPORT_H, }; +use crate::consts::{ TILESIZE, FONTSIZE, DISPLAYWIDTH, DISPLAYHEIGHT }; +use crate::Fonts; +use notan::prelude::*; +use notan::draw::{ Draw, DrawTextSection, DrawImages, DrawShapes }; +use std::collections::HashMap; use bracket_lib::prelude::*; use specs::prelude::*; -use std::collections::BTreeMap; +use std::collections::{ BTreeMap, HashSet }; +use crate::invkeys::check_key; + mod character_creation; mod cheat_menu; mod letter_to_option; @@ -54,25 +67,13 @@ mod identify_menu; pub use identify_menu::*; mod tooltip; pub use cheat_menu::*; -use crate::data::events::*; +use crate::consts::events::*; mod farlook; pub use farlook::*; - -/// Gives a popup box with a message and a title, and waits for a keypress. -#[allow(unused)] -pub fn yes_no(ctx: &mut BTerm, question: String) -> Option { - ctx.print_color_centered(15, RGB::named(YELLOW), RGB::named(BLACK), question); - ctx.print_color_centered(17, RGB::named(CYAN), RGB::named(BLACK), "(y)es or (n)o"); - match ctx.key { - None => None, - Some(key) => - match key { - VirtualKeyCode::Y => Some(true), - VirtualKeyCode::N => Some(false), - _ => None, - } - } -} +mod main_menu; +pub use main_menu::*; +mod inventory; +pub use inventory::*; pub fn draw_lerping_bar( ctx: &mut BTerm, @@ -82,26 +83,345 @@ pub fn draw_lerping_bar( n: i32, max: i32, full_colour: RGB, - empty_colour: RGB + empty_colour: RGB, + with_text: bool, + with_bg: bool ) { let percent = (n as f32) / (max as f32); let fill_width = (percent * (width as f32)) as i32; let bg = empty_colour.lerp(full_colour, percent); - let fg = RGB::named(BLACK); + let black = RGB::named(BLACK); for x in 0..width { if x <= fill_width { - ctx.print_color(sx + x, sy, fg, bg, " "); - } else { - ctx.print_color(sx + x, sy, RGB::named(BLACK), RGB::named(BLACK), " "); + ctx.print_color(sx + x, sy, black, bg, ' '); + } else if with_bg { + ctx.print_color(sx + x, sy, black, black, ' '); } } - ctx.print(sx - 1, sy, "["); - let health = format!("{}/{}", n, max); - ctx.print_color(sx + 1, sy, fg, bg, health); - ctx.print(sx + width, sy, "]"); + if with_text { + ctx.print(sx - 1, sy, "["); + let health = format!("{}/{}", n, max); + ctx.print_color(sx + 1, sy, black, bg, health); + ctx.print(sx + width, sy, "]"); + } +} + +fn draw_bar_sprite( + draw: &mut Draw, + atlas: &HashMap, + sx: f32, + y: f32, + w: i32, + n: i32, + max: i32, + sprite: &str +) { + let percent = (n as f32) / (max as f32); + 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 sprite = if let Some(sprite) = atlas.get(&format!("{}_{}_{}", sprite, fill, suffix)) { + sprite + } else { + panic!("No sprite found in atlas: {}_{}_{}", sprite, fill, suffix) + }; + draw.image(sprite).position(sx + (x as f32) * TILESIZE.x, y); + } +} + +pub const TEXT_FONT_MOD: i32 = 2; + +pub fn draw_bar( + draw: &mut notan::draw::Draw, + x: f32, + y: f32, + width: f32, // Tiles + height: f32, // Px + current: i32, + max: i32, + full: Color, + empty: Color +) { + // % full * maximum width in tiles * tile size, to get width in px + let fill: f32 = (f32::max(current as f32, 0.0) / (max as f32)) * width * TILESIZE.x; + draw.line((x, y), (x + fill, y)) + .color(full) + .width(height); + draw.line((x + fill, y), (x + width * TILESIZE.x, y)) + .color(empty) + .width(height); +} + +pub fn draw_ui2(ecs: &World, draw: &mut Draw, atlas: &HashMap, font: &Fonts) { + let pools = ecs.read_storage::(); + let attributes = ecs.read_storage::(); + let players = ecs.read_storage::(); + let hunger = ecs.read_storage::(); + let burden = ecs.read_storage::(); + let skills = ecs.read_storage::(); + for (_p, stats, attributes, hunger, skills) in ( + &players, + &pools, + &attributes, + &hunger, + &skills, + ).join() { + let initial_x = 24.0 * TILESIZE.x; + let mut x = initial_x; + let row1 = ((DISPLAYHEIGHT as f32) - 3.0) * TILESIZE.x; // 2 tiles from the bottom, in px. + let row2 = row1 + TILESIZE.x; // 1 tile below row2. + const BAR_X: f32 = 1.0 * TILESIZE.x; + const BAR_WIDTH: f32 = 22.0; + draw_bar( + draw, + BAR_X, + row1 + 8.0, + BAR_WIDTH, + TILESIZE.x, + stats.hit_points.current, + stats.hit_points.max, + Color::GREEN, + Color::RED + ); + draw_bar( + draw, + BAR_X, + row2 + 8.0, + BAR_WIDTH, + TILESIZE.x, + stats.mana.current, + stats.mana.max, + Color::BLUE, + Color::RED + ); + let hp_colours: (RGB, RGB, RGB) = ( + RGB::named(GREEN), + RGB::named(RED), + RGB::from_f32(0.0, 0.5, 0.0), + ); + let mp_colours: (RGB, RGB, RGB) = ( + RGB::named(CYAN), + RGB::named(RED), + RGB::from_f32(0.0, 0.5, 0.5), + ); + let hp: RGB = hp_colours.1.lerp( + hp_colours.0, + (stats.hit_points.current as f32) / (stats.hit_points.max as f32) + ); + let mp: RGB = mp_colours.1.lerp( + mp_colours.0, + (stats.mana.current as f32) / (stats.mana.max as f32) + ); + draw.text(&font.b(), "HP").position(x, row1).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{}", stats.hit_points.current)) + .position(x, row1) + .size(FONTSIZE) + .color(Color::from_rgb(hp.r, hp.g, hp.b)); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("({})", stats.hit_points.max)) + .position(x, row1) + .size(FONTSIZE) + .color(Color::from_rgb(hp_colours.2.r, hp_colours.2.g, hp_colours.2.b)); + x = initial_x; + draw.text(&font.b(), "MP").position(x, row2).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{}", stats.mana.current)) + .position(x, row2) + .size(FONTSIZE) + .color(Color::from_rgb(mp.r, mp.g, mp.b)); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("({})", stats.mana.max)) + .position(x, row2) + .size(FONTSIZE) + .color(Color::from_rgb(mp_colours.2.r, mp_colours.2.g, mp_colours.2.b)); + // Draw AC + let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*skills); + let mut armour_ac_bonus = 0; + let equipped = ecs.read_storage::(); + let ac = ecs.read_storage::(); + let player_entity = ecs.fetch::(); + for (wielded, ac) in (&equipped, &ac).join() { + if wielded.owner == *player_entity { + armour_ac_bonus += ac.amount; + } + } + x = draw.last_text_bounds().max_x() + 2.0 * TILESIZE.x; + let armour_class = + stats.bac - attributes.dexterity.modifier() / 2 - skill_ac_bonus - armour_ac_bonus; + draw.text(&font.b(), "AC").position(x, row1).color(Color::PINK).size(FONTSIZE); + let last_x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", armour_class)).position(last_x, row1).size(FONTSIZE); + draw.text(&font.b(), &format!("XP")).position(x, row2).size(FONTSIZE); + let last_x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{}/{}", stats.level, stats.xp)) + .position(last_x, row2) + .size(FONTSIZE); + let attribute_x = draw.last_text_bounds().max_x() + 2.0 * TILESIZE.x; + draw.text(&font.b(), "STR").position(attribute_x, row1).color(Color::RED).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.strength.base)) + .position(x, row1) + .size(FONTSIZE); + x = draw.last_text_bounds().max_x() + TILESIZE.x; + draw.text(&font.b(), "DEX").position(x, row1).color(Color::GREEN).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.dexterity.base)) + .position(x, row1) + .size(FONTSIZE); + x = draw.last_text_bounds().max_x() + TILESIZE.x; + draw.text(&font.b(), "CON").position(x, row1).color(Color::ORANGE).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.constitution.base)) + .position(x, row1) + .size(FONTSIZE); + draw.text(&font.b(), "INT").position(attribute_x, row2).color(Color::BLUE).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.intelligence.base)) + .position(x, row2) + .size(FONTSIZE); + x = draw.last_text_bounds().max_x() + TILESIZE.x; + draw.text(&font.b(), "WIS").position(x, row2).color(Color::YELLOW).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.wisdom.base)) + .position(x, row2) + .size(FONTSIZE); + x = draw.last_text_bounds().max_x() + TILESIZE.x; + draw.text(&font.b(), "CHA").position(x, row2).color(Color::PURPLE).size(FONTSIZE); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), &format!("{:<2}", attributes.charisma.base)) + .position(x, row2) + .size(FONTSIZE); + let hungertxt = match hunger.state { + HungerState::Satiated => "Satiated", + HungerState::Normal => "Normal", + HungerState::Hungry => "Hungry", + HungerState::Weak => "Weak", + HungerState::Fainting => "Fainting", + HungerState::Starving => "Starving", + }; + match hunger.state { + HungerState::Normal => {} + _ => { + let col = get_hunger_colour(hunger.state); + draw.text(&font.n(), hungertxt) + .position(((VIEWPORT_W + 1) as f32) * TILESIZE.x, row1) + .color(Color::from_bytes(col.0, col.1, col.2, 255)) + .size(FONTSIZE) + .h_align_right(); + } + } + let map = ecs.fetch::(); + let id = if map.depth > 0 { + format!("{}{}", map.short_name, map.depth) + } else { + format!("{}", map.short_name) + }; + draw.text(&font.n(), &id) + .position(((VIEWPORT_W + 1) as f32) * TILESIZE.x, row2) + .color(Color::WHITE) // get_local_col() + .size(FONTSIZE) + .h_align_right(); + let turns = crate::gamelog::get_event_count(EVENT::COUNT_TURN); + x = draw.last_text_bounds().min_x() - TILESIZE.x; + draw.text(&font.n(), &format!("T{}", turns)) + .position(x, row2) + .color(Color::YELLOW) + .size(FONTSIZE) + .h_align_right(); + if let Some(burden) = burden.get(*player_entity) { + use crate::BurdenLevel; + let (text, colour) = match burden.level { + BurdenLevel::Burdened => ("Burdened", RGB::named(BROWN1)), + BurdenLevel::Strained => ("Strained", RGB::named(ORANGE)), + BurdenLevel::Overloaded => ("Overloaded", RGB::named(RED)), + }; + draw.text(&font.n(), &text) + .position((VIEWPORT_W as f32) * TILESIZE.x, 50.0 * TILESIZE.x) + .color(Color::from_rgb(colour.r, colour.g, colour.b)) + .size(FONTSIZE) + .h_align_right(); + } + if stats.god { + draw.text(&font.n(), "--- GODMODE: ON ---") + .position(20.0 * TILESIZE.x, 20.0 * TILESIZE.x) + .color(Color::YELLOW) + .size(FONTSIZE); + } + // Equipment + draw_all_items(ecs, draw, font, ((VIEWPORT_W + 3) as f32) * TILESIZE.x, TILESIZE.x); + /*let renderables = ecs.read_storage::(); + let mut equipment: Vec<(String, RGB, RGB, FontCharType)> = Vec::new(); + let entities = ecs.entities(); + for (entity, _equipped, renderable) in (&entities, &equipped, &renderables) + .join() + .filter(|item| item.1.owner == *player_entity) { + equipment.push(( + obfuscate_name_ecs(ecs, entity).0, + RGB::named(item_colour_ecs(ecs, entity)), + renderable.fg, + renderable.glyph, + )); + } + let mut y = 1; + // TODO: Fix all of this to work with notan colours, and sprites. + if !equipment.is_empty() { + draw.text(&font.b(), "Equipment") + .position(((VIEWPORT_W + 3) as f32) * TILESIZE.x, (y as f32) * TILESIZE.x) + .size(FONTSIZE); + let mut j: u8 = 0; + for item in equipment { + y += 1; + x = ((VIEWPORT_W + 3) as f32) * TILESIZE.x; + draw.text(&font.b(), &format!("{} ", (97 + j) as char)) + .position(x, (y as f32) * TILESIZE.x) + .color(Color::YELLOW) + .size(FONTSIZE); + j += 1; + x = draw.last_text_bounds().max_x(); + let mut col = item.2; + draw.text(&font.n(), &format!("{} ", item.3 as u8 as char)) + .position(x, (y as f32) * TILESIZE.x) + .size(FONTSIZE) + .color(Color::from_rgb(col.r, col.g, col.b)); // Colours here - and below. + x = draw.last_text_bounds().max_x(); + col = item.1; + draw.text(&font.n(), &item.0) + .position(x, (y as f32) * TILESIZE.x) + .size(FONTSIZE) + .color(Color::from_rgb(col.r, col.g, col.b)); + x = draw.last_text_bounds().max_x(); + draw.text(&font.n(), " (worn)") + .position(x, (y as f32) * TILESIZE.x) + .size(FONTSIZE); + } + y += 2; + } + // Backpack + x = ((VIEWPORT_W + 3) as f32) * TILESIZE.x; + draw.text(&font.b(), "Backpack") + .position(x, (y as f32) * TILESIZE.x) + .size(FONTSIZE); + draw.text( + &font.b(), + &format!( + "[{:.1}/{} lbs]", + stats.weight, + (attributes.strength.base + attributes.strength.bonuses) * + CARRY_CAPACITY_PER_STRENGTH + ) + ) + .position(((DISPLAYWIDTH - 1) as f32) * TILESIZE.x, (y as f32) * TILESIZE.x) + .size(FONTSIZE) + .h_align_right();*/ + //let player_inventory = get_player_inventory(&ecs); + // TODO: print_options() + } } pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { + ctx.set_active_console(TEXT_LAYER); // Render stats let pools = ecs.read_storage::(); let attributes = ecs.read_storage::(); @@ -119,23 +439,27 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { // Draw hp/mana bars draw_lerping_bar( ctx, - 2, + 2 * TEXT_FONT_MOD, 53, - 22, + 22 * TEXT_FONT_MOD, stats.hit_points.current, stats.hit_points.max, RGB::from_u8(0, 255, 0), - RGB::from_u8(255, 0, 0) + RGB::from_u8(255, 0, 0), + true, + true ); draw_lerping_bar( ctx, - 2, + 2 * TEXT_FONT_MOD, 54, - 22, + 22 * TEXT_FONT_MOD, stats.mana.current, stats.mana.max, RGB::named(BLUE), - RGB::named(BLACK) + RGB::named(BLACK), + true, + true ); // Draw AC let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*skills); @@ -149,19 +473,19 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } } let armour_class = - stats.bac - attributes.dexterity.bonus / 2 - skill_ac_bonus - armour_ac_bonus; - ctx.print_color(26, 53, RGB::named(PINK), RGB::named(BLACK), "AC"); - ctx.print_color(28, 53, RGB::named(WHITE), RGB::named(BLACK), armour_class); + stats.bac - attributes.dexterity.modifier() / 2 - skill_ac_bonus - armour_ac_bonus; + ctx.print_color(26 * TEXT_FONT_MOD, 53, RGB::named(PINK), RGB::named(BLACK), "AC"); + ctx.print_color(28 * TEXT_FONT_MOD, 53, RGB::named(WHITE), RGB::named(BLACK), armour_class); // Draw level ctx.print_color( - 26, + 26 * TEXT_FONT_MOD, 54, RGB::named(WHITE), RGB::named(BLACK), format!("XP{}/{}", stats.level, stats.xp) ); // Draw attributes - let x = 38; + let x = 38 * TEXT_FONT_MOD; ctx.print_color(x, 53, RGB::named(RED), RGB::named(BLACK), "STR"); ctx.print_color(x + 3, 53, RGB::named(WHITE), RGB::named(BLACK), attributes.strength.base); ctx.print_color(x + 7, 53, RGB::named(GREEN), RGB::named(BLACK), "DEX"); @@ -196,7 +520,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { match hunger.state { HungerState::Satiated => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 53, get_hunger_colour(hunger.state), RGB::named(BLACK), @@ -206,7 +530,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { HungerState::Normal => {} HungerState::Hungry => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 53, get_hunger_colour(hunger.state), RGB::named(BLACK), @@ -215,7 +539,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } HungerState::Weak => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 53, get_hunger_colour(hunger.state), RGB::named(BLACK), @@ -224,7 +548,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } HungerState::Fainting => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 53, get_hunger_colour(hunger.state), RGB::named(BLACK), @@ -233,7 +557,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } HungerState::Starving => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 53, get_hunger_colour(hunger.state), RGB::named(BLACK), @@ -246,7 +570,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { match burden.level { crate::BurdenLevel::Burdened => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 50, RGB::named(BROWN1), RGB::named(BLACK), @@ -255,7 +579,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } crate::BurdenLevel::Strained => { ctx.print_color_right( - 70, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, 50, RGB::named(ORANGE), RGB::named(BLACK), @@ -263,12 +587,24 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { ); } crate::BurdenLevel::Overloaded => { - ctx.print_color_right(70, 50, RGB::named(RED), RGB::named(BLACK), "Overloaded"); + ctx.print_color_right( + (VIEWPORT_W + 1) * TEXT_FONT_MOD, + 50, + RGB::named(RED), + RGB::named(BLACK), + "Overloaded" + ); } } } if stats.god { - ctx.print_color(20, 20, RGB::named(YELLOW), RGB::named(BLACK), "--- GODMODE: ON ---"); + ctx.print_color( + 20 * TEXT_FONT_MOD, + 20, + RGB::named(YELLOW), + RGB::named(BLACK), + "--- GODMODE: ON ---" + ); } // Draw equipment let renderables = ecs.read_storage::(); @@ -286,16 +622,34 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } let mut y = 1; if !equipment.is_empty() { - ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Equipment"); + ctx.print_color( + (VIEWPORT_W + 3) * TEXT_FONT_MOD, + y, + RGB::named(BLACK), + RGB::named(WHITE), + "Equipment" + ); let mut j = 0; for item in equipment { y += 1; - ctx.set(72, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType)); + ctx.set( + (VIEWPORT_W + 3) * TEXT_FONT_MOD, + y, + RGB::named(YELLOW), + RGB::named(BLACK), + 97 + (j as FontCharType) + ); j += 1; - ctx.set(74, y, item.2, RGB::named(BLACK), item.3); - ctx.print_color(76, y, item.1, RGB::named(BLACK), &item.0); + ctx.set((VIEWPORT_W + 3) * TEXT_FONT_MOD + 2, y, item.2, RGB::named(BLACK), item.3); ctx.print_color( - 76 + &item.0.len() + 1, + (VIEWPORT_W + 3) * TEXT_FONT_MOD + 4, + y, + item.1, + RGB::named(BLACK), + &item.0 + ); + ctx.print_color( + (VIEWPORT_W + 3) * TEXT_FONT_MOD + 4 + (item.0.len() as i32) + 1, y, RGB::named(WHITE), RGB::named(BLACK), @@ -306,40 +660,50 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } // Draw consumables - ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Backpack"); ctx.print_color( - 81, + (VIEWPORT_W + 3) * TEXT_FONT_MOD, + y, + RGB::named(BLACK), + RGB::named(WHITE), + "Backpack" + ); + ctx.print_color( + (VIEWPORT_W + 12) * TEXT_FONT_MOD, y, RGB::named(WHITE), RGB::named(BLACK), &format!( "[{:.1}/{} lbs]", stats.weight, - (attributes.strength.base + attributes.strength.modifiers) * + (attributes.strength.base + attributes.strength.bonuses) * CARRY_CAPACITY_PER_STRENGTH ) ); y += 1; - let player_inventory = get_player_inventory(&ecs); - y = print_options(&player_inventory, 72, y, ctx).0; - + //let player_inventory = get_player_inventory(&ecs); // Draw spells - if we have any -- NYI! if let Some(known_spells) = ecs.read_storage::().get(*player_entity) { y += 1; // Draw known spells - ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "Known Spells"); + ctx.print_color( + (VIEWPORT_W + 3) * TEXT_FONT_MOD, + y, + RGB::named(BLACK), + RGB::named(WHITE), + "Known Spells" + ); y += 1; let mut index = 1; for spell in known_spells.list.iter() { ctx.print_color( - 72, + (VIEWPORT_W + 3) * TEXT_FONT_MOD, y, RGB::named(YELLOW), RGB::named(BLACK), &format!("{}", index) ); ctx.print_color( - 74, + (VIEWPORT_W + 3) * TEXT_FONT_MOD + 2, y, RGB::named(CYAN), RGB::named(BLACK), @@ -396,23 +760,35 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { if !seen_entities.is_empty() { y += 1; - ctx.print_color(72, y, RGB::named(BLACK), RGB::named(WHITE), "In View"); + ctx.print_color( + (VIEWPORT_W + 3) * TEXT_FONT_MOD, + y, + RGB::named(BLACK), + RGB::named(WHITE), + "In View" + ); for entity in seen_entities { y += 1; - ctx.set(72, y, entity.2, RGB::named(BLACK), entity.3); - ctx.print_color(74, y, entity.1, RGB::named(BLACK), entity.0); + ctx.set((VIEWPORT_W + 3) * TEXT_FONT_MOD, y, entity.2, RGB::named(BLACK), entity.3); + ctx.print_color( + (VIEWPORT_W + 3) * TEXT_FONT_MOD + 2, + y, + entity.1, + RGB::named(BLACK), + entity.0 + ); } } } // Render the message log at [1, 7], ascending, with 7 lines and a max width of 68. - gamelog::print_log( - &mut BACKEND_INTERNAL.lock().consoles[0].console, - Point::new(1, 7), + /*gamelog::print_log( + &mut BACKEND_INTERNAL.lock().consoles[TEXT_LAYER].console, + Point::new(1 * TEXT_FONT_MOD, 7), false, 7, - 68 - ); + (VIEWPORT_W - 1) * TEXT_FONT_MOD + );*/ // Render id let map = ecs.fetch::(); @@ -421,12 +797,18 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { } else { format!("{}", map.short_name) }; - ctx.print_color_right(70, 54, get_local_col(map.id), RGB::named(BLACK), &id); + ctx.print_color_right( + (VIEWPORT_W + 1) * TEXT_FONT_MOD, + 54, + get_local_col(map.id), + RGB::named(BLACK), + &id + ); // Render turn let turns = crate::gamelog::get_event_count(EVENT::COUNT_TURN); ctx.print_color_right( - 69 - id.len(), + VIEWPORT_W * TEXT_FONT_MOD - (id.len() as i32), 54, RGB::named(YELLOW), RGB::named(BLACK), @@ -434,67 +816,84 @@ pub fn draw_ui(ecs: &World, ctx: &mut BTerm) { ); // Boxes and tooltips last, so they draw over everything else. - ctx.draw_hollow_box(0, 0, 70, 8, RGB::named(WHITE), RGB::named(BLACK)); // Log box - ctx.draw_hollow_box(0, 9, 70, 42, RGB::named(WHITE), RGB::named(BLACK)); // Camera box - ctx.draw_hollow_box(0, 52, 70, 3, RGB::named(WHITE), RGB::named(BLACK)); // Stats box - ctx.draw_hollow_box(71, 0, 33, 55, RGB::named(WHITE), RGB::named(BLACK)); // Side box + ctx.draw_hollow_box( + 0 * TEXT_FONT_MOD, + 0, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, + 8, + RGB::named(WHITE), + RGB::named(BLACK) + ); // Log box + ctx.draw_hollow_box( + 0 * TEXT_FONT_MOD, + 9, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, + 42, + RGB::named(WHITE), + RGB::named(BLACK) + ); // Camera box + ctx.draw_hollow_box( + 0 * TEXT_FONT_MOD, + 52, + (VIEWPORT_W + 1) * TEXT_FONT_MOD, + 3, + RGB::named(WHITE), + RGB::named(BLACK) + ); // Stats box + ctx.draw_hollow_box( + (VIEWPORT_W + 2) * TEXT_FONT_MOD, + 0, + 33 * TEXT_FONT_MOD, + 55, + RGB::named(WHITE), + RGB::named(BLACK) + ); // Side box + ctx.set_active_console(TILE_LAYER); tooltip::draw_tooltips(ecs, ctx, None); } pub fn get_input_direction( ecs: &mut World, - ctx: &mut BTerm, + ctx: &mut App, function: fn(i: i32, j: i32, ecs: &mut World) -> RunState ) -> RunState { - let (_, _, _, _, x_offset, y_offset) = camera::get_screen_bounds(ecs, ctx); - - ctx.print_color( - 1 + x_offset, - 1 + y_offset, - RGB::named(WHITE), - RGB::named(BLACK), - "In what direction? [0-9]/[YUHJKLBN]" - ); - match ctx.key { - None => { - return RunState::ActionWithDirection { function }; - } - Some(key) => - match key { - VirtualKeyCode::Escape => { - return RunState::AwaitingInput; - } - // Cardinals - VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => { - return function(-1, 0, ecs); - } - VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L => { - return function(1, 0, ecs); - } - VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => { - return function(0, -1, ecs); - } - VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => { - return function(0, 1, ecs); - } - // Diagonals - VirtualKeyCode::Numpad9 | VirtualKeyCode::U => { - return function(1, -1, ecs); - } - VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => { - return function(-1, -1, ecs); - } - VirtualKeyCode::Numpad3 | VirtualKeyCode::N => { - return function(1, 1, ecs); - } - VirtualKeyCode::Numpad1 | VirtualKeyCode::B => { - return function(-1, 1, ecs); - } - _ => { - return RunState::ActionWithDirection { function }; - } + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return RunState::AwaitingInput; } + KeyCode::Numpad1 | KeyCode::B => { + return function(-1, 1, ecs); + } + KeyCode::Numpad2 | KeyCode::J | KeyCode::Down => { + return function(0, 1, ecs); + } + KeyCode::Numpad3 | KeyCode::N => { + return function(1, 1, ecs); + } + KeyCode::Numpad4 | KeyCode::H | KeyCode::Left => { + return function(-1, 0, ecs); + } + KeyCode::Numpad5 | KeyCode::Period => { + return function(0, 0, ecs); + } + KeyCode::Numpad6 | KeyCode::L | KeyCode::Right => { + return function(1, 0, ecs); + } + KeyCode::Numpad7 | KeyCode::Y => { + return function(-1, -1, ecs); + } + KeyCode::Numpad8 | KeyCode::K | KeyCode::Up => { + return function(0, -1, ecs); + } + KeyCode::Numpad9 | KeyCode::U => { + return function(1, -1, ecs); + } + _ => {} + } } + RunState::ActionWithDirection { function } } #[derive(PartialEq, Copy, Clone)] @@ -505,76 +904,85 @@ pub enum ItemMenuResult { } pub fn print_options( + ecs: &World, + draw: &mut Draw, + font: &Fonts, inventory: &PlayerInventory, - mut x: i32, - mut y: i32, - ctx: &mut BTerm -) -> (i32, i32) { - let mut j = 0; - let initial_x: i32 = x; - let mut width: i32 = -1; - for (item, (_e, item_count)) in inventory { + mut x: f32, + mut y: f32 +) -> f32 { + let initial_x: f32 = x; + let mut sorted: Vec<_> = inventory.iter().collect(); + sorted.sort_by(|a, b| a.1.idx.cmp(&b.1.idx)); + for (info, slot) in sorted { x = initial_x; // Print the character required to access this item. i.e. (a) - if j < 26 { - ctx.set(x, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType)); + if slot.idx < 26 { + draw.text(&font.b(), &format!("{} ", (97 + slot.idx) as u8 as char)) + .position(x, y) + .color(Color::YELLOW) + .size(FONTSIZE); } else { // If we somehow have more than 26, start using capitals - ctx.set(x, y, RGB::named(YELLOW), RGB::named(BLACK), 65 - 26 + (j as FontCharType)); + draw.text(&font.b(), &format!("{} ", (65 - 26 + slot.idx) as u8 as char)) + .position(x, y) + .color(Color::YELLOW) + .size(FONTSIZE); } + x = draw.last_text_bounds().max_x(); + let fg = RGB::from_u8(info.renderables.0, info.renderables.1, info.renderables.2); + draw.text(&font.n(), &format!("{} ", info.glyph as u8 as char)) + .position(x, y) + .size(FONTSIZE) + .color(Color::from_rgb(fg.r, fg.g, fg.b)); + x = draw.last_text_bounds().max_x(); - x += 2; - let fg = RGB::from_u8(item.renderables.0, item.renderables.1, item.renderables.2); - ctx.set(x, y, fg, RGB::named(BLACK), item.glyph); - x += 2; - - let fg = RGB::from_u8(item.rgb.0, item.rgb.1, item.rgb.2); - if item_count > &1 { - // If more than one, print the number and pluralise - // i.e. (a) 3 daggers - ctx.print_color(x, y, fg, RGB::named(BLACK), item_count); - x += 2; - ctx.print_color(x, y, fg, RGB::named(BLACK), item.display_name.plural.to_string()); - let this_width = x - initial_x + (item.display_name.plural.len() as i32); - width = if width > this_width { width } else { this_width }; + let fg = RGB::from_u8(info.rgb.0, info.rgb.1, info.rgb.2); + if slot.count > 1 { + draw.text(&font.n(), &format!("{} {}", slot.count, info.display_name.plural)) + .position(x, y) + .color(Color::from_rgb(fg.r, fg.g, fg.b)) + .size(FONTSIZE); } else { - if item.display_name.singular.to_lowercase().ends_with("s") { - ctx.print_color(x, y, fg, RGB::named(BLACK), "some"); - x += 5; + let prefix = if info.display_name.singular.to_lowercase().ends_with("s") { + "some" } else if ['a', 'e', 'i', 'o', 'u'] .iter() - .any(|&v| item.display_name.singular.to_lowercase().starts_with(v)) + .any(|&v| info.display_name.singular.to_lowercase().starts_with(v)) { - // If one and starts with a vowel, print 'an' - // i.e. (a) an apple - ctx.print_color(x, y, fg, RGB::named(BLACK), "an"); - x += 3; + "an" } else { - // If one and not a vowel, print 'a' - // i.e. (a) a dagger - ctx.print_color(x, y, fg, RGB::named(BLACK), "a"); - x += 2; - } - ctx.print_color(x, y, fg, RGB::named(BLACK), item.display_name.singular.to_string()); - let this_width = x - initial_x + (item.display_name.singular.len() as i32); - width = if width > this_width { width } else { this_width }; + "a" + }; + draw.text(&font.n(), &format!("{} {}", prefix, info.display_name.singular)) + .position(x, y) + .color(Color::from_rgb(fg.r, fg.g, fg.b)) + .size(FONTSIZE); + if let Some(worn) = ecs.read_storage::().get(slot.item) { + x = draw.last_text_bounds().max_x(); + use crate::EquipmentSlot; + let text = match worn.slot { + EquipmentSlot::Melee | EquipmentSlot::Shield => "being held", + _ => "being worn", + }; + draw.text(&font.b(), &format!(" ({})", text)) + .position(x, y) + .color(Color::WHITE) + .size(FONTSIZE); + }; } - - y += 1; - j += 1; + y += TILESIZE.x; } - - return (y, width); + return y; } pub fn get_max_inventory_width(inventory: &PlayerInventory) -> i32 { let mut width: i32 = 0; - for (item, (_e, count)) in inventory { - let mut this_width = item.display_name.singular.len() as i32; - // Clean this up. It should use consts. - this_width += 4; // The spaces before and after the character to select this item, etc. - if count <= &1 { + for (item, slot) in inventory { + let mut this_width = 4; // The spaces before and after the character to select this item, etc. + if slot.count <= 1 { + this_width += item.display_name.singular.len() as i32; if item.display_name.singular == item.display_name.plural { this_width += 4; // "some".len } else if @@ -585,7 +993,8 @@ pub fn get_max_inventory_width(inventory: &PlayerInventory) -> i32 { this_width += 1; // "a".len } } else { - this_width += count.to_string().len() as i32; // i.e. "12".len + this_width += item.display_name.plural.len() as i32; + this_width += slot.count.to_string().len() as i32; // i.e. "12".len } width = if width > this_width { width } else { this_width }; } @@ -636,7 +1045,7 @@ pub fn obfuscate_name( if has_beatitude.known { let prefix = match has_beatitude.buc { BUC::Cursed => Some("cursed "), - BUC::Uncursed => None, + BUC::Uncursed => Some("uncursed "), BUC::Blessed => Some("blessed "), }; if prefix.is_some() { @@ -691,6 +1100,12 @@ pub fn obfuscate_name_ecs(ecs: &World, item: Entity) -> (String, String) { } } } + if let Some(worn) = ecs.read_storage::().get(item) { + if worn.owner == *ecs.fetch::() { + singular.insert_str(singular.len(), " (worn)"); + plural.insert_str(plural.len(), " (worn)"); + } + } return (singular, plural); } @@ -831,13 +1246,13 @@ pub fn show_help(ctx: &mut BTerm) -> YesNoResult { } } -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] struct DisplayName { singular: String, plural: String, } -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct UniqueInventoryItem { display_name: DisplayName, rgb: (u8, u8, u8), @@ -847,223 +1262,260 @@ pub struct UniqueInventoryItem { name: String, } -pub type PlayerInventory = BTreeMap; - -pub fn get_player_inventory(ecs: &World) -> PlayerInventory { - let player_entity = ecs.fetch::(); - let names = ecs.read_storage::(); - let backpack = ecs.read_storage::(); - let entities = ecs.entities(); - let renderables = ecs.read_storage::(); - - let mut player_inventory: BTreeMap = BTreeMap::new(); - for (entity, _pack, name, renderable) in (&entities, &backpack, &names, &renderables) - .join() - .filter(|item| item.1.owner == *player_entity) { - // RGB can't be used as a key. This is converting the RGB (tuple of f32) into a tuple of u8s. - let item_colour = item_colour_ecs(ecs, entity); - let renderables = ( - (renderable.fg.r * 255.0) as u8, - (renderable.fg.g * 255.0) as u8, - (renderable.fg.b * 255.0) as u8, - ); - let (singular, plural) = obfuscate_name_ecs(ecs, entity); - let beatitude_status = if let Some(beatitude) = ecs.read_storage::().get(entity) { - match beatitude.buc { - BUC::Blessed => 1, - BUC::Uncursed => 2, - BUC::Cursed => 3, - } - } else { - 0 - }; - let unique_item = UniqueInventoryItem { - display_name: DisplayName { singular: singular.clone(), plural: plural }, - rgb: item_colour, - renderables: renderables, - glyph: renderable.glyph, - beatitude_status: beatitude_status, - name: name.name.clone(), - }; - player_inventory - .entry(unique_item) - .and_modify(|(_e, count)| { - *count += 1; - }) - .or_insert((entity, 1)); - } - - return player_inventory; -} - -pub fn show_inventory(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option) { - let player_inventory = get_player_inventory(&gs.ecs); - let count = player_inventory.len(); - - let (x_offset, y_offset) = (1, 10); - - let on_overmap = gs.ecs.fetch::().overmap; - let message = if !on_overmap { - "Interact with what item? [aA-zZ][Esc.]" - } else { - "You can't use items on the overmap [Esc.]" - }; - - ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(WHITE), RGB::named(BLACK), message); - - let x = 1 + x_offset; - let y = 3 + y_offset; - let width = get_max_inventory_width(&player_inventory); - ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK)); - print_options(&player_inventory, x + 1, y + 1, ctx); - - match ctx.key { - None => (ItemMenuResult::NoResponse, None), - Some(key) => - match key { - VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None), - _ => { - let selection = letter_to_option::letter_to_option(key, ctx.shift); - if selection > -1 && selection < (count as i32) { - if on_overmap { - gamelog::Logger - ::new() - .append("You can't use items on the overmap.") - .log(); - } else { - return ( - ItemMenuResult::Selected, - Some( - player_inventory - .iter() - .nth(selection as usize) - .unwrap().1.0 - ), - ); - } - } - (ItemMenuResult::NoResponse, None) - } - } - } -} - -pub fn drop_item_menu(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option) { - let player_inventory = get_player_inventory(&gs.ecs); - let count = player_inventory.len(); - - let (x_offset, y_offset) = (1, 10); - - let on_overmap = gs.ecs.fetch::().overmap; - let message = if !on_overmap { - "Drop what? [aA-zZ][Esc.]" - } else { - "You can't drop items on the overmap [Esc.]" - }; - - ctx.print_color(1 + x_offset, 1 + y_offset, RGB::named(WHITE), RGB::named(BLACK), message); - - let x = 1 + x_offset; - let y = 3 + y_offset; - let width = get_max_inventory_width(&player_inventory); - ctx.draw_box(x, y, width + 2, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK)); - print_options(&player_inventory, x + 1, y + 1, ctx); - - match ctx.key { - None => (ItemMenuResult::NoResponse, None), - Some(key) => - match key { - VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None), - _ => { - let selection = letter_to_option(key); - if selection > -1 && selection < (count as i32) { - if on_overmap { - gamelog::Logger - ::new() - .append("You can't drop items on the overmap.") - .log(); - } else { - return ( - ItemMenuResult::Selected, - Some( - player_inventory - .iter() - .nth(selection as usize) - .unwrap().1.0 - ), - ); - } - } - (ItemMenuResult::NoResponse, None) - } - } - } -} - -pub fn remove_item_menu(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option) { - let player_entity = gs.ecs.fetch::(); - let backpack = gs.ecs.read_storage::(); - let entities = gs.ecs.entities(); - let inventory = (&backpack).join().filter(|item| item.owner == *player_entity); - let count = inventory.count(); - - let (x_offset, y_offset) = (1, 10); - - ctx.print_color( - 1 + x_offset, - 1 + y_offset, - RGB::named(WHITE), - RGB::named(BLACK), - "Unequip what? [aA-zZ][Esc.]" +pub fn unique( + entity: Entity, + names: &ReadStorage, + obfuscated_names: &ReadStorage, + renderables: &ReadStorage, + beatitudes: &ReadStorage, + magic_items: &ReadStorage, + charges: Option<&ReadStorage>, + dm: &MasterDungeonMap +) -> UniqueInventoryItem { + let item_colour = item_colour(entity, beatitudes); + let (singular, plural) = obfuscate_name( + entity, + names, + magic_items, + obfuscated_names, + beatitudes, + dm, + charges ); - - let mut equippable: Vec<(Entity, String)> = Vec::new(); - let mut width = 2; - for (entity, _pack) in (&entities, &backpack) - .join() - .filter(|item| item.1.owner == *player_entity) { - let this_name = &obfuscate_name_ecs(&gs.ecs, entity).0; - let this_width = 5 + this_name.len(); - width = if width > this_width { width } else { this_width }; - equippable.push((entity, this_name.to_string())); + let (renderables, glyph) = if let Some(renderable) = renderables.get(entity) { + ( + ( + (renderable.fg.r * 255.0) as u8, + (renderable.fg.g * 255.0) as u8, + (renderable.fg.b * 255.0) as u8, + ), + renderable.glyph, + ) + } else { + unreachable!("Item has no renderable component.") + }; + let name = if let Some(name) = names.get(entity) { + name + } else { + unreachable!("Item has no name component.") + }; + let beatitude_status = if let Some(beatitude) = beatitudes.get(entity) { + match beatitude.buc { + BUC::Blessed => 1, + BUC::Uncursed => 2, + BUC::Cursed => 3, + } + } else { + 0 + }; + UniqueInventoryItem { + display_name: DisplayName { singular: singular.clone(), plural }, + rgb: item_colour, + renderables, + glyph, + beatitude_status, + name: name.name.clone(), } +} - let x = 1 + x_offset; - let mut y = 3 + y_offset; +pub fn unique_ecs(ecs: &World, entity: Entity) -> UniqueInventoryItem { + return unique( + entity, + &ecs.read_storage::(), + &ecs.read_storage::(), + &ecs.read_storage::(), + &ecs.read_storage::(), + &ecs.read_storage::(), + Some(&ecs.read_storage::()), + &ecs.fetch::() + ); +} - ctx.draw_box(x, y, width, (count + 1) as i32, RGB::named(WHITE), RGB::named(BLACK)); - y += 1; +pub struct InventorySlot { + pub item: Entity, + pub count: i32, + pub idx: usize, +} - let mut j = 0; - let renderables = gs.ecs.read_storage::(); - for (e, name) in &equippable { - let (mut fg, glyph) = if let Some(renderable) = renderables.get(*e) { - (renderable.fg, renderable.glyph) - } else { - (RGB::named(WHITE), to_cp437('-')) - }; - ctx.set(x + 1, y, RGB::named(YELLOW), RGB::named(BLACK), 97 + (j as FontCharType)); - ctx.set(x + 3, y, fg, RGB::named(BLACK), glyph); - fg = RGB::named(item_colour_ecs(&gs.ecs, *e)); - ctx.print_color(x + 5, y, fg, RGB::named(BLACK), name); - y += 1; - j += 1; - } +pub type PlayerInventory = HashMap; - match ctx.key { - None => (ItemMenuResult::NoResponse, None), - Some(key) => - match key { - VirtualKeyCode::Escape => (ItemMenuResult::Cancel, None), - _ => { - let selection = letter_to_option(key); - if selection > -1 && selection < (count as i32) { - return (ItemMenuResult::Selected, Some(equippable[selection as usize].0)); - } - (ItemMenuResult::NoResponse, None) +pub enum Filter { + All(Option), + Backpack(Option), + Equipped, +} + +macro_rules! includeitem { + ($inv:expr, $ecs:expr, $e:expr, $k:expr) => { + $inv.entry(unique_ecs($ecs, $e)) + .and_modify(|slot| { + slot.count += 1; + }) + .or_insert(InventorySlot { + item: $e, + count: 1, + idx: $k.idx, + }); + }; +} + +pub fn items(ecs: &World, filter: Filter) -> HashMap { + let entities = ecs.entities(); + let keys = ecs.read_storage::(); + + let mut inv: HashMap = HashMap::new(); + + match filter { + Filter::All(itemtype) => { + if itemtype.is_some() { + let items = ecs.read_storage::(); + for (e, k, _i) in (&entities, &keys, &items) + .join() + .filter(|e| e.2.category == itemtype.unwrap()) { + includeitem!(inv, ecs, e, k); + } + } else { + for (e, k) in (&entities, &keys).join() { + includeitem!(inv, ecs, e, k); } } + } + Filter::Backpack(itemtype) => { + let backpack = ecs.read_storage::(); + if itemtype.is_some() { + let items = ecs.read_storage::(); + for (e, k, _i, _b) in (&entities, &keys, &items, &backpack) + .join() + .filter(|e| e.2.category == itemtype.unwrap()) { + includeitem!(inv, ecs, e, k); + } + } else { + for (e, k, _b) in (&entities, &keys, &backpack).join() { + includeitem!(inv, ecs, e, k); + } + } + } + Filter::Equipped => { + let equipped = ecs.read_storage::(); + for (e, k, _e) in (&entities, &keys, &equipped).join() { + includeitem!(inv, ecs, e, k); + } + } } + + inv +} + +pub fn show_inventory(gs: &mut State, ctx: &mut App) -> (ItemMenuResult, Option) { + let on_overmap = gs.ecs.fetch::().overmap; + + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return (ItemMenuResult::Cancel, None); + } + _ => { + let shift = key.shift(); + let selection = if + let Some(key) = letter_to_option::letter_to_option(*keycode, shift) + { + key + } else { + continue; + }; + if check_key(selection) { + if on_overmap { + gamelog::Logger::new().append("You can't use items on the overmap.").log(); + } else { + // Get the first entity with a Key {} component that has an idx matching "selection". + let entities = gs.ecs.entities(); + let keyed_items = gs.ecs.read_storage::(); + let backpack = gs.ecs.read_storage::(); + for (e, key, _b) in (&entities, &keyed_items, &backpack).join() { + if key.idx == selection { + return (ItemMenuResult::Selected, Some(e)); + } + } + // TODO: Probably some gamelog about not having the selected item? + } + } + } + } + } + return (ItemMenuResult::NoResponse, None); +} + +pub fn drop_item_menu(gs: &mut State, ctx: &mut App) -> (ItemMenuResult, Option) { + let on_overmap = gs.ecs.fetch::().overmap; + + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return (ItemMenuResult::Cancel, None); + } + _ => { + let shift = key.shift(); + let selection = if + let Some(key) = letter_to_option::letter_to_option(*keycode, shift) + { + key + } else { + continue; + }; + if check_key(selection) { + if on_overmap { + gamelog::Logger::new().append("You can't drop items on the overmap.").log(); + } else { + // Get the first entity with a Key {} component that has an idx matching "selection". + let entities = gs.ecs.entities(); + let keyed_items = gs.ecs.read_storage::(); + let backpack = gs.ecs.read_storage::(); + for (e, key, _b) in (&entities, &keyed_items, &backpack).join() { + if key.idx == selection { + return (ItemMenuResult::Selected, Some(e)); + } + } + } + } + } + } + } + (ItemMenuResult::NoResponse, None) +} + +pub fn remove_item_menu(gs: &mut State, ctx: &mut App) -> (ItemMenuResult, Option) { + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return (ItemMenuResult::Cancel, None); + } + _ => { + let shift = key.shift(); + let selection = if + let Some(key) = letter_to_option::letter_to_option(*keycode, shift) + { + key + } else { + continue; + }; + if check_key(selection) { + // Get the first entity with a Key {} component that has an idx matching "selection". + let entities = gs.ecs.entities(); + let keyed_items = gs.ecs.read_storage::(); + let equipped = gs.ecs.read_storage::(); + for (e, key, _e) in (&entities, &keyed_items, &equipped).join() { + if key.idx == selection { + return (ItemMenuResult::Selected, Some(e)); + } + } + } + } + } + } + (ItemMenuResult::NoResponse, None) } #[derive(PartialEq, Copy, Clone)] @@ -1076,26 +1528,27 @@ pub enum TargetResult { Selected, } -pub fn ranged_target( - gs: &mut State, - ctx: &mut BTerm, +pub fn draw_targeting( + ecs: &World, + draw: &mut Draw, + atlas: &HashMap, x: i32, y: i32, range: i32, aoe: i32 -) -> (TargetResult, Option) { - let (min_x, max_x, min_y, max_y, x_offset, y_offset) = camera::get_screen_bounds(&gs.ecs, ctx); - let player_entity = gs.ecs.fetch::(); - let player_pos = gs.ecs.fetch::(); - let viewsheds = gs.ecs.read_storage::(); +) { + let bounds = camera::get_screen_bounds(ecs, false); + let player_entity = ecs.fetch::(); + let player_pos = ecs.fetch::(); + let viewsheds = ecs.read_storage::(); - ctx.print_color( - 1 + x_offset, - 1 + y_offset, - RGB::named(WHITE), - RGB::named(BLACK), - "Targeting which tile? [mouse input]" - ); + let mut needs_draw: HashMap = HashMap::new(); + + const AVAILABLE: u32 = 0b00000001; + const AOE: u32 = 0b00000010; + const LINE_TO_CURSOR: u32 = 0b00000100; + const CURSOR: u32 = 0b00001000; + const CURSOR_UNAVAILABLE: u32 = 0b00010000; // Highlight available cells let mut available_cells = Vec::new(); @@ -1105,44 +1558,37 @@ pub fn ranged_target( for idx in visible.visible_tiles.iter() { let distance = DistanceAlg::Pythagoras.distance2d(*player_pos, *idx); if distance <= (range as f32) { - let screen_x = idx.x - min_x; - let screen_y = idx.y - min_y; + let screen_x = idx.x - bounds.min_x; + let screen_y = idx.y - bounds.min_y; if screen_x > 1 && - screen_x < max_x - min_x - 1 && + screen_x < bounds.max_x - bounds.min_x - 1 && screen_y > 1 && - screen_y < max_y - min_y - 1 + screen_y < bounds.max_y - bounds.min_y - 1 { - ctx.set_bg(screen_x + x_offset, screen_y + y_offset, TARGETING_VALID_COL); + needs_draw.insert( + Point::new(screen_x + bounds.x_offset, screen_y + bounds.y_offset), + AVAILABLE + ); available_cells.push(idx); } } } - } else { - return (TargetResult::Cancel, None); } // Draw mouse cursor let mouse_pos = (x, y); - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = camera::get_screen_bounds( - &gs.ecs, - ctx - ); - let (screen_x, screen_y) = (69, 41); - let x = x.clamp(x_offset, x_offset - 1 + (screen_x as i32)); - let y = y.clamp(y_offset, y_offset - 1 + (screen_y as i32)); - + let bounds = camera::get_screen_bounds(ecs, false); let mut mouse_pos_adjusted = mouse_pos; - mouse_pos_adjusted.0 += min_x - x_offset; - mouse_pos_adjusted.1 += min_y - y_offset; - let map = gs.ecs.fetch::(); + mouse_pos_adjusted.0 += bounds.min_x - bounds.x_offset; + mouse_pos_adjusted.1 += bounds.min_y - bounds.y_offset; + let map = ecs.fetch::(); let mut valid_target = false; for idx in available_cells.iter() { if idx.x == mouse_pos_adjusted.0 && idx.y == mouse_pos_adjusted.1 { valid_target = true; } } - let mut result = (TargetResult::NoResponse { x, y }, None); if valid_target { let path = line2d( LineAlg::Bresenham, @@ -1153,13 +1599,14 @@ pub fn ranged_target( if i == 0 || i == path.len() - 1 { continue; } - ctx.set( - point.x + x_offset - min_x, - point.y + y_offset - min_y, - RGB::named(TARGETING_LINE_COL), - RGB::named(TARGETING_VALID_COL), - to_cp437('~') - ); + *needs_draw + .entry( + Point::new( + point.x + bounds.x_offset - bounds.min_x, + point.y + bounds.y_offset - bounds.min_y + ) + ) + .or_insert(0) |= LINE_TO_CURSOR; } if aoe > 0 { // We adjust for camera position when getting FOV, but then we need to adjust back @@ -1173,54 +1620,133 @@ pub fn ranged_target( |p| p.x > 0 && p.x < map.width - 1 && p.y > 0 && p.y < map.height - 1 ); for tile in blast_tiles.iter() { - let bg = if available_cells.contains(&tile) { - let col1 = TARGETING_AOE_COL; - let col2 = TARGETING_VALID_COL; - ((col1.0 + col2.0) / 2, (col1.1 + col2.1) / 2, (col1.2 + col2.2) / 2) - } else { - let col1 = TARGETING_AOE_COL; - let col2 = BLACK; - ((col1.0 + col2.0) / 2, (col1.1 + col2.1) / 2, (col1.2 + col2.2) / 2) - }; - ctx.set_bg(tile.x - min_x + x_offset, tile.y - min_y + y_offset, bg); + *needs_draw + .entry( + Point::new( + tile.x - bounds.min_x + bounds.x_offset, + tile.y - bounds.min_y + bounds.y_offset + ) + ) + .or_insert(0) |= AOE; } } - - ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(TARGETING_CURSOR_COL)); - result = match ctx.key { - None => result, - Some(key) => - match key { - VirtualKeyCode::Return => { - return ( - TargetResult::Selected, - Some(Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)), - ); - } - _ => result, - } - }; + *needs_draw.entry(Point::new(mouse_pos.0, mouse_pos.1)).or_insert(0) |= CURSOR; } else { - ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(RED)); + *needs_draw.entry(Point::new(mouse_pos.0, mouse_pos.1)).or_insert(0) |= CURSOR_UNAVAILABLE; } - result = match ctx.key { - None => result, - Some(key) => - match key { - VirtualKeyCode::Escape => (TargetResult::Cancel, None), - VirtualKeyCode::Numpad9 => (TargetResult::NoResponse { x: x + 1, y: y - 1 }, None), - VirtualKeyCode::Numpad7 => (TargetResult::NoResponse { x: x - 1, y: y - 1 }, None), - VirtualKeyCode::Numpad6 => (TargetResult::NoResponse { x: x + 1, y }, None), - VirtualKeyCode::Numpad4 => (TargetResult::NoResponse { x: x - 1, y }, None), - VirtualKeyCode::Numpad8 => (TargetResult::NoResponse { x, y: y - 1 }, None), - VirtualKeyCode::Numpad3 => (TargetResult::NoResponse { x: x + 1, y: y + 1 }, None), - VirtualKeyCode::Numpad2 => (TargetResult::NoResponse { x, y: y + 1 }, None), - VirtualKeyCode::Numpad1 => (TargetResult::NoResponse { x: x - 1, y: y + 1 }, None), - _ => result, + for (k, v) in needs_draw { + let pos = ((k.x as f32) * TILESIZE.x, (k.y as f32) * TILESIZE.x); + let tex = atlas.get("217").unwrap(); + if (v & CURSOR_UNAVAILABLE) != 0 { + draw.image(tex).position(pos.0, pos.1).alpha(0.5).color(Color::RED); + continue; + } + if (v & AVAILABLE) != 0 { + draw.image(tex).position(pos.0, pos.1).alpha(0.2).color(Color::WHITE); + } + if (v & CURSOR) != 0 { + draw.image(tex).position(pos.0, pos.1).alpha(0.2).color(Color::WHITE); + } + if (v & AOE) != 0 { + draw.image(tex).position(pos.0, pos.1).alpha(0.2).color(Color::YELLOW); + } + if (v & LINE_TO_CURSOR) != 0 { + draw.image(tex).position(pos.0, pos.1).alpha(0.2).color(Color::WHITE); + } + } +} + +pub fn ranged_target( + gs: &mut State, + ctx: &mut App, + x: i32, + y: i32, + range: i32, + _aoe: i32 +) -> (TargetResult, Option) { + let bounds = camera::get_screen_bounds(&gs.ecs, false); + let x = x.clamp(bounds.x_offset, bounds.x_offset - 1 + VIEWPORT_W); + let y = y.clamp(bounds.y_offset, bounds.y_offset - 1 + VIEWPORT_H); + + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape => { + return (TargetResult::Cancel, None); } - }; - return result; + KeyCode::Numpad1 => { + return (TargetResult::NoResponse { x: x - 1, y: y + 1 }, None); + } + KeyCode::Numpad2 => { + return (TargetResult::NoResponse { x, y: y + 1 }, None); + } + KeyCode::Numpad3 => { + return (TargetResult::NoResponse { x: x + 1, y: y + 1 }, None); + } + KeyCode::Numpad4 => { + return (TargetResult::NoResponse { x: x - 1, y }, None); + } + KeyCode::Numpad6 => { + return (TargetResult::NoResponse { x: x + 1, y }, None); + } + KeyCode::Numpad7 => { + return (TargetResult::NoResponse { x: x - 1, y: y - 1 }, None); + } + KeyCode::Numpad8 => { + return (TargetResult::NoResponse { x, y: y - 1 }, None); + } + KeyCode::Numpad9 => { + return (TargetResult::NoResponse { x: x + 1, y: y - 1 }, None); + } + KeyCode::Return => { + let bounds = camera::get_screen_bounds(&gs.ecs, false); + let player_entity = gs.ecs.fetch::(); + let player_pos = gs.ecs.fetch::(); + let viewsheds = gs.ecs.read_storage::(); + + let mut available_cells = Vec::new(); + let visible = viewsheds.get(*player_entity); + if let Some(visible) = visible { + // We have a viewshed + for idx in visible.visible_tiles.iter() { + let distance = DistanceAlg::Pythagoras.distance2d(*player_pos, *idx); + if distance <= (range as f32) { + let screen_x = idx.x - bounds.min_x; + let screen_y = idx.y - bounds.min_y; + if + screen_x > 1 && + screen_x < bounds.max_x - bounds.min_x - 1 && + screen_y > 1 && + screen_y < bounds.max_y - bounds.min_y - 1 + { + available_cells.push(idx); + } + } + } + } + let mouse_pos = (x, y); + let bounds = camera::get_screen_bounds(&gs.ecs, false); + let mut mouse_pos_adjusted = mouse_pos; + mouse_pos_adjusted.0 += bounds.min_x - bounds.x_offset; + mouse_pos_adjusted.1 += bounds.min_y - bounds.y_offset; + let mut valid_target = false; + for idx in available_cells.iter() { + if idx.x == mouse_pos_adjusted.0 && idx.y == mouse_pos_adjusted.1 { + valid_target = true; + } + } + if valid_target { + return ( + TargetResult::Selected, + Some(Point::new(mouse_pos_adjusted.0, mouse_pos_adjusted.1)), + ); + } + } + _ => {} + } + } + (TargetResult::NoResponse { x, y }, None) } #[derive(PartialEq, Copy, Clone)] @@ -1240,113 +1766,69 @@ pub enum MainMenuResult { }, } -pub fn main_menu(gs: &mut State, ctx: &mut BTerm) -> MainMenuResult { +pub fn main_menu(gs: &mut State, ctx: &mut App) -> MainMenuResult { let save_exists = super::saveload_system::does_save_exist(); let runstate = gs.ecs.fetch::(); - let assets = gs.ecs.fetch::(); + let selection = match *runstate { + RunState::MainMenu { menu_selection: sel } => sel, + _ => MainMenuSelection::NewGame, + }; - ctx.render_xp_sprite(&assets.menu, 0, 0); - - let x = 46; - let mut y = 26; - let mut height = 8; - if !save_exists { - height -= 1; - } - - ctx.draw_box_double(x, y - 4, 13, height, RGB::named(WHITE), RGB::named(BLACK)); - ctx.print_color(x + 3, y - 2, RGB::named(YELLOW), RGB::named(BLACK), "RUST-RL!"); - - if let RunState::MainMenu { menu_selection: selection } = *runstate { - if save_exists { - if selection == MainMenuSelection::LoadGame { - ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "["); - ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "continue"); - ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]"); - } else { - ctx.print_color(x + 3, y, RGB::named(WHITE), RGB::named(BLACK), "continue"); + let key = &ctx.keyboard; + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Escape | KeyCode::C => { + return MainMenuResult::NoSelection { selected: MainMenuSelection::Quit }; } - y += 1; - } - if selection == MainMenuSelection::NewGame { - ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "["); - ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "new game"); - ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]"); - } else { - ctx.print_color(x + 3, y, RGB::named(WHITE), RGB::named(BLACK), "new game"); - } - y += 1; - if selection == MainMenuSelection::Quit { - ctx.print_color(x + 2, y, RGB::named(YELLOW), RGB::named(BLACK), "["); - ctx.print_color(x + 3, y, RGB::named(GREEN), RGB::named(BLACK), "goodbye!"); - ctx.print_color(x + 11, y, RGB::named(YELLOW), RGB::named(BLACK), "]"); - } else { - ctx.print_color(x + 5, y, RGB::named(WHITE), RGB::named(BLACK), "quit"); - } - - match ctx.key { - None => { - return MainMenuResult::NoSelection { selected: selection }; + KeyCode::N => { + return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame }; } - Some(key) => - match key { - VirtualKeyCode::Escape | VirtualKeyCode::C => { - return MainMenuResult::NoSelection { selected: MainMenuSelection::Quit }; + KeyCode::L => { + return MainMenuResult::NoSelection { selected: MainMenuSelection::LoadGame }; + } + KeyCode::Down | KeyCode::Numpad2 | KeyCode::J => { + let mut new_selection; + match selection { + MainMenuSelection::NewGame => { + new_selection = MainMenuSelection::LoadGame; } - VirtualKeyCode::N => { - return MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame }; + MainMenuSelection::LoadGame => { + new_selection = MainMenuSelection::Quit; } - VirtualKeyCode::L => { - return MainMenuResult::NoSelection { - selected: MainMenuSelection::LoadGame, - }; - } - VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => { - let mut new_selection; - match selection { - MainMenuSelection::NewGame => { - new_selection = MainMenuSelection::LoadGame; - } - MainMenuSelection::LoadGame => { - new_selection = MainMenuSelection::Quit; - } - MainMenuSelection::Quit => { - new_selection = MainMenuSelection::NewGame; - } - } - if new_selection == MainMenuSelection::LoadGame && !save_exists { - new_selection = MainMenuSelection::NewGame; - } - return MainMenuResult::NoSelection { selected: new_selection }; - } - VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => { - let mut new_selection; - match selection { - MainMenuSelection::NewGame => { - new_selection = MainMenuSelection::Quit; - } - MainMenuSelection::LoadGame => { - new_selection = MainMenuSelection::NewGame; - } - MainMenuSelection::Quit => { - new_selection = MainMenuSelection::LoadGame; - } - } - if new_selection == MainMenuSelection::LoadGame && !save_exists { - new_selection = MainMenuSelection::Quit; - } - return MainMenuResult::NoSelection { selected: new_selection }; - } - VirtualKeyCode::Return | VirtualKeyCode::NumpadEnter => { - return MainMenuResult::Selected { selected: selection }; - } - _ => { - return MainMenuResult::NoSelection { selected: selection }; + MainMenuSelection::Quit => { + new_selection = MainMenuSelection::NewGame; } } + if new_selection == MainMenuSelection::LoadGame && !save_exists { + new_selection = MainMenuSelection::NewGame; + } + return MainMenuResult::NoSelection { selected: new_selection }; + } + KeyCode::Up | KeyCode::Numpad8 | KeyCode::K => { + let mut new_selection; + match selection { + MainMenuSelection::NewGame => { + new_selection = MainMenuSelection::Quit; + } + MainMenuSelection::LoadGame => { + new_selection = MainMenuSelection::NewGame; + } + MainMenuSelection::Quit => { + new_selection = MainMenuSelection::LoadGame; + } + } + if new_selection == MainMenuSelection::LoadGame && !save_exists { + new_selection = MainMenuSelection::Quit; + } + return MainMenuResult::NoSelection { selected: new_selection }; + } + KeyCode::Return | KeyCode::NumpadEnter => { + return MainMenuResult::Selected { selected: selection }; + } + _ => {} } } - MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame } + return MainMenuResult::NoSelection { selected: selection }; } #[derive(PartialEq, Copy, Clone)] @@ -1356,97 +1838,47 @@ pub enum YesNoResult { No, } -pub fn game_over(ctx: &mut BTerm) -> YesNoResult { - let mut x = 3; - let mut y = 12; - let width = 45; - let height = 20; - ctx.draw_box(x, y, width, height, RGB::named(WHITE), RGB::named(BLACK)); - ctx.print_color(x + 3, y, RGB::named(YELLOW), RGB::named(BLACK), "You died!"); - ctx.print_color( - x + 3, - y + height, - RGB::named(YELLOW), - RGB::named(BLACK), - " Write a morgue file? [y/n] " - ); - x += 2; - y += 2; - ctx.print_color( - x, - y, - RGB::named(GREEN), - RGB::named(BLACK), - format!("You survived for {} turns.", crate::gamelog::get_event_count(EVENT::COUNT_TURN)) - ); - y += 2; - ctx.print_color(x, y, RGB::named(GREEN), RGB::named(BLACK), format!("And in the process, you")); - y += 1; - if crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) > 0 { - ctx.print_color( - x + 1, - y, - RGB::named(WHITE), - RGB::named(BLACK), - format!( - "- changed floor {} times", - crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) - ) - ); - y += 1; - } - if crate::gamelog::get_event_count(EVENT::COUNT_KICK) > 0 { - ctx.print_color( - x + 1, - y, - RGB::named(WHITE), - RGB::named(BLACK), - format!( - "- kicked {} time(s), breaking {} object(s)", - crate::gamelog::get_event_count(EVENT::COUNT_KICK), - crate::gamelog::get_event_count(EVENT::COUNT_BROKE_DOOR) - ) - ); - y += 1; - } - if crate::gamelog::get_event_count(EVENT::COUNT_KILLED) > 0 { - ctx.print_color( - x + 1, - y, - RGB::named(WHITE), - RGB::named(BLACK), - format!( - "- slew {} other creature(s)", - crate::gamelog::get_event_count(EVENT::COUNT_KILLED) - ) - ); - y += 1; - } - if crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP) > 0 { - ctx.print_color( - x + 1, - y, - RGB::named(WHITE), - RGB::named(BLACK), - format!( - "- forgot the controls {} time(s)", - crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP) - ) - ); - } - - match ctx.key { - None => YesNoResult::NoSelection, - Some(key) => - match key { - VirtualKeyCode::N => YesNoResult::No, - VirtualKeyCode::Y => YesNoResult::Yes, - _ => YesNoResult::NoSelection, - } - } +/// Prompts for a YesNoResult with default keys of 'y' and 'n'. +pub fn yes_no(ctx: &mut App) -> YesNoResult { + prompt(ctx, None, None, false, false) } -pub fn with_article(name: String) -> String { +pub fn help_prompt(ctx: &mut App) -> YesNoResult { + prompt(ctx, Some((KeyCode::Slash, true)), Some((KeyCode::Escape, false)), false, false) +} + +/// Prompts for a YesNoResult, where 'yes' and 'no' keys can either be specified, +/// or defaulted to 'y' and 'n'. +pub fn prompt( + ctx: &mut App, + yes: Option<(KeyCode, bool)>, + no: Option<(KeyCode, bool)>, + allow_esc: bool, + allow_enter: bool +) -> YesNoResult { + let (y, y_shift) = yes.unwrap_or((KeyCode::Y, false)); + let (n, n_shift) = no.unwrap_or((KeyCode::N, false)); + for keycode in &ctx.keyboard.pressed { + match (keycode, ctx.keyboard.shift()) { + (k, s) if *k == y && s == y_shift => { + return YesNoResult::Yes; + } + (k, s) if *k == n && s == n_shift => { + return YesNoResult::No; + } + (k, _s) if *k == KeyCode::Escape && allow_esc => { + return YesNoResult::No; + } + (k, _s) if *k == KeyCode::Return && allow_enter => { + return YesNoResult::Yes; + } + _ => {} + } + } + YesNoResult::NoSelection +} + +pub fn with_article(name: &String) -> String { // If first letter is a capital if name.chars().nth(0).unwrap().is_uppercase() { return format!("{}", name); @@ -1458,3 +1890,32 @@ pub fn with_article(name: String) -> String { } format!("a {}", name) } + +/// Returns the map index of a tile in the viewport. +pub fn viewport_to_idx(ecs: &World, x: i32, y: i32) -> usize { + let bounds = crate::camera::get_screen_bounds(ecs, false); + let x = x + bounds.min_x; + let y = y + bounds.min_y; + return ecs.fetch::().xy_idx(x, y); +} + +/// Denotes a pixel location on the screen. +pub struct Px { + x: f32, + y: f32, +} + +impl Px { + pub fn new(x: f32, y: f32) -> Self { + Self { x, y } + } +} + +/// Returns the pixel location of a tile in the viewport. +pub fn viewport_to_px(x: i32, y: i32) -> Px { + let offsets = crate::camera::get_offset(); + Px::new( + (x as f32) * TILESIZE.sprite_x + (offsets.x as f32) * TILESIZE.x, + (y as f32) * TILESIZE.sprite_y + (offsets.y as f32) * TILESIZE.y + ) +} diff --git a/src/gui/remove_curse_menu.rs b/src/gui/remove_curse_menu.rs index f8d1f14..18861bd 100644 --- a/src/gui/remove_curse_menu.rs +++ b/src/gui/remove_curse_menu.rs @@ -3,9 +3,11 @@ use super::{ item_colour_ecs, obfuscate_name_ecs, print_options, + unique_ecs, renderable_colour, ItemMenuResult, UniqueInventoryItem, + InventorySlot, }; use crate::{ gamelog, @@ -18,10 +20,11 @@ use crate::{ Renderable, states::state::*, BUC, + Key, }; use bracket_lib::prelude::*; use specs::prelude::*; -use std::collections::BTreeMap; +use std::collections::HashMap; /// Handles the Remove Curse menu. pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option) { @@ -33,11 +36,12 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option< let beatitudes = gs.ecs.read_storage::(); let names = gs.ecs.read_storage::(); let renderables = gs.ecs.read_storage::(); + let keys = gs.ecs.read_storage::(); let build_cursed_iterator = || { - (&entities, &items, &beatitudes, &renderables, &names) + (&entities, &items, &beatitudes, &renderables, &names, &keys) .join() - .filter(|(item_entity, _i, b, _r, _n)| { + .filter(|(item_entity, _i, b, _r, _n, _k)| { // Set all items to FALSE initially. let mut keep = false; // If found in the player's backpack, set to TRUE @@ -86,8 +90,8 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option< .log(); return (ItemMenuResult::Selected, Some(item)); } - let mut player_inventory: super::PlayerInventory = BTreeMap::new(); - for (entity, _i, _b, renderable, name) in build_cursed_iterator() { + let mut player_inventory: super::PlayerInventory = HashMap::new(); + for (entity, _i, _b, renderable, name, key) in build_cursed_iterator() { let (singular, plural) = obfuscate_name_ecs(&gs.ecs, entity); let beatitude_status = if let Some(beatitude) = gs.ecs.read_storage::().get(entity) @@ -100,37 +104,34 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option< } 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(), - }; + let unique_item = unique_ecs(&gs.ecs, entity); player_inventory .entry(unique_item) - .and_modify(|(_e, count)| { - *count += 1; + .and_modify(|slot| { + slot.count += 1; }) - .or_insert((entity, 1)); + .or_insert(InventorySlot { + item: entity, + count: 1, + idx: key.idx, + }); } // Get display args let width = get_max_inventory_width(&player_inventory); - let (_, _, _, _, x_offset, y_offset) = crate::camera::get_screen_bounds(&gs.ecs, ctx); - let (x, y) = (x_offset + 1, y_offset + 3); + let offsets = crate::camera::get_offset(); + let (x, y) = (offsets.x + 1, offsets.y + 3); // Draw menu ctx.print_color( - 1 + x_offset, - 1 + y_offset, + 1 + offsets.x, + 1 + offsets.y, RGB::named(WHITE), RGB::named(BLACK), "Decurse which item? [aA-zZ][Esc.]" ); ctx.draw_box(x, y, width + 2, count + 1, RGB::named(WHITE), RGB::named(BLACK)); - print_options(&player_inventory, x + 1, y + 1, ctx); + // Input - match ctx.key { + /*match ctx.key { None => (ItemMenuResult::NoResponse, None), Some(key) => match key { @@ -155,5 +156,6 @@ pub fn remove_curse(gs: &mut State, ctx: &mut BTerm) -> (ItemMenuResult, Option< (ItemMenuResult::NoResponse, None) } } - } + }*/ + (ItemMenuResult::NoResponse, None) } diff --git a/src/gui/tooltip.rs b/src/gui/tooltip.rs index 94c3f97..4919a1f 100644 --- a/src/gui/tooltip.rs +++ b/src/gui/tooltip.rs @@ -11,7 +11,8 @@ use super::{ RGB, }; use crate::TileType; -use crate::data::ids::*; +use crate::consts::ids::*; +use crate::consts::prelude::*; use bracket_lib::prelude::*; use specs::prelude::*; @@ -45,6 +46,7 @@ impl Tooltip { return (self.lines.len() as i32) + 2i32; } fn render(&self, ctx: &mut BTerm, x: i32, y: i32) { + ctx.set_active_console(TEXT_LAYER); ctx.draw_box( x, y, @@ -56,12 +58,13 @@ impl Tooltip { 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.set_active_console(TILE_LAYER); } } #[rustfmt::skip] pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx); + let bounds = get_screen_bounds(ecs, false); let map = ecs.fetch::(); let names = ecs.read_storage::(); let positions = ecs.read_storage::(); @@ -74,8 +77,8 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { let mouse_pos = if xy.is_none() { ctx.mouse_pos() } else { xy.unwrap() }; let mut mouse_pos_adjusted = mouse_pos; - mouse_pos_adjusted.0 += min_x - x_offset; - mouse_pos_adjusted.1 += min_y - y_offset; + mouse_pos_adjusted.0 += bounds.min_x - bounds.x_offset; + mouse_pos_adjusted.1 += bounds.min_y - bounds.y_offset; if mouse_pos_adjusted.0 >= map.width || mouse_pos_adjusted.1 >= map.height || mouse_pos_adjusted.1 < 0 // Might need to be 1, and -1 from map height/width. @@ -121,18 +124,18 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { let attr = attributes.get(entity); if let Some(a) = attr { let mut s = "".to_string(); - if a.strength.bonus < -2 { s += "weak "}; - if a.strength.bonus > 2 { s += "strong "}; - if a.dexterity.bonus < -2 { s += "clumsy "}; - if a.dexterity.bonus > 2 { s += "agile "}; - if a.constitution.bonus < -2 { s += "frail "}; - if a.constitution.bonus > 2 { s += "hardy "}; - if a.intelligence.bonus < -2 { s += "dim "}; - if a.intelligence.bonus > 2 { s += "smart "}; - if a.wisdom.bonus < -2 { s += "unwise "}; - if a.wisdom.bonus > 2 { s += "wisened "}; - if a.charisma.bonus < -2 { s += "ugly"}; - if a.charisma.bonus > 2 { s += "attractive"}; + if a.strength.modifier() < -2 { s += "weak "}; + if a.strength.modifier() > 2 { s += "strong "}; + if a.dexterity.modifier() < -2 { s += "clumsy "}; + if a.dexterity.modifier() > 2 { s += "agile "}; + if a.constitution.modifier() < -2 { s += "frail "}; + if a.constitution.modifier() > 2 { s += "hardy "}; + if a.intelligence.modifier() < -2 { s += "dim "}; + if a.intelligence.modifier() > 2 { s += "smart "}; + if a.wisdom.modifier() < -2 { s += "unwise "}; + if a.wisdom.modifier() > 2 { s += "wisened "}; + if a.charisma.modifier() < -2 { s += "ugly"}; + if a.charisma.modifier() > 2 { s += "attractive"}; if !s.is_empty() { if s.ends_with(" ") { s.pop(); @@ -175,13 +178,15 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { if mouse_pos.0 > 35 { // Render to the left arrow = to_cp437('→'); - arrow_x = mouse_pos.0 - 1; + arrow_x = mouse_pos.0 * 2 - 1; } else { // Render to the right 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_active_console(TILE_LAYER); let mut total_height = 0; for t in tooltips.iter() { @@ -195,9 +200,9 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut BTerm, xy: Option<(i32, i32)>) { for t in tooltips.iter() { let x = if mouse_pos.0 > 35 { - mouse_pos.0 - (1 + t.width()) + (mouse_pos.0 * 2) - (1 + t.width()) } else { - mouse_pos.0 + (1 + 1) + (mouse_pos.0 * 2) + 2 + 1 }; t.render(ctx, x, y); y += t.height(); diff --git a/src/inventory/collection_system.rs b/src/inventory/collection_system.rs index 2fb7276..e602454 100644 --- a/src/inventory/collection_system.rs +++ b/src/inventory/collection_system.rs @@ -12,9 +12,12 @@ use crate::{ ObfuscatedName, Position, WantsToPickupItem, + WantsToAssignKey, + Renderable, + Stackable, }; use specs::prelude::*; -use crate::data::messages; +use crate::consts::messages; use bracket_lib::prelude::*; pub struct ItemCollectionSystem {} @@ -30,9 +33,12 @@ impl<'a> System<'a> for ItemCollectionSystem { WriteStorage<'a, EquipmentChanged>, ReadStorage<'a, MagicItem>, ReadStorage<'a, ObfuscatedName>, + ReadStorage<'a, Renderable>, ReadStorage<'a, Beatitude>, ReadExpect<'a, MasterDungeonMap>, ReadStorage<'a, Charges>, + ReadStorage<'a, WantsToAssignKey>, + ReadStorage<'a, Stackable>, ); fn run(&mut self, data: Self::SystemData) { @@ -45,20 +51,17 @@ impl<'a> System<'a> for ItemCollectionSystem { mut equipment_changed, magic_items, obfuscated_names, + renderables, beatitudes, dm, wands, + wants_key, + stackable, ) = data; - for pickup in wants_pickup.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."); - + let mut to_remove: Vec = Vec::new(); + // For every item that wants to be picked up, that *isn't* still waiting on a key assignment. + for (pickup, _key) in (&wants_pickup, !&wants_key).join() { if pickup.collected_by == *player_entity { gamelog::Logger ::new() @@ -82,8 +85,17 @@ impl<'a> System<'a> for ItemCollectionSystem { .period() .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(); } } diff --git a/src/inventory/drop_system.rs b/src/inventory/drop_system.rs index 34084b4..ad058a4 100644 --- a/src/inventory/drop_system.rs +++ b/src/inventory/drop_system.rs @@ -12,9 +12,10 @@ use crate::{ ObfuscatedName, Position, WantsToDropItem, + WantsToRemoveKey, }; use specs::prelude::*; -use crate::data::messages; +use crate::consts::messages; use bracket_lib::prelude::*; pub struct ItemDropSystem {} @@ -34,6 +35,7 @@ impl<'a> System<'a> for ItemDropSystem { ReadStorage<'a, ObfuscatedName>, ReadExpect<'a, MasterDungeonMap>, ReadStorage<'a, Charges>, + WriteStorage<'a, WantsToRemoveKey>, ); fn run(&mut self, data: Self::SystemData) { @@ -50,6 +52,7 @@ impl<'a> System<'a> for ItemDropSystem { obfuscated_names, dm, wands, + mut keys, ) = data; for (entity, to_drop) in (&entities, &wants_drop).join() { @@ -68,6 +71,9 @@ impl<'a> System<'a> for ItemDropSystem { backpack.remove(to_drop.item); if entity == *player_entity { + keys.insert(to_drop.item, WantsToRemoveKey {}).expect( + "Unable to insert WantsToRemoveKey" + ); gamelog::Logger ::new() .append(messages::YOU_DROP_ITEM) diff --git a/src/inventory/equip_system.rs b/src/inventory/equip_system.rs index e21db20..1fd9c36 100644 --- a/src/inventory/equip_system.rs +++ b/src/inventory/equip_system.rs @@ -16,7 +16,7 @@ use crate::{ BUC, }; use specs::prelude::*; -use crate::data::messages; +use crate::consts::messages; use bracket_lib::prelude::*; pub struct ItemEquipSystem {} diff --git a/src/inventory/identification_system.rs b/src/inventory/identification_system.rs index ce4ad23..ce629be 100644 --- a/src/inventory/identification_system.rs +++ b/src/inventory/identification_system.rs @@ -9,7 +9,7 @@ use crate::{ Player, }; use specs::prelude::*; -use crate::data::events::*; +use crate::consts::events::*; use crate::gamelog; pub struct ItemIdentificationSystem {} diff --git a/src/inventory/keyhandling.rs b/src/inventory/keyhandling.rs new file mode 100644 index 0000000..2792274 --- /dev/null +++ b/src/inventory/keyhandling.rs @@ -0,0 +1,175 @@ +use crate::{ + gamelog, + gui::unique, + Beatitude, + Charges, + MagicItem, + MasterDungeonMap, + Name, + ObfuscatedName, + Stackable, + Renderable, + WantsToAssignKey, + WantsToRemoveKey, + Key, +}; +use specs::prelude::*; +use crate::consts::messages; +use bracket_lib::prelude::*; +use crate::invkeys::*; + +pub struct KeyHandling {} + +const DEBUG_KEYHANDLING: bool = false; + +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 { + if DEBUG_KEYHANDLING { + console::log(&format!("KEYHANDLING: Item is stackable.")); + } + let maybe_key = item_exists(&unique); + if maybe_key.is_some() { + if DEBUG_KEYHANDLING { + 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."); + if DEBUG_KEYHANDLING { + console::log(&format!("KEYHANDLING: Assigned key idx {} to item.", key)); + } + handled = true; + } + } + if !handled { + if DEBUG_KEYHANDLING { + console::log( + &format!("KEYHANDLING: Item is not stackable, or no existing stack found.") + ); + } + if let Some(idx) = assign_next_available() { + if DEBUG_KEYHANDLING { + 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 { + if DEBUG_KEYHANDLING { + 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) { + if DEBUG_KEYHANDLING { + 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. + if DEBUG_KEYHANDLING { + 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 { + if DEBUG_KEYHANDLING { + 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 { + if DEBUG_KEYHANDLING { + 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. + if DEBUG_KEYHANDLING { + console::log(&format!("KEYHANDLING: Removing key component from item.")); + } + keys.remove(e); + } + + wants_removekey.clear(); + wants_keys.clear(); + } +} diff --git a/src/inventory/mod.rs b/src/inventory/mod.rs index eceaccb..76748e0 100644 --- a/src/inventory/mod.rs +++ b/src/inventory/mod.rs @@ -4,6 +4,7 @@ mod equip_system; mod identification_system; mod remove_system; mod use_system; +mod keyhandling; pub use self::{ collection_system::ItemCollectionSystem, @@ -12,4 +13,5 @@ pub use self::{ identification_system::ItemIdentificationSystem, remove_system::ItemRemoveSystem, use_system::ItemUseSystem, + keyhandling::KeyHandling, }; diff --git a/src/inventory/remove_system.rs b/src/inventory/remove_system.rs index 0a46bce..62561b9 100644 --- a/src/inventory/remove_system.rs +++ b/src/inventory/remove_system.rs @@ -13,7 +13,7 @@ use crate::{ }; use bracket_lib::prelude::*; use specs::prelude::*; -use crate::data::messages; +use crate::consts::messages; pub struct ItemRemoveSystem {} diff --git a/src/invkeys.rs b/src/invkeys.rs new file mode 100644 index 0000000..80a2db2 --- /dev/null +++ b/src/invkeys.rs @@ -0,0 +1,59 @@ +use std::sync::Mutex; +use std::collections::{ HashMap }; +use specs::prelude::*; +use crate::gui::UniqueInventoryItem; + +lazy_static! { + pub static ref INVKEYS: Mutex> = Mutex::new(HashMap::new()); + pub static ref ASSIGNEDKEYS: Mutex> = Mutex::new(vec![false; 52]); +} + +/// For (de)serialization. +pub fn clone_invkeys() -> HashMap { + let invkeys = INVKEYS.lock().unwrap(); + invkeys.clone() +} +pub fn restore_invkeys(invkeys: HashMap) { + 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 { + let invkeys = INVKEYS.lock().unwrap(); + use bracket_lib::prelude::*; + if invkeys.contains_key(item) { + Some(*invkeys.get(item).unwrap()) + } else { + None + } +} + +pub fn assign_next_available() -> Option { + 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); +} diff --git a/src/lib.rs b/src/lib.rs index 6bbdd04..e0bc40f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ pub mod trigger_system; pub mod inventory; pub mod particle_system; pub mod ai; -pub mod data; +pub mod consts; pub mod config; pub mod effects; pub mod gamesystem; @@ -38,9 +38,11 @@ pub mod rex_assets; pub mod spatial; pub mod morgue; pub mod states; +pub mod invkeys; pub use components::*; use particle_system::ParticleBuilder; pub use map::*; pub use states::runstate::RunState; pub use states::state::State; +pub use states::state::Fonts; diff --git a/src/main.rs b/src/main.rs index f430376..495ec24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,31 +1,70 @@ use rust_rl::*; +use notan::prelude::*; +use notan::math::{ vec2, vec3, Mat4, Vec2 }; +use notan::draw::create_textures_from_atlas; +use notan::draw::{ CreateFont, CreateDraw, DrawImages, Draw, DrawTextSection, DrawShapes }; use specs::prelude::*; use specs::saveload::{ SimpleMarker, SimpleMarkerAllocator }; use bracket_lib::prelude::*; +use std::collections::HashMap; +use crate::consts::{ DISPLAYHEIGHT, DISPLAYWIDTH, TILESIZE, FONTSIZE }; +use crate::states::state::Fonts; -const DISPLAYWIDTH: i32 = 105; -const DISPLAYHEIGHT: i32 = 56; +const WORK_SIZE: Vec2 = vec2( + (DISPLAYWIDTH as f32) * TILESIZE.x, + (DISPLAYHEIGHT as f32) * TILESIZE.x +); -fn main() -> BError { - // 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); - - //link_resource!(CURSES14X16, "../resources/curses_14x16.png"); - - let mut context = BTermBuilder::new() - .with_title("rust-rl") - .with_dimensions(DISPLAYWIDTH, DISPLAYHEIGHT) - .with_font("curses14x16.png", 14, 16) - .with_tile_dimensions(14, 16) - .with_simple_console(DISPLAYWIDTH, DISPLAYHEIGHT, "curses14x16.png") - .build()?; - if config::CONFIG.visuals.with_scanlines { - context.with_post_scanlines(config::CONFIG.visuals.with_screen_burn); - } +#[notan_main] +fn main() -> Result<(), String> { + let win_config = WindowConfig::new() + .set_size(DISPLAYWIDTH * (TILESIZE.x as u32), DISPLAYHEIGHT * (TILESIZE.x as u32)) + .set_title("RUST-RL") + .set_resizable(true) + .set_fullscreen(true) + .set_taskbar_icon_data(Some(include_bytes!("../resources/icon.png"))) + .set_vsync(true); + notan + ::init_with(setup) + .add_config(win_config) + .add_config(notan::draw::DrawConfig) + .draw(draw) + .update(update) + .build() +} +fn setup(app: &mut App, gfx: &mut Graphics) -> State { + effects::sound::init_sounds(app); + effects::sound::ambience("a_relax"); + let texture = gfx + .create_texture() + .from_image(include_bytes!("../resources/atlas.png")) + .build() + .unwrap(); + let data = include_bytes!("../resources/atlas.json"); + let atlas = create_textures_from_atlas(data, &texture).unwrap(); + let texture = gfx + .create_texture() + .from_image(include_bytes!("../resources/td.png")) + .build() + .unwrap(); + let data = include_bytes!("../resources/td.json"); + let interface = create_textures_from_atlas(data, &texture).unwrap(); + let font = Fonts::new( + gfx.create_font(include_bytes!("../resources/fonts/Greybeard-16px.ttf")).unwrap(), + Some( + gfx.create_font(include_bytes!("../resources/fonts/Greybeard-16px-Bold.ttf")).unwrap() + ), + Some( + gfx.create_font(include_bytes!("../resources/fonts/Greybeard-16px-Italic.ttf")).unwrap() + ) + ); let mut gs = State { ecs: World::new(), + //audio: sounds, + atlas, + interface, + font, mapgen_next_state: Some(RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame, }), @@ -37,6 +76,7 @@ fn main() -> BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); @@ -111,6 +151,11 @@ fn main() -> BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); + gs.ecs.register::(); + gs.ecs.register::(); + gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::>(); gs.ecs.register::(); @@ -127,13 +172,526 @@ fn main() -> BError { gs.ecs.insert(gui::Ancestry::Human); // ancestry let player_entity = spawner::player(&mut gs.ecs, 0, 0); gs.ecs.insert(player_entity); // Player entity - gs.ecs.insert(RunState::MapGeneration {}); // RunState + gs.ecs.insert(RunState::MapGeneration {}); // TODO: Set this back to RunState::MapGen gs.ecs.insert(particle_system::ParticleBuilder::new()); gs.ecs.insert(rex_assets::RexAssets::new()); gamelog::setup_log(); - gamelog::record_event(data::events::EVENT::Level(1)); + gamelog::record_event(consts::events::EVENT::Level(1)); gs.generate_world_map(1, TileType::Floor); - main_loop(context, gs) + gs +} +const ASCII_MODE: bool = false; // Change this to config setting +const SHOW_BOUNDARIES: bool = false; // Config setting + +#[derive(PartialEq)] +enum DrawType { + None, + Player, + Visible, + Telepathy, +} + +#[derive(PartialEq, Eq, Hash)] +struct DrawKey { + x: i32, + y: i32, + render_order: i32, +} +struct DrawInfo { + e: Entity, + draw_type: DrawType, +} + +fn draw_entities( + map: &Map, + ecs: &World, + draw: &mut Draw, + atlas: &HashMap, + _font: &Fonts +) { + { + let bounds = crate::camera::get_screen_bounds(ecs, false); + let bounds_to_px = bounds.to_px(); + let offset_x = bounds_to_px.x_offset - bounds_to_px.min_x; + let offset_y = bounds_to_px.y_offset - bounds_to_px.min_y; + let positions = ecs.read_storage::(); + let renderables = ecs.read_storage::(); + let hidden = ecs.read_storage::(); + let minds = ecs.read_storage::(); + let pools = ecs.read_storage::(); + let entities = ecs.entities(); + let player = ecs.read_storage::(); + let data = (&positions, &renderables, &entities, !&hidden).join().collect::>(); + let mut to_draw: HashMap = HashMap::new(); + for (pos, render, e, _h) in data.iter() { + let idx = map.xy_idx(pos.x, pos.y); + if + crate::camera::in_bounds( + pos.x, + pos.y, + bounds.min_x, + bounds.min_y, + bounds.max_x, + bounds.max_y + ) + { + let draw_type = if map.visible_tiles[idx] { + // If it's anything else, just draw it. + if player.get(*e).is_some() { + DrawType::Player + } else { + DrawType::Visible + } + } else if map.telepath_tiles[idx] { + let has_mind = minds.get(*e); + if has_mind.is_some() { + // Mobs we see through telepathy - generally we just + // draw these, but it uses a unique enum variant so + // it can be treated differently if needed in future. + DrawType::Telepathy + } else { + DrawType::None + } + } else { + // If we don't see it, and we don't sense it with + // telepathy, don't draw it at all. + DrawType::None + }; + match draw_type { + DrawType::None => {} + _ => { + to_draw.insert( + DrawKey { x: pos.x, y: pos.y, render_order: render.render_order }, + DrawInfo { e: *e, draw_type } + ); + } + } + } + } + let mut entries: Vec<(&DrawKey, &DrawInfo)> = to_draw.iter().collect(); + entries.sort_by_key(|&(k, _v)| std::cmp::Reverse(k.render_order)); + for entry in entries.iter() { + // TODO: ABSTRACT THESE INTO FUNCTIONS ONCE FUNCTIONALITY IS SETTLED ON. + match entry.1.draw_type { + DrawType::Visible | DrawType::Telepathy => { + let renderable = renderables.get(entry.1.e).unwrap(); + let id = if let Some(sprite) = atlas.get(&renderable.sprite) { + sprite + } else { + panic!("No entity sprite found for ID: {}", &renderable.sprite); + }; + let x_pos = (entry.0.x as f32) * TILESIZE.sprite_x + offset_x; + let y_pos = (entry.0.y as f32) * TILESIZE.sprite_y + offset_y; + let mul = themes::darken_by_distance( + Point::new(entry.0.x, entry.0.y), + *ecs.fetch::() + ); + let col = Color::from_rgb( + renderable.fg.r * mul, + renderable.fg.g * mul, + renderable.fg.b * mul + ); + draw.image(id) + .position( + x_pos + renderable.offset.0 * TILESIZE.sprite_x, + y_pos + renderable.offset.1 * TILESIZE.sprite_y + ) + .color(col) + .size(TILESIZE.sprite_x, TILESIZE.sprite_y); + if let Some(pool) = pools.get(entry.1.e) { + if pool.hit_points.current < pool.hit_points.max { + draw_entity_hp(x_pos, y_pos, pool, draw); + } + } + } + DrawType::Player => { + let (x_pos, y_pos) = ( + (entry.0.x as f32) * TILESIZE.sprite_x + offset_x, + (entry.0.y as f32) * TILESIZE.sprite_y + offset_y, + ); + let textures = get_avatar_textures(ecs, atlas); + for (tex, col) in textures.iter() { + draw.image(tex) + .position(x_pos, y_pos) + .color(*col) + .size(TILESIZE.sprite_x, TILESIZE.sprite_y); + } + } + _ => {} + } + } + } +} + +fn get_avatar_textures(ecs: &World, atlas: &HashMap) -> Vec<(Texture, Color)> { + let player = ecs.fetch::(); + let renderables = ecs.read_storage::(); + let equipped = ecs.read_storage::(); + let has_avatar = ecs.read_storage::(); + let mut avis = Vec::new(); + if let Some(renderables) = renderables.get(*player) { + if let Some(sprite) = atlas.get(&renderables.sprite) { + avis.push(( + sprite.clone(), + Color::from_rgb(renderables.fg.r, renderables.fg.g, renderables.fg.b), + )); + } else { + panic!("No player sprite found for ID: {}", &renderables.sprite); + } + } else { + panic!("No player renderable found!"); + } + for (_e, a, r) in (&equipped, &has_avatar, &renderables) + .join() + .filter(|item| item.0.owner == *player) { + if let Some(sprite) = atlas.get(&a.sprite) { + avis.push((sprite.clone(), Color::from_rgb(r.fg.r, r.fg.g, r.fg.b))); + } else { + panic!("No avatar sprite found for ID: {}", &a.sprite); + } + } + avis +} + +// Draws a HP bar LINE_WIDTH pixels thick centered above the entity. +fn draw_entity_hp(x: f32, y: f32, hp: &Pools, draw: &mut Draw) { + const LINE_WIDTH: f32 = 3.0; + let y = y + LINE_WIDTH + 1.0; + let x = x; + let fill_pct = (hp.hit_points.current as f32) / (hp.hit_points.max as f32); + draw.line((x + 1.0, y), (x + (TILESIZE.sprite_x - 1.0) * fill_pct, y)) + .width(LINE_WIDTH) + .color(Color::GREEN); +} + +fn render_map_in_view( + map: &Map, + ecs: &World, + draw: &mut Draw, + atlas: &HashMap, + mapgen: bool +) { + let bounds = crate::camera::get_screen_bounds(ecs, mapgen); + let mut y = 0; + for tile_y in bounds.min_y..bounds.max_y { + let mut x = 0; + for tile_x in bounds.min_x..bounds.max_x { + if crate::camera::in_bounds(tile_x, tile_y, 0, 0, map.width, map.height) { + let idx = map.xy_idx(tile_x, tile_y); + if map.revealed_tiles[idx] || mapgen { + let draw_x = + (x as f32) * TILESIZE.sprite_x + (bounds.x_offset as f32) * TILESIZE.x; + let draw_y = + (y as f32) * TILESIZE.sprite_y + (bounds.y_offset as f32) * TILESIZE.x; + if ASCII_MODE { + let (glyph, fg, bg) = crate::map::themes::get_tile_renderables_for_id( + idx, + &*map, + Some(*ecs.fetch::()), + None + ); + // TODO: Draw ASCII + } else { + let (id, tint) = crate::map::themes::get_sprite_for_id( + idx, + &*map, + Some(*ecs.fetch::()) + ); + let sprite = if let Some(sprite) = atlas.get(id) { + sprite + } else { + panic!("No sprite found for ID: {}", id); + }; + draw.image(sprite) + .position(draw_x, draw_y) + .color(tint) + .size(TILESIZE.sprite_x, TILESIZE.sprite_y); + } + if !map.visible_tiles[idx] { + // Recall map memory. TODO: Improve this? Optimize? Do we need to remember more fields? + if let Some(memories) = map.memory.get(&idx) { + let mut sorted: Vec<_> = memories.iter().collect(); + sorted.sort_by(|a, b| a.render_order.cmp(&b.render_order)); + for memory in sorted.iter() { + let mult = consts::visuals::NON_VISIBLE_MULTIPLIER; + let col = Color::from_rgb( + memory.fg.r * mult, + memory.fg.g * mult, + memory.fg.b * mult + ); + let sprite = if let Some(sprite) = atlas.get(&memory.sprite) { + sprite + } else { + panic!("No sprite found for ID: {}", memory.sprite); + }; + draw.image(sprite) + .position( + draw_x + memory.offset.0 * TILESIZE.sprite_x, + draw_y + memory.offset.1 * TILESIZE.sprite_y + ) + .color(col) + .size(TILESIZE.sprite_x, TILESIZE.sprite_y); + } + } + } + } + } else if SHOW_BOUNDARIES { + // TODO: Draw boundaries + } + x += 1; + } + y += 1; + } +} + +struct BoxDraw { + frame: String, + fill: bool, + top_left: (i32, i32), + top_right: (i32, i32), + bottom_left: (i32, i32), + bottom_right: (i32, i32), +} +fn draw_spritebox(panel: BoxDraw, draw: &mut Draw, atlas: &HashMap) { + draw.image(atlas.get(&format!("{}_1", panel.frame)).unwrap()).position( + (panel.top_left.0 as f32) * TILESIZE.x, + (panel.top_left.1 as f32) * TILESIZE.x + ); + for i in panel.top_left.0 + 1..panel.top_right.0 { + draw.image(atlas.get(&format!("{}_2", panel.frame)).unwrap()).position( + (i as f32) * TILESIZE.x, + (panel.top_left.1 as f32) * TILESIZE.x + ); + } + draw.image(atlas.get(&format!("{}_3", panel.frame)).unwrap()).position( + (panel.top_right.0 as f32) * TILESIZE.x, + (panel.top_right.1 as f32) * TILESIZE.x + ); + for i in panel.top_left.1 + 1..panel.bottom_left.1 { + draw.image(atlas.get(&format!("{}_4", panel.frame)).unwrap()).position( + (panel.top_left.0 as f32) * TILESIZE.x, + (i as f32) * TILESIZE.x + ); + } + if panel.fill { + for i in panel.top_left.0 + 1..panel.top_right.0 { + for j in panel.top_left.1 + 1..panel.bottom_left.1 { + draw.image(atlas.get(&format!("{}_5", panel.frame)).unwrap()).position( + (i as f32) * TILESIZE.x, + (j as f32) * TILESIZE.x + ); + } + } + } + for i in panel.top_right.1 + 1..panel.bottom_right.1 { + draw.image(atlas.get(&format!("{}_6", panel.frame)).unwrap()).position( + (panel.top_right.0 as f32) * TILESIZE.x, + (i as f32) * TILESIZE.x + ); + } + draw.image(atlas.get(&format!("{}_7", panel.frame)).unwrap()).position( + (panel.bottom_left.0 as f32) * TILESIZE.x, + (panel.bottom_left.1 as f32) * TILESIZE.x + ); + for i in panel.bottom_left.0 + 1..panel.bottom_right.0 { + draw.image(atlas.get(&format!("{}_8", panel.frame)).unwrap()).position( + (i as f32) * TILESIZE.x, + (panel.bottom_left.1 as f32) * TILESIZE.x + ); + } + draw.image(atlas.get(&format!("{}_9", panel.frame)).unwrap()).position( + (panel.bottom_right.0 as f32) * TILESIZE.x, + (panel.bottom_right.1 as f32) * TILESIZE.x + ); +} + +use crate::consts::visuals::{ VIEWPORT_H, VIEWPORT_W }; +fn draw_bg(_ecs: &World, draw: &mut Draw, atlas: &HashMap) { + let offset = crate::camera::get_offset(); + let log = BoxDraw { + frame: "line".to_string(), + fill: false, + top_left: (0, 0), + top_right: (offset.x + VIEWPORT_W, 0), + bottom_left: (0, offset.y - 2), + bottom_right: (offset.x + VIEWPORT_W, offset.y - 2), + }; + let game = BoxDraw { + frame: "line".to_string(), + fill: false, + top_left: (offset.x - 1, offset.y - 1), + top_right: (offset.x + VIEWPORT_W, offset.y - 1), + bottom_left: (offset.x - 1, offset.y + VIEWPORT_H), + bottom_right: (offset.x + VIEWPORT_W, offset.y + VIEWPORT_H), + }; + let attr = BoxDraw { + frame: "line".to_string(), + fill: false, + top_left: (offset.x - 1, offset.y + VIEWPORT_H + 1), + top_right: (offset.x + VIEWPORT_W, offset.y + VIEWPORT_H + 1), + bottom_left: (offset.x - 1, (DISPLAYHEIGHT as i32) - 1), + bottom_right: (offset.x + VIEWPORT_W, (DISPLAYHEIGHT as i32) - 1), + }; + let sidebox = BoxDraw { + frame: "line".to_string(), + fill: false, + top_left: (offset.x + VIEWPORT_W + 1, 0), + top_right: ((DISPLAYWIDTH as i32) - 1, 0), + bottom_left: (offset.x + VIEWPORT_W + 1, (DISPLAYHEIGHT as i32) - 1), + bottom_right: ((DISPLAYWIDTH as i32) - 1, (DISPLAYHEIGHT as i32) - 1), + }; + draw_spritebox(log, draw, atlas); + draw_spritebox(game, draw, atlas); + draw_spritebox(attr, draw, atlas); + draw_spritebox(sidebox, draw, atlas); +} + +fn draw(_app: &mut App, gfx: &mut Graphics, gs: &mut State) { + let mut draw = gfx.create_draw(); + draw.clear(Color::BLACK); + let mut log = false; + let runstate = *gs.ecs.fetch::(); + match runstate { + RunState::MainMenu { .. } => { + gui::draw_mainmenu(&gs.ecs, &mut draw, &gs.atlas, &gs.font); + } + RunState::CharacterCreation { .. } => { + gui::draw_charcreation(&gs.ecs, &mut draw, &gs.atlas, &gs.font); + } + RunState::PreRun { .. } => {} + RunState::MapGeneration => { + draw_bg(&gs.ecs, &mut draw, &gs.interface); + if config::CONFIG.logging.show_mapgen && gs.mapgen_history.len() > 0 { + render_map_in_view( + &gs.mapgen_history[gs.mapgen_index], + &gs.ecs, + &mut draw, + &gs.atlas, + true + ); + } + gui::draw_ui2(&gs.ecs, &mut draw, &gs.atlas, &gs.font); + } + _ => { + let map = gs.ecs.fetch::(); + draw_bg(&gs.ecs, &mut draw, &gs.interface); + render_map_in_view(&*map, &gs.ecs, &mut draw, &gs.atlas, false); + // Special case: targeting needs to be drawn *below* entities, but above tiles. + if let RunState::ShowTargeting { range, item: _, x, y, aoe } = runstate { + gui::draw_targeting(&gs.ecs, &mut draw, &gs.atlas, x, y, range, aoe); + } + draw_entities(&*map, &gs.ecs, &mut draw, &gs.atlas, &gs.font); + gui::draw_ui2(&gs.ecs, &mut draw, &gs.atlas, &gs.font); + log = true; + } + } + match runstate { + RunState::Farlook { x, y } => { + gui::draw_farlook(&gs.ecs, x, y, &mut draw, &gs.atlas); + //draw_tooltips(&gs.ecs, ctx, Some((x, y))); TODO: Put this in draw loop + } + RunState::ShowCheatMenu => { + gui::draw_cheat_menu(&mut draw, &gs.atlas, &gs.font); + } + RunState::ActionWithDirection { .. } => { + corner_text("In what direction? [0-9]/[YUHJKLBN]", &mut draw, &gs.font); + } + RunState::GameOver => { + corner_text("Create morgue file? [Y/N]", &mut draw, &gs.font); + } + RunState::ShowInventory => { + corner_text("Use what? [aA-zZ]/[Esc.]", &mut draw, &gs.font); + let offset = crate::camera::get_offset(); + let (x, y) = ( + ((1 + offset.x) as f32) * TILESIZE.x, + ((3 + offset.y) as f32) * TILESIZE.x, + ); + gui::draw_backpack_items(&gs.ecs, &mut draw, &gs.font, x, y); + } + RunState::ShowDropItem => { + corner_text("Drop what? [aA-zZ]/[Esc.]", &mut draw, &gs.font); + let offset = crate::camera::get_offset(); + let (x, y) = ( + ((1 + offset.x) as f32) * TILESIZE.x, + ((3 + offset.y) as f32) * TILESIZE.x, + ); + gui::draw_backpack_items(&gs.ecs, &mut draw, &gs.font, x, y); + } + RunState::ShowRemoveItem => { + corner_text("Unequip which item? [aA-zZ]/[Esc.]", &mut draw, &gs.font); + let offset = crate::camera::get_offset(); + let (x, y) = ( + ((1 + offset.x) as f32) * TILESIZE.x, + ((3 + offset.y) as f32) * TILESIZE.x, + ); + gui::draw_items(&gs.ecs, &mut draw, &gs.font, x, y, gui::Location::Equipped, None); + } + RunState::ShowTargeting { .. } => { + corner_text("Targeting which tile? [0-9]/[YUHJKLBN]", &mut draw, &gs.font); + } + RunState::HelpScreen => { + corner_text("The help screen is a placeholder! [?]", &mut draw, &gs.font); + } + _ => {} + } + // TODO: Once the rest of drawing is finalised, this should be abstracted + // into some functions that make it easier to tell what is going on. But + // for the short-term: + // 1. notan::Text is required for rich text drawing, rather than just the + // basics that are accessible with notan::Draw's .text() method. + // 2. notan::Text cannot be projected, and rendering both Draw and Text + // requires two GPU calls instead of just one. + // 3. To fix this, our log is drawn to notan::Text, then rendered to a + // render texture, and applied as any other image to notan::Draw. + // 4. notan::Draw is projected, and then rendered, and everything works. + // Further stuff: Make the render texture only as large as is required, + // so text cannot escape the bounds of the logbox. + let (width, height) = gfx.size(); + let win_size = vec2(width as f32, height as f32); + let (projection, _) = calc_projection(win_size, WORK_SIZE); + if log { + let buffer = gfx + .create_render_texture(width, height) + .build() + .expect("Failed to create render texture"); + gamelog::render_log( + &buffer, + gfx, + &gs.font, + &(TILESIZE.x, TILESIZE.x * 6.0 + 4.0), + (VIEWPORT_W as f32) * TILESIZE.x, + 5 + ); + draw.image(&buffer) + .position(0.0, 0.0) + .size(width as f32, height as f32); + } + draw.set_projection(Some(projection)); + gfx.render(&draw); +} + +fn update(ctx: &mut App, state: &mut State) { + state.update(ctx); +} + +fn corner_text(text: &str, draw: &mut Draw, font: &Fonts) { + let offset = crate::camera::get_offset(); + draw.text(&font.b(), &text) + .position(((offset.x + 1) as f32) * TILESIZE.x, ((offset.y + 1) as f32) * TILESIZE.x) + .size(FONTSIZE); +} + +fn calc_projection(win_size: Vec2, work_size: Vec2) -> (Mat4, f32) { + let ratio = (win_size.x / work_size.x).min(win_size.y / work_size.y); + let proj = Mat4::orthographic_rh_gl(0.0, win_size.x, win_size.y, 0.0, -1.0, 1.0); + let scale = Mat4::from_scale(vec3(ratio, ratio, 1.0)); + let position = vec3( + (win_size.x - work_size.x * ratio) * 0.5, + (win_size.y - work_size.y * ratio) * 0.5, + 1.0 + ); + let trans = Mat4::from_translation(position); + (proj * trans * scale, ratio) } diff --git a/src/map/dungeon.rs b/src/map/dungeon.rs index 4407efa..d5331a2 100644 --- a/src/map/dungeon.rs +++ b/src/map/dungeon.rs @@ -4,7 +4,7 @@ use bracket_lib::prelude::*; use serde::{ Deserialize, Serialize }; use specs::prelude::*; use std::collections::{ HashMap, HashSet }; -use crate::data::events::*; +use crate::consts::events::*; #[derive(Default, Serialize, Deserialize, Clone)] pub struct MasterDungeonMap { @@ -112,26 +112,7 @@ fn make_scroll_name(rng: &mut RandomNumberGenerator) -> String { return name; } -const POTION_COLOURS: &[&str] = &[ - "red", - "orange", - "yellow", - "green", - "blue", - "indigo", - "violet", - "black", - "white", - "silver", - "gold", - "rainbow", - "blood", - "purple", - "cyan", - "brown", - "grey", - "octarine", -]; +const POTION_COLOURS: &[&str] = &["blue", "red", "green", "yellow", "black"]; const POTION_ADJECTIVES: &[&str] = &[ "swirling", "viscous", diff --git a/src/map/interval_spawning_system.rs b/src/map/interval_spawning_system.rs index b03918a..acdaad2 100644 --- a/src/map/interval_spawning_system.rs +++ b/src/map/interval_spawning_system.rs @@ -10,7 +10,7 @@ use crate::{ }; use specs::prelude::*; use bracket_lib::prelude::*; -use crate::data::events::*; +use crate::consts::events::*; const TRY_SPAWN_CHANCE: i32 = 70; const FEATURE_MESSAGE_CHANCE: i32 = 110; diff --git a/src/map/mod.rs b/src/map/mod.rs index 99a0c6a..d33ac00 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -1,23 +1,42 @@ use bracket_lib::prelude::*; +use specs::prelude::*; use serde::{ Deserialize, Serialize }; use std::collections::{ HashSet, HashMap }; 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; pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval }; pub mod dungeon; pub use dungeon::{ level_transition, MasterDungeonMap }; pub mod themes; -use super::data::visuals::{ +use super::consts::visuals::{ BRIGHTEN_FG_COLOUR_BY, GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP, + SPRITE_OFFSET_MIN_CLAMP, + SPRITE_OFFSET_MAX_CLAMP, }; // FIXME: If the map size gets too small, entities stop being rendered starting from the right. // i.e. on a map size of 40*40, only entities to the left of the player are rendered. // on a map size of 42*42, the player can see entities up to 2 tiles to their right. +#[derive(Clone, Serialize, Deserialize)] +pub struct MapMemory { + pub sprite: String, + pub fg: RGB, + pub offset: (f32, f32), + pub render_order: i32, +} + #[derive(Default, Serialize, Deserialize, Clone)] pub struct Map { pub overmap: bool, @@ -25,6 +44,7 @@ pub struct Map { pub width: i32, pub height: i32, pub revealed_tiles: Vec, + pub memory: HashMap>, pub visible_tiles: Vec, pub lit_tiles: Vec, pub telepath_tiles: Vec, @@ -63,6 +83,7 @@ impl Map { width: width, height: height, revealed_tiles: vec![false; map_tile_count], + memory: HashMap::new(), visible_tiles: vec![false; map_tile_count], lit_tiles: vec![true; map_tile_count], // NYI: Light sources. Once those exist, we can set this to false. telepath_tiles: vec![false; map_tile_count], @@ -91,9 +112,9 @@ impl Map { rng.range(GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP), ); map.colour_offset[idx].1 = ( - rng.range(GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP), - rng.range(GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP), - rng.range(GLOBAL_OFFSET_MIN_CLAMP, GLOBAL_OFFSET_MAX_CLAMP), + rng.range(SPRITE_OFFSET_MIN_CLAMP, SPRITE_OFFSET_MAX_CLAMP), + rng.range(SPRITE_OFFSET_MIN_CLAMP, SPRITE_OFFSET_MAX_CLAMP), + rng.range(SPRITE_OFFSET_MIN_CLAMP, SPRITE_OFFSET_MAX_CLAMP), ); } diff --git a/src/map/themes.rs b/src/map/themes.rs index 8ddcc2a..c118f47 100644 --- a/src/map/themes.rs +++ b/src/map/themes.rs @@ -1,9 +1,53 @@ use super::{ Map, Point, TileType }; -use crate::data::visuals::*; +use crate::consts::visuals::*; use crate::config::CONFIG; -use crate::data::ids::*; +use crate::consts::ids::*; use bracket_lib::prelude::*; use std::ops::{ Add, Mul }; +use notan::prelude::*; + +pub fn get_sprite_for_id(idx: usize, map: &Map, other_pos: Option) -> (&str, Color) { + let bloody = if map.bloodstains.contains_key(&idx) { + Some(map.bloodstains[&idx]) + } else { + None + }; + let f = map.colour_offset[idx].0.0; // Using offset as a source of random. + let (sprite, offset, mut colour) = match map.tiles[idx] { + TileType::Wall => + ( + map.tiles[idx].sprite(check_if_base(TileType::Wall, idx, map), f, bloody), + map.tiles[idx].offset(), + map.tiles[idx].col(bloody), + ), + _ => + ( + map.tiles[idx].sprite(false, f, bloody), + map.tiles[idx].offset(), + map.tiles[idx].col(bloody), + ), + }; + // Get the right modifier for visibility - darkened by distance from POV, or full dark for out-of-view. + let visibility = if !map.visible_tiles[idx] { + NON_VISIBLE_MULTIPLIER + } else { + if other_pos.is_some() { + darken_by_distance( + Point::new((idx as i32) % map.width, (idx as i32) / map.width), + other_pos.unwrap() + ) + } else { + 1.0 + } + }; + // Apply our offsets to our base colour. + colour = apply_colour_offset(colour, map, idx, offset, true); + // Apply our visibility modifier + colour = colour.mul(visibility); + // Convert to a notan colour. + let tint = Color::from_rgb(colour.r, colour.g, colour.b); + return (sprite, tint); +} /// 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( @@ -136,10 +180,24 @@ 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(tt: TileType, idx: usize, map: &Map) -> bool { + let x = (idx as i32) % map.width; + let y = (idx as i32) / map.width; + // 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; } fn wall_glyph(map: &Map, x: i32, y: i32, debug: Option) -> FontCharType { @@ -156,37 +214,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; } @@ -326,11 +384,11 @@ pub fn multiply_by_float(rgb: RGB, offsets: (f32, f32, f32)) -> RGB { return RGB::from_f32(r, g, b); } -fn darken_by_distance(pos: Point, other_pos: Point) -> f32 { +pub fn darken_by_distance(pos: Point, other_pos: Point) -> f32 { let distance = DistanceAlg::Pythagoras.distance2d(pos, other_pos) as f32; // Get distance in tiles. let interp_factor = (distance - START_DARKEN_AT_N_TILES) / - ((crate::data::entity::DEFAULT_VIEWSHED_STANDARD as f32) - START_DARKEN_AT_N_TILES); + ((crate::consts::entity::DEFAULT_VIEWSHED_STANDARD as f32) - START_DARKEN_AT_N_TILES); let interp_factor = interp_factor.max(0.0).min(1.0); // Clamp [0-1] let result = 1.0 - diff --git a/src/map/tiletype.rs b/src/map/tiletype.rs index f451c9b..08f849c 100644 --- a/src/map/tiletype.rs +++ b/src/map/tiletype.rs @@ -1,4 +1,6 @@ use serde::{ Deserialize, Serialize }; +use bracket_lib::prelude::*; +use crate::consts::visuals::*; #[derive(PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Debug)] pub enum TileType { @@ -27,9 +29,117 @@ pub enum TileType { ToOvermap(i32), ToLocal(i32), } + +impl TileType { + pub fn sprite(&self, base: bool, float: f32, bloody: Option) -> &str { + if base { + return self.h(float, bloody); + } + return self.v(float, bloody); + } + fn h(&self, float: f32, _bloody: Option) -> &str { + let options = match self { + TileType::Wall => vec!["wall_b", "wall_b_cracked"], + _ => unreachable!("Tried to get a h (base) sprite for a non-wall tile."), + }; + return options[(float * (options.len() as f32)) as usize]; + } + fn v(&self, float: f32, bloody: Option) -> &str { + let mut options = match self { + TileType::ImpassableMountain => vec!["wall_b"], + TileType::Wall => vec!["wall"], + TileType::DeepWater => vec!["water", "water2"], + TileType::Fence => vec!["tiles4"], + TileType::Bars => vec!["wall_b"], + TileType::Floor => vec!["dot"], + TileType::WoodFloor => vec!["planks", "planks_missing", "planks_missing2"], + TileType::Gravel => vec!["fluff", "fluff2"], + TileType::Road => + vec![ + "tiles", + "tiles_missing", + "tiles_missing2", + "tiles_missing3", + "tiles_missing4", + "tiles_missing5", + "tiles_missing6" + ], + TileType::Grass => vec!["fluff", "fluff2"], + TileType::Foliage => vec!["grass_small", "grass"], + TileType::HeavyFoliage => vec!["grass_flower"], + TileType::Sand => vec!["fluff", "fluff2"], + TileType::ShallowWater => vec!["water", "water2"], + TileType::Bridge => vec!["planks"], + TileType::DownStair => vec!["stair_down"], + TileType::UpStair => vec!["stair_up"], + TileType::ToLocal(_) => vec!["stair_down"], + TileType::ToOvermap(_) => vec!["stair_up"], + }; + if bloody.is_some() && tile_walkable(*self) { + options.extend( + vec!["blood1", "blood2", "blood3", "blood4", "blood5", "blood6", "blood7"] + ); + } + return options[(float * (options.len() as f32)) as usize]; + } + pub fn offset(&self) -> (i32, i32, i32) { + match self { + TileType::ImpassableMountain => IMPASSABLE_MOUNTAIN_OFFSETS, + TileType::Wall => WALL_OFFSETS, + TileType::DeepWater => DEEP_WATER_OFFSETS, + TileType::Fence => FENCE_OFFSETS, + TileType::Bars => BARS_OFFSETS, + TileType::Floor => FLOOR_OFFSETS, + TileType::WoodFloor => WOOD_FLOOR_OFFSETS, + TileType::Gravel => GRAVEL_OFFSETS, + TileType::Road => ROAD_OFFSETS, + TileType::Grass => GRASS_OFFSETS, + TileType::Foliage => FOLIAGE_OFFSETS, + TileType::HeavyFoliage => HEAVY_FOLIAGE_OFFSETS, + TileType::Sand => SAND_OFFSETS, + TileType::ShallowWater => SHALLOW_WATER_OFFSETS, + TileType::Bridge => BRIDGE_OFFSETS, + TileType::DownStair => STAIR_OFFSETS, + TileType::UpStair => STAIR_OFFSETS, + TileType::ToLocal(_) => WALL_OFFSETS, + TileType::ToOvermap(_) => WALL_OFFSETS, + } + } + pub fn col(&self, bloody: Option) -> RGB { + if let Some(bloody) = bloody { + return bloody; + } + RGB::named(match self { + TileType::ImpassableMountain => IMPASSABLE_MOUNTAIN_COLOUR, + TileType::Wall => WALL_COLOUR, + TileType::DeepWater => DEEP_WATER_COLOUR, + TileType::Fence => FENCE_COLOUR, + TileType::Bars => BARS_COLOUR, + TileType::Floor => FLOOR_COLOUR, + TileType::WoodFloor => WOOD_FLOOR_COLOUR, + TileType::Gravel => GRAVEL_COLOUR, + TileType::Road => ROAD_COLOUR, + TileType::Grass => GRASS_COLOUR, + TileType::Foliage => FOLIAGE_COLOUR, + TileType::HeavyFoliage => HEAVY_FOLIAGE_COLOUR, + TileType::Sand => SAND_COLOUR, + TileType::ShallowWater => SHALLOW_WATER_COLOUR, + TileType::Bridge => BRIDGE_COLOUR, + TileType::DownStair => STAIR_COLOUR, + TileType::UpStair => STAIR_COLOUR, + TileType::ToLocal(_) => WALL_COLOUR, + TileType::ToOvermap(_) => WALL_COLOUR, + }) + } +} + pub fn tile_walkable(tt: TileType) -> bool { 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, } } @@ -40,6 +150,11 @@ pub fn tile_opaque(tt: TileType) -> bool { _ => false, } } +pub fn tile_blocks_telepathy(tt: TileType) -> bool { + match tt { + _ => false, + } +} pub fn tile_cost(tt: TileType) -> f32 { match tt { TileType::Road => 0.75, diff --git a/src/map_builders/forest.rs b/src/map_builders/forest.rs index e30f270..fac9cde 100644 --- a/src/map_builders/forest.rs +++ b/src/map_builders/forest.rs @@ -12,7 +12,7 @@ use super::{ Foliage, }; use bracket_lib::prelude::*; -use crate::data::names::*; +use crate::consts::names::*; pub fn forest_builder( new_id: i32, diff --git a/src/map_builders/mod.rs b/src/map_builders/mod.rs index b9dcbfe..4a783d5 100644 --- a/src/map_builders/mod.rs +++ b/src/map_builders/mod.rs @@ -40,8 +40,8 @@ use common::*; use specs::prelude::*; use voronoi_spawning::VoronoiSpawning; use super::config::CONFIG; -use super::data::ids::*; -use super::data::names::*; +use super::consts::ids::*; +use super::consts::names::*; //use wfc::WaveFunctionCollapseBuilder; mod room_exploder; use room_exploder::RoomExploder; @@ -215,12 +215,12 @@ fn random_start_position(rng: &mut RandomNumberGenerator) -> (XStart, YStart) { } fn random_room_builder(rng: &mut RandomNumberGenerator, builder: &mut BuilderChain, end: bool) { - let build_roll = rng.roll_dice(1, 3); + let build_roll = rng.roll_dice(1, 2); // TODO: BSP Interiors, change this to 1d3 and uncomment. // Start with a room builder. match build_roll { 1 => builder.start_with(SimpleMapBuilder::new(None)), - 2 => builder.start_with(BspDungeonBuilder::new()), - _ => builder.start_with(BspInteriorBuilder::new()), + _ => builder.start_with(BspDungeonBuilder::new()), + //_ => builder.start_with(BspInteriorBuilder::new()), } // BspInterior makes its own doorways. If we're not using that one, @@ -301,7 +301,7 @@ fn random_shape_builder( end: bool ) -> bool { // Pick an initial builder - let builder_roll = rng.roll_dice(1, 16); + let builder_roll = rng.roll_dice(1, 13); let mut want_doors = true; match builder_roll { 1 => builder.start_with(CellularAutomataBuilder::new()), @@ -319,11 +319,7 @@ fn random_shape_builder( 10 => builder.start_with(DLABuilder::central_attractor()), 11 => builder.start_with(DLABuilder::insectoid()), 12 => builder.start_with(VoronoiBuilder::pythagoras()), - 13 => builder.start_with(VoronoiBuilder::manhattan()), - _ => - builder.start_with( - PrefabBuilder::constant(prefab_builder::prefab_levels::WFC_POPULATED) - ), + _ => builder.start_with(VoronoiBuilder::manhattan()), } // 'Select' the centre by placing a starting position, and cull everywhere unreachable. @@ -439,6 +435,8 @@ pub fn random_builder( builder } +use crate::consts::prelude::*; + pub fn level_builder( id: i32, rng: &mut RandomNumberGenerator, @@ -447,15 +445,15 @@ pub fn level_builder( initial_player_level: i32 ) -> BuilderChain { match id { - ID_OVERMAP => room_accretion(), + ID_OVERMAP => overmap_builder(), ID_TOWN => town_builder(id, rng, width, height, 0, initial_player_level), ID_TOWN2 => forest_builder(id, rng, width, height, 1, initial_player_level), ID_TOWN3 => random_builder( id, rng, - width, - height, + VIEWPORT_W, + VIEWPORT_H, 2, 1, initial_player_level, @@ -466,8 +464,8 @@ pub fn level_builder( random_builder( id, rng, - width, - height, + VIEWPORT_W, + VIEWPORT_H, 4 + diff(ID_INFINITE, id), 1 + diff(ID_INFINITE, id), initial_player_level, @@ -478,8 +476,8 @@ pub fn level_builder( random_builder( id, rng, - width, - height, + VIEWPORT_W, + VIEWPORT_H, 1, 404, initial_player_level, diff --git a/src/map_builders/prefab_builder/mod.rs b/src/map_builders/prefab_builder/mod.rs index 582577d..c6b0e35 100644 --- a/src/map_builders/prefab_builder/mod.rs +++ b/src/map_builders/prefab_builder/mod.rs @@ -4,7 +4,7 @@ pub mod prefab_levels; pub mod prefab_sections; pub mod prefab_vaults; use std::collections::HashSet; -use crate::data::ids::*; +use crate::consts::ids::*; #[derive(PartialEq, Copy, Clone)] #[allow(dead_code)] diff --git a/src/map_builders/prefab_builder/prefab_levels.rs b/src/map_builders/prefab_builder/prefab_levels.rs index 3fae32c..997c533 100644 --- a/src/map_builders/prefab_builder/prefab_levels.rs +++ b/src/map_builders/prefab_builder/prefab_levels.rs @@ -5,61 +5,12 @@ pub struct PrefabLevel { pub height: usize, } -#[allow(dead_code)] -pub const WFC_POPULATED: PrefabLevel = PrefabLevel { template: LEVEL_MAP, width: 80, height: 43 }; pub const OVERMAP: PrefabLevel = PrefabLevel { template: OVERMAP_TEMPLATE, width: 69, height: 41 }; -#[allow(dead_code)] -const LEVEL_MAP: &str = - " -################################################################################ -#          ########################################################    ######### -#    @     ######    #########       ####     ###################        ####### -#          ####   g  #                          ###############            ##### -#          #### #    # #######       ####       #############                ### -##### ######### #    # #######       #########  ####    #####                ### -##### ######### ###### #######   o   #########  #### ## #####                ### -##                        ####       #########   ### ##         o            ### -##### ######### ###       ####       #######         ## #####                ### -##### ######### ###       ####       ####### #   ### ## #####                ### -##### ######### ###       ####       ####### #######    #####     o          ### -###          ## ###       ####       ####### ################                ### -###          ## ###   o   ###### ########### #   ############                ### -###          ## ###       ###### ###########     ###                         ### -###    %                  ###### ########### #   ###   !   ##                ### -###          ## ###              ######   ## #######       ##                ### -###          ## ###       ## ### #####     # ########################      ##### -###          ## ###       ## ### #####     # #   ######################    ##### -#### ## ####### ###### ##### ### ####          o ###########     ######    ##### -#### ## ####### ###### ####   ## ####        #   #########         ###### ###### -#    ## ####### ###### ####   ## ####        ############           ##### ###### -# g  ## ####### ###### ####   ##        %    ###########   o      o  #### #    # -#    ## ###            ####   ## ####        #   #######   ##    ##  ####   g  # -#######                  ####### ####            ######     !    !    ### #    # -######                     ##### ####        #   ######               ### ###### -#####                            #####     # ##########               ### ###### -#####           !           ### ######     # ##########      o##o     ### #   ## -#####                       ### #######   ## #   ######               ###   g ## -#   ##                     #### ######## ###   o #######  ^########^ #### #   ## -# g    #                 ###### ######## #####   #######  ^        ^ #### ###### -#   ##g####           ######    ######## ################           ##### ###### -#   ## ########## ##########    ######## #################         ######      # -#####   ######### ########## %  ######## ###################     ######## ##   # -#### ### ######## ##########    ######## #################### ##########   #   # -### ##### ######   #########    ########          ########### #######   # g#   # -### #####           ###############      ###      ########### #######   ####   # -### ##### ####       ############## ######## g  g ########### ####         # ^ # -#### ###^####         ############# ########      #####       ####      # g#   # -#####   ######       ###            ########      ##### g     ####   !  ####^^ # -#!%^## ###  ##           ########## ########  gg                 g         # > # -#!%^   ###  ###     ############### ########      ##### g     ####      # g#   # -# %^##  ^   ###     ############### ########      #####       ################## -################################################################################"; - const OVERMAP_TEMPLATE: &str = " -^^^^^^^^^^^^^^^^^^^^^^^^^^^≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈ -^^^^^^^^^^^^^^^^^^^^^^^^^^≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈...........≈≈≈≈≈≈≈ +^^^^^^^^^^^^^^^^^^^^^^^^^^^≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈ +^^^^^^^^^^^^^^^^^^^^^^^^^^≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈..≈......≈≈≈≈≈≈≈ ^^^^^^^^^^^^^^^....^^^^^^≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈.............≈≈≈≈≈ ^^^^^^^^^^^^^^...........≈≈≈≈≈≈≈≈≈........≈≈≈≈≈≈≈≈..............≈≈≈≈≈ ^^^^^^^^^^^^^............≈≈≈≈≈≈≈≈...........≈≈≈≈≈..............≈≈≈≈≈≈ diff --git a/src/map_builders/room_themer.rs b/src/map_builders/room_themer.rs index 2cc4ca1..1f6b5a9 100644 --- a/src/map_builders/room_themer.rs +++ b/src/map_builders/room_themer.rs @@ -1,6 +1,6 @@ use super::{ BuilderMap, MetaMapBuilder, Rect, TileType }; use crate::tile_walkable; -use crate::data::messages::{ +use crate::consts::messages::{ FEATURE_TREANTS, FEATURE_BARRACKS_GOBLIN, FEATURE_BARRACKS_KOBOLD, diff --git a/src/map_builders/town.rs b/src/map_builders/town.rs index c9cf3f9..f80e90a 100644 --- a/src/map_builders/town.rs +++ b/src/map_builders/town.rs @@ -1,6 +1,6 @@ use super::{ BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType, FillEdges }; use std::collections::HashSet; -use crate::data::names::*; +use crate::consts::names::*; use bracket_lib::prelude::*; pub fn town_builder( @@ -271,6 +271,7 @@ impl TownBuilder { building.1 + building.3 / 2 ); build_data.map.tiles[exit_idx] = TileType::DownStair; + build_data.spawn_list.push((exit_idx, "trapdoor".to_string())); let mut to_place: Vec<&str> = vec!["npc_miner", "npc_miner", "npc_guard", "prop_chair"]; self.random_building_spawn(building, build_data, rng, &mut to_place, exit_idx) } diff --git a/src/melee_combat_system.rs b/src/melee_combat_system.rs index cc63807..487feba 100644 --- a/src/melee_combat_system.rs +++ b/src/melee_combat_system.rs @@ -149,7 +149,7 @@ impl<'a> System<'a> for MeleeCombatSystem { let attack_verb = attack.1; // Get all offensive bonuses let d20 = rng.roll_dice(1, 20); - let attribute_hit_bonus = attacker_attributes.dexterity.bonus; + let attribute_hit_bonus = attacker_attributes.dexterity.modifier(); let skill_hit_bonus = gamesystem::skill_bonus(Skill::Melee, &*attacker_skills); let mut equipment_hit_bonus = weapon_info.hit_bonus; for (wielded, to_hit) in (&equipped, &to_hit).join() { @@ -187,7 +187,7 @@ impl<'a> System<'a> for MeleeCombatSystem { // Get armour class let bac = target_pools.bac; - let attribute_ac_bonus = target_attributes.dexterity.bonus / 2; + let attribute_ac_bonus = target_attributes.dexterity.modifier() / 2; let skill_ac_bonus = gamesystem::skill_bonus(Skill::Defence, &*target_skills); let mut armour_ac_bonus = 0; for (wielded, ac) in (&equipped, &ac).join() { @@ -245,19 +245,19 @@ impl<'a> System<'a> for MeleeCombatSystem { let mut attribute_damage_bonus = weapon_info.damage_bonus; match weapon_info.attribute { WeaponAttribute::Dexterity => { - attribute_damage_bonus += attacker_attributes.dexterity.bonus; + attribute_damage_bonus += attacker_attributes.dexterity.modifier(); } WeaponAttribute::Strength => { - attribute_damage_bonus += attacker_attributes.strength.bonus; + attribute_damage_bonus += attacker_attributes.strength.modifier(); } WeaponAttribute::Finesse => { if - attacker_attributes.dexterity.bonus > - attacker_attributes.strength.bonus + attacker_attributes.dexterity.modifier() > + attacker_attributes.strength.modifier() { - attribute_damage_bonus += attacker_attributes.dexterity.bonus; + attribute_damage_bonus += attacker_attributes.dexterity.modifier(); } else { - attribute_damage_bonus += attacker_attributes.strength.bonus; + attribute_damage_bonus += attacker_attributes.strength.modifier(); } } } @@ -295,11 +295,6 @@ impl<'a> System<'a> for MeleeCombatSystem { ); } } - - let pos = positions.get(wants_melee.target); - if let Some(pos) = pos { - particle_builder.damage_taken(pos.x, pos.y); - } add_effect( Some(entity), EffectType::Damage { amount: damage, damage_type: weapon_info.damage_type }, diff --git a/src/morgue.rs b/src/morgue.rs index b0160d9..1363ab9 100644 --- a/src/morgue.rs +++ b/src/morgue.rs @@ -9,7 +9,7 @@ use specs::prelude::*; use bracket_lib::prelude::*; use to_char; use std::collections::HashMap; -use crate::data::events::*; +use crate::consts::events::*; #[cfg(target_arch = "wasm32")] pub fn create_morgue_file(ecs: &World) { @@ -36,6 +36,7 @@ fn create_file_name(ecs: &World, morgue_dir: &str) -> String { let pools = ecs.read_storage::(); let pool = pools.get(*e).unwrap(); let class = match ecs.read_storage::().get(*e).unwrap().name { + Class::Unset => "classless", Class::Fighter => "fighter", Class::Wizard => "wizard", Class::Rogue => "rogue", @@ -47,7 +48,7 @@ fn create_file_name(ecs: &World, morgue_dir: &str) -> String { Ancestry::Dwarf => "dwarf", Ancestry::Gnome => "gnome", Ancestry::Catfolk => "catfolk", - Ancestry::NULL => "NULL", + Ancestry::Unset => "NULL", }; return format!( "{}/lv{}-{}-{}-{}.txt", @@ -64,6 +65,7 @@ fn create_morgue_string(ecs: &World) -> String { let mut morgue_info: String = Default::default(); let e = ecs.fetch::(); let class = match ecs.read_storage::().get(*e).unwrap().name { + Class::Unset => "classless", Class::Fighter => "fighter", Class::Wizard => "wizard", Class::Rogue => "rogue", @@ -75,7 +77,7 @@ fn create_morgue_string(ecs: &World) -> String { Ancestry::Dwarf => "dwarf", Ancestry::Gnome => "gnome", Ancestry::Catfolk => "catfolk", - Ancestry::NULL => "NULL", + Ancestry::Unset => "NULL", }; let pools = ecs.read_storage::(); let pool = pools.get(*e).unwrap(); @@ -127,19 +129,19 @@ fn draw_tombstone(ecs: &World, len: usize) -> String { pool.mana.max, "", "", - attr.strength.base + attr.strength.modifiers, - attr.strength.bonus, - attr.constitution.base + attr.constitution.modifiers, - attr.constitution.bonus, - attr.wisdom.base + attr.wisdom.modifiers, - attr.wisdom.bonus, + attr.strength.base + attr.strength.bonuses, + attr.strength.modifier(), + attr.constitution.base + attr.constitution.bonuses, + attr.constitution.modifier(), + attr.wisdom.base + attr.wisdom.bonuses, + attr.wisdom.modifier(), "", - attr.dexterity.base + attr.dexterity.modifiers, - attr.dexterity.bonus, - attr.intelligence.base + attr.intelligence.modifiers, - attr.intelligence.bonus, - attr.charisma.base + attr.charisma.modifiers, - attr.charisma.bonus, + attr.dexterity.base + attr.dexterity.bonuses, + attr.dexterity.modifier(), + attr.intelligence.base + attr.intelligence.bonuses, + attr.intelligence.modifier(), + attr.charisma.base + attr.charisma.bonuses, + attr.charisma.modifier(), "", "", map.name, @@ -162,10 +164,10 @@ fn draw_map(ecs: &World) -> String { if idx == map.xy_idx(point.x, point.y) { glyph_u16 = to_cp437('@'); } else if crate::spatial::has_tile_content(idx) { - let mut render_order = 0; + let mut render_order = 4; crate::spatial::for_each_tile_content(idx, |e| { if let Some(renderable) = ecs.read_storage::().get(e) { - if renderable.render_order >= render_order { + if renderable.render_order <= render_order { render_order = renderable.render_order; glyph_u16 = renderable.glyph; } diff --git a/src/particle_system.rs b/src/particle_system.rs index 69e12b7..1e12848 100644 --- a/src/particle_system.rs +++ b/src/particle_system.rs @@ -1,26 +1,27 @@ use super::{ ParticleLifetime, Position, Renderable, BTerm }; use bracket_lib::prelude::*; +use notan::prelude::*; use specs::prelude::*; -use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME }; +use crate::consts::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME }; /// Runs each tick, deleting particles who are past their expiry. // Should make an addition to this to also spawn delayed particles, // running through a list and removing the frame_time_ms from the // delay. When delay is <= 0, make a particle_builder.request for // the particle. -pub fn particle_ticker(ecs: &mut World, ctx: &BTerm) { +pub fn particle_ticker(ecs: &mut World, ctx: &App) { cull_dead_particles(ecs, ctx); create_delayed_particles(ecs, ctx); } -fn cull_dead_particles(ecs: &mut World, ctx: &BTerm) { +fn cull_dead_particles(ecs: &mut World, ctx: &App) { let mut dead_particles: Vec = Vec::new(); { // Age out particles let mut particles = ecs.write_storage::(); let entities = ecs.entities(); for (entity, mut particle) in (&entities, &mut particles).join() { - particle.lifetime_ms -= ctx.frame_time_ms; + particle.lifetime_ms -= ctx.timer.delta_f32() * 1000.0; if particle.lifetime_ms < 0.0 { dead_particles.push(entity); } @@ -39,18 +40,18 @@ pub fn check_queue(ecs: &World) -> bool { return false; } -fn create_delayed_particles(ecs: &mut World, ctx: &BTerm) { +fn create_delayed_particles(ecs: &mut World, ctx: &App) { let mut particle_builder = ecs.write_resource::(); let mut handled_particles: Vec = Vec::new(); for delayed_particle in particle_builder.delayed_requests.iter_mut() { - delayed_particle.delay -= ctx.frame_time_ms; + delayed_particle.delay -= ctx.timer.delta_f32() * 1000.0; if delayed_particle.delay < 0.0 { handled_particles.push(ParticleRequest { x: delayed_particle.particle.x, y: delayed_particle.particle.y, fg: delayed_particle.particle.fg, - bg: delayed_particle.particle.bg, glyph: delayed_particle.particle.glyph, + sprite: delayed_particle.particle.sprite.clone(), lifetime: delayed_particle.particle.lifetime, }); } @@ -80,12 +81,7 @@ fn create_delayed_particles(ecs: &mut World, ctx: &BTerm) { .insert(p, Position { x: handled.x, y: handled.y }) .expect("Could not insert position"); renderables - .insert(p, Renderable { - fg: handled.fg, - bg: handled.bg, - glyph: handled.glyph, - render_order: 0, - }) + .insert(p, Renderable::new(handled.glyph, handled.sprite, handled.fg, 0)) .expect("Could not insert renderables"); particles .insert(p, ParticleLifetime { lifetime_ms: handled.lifetime }) @@ -98,8 +94,8 @@ pub struct ParticleRequest { x: i32, y: i32, fg: RGB, - bg: RGB, glyph: FontCharType, + sprite: String, lifetime: f32, } @@ -126,11 +122,11 @@ impl ParticleBuilder { x: i32, y: i32, fg: RGB, - bg: RGB, glyph: FontCharType, + sprite: String, lifetime: f32 ) { - self.requests.push(ParticleRequest { x, y, fg, bg, glyph, lifetime }); + self.requests.push(ParticleRequest { x, y, fg, glyph, sprite, lifetime }); } pub fn delay( @@ -138,150 +134,43 @@ impl ParticleBuilder { x: i32, y: i32, fg: RGB, - bg: RGB, glyph: FontCharType, + sprite: String, lifetime: f32, delay: f32 ) { self.delayed_requests.push(DelayedParticleRequest { delay: delay, - particle: ParticleRequest { x, y, fg, bg, glyph, lifetime }, + particle: ParticleRequest { x, y, fg, glyph, sprite, lifetime }, }); } + // MASSIVE TODO: Animate these, or make them random. PLACEHOLDER. pub fn damage_taken(&mut self, x: i32, y: i32) { - self.request( - x, - y, - RGB::named(ORANGE), - RGB::named(BLACK), - to_cp437('‼'), - DEFAULT_PARTICLE_LIFETIME - ); + self.request(x, y, RGB::named(RED), to_cp437('‼'), "slash1".to_string(), 75.0); + self.delay(x, y, RGB::named(RED), to_cp437('‼'), "slash2".to_string(), 75.0, 75.0); + self.delay(x, y, RGB::named(RED), to_cp437('‼'), "slash3".to_string(), 75.0, 150.0); } - pub fn attack_miss(&mut self, x: i32, y: i32) { self.request( x, y, RGB::named(CYAN), - RGB::named(BLACK), to_cp437('‼'), + "slash1".to_string(), DEFAULT_PARTICLE_LIFETIME ); } - pub fn kick(&mut self, x: i32, y: i32) { self.request( x, y, RGB::named(CHOCOLATE), - RGB::named(BLACK), to_cp437('‼'), + "kick".to_string(), SHORT_PARTICLE_LIFETIME ); } - - // Makes a particle request in the shape of an 'x'. Sort of. - #[allow(dead_code)] - pub fn request_star( - &mut self, - x: i32, - y: i32, - fg: RGB, - bg: RGB, - glyph: FontCharType, - lifetime: f32, - secondary_fg: RGB - ) { - let eighth_l = lifetime / 8.0; - let quarter_l = eighth_l * 2.0; - self.request(x, y, fg, bg, glyph, lifetime); - self.delay( - x + 1, - y + 1, - secondary_fg.lerp(bg, 0.8), - bg, - to_cp437('/'), - quarter_l, - eighth_l - ); - self.delay( - x + 1, - y - 1, - secondary_fg.lerp(bg, 0.6), - bg, - to_cp437('\\'), - quarter_l, - quarter_l - ); - self.delay( - x - 1, - y - 1, - secondary_fg.lerp(bg, 0.2), - bg, - to_cp437('/'), - quarter_l, - eighth_l * 3.0 - ); - self.delay( - x - 1, - y + 1, - secondary_fg.lerp(bg, 0.4), - bg, - to_cp437('\\'), - quarter_l, - lifetime - ); - } - - // Makes a rainbow particle request in the shape of an 'x'. Sort of. - #[allow(dead_code)] - pub fn request_rainbow_star(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) { - let bg = RGB::named(BLACK); - let eighth_l = lifetime / 8.0; - let quarter_l = eighth_l * 2.0; - let half_l = quarter_l * 2.0; - - self.request(x, y, RGB::named(CYAN), bg, glyph, lifetime); - self.delay(x + 1, y + 1, RGB::named(RED), bg, to_cp437('\\'), half_l, eighth_l); - self.delay(x + 1, y - 1, RGB::named(ORANGE), bg, to_cp437('/'), half_l, quarter_l); - self.delay(x - 1, y - 1, RGB::named(GREEN), bg, to_cp437('\\'), half_l, eighth_l * 3.0); - self.delay(x - 1, y + 1, RGB::named(YELLOW), bg, to_cp437('/'), half_l, half_l); - } - - // Makes a rainbow particle request. Sort of. - #[allow(dead_code)] - pub fn request_rainbow(&mut self, x: i32, y: i32, glyph: FontCharType, lifetime: f32) { - let bg = RGB::named(BLACK); - let eighth_l = lifetime / 8.0; - - self.request(x, y, RGB::named(RED), bg, glyph, eighth_l); - self.delay(x, y, RGB::named(ORANGE), bg, glyph, eighth_l, eighth_l); - self.delay(x, y, RGB::named(YELLOW), bg, glyph, eighth_l, eighth_l * 2.0); - self.delay(x, y, RGB::named(GREEN), bg, glyph, eighth_l, eighth_l * 3.0); - self.delay(x, y, RGB::named(BLUE), bg, glyph, eighth_l, eighth_l * 4.0); - self.delay(x, y, RGB::named(INDIGO), bg, glyph, eighth_l, eighth_l * 5.0); - self.delay(x, y, RGB::named(VIOLET), bg, glyph, eighth_l, eighth_l * 6.0); - } - - /// Makes a particle request in the shape of a +. - #[allow(dead_code)] - pub fn request_plus( - &mut self, - x: i32, - y: i32, - fg: RGB, - bg: RGB, - glyph: FontCharType, - lifetime: f32 - ) { - self.request(x, y, fg, bg, glyph, lifetime * 2.0); - self.request(x + 1, y, fg, bg, to_cp437('─'), lifetime); - self.request(x - 1, y, fg, bg, to_cp437('─'), lifetime); - self.request(x, y + 1, fg, bg, to_cp437('│'), lifetime); - self.request(x, y - 1, fg, bg, to_cp437('│'), lifetime); - } } pub struct ParticleSpawnSystem {} @@ -305,12 +194,15 @@ impl<'a> System<'a> for ParticleSpawnSystem { .insert(p, Position { x: new_particle.x, y: new_particle.y }) .expect("Could not insert position"); renderables - .insert(p, Renderable { - fg: new_particle.fg, - bg: new_particle.bg, - glyph: new_particle.glyph, - render_order: 0, - }) + .insert( + p, + Renderable::new( + new_particle.glyph, + new_particle.sprite.clone(), + new_particle.fg, + 0 + ) + ) .expect("Could not insert renderables"); particles .insert(p, ParticleLifetime { lifetime_ms: new_particle.lifetime }) diff --git a/src/player.rs b/src/player.rs index dd8ecf3..a0139d6 100644 --- a/src/player.rs +++ b/src/player.rs @@ -30,15 +30,20 @@ use super::{ Viewshed, WantsToMelee, WantsToPickupItem, + WantsToAssignKey, get_dest, Destination, DamageType, + effects::sound, }; use bracket_lib::prelude::*; use specs::prelude::*; use std::cmp::{ max, min }; -use crate::data::events::*; -use crate::data::ids::*; +use crate::consts::events::*; +use crate::consts::ids::*; +use crate::gui::with_article; +use notan::prelude::*; +use std::collections::HashMap; pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { let mut positions = ecs.write_storage::(); @@ -89,6 +94,7 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { if door.open == true { let renderables = ecs.read_storage::(); if multiple_tile_content { + sound::door_resist(destination_idx); if let Some(name) = names.get(potential_target) { gamelog::Logger ::new() @@ -99,7 +105,8 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { .append("is blocked.") .log(); } - } else if rng.roll_dice(1, 6) + attributes.strength.bonus < 2 { + } else if rng.roll_dice(1, 6) + attributes.strength.modifier() < 2 { + sound::door_resist(destination_idx); if let Some(name) = names.get(potential_target) { gamelog::Logger ::new() @@ -111,13 +118,18 @@ pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { .log(); } } else { + sound::door_close(destination_idx); door.open = false; - blocks_visibility - .insert(potential_target, BlocksVisibility {}) - .expect("Unable to insert BlocksVisibility."); - blocks_movement - .insert(potential_target, BlocksTile {}) - .expect("Unable to insert BlocksTile."); + if door.blocks_vis { + blocks_visibility + .insert(potential_target, BlocksVisibility {}) + .expect("Unable to insert BlocksVisibility."); + } + if door.blocks_move { + blocks_movement + .insert(potential_target, BlocksTile {}) + .expect("Unable to insert BlocksTile."); + } if let Some(name) = names.get(potential_target) { gamelog::Logger ::new() @@ -132,7 +144,7 @@ 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.swap(); door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); } result = RunState::Ticking; @@ -201,7 +213,8 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState { if let Some(door) = door { if door.open == false { let renderables = ecs.read_storage::(); - if rng.roll_dice(1, 6) + attributes.strength.bonus < 2 { + if rng.roll_dice(1, 6) + attributes.strength.modifier() < 2 { + sound::door_resist(destination_idx); if let Some(name) = names.get(potential_target) { gamelog::Logger ::new() @@ -213,6 +226,7 @@ pub fn open(i: i32, j: i32, ecs: &mut World) -> RunState { .log(); } } else { + sound::door_open(destination_idx); door.open = true; blocks_visibility.remove(potential_target); blocks_movement.remove(potential_target); @@ -229,7 +243,7 @@ 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.swap(); door_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); } result = RunState::Ticking; @@ -330,15 +344,15 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState { None, EffectType::Particle { glyph: to_cp437('‼'), + sprite: "gnome".to_string(), // FIXME: REMOVE THE GNOMES fg: RGB::named(CHOCOLATE), - bg: RGB::named(BLACK), lifespan: 150.0, delay: 0.0, }, Targets::Entity { target: potential_target } ); // ~33% chance of breaking it down + str - if rng.roll_dice(1, 10) + attributes.strength.bonus > 6 { + if rng.roll_dice(1, 10) + attributes.strength.modifier() > 6 { gamelog::Logger ::new() .append("As you kick the") @@ -390,8 +404,8 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState { None, EffectType::Particle { glyph: to_cp437('‼'), + sprite: "gnome".to_string(), // FIXME: REMOVE THE GNOMES fg: RGB::named(CHOCOLATE), - bg: RGB::named(BLACK), lifespan: 150.0, delay: 0.0, }, @@ -491,7 +505,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> RunState } let door = doors.get_mut(potential_target); if let Some(door) = door { - if door.open == false { + if door.open == false && door.blocks_move { if let Some(name) = names.get(potential_target) { let colour = if let Some(_) = ecs.read_storage::().get(potential_target) @@ -560,11 +574,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"); for i in 0..seen_items.len() { if i > 0 && i < seen_items.len() { - logger = logger.append(", a"); + logger = logger.append(", "); } logger = logger .colour(seen_items[i].1) - .append_n(&seen_items[i].0) + .append_n(with_article(&seen_items[i].0)) .colour(WHITE); } logger.period().log(); @@ -633,7 +647,9 @@ fn get_item(ecs: &mut World) -> RunState { return RunState::AwaitingInput; } Some(item) => { + let mut assignkey = ecs.write_storage::(); let mut pickup = ecs.write_storage::(); + assignkey.insert(item, WantsToAssignKey {}).expect("Unable to insert WantsToAssignKey"); pickup .insert(*player_entity, WantsToPickupItem { collected_by: *player_entity, item }) .expect("Unable to insert want to pickup item."); @@ -642,136 +658,118 @@ fn get_item(ecs: &mut World) -> RunState { } } -pub fn player_input(gs: &mut State, ctx: &mut BTerm, on_overmap: bool) -> RunState { - match ctx.key { - None => { - return RunState::AwaitingInput; - } - Some(key) => - match key { - // Cardinals - VirtualKeyCode::Left | VirtualKeyCode::Numpad4 | VirtualKeyCode::H => { - return try_move_player(-1, 0, &mut gs.ecs); - } - VirtualKeyCode::Right | VirtualKeyCode::Numpad6 | VirtualKeyCode::L => { - return try_move_player(1, 0, &mut gs.ecs); - } - VirtualKeyCode::Up | VirtualKeyCode::Numpad8 | VirtualKeyCode::K => { - return try_move_player(0, -1, &mut gs.ecs); - } - VirtualKeyCode::Down | VirtualKeyCode::Numpad2 | VirtualKeyCode::J => { - return try_move_player(0, 1, &mut gs.ecs); - } - // Diagonals - VirtualKeyCode::Numpad9 | VirtualKeyCode::U => { - return try_move_player(1, -1, &mut gs.ecs); - } - VirtualKeyCode::Numpad7 | VirtualKeyCode::Y => { - return try_move_player(-1, -1, &mut gs.ecs); - } - VirtualKeyCode::Numpad3 | VirtualKeyCode::N => { - return try_move_player(1, 1, &mut gs.ecs); - } - VirtualKeyCode::Numpad1 | VirtualKeyCode::B => { - return try_move_player(-1, 1, &mut gs.ecs); - } - // id - VirtualKeyCode::Period => { - if ctx.shift { - let dest = try_change_level(&mut gs.ecs, false); - let curr_map_id = gs.ecs.fetch::().id; - return match dest { - // If we have no destination, do nothing. - Destination::None => RunState::AwaitingInput, - // If we want to go to the next level, go to the up-stair tile of id + 1. - Destination::NextLevel => - RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), - // If we want to go to the previous level, go to the down-stair tile of id - 1. - Destination::PreviousLevel => - RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), - Destination::ToLocal(id) => - RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), - Destination::ToOvermap(id) => - RunState::GoToLevel(id, TileType::ToOvermap(id)), - }; - } else { - return skip_turn(&mut gs.ecs); // (Wait a turn) - } - } - VirtualKeyCode::Comma => { - if ctx.shift { - let dest = try_change_level(&mut gs.ecs, true); - let curr_map_id = gs.ecs.fetch::().id; - return match dest { - Destination::None => RunState::AwaitingInput, - Destination::NextLevel => - RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), - Destination::PreviousLevel => - RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), - Destination::ToLocal(id) => - RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), - Destination::ToOvermap(id) => - RunState::GoToLevel(id, TileType::ToOvermap(id)), - }; - } - } - VirtualKeyCode::Slash => { - if ctx.shift { - return RunState::HelpScreen; - } - } - VirtualKeyCode::NumpadDecimal => { - return skip_turn(&mut gs.ecs); - } +fn try_descend(ecs: &mut World) -> RunState { + let dest = try_change_level(ecs, false); + let curr_map_id = ecs.fetch::().id; + return match dest { + Destination::None => RunState::AwaitingInput, + Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), + Destination::PreviousLevel => RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), + Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), + Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)), + }; +} +fn try_ascend(ecs: &mut World) -> RunState { + let dest = try_change_level(ecs, true); + let curr_map_id = ecs.fetch::().id; + return match dest { + Destination::None => RunState::AwaitingInput, + Destination::NextLevel => RunState::GoToLevel(curr_map_id + 1, TileType::UpStair), + Destination::PreviousLevel => RunState::GoToLevel(curr_map_id - 1, TileType::DownStair), + Destination::ToLocal(id) => RunState::GoToLevel(ID_OVERMAP, TileType::ToLocal(id)), + Destination::ToOvermap(id) => RunState::GoToLevel(id, TileType::ToOvermap(id)), + }; +} - // Items - VirtualKeyCode::C => { - if !on_overmap { - return RunState::ActionWithDirection { function: try_door }; - } +pub fn player_input(gs: &mut State, ctx: &mut App, on_overmap: bool) -> RunState { + let key = &ctx.keyboard; + // Movement + for keycode in key.pressed.iter() { + match *keycode { + KeyCode::Numpad1 | KeyCode::B => { + return try_move_player(-1, 1, &mut gs.ecs); + } + KeyCode::Numpad2 | KeyCode::Down | KeyCode::J => { + return try_move_player(0, 1, &mut gs.ecs); + } + KeyCode::Numpad3 | KeyCode::N => { + return try_move_player(1, 1, &mut gs.ecs); + } + KeyCode::Numpad4 | KeyCode::Left | KeyCode::H => { + return try_move_player(-1, 0, &mut gs.ecs); + } + KeyCode::Numpad6 | KeyCode::Right | KeyCode::L => { + return try_move_player(1, 0, &mut gs.ecs); + } + KeyCode::Numpad7 | KeyCode::Y => { + return try_move_player(-1, -1, &mut gs.ecs); + } + KeyCode::Numpad8 | KeyCode::Up | KeyCode::K => { + return try_move_player(0, -1, &mut gs.ecs); + } + KeyCode::Numpad9 | KeyCode::U => { + return try_move_player(1, -1, &mut gs.ecs); + } + KeyCode::Period => { + if key.shift() { + return try_descend(&mut gs.ecs); } - VirtualKeyCode::O => { - if !on_overmap { - return RunState::ActionWithDirection { function: open }; - } - } - VirtualKeyCode::F => { - if !on_overmap { - return RunState::ActionWithDirection { function: kick }; - } - } - VirtualKeyCode::G => { - return get_item(&mut gs.ecs); - } - VirtualKeyCode::I => { - return RunState::ShowInventory; - } - VirtualKeyCode::D => { - return RunState::ShowDropItem; - } - VirtualKeyCode::R => { - return RunState::ShowRemoveItem; - } - // Other - VirtualKeyCode::Minus => { - return RunState::ShowCheatMenu; - } - VirtualKeyCode::Escape => { - return RunState::SaveGame; - } - VirtualKeyCode::X => { - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds( - &gs.ecs, - ctx - ); - let ppos = gs.ecs.fetch::(); - let (x, y) = (ppos.x + x_offset - min_x, ppos.y + y_offset - min_y); - return RunState::Farlook { x, y }; - } - _ => { - return RunState::AwaitingInput; + return skip_turn(&mut gs.ecs); + } + KeyCode::Comma => { + if key.shift() { + return try_ascend(&mut gs.ecs); } } + KeyCode::Slash => { + if key.shift() { + return RunState::HelpScreen; + } + } + KeyCode::C => { + if !on_overmap { + return RunState::ActionWithDirection { function: try_door }; + } + } + KeyCode::O => { + if !on_overmap { + return RunState::ActionWithDirection { function: open }; + } + } + KeyCode::F => { + if !on_overmap { + return RunState::ActionWithDirection { function: kick }; + } + } + KeyCode::G => { + return get_item(&mut gs.ecs); + } + KeyCode::I => { + return RunState::ShowInventory; + } + KeyCode::D => { + return RunState::ShowDropItem; + } + KeyCode::R => { + return RunState::ShowRemoveItem; + } + KeyCode::Minus => { + return RunState::ShowCheatMenu; + } + KeyCode::Escape => { + return RunState::SaveGame; + } + KeyCode::X => { + let bounds = get_screen_bounds(&gs.ecs, false); + let ppos = gs.ecs.fetch::(); + let (x, y) = ( + ppos.x + bounds.x_offset - bounds.min_x, + ppos.y + bounds.y_offset - bounds.min_y, + ); + return RunState::Farlook { x, y }; + } + _ => {} + } } return RunState::AwaitingInput; } @@ -781,6 +779,18 @@ fn try_change_level(ecs: &mut World, backtracking: bool) -> Destination { let map = ecs.fetch::(); let player_idx = map.xy_idx(player_pos.x, player_pos.y); let this_tile = map.tiles[player_idx]; + let mut blocked = false; + crate::spatial::for_each_tile_content(player_idx, |potential| { + if let Some(is_door) = ecs.read_storage::().get(potential) { + if is_door.open == false { + blocked = true; + gamelog::Logger::new().append("The way is blocked.").log(); + } + } + }); + if blocked { + return Destination::None; + } return get_dest(this_tile, backtracking); } diff --git a/src/raws/item_structs.rs b/src/raws/item_structs.rs index 897d48d..742863a 100644 --- a/src/raws/item_structs.rs +++ b/src/raws/item_structs.rs @@ -6,6 +6,8 @@ pub struct Item { pub id: String, pub name: Name, pub renderable: Option, + pub avatar: Option, + pub class: String, pub weight: Option, pub value: Option, pub equip: Option, @@ -30,9 +32,16 @@ pub struct Equippable { #[derive(Deserialize, Debug)] pub struct Renderable { pub glyph: String, + pub sprite: String, + pub alt: Option, pub fg: String, - pub bg: String, + pub fg_alt: Option, pub order: i32, + pub order_alt: Option, + pub x: Option, + pub x_alt: Option, + pub y: Option, + pub y_alt: Option, } #[derive(Deserialize, Debug)] diff --git a/src/raws/prop_structs.rs b/src/raws/prop_structs.rs index 845c67c..86e9341 100644 --- a/src/raws/prop_structs.rs +++ b/src/raws/prop_structs.rs @@ -9,4 +9,13 @@ pub struct Prop { pub renderable: Option, pub flags: Option>, pub effects: Option>, + pub door: Option, +} + +#[derive(Deserialize, Debug)] +pub struct Door { + pub open: bool, + pub locked: bool, + pub blocks_vis: bool, + pub blocks_move: bool, } diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index 813dbe2..d612da7 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -4,8 +4,8 @@ use crate::gamesystem::*; use crate::gui::Ancestry; use crate::random_table::RandomTable; use crate::config::CONFIG; -use crate::data::visuals::BLOODSTAIN_COLOUR; -use crate::data::entity::DEFAULT_VIEWSHED_STANDARD; +use crate::consts::visuals::BLOODSTAIN_COLOUR; +use crate::consts::entity::DEFAULT_VIEWSHED_STANDARD; use bracket_lib::prelude::*; use specs::prelude::*; use specs::saveload::{ MarkedBuilder, SimpleMarker }; @@ -53,11 +53,6 @@ macro_rules! apply_flags { "BLOCKS_VISIBILITY" => $eb = $eb.with(BlocksVisibility {}), "ENTRY_TRIGGER" => $eb = $eb.with(EntryTrigger {}), "SINGLE_ACTIVATION" => $eb = $eb.with(SingleActivation {}), - "DOOR" => { - $eb = $eb.with(Door { open: false }); - $eb = $eb.with(BlocksVisibility {}); - $eb = $eb.with(BlocksTile {}); - } // --- EFFECT FLAGS --- "FOOD" => $eb = $eb.with(ProvidesNutrition {}), "CONSUMABLE" => $eb = $eb.with(Consumable {}), @@ -66,6 +61,7 @@ macro_rules! apply_flags { "IDENTIFY" => $eb = $eb.with(ProvidesIdentify {}), "DIGGER" => $eb = $eb.with(Digger {}), "MAGICMAP" => $eb = $eb.with(MagicMapper {}), + "STACKABLE" => $eb = $eb.with(Stackable {}), // CAN BE DESTROYED BY DAMAGE "DESTRUCTIBLE" => $eb = $eb.with(Destructible {}), // --- EQUIP SLOTS --- @@ -281,6 +277,7 @@ pub fn spawn_named_item( if known_beatitude && !identified_items.contains(&item_template.name.name) { 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(dm); // -- DROP EVERYTHING THAT INVOLVES THE ECS BEFORE THIS POINT --- @@ -293,12 +290,30 @@ pub fn spawn_named_item( eb = eb.with(Item { weight: item_template.weight.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); + if needs_key { + eb = eb.with(WantsToAssignKey {}); + } if let Some(renderable) = &item_template.renderable { eb = eb.with(get_renderable_component(renderable)); } + if let Some(avatar) = &item_template.avatar { + eb = eb.with(Avatar::new(avatar.clone())); + } // BEATITUDE let buc = if let Some(buc_status) = buc { buc_status @@ -392,6 +407,7 @@ pub fn spawn_named_mob( if raws.mob_index.contains_key(key) { let mob_template = &raws.raws.mobs[raws.mob_index[key]]; let mut player_level = 1; + let needs_key; { let pools = ecs.read_storage::(); let player_entity = ecs.fetch::(); @@ -399,12 +415,15 @@ pub fn spawn_named_mob( if let Some(pool) = player_pool { player_level = pool.level; } + needs_key = is_player_owned(&player_entity, &pos); } - let mut eb; // New entity with a position, name, combatstats, and viewshed eb = ecs.create_entity().marked::>(); 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(Viewshed { visible_tiles: Vec::new(), @@ -445,36 +464,29 @@ pub fn spawn_named_mob( } // Setup combat stats - let mut attr = Attributes { - strength: Attribute { base: 10, modifiers: 0, bonus: 0 }, - dexterity: Attribute { base: 10, modifiers: 0, bonus: 0 }, - constitution: Attribute { base: 10, modifiers: 0, bonus: 0 }, - intelligence: Attribute { base: 10, modifiers: 0, bonus: 0 }, - wisdom: Attribute { base: 10, modifiers: 0, bonus: 0 }, - charisma: Attribute { base: 10, modifiers: 0, bonus: 0 }, - }; + let mut attr = Attributes::default(); let mut mob_con = 10; let mut mob_int = 10; if let Some(attributes) = &mob_template.attributes { if let Some(str) = attributes.str { - attr.strength = Attribute { base: str, modifiers: 0, bonus: attr_bonus(str) }; + attr.strength = Attribute::new(str); } if let Some(dex) = attributes.dex { - attr.strength = Attribute { base: dex, modifiers: 0, bonus: attr_bonus(dex) }; + attr.strength = Attribute::new(dex); } if let Some(con) = attributes.con { - attr.constitution = Attribute { base: con, modifiers: 0, bonus: attr_bonus(con) }; + attr.constitution = Attribute::new(con); mob_con = con; } if let Some(int) = attributes.int { - attr.intelligence = Attribute { base: int, modifiers: 0, bonus: attr_bonus(int) }; + attr.intelligence = Attribute::new(int); mob_int = int; } if let Some(wis) = attributes.wis { - attr.wisdom = Attribute { base: wis, modifiers: 0, bonus: attr_bonus(wis) }; + attr.wisdom = Attribute::new(wis); } if let Some(cha) = attributes.cha { - attr.charisma = Attribute { base: cha, modifiers: 0, bonus: attr_bonus(cha) }; + attr.charisma = Attribute::new(cha); } } eb = eb.with(attr); @@ -632,10 +644,18 @@ pub fn spawn_named_prop( pos: SpawnType ) -> Option { if raws.prop_index.contains_key(key) { + let needs_key; + { + let player_entity = ecs.fetch::(); + needs_key = is_player_owned(&player_entity, &pos); + } // ENTITY BUILDER PREP let prop_template = &raws.raws.props[raws.prop_index[key]]; let mut eb = ecs.create_entity().marked::>(); eb = spawn_position(pos, eb, key, raws); + if needs_key { + eb = eb.with(WantsToAssignKey {}); + } // APPLY MANDATORY COMPONENTS FOR A PROP: // - Name // - Prop {} @@ -656,6 +676,23 @@ pub fn spawn_named_prop( if let Some(effects_list) = &prop_template.effects { apply_effects!(effects_list, eb); } + + if let Some(door) = &prop_template.door { + eb = eb.with(Door { + open: door.open, + locked: door.locked, + blocks_vis: door.blocks_vis, + blocks_move: door.blocks_move, + }); + if !door.open { + if door.blocks_vis { + eb = eb.with(BlocksVisibility {}); + } + if door.blocks_move { + eb = eb.with(BlocksTile {}); + } + } + } // BUILD THE ENTITY return Some(eb.build()); } @@ -686,14 +723,70 @@ fn spawn_position<'a>( 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( renderable: &super::item_structs::Renderable ) -> crate::components::Renderable { + let glyph = to_cp437(renderable.glyph.chars().next().unwrap()); + let sprite = renderable.sprite.clone(); + let sprite_alt = if let Some(sprite_alt) = &renderable.alt { + Some(sprite_alt.clone()) + } else { + None + }; + let fg = RGB::from_hex(&renderable.fg).expect("Invalid RGB"); + let fg_alt = if let Some(fg_alt) = &renderable.fg_alt { + Some(RGB::from_hex(&fg_alt).expect("Invalid RGB")) + } else { + None + }; + let render_order = renderable.order; + let render_order_alt = if let Some(order_alt) = renderable.order_alt { + Some(order_alt) + } else { + None + }; + let offset_x = if let Some(x) = renderable.x { x } else { 0.0 }; + let offset_y = if let Some(y) = renderable.y { -y } else { 0.0 }; + + let offset_alt: Option<(f32, f32)> = if + renderable.x_alt.is_some() || + renderable.y_alt.is_some() + { + Some(( + if let Some(x) = renderable.x_alt { x } else { 0.0 }, + if let Some(y) = renderable.y_alt { -y } else { 0.0 }, + )) + } else { + None + }; + crate::components::Renderable { - glyph: to_cp437(renderable.glyph.chars().next().unwrap()), - fg: RGB::from_hex(&renderable.fg).expect("Invalid RGB"), - bg: RGB::from_hex(&renderable.bg).expect("Invalid RGB"), - render_order: renderable.order, + glyph, + sprite, + sprite_alt, + fg, + fg_alt, + render_order, + render_order_alt, + offset: (offset_x, offset_y), + offset_alt, } } @@ -1017,7 +1110,7 @@ fn get_ancestry_string(ancestry: Ancestry) -> &'static str { Ancestry::Gnome => { return "gnome"; } - Ancestry::NULL => { + Ancestry::Unset => { return "NULL"; } } @@ -1026,35 +1119,41 @@ fn get_ancestry_string(ancestry: Ancestry) -> &'static str { fn parse_particle_line(n: &str) -> SpawnParticleLine { let tokens: Vec<_> = n.split(';').collect(); SpawnParticleLine { - glyph: to_cp437(tokens[0].chars().next().unwrap()), - tail_glyph: to_cp437(tokens[1].chars().next().unwrap()), - colour: RGB::from_hex(tokens[2]).expect("Invalid RGB"), - lifetime_ms: tokens[3].parse::().unwrap(), - trail_colour: RGB::from_hex(tokens[4]).expect("Invalid trail RGB"), - trail_lifetime_ms: tokens[5].parse::().unwrap(), + sprite: tokens[0].to_string(), + tail_sprite: tokens[1].to_string(), + glyph: to_cp437(tokens[2].chars().next().unwrap()), + tail_glyph: to_cp437(tokens[3].chars().next().unwrap()), + colour: RGB::from_hex(tokens[4]).expect("Invalid RGB"), + lifetime_ms: tokens[5].parse::().unwrap(), + trail_colour: RGB::from_hex(tokens[6]).expect("Invalid trail RGB"), + trail_lifetime_ms: tokens[7].parse::().unwrap(), } } fn parse_particle(n: &str) -> SpawnParticleSimple { let tokens: Vec<_> = n.split(';').collect(); SpawnParticleSimple { - glyph: to_cp437(tokens[0].chars().next().unwrap()), - colour: RGB::from_hex(tokens[1]).expect("Invalid RGB"), - lifetime_ms: tokens[2].parse::().unwrap(), + sprite: tokens[0].to_string(), + glyph: to_cp437(tokens[1].chars().next().unwrap()), + colour: RGB::from_hex(tokens[2]).expect(&format!("Invalid RGB: {}", n)), + lifetime_ms: tokens[3].parse::().unwrap(), } } fn parse_particle_burst(n: &str) -> SpawnParticleBurst { let tokens: Vec<_> = n.split(';').collect(); SpawnParticleBurst { - glyph: to_cp437(tokens[0].chars().next().unwrap()), - head_glyph: to_cp437(tokens[1].chars().next().unwrap()), - tail_glyph: to_cp437(tokens[2].chars().next().unwrap()), - colour: RGB::from_hex(tokens[3]).expect("Invalid RGB"), - lerp: RGB::from_hex(tokens[4]).expect("Invalid LERP RGB"), - lifetime_ms: tokens[5].parse::().unwrap(), - trail_colour: RGB::from_hex(tokens[6]).expect("Invalid trail RGB"), - trail_lifetime_ms: tokens[7].parse::().unwrap(), + sprite: tokens[0].to_string(), + head_sprite: tokens[1].to_string(), + tail_sprite: tokens[2].to_string(), + glyph: to_cp437(tokens[3].chars().next().unwrap()), + head_glyph: to_cp437(tokens[4].chars().next().unwrap()), + tail_glyph: to_cp437(tokens[5].chars().next().unwrap()), + colour: RGB::from_hex(tokens[6]).expect("Invalid RGB"), + lerp: RGB::from_hex(tokens[7]).expect("Invalid LERP RGB"), + lifetime_ms: tokens[8].parse::().unwrap(), + trail_colour: RGB::from_hex(tokens[9]).expect("Invalid trail RGB"), + trail_lifetime_ms: tokens[10].parse::().unwrap(), } } diff --git a/src/saveload_system.rs b/src/saveload_system.rs index 362b35f..e3d49a7 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -1,6 +1,5 @@ use super::components::*; use bracket_lib::prelude::*; -use specs::error::NoError; use specs::prelude::*; use specs::saveload::{ DeserializeComponents, @@ -12,11 +11,12 @@ use specs::saveload::{ use std::fs; use std::fs::File; use std::path::Path; +use std::convert::Infallible; macro_rules! serialize_individually { ($ecs:expr, $ser:expr, $data:expr, $($type:ty),*) => { $( - SerializeComponents::>::serialize( + SerializeComponents::>::serialize( &( $ecs.read_storage::<$type>(), ), &$data.0, &$data.1, @@ -28,7 +28,13 @@ macro_rules! serialize_individually { } #[cfg(target_arch = "wasm32")] -pub fn save_game(_ecs: &mut World) {} +pub fn save_game(_ecs: &mut World) { + console::log( + "Unfortunately, saving isn't supported in any easy way on the web. Sorry! + You can, at least, save your morgue file after dying - it'll be written + to the log, and just needs saving into a text file." + ) +} #[cfg(not(target_arch = "wasm32"))] pub fn save_game(ecs: &mut World) { @@ -55,8 +61,8 @@ pub fn save_game(ecs: &mut World) { { let data = (ecs.entities(), ecs.read_storage::>()); - let writer = File::create("./savegame.json").unwrap(); - let mut serializer = serde_json::Serializer::new(writer); + let writer = File::create("./savegame.bin").unwrap(); + let mut serializer = bincode::Serializer::new(writer, bincode::options()); serialize_individually!( ecs, serializer, @@ -64,6 +70,7 @@ pub fn save_game(ecs: &mut World) { AOE, ArmourClassBonus, Attributes, + Avatar, Beatitude, Bleeds, Blind, @@ -98,6 +105,7 @@ pub fn save_game(ecs: &mut World) { IntrinsicChanged, Intrinsics, Item, + Key, KnownSpells, LootTable, MagicItem, @@ -127,17 +135,21 @@ pub fn save_game(ecs: &mut World) { SpawnParticleBurst, SpawnParticleLine, SpawnParticleSimple, + Stackable, TakingTurn, Telepath, ToHitBonus, Viewshed, Charges, WantsToApproach, + WantsToAssignKey, + WantsToDelete, WantsToDropItem, WantsToFlee, WantsToMelee, WantsToPickupItem, WantsToRemoveItem, + WantsToRemoveKey, WantsToUseItem, SerializationHelper, DMSerializationHelper @@ -150,13 +162,13 @@ pub fn save_game(ecs: &mut World) { } pub fn does_save_exist() -> bool { - Path::new("./savegame.json").exists() + Path::new("./savegame.bin").exists() } macro_rules! deserialize_individually { ($ecs:expr, $de:expr, $data:expr, $($type:ty),*) => { $( - DeserializeComponents::::deserialize( + DeserializeComponents::::deserialize( &mut ( &mut $ecs.write_storage::<$type>(), ), &$data.0, // entities &mut $data.1, // marker @@ -180,8 +192,8 @@ pub fn load_game(ecs: &mut World) { } } - let data = fs::read_to_string("./savegame.json").unwrap(); - let mut de = serde_json::Deserializer::from_str(&data); + let data = fs::read("./savegame.bin").unwrap(); + let mut de = bincode::Deserializer::with_reader(&*data, bincode::options()); { let mut d = ( @@ -197,6 +209,7 @@ pub fn load_game(ecs: &mut World) { AOE, ArmourClassBonus, Attributes, + Avatar, Beatitude, Bleeds, Blind, @@ -231,6 +244,7 @@ pub fn load_game(ecs: &mut World) { IntrinsicChanged, Intrinsics, Item, + Key, KnownSpells, LootTable, MagicItem, @@ -260,17 +274,21 @@ pub fn load_game(ecs: &mut World) { SpawnParticleBurst, SpawnParticleLine, SpawnParticleSimple, + Stackable, TakingTurn, Telepath, ToHitBonus, Viewshed, Charges, WantsToApproach, + WantsToAssignKey, + WantsToDelete, WantsToDropItem, WantsToFlee, WantsToMelee, WantsToPickupItem, WantsToRemoveItem, + WantsToRemoveKey, WantsToUseItem, SerializationHelper, DMSerializationHelper @@ -311,7 +329,7 @@ pub fn load_game(ecs: &mut World) { } pub fn delete_save() { - if Path::new("./savegame.json").exists() { - std::fs::remove_file("./savegame.json").expect("Unable to delete file"); + if Path::new("./savegame.bin").exists() { + std::fs::remove_file("./savegame.bin").expect("Unable to delete file"); } } diff --git a/src/spawner.rs b/src/spawner.rs index 3fa673c..47b4747 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -27,9 +27,12 @@ use super::{ Bleeds, HasDamageModifiers, Intrinsics, + HasAncestry, + HasClass, }; -use crate::data::entity; -use crate::data::visuals::BLOODSTAIN_COLOUR; +use crate::gui::{ Ancestry, Class }; +use crate::consts::entity; +use crate::consts::visuals::BLOODSTAIN_COLOUR; use crate::gamesystem::*; use bracket_lib::prelude::*; use specs::prelude::*; @@ -51,17 +54,14 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { let player = ecs .create_entity() .with(Position { x: player_x, y: player_y }) - .with(BlocksTile {}) - .with(Renderable { - glyph: to_cp437('@'), - fg: RGB::named(YELLOW), - bg: RGB::named(BLACK), - render_order: 0, - }) + .with(BlocksTile {}) // FIXME: Put in actual player sprite + .with(Renderable::new(to_cp437('@'), "avatar".to_string(), RGB::named(WHITE), 2)) .with(Bleeds { colour: RGB::named(BLOODSTAIN_COLOUR) }) .with(Player {}) .with(Mind {}) .with(Faction { name: "player".to_string() }) + .with(HasAncestry { name: Ancestry::Unset }) + .with(HasClass { name: Class::Unset }) .with(Viewshed { visible_tiles: Vec::new(), range: entity::DEFAULT_VIEWSHED_STANDARD, @@ -69,15 +69,7 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { }) .with(Name { name: "you".to_string(), plural: "you".to_string() }) .with(HungerClock { state: HungerState::Satiated, duration: 1200 }) - .with(Attributes { - // These are overwritten with chargen later -- placeholders. - strength: Attribute { base: 10, modifiers: 0, bonus: 0 }, - dexterity: Attribute { base: 10, modifiers: 0, bonus: 0 }, - constitution: Attribute { base: 10, modifiers: 0, bonus: 0 }, - intelligence: Attribute { base: 10, modifiers: 0, bonus: 0 }, - wisdom: Attribute { base: 10, modifiers: 0, bonus: 0 }, - charisma: Attribute { base: 10, modifiers: 0, bonus: 0 }, - }) + .with(Attributes::default()) .with(Pools { // These are overwritten with chargen later -- placeholders. hit_points: Pool { current: 8 + attr_bonus(con), max: 8 + attr_bonus(con) }, diff --git a/src/states/state.rs b/src/states/state.rs index 0217cca..b9f6b3d 100644 --- a/src/states/state.rs +++ b/src/states/state.rs @@ -13,8 +13,8 @@ use crate::visibility_system::VisibilitySystem; use crate::ai; use crate::gamelog; use crate::spawner; -use crate::data::ids::*; -use crate::data::events::*; +use crate::consts::ids::*; +use crate::consts::events::*; use crate::components::*; use crate::player::*; use crate::gui; @@ -23,9 +23,48 @@ use crate::camera; use crate::saveload_system; use crate::morgue; use crate::damage_system; +use std::collections::HashMap; +use notan::prelude::*; +pub struct Fonts { + normal: notan::draw::Font, + bold: Option, + italic: Option, +} + +impl Fonts { + pub fn new( + normal: notan::draw::Font, + bold: Option, + italic: Option + ) -> Self { + Self { normal, bold, italic } + } + /// Returns the regular weight font. + pub fn n(&self) -> ¬an::draw::Font { + &self.normal + } + /// Returns the bold weight font, or the regular weight font if no bold font is available. + pub fn b(&self) -> notan::draw::Font { + if self.bold.is_some() { self.bold.unwrap() } else { self.normal } + } + /// Returns the italic weight font, or the regular weight font if no italic font is available. + pub fn i(&self) -> notan::draw::Font { + if self.italic.is_some() { self.italic.unwrap() } else { self.normal } + } + /// Returns in order of preference: italic, bold, regular font weights, depending on what is available. + pub fn ib(&self) -> notan::draw::Font { + if self.italic.is_some() { self.italic.unwrap() } else { self.b() } + } +} + +#[derive(AppState)] pub struct State { pub ecs: World, + //pub audio: HashMap, + pub atlas: HashMap, + pub interface: HashMap, + pub font: Fonts, pub mapgen_next_state: Option, pub mapgen_history: Vec, pub mapgen_index: usize, @@ -46,30 +85,31 @@ impl State { } } - fn run_systems(&mut self) { + fn run_systems(&mut self, ctx: &mut App) { let mut hunger_clock = hunger_system::HungerSystem {}; let mut particle_system = particle_system::ParticleSpawnSystem {}; // Order is *very* important here, to ensure effects take place in the right order, // and that the player/AI are making decisions based on the most up-to-date info. - self.resolve_entity_decisions(); // Push Player messages of intent to effects queue, and run it. + self.resolve_entity_decisions(ctx); // Push Player messages of intent to effects queue, and run it. self.refresh_indexes(); // Get up-to-date map and viewsheds prior to AI turn. self.run_ai(); // Get AI decision-making. - self.resolve_entity_decisions(); // Push AI messages of intent to effects queue, and run it. + self.resolve_entity_decisions(ctx); // Push AI messages of intent to effects queue, and run it. hunger_clock.run_now(&self.ecs); // Tick the hunger clock (on the turn clock's turn) particle_system.run_now(&self.ecs); // Spawn/delete particles (turn independent) self.ecs.maintain(); } - fn resolve_entity_decisions(&mut self) { + fn resolve_entity_decisions(&mut self, ctx: &mut App) { let mut trigger_system = trigger_system::TriggerSystem {}; - let mut inventory_system = inventory::ItemCollectionSystem {}; let mut item_equip_system = inventory::ItemEquipSystem {}; let mut item_use_system = inventory::ItemUseSystem {}; let mut item_drop_system = inventory::ItemDropSystem {}; let mut item_remove_system = inventory::ItemRemoveSystem {}; + let mut inventory_system = inventory::ItemCollectionSystem {}; let mut item_id_system = inventory::ItemIdentificationSystem {}; + let mut key_system = inventory::KeyHandling {}; let mut melee_system = MeleeCombatSystem {}; trigger_system.run_now(&self.ecs); inventory_system.run_now(&self.ecs); @@ -78,9 +118,10 @@ impl State { item_drop_system.run_now(&self.ecs); item_remove_system.run_now(&self.ecs); item_id_system.run_now(&self.ecs); + key_system.run_now(&self.ecs); melee_system.run_now(&self.ecs); - effects::run_effects_queue(&mut self.ecs); + effects::run_effects_queue(ctx, &mut self.ecs); } fn refresh_indexes(&mut self) { @@ -156,42 +197,23 @@ impl State { } } -impl GameState for State { - fn tick(&mut self, ctx: &mut BTerm) { +impl State { + pub fn update(&mut self, ctx: &mut App) { let mut new_runstate; { let runstate = self.ecs.fetch::(); new_runstate = *runstate; } - // Clear screen - ctx.cls(); particle_system::particle_ticker(&mut self.ecs, ctx); - - match new_runstate { - RunState::MainMenu { .. } => {} - RunState::CharacterCreation { .. } => {} - _ => { - // Draw map and ui - camera::render_camera(&self.ecs, ctx); - gui::draw_ui(&self.ecs, ctx); - } - } - match new_runstate { RunState::PreRun => { - self.run_systems(); + self.run_systems(ctx); self.ecs.maintain(); new_runstate = RunState::AwaitingInput; } RunState::AwaitingInput => { - // We refresh the index, and run anything that might - // still be in the queue, just to make 100% sure that - // there are no lingering effects from the last tick. self.refresh_indexes(); - effects::run_effects_queue(&mut self.ecs); - // Sanity-checking that the player actually *should* - // be taking a turn before giving them one. If they - // don't have a turn component, go back to ticking. + effects::run_effects_queue(ctx, &mut self.ecs); let mut can_act = false; { let player_entity = self.ecs.fetch::(); @@ -209,7 +231,7 @@ impl GameState for State { } RunState::Ticking => { while new_runstate == RunState::Ticking && particle_system::check_queue(&self.ecs) { - self.run_systems(); + self.run_systems(ctx); self.ecs.maintain(); try_spawn_interval(&mut self.ecs); maybe_map_message(&mut self.ecs); @@ -218,7 +240,7 @@ impl GameState for State { new_runstate = RunState::AwaitingInput; } RunState::MagicMapReveal { row, cursed } => { - new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed }; + new_runstate = RunState::MagicMapReveal { row, cursed }; } RunState::ShowRemoveCurse => { new_runstate = RunState::ShowRemoveCurse; @@ -300,21 +322,20 @@ impl GameState for State { if let Some(ranged_item) = ranged_item { let is_aoe = self.ecs.read_storage::(); let aoe_item = is_aoe.get(item_entity); - let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = - camera::get_screen_bounds(&self.ecs, ctx); + let bounds = camera::get_screen_bounds(&self.ecs, false); let ppos = self.ecs.fetch::(); if let Some(aoe_item) = aoe_item { new_runstate = RunState::ShowTargeting { - x: ppos.x + x_offset - min_x, - y: ppos.y + y_offset - min_y, + x: ppos.x + bounds.x_offset - bounds.min_x, + y: ppos.y + bounds.y_offset - bounds.min_y, range: ranged_item.range, item: item_entity, aoe: aoe_item.radius, }; } else { new_runstate = RunState::ShowTargeting { - x: ppos.x + x_offset - min_x, - y: ppos.y + y_offset - min_y, + x: ppos.x + bounds.x_offset - bounds.min_x, + y: ppos.y + bounds.y_offset - bounds.min_y, range: ranged_item.range, item: item_entity, aoe: 0, @@ -341,13 +362,17 @@ impl GameState for State { } gui::ItemMenuResult::NoResponse => {} gui::ItemMenuResult::Selected => { - let item_entity = result.1.unwrap(); + let item = result.1.unwrap(); + let mut removekey = self.ecs.write_storage::(); let mut intent = self.ecs.write_storage::(); + removekey + .insert(item, WantsToRemoveKey {}) + .expect("Unable to insert WantsToRemoveKey"); intent .insert(*self.ecs.fetch::(), WantsToDropItem { - item: item_entity, + item, }) - .expect("Unable to insert intent"); + .expect("Unable to insert WantsToDropItem"); new_runstate = RunState::Ticking; } } @@ -392,6 +417,358 @@ impl GameState for State { } } } + // RunState::ShowRemoveCurse + // RunState::ShowIdentify + RunState::ActionWithDirection { function } => { + new_runstate = gui::get_input_direction(&mut self.ecs, ctx, function); + } + RunState::MainMenu { .. } => { + let result = gui::main_menu(self, ctx); + match result { + gui::MainMenuResult::NoSelection { selected } => { + new_runstate = RunState::MainMenu { menu_selection: selected }; + } + gui::MainMenuResult::Selected { selected } => + match selected { + gui::MainMenuSelection::NewGame => { + new_runstate = RunState::CharacterCreation { + ancestry: gui::Ancestry::Human, + class: gui::Class::Fighter, + }; + } + gui::MainMenuSelection::LoadGame => { + saveload_system::load_game(&mut self.ecs); + new_runstate = RunState::AwaitingInput; + saveload_system::delete_save(); + } + gui::MainMenuSelection::Quit => { + ::std::process::exit(0); + } + } + } + } + RunState::CharacterCreation { .. } => { + let result = gui::character_creation(self, ctx); + match result { + gui::CharCreateResult::NoSelection { ancestry, class } => { + new_runstate = RunState::CharacterCreation { ancestry, class }; + } + gui::CharCreateResult::Selected { ancestry, class } => { + if ancestry == gui::Ancestry::Unset { + new_runstate = RunState::MainMenu { + menu_selection: gui::MainMenuSelection::NewGame, + }; + } else { + gui::setup_player_ancestry(&mut self.ecs, ancestry); + gui::setup_player_class(&mut self.ecs, class, ancestry); + new_runstate = RunState::PreRun; + } + } + } + } + RunState::SaveGame => { + saveload_system::save_game(&mut self.ecs); + new_runstate = RunState::MainMenu { + menu_selection: gui::MainMenuSelection::LoadGame, + }; + } + RunState::GameOver => { + let result = gui::yes_no(ctx); + let write_to_morgue: Option = match result { + gui::YesNoResult::NoSelection => None, + gui::YesNoResult::No => Some(false), + gui::YesNoResult::Yes => Some(true), + }; + if let Some(response) = write_to_morgue { + if response { + morgue::create_morgue_file(&self.ecs); + } + self.game_over_cleanup(); + new_runstate = RunState::MapGeneration; + self.mapgen_next_state = Some(RunState::MainMenu { + menu_selection: gui::MainMenuSelection::NewGame, + }); + } + } + RunState::GoToLevel(id, dest_tile) => { + self.goto_id(id, dest_tile); + self.mapgen_next_state = Some(RunState::PreRun); + new_runstate = RunState::MapGeneration; + } + RunState::HelpScreen => { + let result = gui::help_prompt(ctx); + match result { + gui::YesNoResult::NoSelection => {} + _ => { + gamelog::record_event(EVENT::LookedForHelp(1)); + new_runstate = RunState::AwaitingInput; + } + } + } + RunState::MagicMapReveal { row, cursed } => { + let mut map = self.ecs.fetch_mut::(); + // Could probably toss this into a function somewhere, and/or + // have multiple simple animations for it. + for x in 0..map.width { + let idx; + if x % 2 == 0 { + idx = map.xy_idx(x as i32, row); + } else { + idx = map.xy_idx(x as i32, (map.height as i32) - 1 - row); + } + if !cursed { + map.revealed_tiles[idx] = true; + } else { + map.revealed_tiles[idx] = false; + } + } + // Dirtify viewshed only if cursed, so our currently visible tiles aren't removed too + if cursed { + let player_entity = self.ecs.fetch::(); + let mut viewshed_components = self.ecs.write_storage::(); + let viewshed = viewshed_components.get_mut(*player_entity); + if let Some(viewshed) = viewshed { + viewshed.dirty = true; + } + } + + if (row as usize) == (map.height as usize) - 1 { + new_runstate = RunState::Ticking; + } else { + new_runstate = RunState::MagicMapReveal { row: row + 1, cursed: cursed }; + } + } + RunState::MapGeneration => { + if !config::CONFIG.logging.show_mapgen || self.mapgen_history.len() <= 0 { + new_runstate = self.mapgen_next_state.unwrap(); + } else { + if self.mapgen_history.len() > 0 { + self.mapgen_timer += ctx.timer.delta_f32(); + if + self.mapgen_timer > 10.0 / (self.mapgen_history.len() as f32) || + self.mapgen_timer > 1.0 + { + self.mapgen_timer = 0.0; + self.mapgen_index += 1; + if self.mapgen_index >= self.mapgen_history.len() { + new_runstate = self.mapgen_next_state.unwrap(); + } + } + } + } + } + _ => {} + } + { + let mut runwriter = self.ecs.write_resource::(); + *runwriter = new_runstate; + } + damage_system::delete_the_dead(&mut self.ecs); + } + + // Deprecated + fn tick(&mut self, ctx: &mut BTerm) { + let mut new_runstate; + { + let runstate = self.ecs.fetch::(); + new_runstate = *runstate; + } + // Clear screen + ctx.set_active_console(2); + ctx.cls(); + ctx.set_active_console(1); + ctx.cls(); + ctx.set_active_console(0); + ctx.cls(); + //particle_system::particle_ticker(&mut self.ecs, ctx); + + match new_runstate { + RunState::MainMenu { .. } => {} + RunState::CharacterCreation { .. } => {} + _ => { + // Draw map and ui + camera::render_camera(&self.ecs, ctx); + gui::draw_ui(&self.ecs, ctx); + } + } + + match new_runstate { + RunState::PreRun => { + //self.run_systems(); + self.ecs.maintain(); + new_runstate = RunState::AwaitingInput; + } + RunState::AwaitingInput => { + // We refresh the index, and run anything that might + // still be in the queue, just to make 100% sure that + // there are no lingering effects from the last tick. + self.refresh_indexes(); + //effects::run_effects_queue(&mut self.ecs); + // Sanity-checking that the player actually *should* + // be taking a turn before giving them one. If they + // don't have a turn component, go back to ticking. + let mut can_act = false; + { + let player_entity = self.ecs.fetch::(); + let turns = self.ecs.read_storage::(); + if let Some(_) = turns.get(*player_entity) { + can_act = true; + } + } + if can_act { + let on_overmap = self.ecs.fetch::().overmap; + new_runstate = RunState::AwaitingInput; //player_input(self, ctx, on_overmap); + } else { + new_runstate = RunState::Ticking; + } + } + RunState::Ticking => { + while new_runstate == RunState::Ticking && particle_system::check_queue(&self.ecs) { + //self.run_systems(); + self.ecs.maintain(); + try_spawn_interval(&mut self.ecs); + maybe_map_message(&mut self.ecs); + match *self.ecs.fetch::() { + RunState::AwaitingInput => { + new_runstate = RunState::AwaitingInput; + } + RunState::MagicMapReveal { row, cursed } => { + new_runstate = RunState::MagicMapReveal { row: row, cursed: cursed }; + } + RunState::ShowRemoveCurse => { + new_runstate = RunState::ShowRemoveCurse; + } + RunState::ShowIdentify => { + new_runstate = RunState::ShowIdentify; + } + _ => { + new_runstate = RunState::Ticking; + } + } + } + } + RunState::Farlook { .. } => { + let result = gui::FarlookResult::Cancel; //gui::show_farlook(self, ctx); + match result { + gui::FarlookResult::NoResponse { x, y } => { + new_runstate = RunState::Farlook { x, y }; + } + gui::FarlookResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + } + } + RunState::ShowCheatMenu => { + let result = gui::CheatMenuResult::Cancel; //gui::show_cheat_menu(self, ctx); + match result { + gui::CheatMenuResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + gui::CheatMenuResult::NoResponse => {} + gui::CheatMenuResult::Ascend => { + let id = self.ecs.fetch::().id - 1; + self.goto_id(id, TileType::DownStair); + self.mapgen_next_state = Some(RunState::PreRun); + new_runstate = RunState::MapGeneration; + } + gui::CheatMenuResult::Descend => { + let id = self.ecs.fetch::().id + 1; + self.goto_id(id, TileType::UpStair); + self.mapgen_next_state = Some(RunState::PreRun); + new_runstate = RunState::MapGeneration; + } + gui::CheatMenuResult::Heal => { + let player = self.ecs.fetch::(); + let mut pools = self.ecs.write_storage::(); + let mut player_pools = pools.get_mut(*player).unwrap(); + player_pools.hit_points.current = player_pools.hit_points.max; + new_runstate = RunState::AwaitingInput; + } + gui::CheatMenuResult::MagicMap => { + let mut map = self.ecs.fetch_mut::(); + for v in map.revealed_tiles.iter_mut() { + *v = true; + } + new_runstate = RunState::AwaitingInput; + } + gui::CheatMenuResult::GodMode => { + let player = self.ecs.fetch::(); + let mut pools = self.ecs.write_storage::(); + let mut player_pools = pools.get_mut(*player).unwrap(); + gamelog::Logger::new().append("TOGGLED GOD MODE!").log(); + player_pools.god = !player_pools.god; + new_runstate = RunState::AwaitingInput; + } + } + } + RunState::ShowInventory => { + let result = gui::ItemMenuResult::Cancel; //gui::show_inventory(self, ctx); + match result { + gui::ItemMenuResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + _ => {} + } + } + RunState::ShowDropItem => { + let result = (gui::ItemMenuResult::Cancel, None); //gui::drop_item_menu(self, ctx); + match result.0 { + gui::ItemMenuResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + gui::ItemMenuResult::NoResponse => {} + gui::ItemMenuResult::Selected => { + let item_entity = result.1.unwrap(); + let mut intent = self.ecs.write_storage::(); + intent + .insert(*self.ecs.fetch::(), WantsToDropItem { + item: item_entity, + }) + .expect("Unable to insert intent"); + new_runstate = RunState::Ticking; + } + } + } + RunState::ShowRemoveItem => { + let result = (gui::ItemMenuResult::Cancel, None); //gui::remove_item_menu(self, ctx); + match result.0 { + gui::ItemMenuResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + gui::ItemMenuResult::NoResponse => {} + gui::ItemMenuResult::Selected => { + let item_entity = result.1.unwrap(); + let mut intent = self.ecs.write_storage::(); + intent + .insert(*self.ecs.fetch::(), WantsToRemoveItem { + item: item_entity, + }) + .expect("Unable to insert intent"); + new_runstate = RunState::Ticking; + } + } + } + RunState::ShowTargeting { x, y, range, item, aoe } => { + let result = (gui::TargetResult::Cancel, None); //gui::ranged_target(self, ctx, x, y, range, aoe); + match result.0 { + gui::TargetResult::Cancel => { + new_runstate = RunState::AwaitingInput; + } + gui::TargetResult::NoResponse { x, y } => { + new_runstate = RunState::ShowTargeting { x, y, range, item, aoe }; + } + gui::TargetResult::Selected => { + let mut intent = self.ecs.write_storage::(); + intent + .insert(*self.ecs.fetch::(), WantsToUseItem { + item, + target: result.1, + }) + .expect("Unable to insert intent."); + new_runstate = RunState::Ticking; + } + } + } RunState::ShowRemoveCurse => { let result = gui::remove_curse(self, ctx); match result.0 { @@ -434,10 +811,12 @@ impl GameState for State { } } RunState::ActionWithDirection { function } => { - new_runstate = gui::get_input_direction(&mut self.ecs, ctx, function); + new_runstate = RunState::AwaitingInput; //gui::get_input_direction(&mut self.ecs, ctx, function); } RunState::MainMenu { .. } => { - let result = gui::main_menu(self, ctx); + let result = gui::MainMenuResult::Selected { + selected: gui::MainMenuSelection::NewGame, + }; //gui::main_menu(self, ctx); match result { gui::MainMenuResult::NoSelection { selected } => { new_runstate = RunState::MainMenu { menu_selection: selected }; @@ -462,13 +841,16 @@ impl GameState for State { } } RunState::CharacterCreation { .. } => { - let result = gui::character_creation(self, ctx); + let result = gui::CharCreateResult::NoSelection { + ancestry: gui::Ancestry::Human, + class: gui::Class::Fighter, + }; //gui::character_creation(self, ctx); match result { gui::CharCreateResult::NoSelection { ancestry, class } => { new_runstate = RunState::CharacterCreation { ancestry, class }; } gui::CharCreateResult::Selected { ancestry, class } => { - if ancestry == gui::Ancestry::NULL { + if ancestry == gui::Ancestry::Unset { new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame, }; @@ -487,7 +869,7 @@ impl GameState for State { }; } RunState::GameOver => { - let result = gui::game_over(ctx); + let result = gui::YesNoResult::No; //gui::game_over(ctx); let write_to_morgue: Option = match result { gui::YesNoResult::NoSelection => None, gui::YesNoResult::No => Some(false), @@ -559,6 +941,11 @@ impl GameState for State { new_runstate = self.mapgen_next_state.unwrap(); } if self.mapgen_history.len() != 0 { + ctx.set_active_console(2); + ctx.cls(); + ctx.set_active_console(1); + ctx.cls(); + ctx.set_active_console(0); ctx.cls(); camera::render_debug_map(&self.mapgen_history[self.mapgen_index], ctx); diff --git a/src/visibility_system.rs b/src/visibility_system.rs index e53b0e1..2b7e70a 100644 --- a/src/visibility_system.rs +++ b/src/visibility_system.rs @@ -10,7 +10,10 @@ use super::{ Telepath, Viewshed, Renderable, + Prop, + Item, gui::renderable_colour, + tile_blocks_telepathy, }; use bracket_lib::prelude::*; use bracket_lib::pathfinding::FieldOfViewAlg::SymmetricShadowcasting; @@ -34,6 +37,8 @@ impl<'a> System<'a> for VisibilitySystem { ReadStorage<'a, Blind>, ReadStorage<'a, BlocksVisibility>, ReadStorage<'a, Renderable>, + ReadStorage<'a, Prop>, + ReadStorage<'a, Item>, ); fn run(&mut self, data: Self::SystemData) { @@ -50,6 +55,8 @@ impl<'a> System<'a> for VisibilitySystem { blind_entities, blocks_visibility, renderables, + prop, + item, ) = data; map.view_blocked.clear(); @@ -58,6 +65,7 @@ impl<'a> System<'a> for VisibilitySystem { map.view_blocked.insert(idx); } + let mut player_was_dirty = false; for (ent, viewshed, pos) in (&entities, &mut viewshed, &pos).join() { if viewshed.dirty { viewshed.dirty = false; @@ -80,6 +88,7 @@ impl<'a> System<'a> for VisibilitySystem { // If this is the player, reveal what they can see let _p: Option<&Player> = player.get(ent); if let Some(_p) = _p { + player_was_dirty = true; for t in map.visible_tiles.iter_mut() { *t = false; } @@ -120,7 +129,7 @@ impl<'a> System<'a> for VisibilitySystem { if let Some(_is_blind) = blind_entities.get(ent) { 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( |p| p.x >= 0 && p.x < map.width && p.y >= 0 && p.y < map.height ); @@ -138,10 +147,38 @@ impl<'a> System<'a> for VisibilitySystem { } } } + + if player_was_dirty { + // Refresh the memory of our visible tiles, by removing whatever + // was stored for every index we can currently see, and placing + // back in updated data. + let mut to_remove: Vec = Vec::new(); + for (i, &t) in map.visible_tiles.iter().enumerate() { + if t { + to_remove.push(i); + } + } + for idx in to_remove.iter() { + map.memory.remove(idx); + } + for (e, r, p, _h) in (&entities, &renderables, &pos, !&hidden).join() { + if prop.get(e).is_some() || item.get(e).is_some() { + let idx = map.xy_idx(p.x, p.y); + if map.visible_tiles[idx] { + map.memory.entry(idx).or_insert(Vec::new()).push(crate::MapMemory { + sprite: r.sprite.clone(), + fg: r.fg, + offset: r.offset, + render_order: r.render_order, + }); + } + } + } + } } } -pub fn fast_fov(p_x: i32, p_y: i32, r: i32) -> Vec { +pub fn fast_fov(p_x: i32, p_y: i32, r: i32, map: &WriteExpect) -> Vec { let mut visible_tiles: Vec = Vec::new(); let mut i = 0; @@ -152,7 +189,17 @@ pub fn fast_fov(p_x: i32, p_y: i32, r: i32) -> Vec { let mut ox: f32 = (p_x as f32) + (0.5 as f32); let mut oy: f32 = (p_y as f32) + (0.5 as f32); for _i in 0..r { - visible_tiles.push(Point::new(ox as i32, oy as i32)); + 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; oy += y; } diff --git a/tests/gamelog_test.rs b/tests/gamelog_test.rs index 0e18d44..772dc66 100644 --- a/tests/gamelog_test.rs +++ b/tests/gamelog_test.rs @@ -1,6 +1,6 @@ // tests/gamelog_test.rs use rust_rl::gamelog::*; -use rust_rl::data::events::*; +use rust_rl::consts::events::*; use lazy_static::lazy_static; use std::sync::Mutex; diff --git a/wasm/rust/rust-rl.js b/wasm/rust/rust-rl.js new file mode 100644 index 0000000..68a62dd --- /dev/null +++ b/wasm/rust/rust-rl.js @@ -0,0 +1,1336 @@ +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; +} + +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(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +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; + +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; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +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; +} + +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_24(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1d5c38b17c68cbf8(arg0, arg1); +} + +function __wbg_adapter_27(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h21def532cde51782(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.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbg_error_407831efd36ed4ad = function(arg0, arg1) { + console.error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + 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.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_log_0e24d345b14995ec = function(arg0, arg1) { + console.log(getStringFromWasm0(arg0, arg1)); + }; + 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.__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_bindBufferBase_2f6265b5bd82a1f2 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bindBufferBase(arg1 >>> 0, arg2 >>> 0, getObject(arg3)); + }; + 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_bufferSubData_c472b93c9e272eac = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferSubData(arg1 >>> 0, arg2, getObject(arg3)); + }; + imports.wbg.__wbg_createVertexArray_51d51e1e1e13e9f6 = function(arg0) { + const ret = getObject(arg0).createVertexArray(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_deleteVertexArray_3e4f2e2ff7f05a19 = function(arg0, arg1) { + getObject(arg0).deleteVertexArray(getObject(arg1)); + }; + imports.wbg.__wbg_drawArraysInstanced_8fb13fe9faf95212 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).drawArraysInstanced(arg1 >>> 0, arg2, arg3, arg4); + }; + imports.wbg.__wbg_drawElementsInstanced_dcf53461a977d44c = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).drawElementsInstanced(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_getUniformBlockIndex_99c15053c9a87c73 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getUniformBlockIndex(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return ret; + }; + imports.wbg.__wbg_readPixels_99fda83f6ca7ec72 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, getObject(arg7)); + }, arguments) }; + imports.wbg.__wbg_readPixels_9634f0dcfb54667c = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, arg7); + }, arguments) }; + 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_texSubImage2D_d2841ded12a8aa66 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage2D_bccf4e250f1ce1b8 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments) }; + imports.wbg.__wbg_uniformBlockBinding_0dc4bd81bb4ccb6a = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniformBlockBinding(getObject(arg1), arg2 >>> 0, arg3 >>> 0); + }; + imports.wbg.__wbg_vertexAttribDivisor_197e2e23e3fbde7f = function(arg0, arg1, arg2) { + getObject(arg0).vertexAttribDivisor(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_activeTexture_799bf1387e911c27 = function(arg0, arg1) { + getObject(arg0).activeTexture(arg1 >>> 0); + }; + 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_blendEquation_12146cb96dc1bcd9 = function(arg0, arg1) { + getObject(arg0).blendEquation(arg1 >>> 0); + }; + imports.wbg.__wbg_blendEquationSeparate_205526dad772d160 = function(arg0, arg1, arg2) { + getObject(arg0).blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFunc_533de6de45b80a09 = function(arg0, arg1, arg2) { + getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFuncSeparate_fbf93dee3e5ce456 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_checkFramebufferStatus_d5eaeabeb7ea0712 = function(arg0, arg1) { + const ret = getObject(arg0).checkFramebufferStatus(arg1 >>> 0); + return ret; + }; + 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_clearDepth_eb4660e1a89df604 = function(arg0, arg1) { + getObject(arg0).clearDepth(arg1); + }; + imports.wbg.__wbg_clearStencil_6f88ec46b2f75316 = function(arg0, arg1) { + getObject(arg0).clearStencil(arg1); + }; + imports.wbg.__wbg_colorMask_fba1e2efd891e2ac = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }; + 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_cullFace_6daa9f2aa42b4620 = function(arg0, arg1) { + getObject(arg0).cullFace(arg1 >>> 0); + }; + imports.wbg.__wbg_deleteBuffer_2c09d03fa4b0bd08 = function(arg0, arg1) { + getObject(arg0).deleteBuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteFramebuffer_edd16bb8df6a8e0d = function(arg0, arg1) { + getObject(arg0).deleteFramebuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteProgram_53a32852f245b839 = function(arg0, arg1) { + getObject(arg0).deleteProgram(getObject(arg1)); + }; + imports.wbg.__wbg_deleteShader_7c1222349324b5e2 = function(arg0, arg1) { + getObject(arg0).deleteShader(getObject(arg1)); + }; + imports.wbg.__wbg_deleteTexture_4fcfea73cd8f6214 = function(arg0, arg1) { + getObject(arg0).deleteTexture(getObject(arg1)); + }; + imports.wbg.__wbg_depthFunc_fb41ad353d07948d = function(arg0, arg1) { + getObject(arg0).depthFunc(arg1 >>> 0); + }; + imports.wbg.__wbg_depthMask_6a4ff02cd2a2702e = function(arg0, arg1) { + getObject(arg0).depthMask(arg1 !== 0); + }; + 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_generateMipmap_96d73b7b931b4cbf = function(arg0, arg1) { + getObject(arg0).generateMipmap(arg1 >>> 0); + }; + imports.wbg.__wbg_getActiveUniform_78367ddc7339640b = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getActiveUniform(getObject(arg1), arg2 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(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_pixelStorei_f3a24990aa352fc7 = function(arg0, arg1, arg2) { + getObject(arg0).pixelStorei(arg1 >>> 0, arg2); + }; + imports.wbg.__wbg_scissor_e8e41e1c0a9817c8 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).scissor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_shaderSource_1cb7c64dc7d1a500 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_stencilFunc_fc72a03857442e32 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).stencilFunc(arg1 >>> 0, arg2, arg3 >>> 0); + }; + imports.wbg.__wbg_stencilMask_641f92999dd3c3de = function(arg0, arg1) { + getObject(arg0).stencilMask(arg1 >>> 0); + }; + imports.wbg.__wbg_stencilOp_8f363ce325dcedb3 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).stencilOp(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0); + }; + 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_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_viewport_fad1ce9e18f741c0 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).viewport(arg1, arg2, arg3, arg4); + }; + 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_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_screen_452da8d1ab76046e = function() { return handleError(function (arg0) { + const ret = getObject(arg0).screen; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_devicePixelRatio_f9de7bddca0eaf20 = function(arg0) { + const ret = getObject(arg0).devicePixelRatio; + return ret; + }; + imports.wbg.__wbg_open_7a2a86bf6285507d = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).open(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_requestAnimationFrame_d082200514b6674d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).requestAnimationFrame(getObject(arg1)); + return ret; + }, arguments) }; + 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_deleteVertexArrayOES_7bf4589e63d84df6 = function(arg0, arg1) { + getObject(arg0).deleteVertexArrayOES(getObject(arg1)); + }; + imports.wbg.__wbg_pointerId_701aab7b4fb073ff = function(arg0) { + const ret = getObject(arg0).pointerId; + return ret; + }; + imports.wbg.__wbg_pointerType_0009b1e4e6b0f428 = function(arg0, arg1) { + const ret = getObject(arg1).pointerType; + 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_deltaX_84508d00a1050e70 = function(arg0) { + const ret = getObject(arg0).deltaX; + return ret; + }; + imports.wbg.__wbg_deltaY_64823169afb0335d = function(arg0) { + const ret = getObject(arg0).deltaY; + return ret; + }; + imports.wbg.__wbg_now_0cfdc90c97d0c24b = function(arg0) { + const ret = getObject(arg0).now(); + return 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_6d1f155bb5c1096a = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getContext(getStringFromWasm0(arg1, arg2), getObject(arg3)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_debug_9a6b3243fbbebb61 = function(arg0) { + console.debug(getObject(arg0)); + }; + imports.wbg.__wbg_error_788ae33f81d3b84b = function(arg0) { + console.error(getObject(arg0)); + }; + imports.wbg.__wbg_info_2e30e8204b29d91d = function(arg0) { + console.info(getObject(arg0)); + }; + imports.wbg.__wbg_log_1d3ae0273d8f4f8a = function(arg0) { + console.log(getObject(arg0)); + }; + imports.wbg.__wbg_warn_d60e832f9882c1b2 = function(arg0) { + console.warn(getObject(arg0)); + }; + imports.wbg.__wbg_drawArraysInstancedANGLE_01b862ba133350a3 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).drawArraysInstancedANGLE(arg1 >>> 0, arg2, arg3, arg4); + }; + imports.wbg.__wbg_drawElementsInstancedANGLE_ea6343af8bf9c9f8 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).drawElementsInstancedANGLE(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_vertexAttribDivisorANGLE_a8476eb778e16c70 = function(arg0, arg1, arg2) { + getObject(arg0).vertexAttribDivisorANGLE(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_setProperty_b95ef63ab852879e = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setProperty(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_key_8aeaa079126a9cc7 = function(arg0, arg1) { + const ret = getObject(arg1).key; + 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_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_clientX_1a480606ab0cabaa = function(arg0) { + const ret = getObject(arg0).clientX; + return ret; + }; + imports.wbg.__wbg_clientY_9c7878f7faf3900f = function(arg0) { + const ret = getObject(arg0).clientY; + return ret; + }; + imports.wbg.__wbg_button_7a095234b69de930 = function(arg0) { + const ret = getObject(arg0).button; + return ret; + }; + imports.wbg.__wbg_movementX_966ec323c169d1a6 = function(arg0) { + const ret = getObject(arg0).movementX; + return ret; + }; + imports.wbg.__wbg_movementY_b14b3bc8e1b31f23 = function(arg0) { + const ret = getObject(arg0).movementY; + return ret; + }; + imports.wbg.__wbg_body_674aec4c1c0910cd = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_fullscreen_6e5ea390ffad3838 = function(arg0) { + const ret = getObject(arg0).fullscreen; + return ret; + }; + imports.wbg.__wbg_activeElement_2cf540415b6fcd5c = function(arg0) { + const ret = getObject(arg0).activeElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_pointerLockElement_a9be188f5b57ae68 = function(arg0) { + const ret = getObject(arg0).pointerLockElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_exitFullscreen_5fada21e8623256e = function(arg0) { + getObject(arg0).exitFullscreen(); + }; + imports.wbg.__wbg_exitPointerLock_bf425ac90f055faa = function(arg0) { + getObject(arg0).exitPointerLock(); + }; + 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_hasFocus_2b48e9e2604cbbca = function() { return handleError(function (arg0) { + const ret = getObject(arg0).hasFocus(); + return ret; + }, arguments) }; + imports.wbg.__wbg_id_0626af592e3fcac5 = function(arg0, arg1) { + const ret = getObject(arg1).id; + 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_setid_1984ee27e5075311 = function(arg0, arg1, arg2) { + getObject(arg0).id = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_clientWidth_51ec21e3189f5656 = function(arg0) { + const ret = getObject(arg0).clientWidth; + return ret; + }; + imports.wbg.__wbg_clientHeight_09ec0b524d59c367 = function(arg0) { + const ret = getObject(arg0).clientHeight; + return ret; + }; + imports.wbg.__wbg_getAttribute_3d8fcc9eaea35a17 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).getAttribute(getStringFromWasm0(arg2, arg3)); + 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_getBoundingClientRect_ac9db8cf97ca8083 = function(arg0) { + const ret = getObject(arg0).getBoundingClientRect(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_requestFullscreen_3545278bcd44910c = function() { return handleError(function (arg0) { + getObject(arg0).requestFullscreen(); + }, arguments) }; + imports.wbg.__wbg_requestPointerLock_368c5cc6c3ddd339 = function(arg0) { + getObject(arg0).requestPointerLock(); + }; + imports.wbg.__wbg_setAttribute_e7e80b478b7b8b2f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_style_3801009b2339aa94 = function(arg0) { + const ret = getObject(arg0).style; + return addHeapObject(ret); + }; + imports.wbg.__wbg_focus_dbcbbbb2a04c0e1f = function() { return handleError(function (arg0) { + getObject(arg0).focus(); + }, arguments) }; + imports.wbg.__wbg_instanceof_WebGlRenderingContext_ea632546035eecb1 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof WebGLRenderingContext; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_bufferData_a11a9f65f31e7256 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0); + }; + imports.wbg.__wbg_bufferSubData_fca6f1c10273be21 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferSubData(arg1 >>> 0, arg2, getObject(arg3)); + }; + imports.wbg.__wbg_readPixels_91b0d8854de90477 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, getObject(arg7)); + }, arguments) }; + 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_texSubImage2D_f1a31f8045b7f831 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_activeTexture_93b4de60af07da9c = function(arg0, arg1) { + getObject(arg0).activeTexture(arg1 >>> 0); + }; + 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_blendEquation_f31ce08020786a09 = function(arg0, arg1) { + getObject(arg0).blendEquation(arg1 >>> 0); + }; + imports.wbg.__wbg_blendEquationSeparate_7ec5e34f066e44f8 = function(arg0, arg1, arg2) { + getObject(arg0).blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFunc_fbe9d3a688fe71c3 = function(arg0, arg1, arg2) { + getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFuncSeparate_7547ade0a7dfade2 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_checkFramebufferStatus_16ff70667a5f6e18 = function(arg0, arg1) { + const ret = getObject(arg0).checkFramebufferStatus(arg1 >>> 0); + return ret; + }; + 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_clearDepth_de473665af3545ff = function(arg0, arg1) { + getObject(arg0).clearDepth(arg1); + }; + imports.wbg.__wbg_clearStencil_68147b3b4a196080 = function(arg0, arg1) { + getObject(arg0).clearStencil(arg1); + }; + imports.wbg.__wbg_colorMask_7cbd7a102954ede9 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }; + 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_cullFace_4c086dc1d86a19b5 = function(arg0, arg1) { + getObject(arg0).cullFace(arg1 >>> 0); + }; + imports.wbg.__wbg_deleteBuffer_cdc6b9c73f54aff7 = function(arg0, arg1) { + getObject(arg0).deleteBuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteFramebuffer_fcc10cb143c6573d = function(arg0, arg1) { + getObject(arg0).deleteFramebuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteProgram_d8d7fc79ba83b256 = function(arg0, arg1) { + getObject(arg0).deleteProgram(getObject(arg1)); + }; + imports.wbg.__wbg_deleteShader_9a2f85efe5cb3706 = function(arg0, arg1) { + getObject(arg0).deleteShader(getObject(arg1)); + }; + imports.wbg.__wbg_deleteTexture_a883356c5034d482 = function(arg0, arg1) { + getObject(arg0).deleteTexture(getObject(arg1)); + }; + imports.wbg.__wbg_depthFunc_4eda7b4e682acbad = function(arg0, arg1) { + getObject(arg0).depthFunc(arg1 >>> 0); + }; + imports.wbg.__wbg_depthMask_a3071e13bb087102 = function(arg0, arg1) { + getObject(arg0).depthMask(arg1 !== 0); + }; + 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_generateMipmap_99a56abf170def20 = function(arg0, arg1) { + getObject(arg0).generateMipmap(arg1 >>> 0); + }; + imports.wbg.__wbg_getActiveUniform_87df972e841afed2 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getActiveUniform(getObject(arg1), arg2 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getExtension_088d115a16ecbd7d = 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_bfab7f0b00c9d7fb = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).getParameter(arg1 >>> 0); + return addHeapObject(ret); + }, arguments) }; + 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_getSupportedExtensions_4eb3a5f14f552ce5 = function(arg0) { + const ret = getObject(arg0).getSupportedExtensions(); + return isLikeNone(ret) ? 0 : 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_pixelStorei_5ec932ebefd00149 = function(arg0, arg1, arg2) { + getObject(arg0).pixelStorei(arg1 >>> 0, arg2); + }; + imports.wbg.__wbg_scissor_c8ec3b1e053f3756 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).scissor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_shaderSource_f435f9b74440bb54 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_stencilFunc_11e7ac2d45aa66c7 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).stencilFunc(arg1 >>> 0, arg2, arg3 >>> 0); + }; + imports.wbg.__wbg_stencilMask_79416c29ac1ce3a4 = function(arg0, arg1) { + getObject(arg0).stencilMask(arg1 >>> 0); + }; + imports.wbg.__wbg_stencilOp_398dc625213ddfed = function(arg0, arg1, arg2, arg3) { + getObject(arg0).stencilOp(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0); + }; + 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_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_viewport_6ebef187c89e2616 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).viewport(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbg_stopPropagation_55539cfa2506c867 = function(arg0) { + getObject(arg0).stopPropagation(); + }; + imports.wbg.__wbg_parentElement_c75962bc9997ea5f = function(arg0) { + const ret = getObject(arg0).parentElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_appendChild_51339d4cde00ee22 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_size_6eb4aa794f6bf220 = function(arg0) { + const ret = getObject(arg0).size; + return ret; + }; + imports.wbg.__wbg_type_37bb6b4936b5e027 = function(arg0) { + const ret = getObject(arg0).type; + return ret; + }; + imports.wbg.__wbg_name_ebae3a7e89367611 = function(arg0, arg1) { + const ret = getObject(arg1).name; + 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_top_98ff0408c018d25e = function(arg0) { + const ret = getObject(arg0).top; + return ret; + }; + imports.wbg.__wbg_left_23a613d619fb4206 = function(arg0) { + const ret = getObject(arg0).left; + return ret; + }; + imports.wbg.__wbg_addEventListener_5651108fc3ffeb6e = function() { return handleError(function (arg0, arg1, arg2, arg3) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3)); + }, arguments) }; + imports.wbg.__wbg_width_07fc222a210e15f1 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).width; + return ret; + }, arguments) }; + imports.wbg.__wbg_height_6fa226ea329cffc1 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).height; + return ret; + }, arguments) }; + 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_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + 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_getUTCDay_4cf4be86a2d32954 = function(arg0) { + const ret = getObject(arg0).getUTCDay(); + return ret; + }; + imports.wbg.__wbg_getUTCFullYear_ae4f7c4a60c441d1 = function(arg0) { + const ret = getObject(arg0).getUTCFullYear(); + return ret; + }; + imports.wbg.__wbg_getUTCHours_ecf78a80e567729d = function(arg0) { + const ret = getObject(arg0).getUTCHours(); + return ret; + }; + imports.wbg.__wbg_getUTCMinutes_20c281b2e442a4cb = function(arg0) { + const ret = getObject(arg0).getUTCMinutes(); + return ret; + }; + imports.wbg.__wbg_getUTCMonth_0d50a6216b1c52ca = function(arg0) { + const ret = getObject(arg0).getUTCMonth(); + return ret; + }; + imports.wbg.__wbg_getUTCSeconds_53990cae10d4041a = function(arg0) { + const ret = getObject(arg0).getUTCSeconds(); + return ret; + }; + imports.wbg.__wbg_new0_c0be7df4b6bd481f = function() { + const ret = new Date(); + return addHeapObject(ret); + }; + 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.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + 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_wrapper992 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 277, __wbg_adapter_24); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2867 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 707, __wbg_adapter_27); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2869 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 707, __wbg_adapter_27); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2871 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 707, __wbg_adapter_27); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2873 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 707, __wbg_adapter_27); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2875 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 707, __wbg_adapter_27); + 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; + cachedFloat64Memory0 = null; + 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); + +})(); diff --git a/wasm/rust/rust-rl_bg.wasm b/wasm/rust/rust-rl_bg.wasm new file mode 100644 index 0000000..b3076d2 Binary files /dev/null and b/wasm/rust/rust-rl_bg.wasm differ diff --git a/wasm/rust-rl.js b/web/rust-rl.js similarity index 98% rename from wasm/rust-rl.js rename to web/rust-rl.js index ffbe20e..7036263 100644 --- a/wasm/rust-rl.js +++ b/web/rust-rl.js @@ -212,11 +212,11 @@ function makeMutClosure(arg0, arg1, dtor, f) { return real; } 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) { - 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) { @@ -817,16 +817,16 @@ function __wbg_get_imports() { const ret = wasm.memory; return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper258 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 15, __wbg_adapter_20); + 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_wrapper2954 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 696, __wbg_adapter_23); + 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_wrapper2956 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 696, __wbg_adapter_23); + imports.wbg.__wbindgen_closure_wrapper2962 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 698, __wbg_adapter_23); return addHeapObject(ret); }; diff --git a/wasm/rust-rl_bg.wasm b/web/rust-rl_bg.wasm similarity index 52% rename from wasm/rust-rl_bg.wasm rename to web/rust-rl_bg.wasm index f48ccb7..79ebb75 100644 Binary files a/wasm/rust-rl_bg.wasm and b/web/rust-rl_bg.wasm differ