diff options
91 files changed, 1390 insertions, 193 deletions
diff --git a/db/_generated/areas/candy-town.json b/db/_generated/areas/candy-town.json new file mode 100644 index 0000000..a11f4b4 --- /dev/null +++ b/db/_generated/areas/candy-town.json @@ -0,0 +1 @@ +{"name":"Candy Town","locations":{"hospital":{"type":"healingCenter","price":30},"scoop_store":{"type":"shop","economy":"spyder_candy_scoop","items":[{"item_name":"potion","price":20,"cost":5},{"item_name":"revive","price":100,"cost":20},{"item_name":"tuxeball","price":50,"cost":10}]}},"connections":{"route6":{"conditions":[],"name":"Route 6"},"sea-route-c":{"conditions":[],"name":"Sea Route C"}},"encounters":[],"requiredEncounters":0,"trainers":[],"environment":null,"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Candy_Town.png\" \/>\n\n <rect data-location=\"hospital\" x=\"127\" y=\"431\" width=\"210\" height=\"130\" stroke=\"red\" fill=\"transparent\" \/>\n <rect data-location=\"scoop_store\" x=\"17\" y=\"144\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/city-park.json b/db/_generated/areas/city-park.json index 9080b55..f6621fb 100644 --- a/db/_generated/areas/city-park.json +++ b/db/_generated/areas/city-park.json @@ -1 +1 @@ -{"name":"City Park","encounter_slug":"citypark","encounters":[{"monster":"cardiling","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[5,8]},{"monster":"cardiwing","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[8,11]},{"monster":"cataspike","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[6,9]},{"monster":"eyenemy","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[5,8]},{"monster":"axylightl","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"tourbidi","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"squabbit","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"puparmor","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[9,14]}],"requiredEncounters":10,"trainers":[{"name":"Frances","sprite":"florist.png","monsters":[{"slug":"shybulb","level":8},{"slug":"shybulb","level":8}],"inventory":[]}],"environment_slug":"forest","connections":{"route2":{"conditions":[],"name":"Route 2"},"leather-town":{"conditions":["encounters","trainers"],"name":"Leather Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"City Park","encounter_slug":"citypark","encounters":[{"monster":"cardiling","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[5,8]},{"monster":"cardiwing","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[8,11]},{"monster":"cataspike","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[6,9]},{"monster":"eyenemy","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[5,8]},{"monster":"axylightl","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"tourbidi","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"squabbit","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[8,12]},{"monster":"puparmor","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[9,14]}],"requiredEncounters":10,"trainers":[{"name":"Frances","sprite":"florist.png","monsters":[{"slug":"shybulb","level":8},{"slug":"shybulb","level":8}]}],"environment_slug":"forest","connections":{"route2":{"conditions":[],"name":"Route 2"},"leather-town":{"conditions":["encounters","trainers"],"name":"Leather Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/City_park.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/flower-city.json b/db/_generated/areas/flower-city.json new file mode 100644 index 0000000..477399d --- /dev/null +++ b/db/_generated/areas/flower-city.json @@ -0,0 +1 @@ +{"name":"Flower City","encounter_slug":"","encounters":[],"requiredEncounters":0,"trainers":[],"environment_slug":"interior","locations":{"healing_center":{"type":"healingCenter","price":30},"scoop_store":{"type":"shop","economy":"spyder_flower_scoop","items":[{"item_name":"potion","price":20,"cost":5},{"item_name":"revive","price":100,"cost":20},{"item_name":"tuxeball","price":50,"cost":10}]}},"events":[],"connections":{"route4":{"conditions":[],"name":"Route 4"},"route5":{"conditions":[],"name":"Route 5"},"side-route-a":{"conditions":[],"name":"Side Route A"}},"environment":{"slug":"interior","battle_graphics":{"island_back":"paper_back_island.png","island_front":"paper_front_island.png","background":"battle_bg03.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Flower_City.png\" \/>\n\n <rect data-location=\"healing_center\" x=\"224\" y=\"192\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n <rect data-location=\"scoop_store\" x=\"368\" y=\"320\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/leather-town.json b/db/_generated/areas/leather-town.json index 9cd0551..fc0e69e 100644 --- a/db/_generated/areas/leather-town.json +++ b/db/_generated/areas/leather-town.json @@ -1 +1 @@ -{"name":"Leather Town","encounter_slug":"","encounters":[],"requiredEncounters":0,"trainers":[],"environment_slug":"interior","shops":{"leather_scoop":[]},"connections":{"city-park":{"conditions":[],"name":"City Park"},"route3":{"conditions":[],"name":"Route 3"}},"environment":{"slug":"interior","battle_graphics":{"island_back":"paper_back_island.png","island_front":"paper_front_island.png","background":"battle_bg03.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"Leather Town","encounter_slug":"","encounters":[],"requiredEncounters":0,"trainers":[],"environment_slug":"interior","locations":{"healing_center":{"type":"healingCenter","price":20},"leather_scoop":{"type":"shop","economy":"leather_scoop","items":[{"item_name":"potion","price":20,"cost":5},{"item_name":"revive","price":100,"cost":20},{"item_name":"tuxeball","price":50,"cost":10}]}},"connections":{"city-park":{"conditions":[],"name":"City Park"},"route3":{"conditions":[],"name":"Route 3"}},"environment":{"slug":"interior","battle_graphics":{"island_back":"paper_back_island.png","island_front":"paper_front_island.png","background":"battle_bg03.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Leather_Town.png\" \/>\n\n <text x=\"323\" y=\"174\">Healing Center<\/text>\n <rect data-location=\"healing_center\" x=\"336\" y=\"97\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n\n <text x=\"226\" y=\"174\">Shop<\/text>\n <rect data-location=\"leather_scoop\" x=\"208\" y=\"97\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/lion-mountain.json b/db/_generated/areas/lion-mountain.json new file mode 100644 index 0000000..9edf988 --- /dev/null +++ b/db/_generated/areas/lion-mountain.json @@ -0,0 +1 @@ +{"name":"Lion Mountain","encounter_slug":"lion_mountain","encounters":[{"monster":"snowrilla","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[55,65]},{"monster":"snowrilla","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[65,75]},{"monster":"tadcool","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[55,65]},{"monster":"tadcool","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[65,75]},{"monster":"chillimp","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[55,65]},{"monster":"chillimp","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[65,75]},{"monster":"tux","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[55,65]},{"monster":"tux","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[65,75]}],"requiredEncounters":10,"trainers":[{"name":"Miner Jacques","sprite":"monk.png","monsters":[{"slug":"heronquak","level":55},{"slug":"jemuar","level":60}]}],"environment_slug":"snow","connections":{"sphalian-town":{"conditions":[],"name":"Sphalian Town"}},"environment":{"slug":"snow","battle_graphics":{"island_back":"snow_island.png","island_front":"snow_island.png","background":"snow_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 720 1600\"\n>\n <image href=\"\/db\/maps\/Buddha_mountain.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/paper-town.json b/db/_generated/areas/paper-town.json index 6a41be0..0a763ad 100644 --- a/db/_generated/areas/paper-town.json +++ b/db/_generated/areas/paper-town.json @@ -1 +1 @@ -{"name":"Paper Town","encounter_slug":"","encounters":[],"requiredEncounters":0,"trainers":[{"name":"Rival","monsters":[{"slug":"STARTER","level":2}],"inventory":[]}],"environment_slug":"interior","connections":{"route1":{"conditions":["encounters","trainers"],"name":"Route 1"}},"environment":{"slug":"interior","battle_graphics":{"island_back":"paper_back_island.png","island_front":"paper_front_island.png","background":"battle_bg03.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"Paper Town","locations":{"scoop_store":{"type":"shop","economy":"spyder_paper_mart","items":[{"item_name":"potion","price":20,"cost":5},{"item_name":"revive","price":100,"cost":20},{"item_name":"tuxeball","price":50,"cost":10}]}},"connections":{"route1":{"conditions":["encounters","trainers"],"name":"Route 1"},"sea-route-c":{"conditions":["area.sea-route-c"],"name":"Sea Route C"}},"encounters":[],"requiredEncounters":0,"trainers":[],"environment":null,"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 320\"\n>\n <image href=\"\/db\/maps\/Paper_town.png\" \/>\n\n <text x=\"294\" y=\"221\">Shop<\/text>\n <rect data-location=\"scoop_store\" x=\"272\" y=\"144\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route1.json b/db/_generated/areas/route1.json index 02a1af0..d9b88ed 100644 --- a/db/_generated/areas/route1.json +++ b/db/_generated/areas/route1.json @@ -1 +1 @@ -{"name":"Route 1","encounter_slug":"route1","encounters":[{"monster":"pairagrin","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"aardorn","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"cataspike","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"pairagrin","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]},{"monster":"aardorn","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]},{"monster":"cataspike","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]}],"requiredEncounters":10,"trainers":[{"name":"Bruder Mikki","sprite":"dragonrider.png","monsters":[{"slug":"memnomnom","level":5},{"slug":"jelillow","level":5}],"inventory":[{"slug":"potion","quantity":2}]}],"environment_slug":"forest","connections":{"paper-town":{"conditions":[],"name":"Paper Town"},"cotton-town":{"conditions":["encounters","trainers"],"name":"Cotton Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"Route 1","encounter_slug":"route1","encounters":[{"monster":"pairagrin","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"aardorn","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"cataspike","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4]},{"monster":"pairagrin","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]},{"monster":"aardorn","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]},{"monster":"cataspike","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[3,5]}],"requiredEncounters":10,"trainers":[{"name":"Bruder Mikki","sprite":"adventurer.png","monsters":[{"slug":"memnomnom","level":5},{"slug":"jelillow","level":5}],"inventory":[{"slug":"potion","quantity":2}]}],"environment_slug":"forest","connections":{"paper-town":{"conditions":[],"name":"Paper Town"},"cotton-town":{"conditions":["encounters","trainers"],"name":"Cotton Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 320\"\n>\n <image href=\"\/db\/maps\/Route_1.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route2.json b/db/_generated/areas/route2.json index 5ef92c5..5511453 100644 --- a/db/_generated/areas/route2.json +++ b/db/_generated/areas/route2.json @@ -1 +1 @@ -{"name":"Route 2","encounter_slug":"route2","encounters":[{"monster":"cardiling","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"aardorn","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"eyenemy","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"axylightl","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[4,7]},{"monster":"cataspike","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"cardiling","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6]},{"monster":"aardorn","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]},{"monster":"eyenemy","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]},{"monster":"axylightl","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[5,8]},{"monster":"cataspike","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]}],"requiredEncounters":10,"trainers":[{"name":"Rival","monsters":[{"slug":"cardiling","level":3},{"slug":"eyenemy","level":6},{"slug":"STARTER","level":6}],"inventory":[]}],"environment_slug":"forest","connections":{"cotton-town":{"conditions":[],"name":"Cotton Town"},"city-park":{"conditions":["encounters","trainers"],"name":"City Park"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"Route 2","encounter_slug":"route2","encounters":[{"monster":"cardiling","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"aardorn","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"eyenemy","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"axylightl","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[4,7]},{"monster":"cataspike","encounter_rate":2.5,"daytime":true,"exp_req_mod":1,"level_range":[3,6]},{"monster":"cardiling","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6]},{"monster":"aardorn","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]},{"monster":"eyenemy","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]},{"monster":"axylightl","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[5,8]},{"monster":"cataspike","encounter_rate":2.5,"daytime":false,"exp_req_mod":1,"level_range":[4,8]}],"requiredEncounters":10,"trainers":[{"name":"Rival Billie","sprite":"fashionista.png","monsters":[{"slug":"cardiling","level":3},{"slug":"eyenemy","level":6},{"slug":"STARTER","level":6}]}],"environment_slug":"forest","connections":{"cotton-town":{"conditions":[],"name":"Cotton Town"},"city-park":{"conditions":["encounters","trainers"],"name":"City Park"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 320\"\n>\n <image href=\"\/db\/maps\/Route_2.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route3.json b/db/_generated/areas/route3.json index fbd07f4..ca197c7 100644 --- a/db/_generated/areas/route3.json +++ b/db/_generated/areas/route3.json @@ -1 +1 @@ -{"name":"Route 3","encounter_slug":"route3","encounters":[{"monster":"cardiling","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"elofly","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"squabbit","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[8,11]},{"monster":"shybulb","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"cardiling","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"elofly","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"squabbit","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"shybulb","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]}],"requiredEncounters":10,"trainers":[{"name":"Miner Roxby","sprite":"miner.png","monsters":[{"slug":"rockitten","level":13},{"slug":"ignibus","level":13}]}],"environment_slug":"forest","connections":{"leather-town":{"conditions":[],"name":"Leather Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":false}
\ No newline at end of file +{"name":"Route 3","encounter_slug":"route3","encounters":[{"monster":"cardiling","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"elofly","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"squabbit","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[8,11]},{"monster":"shybulb","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[7,10]},{"monster":"cardiling","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"elofly","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"squabbit","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[9,12]},{"monster":"shybulb","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[9,12]}],"requiredEncounters":10,"trainers":[{"name":"Miner Roxby","sprite":"miner.png","monsters":[{"slug":"rockitten","level":13},{"slug":"ignibus","level":13}]}],"environment_slug":"forest","connections":{"leather-town":{"conditions":[],"name":"Leather Town"},"route4":{"conditions":["encounters","trainers"],"name":"Route 4"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Route_3.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route4.json b/db/_generated/areas/route4.json new file mode 100644 index 0000000..0e2fe11 --- /dev/null +++ b/db/_generated/areas/route4.json @@ -0,0 +1 @@ +{"name":"Route 4","encounter_slug":"route4","encounters":[{"monster":"elofly","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[11,14]},{"monster":"sapsnap","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[12,15]},{"monster":"aardorn","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[11,14]},{"monster":"katapill","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[11,14]},{"monster":"elofly","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[13,16]},{"monster":"sapsnap","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[13,16]},{"monster":"aardorn","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[13,16]},{"monster":"katapill","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[13,16]}],"requiredEncounters":10,"trainers":[{"name":"Soldier Marshall","sprite":"soldier.png","monsters":[{"slug":"puparmor","level":16},{"slug":"puparmor","level":16}]},{"name":"Rival Billie","sprite":"fashionista.png","monsters":[{"slug":"cardiwing","level":16},{"slug":"eyesore","level":16},{"slug":"viviphyta","level":16},{"slug":"STARTER","level":18}]}],"environment_slug":"forest","connections":{"route3":{"conditions":[],"name":"Route 3"},"flower-city":{"conditions":["encounters","trainers"],"name":"Flower City"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 320 640\"\n>\n <image href=\"\/db\/maps\/Route_4.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route5.json b/db/_generated/areas/route5.json new file mode 100644 index 0000000..e0677fe --- /dev/null +++ b/db/_generated/areas/route5.json @@ -0,0 +1 @@ +{"name":"Route 5","encounter_slug":"route5","encounters":[{"monster":"foofle","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[19,23]},{"monster":"vamporm","encounter_rate":3,"daytime":true,"exp_req_mod":1,"level_range":[16,20]},{"monster":"dracune","encounter_rate":1,"daytime":true,"exp_req_mod":1,"level_range":[18,22]},{"monster":"anoleaf","encounter_rate":3,"daytime":false,"exp_req_mod":1,"level_range":[18,22]},{"monster":"gectile","encounter_rate":1,"daytime":false,"exp_req_mod":1,"level_range":[22,26]}],"requiredEncounters":10,"trainers":[{"name":"Soldier Hunter","sprite":"soldier.png","monsters":[{"slug":"elofly","level":16},{"slug":"elofly","level":16},{"slug":"elowind","level":18}]}],"environment_slug":"forest","connections":{"flower-city":{"conditions":[],"name":"Flower City"},"timber-town":{"conditions":["encounters","trainers"],"name":"Timber Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 320\"\n>\n <image href=\"\/db\/maps\/Route_5.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route6.json b/db/_generated/areas/route6.json new file mode 100644 index 0000000..3c8f520 --- /dev/null +++ b/db/_generated/areas/route6.json @@ -0,0 +1 @@ +{"name":"Route 6","encounter_slug":"route6","encounters":[{"monster":"dandicub","encounter_rate":10,"daytime":true,"exp_req_mod":1,"level_range":[19,20]},{"monster":"dandylion","encounter_rate":5,"daytime":true,"exp_req_mod":1,"level_range":[21,23]},{"monster":"capiti","encounter_rate":10,"daytime":true,"exp_req_mod":1,"level_range":[19,22]},{"monster":"dandicub","encounter_rate":10,"daytime":false,"exp_req_mod":1,"level_range":[20,24]},{"monster":"dandylion","encounter_rate":5,"daytime":false,"exp_req_mod":1,"level_range":[22,24]},{"monster":"capiti","encounter_rate":10,"daytime":false,"exp_req_mod":1,"level_range":[20,24]}],"requiredEncounters":10,"trainers":[{"name":"Florist Frances","sprite":"florist.png","monsters":[{"slug":"narcileaf","level":30},{"slug":"shybulb","level":30},{"slug":"shybulb","level":30}]}],"environment_slug":"forest","connections":{"tunnel-b":{"conditions":[],"name":"Tunnel B"},"candy-town":{"conditions":["encounters","trainers"],"name":"Candy Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 320\"\n>\n <image href=\"\/db\/maps\/Route_6.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/route7.json b/db/_generated/areas/route7.json new file mode 100644 index 0000000..dffa7b4 --- /dev/null +++ b/db/_generated/areas/route7.json @@ -0,0 +1 @@ +{"name":"Route 7","encounter_slug":"route7","encounters":[{"monster":"pairagrim","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[35,40]},{"monster":"aardart","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[35,40]},{"monster":"weavifly","encounter_rate":3.5,"daytime":true,"exp_req_mod":1,"level_range":[35,40]},{"monster":"pantherafira","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[35,40]},{"monster":"flacono","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[35,40]},{"monster":"slichen","encounter_rate":3.5,"daytime":false,"exp_req_mod":1,"level_range":[35,40]}],"requiredEncounters":10,"trainers":[{"name":"Monk Statius","sprite":"monk.png","monsters":[{"slug":"aardart","level":30},{"slug":"pairagrim","level":30},{"slug":"bolt","level":30},{"slug":"fribbit","level":30}]}],"environment_slug":"forest","connections":{"side-route-a":{"conditions":[],"name":"Side Route A"},"sphalian-town":{"conditions":["encounters","trainers"],"name":"Sphalian Town"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Route_7.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/sea-route-c.json b/db/_generated/areas/sea-route-c.json new file mode 100644 index 0000000..5045969 --- /dev/null +++ b/db/_generated/areas/sea-route-c.json @@ -0,0 +1 @@ +{"name":"Sea Route C","encounter_slug":"default_encounter","encounters":[{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"eyenemy"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"dandicub"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cardiling"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"budaye"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cataspike"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"elofly"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"aardorn"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"nut"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"grimachin"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"spighter"}],"requiredEncounters":10,"trainers":[{"name":"Dragonrider Nigel","sprite":"dragonrider.png","monsters":[{"slug":"agnigon","level":36}]}],"environment_slug":"sea","connections":{"candy-town":{"conditions":[],"name":"Candy Town"},"paper-town":{"conditions":["encounters","trainers"],"name":"Paper Town"}},"environment":{"slug":"sea","battle_graphics":{"island_back":"water_island.png","island_front":"water_island.png","background":"sea_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Sea_Route_C.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/side-route-a.json b/db/_generated/areas/side-route-a.json new file mode 100644 index 0000000..76cb968 --- /dev/null +++ b/db/_generated/areas/side-route-a.json @@ -0,0 +1 @@ +{"name":"Side Route A","encounter_slug":"default_encounter","encounters":[{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"eyenemy"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"dandicub"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cardiling"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"budaye"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cataspike"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"elofly"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"aardorn"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"nut"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"grimachin"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"spighter"}],"requiredEncounters":10,"trainers":[{"name":"Rival Billie","sprite":"fashionista.png","monsters":[{"slug":"cardiwing","level":17},{"slug":"eyesore","level":17},{"slug":"viviphyta","level":17},{"slug":"STARTER","level":20}]}],"environment_slug":"forest","connections":{"flower-city":{"conditions":[],"name":"Flower City"},"route7":{"conditions":["encounters","trainers"],"name":"Route 7"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 320 640\"\n>\n <image href=\"\/db\/maps\/Side_Route_A.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/sphalian-town.json b/db/_generated/areas/sphalian-town.json new file mode 100644 index 0000000..5f436dd --- /dev/null +++ b/db/_generated/areas/sphalian-town.json @@ -0,0 +1 @@ +{"name":"Sphalian Town","locations":{"healing_center":{"type":"healingCenter","price":40}},"connections":{"route7":{"conditions":[],"name":"Route 7"},"lion-mountain":{"conditions":[],"name":"Lion Mountain"}},"encounters":[],"requiredEncounters":0,"trainers":[],"environment":null,"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 368 400\"\n>\n <image href=\"\/db\/maps\/Sphalian_town.png\" \/>\n\n <rect data-location=\"healing_center\" x=\"240\" y=\"48\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/timber-town.json b/db/_generated/areas/timber-town.json new file mode 100644 index 0000000..041309c --- /dev/null +++ b/db/_generated/areas/timber-town.json @@ -0,0 +1 @@ +{"name":"Timber Town","locations":{"healing_center":{"type":"healingCenter","price":20},"scoop_store":{"type":"shop","economy":"spyder_timber_scoop","items":[{"item_name":"potion","price":20,"cost":5},{"item_name":"revive","price":100,"cost":20},{"item_name":"tuxeball","price":50,"cost":10}]}},"connections":{"route5":{"conditions":[],"name":"Route 5"},"tunnel-b":{"conditions":[],"name":"Tunnel B"}},"encounters":[],"requiredEncounters":0,"trainers":[],"environment":null,"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 640 640\"\n>\n <image href=\"\/db\/maps\/Timber_Town.png\" \/>\n\n <rect data-location=\"healing_center\" x=\"96\" y=\"48\" width=\"80\" height=\"64\" stroke=\"red\" fill=\"transparent\" \/>\n <rect data-location=\"scoop_store\" x=\"191\" y=\"127\" width=\"82\" height=\"66\" stroke=\"red\" fill=\"transparent\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/_generated/areas/tunnel-b.json b/db/_generated/areas/tunnel-b.json new file mode 100644 index 0000000..bdf3a76 --- /dev/null +++ b/db/_generated/areas/tunnel-b.json @@ -0,0 +1 @@ +{"name":"Tunnel B","encounter_slug":"default_encounter","encounters":[{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"eyenemy"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"dandicub"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cardiling"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"budaye"},{"encounter_rate":0.5,"daytime":true,"exp_req_mod":1,"level_range":[2,4],"monster":"cataspike"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"elofly"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"aardorn"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"nut"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"grimachin"},{"encounter_rate":0.5,"daytime":false,"exp_req_mod":1,"level_range":[3,6],"monster":"spighter"}],"requiredEncounters":10,"trainers":[{"name":"Florist Iris","sprite":"florist.png","monsters":[{"slug":"tourbidi","level":18},{"slug":"tourbidi","level":18},{"slug":"tourbidi","level":18}]}],"environment_slug":"forest","connections":{"timber-town":{"conditions":[],"name":"Timber Town"},"route6":{"conditions":["encounters","trainers"],"name":"Route 6"}},"environment":{"slug":"forest","battle_graphics":{"island_back":"woodland_island.png","island_front":"woodland_island.png","background":"forest_background.png"},"battle_music":"music_battle_loop"},"map":"<svg\n version=\"1.1\"\n xmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n viewbox=\"0 0 320 640\"\n>\n <image href=\"\/db\/maps\/Tunnel_Route_B.png\" \/>\n<\/svg>\n"}
\ No newline at end of file diff --git a/db/areas.php b/db/areas.php index 185589e..d423a3e 100644 --- a/db/areas.php +++ b/db/areas.php @@ -8,10 +8,15 @@ foreach (scandir(__DIR__ . '/areas') as $file) { $area = json_decode(file_get_contents($filePath), true); $encounters = json_decode(@file_get_contents(dirname(__DIR__) . "/modules/tuxemon/mods/tuxemon/db/encounter/$area[encounter_slug].json") ?? '', true); - $environment = json_decode(file_get_contents(dirname(__DIR__) . "/modules/tuxemon/mods/tuxemon/db/environment/$area[environment_slug].json"), true); + $environment = json_decode(@file_get_contents(dirname(__DIR__) . "/modules/tuxemon/mods/tuxemon/db/environment/$area[environment_slug].json") ?? '', true); $map = @file_get_contents(__DIR__ . "/maps/$fileName.svg"); + $area['encounters'] ??= []; array_push($area['encounters'], ...$encounters['monsters'] ?? []); + $area['requiredEncounters'] ??= 0; + + $area['trainers'] ??= []; + $area['environment'] = $environment; $area['map'] = $map; diff --git a/db/areas/candy-town.json b/db/areas/candy-town.json new file mode 100644 index 0000000..59ddca0 --- /dev/null +++ b/db/areas/candy-town.json @@ -0,0 +1,26 @@ +{ + "name": "Candy Town", + + "locations": { + "hospital": { + "type": "healingCenter", + "price": 30 + }, + + "scoop_store": { + "type": "shop", + "economy": "spyder_candy_scoop", + "items": [] + } + }, + + "connections": { + "route6": { + "conditions": [] + }, + + "sea-route-c": { + "conditions": [] + } + } +} diff --git a/db/areas/city-park.json b/db/areas/city-park.json index d0e5af3..865df3c 100644 --- a/db/areas/city-park.json +++ b/db/areas/city-park.json @@ -20,8 +20,7 @@ "slug": "shybulb", "level": 8 } - ], - "inventory": [] + ] } ], diff --git a/db/areas/flower-city.json b/db/areas/flower-city.json new file mode 100644 index 0000000..1e7ebf9 --- /dev/null +++ b/db/areas/flower-city.json @@ -0,0 +1,42 @@ +{ + "name": "Flower City", + + "encounter_slug": "", + + "encounters": [], + + "requiredEncounters": 0, + + "trainers": [], + + "environment_slug": "interior", + + "locations": { + "healing_center": { + "type": "healingCenter", + "price": 30 + }, + + "scoop_store": { + "type": "shop", + "economy": "spyder_flower_scoop", + "items": [] + } + }, + + "events": {}, + + "connections": { + "route4": { + "conditions": [] + }, + + "route5": { + "conditions": [] + }, + + "side-route-a": { + "conditions": [] + } + } +} diff --git a/db/areas/lion-mountain.json b/db/areas/lion-mountain.json new file mode 100644 index 0000000..fc804f8 --- /dev/null +++ b/db/areas/lion-mountain.json @@ -0,0 +1,34 @@ +{ + "name": "Lion Mountain", + + "encounter_slug": "lion_mountain", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Miner Jacques", + "sprite": "monk.png", + "monsters": [ + { + "slug": "heronquak", + "level": 55 + }, + { + "slug": "jemuar", + "level": 60 + } + ] + } + ], + + "environment_slug": "snow", + + "connections": { + "sphalian-town": { + "conditions": [] + } + } +} diff --git a/db/areas/paper-town.json b/db/areas/paper-town.json index 688dd7f..f3d3255 100644 --- a/db/areas/paper-town.json +++ b/db/areas/paper-town.json @@ -1,26 +1,18 @@ { "name": "Paper Town", - "encounter_slug": "", + "locations": { + "home": { + "type": "healingCenter", + "price": 0 + }, - "encounters": [], - - "requiredEncounters": 0, - - "trainers": [ - { - "name": "Rival", - "monsters": [ - { - "slug": "STARTER", - "level": 2 - } - ], - "inventory": [] + "scoop_store": { + "type": "shop", + "economy": "spyder_paper_mart", + "items": [] } - ], - - "environment_slug": "interior", + }, "connections": { "route1": { @@ -28,6 +20,12 @@ "encounters", "trainers" ] + }, + + "sea-route-c": { + "conditions": [ + "area.sea-route-c" + ] } } } diff --git a/db/areas/route1.json b/db/areas/route1.json index 5c49e04..0c9523f 100644 --- a/db/areas/route1.json +++ b/db/areas/route1.json @@ -10,7 +10,7 @@ "trainers": [ { "name": "Bruder Mikki", - "sprite": "dragonrider.png", + "sprite": "adventurer.png", "monsters": [ { "slug": "memnomnom", diff --git a/db/areas/route2.json b/db/areas/route2.json index b08e1af..5e56ad9 100644 --- a/db/areas/route2.json +++ b/db/areas/route2.json @@ -9,7 +9,8 @@ "trainers": [ { - "name": "Rival", + "name": "Rival Billie", + "sprite": "fashionista.png", "monsters": [ { "slug": "cardiling", @@ -23,8 +24,7 @@ "slug": "STARTER", "level": 6 } - ], - "inventory": [] + ] } ], diff --git a/db/areas/route3.json b/db/areas/route3.json index ea59234..5dbcba3 100644 --- a/db/areas/route3.json +++ b/db/areas/route3.json @@ -29,6 +29,13 @@ "connections": { "leather-town": { "conditions": [] + }, + + "route4": { + "conditions": [ + "encounters", + "trainers" + ] } } } diff --git a/db/areas/route4.json b/db/areas/route4.json new file mode 100644 index 0000000..a0c4a97 --- /dev/null +++ b/db/areas/route4.json @@ -0,0 +1,63 @@ +{ + "name": "Route 4", + + "encounter_slug": "route4", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Soldier Marshall", + "sprite": "soldier.png", + "monsters": [ + { + "slug": "puparmor", + "level": 16 + }, + { + "slug": "puparmor", + "level": 16 + } + ] + }, + { + "name": "Rival Billie", + "sprite": "fashionista.png", + "monsters": [ + { + "slug": "cardiwing", + "level": 16 + }, + { + "slug": "eyesore", + "level": 16 + }, + { + "slug": "viviphyta", + "level": 16 + }, + { + "slug": "STARTER", + "level": 18 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "route3": { + "conditions": [] + }, + + "flower-city": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/route5.json b/db/areas/route5.json new file mode 100644 index 0000000..368ddbc --- /dev/null +++ b/db/areas/route5.json @@ -0,0 +1,45 @@ +{ + "name": "Route 5", + + "encounter_slug": "route5", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Soldier Hunter", + "sprite": "soldier.png", + "monsters": [ + { + "slug": "elofly", + "level": 16 + }, + { + "slug": "elofly", + "level": 16 + }, + { + "slug": "elowind", + "level": 18 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "flower-city": { + "conditions": [] + }, + + "timber-town": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/route6.json b/db/areas/route6.json new file mode 100644 index 0000000..f30d050 --- /dev/null +++ b/db/areas/route6.json @@ -0,0 +1,45 @@ +{ + "name": "Route 6", + + "encounter_slug": "route6", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Florist Frances", + "sprite": "florist.png", + "monsters": [ + { + "slug": "narcileaf", + "level": 30 + }, + { + "slug": "shybulb", + "level": 30 + }, + { + "slug": "shybulb", + "level": 30 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "tunnel-b": { + "conditions": [] + }, + + "candy-town": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/route7.json b/db/areas/route7.json new file mode 100644 index 0000000..647227a --- /dev/null +++ b/db/areas/route7.json @@ -0,0 +1,49 @@ +{ + "name": "Route 7", + + "encounter_slug": "route7", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Monk Statius", + "sprite": "monk.png", + "monsters": [ + { + "slug": "aardart", + "level": 30 + }, + { + "slug": "pairagrim", + "level": 30 + }, + { + "slug": "bolt", + "level": 30 + }, + { + "slug": "fribbit", + "level": 30 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "side-route-a": { + "conditions": [] + }, + + "sphalian-town": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/sea-route-c.json b/db/areas/sea-route-c.json new file mode 100644 index 0000000..34526f5 --- /dev/null +++ b/db/areas/sea-route-c.json @@ -0,0 +1,37 @@ +{ + "name": "Sea Route C", + + "encounter_slug": "default_encounter", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Dragonrider Nigel", + "sprite": "dragonrider.png", + "monsters": [ + { + "slug": "agnigon", + "level": 36 + } + ] + } + ], + + "environment_slug": "sea", + + "connections": { + "candy-town": { + "conditions": [] + }, + + "paper-town": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/side-route-a.json b/db/areas/side-route-a.json new file mode 100644 index 0000000..b83c51b --- /dev/null +++ b/db/areas/side-route-a.json @@ -0,0 +1,49 @@ +{ + "name": "Side Route A", + + "encounter_slug": "default_encounter", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Rival Billie", + "sprite": "fashionista.png", + "monsters": [ + { + "slug": "cardiwing", + "level": 17 + }, + { + "slug": "eyesore", + "level": 17 + }, + { + "slug": "viviphyta", + "level": 17 + }, + { + "slug": "STARTER", + "level": 20 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "flower-city": { + "conditions": [] + }, + + "route7": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/areas/sphalian-town.json b/db/areas/sphalian-town.json new file mode 100644 index 0000000..4c70aa5 --- /dev/null +++ b/db/areas/sphalian-town.json @@ -0,0 +1,20 @@ +{ + "name": "Sphalian Town", + + "locations": { + "healing_center": { + "type": "healingCenter", + "price": 40 + } + }, + + "connections": { + "route7": { + "conditions": [] + }, + + "lion-mountain": { + "conditions": [] + } + } +} diff --git a/db/areas/timber-town.json b/db/areas/timber-town.json new file mode 100644 index 0000000..bfb9ca7 --- /dev/null +++ b/db/areas/timber-town.json @@ -0,0 +1,26 @@ +{ + "name": "Timber Town", + + "locations": { + "healing_center": { + "type": "healingCenter", + "price": 20 + }, + + "scoop_store": { + "type": "shop", + "economy": "spyder_timber_scoop", + "items": [] + } + }, + + "connections": { + "route5": { + "conditions": [] + }, + + "tunnel-b": { + "conditions": [] + } + } +} diff --git a/db/areas/tunnel-b.json b/db/areas/tunnel-b.json new file mode 100644 index 0000000..0e7954c --- /dev/null +++ b/db/areas/tunnel-b.json @@ -0,0 +1,45 @@ +{ + "name": "Tunnel B", + + "encounter_slug": "default_encounter", + + "encounters": [], + + "requiredEncounters": 10, + + "trainers": [ + { + "name": "Florist Iris", + "sprite": "florist.png", + "monsters": [ + { + "slug": "tourbidi", + "level": 18 + }, + { + "slug": "tourbidi", + "level": 18 + }, + { + "slug": "tourbidi", + "level": 18 + } + ] + } + ], + + "environment_slug": "forest", + + "connections": { + "timber-town": { + "conditions": [] + }, + + "route6": { + "conditions": [ + "encounters", + "trainers" + ] + } + } +} diff --git a/db/maps/Buddha_mountain.png b/db/maps/Buddha_mountain.png Binary files differnew file mode 100644 index 0000000..96fb617 --- /dev/null +++ b/db/maps/Buddha_mountain.png diff --git a/db/maps/Candy_Town.png b/db/maps/Candy_Town.png Binary files differnew file mode 100644 index 0000000..ad067cf --- /dev/null +++ b/db/maps/Candy_Town.png diff --git a/db/maps/City_park.png b/db/maps/City_park.png Binary files differnew file mode 100644 index 0000000..01d67c0 --- /dev/null +++ b/db/maps/City_park.png diff --git a/db/maps/Flower_City.png b/db/maps/Flower_City.png Binary files differnew file mode 100644 index 0000000..2b9527a --- /dev/null +++ b/db/maps/Flower_City.png diff --git a/db/maps/Leather_Town.png b/db/maps/Leather_Town.png Binary files differnew file mode 100644 index 0000000..0599799 --- /dev/null +++ b/db/maps/Leather_Town.png diff --git a/db/maps/Paper_town.png b/db/maps/Paper_town.png Binary files differnew file mode 100644 index 0000000..1eb12ef --- /dev/null +++ b/db/maps/Paper_town.png diff --git a/db/maps/Route_1.png b/db/maps/Route_1.png Binary files differnew file mode 100644 index 0000000..b34e1b2 --- /dev/null +++ b/db/maps/Route_1.png diff --git a/db/maps/Route_2.png b/db/maps/Route_2.png Binary files differnew file mode 100644 index 0000000..ffe3c1b --- /dev/null +++ b/db/maps/Route_2.png diff --git a/db/maps/Route_3.png b/db/maps/Route_3.png Binary files differnew file mode 100644 index 0000000..a772dbb --- /dev/null +++ b/db/maps/Route_3.png diff --git a/db/maps/Route_4.png b/db/maps/Route_4.png Binary files differnew file mode 100644 index 0000000..13510c6 --- /dev/null +++ b/db/maps/Route_4.png diff --git a/db/maps/Route_5.png b/db/maps/Route_5.png Binary files differnew file mode 100644 index 0000000..793e2d4 --- /dev/null +++ b/db/maps/Route_5.png diff --git a/db/maps/Route_6.png b/db/maps/Route_6.png Binary files differnew file mode 100644 index 0000000..30082b5 --- /dev/null +++ b/db/maps/Route_6.png diff --git a/db/maps/Route_7.png b/db/maps/Route_7.png Binary files differnew file mode 100644 index 0000000..4600d3e --- /dev/null +++ b/db/maps/Route_7.png diff --git a/db/maps/Sea_Route_C.png b/db/maps/Sea_Route_C.png Binary files differnew file mode 100644 index 0000000..4afeb1a --- /dev/null +++ b/db/maps/Sea_Route_C.png diff --git a/db/maps/Side_Route_A.png b/db/maps/Side_Route_A.png Binary files differnew file mode 100644 index 0000000..3a13711 --- /dev/null +++ b/db/maps/Side_Route_A.png diff --git a/db/maps/Sphalian_town.png b/db/maps/Sphalian_town.png Binary files differnew file mode 100644 index 0000000..87c9de5 --- /dev/null +++ b/db/maps/Sphalian_town.png diff --git a/db/maps/Timber_Town.png b/db/maps/Timber_Town.png Binary files differnew file mode 100644 index 0000000..e81419f --- /dev/null +++ b/db/maps/Timber_Town.png diff --git a/db/maps/Tunnel_Route_B.png b/db/maps/Tunnel_Route_B.png Binary files differnew file mode 100644 index 0000000..9b6cb0d --- /dev/null +++ b/db/maps/Tunnel_Route_B.png diff --git a/db/maps/Tunnel_Route_B_-_Below.png b/db/maps/Tunnel_Route_B_-_Below.png Binary files differnew file mode 100644 index 0000000..84e3645 --- /dev/null +++ b/db/maps/Tunnel_Route_B_-_Below.png diff --git a/db/maps/candy-town.svg b/db/maps/candy-town.svg new file mode 100644 index 0000000..2dab5f3 --- /dev/null +++ b/db/maps/candy-town.svg @@ -0,0 +1,10 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Candy_Town.png" /> + + <rect data-location="hospital" x="127" y="431" width="210" height="130" stroke="red" fill="transparent" /> + <rect data-location="scoop_store" x="17" y="144" width="80" height="64" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/city-park.svg b/db/maps/city-park.svg new file mode 100644 index 0000000..91a32cd --- /dev/null +++ b/db/maps/city-park.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/City_park.png" /> +</svg> diff --git a/db/maps/flower-city.svg b/db/maps/flower-city.svg new file mode 100644 index 0000000..dc4c4b2 --- /dev/null +++ b/db/maps/flower-city.svg @@ -0,0 +1,10 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Flower_City.png" /> + + <rect data-location="healing_center" x="224" y="192" width="80" height="64" stroke="red" fill="transparent" /> + <rect data-location="scoop_store" x="368" y="320" width="80" height="64" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/leather-town.svg b/db/maps/leather-town.svg new file mode 100644 index 0000000..9607b32 --- /dev/null +++ b/db/maps/leather-town.svg @@ -0,0 +1,13 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Leather_Town.png" /> + + <text x="323" y="174">Healing Center</text> + <rect data-location="healing_center" x="336" y="97" width="80" height="64" stroke="red" fill="transparent" /> + + <text x="226" y="174">Shop</text> + <rect data-location="leather_scoop" x="208" y="97" width="80" height="64" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/lion-mountain.svg b/db/maps/lion-mountain.svg new file mode 100644 index 0000000..6367992 --- /dev/null +++ b/db/maps/lion-mountain.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 720 1600" +> + <image href="/db/maps/Buddha_mountain.png" /> +</svg> diff --git a/db/maps/paper-town.svg b/db/maps/paper-town.svg new file mode 100644 index 0000000..b0c929d --- /dev/null +++ b/db/maps/paper-town.svg @@ -0,0 +1,10 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 320" +> + <image href="/db/maps/Paper_town.png" /> + + <text x="294" y="221">Shop</text> + <rect data-location="scoop_store" x="272" y="144" width="80" height="64" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/route1.svg b/db/maps/route1.svg new file mode 100644 index 0000000..b7f1647 --- /dev/null +++ b/db/maps/route1.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 320" +> + <image href="/db/maps/Route_1.png" /> +</svg> diff --git a/db/maps/route2.svg b/db/maps/route2.svg new file mode 100644 index 0000000..7471402 --- /dev/null +++ b/db/maps/route2.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 320" +> + <image href="/db/maps/Route_2.png" /> +</svg> diff --git a/db/maps/route3.svg b/db/maps/route3.svg new file mode 100644 index 0000000..c9f8196 --- /dev/null +++ b/db/maps/route3.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Route_3.png" /> +</svg> diff --git a/db/maps/route4.svg b/db/maps/route4.svg new file mode 100644 index 0000000..4f60aec --- /dev/null +++ b/db/maps/route4.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 320 640" +> + <image href="/db/maps/Route_4.png" /> +</svg> diff --git a/db/maps/route5.svg b/db/maps/route5.svg new file mode 100644 index 0000000..3a776da --- /dev/null +++ b/db/maps/route5.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 320" +> + <image href="/db/maps/Route_5.png" /> +</svg> diff --git a/db/maps/route6.svg b/db/maps/route6.svg new file mode 100644 index 0000000..84ce82d --- /dev/null +++ b/db/maps/route6.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 320" +> + <image href="/db/maps/Route_6.png" /> +</svg> diff --git a/db/maps/route7.svg b/db/maps/route7.svg new file mode 100644 index 0000000..038bc9b --- /dev/null +++ b/db/maps/route7.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Route_7.png" /> +</svg> diff --git a/db/maps/sea-route-c.svg b/db/maps/sea-route-c.svg new file mode 100644 index 0000000..aa93f1e --- /dev/null +++ b/db/maps/sea-route-c.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Sea_Route_C.png" /> +</svg> diff --git a/db/maps/side-route-a.svg b/db/maps/side-route-a.svg new file mode 100644 index 0000000..48967fe --- /dev/null +++ b/db/maps/side-route-a.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 320 640" +> + <image href="/db/maps/Side_Route_A.png" /> +</svg> diff --git a/db/maps/sphalian-town.svg b/db/maps/sphalian-town.svg new file mode 100644 index 0000000..4b9e51f --- /dev/null +++ b/db/maps/sphalian-town.svg @@ -0,0 +1,9 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 368 400" +> + <image href="/db/maps/Sphalian_town.png" /> + + <rect data-location="healing_center" x="240" y="48" width="80" height="64" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/timber-town.svg b/db/maps/timber-town.svg new file mode 100644 index 0000000..5b76f85 --- /dev/null +++ b/db/maps/timber-town.svg @@ -0,0 +1,10 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 640 640" +> + <image href="/db/maps/Timber_Town.png" /> + + <rect data-location="healing_center" x="96" y="48" width="80" height="64" stroke="red" fill="transparent" /> + <rect data-location="scoop_store" x="191" y="127" width="82" height="66" stroke="red" fill="transparent" /> +</svg> diff --git a/db/maps/tunnel-b-underground.svg b/db/maps/tunnel-b-underground.svg new file mode 100644 index 0000000..af07768 --- /dev/null +++ b/db/maps/tunnel-b-underground.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 320 640" +> + <image href="/db/maps/Tunnel_Route_B_-_Below.png" /> +</svg> diff --git a/db/maps/tunnel-b.svg b/db/maps/tunnel-b.svg new file mode 100644 index 0000000..19bc73a --- /dev/null +++ b/db/maps/tunnel-b.svg @@ -0,0 +1,7 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + viewbox="0 0 320 640" +> + <image href="/db/maps/Tunnel_Route_B.png" /> +</svg> @@ -4,6 +4,9 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>TuxemonClicker</title> + <link rel="icon" href="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/tuxemon.png"> + <link rel="stylesheet" href="/resources/css/variables.css" /> <link rel="stylesheet" href="/resources/css/page.css" /> <link rel="stylesheet" href="/resources/css/battle.css" /> @@ -25,18 +28,20 @@ <div id="techniques"></div> </div> - <div id="scene__town" class="hidden"></div> + <div id="scene__town" class="hidden"> + <div data-template-slot="map"></div> + </div> <div id="log"></div> <div id="status"> <div class="status__area"> - <span><img data-template-slot="showMap" src="/modules/tuxemon/mods/tuxemon/gfx/items/app_map.png" /> <span data-template-slot="area" title="Area"></span></span> + <span title="Area"><img data-template-slot="showMap" src="/modules/tuxemon/mods/tuxemon/gfx/items/app_map.png" /> <span data-template-slot="area"></span></span> </div> <div class="status__numbers"> - <span><i title="Money">¤</i> <span data-template-slot="money"></span></span> - <span><img src="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/tuxemon.png" title="Monster Progress" /> <span data-template-slot="monsterProgress"></span></span> - <span><img src="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/player.png" title="Trainer Progress" style="filter: invert(1);" /> <span data-template-slot="trainerProgress"></span></span> + <span title="Money">¤ <span data-template-slot="money"></span></span> + <span title="Monster Progress"><img src="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/tuxemon.png" /> <span data-template-slot="monsterProgress"></span></span> + <span title="Trainer Progress"><img src="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/player.png" style="filter: invert(1);" /> <span data-template-slot="trainerProgress"></span></span> </div> <div class="status__actions"> <button data-template-slot="nextTrainer" class="menu-button">⇒ Next Trainer</button> @@ -168,6 +173,25 @@ </div> </template> + <template id="tpl___healing-center"> + <div class="healing-center"> + <div>Price for Full Heal per Tuxemon: <span data-template-slot="price"></span></div> + <button data-template-slot="heal" class="menu-button">Select to Heal</button> + </div> + </template> + + <template id="tpl___shop"> + <div class="shop"></div> + </template> + + <template id="tpl___shop__item"> + <div class="shop__item"> + <img data-template-slot="sprite" src="" /> + <span data-template-slot="name"></span> + <span data-template-slot="price"></span> + </div> + </template> + <template id="tpl___party"> <div class="party"> <div data-template-slot="monsters" class="party__monsters"></div> @@ -188,6 +212,7 @@ Lv. <span data-template-slot="level"></span> </div> <div> + <span data-template-slot="statusEffect"></span> HP <span data-template-slot="hpText"></span> </div> </div> @@ -309,13 +334,13 @@ <select data-template-slot="language"></select> </label> - <br><br> - <label> Currency <select data-template-slot="currency"></select> <div>Last Updated: <span data-template-slot="currency.lastUpdated"></span></div> </label> + + <button data-template-slot="highlight" class="menu-button">Highlight Interactive Elements</button> </div> </template> diff --git a/resources/css/battle.css b/resources/css/battle.css index 748dad1..681b2e6 100644 --- a/resources/css/battle.css +++ b/resources/css/battle.css @@ -7,7 +7,6 @@ flex-direction: column; justify-content: space-between; - background-image: url('/modules/tuxemon/mods/tuxemon/gfx/ui/combat/sea_background.png'); background-size: cover; } diff --git a/resources/css/menu.css b/resources/css/menu.css index 8b0cb0b..82ba18e 100644 --- a/resources/css/menu.css +++ b/resources/css/menu.css @@ -112,15 +112,24 @@ .status__area > span > span { margin: 0 0.5rem; } +.status__area img { + cursor: pointer; +} .status__numbers { - display: flex; - justify-content: space-between; + display: grid; + grid-template-columns: 1fr 1fr 1fr; } .status__numbers > span { display: flex; align-items: center; } +.status__numbers > span:nth-child(2) { + justify-content: center; +} +.status__numbers > span:nth-child(3) { + justify-content: flex-end; +} .status__numbers > span > span { margin-left: 0.5rem; } @@ -325,3 +334,18 @@ font-size: 2rem; width: 80vw; } + + + + +.menu__settings { + padding: 1rem; + display: grid; + grid-gap: 1rem; +} + +.setting-highlight { + border: 2px solid yellow; + stroke: yellow; + stroke-width: 2px; +} diff --git a/resources/css/page.css b/resources/css/page.css index 57c46a5..635a160 100644 --- a/resources/css/page.css +++ b/resources/css/page.css @@ -27,3 +27,13 @@ img { .hidden { display: none; } + +svg { + width: 100%; + height: 100%; + display: block; +} + +svg [data-location] { + cursor: pointer; +} diff --git a/resources/css/town.css b/resources/css/town.css index b8be144..832c3d8 100644 --- a/resources/css/town.css +++ b/resources/css/town.css @@ -1,11 +1,25 @@ #scene__town {} -#scene__town svg { - width: 100%; - height: 100%; - display: block; + + + +.healing-center { + padding: 1rem; +} + + + + +.shop { + padding: 1rem; + + display: grid; + grid-gap: 1rem; } -svg [data-location] { +.shop__item { + display: flex; + justify-content: space-between; + align-items: center; cursor: pointer; } diff --git a/resources/js/classes/Area.js b/resources/js/classes/Area.js index b0bd710..e8d7acc 100644 --- a/resources/js/classes/Area.js +++ b/resources/js/classes/Area.js @@ -35,6 +35,9 @@ class Area { return DB.areas[this.slug].map; } + /** + * @returns {Object[]} + */ get locations () { return DB.areas[this.slug].locations; } diff --git a/resources/js/classes/Item.js b/resources/js/classes/Item.js index 9da6a92..40089f2 100644 --- a/resources/js/classes/Item.js +++ b/resources/js/classes/Item.js @@ -20,7 +20,13 @@ class Item { } get sprite () { - return DB.items[this.slug].sprite; + const sprite = DB.items[this.slug].sprite; + + if (sprite) { + return '/modules/tuxemon/mods/tuxemon/' + sprite; + } + + return ''; } get conditions () { diff --git a/resources/js/classes/Monster.js b/resources/js/classes/Monster.js index 84ea5da..c058a75 100644 --- a/resources/js/classes/Monster.js +++ b/resources/js/classes/Monster.js @@ -62,6 +62,9 @@ class Monster { } } + /** + * @returns {string[]} + */ get types () { return DB.monsters[this.slug].types; } @@ -74,6 +77,18 @@ class Monster { return DB.monsters[this.slug].moveset; } + get catch_rate () { + return DB.monsters[this.slug].catch_rate; + } + + get upper_catch_resistance () { + return DB.monsters[this.slug].upper_catch_resistance; + } + + get lower_catch_resistance () { + return DB.monsters[this.slug].lower_catch_resistance; + } + /** * @returns {DB_Evolution[]} */ diff --git a/resources/js/classes/State.js b/resources/js/classes/State.js index 085d1c7..1a65efe 100644 --- a/resources/js/classes/State.js +++ b/resources/js/classes/State.js @@ -26,6 +26,11 @@ class State { currentArea = null; /** + * @type {AreaSlug} + */ + lastVisitedTown = ''; + + /** * @type {number} */ turn = 0; diff --git a/resources/js/classes/StatusEffect.js b/resources/js/classes/StatusEffect.js index e1ae9c9..d161761 100644 --- a/resources/js/classes/StatusEffect.js +++ b/resources/js/classes/StatusEffect.js @@ -18,6 +18,9 @@ class StatusEffect { else if (['charging'].includes(this.slug)) { this.turnsLeft = 2; } + else if (['faint'].includes(this.slug)) { + this.turnsLeft = Number.MAX_SAFE_INTEGER; + } else if (this.category === 'positive') { this.turnsLeft = Math.ceil(Math.random() * 6) + 4; } diff --git a/resources/js/definitions.js b/resources/js/definitions.js index 338fdf7..d399a3c 100644 --- a/resources/js/definitions.js +++ b/resources/js/definitions.js @@ -1,6 +1,7 @@ /** * @typedef {string} MonsterSlug * @typedef {string} TechniqueSlug + * @typedef {string} AreaSlug */ // diff --git a/resources/js/formula.js b/resources/js/formula.js index 7223cb8..f28ce2d 100644 --- a/resources/js/formula.js +++ b/resources/js/formula.js @@ -95,13 +95,89 @@ function calculateAwardedExperience (opposingMonster, participants) { /** * @param {Monster} opposingMonster * - * @returns {number[]} + * @returns {number} */ function calculateAwardedMoney (opposingMonster) { let money = opposingMonster.level * opposingMonster.moneyModifier; - const baseDecimalDiff = 2 - DB.currencies.map[Memory.state.Settings.currency].decimals; - money = money * Math.pow(10, baseDecimalDiff); + money = convertToCurrencyBase(money); return money; } + +/** + * @param {Monster} playerMonster + * @param {Monster} opposingMonster + * @param {Item} ball + * + * @returns {boolean} + */ +function checkCapture (playerMonster, opposingMonster, ball) { + const MAX_CATCH_RATE = 255; + const MAX_ATTEMPT_RATE = 65536; + const ATTEMPT_CONSTANT = 524325; + + // status effect + let STATUS_MODIFER = 1.0; + if (opposingMonster.statusEffect && opposingMonster.statusEffect.category === 'negative') { + STATUS_MODIFER = 1.2; + } + + // ball + let BALL_MODIFIER = 1.0; + if (ball.slug === 'tuxeball_wood') { + if (opposingMonster.types.includes(ElementType.wood)) { + BALL_MODIFIER = 1.5 + } else { + BALL_MODIFIER = 0.2; + } + } + else if (ball.slug === 'tuxeball_fire') { + if (opposingMonster.types.includes(ElementType.fire)) { + BALL_MODIFIER = 1.5 + } else { + BALL_MODIFIER = 0.2; + } + } + else if (ball.slug === 'tuxeball_earth') { + if (opposingMonster.types.includes(ElementType.earth)) { + BALL_MODIFIER = 1.5 + } else { + BALL_MODIFIER = 0.2; + } + } + else if (ball.slug === 'tuxeball_metal') { + if (opposingMonster.types.includes(ElementType.metal)) { + BALL_MODIFIER = 1.5 + } else { + BALL_MODIFIER = 0.2; + } + } + else if (ball.slug === 'tuxeball_water') { + if (opposingMonster.types.includes(ElementType.water)) { + BALL_MODIFIER = 1.5 + } else { + BALL_MODIFIER = 0.2; + } + } + + // calculate + const catchCheck = Math.max( + (3 * opposingMonster.hp - 2 * playerMonster.hp) + * opposingMonster.catch_rate + * STATUS_MODIFER + * BALL_MODIFIER + / (3 * opposingMonster.hp), + 1 + ); + + let attemptCheck = ATTEMPT_CONSTANT / ( + Math.sqrt(Math.sqrt(MAX_CATCH_RATE / catchCheck)) * 8 + ) + + const catchResistance = Math.random() * (opposingMonster.upper_catch_resistance - opposingMonster.lower_catch_resistance) + opposingMonster.lower_catch_resistance; + + attemptCheck = attemptCheck * catchResistance; + + return Math.random() * MAX_ATTEMPT_RATE > Math.round(attemptCheck); +} diff --git a/resources/js/game.js b/resources/js/game.js index 9370382..663e6b0 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -1,5 +1,6 @@ const Game = { phases: { + preTurnBegin: [], preTurn: [], battle: { preAction: { @@ -16,6 +17,7 @@ const Game = { }, }, postTurn: [], + postTurnEnd: [], }, logMessages: [], @@ -73,6 +75,11 @@ const Game = { Game.logTurn('end'); + for (const event of Game.phases.postTurnEnd) { + event(); + } + Game.phases.postTurnEnd = []; + UI.progressTurn(); Game.isProgressingTurn = false; }, @@ -133,29 +140,33 @@ const Game = { } Game.removeBattlePhaseEvents('action', 'opponent'); + Memory.state.player.activeMonster.statusEffect = await fetchStatusEffect('faint'); + // whole party defeated if (!Memory.state.player.monsters.some((monster) => monster.hp > 0)) { - if (Game.isBattleType('trainer')) { - if (Memory.state.currentArea.encounters.length > 0) { - await Game.encounterWildMonster(); - } else { - await Game.encounterTrainer(); - } - } + Game.isInBattle = false; + Memory.state.currentArea.monsterProgress = 0; - else if (Game.isBattleType('monster')) { - if (Memory.state.currentArea.monsterProgress < Memory.state.currentArea.requiredEncounters) { - Memory.state.currentArea.monsterProgress = 0; - UI.drawStatus(); - } - - await Game.encounterWildMonster(); - } + // go to last visited town + await Game.goToArea(Memory.state.lastVisitedTown); // heal all monsters full + let totalHealingCenterPrice = 0; for (const monster of Memory.state.player.monsters) { monster.hp = monster.stats.hp; + monster.statusEffect = null; + + // pay healing center + const healingCenterPrice = Object.values(Memory.state.currentArea.locations).find((location) => location.type === 'healingCenter').price; + totalHealingCenterPrice += healingCenterPrice; } + + Memory.state.money -= totalHealingCenterPrice; + + Game.addPhaseEvent('postTurnEnd', () => { + Game.log(`Whited out!`); + Game.log(`Payed ${formatPrice(totalHealingCenterPrice)} for full recovery at ${Memory.state.currentArea.name}!`); + }); } // party members still left @@ -189,7 +200,7 @@ const Game = { }, /** - * @param {('preTurn' | 'postTurn')} phase + * @param {('preTurnBegin' | 'preTurn' | 'postTurn' | 'postTurnEnd')} phase * @param {Function} event */ addPhaseEvent (phase, event) { @@ -459,6 +470,14 @@ const Game = { }); } + // confused + else if (monster.statusEffect.slug === 'confused') { + Game.addBattlePhaseEvent('preAction', monster, () => { + // TODO + logStatusIs(); + }); + } + // stuck else if (monster.statusEffect.slug === 'stuck') { for (const technique of monster.activeTechniques) { @@ -533,25 +552,15 @@ const Game = { }); }, - /** - * @param {MouseEvent} event - */ - async battleClick (event) { - if (Game.isLoadingArea || Game.isProgressingTurn) { - return; - } - - Game.isInBattle = true; - UI.battleClickEvent = event; - - // player - await Game.tryUseTechnique(Memory.state.activeTechnique, Memory.state.player.activeMonster, Memory.state.opponent.activeMonster); - - // opponent + async opponentTryUseTechnique () { if (!Game.opponentActionTimeout) { let speedDifference = Memory.state.opponent.activeMonster.stats.speed - Memory.state.player.activeMonster.stats.speed; if (speedDifference > 0) speedDifference = speedDifference / 2; - else if (speedDifference < 0) speedDifference = speedDifference * 2; + else if (speedDifference < 0 && speedDifference > -100) speedDifference = speedDifference * 2; + let levelDifference = Memory.state.opponent.activeMonster.level - Memory.state.player.activeMonster.level; + if (levelDifference >= 5) levelDifference = levelDifference * 2; + else if (levelDifference < 0 && levelDifference > -10) levelDifference = 0; + else if (levelDifference <= -10) levelDifference = levelDifference / 10; const opponentActiveMonster = Memory.state.opponent.activeMonster; Game.opponentActionTimeout = setTimeout(async () => { @@ -576,13 +585,31 @@ const Game = { } Game.opponentActionTimeout = null; - }, Math.max(500, 2000 - (speedDifference * 10))); + }, Math.max(levelDifference < 10 ? 500 : 50, Math.min(2000 - (speedDifference * 10) - (levelDifference * 100), 3000))); console.log( 'Opponent Attack Timeout', Memory.state.opponent.activeMonster.stats.speed, Memory.state.player.activeMonster.stats.speed, - 2000 - (speedDifference * 10) + 2000 - (speedDifference * 10) - (levelDifference * 100) ); } + }, + + /** + * @param {MouseEvent} event + */ + async battleClick (event) { + if (Game.isLoadingArea || Game.isProgressingTurn) { + return; + } + + Game.isInBattle = true; + UI.battleClickEvent = event; + + // player + await Game.tryUseTechnique(Memory.state.activeTechnique, Memory.state.player.activeMonster, Memory.state.opponent.activeMonster); + + // opponent + await Game.opponentTryUseTechnique(); await Game.progressTurn(); }, @@ -669,7 +696,7 @@ const Game = { } const nextTrainer = Memory.state.currentArea.trainers[nextTrainerIdx]; - if (nextTrainer.name === 'Rival') { + if (nextTrainer.name.startsWith('Rival')) { for (const idx in nextTrainer.monsters) { if (nextTrainer.monsters[idx].slug === 'STARTER') { nextTrainer.monsters[idx].slug = Memory.state.rivalMonster; @@ -704,16 +731,12 @@ const Game = { } Memory.state.currentArea = await fetchArea(areaSlug); - UI.drawArea(); if (Game.isTown(Memory.state.currentArea)) { - UI.elements.sceneBattle.classList.add('hidden'); - UI.elements.sceneTown.classList.remove('hidden'); - - UI.drawTown(); + if (Object.values(Memory.state.currentArea.locations).some((location) => location.type === 'healingCenter')) { + Memory.state.lastVisitedTown = areaSlug; + } } else { - UI.elements.sceneTown.classList.add('hidden'); - UI.elements.sceneBattle.classList.remove('hidden'); if (Memory.state.currentArea.encounters.length > 0) { await Game.encounterWildMonster(); } else if (Memory.state.currentArea.trainers.length > 0) { @@ -721,8 +744,7 @@ const Game = { } } - UI.drawStatus(); - UI.drawActiveBall(); + UI.drawArea(); Game.isLoadingArea = false; }, @@ -748,6 +770,10 @@ const Game = { conditionIsApplicable = eval(`${monster.hp} ${itemCondition.comparator} ${value}`); } + else if (itemCondition.what === 'status') { + conditionIsApplicable = monster.statusEffect && monster.statusEffect.slug === itemCondition.value.replace('status_', ''); + } + else if (itemCondition.what === 'wild_monster') { conditionIsApplicable = Game.isBattleType('monster'); } @@ -784,6 +810,13 @@ const Game = { UI.drawActiveMonster(); } + if (itemEffect.type === 'revive') { + monster.hp = itemEffect.amount; + monster.statusEffect = null; + item.quantity--; + UI.drawActiveMonster(); + } + else if (itemEffect.type === 'capture') { Memory.state.activeBall = item; UI.drawActiveBall(); @@ -825,15 +858,41 @@ const Game = { return; } - Game.clearCurrentTurn(); + const playerMonster = Memory.state.player.activeMonster; + const opposingMonster = Memory.state.opponent.activeMonster; + const activeBall = Memory.state.activeBall; - Memory.state.activeBall.quantity--; - if (Memory.state.activeBall.quantity === 0) { + // remove ball + activeBall.quantity--; + if (activeBall.quantity === 0) { Game.removeItemFromInventory(Memory.state.player.inventory, Memory.state.activeBall); Memory.state.activeBall = null; UI.drawActiveBall(); } + // attempt capture + Game.log('Attempting capture!'); + let success = true; + let attempts = 1; + const maxAttempts = 4; + while (success && attempts <= maxAttempts) { + success = checkCapture(playerMonster, opposingMonster, activeBall); + + if (!success) { + Game.log(`Escape attempt ${attempts}: succeeded!`); + Game.log(`${opposingMonster.name} broke free!`); + + Game.opponentTryUseTechnique(); + return; // can't catch + } + + Game.log(`Escape attempt ${attempts}: failed!`); + + attempts++; + } + + Game.clearCurrentTurn(); + const caughtMonster = new Monster(Memory.state.opponent.activeMonster.slug); caughtMonster.initialize(); caughtMonster.level = Memory.state.opponent.activeMonster.level; diff --git a/resources/js/helpers.js b/resources/js/helpers.js index e9cb37d..adf0bb7 100644 --- a/resources/js/helpers.js +++ b/resources/js/helpers.js @@ -63,3 +63,23 @@ function randomString () { function translate (msgid) { return DB.translations[Memory.state.Settings.language][msgid]; } + +/** + * @param {number} amount + * + * @returns {number} + */ +function convertToCurrencyBase (amount) { + const baseDecimalDiff = 2 - DB.currencies.map[Memory.state.Settings.currency].decimals; + + return amount * Math.pow(10, baseDecimalDiff); +} + +/** + * @param {number} price + * + * @returns {number} + */ +function formatPrice (price) { + return `${price} ${DB.currencies.map[Memory.state.Settings.currency].symbol}`; +} diff --git a/resources/js/main.js b/resources/js/main.js index 24eafec..6ea94e2 100644 --- a/resources/js/main.js +++ b/resources/js/main.js @@ -4,24 +4,36 @@ // Start Game const possibleStarterMonsters = ['budaye', 'dollfin', 'grintot', 'ignibus', 'memnomnom']; - Memory.state.player = new Trainer({ - monsters: [ - await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]), - ], - inventory: [ - new InventoryItem(await fetchItem('tuxeball'), 5), - new InventoryItem(await fetchItem('potion')), - ] - }); - await Memory.state.player.initialize(); + const monsterSelection = UI.openStarterMonsterSelection( + await Promise.all(possibleStarterMonsters.map(async (monsterSlug) => await fetchMonster(monsterSlug))) + ); + monsterSelection.addEventListener('starter:monster:selected', async (event) => { + if (!confirm(`Select ${event.detail.monster.name}?`)) { + return; + } + + Memory.state.player = new Trainer({ + monsters: [ + event.detail.monster, + ], + inventory: [ + new InventoryItem(await fetchItem('tuxeball'), 5), + new InventoryItem(await fetchItem('potion')), + ] + }); + await Memory.state.player.initialize(); - Game.setActivePlayerMonster(Memory.state.player.monsters[0]); - Memory.state.activeBall = Memory.state.player.inventory[0]; // tuxeball + Game.setActivePlayerMonster(Memory.state.player.monsters[0]); + Memory.state.activeBall = Memory.state.player.inventory[0]; // tuxeball - Memory.state.rivalMonster = possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]; + possibleStarterMonsters.splice(possibleStarterMonsters.indexOf(event.detail.monster), 1); + Memory.state.rivalMonster = possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]; - await Game.goToArea('paper-town'); + await Game.goToArea('paper-town'); - UI.drawActiveMonster(); - UI.drawActiveTechniques(); + UI.drawActiveMonster(); + UI.drawActiveTechniques(); + + event.detail.popup.remove(); + }); })(); diff --git a/resources/js/memory.js b/resources/js/memory.js index 47cde88..40be4df 100644 --- a/resources/js/memory.js +++ b/resources/js/memory.js @@ -9,21 +9,39 @@ const Memory = { * @returns {string} */ save () { + const prepareSaveData = (saveData) => { + const prepareMonster = (monster) => { + if (monster.statusEffect && monster.statusEffect.slug === 'lifeleech') { + monster.statusEffect = null; + } + + return monster; + }; + + for (const idx in saveData.monsters) { + saveData.monsters[idx] = prepareMonster(saveData.monsters[idx]); + } + for (const idx in saveData.player.monsters) { + saveData.player.monsters[idx] = prepareMonster(saveData.player.monsters[idx]); + } + for (const idx in saveData.opponent.monsters) { + saveData.opponent.monsters[idx] = prepareMonster(saveData.opponent.monsters[idx]); + } + + return JSON.parse(JSON.stringify(saveData)); + }; + const saveMonster = (monsterData, monsterState) => { monsterData.level = monsterState.level; monsterData.hp = monsterState.hp; - if (monsterData.statusEffect && monsterData.statusEffect.slug === 'lifeleech') { - monsterData.statusEffect = null; - } - return monsterData; }; /** * @type {State} */ - const saveData = JSON.parse(JSON.stringify(Memory.state)); + const saveData = prepareSaveData(Object.assign({}, Memory.state)); // monsters for (const idx in saveData.monsters) { @@ -163,6 +181,7 @@ const Memory = { Memory.state.areaProgress[areaSlug] = await loadArea(areaData); } Memory.state.currentArea = await loadArea(loadedState.currentArea); + Memory.state.lastVisitedTown = loadedState.lastVisitedTown; Memory.state.turn = loadedState.turn; Memory.state.money = loadedState.money; @@ -179,7 +198,7 @@ const Memory = { Memory.state.activeTechnique = await loadTechnique(loadedState.activeTechnique); Memory.state.activeBall = await loadInventoryItem(loadedState.activeBall); - UI.drawArea(Memory.state.currentArea); + UI.drawArea(); UI.drawStatus(); UI.drawOpponentMonster(); UI.drawActiveMonster(); diff --git a/resources/js/ui.js b/resources/js/ui.js index 3940574..6f38867 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -14,6 +14,10 @@ const Template = { techniques: document.querySelector('#tpl___techniques'), technique: document.querySelector('#tpl___technique'), + healingCenter: document.querySelector('#tpl___healing-center'), + shop: document.querySelector('#tpl___shop'), + shopItem: document.querySelector('#tpl___shop__item'), + party: document.querySelector('#tpl___party'), partyMonster: document.querySelector('#tpl___party__monster'), @@ -51,6 +55,7 @@ const UI = { log: document.querySelector('#log'), status: document.querySelector('#status'), + showMap: document.querySelector('#status [data-template-slot="showMap"]'), nextTrainer: document.querySelector('#status [data-template-slot="nextTrainer"]'), changeArea: document.querySelector('#status [data-template-slot="changeArea"]'), @@ -274,6 +279,14 @@ const UI = { return document.createElement('i'); } + if (statusEffect.slug === 'faint') { + const node = document.createElement('b'); + node.innerHTML = 'X'; + node.title = statusEffect.name; + + return node; + } + const img = document.createElement('img'); img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/status/icon_${statusEffect.slug}.png`; img.title = statusEffect.name; @@ -420,6 +433,10 @@ const UI = { * @returns {void} */ drawActiveTechniques () { + if (!Memory.state.player) { // on starter selection screen only + return; + } + const activeTechniques = UI.createActiveTechniques(Memory.state.player.activeMonster); activeTechniques.id = 'techniques'; @@ -495,8 +512,35 @@ const UI = { UI.elements.log.classList.toggle('log--is-hidden'); }, + openLog () { + UI.elements.log.classList.remove('log--is-hidden'); + }, + + closeLog () { + UI.elements.log.classList.add('log--is-hidden'); + }, + drawArea () { - UI.elements.battle.style.backgroundImage = `url(/modules/tuxemon/mods/tuxemon/gfx/ui/combat/${Memory.state.currentArea.environment.battle_graphics.background})`; + if (Game.isTown(Memory.state.currentArea)) { + UI.elements.sceneTown.querySelector('[data-template-slot="map"]').replaceChildren(UI.createMap()); + + UI.closeLog(); + + UI.elements.sceneBattle.classList.add('hidden'); + UI.elements.sceneTown.classList.remove('hidden'); + } else { + UI.elements.battle.style.backgroundImage = `url(/modules/tuxemon/mods/tuxemon/gfx/ui/combat/${Memory.state.currentArea.environment.battle_graphics.background})`; + + UI.elements.sceneTown.classList.add('hidden'); + UI.elements.sceneBattle.classList.remove('hidden'); + + UI.drawOpponentMonster(); + UI.drawActiveMonster(); + UI.drawActiveTechniques(); + } + + UI.drawStatus(); + UI.drawActiveBall(); }, progressTurn () { @@ -633,39 +677,120 @@ const UI = { /* Town */ - async drawTown () { + drawTown () {}, + + + /* Map */ + + /** + * @returns {HTMLElement} + */ + createMap () { + const template = document.createElement('div'); const currentArea = Memory.state.currentArea; - UI.elements.sceneTown.innerHTML = Memory.state.currentArea.map; + template.innerHTML = currentArea.map; + template.style.width = '100vw'; + template.style.maxWidth = '750px'; + + if (currentArea.locations) { + for (const locationId of Object.keys(currentArea.locations)) { + const location = currentArea.locations[locationId]; + + template.querySelector(`[data-location="${locationId}"]`).addEventListener('click', () => { + if (location.type === 'healingCenter') { + UI.openHealingCenter(location); + } + + else if (location.type === 'shop') { + UI.openShop(location); + } + }); + } + } + + return template; + }, - for (const locationId of Object.keys(currentArea.locations)) { - const location = currentArea.locations[locationId]; + /** + * @param {Object} healingCenter + */ + openHealingCenter (healingCenter) { + const popup = UI.createPopup(); + const template = UI.createTemplate(Template.healingCenter); + + const price = convertToCurrencyBase(healingCenter.price); + template.querySelector('[data-template-slot="price"]').innerHTML = formatPrice(price); - UI.elements.sceneTown.querySelector(`[data-location="${locationId}"]`).addEventListener('click', () => { - if (location.type === 'healingCenter') { - UI.openHealingCenter(location); + template.querySelector('[data-template-slot="heal"]').addEventListener('click', () => { + const applicableMonsters = Memory.state.player.monsters.filter((monster) => monster.hp < monster.stats.hp || monster.statusEffect); + if (applicableMonsters.length === 0) { + alert('No applicable monsters.'); + return; + } + + const monsterSelectionPopup = UI.createPopup(); + const monsterSelection = UI.createMonsterSelection(applicableMonsters); + + monsterSelection.addEventListener('monster:selected', (event) => { + if (Memory.state.money < price) { + alert(`Not enough ${DB.currencies.map[Memory.state.Settings.currency].symbol}.`); + return; } - else if (location.type === 'shop') { - UI.openShop(location); + Memory.state.money -= price; + event.detail.monster.hp = event.detail.monster.stats.hp; + event.detail.monster.statusEffect = null; + event.detail.node.remove(); + + if (monsterSelection.children.length === 0) { + monsterSelectionPopup.remove(); } + + UI.drawStatus(); }); - } - }, - openHealingCenter (healingCenter) {}, + monsterSelectionPopup.querySelector('.popup').appendChild(monsterSelection); + UI.drawPopup(monsterSelectionPopup); + }); + + popup.querySelector('.popup').appendChild(template); + UI.drawPopup(popup); + }, + /** + * @param {Object} shop + */ async openShop (shop) { const popup = UI.createPopup(); - const template = document.createElement('div'); + const template = UI.createTemplate(Template.shop); for (const itemData of shop.items) { + const price = convertToCurrencyBase(itemData.price); const item = await fetchItem(itemData.item_name); - const itemNode = document.createElement('div'); + const itemNode = UI.createTemplate(Template.shopItem); + + itemNode.querySelector('[data-template-slot="sprite"]').src = item.sprite; + itemNode.querySelector('[data-template-slot="name"]').innerHTML = item.name; + itemNode.querySelector('[data-template-slot="price"]').innerHTML = formatPrice(price); + + itemNode.addEventListener('click', () => { + if (Memory.state.money < price) { + alert(`Not enough ${DB.currencies.map[Memory.state.Settings.currency].symbol}.`); + return; + } + + Memory.state.money -= price; - itemNode.innerHTML = `<img src="/modules/tuxemon/mods/tuxemon/${item.sprite}" />`; - itemNode.innerHTML += `${item.name}`; - itemNode.innerHTML += `${itemData.price} ${DB.currencies.map[Memory.state.Settings.currency].symbol}`; + const itemInInventory = Memory.state.player.inventory.find((inventoryItem) => inventoryItem.slug === item.slug); + if (itemInInventory) { + itemInInventory.quantity++; + } else { + Memory.state.player.inventory.push(new InventoryItem(item, 1)); + } + + UI.drawStatus(); + }); template.appendChild(itemNode); } @@ -679,6 +804,7 @@ const UI = { partySelectionMode: 'select', inventorySelectionMode: 'use', + isHighlighting: false, /** @@ -727,6 +853,56 @@ const UI = { return template; }, + /** + * @param {Monster[]} monsters + * + * @returns {HTMLElement} + */ + createPartySelection (monsters) { + const party = UI.createTemplate(Template.party); + party.id = 'party'; + for (const monsterIdx in monsters) { + const monster = monsters[monsterIdx]; + const partyMonster = UI.createPartyMonster(monster); + + partyMonster.addEventListener('click', async (event) => { + // bubble up to partyNode + let target = event.target; + while (target.parentNode.id !== party.id) { + target = target.parentNode; + } + + party.dispatchEvent(new CustomEvent('party:monster:selected', { + detail: { + monster: monster, + mode: UI.partySelectionMode, + node: partyMonster, + }, + })); + }); + + party.querySelector('[data-template-slot="monsters"]').appendChild(partyMonster); + } + + const selectionModesNode = party.querySelector('[data-template-slot="modes"]'); + const selectionModeNodes = selectionModesNode.querySelectorAll('[data-party-selection-mode]'); + selectionModeNodes.forEach((node) => { + if (node.dataset.partySelectionMode === UI.partySelectionMode) { + node.setAttribute('selected', true); + } + + node.addEventListener('click', () => { + selectionModesNode.querySelector(`[data-party-selection-mode="${UI.partySelectionMode}"]`).removeAttribute('selected'); + + UI.partySelectionMode = node.dataset.partySelectionMode; + + node.setAttribute('selected', true); + }); + }); + + return party; + }, + drawStatus () { const currentArea = Memory.state.currentArea; @@ -739,15 +915,84 @@ const UI = { UI.elements.status.querySelector('[data-template-slot="trainerProgress"]').textContent = `${currentArea.trainerProgress} / ${currentArea.trainers.length}`; const nextTrainerButton = UI.elements.nextTrainer; - if ( - Memory.state.opponent.type === 'monster' && - currentArea.monsterProgress >= currentArea.requiredEncounters && - currentArea.trainerProgress < currentArea.trainers.length - ) { - nextTrainerButton.disabled = false; + if (!Game.isTown(currentArea)) { + if ( + Memory.state.opponent.type === 'monster' && + currentArea.monsterProgress >= currentArea.requiredEncounters && + currentArea.trainerProgress < currentArea.trainers.length && + !Game.isInBattle + ) { + nextTrainerButton.disabled = false; + } else { + nextTrainerButton.disabled = true; + } } else { nextTrainerButton.disabled = true; } + + const changeAreaButton = UI.elements.changeArea; + if (!Game.isTown(currentArea)) { + if ( + Game.isInBattle || + (Memory.state.opponent && Memory.state.opponent.type === 'trainer') + ) { + changeAreaButton.disabled = true; + } else { + changeAreaButton.disabled = false; + } + } else { + changeAreaButton.disabled = false; + } + }, + + /** + * @param {Monster[]} monsters + */ + openStarterMonsterSelection (monsters) { + const popup = UI.createPopup().cloneNode(true); // remove close event + const template = UI.createPartySelection(monsters); + + const title = document.createElement('h1'); + title.textContent = 'Select your Tuxemon!'; + title.style.textAlign = 'center'; + template.prepend(title); + + template.addEventListener('party:monster:selected', (event) => { + const monster = event.detail.monster; + + if (UI.partySelectionMode === 'select') { + template.dispatchEvent(new CustomEvent('starter:monster:selected', { + detail: { + monster: monster, + node: event.detail.node, + popup: popup, + }, + })); + } + else if (UI.partySelectionMode === 'stats') { + UI.openStatsMenu(monster); + } + else if (UI.partySelectionMode === 'techniques') { + UI.openMovesetSelection(monster); + } + }); + + popup.querySelector('.popup').appendChild(template); + UI.drawPopup(popup); + + return template; + }, + + openMap () { + if (Game.isInBattle || Game.isTown(Memory.state.currentArea)) { + return; + } + + const popup = UI.createPopup(); + const template = UI.createMap(); + + popup.querySelector('.popup').appendChild(template); + UI.drawPopup(popup); }, openAreaSelection () { @@ -771,6 +1016,10 @@ const UI = { canGo = canGo && currentArea.trainerProgress >= currentArea.trainers.length; } + else if (condition.startsWith('area.')) { + canGo = Memory.state.areaProgress.hasOwnProperty(condition.replace('area.', '')); + } + else if (condition.startsWith('event.')) { canGo = false; } @@ -798,60 +1047,25 @@ const UI = { openPartyMenu () { const popup = UI.createPopup(); + const template = UI.createPartySelection(Memory.state.player.monsters); - const party = UI.createTemplate(Template.party); - party.id = 'party'; - for (const monsterIdx in Memory.state.player.monsters) { - const monster = Memory.state.player.monsters[monsterIdx]; - const partyMonster = UI.createPartyMonster(monster); - - partyMonster.addEventListener('click', async (event) => { - // bubble up to partyNode - let target = event.target; - while (target.parentNode.id !== party.id) { - target = target.parentNode; - } - - if (UI.partySelectionMode === 'select') { - Game.setActivePlayerMonster(monster); - - popup.remove(); - } - else if (UI.partySelectionMode === 'stats') { - UI.openStatsMenu(monster); - } - else if (UI.partySelectionMode === 'techniques') { - UI.openMovesetSelection(monster); - } - - UI.events.dispatchEvent(new CustomEvent('party:monsterSelected', { - detail: { - monster: monster, - mode: UI.partySelectionMode, - }, - })); - }); + template.addEventListener('party:monster:selected', (event) => { + const monster = event.detail.monster; - party.querySelector('[data-template-slot="monsters"]').appendChild(partyMonster); - } + if (UI.partySelectionMode === 'select') { + Game.setActivePlayerMonster(monster); - const selectionModesNode = party.querySelector('[data-template-slot="modes"]'); - const selectionModeNodes = selectionModesNode.querySelectorAll('[data-party-selection-mode]'); - selectionModeNodes.forEach((node) => { - if (node.dataset.partySelectionMode === UI.partySelectionMode) { - node.setAttribute('selected', true); + popup.remove(); + } + else if (UI.partySelectionMode === 'stats') { + UI.openStatsMenu(monster); + } + else if (UI.partySelectionMode === 'techniques') { + UI.openMovesetSelection(monster); } - - node.addEventListener('click', () => { - selectionModesNode.querySelector(`[data-party-selection-mode="${UI.partySelectionMode}"]`).removeAttribute('selected'); - - UI.partySelectionMode = node.dataset.partySelectionMode; - - node.setAttribute('selected', true); - }); }); - popup.querySelector('.popup').appendChild(party); + popup.querySelector('.popup').appendChild(template); UI.drawPopup(popup); }, @@ -1067,13 +1281,44 @@ const UI = { const exchangedMoney = baseRateMoney * newCurrency.rate; Memory.state.money = Number(exchangedMoney.toFixed(newCurrency.decimals)); - UI.drawTown(); + UI.drawArea(); UI.drawStatus(); }); template.querySelector('[data-template-slot="currency.lastUpdated"]').textContent = DB.currencies.last_updated; + // Highlight + + template.querySelector('[data-template-slot="highlight"]').addEventListener('click', () => { + UI.isHighlighting = !UI.isHighlighting; + + const elements = [ + UI.elements.battleOpponent, + UI.elements.battlePlayer.querySelector('[data-template-slot="sprite"]'), + UI.elements.techniques, + ...UI.elements.sceneTown.querySelectorAll('[data-location]'), + UI.elements.showMap, + UI.elements.nextTrainer, + UI.elements.changeArea, + UI.elements.menuParty, + UI.elements.menuCatch, + UI.elements.menuInventory, + UI.elements.menuLog, + UI.elements.menuJournal, + UI.elements.menuSettings, + ]; + + for (const element of elements) { + if (UI.isHighlighting) { + element.classList.add('setting-highlight'); + } else { + element.classList.remove('setting-highlight'); + } + } + }); + + popup.querySelector('.popup').appendChild(template); UI.drawPopup(popup); }, @@ -1093,6 +1338,7 @@ const UI = { partyMonster.querySelector('[data-template-slot="name"]').textContent = monster.name; partyMonster.querySelector('[data-template-slot="gender"]').innerHTML = UI.createGenderIcon(monster.gender).outerHTML; partyMonster.querySelector('[data-template-slot="level"]').textContent = monster.level; + partyMonster.querySelector('[data-template-slot="statusEffect"]').innerHTML = UI.createStatusEffectIcon(monster.statusEffect).outerHTML; partyMonster.querySelector('[data-template-slot="hpText"]').textContent = `${monster.hp} / ${monster.stats.hp}`; return partyMonster; @@ -1235,7 +1481,7 @@ const UI = { inventoryItemNode.title = item.description; inventoryItemNode.dataset.inventoryItem = item.slug; - inventoryItemNode.querySelector('[data-template-slot="sprite"]').src = `/modules/tuxemon/mods/tuxemon/${item.sprite}`; + inventoryItemNode.querySelector('[data-template-slot="sprite"]').src = item.sprite; inventoryItemNode.querySelector('[data-template-slot="name"]').textContent = item.name; inventoryItemNode.querySelector('[data-template-slot="quantity"]').textContent = item.quantity; @@ -1245,6 +1491,10 @@ const UI = { UI.openItemMonsterSelection(item); } + else if (item.category === 'revive') { + UI.openItemMonsterSelection(item); + } + else if (item.category === 'capture') { Game.useItem(item); } @@ -1389,6 +1639,7 @@ const UI = { }; // UI element click bindings +UI.elements.showMap.addEventListener('click', UI.openMap); UI.elements.changeArea.addEventListener('click', UI.openAreaSelection); UI.elements.menuParty.addEventListener('click', UI.openPartyMenu); UI.elements.menuInventory.addEventListener('click', UI.openInventoryMenu); |