├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── app.js ├── documentation ├── 02030150 addresses.txt ├── asm │ ├── function_add_archipelago_item.txt │ ├── function_add_item.txt │ ├── function_add_party_member.txt │ ├── function_overflow_djinn.txt │ ├── function_overflow_djinn_queue.txt │ ├── function_receive_archipelago_item.txt │ ├── function_set_treasure_icon.txt │ └── mapCode │ │ ├── contigo │ │ ├── add_party_items.txt │ │ └── show_party_items.txt │ │ ├── idejima │ │ ├── add_sheba_item.txt │ │ ├── add_starting_party_member.txt │ │ └── show_sheba_item.txt │ │ ├── kibombo │ │ ├── add_piers_item.txt │ │ └── show_piers_item.txt │ │ └── mars_lighthouse │ │ └── check_mars_star.txt ├── boss balancing.txt ├── character shuffle djinn nums.txt ├── djinn_stats.ods ├── glitch logic issues.txt ├── icons │ ├── icon_archipelago_2.aseprite │ ├── icon_archipelago_shading.aseprite │ ├── icon_archipelago_shading_major.aseprite │ ├── icon_felix.aseprite │ ├── icon_garet.aseprite │ ├── icon_isaac.aseprite │ ├── icon_ivan.aseprite │ ├── icon_jenna.aseprite │ ├── icon_mia.aseprite │ ├── icon_piers.aseprite │ └── icon_sheba.aseprite ├── sunshine selection patch notes.txt └── world map entries.txt ├── lang ├── de_DE.json ├── en_GB.json ├── es_ES.json └── fr_FR.json ├── location_schema.json ├── logic_graph.json ├── modules ├── archipelago.js ├── decompression.js ├── mersenne.js └── packer.js ├── package-lock.json ├── package.json ├── permalinks.json ├── public ├── css │ ├── common.css │ ├── font │ │ └── Taranis.ttf │ └── randomise.css ├── img │ ├── ap-logo.svg │ ├── favicon.webp │ └── gstlar-logo.webp └── js │ ├── common.js │ ├── generate.js │ ├── patcher.js │ ├── permalink.js │ ├── randomise.js │ ├── randomise_race.js │ ├── settings.js │ └── spoiler.js ├── randomiser ├── game_data.js ├── game_data │ ├── abilities.js │ ├── characters.js │ ├── classes.js │ ├── djinn.js │ ├── doors.js │ ├── elem_tables.js │ ├── enemies.js │ ├── forgeables.js │ ├── item_locations.js │ ├── items.js │ ├── json │ │ └── psynergyLines.json │ ├── music.js │ ├── shops.js │ └── summons.js ├── game_logic │ ├── credits.js │ ├── hint_system.js │ ├── icons.js │ ├── locations.js │ ├── locations │ │ ├── AirsRock.json │ │ ├── Alhafra.json │ │ ├── AlhafranCave.json │ │ ├── AnemosInnerSanctum.json │ │ ├── AngaraCavern.json │ │ ├── AnkohlRuins.json │ │ ├── ApojiiIslands.json │ │ ├── AquaRock.json │ │ ├── AttekaCavern.json │ │ ├── AttekaInlet.json │ │ ├── Champa.json │ │ ├── Contigo.json │ │ ├── Daila.json │ │ ├── DehkanPlateau.json │ │ ├── ETundariaIslet.json │ │ ├── GabombaCatacombs.json │ │ ├── GabombaStatue.json │ │ ├── GaiaRock.json │ │ ├── Garoh.json │ │ ├── GondowanCliffs.json │ │ ├── GondowanSettlement.json │ │ ├── HesperiaSettlement.json │ │ ├── Idejima.json │ │ ├── IndraCavern.json │ │ ├── IsletCave.json │ │ ├── Izumo.json │ │ ├── JupiterLighthouse.json │ │ ├── KaltIsland.json │ │ ├── KandoreanTemple.json │ │ ├── Kibombo.json │ │ ├── KibomboMountains.json │ │ ├── Lemuria.json │ │ ├── LemurianShip.json │ │ ├── Loho.json │ │ ├── Madra.json │ │ ├── MadraCatacombs.json │ │ ├── MagmaRock.json │ │ ├── MarsLighthouse.json │ │ ├── Mikasalla.json │ │ ├── NOseniaIslet.json │ │ ├── Naribwe.json │ │ ├── OseniaCavern.json │ │ ├── OseniaCliffs.json │ │ ├── Overworld.json │ │ ├── Prox.json │ │ ├── SEAngaraIslet.json │ │ ├── SWAttekaIslet.json │ │ ├── SeaGodShrine.json │ │ ├── SeaOfTime.json │ │ ├── SeaOfTimeIslet.json │ │ ├── ShamanVillage.json │ │ ├── ShamanVillageCave.json │ │ ├── TaopoSwamp.json │ │ ├── TreasureIsle.json │ │ ├── TundariaTower.json │ │ ├── WIndraIslet.json │ │ ├── Yallam.json │ │ ├── YampiDesert.json │ │ └── YampiDesertCave.json │ ├── locations_detailed │ │ ├── AirsRock.json │ │ ├── Alhafra.json │ │ ├── AlhafranCave.json │ │ ├── AnemosInnerSanctum.json │ │ ├── AngaraCavern.json │ │ ├── AnkohlRuins.json │ │ ├── ApojiiIslands.json │ │ ├── AquaRock.json │ │ ├── AttekaCavern.json │ │ ├── AttekaInlet.json │ │ ├── Champa.json │ │ ├── Contigo.json │ │ ├── Daila.json │ │ ├── DehkanPlateau.json │ │ ├── ETundariaIslet.json │ │ ├── GabombaCatacombs.json │ │ ├── GabombaStatue.json │ │ ├── GaiaRock.json │ │ ├── Garoh.json │ │ ├── GondowanCliffs.json │ │ ├── GondowanSettlement.json │ │ ├── HesperiaSettlement.json │ │ ├── Idejima.json │ │ ├── IndraCavern.json │ │ ├── IsletCave.json │ │ ├── Izumo.json │ │ ├── JupiterLighthouse.json │ │ ├── KaltIsland.json │ │ ├── KandoreanTemple.json │ │ ├── Kibombo.json │ │ ├── KibomboMountains.json │ │ ├── Lemuria.json │ │ ├── LemurianShip.json │ │ ├── Loho.json │ │ ├── Madra.json │ │ ├── MadraCatacombs.json │ │ ├── MadraDrawbridge.json │ │ ├── MagmaRock.json │ │ ├── MarsLighthouse.json │ │ ├── Mikasalla.json │ │ ├── NOseniaIslet.json │ │ ├── Naribwe.json │ │ ├── NorthernReaches.json │ │ ├── OseniaCavern.json │ │ ├── OseniaCliffs.json │ │ ├── Overworld.json │ │ ├── Prox.json │ │ ├── SEAngaraIslet.json │ │ ├── SWAttekaIslet.json │ │ ├── SeaGodShrine.json │ │ ├── SeaOfTime.json │ │ ├── SeaOfTimeIslet.json │ │ ├── ShamanVillage.json │ │ ├── ShamanVillageCave.json │ │ ├── TaopoSwamp.json │ │ ├── TreasureIsle.json │ │ ├── TundariaTower.json │ │ ├── WIndraIslet.json │ │ ├── Yallam.json │ │ ├── YampiDesert.json │ │ └── YampiDesertCave.json │ ├── map_code.js │ ├── randomisers │ │ ├── archipelago_filler.js │ │ ├── base_randomiser.js │ │ ├── door_randomiser.js │ │ └── item_randomiser.js │ └── textutil.js ├── icons │ ├── archipelago_icons.js │ └── character_icons.js ├── patches │ ├── innate │ │ ├── endgame_shortcuts.js │ │ ├── extra_icons.js │ │ ├── fast_forging.js │ │ ├── fix_char.js │ │ ├── fix_lemurian_ship.js │ │ ├── gabomba_puzzle.js │ │ ├── randomiser_general.js │ │ ├── register_back_entrances.js │ │ ├── teleport.js │ │ ├── trial_road.js │ │ └── tutorial_npcs.js │ ├── mini_patches.js │ ├── options │ │ ├── add_character_items.js │ │ ├── anemos_requirements.js │ │ ├── archipelago.js │ │ ├── avoid.js │ │ ├── cutscene_skip.js │ │ ├── djinn_scaling.js │ │ ├── easier_bosses.js │ │ ├── mimic_disguise.js │ │ ├── puzzles.js │ │ ├── retreat_glitch.js │ │ └── teleport_everywhere.js │ └── shortcuts │ │ ├── magma_rock_interior.js │ │ └── upper_mars_lighthouse.js ├── randomiser.js ├── rom │ └── readme.txt ├── settings.js ├── spoiler_log.js ├── ups.js └── ups │ ├── randomiser_general.ups │ └── teleport.ups ├── routers ├── ajax.js └── public.js ├── run ├── generate_logic_graph.js ├── test_logic_graph.js └── validate_logic_graph.js ├── util ├── binary.js ├── config.js ├── npcWriter.js └── weightedPicker.js └── views ├── browse_permalinks.ejs ├── changelog.ejs ├── custom.ejs ├── help.ejs ├── index.ejs ├── partials ├── changelogs │ ├── v1_0_1.ejs │ ├── v1_0_2.ejs │ ├── v1_0_3.ejs │ ├── v1_0_4.ejs │ ├── v1_0_5.ejs │ ├── v1_0_6.ejs │ ├── v1_1_0.ejs │ ├── v1_1_1.ejs │ ├── v1_1_2.ejs │ ├── v1_1_3.ejs │ ├── v1_2_0.ejs │ ├── v1_2_1.ejs │ ├── v1_2_10.ejs │ ├── v1_2_11.ejs │ ├── v1_2_2.ejs │ ├── v1_2_3.ejs │ ├── v1_2_4.ejs │ ├── v1_2_5.ejs │ ├── v1_2_6.ejs │ ├── v1_2_7.ejs │ ├── v1_2_8.ejs │ └── v1_2_9.ejs ├── custom │ └── tab_location.ejs ├── head_common.ejs ├── item_dropdown.ejs ├── modals │ ├── delete_preset.ejs │ ├── export_preset.ejs │ ├── import_preset.ejs │ └── save_preset.ejs ├── preset_buttons.ejs ├── rando_settings │ ├── tab_logic_access.ejs │ ├── tab_logic_glitches.ejs │ ├── tab_randomisation_djinn.ejs │ ├── tab_randomisation_items.ejs │ ├── tab_randomisation_misc.ejs │ ├── tab_randomisation_psy.ejs │ └── tab_randomisation_stats.ejs ├── setting_dropdown.ejs ├── setting_switch.ejs ├── spoiler_log.ejs ├── tab_button.ejs └── top_nav.ejs ├── permalink.ejs ├── randomise.ejs ├── randomise_race.ejs └── tips.ejs /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | node_modules/ 3 | output_cache/ 4 | permalinks/ 5 | temp/ 6 | debug/ 7 | map_code_cache/ 8 | analysis/ 9 | 10 | .vscode/ 11 | config.json 12 | 13 | *.pem 14 | *.crt 15 | *.key 16 | 17 | *.gba -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "json.schemas": [ 3 | { 4 | "fileMatch": [ 5 | "locations_detailed/*.json" 6 | ], 7 | "url": "./location_schema.json" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Karanum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golden Sun: The Lost Age Randomiser 2 2 | Rework of the original GS:TLA randomiser, now in a handy web-based format 3 | 4 | Special thanks to MarvinXLII, who created the original randomiser, and Teawater and Salanewt, who have thoroughly documented the game itself. 5 | 6 | ## Info for Players 7 | If you're just looking to play the randomiser, you can find it over at https://gs2randomiser.com. You can report bugs and request features in the Issue Tracker: https://github.com/Karanum/gs2-randomiser2/issues. Other than that, this place is mainly for development purposes so you shouldn't have to worry about it. 8 | 9 | ## Requirements 10 | NodeJS is required to run this application, with v12.x or above being recommended. In addition, NPM is used to install dependencies. 11 | 12 | ## Installation and running 13 | Navigate to this directory with the terminal/shell of your choice and run `npm install` to install dependencies. 14 | Next, acquire an unmodified ROM file of Golden Sun: The Lost Age and add this to the `randomiser/rom` directory and follow the instructions in the `readme.txt` file there. 15 | 16 | The application can then be run with `node app.js`. The application will be running on port 3000 by default. 17 | 18 | After running the application for the first time, the file `config.json` will be generated in this directory. This can be used to change the default port, as well as configure HTTPS for the server which allows it to accept secure connections. 19 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const fs = require('fs'); 3 | const https = require('https'); 4 | const config = require('./util/config.js'); 5 | 6 | const port = config.get("port"); 7 | const app = express(); 8 | 9 | // App initialisation 10 | console.log("Starting..."); 11 | 12 | if (!fs.existsSync('./output_cache/')) { 13 | fs.mkdirSync('./output_cache/'); 14 | } 15 | if (!fs.existsSync('./permalinks/')) { 16 | fs.mkdirSync('./permalinks/'); 17 | } 18 | if (!fs.existsSync('./temp/')) { 19 | fs.mkdirSync('./temp/'); 20 | } 21 | 22 | //======================================================================================= 23 | // Router initialisation 24 | //======================================================================================= 25 | 26 | app.use('/', require('./routers/ajax.js')); 27 | app.use('/', require('./routers/public.js')); 28 | 29 | //======================================================================================= 30 | // Server initialisation 31 | //======================================================================================= 32 | 33 | app.disable('x-powered-by'); 34 | app.set('view engine', 'ejs'); 35 | app.set('views', './views'); 36 | app.use(express.static('public')); 37 | 38 | if (config.get("use-https")) { 39 | var key = fs.readFileSync(config.get("ssl-key"), 'utf8'); 40 | var cert = fs.readFileSync(config.get("ssl-cert"), 'utf8'); 41 | 42 | var server = https.createServer({key: key, cert: cert}, app); 43 | server.listen(port); 44 | console.log("Server listening for HTTPS on port " + port); 45 | } else { 46 | app.listen(port, () => { 47 | console.log("Server listening on port " + port); 48 | }); 49 | } -------------------------------------------------------------------------------- /documentation/02030150 addresses.txt: -------------------------------------------------------------------------------- 1 | 02030*** 2 | 3 | 154 Event ID (???) 4 | 156 (???) 5 | 158 Exit --> 080CBDEC 6 | 15A Game menu 7 | 15C Game menu 8 | 15E System menu 9 | 160 NPC interaction 10 | 162 NPC event 11 | 164 Encounter 12 | 166 Psynergy 13 | 168 "But nothing happens" (???) 14 | 16A System events --> 080CBDFC 15 | (0xFFFF = poison) --> 080CBE18 16 | (0xFC87 = world map zoom) 17 | (0xFC88 = map screen) -------------------------------------------------------------------------------- /documentation/asm/function_add_archipelago_item.txt: -------------------------------------------------------------------------------- 1 | @offset = 090061F0 2 | 3 | 4 | push {lr} 5 | movs r0, #0x4 6 | movs r1, #0x1 7 | bl thunkSetTextVar 8 | 9 | movs r0, #0xB5 10 | lsls r0, #0x5 11 | movs r1, #0x0 12 | bl thunkShowStatusBox 13 | pop {pc} 14 | 15 | 16 | thunkSetTextVar: 17 | ldr r4, #0x0 18 | bx r4 19 | .word 0x0803CCD1 20 | 21 | thunkShowStatusBox: 22 | ldr r4, #0x0 23 | bx r4 24 | .word 0x08038041 -------------------------------------------------------------------------------- /documentation/asm/function_add_item.txt: -------------------------------------------------------------------------------- 1 | @ offset = 09006000 2 | 3 | 4 | push {r1-r6, lr} 5 | lsrs r2, r0, #8 6 | movs r1, #0xFF 7 | ands r0, r1 8 | movs r1, #0xF 9 | ands r2, r1 10 | cmp r2, #0xF 11 | beq handleSummonPickup 12 | cmp r2, #0xE 13 | beq handlePsynergyPickup 14 | cmp r2, #0xD 15 | beq handleCharacterPickup 16 | cmp r2, #0xA 17 | beq handleArchipelagoPickup 18 | movs r0, #0 19 | pop {r1-r6, pc} 20 | 21 | handleSummonPickup: 22 | bl funcSummonPickup 23 | b end 24 | 25 | handlePsynergyPickup: 26 | adds r1, r0, #0 27 | bl funcPsynergyPickup 28 | bl thunk_3 29 | b end 30 | 31 | handleCharacterPickup: 32 | bl #0x90060BC 33 | b end 34 | 35 | handleArchipelagoPickup: 36 | bl #0x090061F0 37 | 38 | end: 39 | movs r0, #0x1 40 | pop {r1-r6, pc} 41 | 42 | 43 | funcSummonPickup: 44 | push {r0, lr} 45 | bl thunk_1 46 | pop {r0} 47 | bl thunk_2 48 | pop {pc} 49 | 50 | 51 | thunk_1: 52 | ldr r3, [pc, #0x50] 53 | bx r3 54 | 55 | thunk_2: 56 | ldr r4, [pc, #0x50] 57 | bx r4 58 | 59 | thunk_3: 60 | ldr r4, [pc, #0x50] 61 | bx r4 62 | 63 | 64 | funcPsynergyPickup: 65 | push {r1-r7, lr} 66 | bl #0x900609c 67 | adds r6, r0, #0 68 | ldr r5, [pc, #0x48] 69 | movs r7, #0 70 | ldrb r4, [r5, r7] 71 | ldr r0, [pc, #0x44] 72 | ldr r1, [pc, #0x48] 73 | muls r1, r4, r1 74 | adds r0, r0, r1 75 | movs r1, #0 76 | movs r2, #0 77 | ldr r3, [r0] 78 | cmp r3, #0 79 | beq #0x9006098 80 | lsrs r3, r3, #8 81 | cmp r3, #0x80 82 | bge #0x9006082 83 | adds r1, #1 84 | cmp r1, #0xe 85 | beq #0x9006090 86 | adds r2, #1 87 | cmp r2, #0x1f 88 | beq #0x9006090 89 | adds r0, #4 90 | b #0x9006074 91 | adds r7, #1 92 | cmp r7, r6 93 | beq #0x9006098 94 | b #0x9006066 95 | ldrb r0, [r5, r7] 96 | pop {r1-r7, pc} 97 | ldr r0, [pc, #0x18] 98 | bx r0 99 | 100 | .word 0x08038341 101 | .word 0x080AFF95 102 | .word 0x080D2A0D 103 | .word 0x02000458 104 | .word 0x02000578 105 | .word 0x0000014C 106 | .word 0x080AFDBD -------------------------------------------------------------------------------- /documentation/asm/function_overflow_djinn.txt: -------------------------------------------------------------------------------- 1 | @offset = 09006D00 2 | @ NOTE: This exact version of this function is not used. 3 | @ It is intended for reference purposes. 4 | 5 | 6 | movs r0, r8 7 | push {r0, r7} 8 | bl thunkGetPartySize 9 | cmp r0, #0x8 10 | beq end 11 | 12 | movs r5, #0x9 13 | muls r5, r0, r5 @ r5 = max djinn capacity 14 | movs r8, r0 @ r8 = party size 15 | movs r6, #0x0 16 | movs r7, #0x30 17 | 18 | loop: 19 | adds r0, r7, #0x0 20 | bl thunkReadFlag 21 | adds r6, r6, r0 22 | adds r7, #0x1 23 | cmp r7, #0x80 24 | blt loop 25 | cmp r6, r5 26 | blt end 27 | 28 | adds r0, r6, #0x0 29 | movs r6, r8 30 | cmp r6, #0x7 31 | beq endPiers 32 | 33 | subs r7, r0, r5 34 | cmp r6, #0x3 35 | bne endOther 36 | cmp r7, #0x7 37 | blt endPiers 38 | 39 | @ UNMARKED 40 | subs r7, #7 41 | movs r0, #0 42 | cmp r7, #3 43 | blt #0x9006d4a 44 | subs r7, #3 45 | adds r0, #1 46 | b #0x9006d3e 47 | movs r0, #7 48 | mov sb, r0 49 | pop {r0, r7} 50 | mov r8, r0 51 | adds r1, r7, #0 52 | mov r2, sl 53 | mov r0, sb 54 | bl #0x9006d62 55 | 56 | 57 | @endOther: 58 | 59 | @endPiers: 60 | 61 | @end: 62 | @... 63 | 64 | ldr r4, #0x0 65 | bx r4 66 | .word 0x080B0B55 67 | 68 | thunkGetPartySize: 69 | ldr r4, #0x0 70 | bx r4 71 | .word 0x080AFDBD 72 | 73 | thunkAddDjinni: 74 | ldr r4, #0x0 75 | bx r4 76 | .word 0x080B0B79 77 | 78 | thunkReadFlag: 79 | ldr r4, #0x0 80 | bx r4 81 | .word 0x08016CE5 -------------------------------------------------------------------------------- /documentation/asm/function_overflow_djinn_queue.txt: -------------------------------------------------------------------------------- 1 | @ Alternate version of the Djinn overflow function for character shuffle 2 | @offset = 09006D00 3 | 4 | 5 | mov r0, r8 6 | push {r0, r7} 7 | bl thunkGetPartySize 8 | cmp r0, #0x8 9 | beq giveDjinni 10 | 11 | movs r5, #0x9 12 | muls r5, r0, r5 13 | mov r8, r0 14 | movs r6, #0x0 15 | movs r7, #0x30 16 | 17 | loop: 18 | adds r0, r7, #0x0 19 | bl thunkReadFlag 20 | adds r6, r6, r0 21 | adds r7, #0x1 22 | cmp r7, #0x80 23 | blt loop 24 | cmp r6, r5 25 | blt giveDjinni 26 | 27 | ldr r0, ptrOverflowDjinn 28 | ldrb r1, [r0, #0x0] 29 | adds r1, r1, #0x1 30 | strb r1, [r0, #0x0] 31 | lsls r1, r1, #0x1 32 | adds r0, r0, r1 33 | 34 | addToQueue: 35 | pop {r1, r7} 36 | mov r8, r1 37 | movs r1, r7 38 | mov r2, r10 39 | strb r1, [r0, #0x0] 40 | strb r2, [r0, #0x1] 41 | b end 42 | 43 | giveDjinni: 44 | pop {r0, r7} 45 | mov r8, r0 46 | adds r1, r7, #0x0 47 | mov r2, r10 48 | mov r0, r9 49 | bl thunkAddDjinni 50 | 51 | end: 52 | ldr r4, #0x0 53 | bx r4 54 | .word 0x080B0B55 55 | 56 | thunkGetPartySize: 57 | ldr r4, #0x0 58 | bx r4 59 | .word 0x080AFDBD 60 | 61 | thunkAddDjinni: 62 | ldr r4, #0x0 63 | bx r4 64 | .word 0x080B0B79 65 | 66 | thunkReadFlag: 67 | ldr r4, #0x0 68 | bx r4 69 | .word 0x08016CE5 70 | 71 | ptrOverflowDjinn: 72 | .word 0x02002980 -------------------------------------------------------------------------------- /documentation/asm/function_set_treasure_icon.txt: -------------------------------------------------------------------------------- 1 | @offset = 09000080 2 | @caller = 080CEDF2 3 | 4 | adds r0, #0x40 5 | cmp r7, #0x83 6 | beq doSetIcon 7 | cmp r7, #0x81 8 | bne end 9 | 10 | lsls r1, r1, #0x1 11 | ldr r4, ptrIcons 12 | ldrh r1, [r4, r1] 13 | 14 | doSetIcon: 15 | bl thunkSetIcon 16 | 17 | end: 18 | ldr r4, ptrThunkContinue 19 | bx r4 20 | 21 | ptrThunkContinue: 22 | .word 0x080CEE01 23 | 24 | thunkSetIcon: 25 | ldr r4, ptrThunkSetIcon 26 | bx r4 27 | 28 | ptrThunkSetIcon: 29 | .word 0x080D3B29 30 | 31 | ptrIcons: 32 | .word dataIcons 33 | 34 | dataIcons: 35 | .hword 0x0 36 | .hword 0x0 37 | .hword 0x0 38 | .hword 0x0 39 | .hword 0x0 40 | .hword 0x0 41 | .hword 0x0 42 | .hword 0x0 43 | .hword 0x0 -------------------------------------------------------------------------------- /documentation/asm/mapCode/contigo/add_party_items.txt: -------------------------------------------------------------------------------- 1 | @offset = 02009D98 2 | 3 | 4 | push {r5, r6, r7, lr} 5 | movs r6, r0 6 | subs r0, #0x8 7 | movs r7, r0 8 | 9 | bl 0x0200C06C 10 | movs r0, #0x0 11 | bl 0x0200C204 12 | 13 | movs r0, #0xA0 14 | lsls r0, #0x4 15 | adds r0, #0x21 16 | bl 0x0200BFC4 17 | cmp r0, #0x0 18 | bne flagIsOn 19 | 20 | movs r0, #0x2B 21 | lsls r0, #0x8 22 | adds r0, #0x5E 23 | bl 0x0200C12C 24 | movs r0, r6 25 | movs r1, #0x0 26 | bl 0x0200C144 27 | b end 28 | 29 | flagIsOn: 30 | ldr r0, ptrMappedItem 31 | movs r1, r7 32 | lsls r1, #0x1 33 | ldrh r0, [r0, r1] 34 | movs r5, r0 35 | bl thunkAddSpecialItem 36 | cmp r0, #0x1 37 | beq skip 38 | 39 | movs r0, #0x53 40 | bl thunkPlaySound 41 | bl thunkAddItem 42 | cmp r0, #0x0 43 | blt invFull 44 | 45 | skip: 46 | movs r0, r6 47 | movs r1, #0x0 48 | movs r2, #0x0 49 | bl thunkSetPosition 50 | 51 | movs r0, #0xD0 52 | lsls r0, r0, #0x4 53 | adds r0, r0, r7 54 | bl 0x0200BFCC 55 | b end 56 | 57 | invFull: 58 | movs r0, #0xE2 59 | lsls r0, #0x4 60 | movs r1, #0x0 61 | bl 0x0200C034 62 | 63 | end: 64 | bl 0x0200C074 65 | 66 | pop {r5, r6, r7, pc} 67 | 68 | 69 | ptrMappedItem: 70 | .word 0x08FA0180 71 | 72 | thunkAddItem: 73 | ldr r4, #0x0 74 | bx r4 75 | .word 0x09000207 76 | 77 | thunkAddSpecialItem: 78 | ldr r4, #0x0 79 | bx r4 80 | .word 0x09006001 81 | 82 | thunkPlaySound: 83 | ldr r4, #0x0 84 | bx r4 85 | .word 0x081C0CB1 86 | 87 | thunkSetPosition: 88 | ldr r4, #0x0 89 | bx r4 90 | .word 0x080C80F9 -------------------------------------------------------------------------------- /documentation/asm/mapCode/contigo/show_party_items.txt: -------------------------------------------------------------------------------- 1 | @offset = 02009D54 2 | @caller = 0200B9F4 3 | 4 | 5 | push {r5, r6, lr} 6 | 7 | movs r0, #0xD0 8 | lsls r0, r0, #0x4 9 | movs r5, r0 10 | movs r6, #0x0 11 | 12 | loop: 13 | movs r0, r5 14 | adds r0, r0, r6 15 | bl 0x0200BFC4 16 | cmp r0, #0x0 17 | bne skip 18 | 19 | movs r0, #0x8 20 | adds r0, r0, r6 21 | bl 0x0200C08C 22 | movs r1, r5 23 | adds r1, r6 24 | bl thunkSetItemDisplay 25 | 26 | movs r0, #0x8 27 | adds r0, r0, r6 28 | bl 0x0200C08C 29 | movs r1, #0x0 30 | bl 0x0200C014 31 | 32 | skip: 33 | adds r6, #0x1 34 | cmp r6, #0x4 35 | blt loop 36 | 37 | pop {r5, r6, pc} 38 | 39 | thunkSetItemDisplay: 40 | ldr r4, #0x0 41 | bx r4 42 | .word 0x08020301 43 | -------------------------------------------------------------------------------- /documentation/asm/mapCode/idejima/add_sheba_item.txt: -------------------------------------------------------------------------------- 1 | @offset = 0x020082B4 2 | 3 | 4 | push {r5, lr} 5 | bl 0x0200B1B8 6 | movs r0, #0x0 7 | bl 0x0200B310 8 | 9 | ldr r0, ptrMappedItem 10 | ldrh r0, [r0, #0x0] 11 | movs r5, r0 12 | bl thunkAddSpecialItem 13 | cmp r0, #0x1 14 | beq skip 15 | 16 | movs r0, #0x53 17 | bl thunkPlaySound 18 | bl thunkAddItem 19 | 20 | skip: 21 | movs r0, #0xFF 22 | movs r1, #0x0 23 | movs r2, #0x0 24 | bl thunkSetPosition 25 | 26 | movs r0, #0xD0 27 | lsls r0, r0, #0x4 28 | adds r0, #0x6 29 | bl 0x0200B158 30 | bl 0x0200B1C0 31 | 32 | pop {r5, pc} 33 | 34 | 35 | ptrMappedItem: 36 | .word 0x08FA018A 37 | 38 | thunkAddItem: 39 | ldr r4, #0x0 40 | bx r4 41 | .word 0x09000207 42 | 43 | thunkAddSpecialItem: 44 | ldr r4, #0x0 45 | bx r4 46 | .word 0x09006001 47 | 48 | thunkPlaySound: 49 | ldr r4, #0x0 50 | bx r4 51 | .word 0x081C0CB1 52 | 53 | thunkSetPosition: 54 | ldr r4, #0x0 55 | bx r4 56 | .word 0x080C80F9 -------------------------------------------------------------------------------- /documentation/asm/mapCode/idejima/add_starting_party_member.txt: -------------------------------------------------------------------------------- 1 | .offset 0x0200AFD4 2 | 3 | push {r5, r6, lr} 4 | sub sp, #0x8 5 | movs r0, #0xD0 6 | lsls r0, r0, #0x4 7 | adds r0, #0x5 8 | movs r5, r0 9 | bl 0x0200B150 10 | cmp r0, #0x0 11 | bne end 12 | 13 | bl 0x0200B1B8 14 | bl 0x0200B2F8 15 | bl 0x0200B308 16 | 17 | ldr r0, ptrMappedCharacter 18 | movs r1, #0x0 19 | ldrb r0, [r0, r1] 20 | bl thunkAddPartyMember 21 | 22 | movs r0, r5 23 | bl 0x0200B158 24 | ldr r5, ptrStartingItems 25 | movs r6, #0x0 26 | 27 | loop: 28 | ldrh r0, [r5, #0x0] 29 | ldrh r1, [r5, #0x2] 30 | cmp r1, #0x0 31 | beq endLoop 32 | adds r5, #0x4 33 | cmp r0, #0x4 34 | bne loop 35 | bl thunkAddItem 36 | b loop 37 | 38 | endLoop: 39 | cmp r6, #0x0 40 | bne endLoop2 41 | movs r6, #0x1 42 | ldr r5, ptrExtraItems 43 | b loop 44 | 45 | endLoop2: 46 | bl 0x0200B1C0 47 | 48 | end: 49 | b 0x0200B10A 50 | 51 | ptrMappedCharacter: 52 | .word 0x08FA0188 53 | 54 | ptrStartingItems: 55 | .word 0x08FA00E0 56 | 57 | ptrExtraItems: 58 | .word 0x08FA0130 59 | 60 | thunkAddPartyMember: 61 | ldr r4, #0x0 62 | bx r4 63 | .word 0x090060BD 64 | 65 | thunkAddItem: 66 | ldr r4, #0x0 67 | bx r4 68 | .word 0x09005039 -------------------------------------------------------------------------------- /documentation/asm/mapCode/idejima/show_sheba_item.txt: -------------------------------------------------------------------------------- 1 | @offset = 0x020080F0 2 | @caller = 0x0200AECA 3 | 4 | push {r5, lr} 5 | bl 0x0200953C 6 | 7 | movs r0, #0xD0 8 | lsls r0, r0, #0x4 9 | adds r0, #0x6 10 | bl 0x0200B150 @readFlag 11 | cmp r0, #0x0 12 | bne skip 13 | 14 | movs r5, #0xFF 15 | movs r0, r5 16 | bl 0x0200B1D8 @getObjectPointer 17 | ldr r1, ptrMappedItem 18 | ldrh r1, [r1, #0x0] 19 | bl thunkSetItemDisplay 20 | 21 | movs r0, r5 22 | bl 0x0200B1D8 @getObjectPointer 23 | movs r1, #0x0 24 | bl 0x0200B198 @setObjectShadow 25 | 26 | skip: 27 | pop {r5, pc} 28 | 29 | thunkSetItemDisplay: 30 | ldr r4, #0x0 31 | bx r4 32 | .word 0x08020301 33 | 34 | ptrMappedItem: 35 | .word 0x08FA018A -------------------------------------------------------------------------------- /documentation/asm/mapCode/kibombo/add_piers_item.txt: -------------------------------------------------------------------------------- 1 | @offset = 02009318 2 | 3 | 4 | push {r5, lr} 5 | bl 0x0200DA9C 6 | movs r0, #0x0 7 | bl 0x0200DC3C 8 | 9 | ldr r0, ptrMappedItem 10 | ldrh r0, [r0, #0x0] 11 | movs r5, r0 12 | bl thunkAddSpecialItem 13 | cmp r0, #0x1 14 | beq skip 15 | 16 | movs r0, #0x53 17 | bl thunkPlaySound 18 | bl thunkAddItem 19 | cmp r0, #0x0 20 | blt invFull 21 | 22 | skip: 23 | movs r0, #0x1A 24 | movs r1, #0x0 25 | movs r2, #0x0 26 | bl thunkSetPosition 27 | 28 | movs r0, #0xD0 29 | lsls r0, r0, #0x4 30 | adds r0, #0x7 31 | bl 0x0200DA14 32 | b end 33 | 34 | invFull: 35 | movs r0, #0xE2 36 | lsls r0, #0x4 37 | movs r1, #0x0 38 | bl thunkShowStatusBox 39 | 40 | end: 41 | bl 0x0200DAA4 42 | 43 | pop {r5, pc} 44 | 45 | 46 | ptrMappedItem: 47 | .word 0x08FA018C 48 | 49 | thunkAddItem: 50 | ldr r4, #0x0 51 | bx r4 52 | .word 0x09000207 53 | 54 | thunkAddSpecialItem: 55 | ldr r4, #0x0 56 | bx r4 57 | .word 0x09006001 58 | 59 | thunkPlaySound: 60 | ldr r4, #0x0 61 | bx r4 62 | .word 0x081C0CB1 63 | 64 | thunkSetPosition: 65 | ldr r4, #0x0 66 | bx r4 67 | .word 0x080C80F9 68 | 69 | thunkShowStatusBox: 70 | ldr r4, #0x0 71 | bx r4 72 | .word 0x08038041 -------------------------------------------------------------------------------- /documentation/asm/mapCode/kibombo/show_piers_item.txt: -------------------------------------------------------------------------------- 1 | @offset = 020087C8 2 | @caller = 0200D5DE 3 | 4 | push {lr} 5 | bl 0x0200D38C 6 | 7 | movs r0, #0xD0 8 | lsls r0, r0, #0x4 9 | adds r0, #0x7 10 | bl 0x0200DA0C 11 | cmp r0, #0x0 12 | bne skip 13 | 14 | movs r0, #0x1A 15 | bl 0x0200DAC4 16 | movs r1, #0xD0 17 | lsls r1, #0x4 18 | adds r1, #0x7 19 | bl thunkSetItemDisplay 20 | 21 | movs r0, #0x1A 22 | bl 0x0200DAC4 23 | movs r1, #0x0 24 | bl 0x0200DA74 25 | 26 | skip: 27 | movs r0, #0x7 28 | movs r1, #0x0 29 | movs r2, #0x0 30 | bl 0x0200DB0C 31 | 32 | pop {pc} 33 | 34 | thunkSetItemDisplay: 35 | ldr r4, #0x0 36 | bx r4 37 | .word 0x08020301 -------------------------------------------------------------------------------- /documentation/asm/mapCode/mars_lighthouse/check_mars_star.txt: -------------------------------------------------------------------------------- 1 | @offset = 0200BA80 2 | 3 | push {lr} 4 | movs r0, #0xA3 5 | lsls r0, r0, #0x4 6 | bl 0x0200B0F8 7 | cmp r0, #0x0 8 | bne marsStarFound 9 | 10 | movs r0, #0xDE 11 | bl thunkHasItem 12 | cmp r0, #0x0 13 | bge marsStarFound 14 | movs r0, #0xF7 15 | bl thunkHasItem 16 | cmp r0, #0x0 17 | blt notFound 18 | 19 | marsStarFound: 20 | movs r0, #0xAB 21 | lsls r0, r0, #0x4 22 | bl 0x0200B100 23 | 24 | notFound: 25 | bl 0x02008B64 26 | pop {pc} 27 | 28 | thunkHasItem: 29 | ldr r4, #0x0 30 | bx r4 31 | .word 0x080AEEC9 32 | -------------------------------------------------------------------------------- /documentation/character shuffle djinn nums.txt: -------------------------------------------------------------------------------- 1 | 26 2 | 3 | 0 0 [26] 4 | 1 0 [26] 5 | 2 2 [24] 6 | 3 3 [21] 7 | 4 4 [17] 8 | 5 5 [12] 9 | 6 6 [6] 10 | 7 6 [0] -------------------------------------------------------------------------------- /documentation/djinn_stats.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/djinn_stats.ods -------------------------------------------------------------------------------- /documentation/glitch logic issues.txt: -------------------------------------------------------------------------------- 1 | - The G. Ring item in Yampi is non-missable with S&Q 2 | - Figure out how to classify the S&Q warps from Mikasalla -------------------------------------------------------------------------------- /documentation/icons/icon_archipelago_2.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_archipelago_2.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_archipelago_shading.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_archipelago_shading.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_archipelago_shading_major.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_archipelago_shading_major.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_felix.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_felix.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_garet.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_garet.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_isaac.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_isaac.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_ivan.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_ivan.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_jenna.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_jenna.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_mia.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_mia.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_piers.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_piers.aseprite -------------------------------------------------------------------------------- /documentation/icons/icon_sheba.aseprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/documentation/icons/icon_sheba.aseprite -------------------------------------------------------------------------------- /documentation/sunshine selection patch notes.txt: -------------------------------------------------------------------------------- 1 | * get the forging results and store them somewhere (stack?) 2 | * setup information panels (or hijack existing ones) 3 | * loop until result: 4 | * input handling (?) 5 | * update information panels based on selected item 6 | 7 | params: 8 | - forgeable item selected 9 | - inventory panel pointer 10 | - price panel pointer 11 | - description panel pointer 12 | 13 | ============================================================ 14 | 15 | // r5 = item price panel 16 | // r6 = item description panel 17 | 18 | push {r5, r6, lr} 19 | 20 | ldr r0, [sp, 0x10] 21 | mov r5, r0 22 | ldr r0, [sp, 0x14] 23 | mov r6, r0 -------------------------------------------------------------------------------- /modules/archipelago.js: -------------------------------------------------------------------------------- 1 | function parseAPFile(buffer) { 2 | let arr = new Uint8Array(buffer); 3 | 4 | // Version check 5 | let version = arr[0]; 6 | if (version != 1) { 7 | return; 8 | } 9 | 10 | // Extract static header fields 11 | let seed = arr.slice(1, 17); 12 | let settings = arr.slice(17, 33); 13 | let pos = 33; 14 | 15 | // Extract user name 16 | let userName = ''; 17 | while (pos < arr.length) { 18 | let byte = arr[pos++]; 19 | if (byte == 0xA || byte == 0x0) break; 20 | userName += String.fromCharCode(byte); 21 | } 22 | 23 | // Extract item data 24 | let itemMap = {}; 25 | let valid = false; 26 | while (pos < arr.length - 3) { 27 | let location = arr[pos++] + (arr[pos++] << 8); 28 | let item = arr[pos++] + (arr[pos++] << 8); 29 | if (location == 0xFFFF && item == 0xFFFF) { 30 | valid = true; 31 | break; 32 | } 33 | itemMap['0x' + location.toString('16')] = item; 34 | } 35 | if (!valid) return {}; 36 | 37 | // Extract djinni data 38 | let djinniMap = {}; 39 | while (pos < arr.length - 1) { 40 | let location = arr[pos++]; 41 | let djinni = arr[pos++]; 42 | if (location == 0xFF && djinni == 0xFF) break; 43 | djinniMap['0x' + location.toString('16')] = djinni; 44 | } 45 | 46 | // Get character level scaling 47 | let startingLevels = [0, 0, 0, 0, 0, 0, 0, 0]; 48 | while (pos < arr.length - 1) { 49 | let char = arr[pos++]; 50 | let level = arr[pos++]; 51 | if (char == 0xFF) break; 52 | if (char >= 8) continue; 53 | startingLevels[char] = level; 54 | } 55 | 56 | return {seed, settings, userName, itemMap, djinniMap, startingLevels}; 57 | } 58 | 59 | module.exports = {parseAPFile}; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gs2r2", 3 | "version": "1.2.11", 4 | "description": "Golden Sun TLA Randomiser2", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "node app.js", 8 | "gen-graph": "node ./run/generate_logic_graph.js && node ./run/validate_logic_graph.js && node ./run/test_logic_graph.js", 9 | "validate-graph": "node ./run/validate_logic_graph.js", 10 | "test-graph": "node ./run/test_logic_graph.js" 11 | }, 12 | "author": "Karanum", 13 | "license": "MIT", 14 | "dependencies": { 15 | "@selectize/selectize": "^0.15.2", 16 | "body-parser": "^1.20.3", 17 | "cookie-parser": "^1.4.6", 18 | "crc": "^3.8.0", 19 | "ejs": "^3.1.6", 20 | "express": "^4.17.1", 21 | "fast-mersenne-twister": "^1.0.3", 22 | "graphology": "^0.26.0", 23 | "graphology-shortest-path": "^2.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /permalinks.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "name": "Example Category", 5 | "desc": "Lorem ipsum (optional)", 6 | "contents": [ 7 | { 8 | "id": "permalink_id", 9 | "name": "Example permalink", 10 | "desc": "Lorem ipsum (optional)" 11 | } 12 | ] 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /public/css/font/Taranis.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/public/css/font/Taranis.ttf -------------------------------------------------------------------------------- /public/css/randomise.css: -------------------------------------------------------------------------------- 1 | 2 | .rot-base::before { 3 | transition: all 0.35s; 4 | } 5 | 6 | .rot-180::before { 7 | transform: rotate(180deg); 8 | } 9 | 10 | #card-log { 11 | overflow-x: auto; 12 | overflow-y: auto; 13 | max-height: 80vh; 14 | } 15 | 16 | #card-log > .nav { 17 | border-bottom-width: 0 !important; 18 | } 19 | 20 | #card-log .nav-link { 21 | white-space: nowrap !important; 22 | border-bottom: 1px solid #dee2e6; 23 | } 24 | 25 | @media (max-width: 768px) { 26 | #card-log > .nav { 27 | flex-wrap: nowrap !important; 28 | } 29 | } 30 | 31 | tr, td { 32 | border-style: none !important; 33 | } 34 | 35 | .table-active { 36 | border-top: 1px solid #000 !important; 37 | } 38 | 39 | table { 40 | font-size: smaller; 41 | } -------------------------------------------------------------------------------- /public/img/favicon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/public/img/favicon.webp -------------------------------------------------------------------------------- /public/img/gstlar-logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/public/img/gstlar-logo.webp -------------------------------------------------------------------------------- /public/js/common.js: -------------------------------------------------------------------------------- 1 | function setLang(lang) { 2 | let date = new Date(); 3 | date.setTime(date.getTime() + 2592000000); 4 | document.cookie = `lang=${lang};expires=${date.toUTCString()};path=/`; 5 | window.location = getLangPath(lang); 6 | } 7 | 8 | function getLangPath(lang) { 9 | let path = window.location.pathname; 10 | if (path.startsWith('/en/') || path.startsWith('/de/') || path.startsWith('/fr/') || path.startsWith('/es/')) { 11 | path = path.substring(3); 12 | } 13 | if (path.length == 0) path += "/index.html"; 14 | if (path.length == 1) path += "index.html"; 15 | 16 | return `/${lang}${path}`; 17 | } 18 | 19 | $(document).ready(() => { 20 | if ($("html").hasClass("dark")) { 21 | $("meta[name=theme-color]").remove(); 22 | $("head").append(''); 23 | } 24 | 25 | $("#btn-theme").click(() => { 26 | $("meta[name=theme-color]").remove(); 27 | if ($("html").hasClass("dark")) { 28 | localStorage.setItem("theme", "light"); 29 | $("html").removeClass("dark"); 30 | $("head").append(''); 31 | } else { 32 | localStorage.setItem("theme", "dark"); 33 | $("html").addClass("dark"); 34 | $("head").append(''); 35 | } 36 | }); 37 | 38 | $("#lang-en").click(() => setLang("en")); 39 | $("#lang-de").click(() => setLang("de")); 40 | $("#lang-fr").click(() => setLang("fr")); 41 | $("#lang-es").click(() => setLang("es")); 42 | }); -------------------------------------------------------------------------------- /randomiser/game_data/djinn.js: -------------------------------------------------------------------------------- 1 | const textOffset = 1747; 2 | const addrOffset = 0xFA0000; 3 | const statAddrOffset = 0xC6BB4; 4 | 5 | var djinnData = []; 6 | 7 | function initialise(rom, textutil) { 8 | for (var i = 0; i < 80; ++i) { 9 | var djinniId = i % 20; 10 | if (djinniId >= 18) continue; 11 | 12 | var element = Math.floor(i / 20); 13 | var name = textutil.readLinePretty(undefined, textOffset + i); 14 | var addr = addrOffset + 36 * element + 2 * djinniId; 15 | 16 | var statAddr = statAddrOffset + 240 * element + 12 * djinniId; 17 | var stats = [rom[statAddr], rom[statAddr + 1], rom[statAddr + 2], 18 | rom[statAddr + 3], rom[statAddr + 4], rom[statAddr + 5]]; 19 | 20 | djinnData.push({vanillaId: djinniId, vanillaElement: element, vanillaName: name, addr: addr, 21 | statAddr: statAddr, id: djinniId, element: element, name: name, stats: stats}); 22 | } 23 | } 24 | 25 | function clone() { 26 | return JSON.parse(JSON.stringify(djinnData)); 27 | } 28 | 29 | function writeToRom(instance, rom) { 30 | instance.forEach((djinni) => { 31 | var addr = djinni.addr; 32 | rom[addr] = djinni.id; 33 | rom[addr + 1] = djinni.element; 34 | 35 | var statAddr = djinni.statAddr; 36 | for (var i = 0; i < 6; ++i) { 37 | rom[statAddr + i] = djinni.stats[i]; 38 | } 39 | }); 40 | } 41 | 42 | function shuffleDjinn(instance, prng) { 43 | var djinniPool = []; 44 | for (var i = 0; i < djinnData.length; ++i) 45 | djinniPool.push(i); 46 | 47 | for (var i = 0; i < djinnData.length; ++i) { 48 | var index = djinniPool.splice(Math.floor(prng.random() * djinniPool.length), 1)[0]; 49 | var djinni = djinnData[index]; 50 | instance[i].name = djinni.vanillaName; 51 | instance[i].id = djinni.vanillaId; 52 | instance[i].element = djinni.vanillaElement; 53 | } 54 | } 55 | 56 | function shuffleStats(instance, prng) { 57 | var statPools = [[], [], [], [], [], []]; 58 | for (var i = 0; i < djinnData.length; ++i) { 59 | for (var j = 0; j < 6; ++j) { 60 | statPools[j].push(djinnData[i].stats[j]); 61 | } 62 | } 63 | 64 | for (var i = 0; i < djinnData.length; ++i) { 65 | for (var j = 0; j < 6; ++j) { 66 | instance[i].stats[j] = statPools[j].splice(Math.floor(prng.random() * statPools[j].length), 1)[0]; 67 | } 68 | } 69 | } 70 | 71 | module.exports = {initialise, clone, writeToRom, shuffleDjinn, shuffleStats}; -------------------------------------------------------------------------------- /randomiser/game_data/doors.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Data struct representing all "doors" (screen transitions/exits) in the game. 3 | * To be used in combination with the door randomiser to change where exits lead in-game. 4 | */ 5 | 6 | const { read32b, write32b } = require("../../util/binary"); 7 | 8 | // List of map code IDs to skip because they will not contain any shuffled exits 9 | const skipIds = [1612, 1613, 1614, 1615, 1673]; 10 | 11 | // Exit data container 12 | let exitData = []; 13 | 14 | // Internal function that returns the exit table pointer for a given map code block 15 | function getExitTablePointer(mapCode, id) { 16 | // Daila maps have multiple exit tables so we just pick the one we want 17 | if (id == 1617) return 0x1068; 18 | if (id == 1618) return 0x11B8; 19 | 20 | let funcPointer = read32b(mapCode, 0x14) - 0x02008001; 21 | return read32b(mapCode, funcPointer + 4) - 0x02008000; 22 | } 23 | 24 | // Loads the exit data from the game and populates the data container 25 | function initialise(mapCode) { 26 | for (let i = 1611; i <= 1713; ++i) { 27 | if (skipIds.includes(i)) continue; 28 | 29 | let pointer = getExitTablePointer(mapCode[i][1], i); 30 | let word = read32b(mapCode[i][1], pointer); 31 | let mapId = word; 32 | 33 | while (true) { 34 | pointer += 4; 35 | word = read32b(mapCode[i][1], pointer); 36 | if (word == 0x1FF) break; 37 | 38 | if ((word & 0xFFFFF000) == 0) { 39 | mapId = word; 40 | continue; 41 | } 42 | 43 | let exit = { mapCode: i, mapId, addr: pointer, exitId: (word >> 20) & 0xFF, destEntrance: (word >> 12) & 0xFF, destMap: word & 0xFFF }; 44 | 45 | if ((word & 0x10000000) != 0) { 46 | pointer += 4; 47 | exit.condition = read32b(mapCode[i][1], pointer); 48 | } 49 | 50 | exitData.push(exit); 51 | } 52 | } 53 | } 54 | 55 | // Returns a deep copy of the data container 56 | function clone() { 57 | return JSON.parse(JSON.stringify(exitData)); 58 | } 59 | 60 | // Writes the contents of (a copy of) the data container back into the game 61 | function writeToMapCode(instance, mapCode) { 62 | instance.forEach((exit) => { 63 | if (exit.vanillaDestMap == undefined) return; 64 | mapCode[exit.mapCode][0] = true; 65 | 66 | let entry = (exit.exitId << 20) + (exit.destEntrance << 12) + (exit.destMap); 67 | if (exit.condition) { 68 | entry += 0x10000000; 69 | write32b(mapCode[exit.mapCode][1], exit.addr + 4, exit.condition); 70 | } 71 | write32b(mapCode[exit.mapCode][1], exit.addr, entry); 72 | }); 73 | } 74 | 75 | module.exports = {initialise, clone, writeToMapCode}; -------------------------------------------------------------------------------- /randomiser/game_data/elem_tables.js: -------------------------------------------------------------------------------- 1 | const addrFrom = 0xC6684; 2 | const addrTo = 0xC6B04; 3 | 4 | var tableData = []; 5 | 6 | function initialise(rom) { 7 | var addr = addrFrom; 8 | while (addr < addrTo) { 9 | var element = rom[addr]; 10 | var levels = [rom[addr + 4], rom[addr + 5], rom[addr + 6], rom[addr + 7]]; 11 | var pow = [], res = []; 12 | for (var i = 0; i < 4; ++i) { 13 | pow.push(rom[addr + 4 * i + 8] + (rom[addr + 4 * i + 9] << 8)); 14 | res.push(rom[addr + 4 * i + 10] + (rom[addr + 4 * i + 11] << 8)); 15 | } 16 | tableData.push({addr: addr, element: element, levels: levels, elemPow: pow, elemRes: res}); 17 | addr += 24; 18 | } 19 | } 20 | 21 | function clone() { 22 | return JSON.parse(JSON.stringify(tableData)); 23 | } 24 | 25 | function writeToRom(instance, rom) { 26 | instance.forEach((table) => { 27 | var addr = table.addr; 28 | rom[addr] = table.element; 29 | for (var i = 0; i < 4; ++i) { 30 | rom[addr + i + 4] = table.levels[i]; 31 | rom[addr + 4 * i + 8] = (table.elemPow[i] & 0xFF); 32 | rom[addr + 4 * i + 9] = (table.elemPow[i] >> 8); 33 | rom[addr + 4 * i + 10] = (table.elemRes[i] & 0xFF); 34 | rom[addr + 4 * i + 11] = (table.elemRes[i] >> 8); 35 | } 36 | }); 37 | } 38 | 39 | function shuffleResistances(instance, prng) { 40 | instance.forEach((table) => { 41 | var oldRes = table.elemRes; 42 | table.elemRes = []; 43 | while (oldRes.length > 0) { 44 | table.elemRes.push(oldRes.splice(Math.floor(prng.random() * oldRes.length), 1)[0]); 45 | } 46 | }); 47 | } 48 | 49 | function randomiseResistances(instance, prng) { 50 | instance.forEach((table) => { 51 | var totalRes = 0; 52 | var newRes = []; 53 | table.elemRes.forEach((res) => {totalRes += res}); 54 | while (newRes.length < 4) { 55 | var res = totalRes; 56 | if (newRes.length != 3) 57 | res = Math.floor(Math.max(totalRes / 3, prng.random() * totalRes * 0.5)); 58 | res = Math.min(res, 200); 59 | totalRes -= res; 60 | newRes.push(res); 61 | } 62 | for (var i = 0; i < 4; ++i) { 63 | table.elemRes[i] = newRes.splice(Math.floor(prng.random() * newRes.length), 1)[0]; 64 | } 65 | }); 66 | } 67 | 68 | module.exports = {initialise, clone, writeToRom, shuffleResistances, randomiseResistances}; -------------------------------------------------------------------------------- /randomiser/game_data/forgeables.js: -------------------------------------------------------------------------------- 1 | const addrOffset = 0x10CC34; 2 | const itemData = require('./items.js'); 3 | 4 | const forgeData = {}; 5 | 6 | function initialise(rom) { 7 | var offset = 0; 8 | var itemId = rom[addrOffset] + (rom[addrOffset + 1] << 8); 9 | while (itemId != 0xFFFF) { 10 | var addr = addrOffset + offset; 11 | var results = []; 12 | for (var i = 0; i < 8; ++i) { 13 | results.push(rom[addr + 2 * i + 4] + (rom[addr + 2 * i + 5] << 8)); 14 | } 15 | forgeData[itemId] = {addr: addr, results: results}; 16 | 17 | offset += 36; 18 | itemId = rom[addrOffset + offset] + (rom[addrOffset + offset + 1] << 8); 19 | } 20 | } 21 | 22 | function clone() { 23 | return JSON.parse(JSON.stringify(forgeData)); 24 | } 25 | 26 | function writeToRom(instance, rom) { 27 | for (var item in instance) { 28 | if (!instance.hasOwnProperty(item)) continue; 29 | var addr = instance[item].addr; 30 | var results = instance[item].results; 31 | for (var i = 0; i < results.length; ++i) { 32 | rom[addr + 2 * i + 4] = (results[i] & 0xFF); 33 | rom[addr + 2 * i + 5] = (results[i] >> 8); 34 | } 35 | } 36 | } 37 | 38 | function getAllEquipment(instance, instItems) { 39 | var equipment = []; 40 | for (var item in instance) { 41 | if (!instance.hasOwnProperty(item)) continue; 42 | var results = instance[item].results; 43 | for (var i = 0; i < results.length; ++i) { 44 | if (results[i] == 0) continue; 45 | var data = instItems[results[i]]; 46 | if (data.itemType == 1 || itemData.isArmour(data.itemType)) 47 | equipment.push(results[i]); 48 | } 49 | } 50 | return equipment; 51 | } 52 | 53 | function shuffleEquipment(instance, prng, equipment) { 54 | for (var item in instance) { 55 | if (!instance.hasOwnProperty(item)) continue; 56 | var results = instance[item].results; 57 | for (var i = 0; i < results.length; ++i) { 58 | if (results[i] == 0) continue; 59 | var rand = Math.floor(prng.random() * equipment.length); 60 | results[i] = equipment.splice(rand, 1)[0]; 61 | } 62 | } 63 | } 64 | 65 | module.exports = {initialise, clone, writeToRom, getAllEquipment, shuffleEquipment}; -------------------------------------------------------------------------------- /randomiser/game_data/music.js: -------------------------------------------------------------------------------- 1 | const { read32b, read16b } = require("../../util/binary"); 2 | 3 | const addrOffset = 0x1C4530; 4 | 5 | const fieldBGM = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 39, 6 | 41, 42, 43, 44, 60, 61, 62, 63, 65, 67, 74, 76, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 720, 721, 722, 723, 724, 725, 726, 7 | 727, 728, 729, 730, 741, 742, 743]; 8 | const battleBGM = [49, 50, 51, 52, 53, 54, 55, 56, 57, 750, 751, 752, 753, 754]; 9 | 10 | var musicData = []; 11 | 12 | function shuffleBGM(instance, prng) { 13 | var pointers = instance.map((entry) => entry.pointer); 14 | instance.forEach((entry) => { 15 | var i = Math.floor(prng.random() * pointers.length); 16 | entry.pointer = pointers.splice(i, 1); 17 | }); 18 | } 19 | 20 | function initialise(rom) { 21 | fieldBGM.forEach((i) => { 22 | var addr = addrOffset + (i * 8); 23 | var pointer = read32b(rom, addr); 24 | var type = read16b(rom, addr + 4); 25 | musicData.push({ addr, pointer, type, forBattle: false }); 26 | }); 27 | battleBGM.forEach((i) => { 28 | var addr = addrOffset + (i * 8); 29 | var pointer = read32b(rom, addr); 30 | var type = read16b(rom, addr + 4); 31 | musicData.push({ addr, pointer, type, forBattle: true }); 32 | }); 33 | } 34 | 35 | function clone() { 36 | return JSON.parse(JSON.stringify(musicData)); 37 | } 38 | 39 | function writeToRom(instance, rom) { 40 | instance.forEach((entry) => { 41 | rom[entry.addr] = entry.pointer & 0xFF; 42 | rom[entry.addr + 1] = (entry.pointer >> 8) & 0xFF; 43 | rom[entry.addr + 2] = (entry.pointer >> 16) & 0xFF; 44 | rom[entry.addr + 3] = (entry.pointer >> 24) & 0xFF; 45 | }); 46 | } 47 | 48 | module.exports = { shuffleBGM, initialise, clone, writeToRom }; -------------------------------------------------------------------------------- /randomiser/game_logic/icons.js: -------------------------------------------------------------------------------- 1 | const { write32b, write16b, read32b, writeArray } = require("../../util/binary"); 2 | 3 | const pointerOffset = 0x3D4DC; 4 | const tableReadOffset = 0x54A14; 5 | const tableWriteOffset = 0xFFAA00; 6 | const iconWriteOffset = 0xFFB000; 7 | const mappingOffset = 0x0100311C; 8 | 9 | class IconManager { 10 | #nextId; 11 | #nextAddr; 12 | 13 | #iconData; 14 | #iconPointers; 15 | #iconMappings; 16 | 17 | constructor() { 18 | this.#nextId = 0x104; 19 | this.#nextAddr = 0x08000000 + iconWriteOffset; 20 | 21 | this.#iconData = []; 22 | this.#iconPointers = []; 23 | this.#iconMappings = []; 24 | } 25 | 26 | insertMapping(itemId, iconId) { 27 | write16b(this.#iconMappings, this.#iconMappings.length, itemId); 28 | write16b(this.#iconMappings, this.#iconMappings.length, iconId); 29 | } 30 | 31 | insertIcon(data) { 32 | this.#iconData = this.#iconData.concat(data); 33 | write32b(this.#iconPointers, this.#iconPointers.length, this.#nextAddr); 34 | 35 | this.#nextAddr += data.length; 36 | return this.#nextId++; 37 | } 38 | 39 | insertIconWithMapping(data, itemId) { 40 | let id = this.insertIcon(data); 41 | this.insertMapping(itemId, id); 42 | } 43 | 44 | writeToRom(rom) { 45 | this.#moveIconTable(rom); 46 | 47 | writeArray(rom, iconWriteOffset, this.#iconData); 48 | writeArray(rom, tableWriteOffset + 0x410, this.#iconPointers); 49 | writeArray(rom, mappingOffset, this.#iconMappings); 50 | 51 | write32b(rom, pointerOffset, 0x08000000 + tableWriteOffset + this.#nextId * 4); 52 | write32b(rom, pointerOffset + 4, 0x08000000 + tableWriteOffset); 53 | write32b(rom, pointerOffset + 0x598, 0x08000000 + tableWriteOffset); 54 | } 55 | 56 | #moveIconTable(rom) { 57 | let offset = 0; 58 | let word = read32b(rom, tableReadOffset); 59 | while (word != 0xFFFFFFFF) { 60 | write32b(rom, tableWriteOffset + offset, word); 61 | offset += 4; 62 | word = read32b(rom, tableReadOffset + offset); 63 | } 64 | } 65 | } 66 | 67 | module.exports = {IconManager}; -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Alhafra.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "YampiBackside" 5 | ], 6 | [ 7 | "Ship" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf1d", 13 | "Reqs": [ 14 | [ 15 | "Reveal" 16 | ], 17 | [ 18 | "Skips_BasicRG", 19 | "Skips_Missable" 20 | ] 21 | ] 22 | }, 23 | { 24 | "Addr": "0xf1e", 25 | "Reqs": [] 26 | }, 27 | { 28 | "Addr": "0xf1f", 29 | "Reqs": [ 30 | [ 31 | "Boss_Briggs" 32 | ] 33 | ] 34 | }, 35 | { 36 | "Addr": "0xf20", 37 | "Reqs": [] 38 | }, 39 | { 40 | "Addr": "0xf21", 41 | "Reqs": [] 42 | }, 43 | { 44 | "Addr": "0xf23", 45 | "Reqs": [] 46 | }, 47 | { 48 | "Addr": "0xf24", 49 | "Reqs": [] 50 | } 51 | ], 52 | "Djinn": [], 53 | "Special": [ 54 | { 55 | "Name": "Boss_Briggs", 56 | "Type": "Boss", 57 | "Reqs": [ 58 | [ 59 | "AnyDjinn_6" 60 | ] 61 | ] 62 | }, 63 | { 64 | "Name": "BriggsEscaped", 65 | "Type": "Flag", 66 | "Reqs": [ 67 | [ 68 | "Boss_Briggs", 69 | "Lash Pebble", 70 | "Pound Cube", 71 | "Burst Brooch" 72 | ], 73 | [ 74 | "Boss_Briggs", 75 | "Skips_SaveQuitRG", 76 | "Burst Brooch" 77 | ], 78 | [ 79 | "Skips_SandGlitch", 80 | "Sand" 81 | ] 82 | ] 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/AlhafranCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Boss_Briggs", 5 | "Tremor Bit" 6 | ], 7 | [ 8 | "BriggsEscaped" 9 | ] 10 | ], 11 | "Treasure": [ 12 | { 13 | "Addr": "0xf25", 14 | "Reqs": [ 15 | [ 16 | "Pound Cube", 17 | "Lash Pebble" 18 | ] 19 | ] 20 | }, 21 | { 22 | "Addr": "0xf26", 23 | "Reqs": [ 24 | [ 25 | "Pound Cube", 26 | "Lash Pebble" 27 | ] 28 | ] 29 | }, 30 | { 31 | "Addr": "0xf27", 32 | "Reqs": [ 33 | [ 34 | "Pound Cube", 35 | "Lash Pebble" 36 | ] 37 | ] 38 | }, 39 | { 40 | "Addr": "0xf8e", 41 | "Reqs": [ 42 | [ 43 | "BriggsEscaped" 44 | ] 45 | ] 46 | }, 47 | { 48 | "Addr": "0xf8f", 49 | "Reqs": [ 50 | [ 51 | "BriggsEscaped", 52 | "Frost Jewel" 53 | ], 54 | [ 55 | "Pound Cube", 56 | "Lash Pebble", 57 | "Skips_BasicRG", 58 | "Skips_Missable" 59 | ] 60 | ] 61 | }, 62 | { 63 | "Addr": "0xf90", 64 | "Reqs": [ 65 | [ 66 | "BriggsEscaped", 67 | "Frost Jewel" 68 | ], 69 | [ 70 | "Pound Cube", 71 | "Lash Pebble", 72 | "Skips_BasicRG", 73 | "Skips_Missable" 74 | ] 75 | ] 76 | }, 77 | { 78 | "Addr": "0xf91", 79 | "Reqs": [ 80 | [ 81 | "BriggsEscaped", 82 | "Frost Jewel" 83 | ], 84 | [ 85 | "Pound Cube", 86 | "Lash Pebble", 87 | "Skips_BasicRG", 88 | "Skips_Missable" 89 | ] 90 | ] 91 | } 92 | ], 93 | "Djinn": [], 94 | "Special": [] 95 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/AnemosInnerSanctum.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0x1b", 16 | "Reqs": [ 17 | [ 18 | "Teleport Lapis" 19 | ] 20 | ] 21 | }, 22 | { 23 | "Addr": "0x1c", 24 | "Reqs": [ 25 | [ 26 | "Teleport Lapis", 27 | "Boss_Dullahan" 28 | ], 29 | [ 30 | "Reveal", 31 | "Skips_BasicRG", 32 | "Skips_Missable" 33 | ], 34 | [ 35 | "Teleport Lapis", 36 | "Skips_BasicRG" 37 | ] 38 | ] 39 | }, 40 | { 41 | "Addr": "0xe05", 42 | "Reqs": [ 43 | [ 44 | "Teleport Lapis" 45 | ] 46 | ] 47 | }, 48 | { 49 | "Addr": "0xe06", 50 | "Reqs": [ 51 | [ 52 | "Teleport Lapis", 53 | "Lifting Gem" 54 | ] 55 | ] 56 | } 57 | ], 58 | "Djinn": [], 59 | "Special": [ 60 | { 61 | "Name": "Boss_Dullahan", 62 | "Type": "Boss", 63 | "Reqs": [ 64 | [ 65 | "Teleport Lapis", 66 | "Lifting Gem", 67 | "Sand", 68 | "Hover Jade", 69 | "AnyDjinn_72" 70 | ] 71 | ] 72 | } 73 | ] 74 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/AngaraCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0x15", 16 | "Reqs": [ 17 | [ 18 | "Carry Stone" 19 | ] 20 | ] 21 | } 22 | ], 23 | "Djinn": [], 24 | "Special": [] 25 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/ApojiiIslands.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ], 6 | [ 7 | "Skips_SanctumWarp" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf9a", 13 | "Reqs": [ 14 | [ 15 | "Cyclone Chip" 16 | ] 17 | ] 18 | }, 19 | { 20 | "Addr": "0xf9b", 21 | "Reqs": [ 22 | [ 23 | "Cyclone Chip" 24 | ] 25 | ] 26 | }, 27 | { 28 | "Addr": "0xf9c", 29 | "Reqs": [] 30 | }, 31 | { 32 | "Addr": "0xf9d", 33 | "Reqs": [] 34 | }, 35 | { 36 | "Addr": "0xf9e", 37 | "Reqs": [ 38 | [ 39 | "Cyclone Chip" 40 | ] 41 | ] 42 | } 43 | ], 44 | "Djinn": [ 45 | { 46 | "Addr": "0x77", 47 | "Reqs": [ 48 | [ 49 | "Sand", 50 | "Whirlwind" 51 | ], 52 | [ 53 | "Whirlwind", 54 | "Skips_BasicRG" 55 | ], 56 | [ 57 | "Lash Pebble", 58 | "Skips_BasicRG" 59 | ] 60 | ] 61 | } 62 | ], 63 | "Special": [] 64 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/AttekaCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Reunion", 5 | "Hover Jade" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ], 12 | [ 13 | "Ship", 14 | "Grindstone", 15 | "Skips_WiggleClip" 16 | ] 17 | ], 18 | "Treasure": [ 19 | { 20 | "Addr": "0x17", 21 | "Reqs": [ 22 | [ 23 | "Parch" 24 | ] 25 | ] 26 | } 27 | ], 28 | "Djinn": [], 29 | "Special": [] 30 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/AttekaInlet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0xfc4", 16 | "Reqs": [] 17 | } 18 | ], 19 | "Djinn": [ 20 | { 21 | "Addr": "0x3f", 22 | "Reqs": [ 23 | [ 24 | "Cyclone Chip", 25 | "Lifting Gem" 26 | ], 27 | [ 28 | "Skips_SaveQuitRG" 29 | ] 30 | ] 31 | } 32 | ], 33 | "Special": [] 34 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Champa.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0x978", 10 | "Reqs": [ 11 | [ 12 | "Boss_Avimander", 13 | "Left Prong", 14 | "Center Prong", 15 | "Right Prong", 16 | "Reveal" 17 | ] 18 | ], 19 | "Restriction": [ 20 | "no-empty", 21 | "no-mimic" 22 | ] 23 | }, 24 | { 25 | "Addr": "0xfaa", 26 | "Reqs": [ 27 | [ 28 | "Reveal" 29 | ], 30 | [ 31 | "Skips_BasicRG", 32 | "Skips_Missable" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xfab", 38 | "Reqs": [] 39 | }, 40 | { 41 | "Addr": "0xfac", 42 | "Reqs": [] 43 | }, 44 | { 45 | "Addr": "0xfad", 46 | "Reqs": [] 47 | }, 48 | { 49 | "Addr": "0xfae", 50 | "Reqs": [] 51 | }, 52 | { 53 | "Addr": "0xfaf", 54 | "Reqs": [] 55 | } 56 | ], 57 | "Djinn": [], 58 | "Special": [ 59 | { 60 | "Name": "Boss_Avimander", 61 | "Type": "Boss", 62 | "Reqs": [ 63 | [ 64 | "AnyDjinn_20", 65 | "BriggsEscaped" 66 | ] 67 | ] 68 | } 69 | ] 70 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Daila.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0xa20", 6 | "Reqs": [ 7 | [ 8 | "Frost Jewel" 9 | ], 10 | [ 11 | "Skips_SaveQuitRG" 12 | ] 13 | ], 14 | "Restriction": [ 15 | "no-empty", 16 | "no-mimic" 17 | ] 18 | }, 19 | { 20 | "Addr": "0xf01", 21 | "Reqs": [] 22 | }, 23 | { 24 | "Addr": "0xf02", 25 | "Reqs": [] 26 | }, 27 | { 28 | "Addr": "0xf03", 29 | "Reqs": [] 30 | }, 31 | { 32 | "Addr": "0xf04", 33 | "Reqs": [] 34 | }, 35 | { 36 | "Addr": "0xf05", 37 | "Reqs": [] 38 | }, 39 | { 40 | "Addr": "0xf5e", 41 | "Reqs": [ 42 | [ 43 | "Scoop Gem" 44 | ] 45 | ] 46 | } 47 | ], 48 | "Djinn": [], 49 | "Special": [] 50 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/DehkanPlateau.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x878", 6 | "Reqs": [], 7 | "Restriction": [ 8 | "no-mimic", 9 | "no-empty" 10 | ] 11 | }, 12 | { 13 | "Addr": "0xf07", 14 | "Reqs": [] 15 | }, 16 | { 17 | "Addr": "0xf08", 18 | "Reqs": [] 19 | }, 20 | { 21 | "Addr": "0xf09", 22 | "Reqs": [] 23 | }, 24 | { 25 | "Addr": "0xf0a", 26 | "Reqs": [] 27 | }, 28 | { 29 | "Addr": "0xf0b", 30 | "Reqs": [ 31 | [ 32 | "Lash Pebble" 33 | ], 34 | [ 35 | "Skips_BasicRG", 36 | "Skips_Missable" 37 | ], 38 | [ 39 | "Skips_SaveQuitRG", 40 | "Skips_Missable" 41 | ] 42 | ] 43 | } 44 | ], 45 | "Djinn": [ 46 | { 47 | "Addr": "0x5f", 48 | "Reqs": [ 49 | [ 50 | "Pound Cube" 51 | ] 52 | ] 53 | } 54 | ], 55 | "Special": [] 56 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/ETundariaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xaa2", 10 | "Reqs": [], 11 | "Restriction": [ 12 | "no-empty", 13 | "no-mimic" 14 | ] 15 | }, 16 | { 17 | "Addr": "0xf92", 18 | "Reqs": [] 19 | } 20 | ], 21 | "Djinn": [], 22 | "Special": [] 23 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/GabombaCatacombs.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "GabombaCleared" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xf53", 10 | "Reqs": [ 11 | [ 12 | "Cyclone Chip" 13 | ] 14 | ] 15 | }, 16 | { 17 | "Addr": "0xf93", 18 | "Reqs": [ 19 | [ 20 | "Cyclone Chip", 21 | "Reveal", 22 | "Frost Jewel" 23 | ] 24 | ], 25 | "Restriction": [ 26 | "no-empty", 27 | "no-mimic" 28 | ] 29 | } 30 | ], 31 | "Djinn": [ 32 | { 33 | "Addr": "0x3a", 34 | "Reqs": [ 35 | [ 36 | "Cyclone Chip" 37 | ] 38 | ] 39 | } 40 | ], 41 | "Special": [] 42 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/GabombaStatue.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "FlagPiers", 5 | "Scoop Gem" 6 | ] 7 | ], 8 | "Treasure": [ 9 | { 10 | "Addr": "0x8ff", 11 | "Reqs": [ 12 | [ 13 | "GabombaCleared" 14 | ] 15 | ], 16 | "Restriction": [ 17 | "no-empty", 18 | "no-mimic" 19 | ] 20 | }, 21 | { 22 | "Addr": "0xe72", 23 | "Reqs": [] 24 | }, 25 | { 26 | "Addr": "0xf51", 27 | "Reqs": [] 28 | }, 29 | { 30 | "Addr": "0xf52", 31 | "Reqs": [ 32 | [ 33 | "Lash Pebble" 34 | ], 35 | [ 36 | "Skips_SaveQuitRG", 37 | "FlagPiers", 38 | "Scoop Gem" 39 | ] 40 | ] 41 | } 42 | ], 43 | "Djinn": [ 44 | { 45 | "Addr": "0x39", 46 | "Reqs": [ 47 | [ 48 | "Lash Pebble", 49 | "Pound Cube" 50 | ], 51 | [ 52 | "Skips_SaveQuitRG", 53 | "FlagPiers", 54 | "Scoop Gem", 55 | "Pound Cube" 56 | ] 57 | ] 58 | } 59 | ], 60 | "Special": [ 61 | { 62 | "Name": "GabombaCleared", 63 | "Type": "Flag", 64 | "Reqs": [ 65 | [ 66 | "Lash Pebble", 67 | "Pound Cube" 68 | ], 69 | [ 70 | "Skips_SaveQuitRG", 71 | "FlagPiers", 72 | "Scoop Gem", 73 | "Pound Cube" 74 | ] 75 | ] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Garoh.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0xf2d", 6 | "Reqs": [ 7 | [ 8 | "Reveal" 9 | ] 10 | ] 11 | }, 12 | { 13 | "Addr": "0xf2e", 14 | "Reqs": [] 15 | }, 16 | { 17 | "Addr": "0xf2f", 18 | "Reqs": [] 19 | }, 20 | { 21 | "Addr": "0xf30", 22 | "Reqs": [] 23 | }, 24 | { 25 | "Addr": "0xf31", 26 | "Reqs": [] 27 | } 28 | ], 29 | "Djinn": [ 30 | { 31 | "Addr": "0x75", 32 | "Reqs": [ 33 | [ 34 | "Reveal" 35 | ] 36 | ] 37 | } 38 | ], 39 | "Special": [] 40 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/GondowanCliffs.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0xf40", 6 | "Reqs": [ 7 | [ 8 | "Frost Jewel" 9 | ] 10 | ] 11 | }, 12 | { 13 | "Addr": "0xf41", 14 | "Reqs": [ 15 | [ 16 | "Frost Jewel" 17 | ], 18 | [ 19 | "Scoop Gem" 20 | ], 21 | [ 22 | "GondowanAccess", 23 | "Boss_Briggs" 24 | ] 25 | ] 26 | }, 27 | { 28 | "Addr": "0xf43", 29 | "Reqs": [ 30 | [ 31 | "Frost Jewel" 32 | ], 33 | [ 34 | "Scoop Gem" 35 | ], 36 | [ 37 | "GondowanAccess", 38 | "Boss_Briggs" 39 | ] 40 | ] 41 | } 42 | ], 43 | "Djinn": [ 44 | { 45 | "Addr": "0x61", 46 | "Reqs": [ 47 | [ 48 | "Frost Jewel" 49 | ], 50 | [ 51 | "Scoop Gem" 52 | ], 53 | [ 54 | "GondowanAccess", 55 | "Boss_Briggs" 56 | ] 57 | ] 58 | } 59 | ], 60 | "Special": [ 61 | { 62 | "Name": "GondowanAccess", 63 | "Type": "Flag", 64 | "Reqs": [ 65 | [ 66 | "Ship" 67 | ], 68 | [ 69 | "Boss_Briggs", 70 | "Frost Jewel" 71 | ], 72 | [ 73 | "Boss_Briggs", 74 | "Scoop Gem" 75 | ], 76 | [ 77 | "Skips_OOBRG", 78 | "Whirlwind" 79 | ] 80 | ] 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/GondowanSettlement.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0xfc0", 16 | "Reqs": [ 17 | [ 18 | "Cyclone Chip" 19 | ] 20 | ] 21 | }, 22 | { 23 | "Addr": "0xfc1", 24 | "Reqs": [] 25 | } 26 | ], 27 | "Djinn": [], 28 | "Special": [] 29 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/HesperiaSettlement.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0xfc2", 16 | "Reqs": [ 17 | [ 18 | "Growth" 19 | ], 20 | [ 21 | "Skips_OOBRG" 22 | ] 23 | ] 24 | } 25 | ], 26 | "Djinn": [ 27 | { 28 | "Addr": "0x66", 29 | "Reqs": [ 30 | [ 31 | "Growth" 32 | ], 33 | [ 34 | "Skips_OOBRG" 35 | ] 36 | ] 37 | } 38 | ], 39 | "Special": [] 40 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Idejima.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x1", 6 | "Reqs": [], 7 | "Restriction": ["no-summon"] 8 | }, 9 | { 10 | "Addr": "0x2", 11 | "Reqs": [], 12 | "Restriction": ["no-summon"] 13 | }, 14 | { 15 | "Addr": "0x3", 16 | "Reqs": [], 17 | "Restriction": ["no-summon"] 18 | }, 19 | { 20 | "Addr": "0x4", 21 | "Reqs": [], 22 | "Restriction": ["no-summon"] 23 | }, 24 | { 25 | "Addr": "0xd05", 26 | "Reqs": [], 27 | "Restriction": ["no-empty", "no-mimic"] 28 | }, 29 | { 30 | "Addr": "0xd06", 31 | "Reqs": [], 32 | "Restriction": ["no-empty", "no-mimic"] 33 | } 34 | ], 35 | "Djinn": [], 36 | "Special": [] 37 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/IndraCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x10", 6 | "Reqs": [ 7 | [ 8 | "Lash Pebble" 9 | ] 10 | ] 11 | } 12 | ], 13 | "Djinn": [], 14 | "Special": [] 15 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/IsletCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Mind Read", 6 | "Li'l Turtle" 7 | ] 8 | ], 9 | "Treasure": [ 10 | { 11 | "Addr": "0x1a", 12 | "Reqs": [ 13 | [ 14 | "Boss_Sentinel" 15 | ] 16 | ] 17 | }, 18 | { 19 | "Addr": "0xfa8", 20 | "Reqs": [] 21 | }, 22 | { 23 | "Addr": "0xfa9", 24 | "Reqs": [] 25 | } 26 | ], 27 | "Djinn": [ 28 | { 29 | "Addr": "0x3c", 30 | "Reqs": [] 31 | }, 32 | { 33 | "Addr": "0x55", 34 | "Reqs": [ 35 | [ 36 | "Teleport Lapis", 37 | "Tremor Bit" 38 | ], 39 | [ 40 | "Skips_OOBRG", 41 | "Sand", 42 | "Tremor Bit" 43 | ] 44 | ] 45 | } 46 | ], 47 | "Special": [ 48 | { 49 | "Name": "Boss_Sentinel", 50 | "Type": "Boss", 51 | "Reqs": [ 52 | [ 53 | "AnyDjinn_64", 54 | "Teleport Lapis" 55 | ], 56 | [ 57 | "AnyDjinn_64", 58 | "Skips_OOBRG", 59 | "Sand" 60 | ] 61 | ] 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Izumo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0x14", 10 | "Reqs": [ 11 | [ 12 | "Reveal", 13 | "Sand", 14 | "Frost Jewel", 15 | "Pound Cube", 16 | "Parch" 17 | ] 18 | ] 19 | }, 20 | { 21 | "Addr": "0xf9f", 22 | "Reqs": [ 23 | [ 24 | "Cyclone Chip" 25 | ] 26 | ] 27 | }, 28 | { 29 | "Addr": "0xfa0", 30 | "Reqs": [ 31 | [ 32 | "Cyclone Chip" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xfa1", 38 | "Reqs": [ 39 | [ 40 | "Cyclone Chip" 41 | ] 42 | ] 43 | }, 44 | { 45 | "Addr": "0xfa2", 46 | "Reqs": [] 47 | }, 48 | { 49 | "Addr": "0xfa3", 50 | "Reqs": [] 51 | }, 52 | { 53 | "Addr": "0xfa4", 54 | "Reqs": [] 55 | }, 56 | { 57 | "Addr": "0xfa5", 58 | "Reqs": [] 59 | }, 60 | { 61 | "Addr": "0xfa6", 62 | "Reqs": [ 63 | [ 64 | "Reveal", 65 | "Sand", 66 | "Frost Jewel", 67 | "Pound Cube" 68 | ] 69 | ] 70 | } 71 | ], 72 | "Djinn": [ 73 | { 74 | "Addr": "0x63", 75 | "Reqs": [ 76 | [ 77 | "Boss_Serpent", 78 | "Dancing Idol" 79 | ] 80 | ] 81 | } 82 | ], 83 | "Special": [] 84 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/KaltIsland.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [], 14 | "Djinn": [ 15 | { 16 | "Addr": "0x52", 17 | "Reqs": [ 18 | [ 19 | "Lash Pebble" 20 | ], 21 | [ 22 | "Skips_WiggleClip" 23 | ] 24 | ] 25 | } 26 | ], 27 | "Special": [] 28 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/KandoreanTemple.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x84a", 6 | "Reqs": [ 7 | [ 8 | "Whirlwind" 9 | ] 10 | ], 11 | "Restriction": [ 12 | "no-empty", 13 | "no-mimic" 14 | ] 15 | }, 16 | { 17 | "Addr": "0xe70", 18 | "Reqs": [ 19 | [ 20 | "Whirlwind" 21 | ] 22 | ] 23 | }, 24 | { 25 | "Addr": "0xf06", 26 | "Reqs": [ 27 | [ 28 | "Whirlwind" 29 | ] 30 | ] 31 | } 32 | ], 33 | "Djinn": [ 34 | { 35 | "Addr": "0x4b", 36 | "Reqs": [ 37 | [ 38 | "Whirlwind", 39 | "Lash Pebble" 40 | ] 41 | ] 42 | } 43 | ], 44 | "Special": [] 45 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Kibombo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ], 6 | [ 7 | "GondowanAccess", 8 | "Frost Jewel" 9 | ], 10 | [ 11 | "GondowanAccess", 12 | "Lash Pebble", 13 | "Whirlwind" 14 | ] 15 | ], 16 | "Treasure": [ 17 | { 18 | "Addr": "0x105", 19 | "Reqs": [["FlagPiers"]], 20 | "Restriction": ["no-summon"] 21 | }, 22 | { 23 | "Addr": "0x106", 24 | "Reqs": [["FlagPiers"]], 25 | "Restriction": ["no-summon"] 26 | }, 27 | { 28 | "Addr": "0xd07", 29 | "Reqs": [["FlagPiers"]], 30 | "Restriction": ["no-empty", "no-mimic"] 31 | }, 32 | { 33 | "Addr": "0xf4e", 34 | "Reqs": [] 35 | }, 36 | { 37 | "Addr": "0xf4f", 38 | "Reqs": [ 39 | [ 40 | "GabombaCleared" 41 | ] 42 | ] 43 | }, 44 | { 45 | "Addr": "0xf50", 46 | "Reqs": [ 47 | [ 48 | "GabombaCleared" 49 | ] 50 | ] 51 | } 52 | ], 53 | "Djinn": [ 54 | { 55 | "Addr": "0x4d", 56 | "Reqs": [ 57 | [ 58 | "FlagPiers" 59 | ] 60 | ] 61 | }, 62 | { 63 | "Addr": "0x4e", 64 | "Reqs": [ 65 | [ 66 | "FlagPiers" 67 | ] 68 | ] 69 | } 70 | ], 71 | "Special": [ 72 | { 73 | "Name": "FlagPiers", 74 | "Type": "Flag", 75 | "Reqs": [ 76 | [ 77 | "Lash Pebble" 78 | ], 79 | [ 80 | "Skips_SanctumWarp" 81 | ] 82 | ] 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/KibomboMountains.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "GondowanAccess" 5 | ], 6 | [ 7 | "Ship" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf49", 13 | "Reqs": [ 14 | [ 15 | "Lash Pebble" 16 | ], 17 | [ 18 | "GabombaCleared" 19 | ], 20 | [ 21 | "Ship", 22 | "Skips_BasicRG" 23 | ] 24 | ] 25 | }, 26 | { 27 | "Addr": "0xf4a", 28 | "Reqs": [ 29 | [ 30 | "Lash Pebble" 31 | ], 32 | [ 33 | "GabombaCleared" 34 | ], 35 | [ 36 | "Ship", 37 | "Skips_BasicRG" 38 | ] 39 | ] 40 | }, 41 | { 42 | "Addr": "0xf4b", 43 | "Reqs": [] 44 | }, 45 | { 46 | "Addr": "0xf4c", 47 | "Reqs": [ 48 | [ 49 | "Lash Pebble" 50 | ], 51 | [ 52 | "GabombaCleared" 53 | ], 54 | [ 55 | "Ship", 56 | "Skips_BasicRG" 57 | ] 58 | ] 59 | } 60 | ], 61 | "Djinn": [ 62 | { 63 | "Addr": "0x76", 64 | "Reqs": [ 65 | [ 66 | "Frost Jewel", 67 | "Growth" 68 | ], 69 | [ 70 | "Lash Pebble", 71 | "Skips_SaveQuitRG" 72 | ], 73 | [ 74 | "Ship", 75 | "Skips_SaveQuitRG" 76 | ] 77 | ] 78 | } 79 | ], 80 | "Special": [] 81 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Lemuria.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Boss_Poseidon" 5 | ], 6 | [ 7 | "Ship", 8 | "Grindstone" 9 | ], 10 | [ 11 | "Ship", 12 | "Skips_DeathStorage" 13 | ] 14 | ], 15 | "Treasure": [ 16 | { 17 | "Addr": "0x90b", 18 | "Reqs": [] 19 | }, 20 | { 21 | "Addr": "0xf67", 22 | "Reqs": [] 23 | }, 24 | { 25 | "Addr": "0xfb9", 26 | "Reqs": [ 27 | [ 28 | "Scoop Gem" 29 | ] 30 | ] 31 | }, 32 | { 33 | "Addr": "0xfba", 34 | "Reqs": [ 35 | [ 36 | "Scoop Gem" 37 | ] 38 | ] 39 | }, 40 | { 41 | "Addr": "0xfbb", 42 | "Reqs": [ 43 | [ 44 | "Growth", 45 | "Cyclone Chip" 46 | ] 47 | ] 48 | }, 49 | { 50 | "Addr": "0xfbc", 51 | "Reqs": [ 52 | [ 53 | "Scoop Gem" 54 | ] 55 | ] 56 | }, 57 | { 58 | "Addr": "0xfbd", 59 | "Reqs": [ 60 | [ 61 | "Scoop Gem" 62 | ] 63 | ] 64 | }, 65 | { 66 | "Addr": "0xfbf", 67 | "Reqs": [] 68 | } 69 | ], 70 | "Djinn": [ 71 | { 72 | "Addr": "0x51", 73 | "Reqs": [ 74 | [ 75 | "Grindstone", 76 | "Cyclone Chip", 77 | "Tremor Bit" 78 | ] 79 | ] 80 | } 81 | ], 82 | "Special": [] 83 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Loho.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0xff5", 16 | "Reqs": [ 17 | [ 18 | "Magma Ball", 19 | "Scoop Gem" 20 | ] 21 | ] 22 | }, 23 | { 24 | "Addr": "0xff6", 25 | "Reqs": [ 26 | [ 27 | "Magma Ball", 28 | "Scoop Gem" 29 | ], 30 | [ 31 | "Skips_SaveQuitRG", 32 | "Scoop Gem" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xff7", 38 | "Reqs": [ 39 | [ 40 | "Magma Ball", 41 | "Lifting Gem", 42 | "Scoop Gem" 43 | ], 44 | [ 45 | "Skips_SaveQuitRG", 46 | "Lifting Gem", 47 | "Scoop Gem" 48 | ] 49 | ] 50 | }, 51 | { 52 | "Addr": "0xff8", 53 | "Reqs": [] 54 | } 55 | ], 56 | "Djinn": [ 57 | { 58 | "Addr": "0x7c", 59 | "Reqs": [ 60 | [ 61 | "Magma Ball" 62 | ], 63 | [ 64 | "Skips_SaveQuitRG" 65 | ] 66 | ] 67 | } 68 | ], 69 | "Special": [] 70 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Madra.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x918", 6 | "Reqs": [ 7 | [ 8 | "GabombaCleared" 9 | ], 10 | [ 11 | "Skips_BasicRG", 12 | "Skips_Missable" 13 | ] 14 | ], 15 | "Restriction": [ 16 | "no-empty", 17 | "no-mimic" 18 | ] 19 | }, 20 | { 21 | "Addr": "0xf0c", 22 | "Reqs": [] 23 | }, 24 | { 25 | "Addr": "0xf0d", 26 | "Reqs": [] 27 | }, 28 | { 29 | "Addr": "0xf0e", 30 | "Reqs": [] 31 | }, 32 | { 33 | "Addr": "0xf0f", 34 | "Reqs": [] 35 | }, 36 | { 37 | "Addr": "0xf10", 38 | "Reqs": [] 39 | }, 40 | { 41 | "Addr": "0xf11", 42 | "Reqs": [] 43 | } 44 | ], 45 | "Djinn": [ 46 | { 47 | "Addr": "0x62", 48 | "Reqs": [ 49 | [ 50 | "Healing Fungus" 51 | ] 52 | ] 53 | } 54 | ], 55 | "Special": [] 56 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/MadraCatacombs.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x13", 6 | "Reqs": [ 7 | [ 8 | "Reveal", 9 | "Ruin Key" 10 | ] 11 | ] 12 | }, 13 | { 14 | "Addr": "0xf13", 15 | "Reqs": [ 16 | [ 17 | "Reveal" 18 | ] 19 | ] 20 | }, 21 | { 22 | "Addr": "0xf14", 23 | "Reqs": [ 24 | [ 25 | "Reveal" 26 | ] 27 | ] 28 | }, 29 | { 30 | "Addr": "0xf15", 31 | "Reqs": [ 32 | [ 33 | "Reveal", 34 | "Lash Pebble", 35 | "Frost Jewel", 36 | "Tremor Bit" 37 | ] 38 | ] 39 | }, 40 | { 41 | "Addr": "0xf16", 42 | "Reqs": [ 43 | [ 44 | "Reveal" 45 | ] 46 | ] 47 | }, 48 | { 49 | "Addr": "0xf42", 50 | "Reqs": [ 51 | [ 52 | "Reveal", 53 | "Lash Pebble", 54 | "Frost Jewel" 55 | ] 56 | ] 57 | } 58 | ], 59 | "Djinn": [], 60 | "Special": [] 61 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Mikasalla.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0xf28", 6 | "Reqs": [] 7 | }, 8 | { 9 | "Addr": "0xf29", 10 | "Reqs": [] 11 | }, 12 | { 13 | "Addr": "0xf2a", 14 | "Reqs": [] 15 | }, 16 | { 17 | "Addr": "0xf2b", 18 | "Reqs": [] 19 | }, 20 | { 21 | "Addr": "0xf2c", 22 | "Reqs": [] 23 | } 24 | ], 25 | "Djinn": [ 26 | { 27 | "Addr": "0x60", 28 | "Reqs": [ 29 | [ 30 | "Scoop Gem" 31 | ], 32 | [ 33 | "Skips_SaveQuitRG" 34 | ] 35 | ] 36 | } 37 | ], 38 | "Special": [] 39 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/NOseniaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xaa3", 10 | "Reqs": [ 11 | [ 12 | "Mind Read", 13 | "Sand", 14 | "Red Cloth" 15 | ] 16 | ], 17 | "Restriction": [ 18 | "no-empty", 19 | "no-mimic" 20 | ] 21 | }, 22 | { 23 | "Addr": "0xf12", 24 | "Reqs": [] 25 | } 26 | ], 27 | "Djinn": [], 28 | "Special": [] 29 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Naribwe.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "GondowanAccess" 5 | ], 6 | [ 7 | "Ship" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf44", 13 | "Reqs": [ 14 | [ 15 | "Lash Pebble" 16 | ], 17 | [ 18 | "Skips_BasicRG", 19 | "Skips_Missable" 20 | ] 21 | ] 22 | }, 23 | { 24 | "Addr": "0xf45", 25 | "Reqs": [ 26 | [ 27 | "Whirlwind", 28 | "Reveal" 29 | ], 30 | [ 31 | "Skips_BasicRG", 32 | "Skips_Missable" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xf46", 38 | "Reqs": [] 39 | }, 40 | { 41 | "Addr": "0xf47", 42 | "Reqs": [] 43 | }, 44 | { 45 | "Addr": "0xf48", 46 | "Reqs": [] 47 | } 48 | ], 49 | "Djinn": [], 50 | "Special": [] 51 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/OseniaCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x11", 6 | "Reqs": [ 7 | [ 8 | "Scoop Gem" 9 | ] 10 | ] 11 | } 12 | ], 13 | "Djinn": [], 14 | "Special": [] 15 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/OseniaCliffs.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0xf17", 6 | "Reqs": [ 7 | [ 8 | "Lash Pebble" 9 | ] 10 | ] 11 | } 12 | ], 13 | "Djinn": [], 14 | "Special": [] 15 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Prox.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone", 6 | "Magma Ball" 7 | ], 8 | [ 9 | "Ship", 10 | "ShipWings", 11 | "Hover Jade", 12 | "Magma Ball" 13 | ], 14 | [ 15 | "Ship", 16 | "Grindstone", 17 | "Skips_DeathStorage" 18 | ], 19 | [ 20 | "Ship", 21 | "ShipWings", 22 | "Hover Jade", 23 | "Skips_DeathStorage" 24 | ] 25 | ], 26 | "Treasure": [ 27 | { 28 | "Addr": "0xff9", 29 | "Reqs": [ 30 | [ 31 | "Lifting Gem", 32 | "Scoop Gem" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xffa", 38 | "Reqs": [] 39 | }, 40 | { 41 | "Addr": "0xffb", 42 | "Reqs": [] 43 | }, 44 | { 45 | "Addr": "0xffc", 46 | "Reqs": [] 47 | } 48 | ], 49 | "Djinn": [ 50 | { 51 | "Addr": "0x40", 52 | "Reqs": [ 53 | [ 54 | "Scoop Gem" 55 | ] 56 | ] 57 | }, 58 | { 59 | "Addr": "0x4a", 60 | "Reqs": [] 61 | } 62 | ], 63 | "Special": [] 64 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/SEAngaraIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xaa4", 10 | "Reqs": [ 11 | [ 12 | "Mind Read", 13 | "Frost Jewel", 14 | "Pretty Stone" 15 | ] 16 | ], 17 | "Restriction": [ 18 | "no-empty", 19 | "no-mimic" 20 | ] 21 | }, 22 | { 23 | "Addr": "0xf5b", 24 | "Reqs": [] 25 | } 26 | ], 27 | "Djinn": [], 28 | "Special": [] 29 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/SWAttekaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [ 14 | { 15 | "Addr": "0xfc3", 16 | "Reqs": [] 17 | } 18 | ], 19 | "Djinn": [ 20 | { 21 | "Addr": "0x72", 22 | "Reqs": [ 23 | [ 24 | "Lifting Gem" 25 | ] 26 | ] 27 | } 28 | ], 29 | "Special": [] 30 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/SeaGodShrine.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [], 3 | "Treasure": [ 4 | { 5 | "Addr": "0x8c7", 6 | "Reqs": [ 7 | [ 8 | "Lash Pebble", 9 | "Frost Jewel", 10 | "Reveal", 11 | "Sea God's Tear" 12 | ], 13 | [ 14 | "Skips_BasicRG", 15 | "Frost Jewel", 16 | "Reveal", 17 | "Sea God's Tear" 18 | ], 19 | [ 20 | "Skips_OOBRG", 21 | "Reveal", 22 | "Sea God's Tear" 23 | ] 24 | ] 25 | }, 26 | { 27 | "Addr": "0xf59", 28 | "Reqs": [ 29 | [ 30 | "Lash Pebble", 31 | "Frost Jewel" 32 | ], 33 | [ 34 | "Skips_OOBRG", 35 | "Lash Pebble" 36 | ], 37 | [ 38 | "Skips_BasicRG", 39 | "Frost Jewel" 40 | ] 41 | ] 42 | } 43 | ], 44 | "Djinn": [ 45 | { 46 | "Addr": "0x73", 47 | "Reqs": [ 48 | [ 49 | "Lash Pebble" 50 | ], 51 | [ 52 | "Skips_BasicRG" 53 | ] 54 | ] 55 | } 56 | ], 57 | "Special": [] 58 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/SeaOfTime.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [], 8 | "Djinn": [], 9 | "Special": [ 10 | { 11 | "Name": "Boss_Poseidon", 12 | "Type": "Boss", 13 | "Reqs": [ 14 | [ 15 | "AnyDjinn_24", 16 | "Trident" 17 | ] 18 | ] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/SeaOfTimeIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xf5c", 10 | "Reqs": [] 11 | } 12 | ], 13 | "Djinn": [], 14 | "Special": [] 15 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/ShamanVillageCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship", 5 | "Grindstone" 6 | ], 7 | [ 8 | "Ship", 9 | "ShipWings", 10 | "Hover Jade" 11 | ] 12 | ], 13 | "Treasure": [], 14 | "Djinn": [ 15 | { 16 | "Addr": "0x53", 17 | "Reqs": [ 18 | [ 19 | "Whirlwind", 20 | "Frost Jewel", 21 | "Lifting Gem" 22 | ] 23 | ] 24 | } 25 | ], 26 | "Special": [] 27 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/TaopoSwamp.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ], 6 | [ 7 | "Skips_SanctumWarp" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf63", 13 | "Reqs": [ 14 | [ 15 | "Whirlwind", 16 | "Scoop Gem" 17 | ] 18 | ] 19 | }, 20 | { 21 | "Addr": "0xf64", 22 | "Reqs": [ 23 | [ 24 | "Whirlwind", 25 | "Scoop Gem" 26 | ] 27 | ] 28 | }, 29 | { 30 | "Addr": "0xf65", 31 | "Reqs": [ 32 | [ 33 | "Whirlwind", 34 | "Growth", 35 | "Douse Drop", 36 | "Frost Jewel" 37 | ] 38 | ] 39 | }, 40 | { 41 | "Addr": "0xf66", 42 | "Reqs": [ 43 | [ 44 | "Whirlwind", 45 | "Growth", 46 | "Douse Drop", 47 | "Frost Jewel", 48 | "Tremor Bit", 49 | "Scoop Gem" 50 | ] 51 | ] 52 | }, 53 | { 54 | "Addr": "0xf98", 55 | "Reqs": [] 56 | }, 57 | { 58 | "Addr": "0xf99", 59 | "Reqs": [ 60 | [ 61 | "Whirlwind", 62 | "Cyclone Chip" 63 | ] 64 | ] 65 | } 66 | ], 67 | "Djinn": [ 68 | { 69 | "Addr": "0x3b", 70 | "Reqs": [ 71 | [ 72 | "Whirlwind" 73 | ] 74 | ] 75 | } 76 | ], 77 | "Special": [] 78 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/WIndraIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ] 6 | ], 7 | "Treasure": [ 8 | { 9 | "Addr": "0xaa1", 10 | "Reqs": [ 11 | [ 12 | "Mind Read", 13 | "Milk" 14 | ] 15 | ], 16 | "Restriction": [ 17 | "no-empty", 18 | "no-mimic" 19 | ] 20 | }, 21 | { 22 | "Addr": "0xf5a", 23 | "Reqs": [] 24 | } 25 | ], 26 | "Djinn": [], 27 | "Special": [] 28 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/Yallam.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "Ship" 5 | ], 6 | [ 7 | "Skips_SanctumWarp" 8 | ] 9 | ], 10 | "Treasure": [ 11 | { 12 | "Addr": "0xf60", 13 | "Reqs": [ 14 | [ 15 | "Cyclone Chip" 16 | ] 17 | ] 18 | }, 19 | { 20 | "Addr": "0xf61", 21 | "Reqs": [] 22 | }, 23 | { 24 | "Addr": "0xf62", 25 | "Reqs": [ 26 | [ 27 | "Cyclone Chip" 28 | ] 29 | ] 30 | }, 31 | { 32 | "Addr": "0xf95", 33 | "Reqs": [ 34 | [ 35 | "Orb of Force", 36 | "Cyclone Chip" 37 | ], 38 | [ 39 | "Skips_SaveQuitRG" 40 | ] 41 | ] 42 | }, 43 | { 44 | "Addr": "0xf96", 45 | "Reqs": [] 46 | }, 47 | { 48 | "Addr": "0xf97", 49 | "Reqs": [] 50 | } 51 | ], 52 | "Djinn": [], 53 | "Special": [] 54 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations/YampiDesertCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "Access": [ 3 | [ 4 | "YampiBackside", 5 | "Sand" 6 | ], 7 | [ 8 | "YampiBackside", 9 | "Skips_BasicRG" 10 | ] 11 | ], 12 | "Treasure": [ 13 | { 14 | "Addr": "0x18", 15 | "Reqs": [ 16 | [ 17 | "Boss_Valukar" 18 | ] 19 | ] 20 | }, 21 | { 22 | "Addr": "0xf8a", 23 | "Reqs": [] 24 | }, 25 | { 26 | "Addr": "0xf8b", 27 | "Reqs": [ 28 | [ 29 | "Teleport Lapis", 30 | "Sand", 31 | "Burst Brooch", 32 | "Scoop Gem" 33 | ] 34 | ] 35 | }, 36 | { 37 | "Addr": "0xf8c", 38 | "Reqs": [ 39 | [ 40 | "Teleport Lapis", 41 | "Sand", 42 | "Burst Brooch" 43 | ] 44 | ] 45 | }, 46 | { 47 | "Addr": "0xf8d", 48 | "Reqs": [ 49 | [ 50 | "Teleport Lapis", 51 | "Sand", 52 | "Burst Brooch" 53 | ] 54 | ] 55 | } 56 | ], 57 | "Djinn": [ 58 | { 59 | "Addr": "0x41", 60 | "Reqs": [ 61 | [ 62 | "Teleport Lapis", 63 | "Sand", 64 | "Burst Brooch", 65 | "Scoop Gem" 66 | ] 67 | ] 68 | } 69 | ], 70 | "Special": [ 71 | { 72 | "Name": "Boss_Valukar", 73 | "Type": "Boss", 74 | "Reqs": [ 75 | [ 76 | "AnyDjinn_64", 77 | "Teleport Lapis", 78 | "Sand", 79 | "Burst Brooch", 80 | "Pound Cube" 81 | ] 82 | ] 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/AlhafranCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "100:1", "100:2", "100:3", "100:4", "100:5", 5 | "101:6;dead-end", "101:7", "101:8;dead-end", "101:9;dead-end", "101:10" 6 | ], 7 | 8 | "treasure": [ 9 | "0xF25", "0xF26", "0xF27", "0xF8E", "0xF8F", "0xF90", "0xF91" 10 | ], 11 | 12 | "djinn": [], 13 | "flags": [] 14 | }, 15 | 16 | "edges": { 17 | "external": [ 18 | ["100:1", "95:12", "Alhafra", true, "", []], 19 | ["101:8", "95:8", "Alhafra", true, "", []] 20 | ], 21 | 22 | "internal": [ 23 | ["100:1", "100:2", true, false, "", []], 24 | ["100:3", "100:4", true, false, "", []], 25 | ["100:3", "100:5", true, false, "", [ ["alhafra_briggsEscaped"] ]], 26 | ["100:3", "0xF8F", false, false, "", [ ["alhafra_briggsEscaped", "Frost Jewel"] ]], 27 | ["100:3", "0xF90", false, false, "", [ ["alhafra_briggsEscaped", "Frost Jewel"] ]], 28 | ["100:3", "0xF91", false, false, "", [ ["alhafra_briggsEscaped", "Frost Jewel"] ]], 29 | ["100:2", "100:3", true, true, "", []], 30 | ["100:4", "101:6", true, true, "", []], 31 | ["100:5", "101:7", true, true, "", []], 32 | 33 | ["101:6", "0xF25", false, false, "", [ ["Pound Cube", "Lash Pebble"] ]], 34 | ["101:6", "0xF26", false, false, "", [ ["Pound Cube", "Lash Pebble"] ]], 35 | ["101:6", "0xF27", false, false, "", [ ["Pound Cube", "Lash Pebble"] ]], 36 | ["101:7", "101:10", true, false, "", []], 37 | ["101:9", "0xF8E", false, false, "", []], 38 | ["101:9", "101:10", false, true, "", []], 39 | ["101:10", "101:9", false, true, "", [ ["alhafra_briggsEscaped"] ]] 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/AngaraCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["278:1", "278:2", "278:3", "278:4", "278:5", "278:6", "278:7", "278:8", "278:9;dead-end"], 4 | "treasure": ["0x15"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["278:1", "2:89", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["278:1", "278:2", true, false, "", []], 16 | ["278:2", "278:3", true, true, "", []], 17 | ["278:3", "278:4", true, false, "", []], 18 | ["278:4", "278:5", true, true, "", []], 19 | ["278:5", "278:6", true, false, "", []], 20 | ["278:6", "278:7", true, true, "", []], 21 | ["278:7", "278:8", true, false, "", []], 22 | ["278:8", "278:9", true, true, "", []], 23 | ["278:9", "0x15", false, false, "", [ ["Carry Stone"] ]] 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/AttekaCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["277:5;dead-end"], 4 | "treasure": ["0x17"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["277:5", "2:88", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["277:5", "0x17", false, false, "", [ ["Parch"] ]] 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/AttekaInlet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "234:1", "234:2", "234:3;dead-end", "234:4", 5 | "235:1", "235:2", "235:3", "235:5", "235:6", 6 | "237:21;dead-end" 7 | ], 8 | "treasure": ["0xFC4"], 9 | "djinn": ["0x3F"], 10 | "flags": [] 11 | }, 12 | 13 | "edges": { 14 | "external": [ 15 | ["234:1", "2:52", "Overworld", true, "ship", []], 16 | ["234:4", "40:1", "LemurianShip", true, "", []], 17 | ["235:2", "2:53", "Overworld", true, "", []] 18 | ], 19 | 20 | "internal": [ 21 | ["234:1", "234:2", true, false, "", []], 22 | ["234:1", "234:4", true, false, "", []], 23 | ["234:3", "0xFC4", false, false, "", []], 24 | ["234:2", "235:1", true, true, "", []], 25 | ["234:3", "235:5", true, true, "", []], 26 | 27 | ["235:1", "235:2", true, false, "", []], 28 | ["235:1", "235:3", true, false, "", []], 29 | ["235:1", "235:5", true, false, "", []], 30 | ["235:1", "235:6", true, false, "", []], 31 | ["235:1", "0x3F", false, false, "", [ ["Cyclone Chip", "Lifting Gem"] ]], 32 | ["235:3", "237:21", true, true, "", []] 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Daila.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "11:1;dead-end", "11:2;dead-end", "11:3;dead-end", "11:4;dead-end", "11:5;dead-end", "11:6;dead-end", 5 | "12:1;dead-end", 6 | "13:1", "13:2", "13:3", "13:4", "13:5", "13:6", "13:7", "13:8", "13:9" 7 | ], 8 | 9 | "treasure": [ 10 | "0xA20;no-empty;no-mimic", "0xF01", "0xF02", "0xF03", "0xF04", "0xF05", "0xF5E" 11 | ], 12 | 13 | "djinn": [], 14 | "flags": [] 15 | }, 16 | 17 | "edges": { 18 | "external": [ 19 | ["13:8", "2:2", "Overworld", true, "", []], 20 | ["13:9", "2:3", "Overworld", true, "", []] 21 | ], 22 | 23 | "internal": [ 24 | ["13:1", "13:2", true, false, "", []], 25 | ["13:1", "13:3", true, false, "", []], 26 | ["13:1", "13:4", true, false, "", []], 27 | ["13:1", "13:5", true, false, "", []], 28 | ["13:1", "13:6", true, false, "", []], 29 | ["13:1", "13:7", true, false, "", []], 30 | ["13:1", "13:8", true, false, "", []], 31 | ["13:1", "13:9", true, false, "", []], 32 | ["13:1", "0xF01", false, false, "", []], 33 | ["13:1", "0xF02", false, false, "", []], 34 | ["13:1", "0xF5E", false, false, "", [ ["Scoop Gem"] ]], 35 | ["13:1", "11:1", true, true, "", []], 36 | ["13:2", "11:2", true, true, "", []], 37 | ["13:3", "11:3", true, true, "", []], 38 | ["13:4", "11:4", true, true, "", []], 39 | ["13:5", "11:5", true, true, "", []], 40 | ["13:6", "11:6", true, true, "", []], 41 | ["13:7", "12:1", true, true, "", []], 42 | 43 | ["11:3", "0xF04", false, false, "", []], 44 | ["11:4", "0xF05", false, false, "", []], 45 | ["11:5", "0xF03", false, false, "", []], 46 | ["12:1", "0xA20", false, false, "", [ ["Frost Jewel"] ]] 47 | ] 48 | } 49 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/ETundariaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["57:5;dead-end", "132:1", "132:2"], 4 | "treasure": ["0xAA2;no-empty;no-mimic", "0xF92"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["132:1", "2:29", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["132:1", "132:2", true, false, "", []], 16 | ["132:1", "0xAA2", false, false, "", []], 17 | ["132:2", "57:5", true, true, "", []], 18 | ["57:5", "0xF92", false, false, "", []] 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/GabombaCatacombs.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "126:1", "126:2", "126:43", "126:44", "126:45", 5 | "127:1;dead-end", "127:2", "127:3", "127:4", "127:5", 6 | "128:1", "128:2", 7 | "129:1;dead-end", 8 | "130:1", "130:2" 9 | ], 10 | 11 | "treasure": ["0xF53", "0xF93"], 12 | "djinn": ["0x3A"], 13 | "flags": [] 14 | }, 15 | 16 | "edges": { 17 | "external": [ 18 | ["126:1", "124:2", "GabombaStatue", true, "ladder", []] 19 | ], 20 | 21 | "internal": [ 22 | ["126:1", "126:43", true, false, "", []], 23 | ["126:1", "126:44", true, false, "", []], 24 | ["126:1", "126:45", true, false, "", []], 25 | ["126:2", "126:1", false, false, "", []], 26 | ["126:2", "127:1", true, true, "", []], 27 | ["126:43", "127:3", false, true, "cyclone;one-way", [ ["Cyclone Chip"] ]], 28 | ["126:44", "127:4", false, true, "cyclone;one-way", [ ["Cyclone Chip"] ]], 29 | ["126:45", "127:5", false, true, "cyclone;one-way", [ ["Cyclone Chip"] ]], 30 | 31 | ["127:1", "127:5", true, false, "", []], 32 | ["127:2", "127:1", false, false, "", []], 33 | ["127:2", "127:3", true, false, "", []], 34 | ["127:4", "127:1", false, false, "", []], 35 | ["127:4", "0x3A", false, false, "", []], 36 | ["127:2", "128:1", true, true, "", []], 37 | 38 | ["128:1", "128:2", false, false, "", [ ["Cyclone Chip", "Frost Jewel"] ]], 39 | ["128:1", "0xF53", false, false, "", [ ["Cyclone Chip"] ]], 40 | ["128:2", "128:1", false, false, "", []], 41 | ["128:2", "130:1", false, true, "", [ ["Reveal"] ]], 42 | 43 | ["129:1", "0xF93", false, false, "", []], 44 | ["129:1", "130:2", true, true, "", []], 45 | 46 | ["130:1", "130:2", false, false, "", [ ["Cyclone Chip", "Frost Jewel"] ]], 47 | ["130:2", "130:1", false, false, "", []], 48 | ["130:1", "128:2", false, true, "", []] 49 | ] 50 | } 51 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/GondowanCliffs.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["102:1", "102:2", "102:3", "103:1", "103:2", "104:1;dead-end"], 4 | "treasure": ["0xF40", "0xF41", "0xF43"], 5 | "djinn": ["0x61"], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["102:1", "2:21", "Overworld", true, "", []], 12 | ["102:2", "2:22", "Overworld", true, "", []], 13 | ["103:1", "2:85", "Overworld", true, "ship", []], 14 | ["103:2", "2:86", "Overworld", true, "ship", []] 15 | ], 16 | 17 | "internal": [ 18 | ["102:1", "102:2", true, false, "", [ ["boss_briggs"] ]], 19 | ["102:1", "0x61", false, false, "", [ ["boss_briggs"] ]], 20 | ["102:1", "0xF40", false, false, "", [ ["boss_briggs", "Frost Jewel"] ]], 21 | ["102:1", "0xF41", false, false, "", [ ["boss_briggs"] ]], 22 | ["102:1", "0xF43", false, false, "", [ ["boss_briggs"] ]], 23 | ["102:2", "0x61", false, false, "", [ ["Frost Jewel"], ["Scoop Gem"] ]], 24 | ["102:2", "0xF40", false, false, "", [ ["Frost Jewel"] ]], 25 | ["102:2", "0xF41", false, false, "", [ ["Frost Jewel"], ["Scoop Gem"] ]], 26 | ["102:2", "0xF43", false, false, "", [ ["Frost Jewel"], ["Scoop Gem"] ]], 27 | ["102:2", "102:3", true, false, "", []], 28 | ["102:3", "104:1", false, true, "", [ ["Whirlwind"] ]], 29 | 30 | ["103:1", "103:2", true, false, "", [ ["Grindstone"] ]], 31 | 32 | ["104:1", "102:3", false, true, "", []] 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/GondowanSettlement.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["213:1", "213:2", "213:3", "214:11;dead-end", "215:1;dead-end"], 4 | "treasure": ["0xFC0", "0xFC1"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["213:1", "2:48", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["213:1", "213:2", true, false, "", []], 16 | ["213:1", "213:3", true, false, "", []], 17 | ["213:1", "0xFC1", false, false, "", []], 18 | ["213:2", "214:11", true, true, "", []], 19 | ["213:3", "215:1", false, true, "ladder", [ ["Cyclone Chip"] ]], 20 | 21 | ["215:1", "0xFC0", false, false, "", []], 22 | ["215:1", "213:3", false, true, "ladder", []] 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/HesperiaSettlement.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "216:1", "216:2", "216:3;dead-end", "216:4", 5 | "217:11", "217:12", "217:13", "217:14", 6 | "218:2;dead-end" 7 | ], 8 | 9 | "treasure": ["0xFC2"], 10 | "djinn": ["0x66"], 11 | "flags": [] 12 | }, 13 | 14 | "edges": { 15 | "external": [ 16 | ["216:1", "2:49", "Overworld", true, "", []] 17 | ], 18 | 19 | "internal": [ 20 | ["216:1", "216:2", true, false, "", []], 21 | ["216:1", "216:4", false, false, "", [ ["Growth"] ]], 22 | ["216:1", "0x66", false, false, "", [ ["Growth"] ]], 23 | ["216:4", "216:1", false, false, "", []], 24 | ["216:2", "217:11", true, true, "", []], 25 | ["216:3", "217:14", true, true, "ladder", []], 26 | ["216:4", "218:2", true, true, "", []], 27 | 28 | ["217:11", "217:12", true, false, "", []], 29 | ["217:13", "217:14", true, false, "", []], 30 | ["217:12", "217:13", true, true, "", []], 31 | 32 | ["218:2", "0xFC2", false, false, "", []] 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Idejima.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["9:4"], 4 | "treasure": ["0x1;no-summon", "0x2;no-summon", "0x3;no-summon", "0x4;no-summon"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["9:4", "2:1", "Overworld", false, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["9:4", "0x1", false, false, "", []], 16 | ["9:4", "0x2", false, false, "", []], 17 | ["9:4", "0x3", false, false, "", []], 18 | ["9:4", "0x4", false, false, "", []] 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/IndraCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["275:1;dead-end"], 4 | "treasure": ["0x10"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["275:1", "2:83", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["275:1", "0x10", false, false, "", [ ["Lash Pebble"] ]] 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/IsletCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "136:1", "136:2", "136:3", "136:4", "136:5", "136:6", "136:7;dead-end", "136:8", "136:9", "136:10", 5 | "137:1", "137:2", "137:3", "137:4", "137:5", "137:6", "137:7", "137:8", "137:9", "137:10", 6 | "138:1;dead-end" 7 | ], 8 | 9 | "treasure": ["0x1A", "0xFA8", "0xFA9"], 10 | "djinn": ["0x3C", "0x55"], 11 | "flags": ["boss_sentinel"] 12 | }, 13 | 14 | "edges": { 15 | "external": [ 16 | ["136:1", "135:5", "SeaOfTimeIslet", true, "", []] 17 | ], 18 | 19 | "internal": [ 20 | ["136:1", "136:2", true, false, "", []], 21 | ["136:3", "136:4", true, false, "", []], 22 | ["136:3", "136:9", true, false, "", []], 23 | ["136:3", "0xFA8", false, false, "", []], 24 | ["136:5", "136:6", true, false, "", []], 25 | ["136:3", "0x3C", false, false, "", []], 26 | ["136:7", "0xFA9", false, false, "", []], 27 | ["136:8", "136:10", true, false, "", []], 28 | ["136:2", "136:3", true, true, "", []], 29 | ["136:4", "136:5", true, true, "", []], 30 | ["136:6", "136:7", true, true, "", []], 31 | ["136:8", "137:1", true, true, "", []], 32 | ["136:9", "136:10", true, true, "teleport", [ ["Teleport Lapis"] ]], 33 | 34 | ["137:1", "137:2", true, false, "", []], 35 | ["137:3", "137:4", true, false, "", []], 36 | ["137:3", "0x55", false, false, "", [ ["Tremor Bit"] ]], 37 | ["137:5", "137:6", true, false, "", []], 38 | ["137:7", "137:8", true, false, "", []], 39 | ["137:9", "137:10", true, false, "", []], 40 | ["137:2", "137:3", true, true, "", []], 41 | ["137:4", "137:5", true, true, "", []], 42 | ["137:6", "137:7", true, true, "", []], 43 | ["137:8", "137:9", true, true, "", []], 44 | ["137:10", "138:1", true, true, "", []], 45 | 46 | ["138:1", "boss_sentinel", false, false, "", [ ["djinn:64"] ]], 47 | ["138:1", "0x1A", false, false, "", [ ["boss_sentinel"] ]] 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/KaltIsland.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["219:1", "219:2", "220:1;dead-end"], 4 | "treasure": [], 5 | "djinn": ["0x52"], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["219:1", "2:50", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["219:1", "219:2", true, false, "", []], 16 | ["219:1", "0x52", false, false, "", [ ["Lash Pebble"] ]], 17 | ["219:2", "220:1", true, true, "", []] 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/KibomboMountains.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "107:1", "107:2", "107:3", "107:4", "107:5", "107:6", "107:7", 5 | "108:1", "108:2", "108:3", "108:4", "109:1;dead-end", "109:2", "109:3" 6 | ], 7 | "treasure": ["0xF49", "0xF4A", "0xF4B", "0xF4C"], 8 | "djinn": ["0x76"], 9 | "flags": [] 10 | }, 11 | 12 | "edges": { 13 | "external": [ 14 | ["107:1", "2:26", "Overworld", true, "", []], 15 | ["108:1", "2:25", "Overworld", true, "", []] 16 | ], 17 | 18 | "internal": [ 19 | ["107:1", "107:2", true, false, "", [ ["gabomba_cleared"] ]], 20 | ["107:1", "107:4", true, false, "", [ ["Frost Jewel"] ]], 21 | ["107:1", "107:7", true, false, "", []], 22 | ["107:2", "107:3", true, false, "", []], 23 | ["107:2", "107:5", true, false, "", []], 24 | ["107:2", "107:6", true, false, "", []], 25 | ["107:2", "108:2", true, true, "", []], 26 | ["107:3", "108:3", true, true, "", []], 27 | ["107:4", "108:4", true, true, "", []], 28 | ["107:5", "109:1", true, true, "", []], 29 | ["107:6", "109:2", true, true, "", []], 30 | ["107:7", "109:3", false, true, "", [ ["Whirlwind"] ]], 31 | ["107:2", "0xF49", false, false, "", []], 32 | ["107:2", "0xF4A", false, false, "", []], 33 | ["107:4", "0x76", false, false, "", [ ["Growth"] ]], 34 | 35 | ["108:1", "108:2", true, false, "", [ ["gabomba_cleared"] ]], 36 | ["108:1", "108:3", false, false, "", [ ["Lash Pebble"] ]], 37 | ["108:1", "108:4", false, false, "", [ ["Frost Jewel"] ]], 38 | ["108:3", "108:1", false, false, "", []], 39 | ["108:4", "108:1", false, false, "", []], 40 | ["108:1", "0xF4B", false, false, "", []], 41 | 42 | ["109:2", "109:3", true, false, "", []], 43 | ["109:3", "107:7", false, true, "", []], 44 | ["109:1", "0xF4C", false, false, "", []] 45 | ] 46 | } 47 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Loho.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "266:1", "266:2", "266:3", "266:4", "266:5", "266:6;dead-end", "266:7", 5 | "267:1;dead-end", "267:2;dead-end", "267:3", "267:4", "267:5;dead-end", "267:6", "267:7", "267:8;dead-end", "267:9", "267:10" 6 | ], 7 | "treasure": ["0xFF5", "0xFF6", "0xFF7", "0xFF8"], 8 | "djinn": ["0x7C"], 9 | "flags": ["cannon"] 10 | }, 11 | 12 | "edges": { 13 | "external": [ 14 | ["266:7", "2:59", "Overworld", true, "", []] 15 | ], 16 | 17 | "internal": [ 18 | ["266:1", "266:7", true, false, "", []], 19 | ["266:2", "266:7", true, false, "", []], 20 | ["266:3", "266:7", true, false, "", []], 21 | ["266:4", "266:7", true, false, "", []], 22 | ["266:5", "266:7", true, false, "", []], 23 | ["266:1", "267:1", true, true, "", []], 24 | ["266:2", "267:2", true, true, "", []], 25 | ["266:3", "267:3", true, true, "", []], 26 | ["266:4", "267:4", true, true, "", []], 27 | ["266:5", "267:5", true, true, "", []], 28 | ["266:6", "267:6", true, true, "", []], 29 | ["266:7", "cannon", false, false, "", [ ["Magma Ball"] ]], 30 | ["266:7", "0xFF5", false, false, "", [ ["cannon", "Scoop Gem"] ]], 31 | ["266:7", "0xFF6", false, false, "", [ ["cannon", "Scoop Gem"] ]], 32 | ["266:7", "0xFF7", false, false, "", [ ["cannon", "Scoop Gem", "Lifting Gem"] ]], 33 | ["266:7", "0xFF8", false, false, "", []], 34 | ["266:7", "0x7C", false, false, "", [ ["cannon"] ]], 35 | 36 | ["267:3", "267:7", true, false, "", []], 37 | ["267:4", "267:9", true, false, "", []], 38 | ["267:6", "267:10", true, false, "", []], 39 | ["267:7", "267:8", true, true, "", []], 40 | ["267:9", "267:10", true, true, "", []] 41 | ] 42 | } 43 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/MadraDrawbridge.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["53:1", "53:2"], 4 | "treasure": [], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["53:1", "2:10", "Overworld", true, "", []], 12 | ["53:2", "2:11", "Overworld", true, "", []] 13 | ], 14 | 15 | "internal": [ 16 | ["53:1", "53:2", true, false, "", []] 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Mikasalla.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "55:1", "55:2", "55:3", "55:4", "55:5", "55:6", "55:7", "55:8", "55:9;dead-end", "55:10;dead-end", "55:11", "55:12", 5 | "56:1", "56:2", "56:3", "56:4", "57:1;dead-end", "57:2;dead-end", "57:3;dead-end", "57:4;dead-end", "58:1;dead-end" 6 | ], 7 | "treasure": ["0xF28", "0xF29", "0xF2A", "0xF2B", "0xF2C"], 8 | "djinn": ["0x60"], 9 | "flags": [] 10 | }, 11 | 12 | "edges": { 13 | "external": [ 14 | ["55:6", "2:14", "Overworld", true, "", []] 15 | ], 16 | 17 | "internal": [ 18 | ["55:1", "55:6", true, false, "", []], 19 | ["55:2", "55:6", true, false, "", []], 20 | ["55:3", "55:6", true, false, "", []], 21 | ["55:4", "55:6", true, false, "", []], 22 | ["55:5", "55:6", true, false, "", []], 23 | ["55:6", "55:8", true, false, "", []], 24 | ["55:6", "55:12", true, false, "", []], 25 | ["55:7", "55:11", true, false, "", []], 26 | ["55:1", "57:1", true, true, "", []], 27 | ["55:2", "57:2", true, true, "", []], 28 | ["55:3", "57:3", true, true, "", []], 29 | ["55:4", "57:4", true, true, "", []], 30 | ["55:5", "58:1", true, true, "", []], 31 | ["55:7", "55:9", true, true, "", []], 32 | ["55:8", "55:10", true, true, "", []], 33 | ["55:11", "56:4", true, true, "", []], 34 | ["55:12", "56:1", false, true, "", [ ["Scoop Gem"] ]], 35 | ["55:6", "0xF29", false, false, "", []], 36 | ["55:6", "0xF2A", false, false, "", []], 37 | ["55:9", "0x60", false, false, "", []], 38 | ["55:10", "0xF28", false, false, "", []], 39 | 40 | ["56:1", "56:2", true, false, "", []], 41 | ["56:3", "56:4", true, false, "", []], 42 | ["56:1", "55:12", false, true, "", []], 43 | ["56:2", "56:3", true, true, "", []], 44 | 45 | ["57:1", "0xF2B", false, false, "", []], 46 | ["57:3", "0xF2C", false, false, "", []] 47 | ] 48 | } 49 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/NOseniaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["11:7;dead-end", "133:1", "133:2", "133:3", "133:4"], 4 | "treasure": ["0xAA3", "0xF12"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["133:1", "2:30", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["133:1", "133:2", true, false, "", []], 16 | ["133:1", "133:3", true, false, "", []], 17 | ["133:1", "133:4", true, false, "", [ ["Sand"] ]], 18 | ["133:2", "133:4", true, true, "", []], 19 | ["133:3", "11:7", true, true, "", []], 20 | ["133:4", "0xAA3", false, false, "", [ ["Mind Read", "Red Cloth"] ]], 21 | ["11:7", "0xF12", false, false, "", []] 22 | ] 23 | } 24 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Naribwe.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "105:1", "105:2;dead-end", "105:3", "105:4", "105:5", "105:6", "105:7", 5 | "106:1", "106:2", "106:3;dead-end", "106:4;dead-end", "106:5;dead-end", "106:6", "106:7" 6 | ], 7 | "treasure": ["0xF44", "0xF45", "0xF46", "0xF47", "0xF48"], 8 | "djinn": [], 9 | "flags": [] 10 | }, 11 | 12 | "edges": { 13 | "external": [ 14 | ["105:6", "2:23", "Overworld", true, "", []], 15 | ["105:7", "2:24", "Overworld", true, "", []] 16 | ], 17 | 18 | "internal": [ 19 | ["105:1", "105:6", true, false, "", []], 20 | ["105:3", "105:6", true, false, "", []], 21 | ["105:4", "105:6", true, false, "", []], 22 | ["105:5", "105:6", true, false, "", []], 23 | ["105:6", "105:7", true, false, "", []], 24 | ["105:1", "106:1", true, true, "", []], 25 | ["105:2", "106:2", true, true, "", []], 26 | ["105:3", "106:3", true, true, "", []], 27 | ["105:4", "106:4", true, true, "", []], 28 | ["105:5", "106:5", true, true, "", []], 29 | ["105:2", "0xF45", false, false, "", [ ["Whirlwind", "Reveal"] ]], 30 | ["105:6", "0xF44", false, false, "", [ ["Lash Pebble"] ]], 31 | ["105:6", "0xF46", false, false, "", []], 32 | 33 | ["106:1", "106:6", true, false, "", []], 34 | ["106:2", "106:7", true, false, "", []], 35 | ["106:6", "106:7", true, true, "", []], 36 | ["106:1", "0xF47", false, false, "", []], 37 | ["106:4", "0xF48", false, false, "", []] 38 | ] 39 | } 40 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/NorthernReaches.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["268:1", "268:2"], 4 | "treasure": [], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["268:1", "2:60", "Overworld", true, "ship", []], 12 | ["268:2", "2:61", "Overworld", true, "ship", [ ["cannon"] ]] 13 | ], 14 | 15 | "internal": [ 16 | ["268:1", "268:2", true, false, "", []] 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/OseniaCavern.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["276:1", "276:2;dead-end", "276:3", "276:4", "276:5"], 4 | "treasure": ["0x11"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["276:1", "2:82", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["276:1", "276:3", true, false, "", []], 16 | ["276:4", "276:5", true, false, "", []], 17 | ["276:1", "276:3", true, false, "", []], 18 | ["276:2", "276:4", false, true, "", [ ["Scoop Gem"] ]], 19 | ["276:3", "276:5", false, true, "", [ ["Scoop Gem"] ]], 20 | ["276:4", "276:2", false, true, "", []], 21 | ["276:5", "276:3", false, true, "", []], 22 | ["276:2", "0x11", false, false, "", []] 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/OseniaCliffs.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["54:1", "54:2"], 4 | "treasure": ["0xF17"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["54:1", "2:12", "Overworld", true, "", []], 12 | ["54:2", "2:13", "Overworld", true, "", []] 13 | ], 14 | 15 | "internal": [ 16 | ["54:1", "54:2", true, false, "", []], 17 | ["54:1", "0xF17", false, false, "", [ ["Lash Pebble"] ]] 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/SEAngaraIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["134:10", "134:11", "183:8;dead-end"], 4 | "treasure": ["0xAA4", "0xF5B"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["134:10", "2:31", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["134:10", "134:11", true, false, "", []], 16 | ["134:11", "183:8", true, true, "", []], 17 | 18 | ["134:10", "0xAA4", false, false, "", [ ["Frost Jewel", "Mind Read", "Pretty Stone"] ]], 19 | ["134:10", "0xF5B", false, false, "", []] 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/SWAttekaIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["221:1", "221:2", "222:11;dead-end"], 4 | "treasure": ["0xFC3"], 5 | "djinn": ["0x72"], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["221:1", "2:47", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["221:1", "221:2", true, false, "", []], 16 | ["221:2", "222:11", true, true, "", []], 17 | ["221:1", "0xFC3", false, false, "", []], 18 | ["221:1", "0x72", false, false, "", [ ["Lifting Gem"] ]] 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/SeaOfTime.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["197:1", "197:2", "198:1", "198:2", "198:3", "198:5", "198:6"], 4 | "treasure": [], 5 | "djinn": [], 6 | "flags": ["boss_poseidon"] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["197:1", "2:42", "Overworld", true, "ship", []], 12 | ["198:3", "2:44", "Overworld", true, "ship", []], 13 | ["198:5", "2:43", "Overworld", true, "ship", []] 14 | ], 15 | 16 | "internal": [ 17 | ["197:1", "197:2", true, false, "", []], 18 | ["197:2", "198:1", true, true, "", []], 19 | 20 | ["198:1", "198:2", true, false, "", [ ["boss_poseidon"] ]], 21 | ["198:2", "198:3", true, false, "", []], 22 | ["198:5", "198:6", true, false, "", [ ["Grindstone"] ]], 23 | ["198:2", "198:6", true, true, "", []], 24 | ["198:1", "boss_poseidon", false, false, "", [ ["Trident", "djinn:24"] ]], 25 | ["198:2", "boss_poseidon", false, false, "", [ ["Trident", "djinn:24"] ]] 26 | ] 27 | } 28 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/SeaOfTimeIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["135:1", "135:2", "135:3", "135:4", "135:5", "156:6;dead-end"], 4 | "treasure": ["0xF5C"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["135:1", "2:32", "Overworld", true, "", []], 12 | ["135:5", "136:1", "IsletCave", true, "", []] 13 | ], 14 | 15 | "internal": [ 16 | ["135:1", "135:2", true, false, "", []], 17 | ["135:1", "135:3", true, false, "", []], 18 | ["135:4", "135:5", true, false, "", []], 19 | ["135:2", "156:6", true, true, "", []], 20 | ["135:3", "135:4", false, true, "", [ ["Mind Read", "Li'l Turtle"] ]], 21 | ["135:4", "135:3", false, true, "", [ ["Mind Read"] ]], 22 | ["135:1", "0xF5C", false, false, "", []] 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/ShamanVillageCave.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["240:1", "240:2;dead-end", "240:3", "240:4", "240:5", "240:6", "240:7", "240:8", "240:9;dead-end", "240:10;dead-end"], 4 | "treasure": [], 5 | "djinn": ["0x53"], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["240:1", "2:56", "Overworld", true, "", []], 12 | ["240:10", "2:57", "Overworld", true, "", []] 13 | ], 14 | 15 | "internal": [ 16 | ["240:1", "240:2", false, false, "", [ ["Whirlwind"] ]], 17 | ["240:1", "240:3", true, false, "", []], 18 | ["240:1", "240:4", true, false, "", []], 19 | ["240:5", "240:7", true, false, "", []], 20 | ["240:6", "240:5", false, false, "", [ ["Whirlwind"], ["Lifting Gem", "Frost Jewel"] ]], 21 | ["240:8", "240:9", false, false, "", []], 22 | ["240:8", "240:10", false, false, "", []], 23 | ["240:2", "240:5", true, true, "", []], 24 | ["240:3", "240:6", true, true, "", []], 25 | ["240:4", "240:9", true, true, "", []], 26 | ["240:7", "240:8", true, true, "", []], 27 | ["240:6", "0x53", false, false, "", [ ["Whirlwind", "Frost Jewel", "Lifting Gem"] ]] 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/WIndraIslet.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": ["131:1", "131:2", "183:9;dead-end"], 4 | "treasure": ["0xAA1", "0xF5A"], 5 | "djinn": [], 6 | "flags": [] 7 | }, 8 | 9 | "edges": { 10 | "external": [ 11 | ["131:1", "2:28", "Overworld", true, "", []] 12 | ], 13 | 14 | "internal": [ 15 | ["131:1", "131:2", true, false, "", []], 16 | ["131:2", "183:9", true, true, "", []], 17 | ["131:1", "0xAA1", false, false, "", [ ["Mind Read", "Milk"] ]], 18 | ["131:1", "0xF5A", false, false, "", []] 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /randomiser/game_logic/locations_detailed/Yallam.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "entrances": [ 4 | "139:1", "139:2", "139:3", "139:4", "139:5", "139:6", "139:7", "139:8", "139:9;dead-end", "139:10", "139:11", "139:12", "139:13;dead-end", "139:15;dead-end", 5 | "140:6", "140:7", 6 | "141:1;dead-end", "141:2;dead-end", "141:3;dead-end", "141:4;dead-end", 7 | "142:1;dead-end", "142:2;dead-end", "142:3;dead-end", 8 | "58:4;dead-end" 9 | ], 10 | "treasure": ["0xF60", "0xF61", "0xF62", "0xF95", "0xF96", "0xF97"], 11 | "djinn": [], 12 | "flags": [] 13 | }, 14 | 15 | "edges": { 16 | "external": [ 17 | ["139:10", "2:34", "Overworld", true, "", []], 18 | ["139:11", "2:33", "Overworld", true, "", []] 19 | ], 20 | 21 | "internal": [ 22 | ["139:1", "139:10", true, false, "", []], 23 | ["139:2", "139:10", true, false, "", []], 24 | ["139:3", "139:10", true, false, "", []], 25 | ["139:4", "139:10", true, false, "", []], 26 | ["139:5", "139:10", true, false, "", []], 27 | ["139:6", "139:10", true, false, "", []], 28 | ["139:7", "139:10", true, false, "", []], 29 | ["139:8", "139:10", true, false, "", []], 30 | ["139:10", "139:11", true, false, "", []], 31 | ["139:10", "139:12", true, false, "", []], 32 | ["139:10", "139:13", false, false, "", [ ["Orb of Force"] ]], 33 | ["139:1", "141:1", true, true, "", []], 34 | ["139:2", "141:2", true, true, "", []], 35 | ["139:3", "142:1", true, true, "", []], 36 | ["139:4", "141:4", true, true, "", []], 37 | ["139:5", "142:3", true, true, "", []], 38 | ["139:6", "142:2", true, true, "", []], 39 | ["139:7", "141:3", true, true, "", []], 40 | ["139:8", "58:4", true, true, "", []], 41 | ["139:9", "140:6", true, true, "", []], 42 | ["139:12", "139:15", true, true, "", []], 43 | ["139:13", "140:7", false, true, "", [ ["Cyclone Chip"] ]], 44 | ["139:9", "0xF95", false, false, "", []], 45 | ["139:10", "0xF60", false, false, "", [ ["Cyclone Chip"] ]], 46 | ["139:10", "0xF61", false, false, "", []], 47 | ["139:10", "0xF62", false, false, "", [ ["Cyclone Chip"] ]], 48 | 49 | ["140:6", "140:7", true, false, "", []], 50 | ["140:7", "139:13", false, true, "", []], 51 | 52 | ["141:3", "0xF96", false, false, "", []], 53 | ["141:4", "0xF97", false, false, "", []] 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /randomiser/game_logic/randomisers/archipelago_filler.js: -------------------------------------------------------------------------------- 1 | const { BaseRandomiser } = require('./base_randomiser.js'); 2 | 3 | class ArchipelagoFiller extends BaseRandomiser { 4 | constructor(prng, instLocations, settings) { 5 | super(prng, instLocations, settings); 6 | this.isMultiworld = false; 7 | } 8 | 9 | placeItems(itemMapping, instItemLocations) { 10 | this.itemLocations = instItemLocations; 11 | 12 | Object.keys(this.itemLocations).forEach((slot) => { 13 | let mapping = itemMapping[slot] ?? this.itemLocations[slot][0]['vanillaContents']; 14 | 15 | if (mapping >= 0xA01 && mapping <= 0xA09) { 16 | mapping -= 0xA01; 17 | this.itemLocations[slot].forEach((t) => { 18 | t['eventType'] = 0x81; 19 | t['contents'] = mapping; 20 | }); 21 | } else { 22 | if (mapping == 0xA00 || mapping == 0xA0A) { 23 | this.isMultiworld = true; 24 | } 25 | 26 | this.itemLocations[slot].forEach((t) => { 27 | t['contents'] = mapping; 28 | if (t['eventType'] == 0x81) t['eventType'] = 0x80; 29 | }); 30 | } 31 | }); 32 | } 33 | 34 | placeDjinn(djinnMapping, djinnClone) { 35 | djinnClone.forEach((djinni) => { 36 | let slotId = 0x30 + djinni.vanillaElement * 20 + djinni.vanillaId; 37 | let mappedDjinni = djinnMapping['0x' + slotId.toString('16')]; 38 | if (mappedDjinni) { 39 | djinni.element = Math.floor((mappedDjinni - 0x30) / 20); 40 | djinni.id = (mappedDjinni - 0x30) % 20; 41 | } 42 | }); 43 | } 44 | 45 | sortMimics() {} 46 | } 47 | 48 | module.exports = {ArchipelagoFiller}; -------------------------------------------------------------------------------- /randomiser/icons/archipelago_icons.js: -------------------------------------------------------------------------------- 1 | const fillerItemIcon = [0x0, 0x0, 0x80, 0x8, 0x0, 0xE4, 0xEF, 0xDF, 0x6A, 0x80, 0xD0, 0x6D, 0xAA, 0xD, 0xE4, 0x9F, 0xAD, 0x58, 0xF5, 0x75, 0x2D, 0xD9, 2 | 0xF6, 0xD6, 0x99, 0x5B, 0x5F, 0x3D, 0x66, 0x3C, 0x9E, 0xD7, 0x8C, 0xC7, 0xF3, 0x70, 0x2B, 0x85, 0x6E, 0x29, 0xD4, 0xBF, 0x57, 0x8D, 0x74, 0x57, 0x93, 3 | 0x6E, 0x7F, 0xD5, 0xA4, 0xFD, 0x53, 0x6B, 0xC6, 0xAA, 0xAF, 0x2B, 0xCE, 0x1D, 0x39, 0x7B, 0xE7, 0xAF, 0x1E, 0xF7, 0x40, 0xDC, 0x39, 0x37, 0x16, 0xA0, 4 | 0x5A, 0xA, 0x0, 0x22, 0x0, 0x0, 0xC0, 0xFF]; 5 | 6 | const usefulItemIcon = [0x0, 0x0, 0x80, 0x7F, 0x4, 0x0, 0x32, 0x53, 0xD, 0xF0, 0x8F, 0x9A, 0xA1, 0xDB, 0x40, 0xFD, 0xF7, 0xD4, 0x62, 0xFB, 0xAD, 0x63, 7 | 0x6F, 0x79, 0x1E, 0xD7, 0xF, 0xDF, 0xEB, 0x1D, 0x3C, 0xE5, 0xE, 0x77, 0xEC, 0x48, 0xA1, 0x5B, 0xA, 0xF5, 0xF3, 0x5B, 0x8D, 0xFC, 0xF3, 0x4F, 0x35, 8 | 0xD9, 0xE5, 0x3E, 0xF3, 0x3C, 0xEC, 0x63, 0xA, 0xFB, 0xF3, 0xD5, 0x61, 0x8E, 0xB7, 0xCC, 0x1D, 0xFF, 0x3E, 0xF6, 0x81, 0xC7, 0x73, 0xB8, 0xB5, 0x0, 9 | 0xD5, 0x52, 0x0, 0x10, 0x1, 0x0, 0x0, 0xFE, 0xFF]; 10 | 11 | const progressionItemIcon = [0x80, 0xFF, 0x4, 0x0, 0xF2, 0x8F, 0x14, 0x40, 0xA8, 0xDD, 0x6A, 0x6, 0x32, 0x3A, 0x43, 0xBD, 0x66, 0xC9, 0xE6, 0xA9, 0xC3, 12 | 0xF6, 0x5B, 0x7B, 0xB9, 0x2C, 0x75, 0xB6, 0x8F, 0x5A, 0x3B, 0xC8, 0x63, 0x16, 0xD9, 0x27, 0xDB, 0x52, 0x58, 0xBA, 0x46, 0xEA, 0xFB, 0xA9, 0x66, 0xBD, 13 | 0x51, 0x97, 0xB9, 0xA3, 0xFE, 0x39, 0xF, 0x71, 0x66, 0xB1, 0x63, 0x21, 0x9E, 0xBB, 0x73, 0x77, 0x1, 0x72, 0xEE, 0xEC, 0xBB, 0x1C, 0xE1, 0x38, 0x76, 14 | 0xCD, 0x92, 0x5, 0xEC, 0xEA, 0x21, 0x3, 0x30, 0xA, 0xCA, 0xFF]; 15 | 16 | module.exports = { fillerItemIcon, usefulItemIcon, progressionItemIcon }; -------------------------------------------------------------------------------- /randomiser/patches/innate/endgame_shortcuts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch changes some Move pillar flags in the optional endgame dungeons 3 | * to make them persist between area changes. Why are they like that in the first place? 4 | */ 5 | 6 | const { writeArray } = require('../../../util/binary.js'); 7 | 8 | /** 9 | * Applies this patch to the map code 10 | * @param {MapCodeData} mapCode The rom instance 11 | */ 12 | function apply(mapCode) { 13 | // Treasure Isle 14 | mapCode[1711][0] = true; 15 | 16 | // Water room move pillar (0x308 -> 0xC00) 17 | writeArray(mapCode[1711][1], 0x7DC, [0xC0, 0x20, 0x0, 0x1]); 18 | writeArray(mapCode[1711][1], 0xDB2, [0xC0, 0x20, 0x0, 0x1]); 19 | writeArray(mapCode[1711][1], 0x1822, [0x0, 0xC]); 20 | 21 | // Basement move pillar (0x30D -> 0xC01) 22 | writeArray(mapCode[1711][1], 0x844, [0x0, 0x1, 0x1]); 23 | writeArray(mapCode[1711][1], 0xECE, [0x0, 0x1, 0x1]); 24 | writeArray(mapCode[1711][1], 0x19DE, [0x1, 0xC]); 25 | 26 | 27 | // Yampi Desert Cave 28 | mapCode[1634][0] = true; 29 | 30 | // Entrance burst pillar (0x300 -> 0xC10) 31 | writeArray(mapCode[1634][1], 0xE18, [0xC1, 0x20, 0x0, 0x1]); 32 | writeArray(mapCode[1634][1], 0xE32, [0xC1, 0x20, 0x0, 0x1]); 33 | writeArray(mapCode[1634][1], 0x1476, [0xC1, 0x20, 0x0, 0x1]); 34 | writeArray(mapCode[1634][1], 0x1D9A, [0x10, 0xC]); 35 | 36 | // Shortcut burst pillar (0x301 -> 0xC11) 37 | writeArray(mapCode[1634][1], 0xE40, [0xC1, 0x20, 0x0, 0x1]); 38 | writeArray(mapCode[1634][1], 0xE5C, [0xC1, 0x20, 0x0, 0x1]); 39 | writeArray(mapCode[1634][1], 0x1684, [0xC1, 0x20, 0x0, 0x1]); 40 | writeArray(mapCode[1634][1], 0x1F3E, [0x11, 0xC]); 41 | 42 | // Final pre-boss move pillar (0x304 -> 0xC20) 43 | writeArray(mapCode[1634][1], 0x1010, [0xC2, 0x20, 0x0, 0x1]); 44 | writeArray(mapCode[1634][1], 0x169C, [0xC2, 0x20, 0x0, 0x1]); 45 | writeArray(mapCode[1634][1], 0x1F62, [0x20, 0xC]); 46 | writeArray(mapCode[1634][1], 0x1F6E, [0x20, 0xC]); 47 | 48 | // Djinni room move pillar (0x305 -> 0xC03) 49 | writeArray(mapCode[1634][1], 0xFCC, [0x0, 0x1, 0x3]); 50 | writeArray(mapCode[1634][1], 0x16EC, [0x0, 0x1, 0x3]); 51 | writeArray(mapCode[1634][1], 0x1F4A, [0x3, 0xC]); 52 | writeArray(mapCode[1634][1], 0x1F56, [0x3, 0xC]); 53 | } 54 | 55 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/innate/fast_forging.js: -------------------------------------------------------------------------------- 1 | const textutil = require('../../game_logic/textutil.js'); 2 | 3 | /** 4 | * Applies this patch to the map code 5 | * @param {MapCodeData} mapCode The map code data instance 6 | * @param {string[]} text The text data instance 7 | */ 8 | function apply(mapCode, text) { 9 | mapCode[1655][0] = true; 10 | 11 | // Make Sunshine always return to bed 12 | mapCode[1655][1][0x654] = 0x65; 13 | mapCode[1655][1][0x655] = 0xE0; 14 | 15 | // Change text lines 16 | textutil.writeLine(text, 0x1305, "Consider it done.\x03Just talk to my wife.\x02"); 17 | textutil.writeLine(text, 0x1306, "Consider it done.\x03Just talk to my wife.\x02"); 18 | textutil.writeLine(text, 0x1308, "You ain't got anything\x03for me to work with!\x02"); 19 | textutil.writeLine(text, 0x1311, "It's \x16 coins for\x03this \x14\x01.\x03Do you want it?\x1E"); 20 | } 21 | 22 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/innate/fix_char.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Applies this patch to the map code 3 | * @param {MapCodeData} mapCode The map code data instance 4 | * @param {object[]} djinn The djinni data instance 5 | */ 6 | function apply(mapCode, djinn) { 7 | mapCode[1625][0] = true; 8 | 9 | mapCode[1625][1][0x23D8] = 0xF3 + djinn[46].element; 10 | } 11 | 12 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/innate/fix_lemurian_ship.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch removes the event where Piers blocks the party from boarding the Lemurian Ship. 3 | * This should only be applied on the "Door Open" ship logic setting, and is meant to 4 | * resolve any lingering issues with that setting because it refuses to play nice otherwise. 5 | * @param {MapCodeData} mapCode The map code data instance 6 | */ 7 | function applyEntranceFix(mapCode) { 8 | mapCode[1623][0] = true; 9 | mapCode[1623][1][0x1DA2] = 0xE0; 10 | mapCode[1623][1][0x1DA3] = 0xBD; 11 | } 12 | 13 | /** 14 | * This patch fixes the disappearing item sprite in the Aqua Hydra room. 15 | * @param {MapCodeData} mapCode The map code data instance 16 | */ 17 | function applyChestFix(mapCode) { 18 | mapCode[1622][0] = true; 19 | mapCode[1622][1][0x130C] = 0x1; 20 | mapCode[1622][1][0x130D] = 0xE0; 21 | mapCode[1622][1][0x288B] = 0xE0; 22 | } 23 | 24 | module.exports = {applyEntranceFix, applyChestFix}; -------------------------------------------------------------------------------- /randomiser/patches/innate/gabomba_puzzle.js: -------------------------------------------------------------------------------- 1 | const textutil = require('../../game_logic/textutil.js'); 2 | const { writeArray } = require('../../../util/binary.js'); 3 | 4 | /** 5 | * Applies this patch to the map code 6 | * @param {MapCodeData} mapCode The map code data instance 7 | * @param {string[]} text The text data instance 8 | */ 9 | function apply(mapCode, text) { 10 | mapCode[1649][0] = true; 11 | 12 | // ASM for unsetting the puzzle timer and adding a custom handler 13 | writeArray(mapCode[1649][1], 0x3388, [0x0, 0xBD]); 14 | writeArray(mapCode[1649][1], 0x377E, [0x0, 0x1C, 0x17, 0x20, 0x15, 0x21, 0x98, 0x22, 0x9, 0x5, 0x12, 0x4, 0x1, 0xF0, 0xC3, 0xFF]); 15 | writeArray(mapCode[1649][1], 0x382A, [0xE, 0xE0]); 16 | writeArray(mapCode[1649][1], 0x525E, [0x0, 0xBD, 0x0, 0xB5, 0xA0, 0x20, 0x40, 0x0, 0x0, 0xF0, 0x75, 0xFA, 0x17, 0x20, 0x0, 0x21, 17 | 0x0, 0xF0, 0x75, 0xFA, 0x4, 0x20, 0x1, 0x21, 0x0, 0xF0, 0x25, 0xFA, 0x0, 0x28, 0x1, 0xD1, 0xFB, 0xF7, 0x9F, 0xFE]); 18 | 19 | // Overwriting the timer trigger with a talk event for Kraden and setting a text line 20 | writeArray(mapCode[1649][1], 0x6DF4, [0x0, 0x0, 0x0, 0x0, 0x17, 0x0, 0xFD, 0x8, 0x61, 0xD2, 0x0, 0x2]); 21 | textutil.writeLine(text, 0x140, "Are you finished?\x1E"); 22 | } 23 | 24 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/innate/register_back_entrances.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch allows certain world map locations to be registered from either entrance. 3 | * Normally areas such as Dehkan, Yampi, etc. would only be registered from the front entrance, 4 | * which causes user friction when trying to Teleport back to these places and them not being unlocked. 5 | */ 6 | 7 | const { writeArray } = require('../../../util/binary.js'); 8 | 9 | /** 10 | * Applies this patch to the map code 11 | * @param {Uint8Array} rom The rom instance 12 | */ 13 | function apply(rom) { 14 | // Fix the Dehkan Plateau back exit 15 | rom[0xF1190] = 0x6; 16 | writeArray(rom, 0xF119C, [0x24, 0x0, 0xFF, 0xFF]); 17 | 18 | // Fix the Yampi Desert exits 19 | rom[0xF123C] = 0x4B; 20 | rom[0xF1690] = 0x13; 21 | rom[0xF169C] = 0x4A; 22 | } 23 | 24 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/innate/trial_road.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch changes inventory snapshotting in Trial Road 3 | * to prevent duplication issues and potential item loss. 4 | */ 5 | 6 | const { write16b } = require('./../../../util/binary'); 7 | 8 | function apply(rom) { 9 | // Disables inventory snapshotting 10 | write16b(rom, 0xB10A4, 0xE08C); 11 | 12 | // Stop the chest flags in Trial Road from being reset 13 | write16b(rom, 0xB11D0, 0xE009); 14 | 15 | // Disables restoration of inventory snapshot 16 | write16b(rom, 0xB125A, 0x0); 17 | write16b(rom, 0xB1264, 0x0); 18 | } 19 | 20 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/mini_patches.js: -------------------------------------------------------------------------------- 1 | const { writeArray } = require("../../util/binary"); 2 | 3 | /** 4 | * Applies Game Ticket removal patch to the ROM 5 | * @param {Uint8Array} target 6 | */ 7 | function applyGameTicketPatch(target) { 8 | target[0xAFED4] = 0x70; 9 | target[0xAFED5] = 0x47; 10 | } 11 | 12 | /** 13 | * Applies ship overworld speed patch to the ROM 14 | * @param {Uint8Array} target 15 | */ 16 | function applyShipSpeedPatch(target) { 17 | target[0x285A4] = 0xF0; 18 | } 19 | 20 | /** 21 | * Applies revive cost reduction to the ROM 22 | * @param {Uint8Array} target 23 | */ 24 | function applyCheapRevivePatch(target) { 25 | writeArray(target, 0x10A874, [0x50, 0x00, 0xC0, 0x46, 0xC0, 0x46]); 26 | } 27 | 28 | /** 29 | * Applies fixed revive cost to the ROM 30 | * @param {Uint8Array} target 31 | */ 32 | function applyFixedRevivePatch(target) { 33 | writeArray(target, 0x10A874, [0x64, 0x20, 0xC0, 0x46, 0xC0, 0x46]); 34 | } 35 | 36 | /** 37 | * Applies encounter rate halving to the ROM 38 | * @param {Uint8Array} target 39 | */ 40 | function applyHalvedRatePatch(target) { 41 | target[0xCA0B8] = 0x78; 42 | } 43 | 44 | module.exports = {applyGameTicketPatch, applyShipSpeedPatch, applyCheapRevivePatch, applyFixedRevivePatch, applyHalvedRatePatch}; -------------------------------------------------------------------------------- /randomiser/patches/options/anemos_requirements.js: -------------------------------------------------------------------------------- 1 | const textutil = require('../../game_logic/textutil.js'); 2 | const { setTalkObject } = require('../../../util/npcWriter'); 3 | const { writeArray } = require('../../../util/binary'); 4 | 5 | function apply(mapCode, text) { 6 | mapCode[1712][0] = true; 7 | 8 | // Disable unused event table entries for map 303 9 | mapCode[1712][1][0x3DF7] = 0x12; 10 | mapCode[1712][1][0x3E03] = 0x12; 11 | mapCode[1712][1][0x3E0F] = 0x12; 12 | mapCode[1712][1][0x3E1B] = 0x12; 13 | 14 | // Create new NPC table for map 303 15 | setTalkObject(mapCode[1712][1], 0x4454, 0x3DE4, 0x8, 0x1C2, 0xFFFF, 0x200, 0, 0xE4, 0, 1, 0x0200C485); 16 | writeArray(mapCode[1712][1], 0x446C, [0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 17 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]); 18 | writeArray(mapCode[1712][1], 0x864, [0x54, 0xC4]); 19 | 20 | // Create custom interact function for the Djinn sign 21 | writeArray(mapCode[1712][1], 0x4484, [0x20, 0xB5, 0x6, 0x48, 0x0, 0x78, 0x5, 0x21, 0x0, 0xF0, 0xC, 0xF8, 0x4, 0x48, 0x0, 0xF0, 0xD, 0xF8, 0xE, 22 | 0x20, 0x0, 0x21, 0x0, 0xF0, 0xD, 0xF8, 0x20, 0xBD, 0x2, 0x79, 0x0, 0x9, 0x78, 0x15, 0x0, 0x0, 0x0, 0x4C, 0x20, 0x47, 0x21, 0x81, 0x3, 0x8, 23 | 0x0, 0x4C, 0x20, 0x47, 0x81, 0x81, 0xC, 0x8, 0x0, 0x4C, 0x20, 0x47, 0xA1, 0x81, 0xC, 0x8]); 24 | 25 | // Set text line for the Djinn sign 26 | textutil.writeLine(text, 0x1578, "\x16 Djinn are required\x03to open the door.\x02"); 27 | 28 | // Update room init function to open the door automatically when the required number of Djinn is met 29 | writeArray(mapCode[1712][1], 0x1E94, [0xFE, 0xF7, 0x18, 0xFE]); 30 | writeArray(mapCode[1712][1], 0xAC8, [0xE0, 0xB5, 0xFF, 0xF7, 0xB5, 0xFA, 0x30, 0x25, 0x80, 0x26, 0x0, 0x27, 0x28, 0x0, 0x2, 0xF0, 0xEF, 0xFB, 0x3F, 31 | 0x18, 0x1, 0x35, 0xB5, 0x42, 0xF8, 0xD1, 0xB, 0x48, 0x0, 0x78, 0xB8, 0x42, 0x11, 0xDC, 0xA0, 0x20, 0x0, 0x1, 0x87, 0x30, 0x5, 0x0, 0x2, 0xF0, 32 | 0xE5, 0xFB, 0x68, 0x1C, 0x2, 0xF0, 0xE2, 0xFB, 0xA8, 0x1C, 0x2, 0xF0, 0xDF, 0xFB, 0xE8, 0x1C, 0x2, 0xF0, 0xDC, 0xFB, 0x28, 0x1D, 0x2, 0xF0, 0xD9, 33 | 0xFB, 0xE0, 0xBD, 0x2, 0x79, 0x0, 0x9]); 34 | } 35 | 36 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/options/avoid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch changes Avoid to be a toggle and work regardless of party level. 3 | * Ported over from the UPS files of the original GS2 randomiser. 4 | */ 5 | 6 | const { writeArray } = require('../../../util/binary.js'); 7 | 8 | function apply(rom) { 9 | // Alter level checking functions 10 | writeArray(rom, 0xCA054, [0x1, 0x20]); 11 | writeArray(rom, 0xCB558, [0x13, 0x1C]); 12 | 13 | // Change Avoid to a toggle 14 | writeArray(rom, 0xE1266, [0x13, 0x68, 0x53, 0x40]); 15 | 16 | // Jump to custom Avoid text display function 17 | writeArray(rom, 0xE1354, [0x12, 0xF0, 0xD4, 0xFD, 0x0, 0xE0]); 18 | 19 | // Insert Avoid text display function 20 | writeArray(rom, 0xF3F00, [0x60, 0xB5, 0x7, 0x4D, 0x2D, 0x68, 0x7, 0x48, 0x0, 0x2D, 0x5, 0xDC, 0x6, 0x0, 0x96, 0x20, 0x4, 0x21, 0x48, 0xF7, 21 | 0xDD, 0xFE, 0x70, 0x1C, 0x1, 0x21, 0x46, 0xF7, 0x47, 0xFC, 0x60, 0xBD, 0xA4, 0x4, 0x0, 0x2, 0xBE, 0xD, 0x0, 0x0]); 22 | } 23 | 24 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/options/mimic_disguise.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch changes the way Mimics are handled when chest sprites are off. 3 | * Instead of removing them entirely, they are instead disguised as key items. 4 | */ 5 | 6 | const { writeArray, write16b } = require("../../../util/binary"); 7 | const { writeLine } = require("../../game_logic/textutil"); 8 | 9 | const allowedDisguises = [0xA, 0x41, 0xF3, 0xF4, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, 0x1C8, 0x1CB, 0x1CC, 10 | 0xE0C, 0xE18, 0xE21, 0xE4E, 0xE85, 0xE86, 0xE88, 0xE89, 0xE8A, 0xE8B, 0xE8D, 0xE90, 0xE97, 0xE98, 0xE99, 0xE9C, 0xF16]; 11 | 12 | function apply(rom, text, prng, isArchipelago, isCharacterShuffle) { 13 | // Replace text lines for Mimic interactions 14 | writeLine(text, 0xDC5, "\x10 checked on the ground...\x01"); 15 | writeLine(text, 0xE1A, "The item suddenly\x03lunges forward!\x02"); 16 | 17 | // Determine a disguise for each Mimic 18 | let disguiseList = allowedDisguises; 19 | if (isCharacterShuffle && !isArchipelago) { 20 | disguiseList = disguiseList.concat([0xD00, 0xD01, 0xD02, 0xD03, 0xD05, 0xD06, 0xD07]); 21 | } 22 | 23 | let iconList = [0, 0, 0, 0, 0, 0, 0, 0, 0].map(() => { 24 | if (isArchipelago) { 25 | if (prng.random() > 0.33) { 26 | return 0xA0A; 27 | } 28 | } 29 | let i = Math.floor(prng.random() * disguiseList.length); 30 | return disguiseList[i]; 31 | }); 32 | 33 | // Replace Mimic chest icons with ground item icons 34 | rom[0xCECBA] = 0xEA; 35 | 36 | writeArray(rom, 0xCEDF2, [0x48, 0x46, 0x0, 0x99, 0x1, 0x4C, 0x20, 0x47, 0x0, 0x0, 0x81, 0x0, 0x0, 0x9]); 37 | writeArray(rom, 0x1000080, [0x40, 0x30, 0x83, 0x2F, 0x4, 0xD0, 0x81, 0x2F, 0x4, 0xD1, 0x49, 0x0, 0x5, 0x4C, 0x61, 0x5A, 0x0, 0xF0, 0x4, 0xF8, 0x0, 38 | 0x4C, 0x20, 0x47, 0x1, 0xEE, 0xC, 0x8, 0x0, 0x4C, 0x20, 0x47, 0x29, 0x3B, 0xD, 0x8, 0xA8, 0x0, 0x0, 0x9]); 39 | 40 | for (let i = 0; i < iconList.length; ++i) { 41 | write16b(rom, 0x10000A8 + 2 * i, iconList[i]); 42 | } 43 | 44 | // Cancel part of the Mimic interact animation 45 | writeArray(rom, 0xCEFAA, [0x20, 0xBD]); 46 | } 47 | 48 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/options/puzzles.js: -------------------------------------------------------------------------------- 1 | /* 2 | Because the Gabomba Statue puzzle only has 16 permutations, it can be handled by a single byte, 3 | and the patch for that is as easy as doing a `mov r0, ##` then returning out of the function. 4 | (Yes, it's nicely within its own function call too.) 5 | 6 | For Gaia Rock and Trial Road the method is similar, but the name sum can be a 32-bit (maybe 16-bit?) number. 7 | So for that, the value is stored as a literal and fetched with a pc-relative ldr before branching 8 | to bypass the rest of the code block that determines the name sum. 9 | */ 10 | 11 | const { writeArray } = require('../../../util/binary.js'); 12 | 13 | /** 14 | * Fixes all name-based puzzles to a random 16-bit name sum. 15 | * @param {MapCodeData} mapCode 16 | * @param {MersenneTwister} prng 17 | */ 18 | function applyRandom(mapCode, prng) { 19 | let sum = Math.floor(prng.random() * 0xFFFF); 20 | applyGabomba(mapCode, sum); 21 | applyGaiaRock(mapCode, sum); 22 | applyTrialRoad(mapCode, sum); 23 | } 24 | 25 | /** 26 | * Fixes all name-based puzzles to the name "Felix". (sum 0x1F8) 27 | * @param {MapCodeData} mapCode 28 | */ 29 | function applyFixed(mapCode) { 30 | applyGabomba(mapCode, 8); 31 | applyGaiaRock(mapCode, 0x1F8); 32 | applyTrialRoad(mapCode, 0x1F8); 33 | } 34 | 35 | 36 | function applyGabomba(mapCode, sum) { 37 | mapCode[1649][0] = true; 38 | writeArray(mapCode[1649][1], 0x3606, [sum & 0xF, 0x20, 0x0, 0xBD]); 39 | } 40 | 41 | function applyGaiaRock(mapCode, sum) { 42 | mapCode[1665][0] = true; 43 | writeArray(mapCode[1665][1], 0x42AE, [0x1, 0x48, 0xB, 0xE0, 0x0, 0x0, sum & 0xFF, (sum >> 8) & 0xFF, 0x0, 0x0]); 44 | } 45 | 46 | function applyTrialRoad(mapCode, sum) { 47 | mapCode[1687][0] = true; 48 | writeArray(mapCode[1687][1], 0x2492, [0x1, 0x48, 0x7, 0xE0, 0x0, 0x0, sum & 0xFF, (sum >> 8) & 0xFF, 0x0, 0x0]); 49 | } 50 | 51 | module.exports = { applyRandom, applyFixed }; -------------------------------------------------------------------------------- /randomiser/patches/options/retreat_glitch.js: -------------------------------------------------------------------------------- 1 | const textutil = require('../../game_logic/textutil.js'); 2 | const { writeArray } = require('../../../util/binary.js'); 3 | 4 | function apply(rom, text) { 5 | rom[0xCE7C1] = 0x68; 6 | writeArray(rom, 0xCE7C9, [0x60, 0x1, 0x48, 0x0, 0x47, 0x0, 0x0, 0x1, 0xC0, 0xFF, 0x8]); 7 | 8 | writeArray(rom, 0xFFC000, [0x8, 0x48, 0x1, 0x1C, 0x8, 0x88, 0x4, 0x21, 0x8, 0x40, 0x0, 0x28, 0x7, 0xD0, 0xD0, 0x20, 0x0, 0x1, 9 | 0x66, 0x30, 0x1, 0x21, 0x0, 0xF0, 0xB, 0xF8, 0x4, 0x48, 0x0, 0x47, 0x2, 0x48, 0x0, 0x47, 0x0, 0x0, 0x50, 0x11, 0x0, 0x3, 0xDB, 10 | 0xE7, 0xC, 0x8, 0xEF, 0xEA, 0xC, 0x8, 0x0, 0x4C, 0x20, 0x47, 0x41, 0x80, 0x3, 0x8]); 11 | 12 | textutil.writeLine(text, 0xD66, "Retreat glitch activated.\x02"); 13 | } 14 | 15 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/options/teleport_everywhere.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch allows for using Teleport on most locations instead of only towns. 3 | */ 4 | const { writeArray } = require('../../../util/binary.js'); 5 | 6 | function apply(rom) { 7 | // Change function that sets ship position on sanctum warp 8 | writeArray(rom, 0xCA394, [0xA, 0x4C, 0xB, 0x48, 0x7, 0x68, 0x0, 0x23, 0x1, 0x3B, 0x1B, 0xC, 0x20, 0x88, 0xB8, 0x42, 0x3, 0xD0, 0x6, 0x34, 9 | 0x98, 0x42, 0xF9, 0xD1, 0x5, 0xE0, 0x60, 0x88, 0x0, 0x4, 0x8, 0x60, 0xA0, 0x88, 0x0, 0x4, 0x48, 0x60, 0x8, 0xBC, 0x98, 0x46, 0xE0, 10 | 0xBD, 0x6A, 0x40, 0xF, 0x8, 0x12, 0xA0, 0x2, 0x2]); 11 | 12 | // Change world map display function 13 | writeArray(rom, 0xED2D8, [0x0, 0x26]); 14 | 15 | // Change world map location entries to allow teleportation 16 | [0x155, 0x17D, 0x21D, 0x231, 0x26D, 0x295, 0x2D1, 0x2E5, 0x2F9, 0x30D, 0x321, 0x349, 0x371, 0x399, 0x3C1, 0x425, 0x439, 0x44D, 17 | 0x461, 0x475, 0x489, 0x4B1, 0x4C5, 0x53D, 0x551, 0x58D, 0x5A1, 0x5B5, 0x5C9, 0x5DD].forEach((entry) => { 18 | rom[0xF1000 + entry] |= 0x10; 19 | }); 20 | 21 | // Change world map location entries to have a map marker in the first place 22 | [0x4C5, 0x53D, 0x551, 0x5A1, 0x5B5].forEach((entry) => { 23 | rom[0xF1000 + entry] |= 0x1; 24 | }); 25 | 26 | // Fix Shaman Village Cave world map location entries 27 | rom[0xF14D0] = 0xF0; 28 | rom[0xF14D8] = 0x38; 29 | rom[0xF14E4] = 0xF0; 30 | } 31 | 32 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/shortcuts/magma_rock_interior.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch opens the two shortcut pillars at the bottom of Magma Rock Interior. 3 | * This allows for a good part of interior to be checked with just Lift and avoids having 4 | * to backtrack if e.g. the player did an initial runthrough without Whirlwind. 5 | */ 6 | 7 | const { write16b } = require("../../../util/binary"); 8 | 9 | function apply(mapCode, locations) { 10 | // Set the top interior exit to only be usable once the stone has been Bursted in exterior 11 | mapCode[1682][0] = true; 12 | write16b(mapCode[1682][1], 0x603E, 0x18DC); 13 | 14 | // Change the access rules for Magma Rock interior checks 15 | locations[0].find((loc) => loc.Addr == '0xff0').Reqs.forEach((reqSet) => { 16 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 17 | reqSet.push('Burst Brooch'); 18 | }); 19 | locations[0].find((loc) => loc.Addr == '0xff1').Reqs.forEach((reqSet) => { 20 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 21 | reqSet.push('Burst Brooch'); 22 | }); 23 | locations[0].find((loc) => loc.Addr == '0xff2').Reqs.forEach((reqSet) => { 24 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 25 | reqSet.splice(reqSet.indexOf('Whirlwind'), 1); 26 | reqSet.push('Burst Brooch'); 27 | }); 28 | locations[0].find((loc) => loc.Addr == '0xff4').Reqs.forEach((reqSet) => { 29 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 30 | reqSet.push('Burst Brooch'); 31 | }); 32 | locations[0].find((loc) => loc.Addr == '0x9f9').Reqs.forEach((reqSet) => { 33 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 34 | reqSet.splice(reqSet.indexOf('Whirlwind'), 1); 35 | }); 36 | locations[0].find((loc) => loc.Addr == '0x9fa').Reqs.forEach((reqSet) => { 37 | reqSet.splice(reqSet.indexOf('MagmaInterior'), 1); 38 | reqSet.splice(reqSet.indexOf('Whirlwind'), 1); 39 | }); 40 | } 41 | 42 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/patches/shortcuts/upper_mars_lighthouse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This patch changes upper Mars Lighthouse to be openable just by having the Mars Star 3 | * in your possession, skipping the need to fight Flame Dragons. 4 | */ 5 | 6 | const { writeArray, write32b, write16b } = require("../../../util/binary"); 7 | 8 | function apply(mapCode, locations) { 9 | mapCode[1708][0] = true; 10 | 11 | // Add a Mars Star check to the init of upper Mars Lighthouse 12 | write32b(mapCode[1708][1], 0x4, 0x0200BC21); 13 | writeArray(mapCode[1708][1], 0x3C20, [0x0, 0xB5, 0xA3, 0x20, 0x0, 0x1, 0xFF, 0xF7, 0x67, 0xFA, 0x0, 0x28, 0x9, 0xD1, 0xDE, 0x20, 0x0, 0xF0, 0xE, 14 | 0xF8, 0x0, 0x28, 0x4, 0xDA, 0xF7, 0x20, 0x0, 0xF0, 0x9, 0xF8, 0x0, 0x28, 0x3, 0xDB, 0xAB, 0x20, 0x0, 0x1, 0xFF, 0xF7, 0x5B, 0xFA, 0xFC, 0xF7, 15 | 0x8B, 0xFF, 0x0, 0xBD, 0x0, 0x4C, 0x20, 0x47, 0xC9, 0xEE, 0xA, 0x8 ]); 16 | 17 | // Change the flag requirement for the elemental wing doors 18 | for (let i = 0; i < 8; ++i) { 19 | write16b(mapCode[1708][1], 0x37AA + i * 0xC, 0x1AB0); 20 | } 21 | 22 | // Change the access rules for upper Mars Lighthouse checks 23 | const affectedItems = ['0xe03', '0xfff']; 24 | const affectedFlags = ['JupiterWing', 'MercuryWing', 'MarsWing', 'VenusWing']; 25 | 26 | locations[0].filter((loc) => affectedItems.includes(loc.Addr)).forEach((loc) => { 27 | loc.Reqs.forEach((reqSet) => { 28 | if (!reqSet.includes('Boss_FlameDragons')) return; 29 | reqSet.splice(reqSet.indexOf('Boss_FlameDragons'), 1); 30 | }); 31 | }); 32 | locations[2].filter((loc) => affectedFlags.includes(loc.Addr)).forEach((loc) => { 33 | loc.Reqs.forEach((reqSet) => { 34 | if (!reqSet.includes('Boss_FlameDragons')) return; 35 | reqSet.splice(reqSet.indexOf('Boss_FlameDragons'), 1); 36 | }); 37 | }); 38 | } 39 | 40 | module.exports = {apply}; -------------------------------------------------------------------------------- /randomiser/rom/readme.txt: -------------------------------------------------------------------------------- 1 | Step 1: Put the vanilla GS2 rom here and name it gs2.gba 2 | Step 2: ??? 3 | Step 3: Randomised profit -------------------------------------------------------------------------------- /randomiser/ups.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const packer = require("./../modules/packer.js"); 3 | 4 | function applyPatch(rom, patchData) { 5 | var target = rom; 6 | var data = patchData.slice(4, patchData.length - 12); 7 | var sourceLen, targetLen, offset, patchOffset = 0; 8 | [patchOffset, sourceLen] = readOffset(data, patchOffset); 9 | [patchOffset, targetLen] = readOffset(data, patchOffset); 10 | 11 | if (targetLen > sourceLen) { 12 | target = new Uint8Array(targetLen); 13 | target.set(rom); 14 | } 15 | 16 | var byteOffset = 0; 17 | while (patchOffset < data.length) { 18 | [patchOffset, offset] = readOffset(data, patchOffset); 19 | byteOffset += offset; 20 | while (true) { 21 | var byte = data[patchOffset++]; 22 | target[byteOffset++] ^= byte; 23 | if (byte == 0) break; 24 | } 25 | } 26 | 27 | return target; 28 | } 29 | 30 | function createPatch(vanilla, rom) { 31 | return packer.generatePatch(vanilla, rom); 32 | } 33 | 34 | function readOffset(data, patchOffset) { 35 | var offset = 0; 36 | var shift = 1; 37 | while (true) { 38 | var byte = data[patchOffset++]; 39 | offset += (byte & 0x7F) * shift; 40 | if ((byte & 0x80) > 0) break; 41 | 42 | shift = (shift << 7); 43 | offset += shift; 44 | } 45 | return [patchOffset, offset]; 46 | } 47 | 48 | module.exports = {applyPatch, createPatch}; -------------------------------------------------------------------------------- /randomiser/ups/randomiser_general.ups: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/randomiser/ups/randomiser_general.ups -------------------------------------------------------------------------------- /randomiser/ups/teleport.ups: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Karanum/gs2-randomiser2/1c89e9d7159fe3c43619f295b9511111316087f3/randomiser/ups/teleport.ups -------------------------------------------------------------------------------- /util/binary.js: -------------------------------------------------------------------------------- 1 | function write8b(buffer, location, data) { 2 | buffer[location] = (data & 0xFF); 3 | } 4 | 5 | function write16b(buffer, location, data) { 6 | write8b(buffer, location, data); 7 | write8b(buffer, location + 1, data >> 8); 8 | } 9 | 10 | function write32b(buffer, location, data) { 11 | write8b(buffer, location, data); 12 | write8b(buffer, location + 1, data >> 8); 13 | write8b(buffer, location + 2, data >> 16); 14 | write8b(buffer, location + 3, data >> 24); 15 | } 16 | 17 | function writeArray(buffer, location, data) { 18 | for (let i = 0; i < data.length; ++i) { 19 | buffer[location + i] = data[i]; 20 | } 21 | } 22 | 23 | function read16b(buffer, location) { 24 | return buffer[location] + (buffer[location + 1] << 8); 25 | } 26 | 27 | function read32b(buffer, location) { 28 | return (buffer[location] + (buffer[location + 1] << 8) + (buffer[location + 2] << 16) + (buffer[location + 3] << 24)) >>> 0; 29 | } 30 | 31 | module.exports = {write8b, write16b, write32b, writeArray, read16b, read32b}; -------------------------------------------------------------------------------- /util/config.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const defaultValues = { 3 | "use-https": false, 4 | "ssl-key": "", 5 | "ssl-cert": "", 6 | "port": 3000, 7 | "production": false 8 | }; 9 | 10 | var config; 11 | 12 | function get(key) { 13 | if (!(key in config)) 14 | return defaultValues[key]; 15 | return config[key]; 16 | } 17 | 18 | function initialise() { 19 | if (!fs.existsSync("./config.json")) { 20 | fs.writeFileSync("./config.json", JSON.stringify(defaultValues, null, '\t')); 21 | config = JSON.parse(JSON.stringify(defaultValues)); 22 | } else { 23 | config = require("../config.json"); 24 | } 25 | } 26 | 27 | initialise(); 28 | 29 | module.exports = {get}; -------------------------------------------------------------------------------- /util/weightedPicker.js: -------------------------------------------------------------------------------- 1 | function pickIndex(prng, weights, totalWeight = undefined) { 2 | if (totalWeight == undefined) { 3 | totalWeight = 0; 4 | weights.forEach((w) => totalWeight += w); 5 | } 6 | 7 | var pick; 8 | var rand = prng.random() * totalWeight; 9 | for (var i = 0; i < weights.length && rand > 0; ++i) { 10 | pick = i; 11 | rand -= weights[i]; 12 | } 13 | return pick; 14 | } 15 | 16 | module.exports = {pickIndex}; -------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_1.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.1

3 | <%= lang.versions.date_format 4 | .replace("%d", "21") 5 | .replace("%s", lang.versions.num_suffixes[1]) 6 | .replace("%m", lang.versions.months[3]) 7 | .replace("%y", "2021") 8 | %> 9 | 14 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_2.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.2

3 | <%= lang.versions.date_format 4 | .replace("%d", "25") 5 | .replace("%s", lang.versions.num_suffixes[5]) 6 | .replace("%m", lang.versions.months[3]) 7 | .replace("%y", "2021") 8 | %> 9 | 12 |
13 | 14 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_3.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.3

3 | <%= lang.versions.date_format 4 | .replace("%d", "4") 5 | .replace("%s", lang.versions.num_suffixes[4]) 6 | .replace("%m", lang.versions.months[4]) 7 | .replace("%y", "2021") 8 | %> 9 | 14 |
15 | 16 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_4.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.4

3 | <%= lang.versions.date_format 4 | .replace("%d", "8") 5 | .replace("%s", lang.versions.num_suffixes[8]) 6 | .replace("%m", lang.versions.months[4]) 7 | .replace("%y", "2021") 8 | %> 9 | 19 |
20 | 21 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_5.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.5

3 | <%= lang.versions.date_format 4 | .replace("%d", "18") 5 | .replace("%s", lang.versions.num_suffixes[8]) 6 | .replace("%m", lang.versions.months[4]) 7 | .replace("%y", "2021") 8 | %> 9 | 16 |
17 | 18 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_0_6.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.0.6

3 | <%= lang.versions.date_format 4 | .replace("%d", "24") 5 | .replace("%s", lang.versions.num_suffixes[4]) 6 | .replace("%m", lang.versions.months[4]) 7 | .replace("%y", "2021") 8 | %> 9 | 13 |
14 | 15 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_1_0.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.1.0

3 | <%= lang.versions.date_format 4 | .replace("%d", "7") 5 | .replace("%s", lang.versions.num_suffixes[7]) 6 | .replace("%m", lang.versions.months[10]) 7 | .replace("%y", "2021") 8 | %> 9 | 19 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_1_1.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.1.1

3 | <%= lang.versions.date_format 4 | .replace("%d", "13") 5 | .replace("%s", lang.versions.num_suffixes[3]) 6 | .replace("%m", lang.versions.months[10]) 7 | .replace("%y", "2021") 8 | %> 9 | 17 |
18 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_1_2.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.1.2

3 | <%= lang.versions.date_format 4 | .replace("%d", "3") 5 | .replace("%s", lang.versions.num_suffixes[3]) 6 | .replace("%m", lang.versions.months[11]) 7 | .replace("%y", "2021") 8 | %> 9 | 18 |
19 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_1_3.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.1.3

3 | <%= lang.versions.date_format 4 | .replace("%d", "17") 5 | .replace("%s", lang.versions.num_suffixes[7]) 6 | .replace("%m", lang.versions.months[4]) 7 | .replace("%y", "2022") 8 | %> 9 | 18 |
19 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_0.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.0

3 | <%= lang.versions.date_format 4 | .replace("%d", "25") 5 | .replace("%s", lang.versions.num_suffixes[5]) 6 | .replace("%m", lang.versions.months[0]) 7 | .replace("%y", "2023") 8 | %> 9 |
10 | Randomiser changes 11 | 26 |
27 |
28 | Website changes 29 | 36 |
37 | Note: With this update, randomisation times have increased due to map code compression. Generating a seed may take up to 15 seconds depending on settings and server load. 38 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_1.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.1

3 | <%= lang.versions.date_format 4 | .replace("%d", "1") 5 | .replace("%s", lang.versions.num_suffixes[1]) 6 | .replace("%m", lang.versions.months[6]) 7 | .replace("%y", "2023") 8 | %> 9 | 19 |
20 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_10.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.10

3 | <%= lang.versions.date_format 4 | .replace("%d", "4") 5 | .replace("%s", lang.versions.num_suffixes[4]) 6 | .replace("%m", lang.versions.months[0]) 7 | .replace("%y", "2025") 8 | %> 9 |
10 | Randomiser changes: 11 | 21 |
22 | 23 |
24 | Archipelago changes: 25 | 28 |
29 |
30 | 31 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_11.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.11

3 | <%= lang.versions.date_format 4 | .replace("%d", "23") 5 | .replace("%s", lang.versions.num_suffixes[3]) 6 | .replace("%m", lang.versions.months[3]) 7 | .replace("%y", "2025") 8 | %> 9 |
10 | 18 |
19 |
20 | 21 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_2.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.2

3 | <%= lang.versions.date_format 4 | .replace("%d", "15") 5 | .replace("%s", lang.versions.num_suffixes[5]) 6 | .replace("%m", lang.versions.months[6]) 7 | .replace("%y", "2023") 8 | %> 9 | 13 |
14 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_3.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.3

3 | <%= lang.versions.date_format 4 | .replace("%d", "22") 5 | .replace("%s", lang.versions.num_suffixes[2]) 6 | .replace("%m", lang.versions.months[9]) 7 | .replace("%y", "2023") 8 | %> 9 | 22 |
23 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_4.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.4

3 | <%= lang.versions.date_format 4 | .replace("%d", "19") 5 | .replace("%s", lang.versions.num_suffixes[9]) 6 | .replace("%m", lang.versions.months[5]) 7 | .replace("%y", "2024") 8 | %> 9 | 23 |
24 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_5.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.5

3 | <%= lang.versions.date_format 4 | .replace("%d", "25") 5 | .replace("%s", lang.versions.num_suffixes[5]) 6 | .replace("%m", lang.versions.months[5]) 7 | .replace("%y", "2024") 8 | %> 9 | 19 |
20 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_6.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.6

3 | <%= lang.versions.date_format 4 | .replace("%d", "22") 5 | .replace("%s", lang.versions.num_suffixes[2]) 6 | .replace("%m", lang.versions.months[8]) 7 | .replace("%y", "2024") 8 | %> 9 | 26 |
27 | 28 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_7.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.7

3 | <%= lang.versions.date_format 4 | .replace("%d", "26") 5 | .replace("%s", lang.versions.num_suffixes[6]) 6 | .replace("%m", lang.versions.months[9]) 7 | .replace("%y", "2024") 8 | %> 9 | 21 |
22 | 23 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_8.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.8

3 | <%= lang.versions.date_format 4 | .replace("%d", "3") 5 | .replace("%s", lang.versions.num_suffixes[3]) 6 | .replace("%m", lang.versions.months[10]) 7 | .replace("%y", "2024") 8 | %> 9 | 18 |
19 | 20 |
-------------------------------------------------------------------------------- /views/partials/changelogs/v1_2_9.ejs: -------------------------------------------------------------------------------- 1 |
2 |

v1.2.9

3 | <%= lang.versions.date_format 4 | .replace("%d", "24") 5 | .replace("%s", lang.versions.num_suffixes[4]) 6 | .replace("%m", lang.versions.months[10]) 7 | .replace("%y", "2024") 8 | %> 9 | 31 |
32 | 33 |
-------------------------------------------------------------------------------- /views/partials/head_common.ejs: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /views/partials/item_dropdown.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | let margin = locals.margin ?? '3'; 3 | _%> 4 |
5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 |
13 |
-------------------------------------------------------------------------------- /views/partials/modals/delete_preset.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/partials/modals/export_preset.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/partials/modals/import_preset.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/partials/modals/save_preset.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/partials/preset_buttons.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_logic_access.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_dropdown', { id: 'inp-ship', label: lang.settings.logic_ship_mode, selected: '0', data: [ 5 | ['0', lang.options.ship_mode.vanilla], 6 | ['1', lang.options.ship_mode.open], 7 | ['2', lang.options.ship_mode.unlocked] 8 | ] }) %> 9 | <%- include('../setting_dropdown', { id: 'inp-anemos-access', label: lang.settings.anemos_access, selected: '0', data: [ 10 | ['0', lang.options.anemos_access.vanilla], 11 | ['1', lang.options.anemos_access.random], 12 | ['2', lang.options.anemos_access.open] 13 | ] }) %> 14 | <%- include('../setting_switch', { id: 'inp-ship-wings', label: lang.settings.logic_ship_wings }) %> 15 | <%- include('../setting_switch', { id: 'inp-boss-logic', label: lang.settings.logic_bosses, tooltip: 8 }) %> 16 | <%- include('../setting_switch', { id: 'inp-skips-maze', label: lang.settings.skips_gaia_maze, margin: 3 }) %> 17 |
18 | 19 |
20 | <%- include('../setting_switch', { id: 'inp-shortcut-magma-rock', label: "Allow access to Magma Rock interior from the bottom" }) %> 21 | <%- include('../setting_switch', { id: 'inp-shortcut-mars-lighthouse', label: "Unlock upper Mars Lighthouse by having the Mars Star" }) %> 22 | 23 |
24 | <%- include('../setting_switch', { id: 'inp-random-puzzles', label: lang.settings.puzzles_random, tooltip: 16 }) %> 25 | <%- include('../setting_switch', { id: 'inp-fixed-puzzles', label: lang.settings.puzzles_fixed, tooltip: 15 }) %> 26 |
27 | 28 | 29 |
30 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_logic_glitches.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_switch', { id: 'inp-skips-sanctum', label: lang.settings.skips_sanc_warp }) %> 5 | <%- include('../setting_switch', { id: 'inp-skips-basic', label: lang.settings.skips_basic }) %> 6 | <%- include('../setting_switch', { id: 'inp-skips-sq', label: lang.settings.skips_sq }) %> 7 | <%- include('../setting_switch', { id: 'inp-skips-oob', label: lang.settings.skips_oob }) %> 8 |
9 |
10 | <%- include('../setting_switch', { id: 'inp-skips-wiggle', label: lang.settings.skips_wiggle }) %> 11 | <%- include('../setting_switch', { id: 'inp-skips-sand', label: lang.settings.skips_sand }) %> 12 | <%- include('../setting_switch', { id: 'inp-skips-storage', label: lang.settings.skips_death_storage }) %> 13 | <%- include('../setting_switch', { id: 'inp-skips-missable', label: lang.settings.skips_missable, margin: 3 }) %> 14 |
15 | 16 |
17 |
18 | <%- lang.settings.skips_info.replace('%1', '').replace('%2', '') %> 19 |
20 |
21 |
22 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_randomisation_djinn.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_switch', { id: 'inp-djinn-shuffle', label: lang.settings.djinn_shuffle, checked: true }) %> 5 | <%- include('../setting_switch', { id: 'inp-djinn-stats', label: lang.settings.djinn_stats_shuffle }) %> 6 | <%- include('../setting_switch', { id: 'inp-djinn-power', label: lang.settings.djinn_power_adjust }) %> 7 | <%- include('../setting_switch', { id: 'inp-djinn-aoe', label: lang.settings.djinn_range_random }) %> 8 | <%- include('../setting_switch', { id: 'inp-djinn-scale', label: lang.settings.djinn_scaling, checked: true, margin: 3, tooltip: 4 }) %> 9 |
10 | 11 |
12 | <%- include('../setting_switch', { id: 'inp-summon-cost', label: lang.settings.summon_cost_random }) %> 13 | <%- include('../setting_switch', { id: 'inp-summon-power', label: lang.settings.summon_power_adjust }) %> 14 | <%- include('../setting_switch', { id: 'inp-summon-sort', label: lang.settings.summon_sort, checked: true, tooltip: 5 }) %> 15 |
16 |
17 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_randomisation_misc.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_switch', { id: 'inp-music-shuffle', label: lang.settings.music_shuffle }) %> 5 | <%- include('../setting_switch', { id: 'inp-shuffle-characters', label: lang.settings.character_shuffle}) %> 6 | <%- include('../setting_switch', { id: 'inp-remove-mimics', label: lang.settings.remove_mimics, margin: 3 }) %> 7 |
8 |
9 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_randomisation_psy.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_dropdown', { id: 'inp-class-psynergy', label: lang.settings.psy_shuffle, selected: '0', data: [ 5 | ['0', lang.options.psy_shuffle.vanilla], 6 | ['1', lang.options.psy_shuffle.class], 7 | ['2', lang.options.psy_shuffle.group], 8 | ['5', lang.options.psy_shuffle.group_element], 9 | ['3', lang.options.psy_shuffle.element], 10 | ['4', lang.options.psy_shuffle.full] 11 | ] }) %> 12 |
13 | 14 |
15 | <%- include('../setting_dropdown', { id: 'inp-class-levels', label: lang.settings.psy_levels, selected: '0', data: [ 16 | ['0', lang.options.psy_levels.vanilla], 17 | ['1', lang.options.psy_levels.adjust], 18 | ['2', lang.options.psy_levels.random] 19 | ] }) %> 20 |
21 | 22 |
23 | 24 |
25 | <%- include('../setting_switch', { id: 'inp-psynergy-power', label: lang.settings.psy_power_adjust }) %> 26 | <%- include('../setting_switch', { id: 'inp-psynergy-cost', label: lang.settings.psy_cost_adjust }) %> 27 | <%- include('../setting_switch', { id: 'inp-psynergy-aoe', label: lang.settings.psy_range_random, margin: 3 }) %> 28 |
29 | 30 |
31 | <%- include('../setting_switch', { id: 'inp-enemypsy-power', label: lang.settings.enemypsy_power_adjust }) %> 32 | <%- include('../setting_switch', { id: 'inp-enemypsy-aoe', label: lang.settings.enemypsy_range_random }) %> 33 |
34 |
35 |
-------------------------------------------------------------------------------- /views/partials/rando_settings/tab_randomisation_stats.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%- include('../setting_dropdown', { id: 'inp-char-stats', label: lang.settings.character_stats, selected: '0', data: [ 5 | ['0', lang.options.character_stats.vanilla], 6 | ['1', lang.options.character_stats.shuffle], 7 | ['2', lang.options.character_stats.adjust] 8 | ] }) %> 9 |
10 | 11 |
12 | <%- include('../setting_dropdown', { id: 'inp-char-element', label: lang.settings.character_element, selected: '0', data: [ 13 | ['0', lang.options.character_element.vanilla], 14 | ['1', lang.options.character_element.shuffle], 15 | ['2', lang.options.character_element.random] 16 | ] }) %> 17 |
18 | 19 |
20 | <%- include('../setting_dropdown', { id: 'inp-enemy-eres', label: lang.settings.enemy_stats, selected: '0', data: [ 21 | ['0', lang.options.enemy_stats.vanilla], 22 | ['1', lang.options.enemy_stats.shuffle], 23 | ['2', lang.options.enemy_stats.random] 24 | ] }) %> 25 |
26 | 27 |
28 | 29 |
30 | <%- include('../setting_switch', { id: 'inp-class-stats', label: lang.settings.class_stats_random, margin: 3 }) %> 31 |
32 |
33 |
-------------------------------------------------------------------------------- /views/partials/setting_dropdown.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | let margin = locals.margin ?? '3'; 3 | let selected = locals.selected ?? ''; 4 | _%> 5 |
6 | 7 | 12 |
-------------------------------------------------------------------------------- /views/partials/setting_switch.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | let margin = locals.margin ?? '2'; 3 | let checked = (locals.checked ? 'checked' : ''); 4 | _%> 5 |
6 | > 7 | 15 |
-------------------------------------------------------------------------------- /views/partials/spoiler_log.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | 5 | <%= lang.randomised.header_log %> 6 |

7 | 23 |
24 |
-------------------------------------------------------------------------------- /views/partials/tab_button.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | let active = locals.active ?? false; 3 | _%> 4 | --------------------------------------------------------------------------------