From 74a8ec6486b96203b292501044d4350152b0d1ec Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Fri, 12 Feb 2021 23:01:50 +0100 Subject: [PATCH 01/10] Minor fixes for in-room stairs --- DoorShuffle.py | 2 +- Rom.py | 2 +- asm/asm_investigations.txt | 11 +++++++++++ asm/spiral.asm | 37 +++++++++++++++++++++++++------------ data/base2current.bps | Bin 131841 -> 131877 bytes 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index 97e7d234..58d84688 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -89,7 +89,7 @@ def link_doors_main(world, player): world.get_portal('Desert East', player).destination = True if world.mode[player] == 'inverted': world.get_portal('Desert West', player).destination = True - if world.mode[player] == 'open': + else: world.get_portal('Skull 2 West', player).destination = True world.get_portal('Turtle Rock Lazy Eyes', player).destination = True world.get_portal('Turtle Rock Eye Bridge', player).destination = True diff --git a/Rom.py b/Rom.py index 4b97fc4e..4b9680da 100644 --- a/Rom.py +++ b/Rom.py @@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'bffd4e834049ca5f5295601436fc6009' +RANDOMIZERBASEHASH = '3a77558175cf8b2233f87c60329baa5d' class JsonRom(object): diff --git a/asm/asm_investigations.txt b/asm/asm_investigations.txt index feb5e09b..9d0cce24 100644 --- a/asm/asm_investigations.txt +++ b/asm/asm_investigations.txt @@ -200,3 +200,14 @@ $bc - TT 188 idx 1 ; called by 10CE2, (Dungeon_SpiralStaircase_3) ;122f0 + +Link's position after screen transition and auto-walk (from $02C034): + +0C 20 30 38 48 ; down +D4 D8 C0 C0 A8 ; up +0C 18 28 30 40 ; right +E4 D8 C8 C0 B0 ; left + +Effectively indexed by $0418*#$05+$4E. +Row ($0418) is the direction and column ($4E) determines how far to auto-walk (depends on tile attribute at edge of screen). +From left to right: edge, inside high door, outside high door, inside low door and outside low door. diff --git a/asm/spiral.asm b/asm/spiral.asm index 0d13c4e7..2dd2ab8b 100644 --- a/asm/spiral.asm +++ b/asm/spiral.asm @@ -170,10 +170,10 @@ InroomStairsWarp: { ; should be the same as lda $0462 : and #$04 : lsr #2 : eor #$01 : sta $07 lda $01 : and #$80 : beq .notEdge lda $07 : sta $03 : beq + - lda $01 : jsr LoadSouthMidpoint : sta $22 : lda #$e0 + lda $01 : jsr LoadSouthMidpoint : sta $22 : lda #$f4 bra ++ + - lda $01 : jsr LoadNorthMidpoint : sta $22 : lda #$1b + lda $01 : jsr LoadNorthMidpoint : sta $22 : dec $21 : lda #$f7 ++ sta $20 lda $01 : and #$20 : beq + @@ -185,26 +185,36 @@ InroomStairsWarp: { brl .layer .notEdge lda $01 : and #$03 : cmp #$03 : bne .normal + txa : and #$06 : sta $07 lda $01 : and #$30 : lsr #3 : tay - lda.w InroomStairsX,y : sta $22 lda.w InroomStairsX+1,y : sta $02 lda.w InroomStairsY+1,y : sta $03 - lda.w InroomStairsY,y - ldy $07 : beq + - !add #$07 - + - sta $20 + cpy $07 : beq .vanillaTransition + lda.w InroomStairsX,y : sta $22 + lda.w InroomStairsY,y + ldy $07 : beq + + !add #$07 + + + sta $20 + inc $07 + bra ++ + .vanillaTransition + lda #$c0 : sta $07 ; leave camera + ++ %StonewallCheck($1b) - inc $07 lda $01 : and #$04 : lsr #2 bra .layer .normal lda $01 : sta $fe ; trap door lda $07 : sta $03 : beq + + ldy $a0 : cpy #$51 : beq .specialFix ; throne room + cpy #$02 : beq .specialFix ; sewers pull switch + cpy #$71 : beq .specialFix ; castle armory lda #$e0 - ldy $a0 : cpy #$51 : bne ++ ; special fix for throne room - !sub #$18 - bra ++ + bra ++ + .specialFix + lda #$c8 + bra ++ + %StonewallCheck($43) lda #$1b @@ -235,12 +245,15 @@ InroomStairsWarp: { ldy #$01 : jsr ShiftQuadSimple .skipYQuad + lda $07 : bmi .skipCamera ldy #$00 : jsr SetCamera ; horizontal camera ldy #$01 : sty $07 : jsr SetCamera ; vertical camera lda $20 : cmp #$e0 : bcc + lda $e8 : bne + lda #$10 : sta $e8 ; adjust vertical camera at bottom + + .skipCamera + jsr StairCleanup ply : plx : plb ; pull the stuff we pushed rts diff --git a/data/base2current.bps b/data/base2current.bps index 71800df832f4178ed90683aa6572c4bcb9765874..970df14e576c2923e6564beaed7c30e523d35e04 100644 GIT binary patch delta 1418 zcmW-fdrVVz6vyxH_Q^xQf~E4}Y7oB?EN)#)%A9aCY5P^PF=VVkc^;#iz<_-o}N z1xg>saxIDXfxaz%#ik2p`ID{OK-X*NPxq)KOv`Kh`TdcschzvhGJwKqLj_l^~PN< zeX!90^X?4nDa1q{L)^(_xF!uMM2sx5iG>-wj1dVjk^4PXhW0+iuW>wrKV^8w7^)0jo6Y~axrryw=Jhe6UYRh-0ypThxqY27L8RIw zW2hk+7JGw?tUCoyWuq~J%PsvNb^f93*V>!5TsA{R=C-{aDdm+wsbq%23dL zH+}M_jZU7_-uDWzE-Coz2GNy9lPos{R>IZ0C6iWoo+MrR(yG*s>}13TqE(y3UDUTQ z{T?kV@fbudssmQv%R{ALzNgJ2_9*Z-MLe_W7Ua7hZ?Lz=uqP7J71(mfL77{IPHk~z zcG{{=4V~QLeoL&t>^%7UUY1mzHW5Q9(D%QOixnS%loqBy@J%(t3>doKhN|JKp{}J{ z?Hq|k)EWDwu%K#R6K8)B3=0x!f-NEoZPb2?RHNngW7itdNEcw8dzkz}Ol)5!-i8!%n>>jI{R&R&%B`|1rC*eEf-U zQ4=PP@&qLYhU8_DAwpfeM3WRx96jq=l@LBiQrW-|d@P%q1}Vdt>H4zS0bFMXsPBHuBtHPMz&{JKYD zsZpNj;*$#--plc`x+pYNv?FF9z(k>cvt+Z^1PqJ%RDs4^)H(?*WRn-8bTVdnVCG^} zj^gZd#7*|79YMpSj{MYMpnVBiP$6}dE_pDofxYcUZiy&Ngb9}6&~nlI{Gq@v9Lh(c zgpKC{(H^9t^L@pN5mQ(Ayf1FSH7`Mg!{--;BcXF`D0A|-D;!QLlgr6h?rn@s^&si) YKc2O}2g-U;=Y094DOLN>ox`I40G6d!sQ>@~ delta 1366 zcmW-fYfMvT7{~jb(;L@fg|-Tq*8`)V+XOM%vB^-Gr~|xUD0477hcoKXu?jF{CGFJEL`8~h<^W^#P=k#K& zUfi<@#d8%$=x;`?)Q|N_uU8X8Td70!N*aOly&bgKOZ`-*%+uSb={iuO@-0^k%BU(U zbkQNhP!sFr8|syXm9^CJqcGYk@s*G9y?mXS>IWmSfJnGRW}|xd zeXx>XxR&FVVc=vTP<#|bn8lE-UgFO7)q#f->-@XO2iVNKbq zE;vm?>fvqb1oA@bxhI$ew=)bkqmB2J7Ciiu+;*)juUjP&cbWv zWfHV@dw0H8OBr={h`yu|hU`lmafy7S;-rYd17S2XD`Ep_hR!mMg3#6*(lP0B3?3Yl ztL7E7bfBcoSl0G*R#ZrIlrj_yPDMmSHrY5rHPhh>ZWcn9MN5vbudEad>(%H zf=Q;DFJ<`O2P#hTJFy84Pg9}@rakMERjfYRb{GZX=iahnn z&)A~ef1msAB&_h-IUb(1Fa#&^FMjIe1PKyedtdXqu$3zW4g`kB1+zyZVf$QcbZnni zY}DNlaD0CY=K5`Sm>_T(f;9<}=8G80=P2PJET@@CxH=buqTt?~5~ z0%IKg%li=GT^o`Q^cuFtRt&TRXTTQkhY9t-zHyZ874v-Y-7$;hufN&GzDV0wXUx}Y zHO)Fm{i0So247c0yZ4xMvC-&cFBR9_c8!$xC;ISWBSbwpNbHlq*(a$5AEz`iOFYP} zwTgISq;4KQWxDp{HT89b#Tx=;hH#l-oy;&TGuj1otlUZPI(R%qMQMXlQPI$#Y#-40 zl(ux)=xE1MtbaO#O|4@5u+finSX=RW2waF>eJUoLZqBN#l?+^Jl$O^RgjfhE3mGD{ zx=B00VyIczjJ|?f3q>dr5}xiAZ))9Ks%Hf`?y{#ZA_LmaCywsY$MG82vH-M^RKMHe zX%9gE#ED7@Jlgb;!=A20R3CvV*p%HUn%JM|`Di!FMWL|gjN9@-QLi?lO%Sx?>CZqr z@`O!N`S^uOmhV7z0qni{mX>XIpe$nV6VFQrN=D?W Date: Fri, 5 Feb 2021 15:05:16 -0700 Subject: [PATCH 02/10] -Disallowed Swamp Lobby in Hyrule Castle in Standard mode -Prevent defeating Aga 1 before Zelda is delivered to the Sanctuary. (He can't take damage) -Fix for Ice Jelly room when going backward and enemizer is on -Fix for inverted - don't start as a bunny in Dark Sanctuary -Fix for non-ER Inverted with Lobby shuffle. Aga Tower's exit works properly now. --- BaseClasses.py | 1 + DoorShuffle.py | 38 +++++++++++++++++++------------------- Doors.py | 1 + RELEASENOTES.md | 6 ++++++ Rom.py | 11 +++++++++-- RoomData.py | 7 ++++--- asm/dr_lobby.asm | 1 + asm/drhooks.asm | 3 +++ asm/overrides.asm | 7 +++++++ data/base2current.bps | Bin 131877 -> 132335 bytes 10 files changed, 51 insertions(+), 24 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 6be6174b..9ac6377b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1214,6 +1214,7 @@ class Door(object): self.passage = True self.dungeonLink = None self.bk_shuffle_req = False + self.standard_restrict = False # flag if portal is not allowed in HC in standard # self.incognitoPos = -1 # self.sectorLink = False diff --git a/DoorShuffle.py b/DoorShuffle.py index 58d84688..c2085c50 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -357,6 +357,7 @@ def choose_portals(world, player): if world.doorShuffle[player] in ['basic', 'crossed']: cross_flag = world.doorShuffle[player] == 'crossed' bk_shuffle = world.bigkeyshuffle[player] + std_flag = world.mode[player] == 'standard' # roast incognito doors world.get_room(0x60, player).delete(5) world.get_room(0x60, player).change(2, DoorKind.DungeonEntrance) @@ -369,13 +370,14 @@ def choose_portals(world, player): region_map = defaultdict(list) reachable_portals = [] inaccessible_portals = [] + hc_flag = std_flag and dungeon == 'Hyrule Castle' for portal in portal_list: placeholder = world.get_region(portal + ' Portal', player) portal_region = placeholder.exits[0].connected_region name = portal_region.name if portal_region.type == RegionType.LightWorld: world.get_portal(portal, player).light_world = True - if name in world.inaccessible_regions[player]: + if name in world.inaccessible_regions[player] or (hc_flag and portal != 'Hyrule Castle South'): name_key = 'Desert Ledge' if name == 'Desert Palace Entrance (North) Spot' else name region_map[name_key].append(portal) inaccessible_portals.append(portal) @@ -397,7 +399,8 @@ def choose_portals(world, player): portal_assignment = defaultdict(list) for dungeon, info in info_map.items(): outstanding_portals = list(dungeon_portals[dungeon]) - if dungeon == 'Hyrule Castle' and world.mode[player] == 'standard': + hc_flag = std_flag and dungeon == 'Hyrule Castle' + if hc_flag: sanc = world.get_portal('Sanctuary', player) sanc.destination = True clean_up_portal_assignment(portal_assignment, dungeon, sanc, master_door_list, outstanding_portals) @@ -425,7 +428,7 @@ def choose_portals(world, player): the_rest = info.total - len(portal_assignment[dungeon]) for i in range(0, the_rest): candidates = find_portal_candidates(master_door_list, dungeon, crossed=cross_flag, - bk_shuffle=bk_shuffle) + bk_shuffle=bk_shuffle, standard=hc_flag) choice, portal = assign_portal(candidates, outstanding_portals, world, player) clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals) @@ -536,23 +539,20 @@ def disconnect_portal(portal, world, player): chosen_door.entranceFlag = False -def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allowed=False, crossed=False, bk_shuffle=False): - filter_list = [x for x in door_list if bk_shuffle or not x.bk_shuffle_req] - if need_passage: - if crossed: - return [x for x in filter_list if x.passage and (x.dungeonLink is None or x.entrance.parent_region.dungeon.name == dungeon)] - else: - return [x for x in filter_list if x.passage and x.entrance.parent_region.dungeon.name == dungeon] - elif dead_end_allowed: - if crossed: - return [x for x in filter_list if x.dungeonLink is None or x.entrance.parent_region.dungeon.name == dungeon] - else: - return [x for x in filter_list if x.entrance.parent_region.dungeon.name == dungeon] +def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allowed=False, crossed=False, + bk_shuffle=False, standard=False): + ret = [x for x in door_list if bk_shuffle or not x.bk_shuffle_req] + if crossed: + ret = [x for x in ret if not x.dungeonLink or x.entrance.parent_region.dungeon.name == dungeon] else: - if crossed: - return [x for x in filter_list if (not x.dungeonLink or x.entrance.parent_region.dungeon.name == dungeon) and not x.deadEnd] - else: - return [x for x in filter_list if x.entrance.parent_region.dungeon.name == dungeon and not x.deadEnd] + ret = [x for x in ret if x.entrance.parent_region.dungeon.name == dungeon] + if need_passage: + ret = [x for x in ret if x.passage] + if not dead_end_allowed: + ret = [x for x in ret if not x.deadEnd] + if standard: + ret = [x for x in ret if not x.standard_restrict] + return ret def assign_portal(candidates, possible_portals, world, player): diff --git a/Doors.py b/Doors.py index 3bc41766..c3cc969d 100644 --- a/Doors.py +++ b/Doors.py @@ -1306,6 +1306,7 @@ def create_doors(world, player): world.get_door("GT Bob\'s Room SE", player).passage = False world.get_door('PoD Mimics 2 SW', player).bk_shuffle_req = True world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note (todo) + world.get_door('Swamp Lobby S', player).standard_restricted = True # key-drop note (todo) # can't unlink from boss right now world.get_door('Hera Lobby S', player).dungeonLink = 'Tower of Hera' diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 460d34ad..339ed2f8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,6 +9,12 @@ Big thanks to Catobat for doing all the hard work. # Bug Fixes +* 0.3.0.2-u + * Disallowed Swamp Lobby in Hyrule Castle in Standard mode + * Prevent defeating Aga 1 before Zelda is delivered to the Sanctuary. (He can't take damage) + * Fix for Ice Jelly room when going backward and enemizer is on + * Fix for inverted - don't start as a bunny in Dark Sanctuary + * Fix for non-ER Inverted with Lobby shuffle. Aga Tower's exit works properly now. * 0.3.0.1-u * Problem with lobbies on re-rolls corrected * Potential playthrough problem addressed diff --git a/Rom.py b/Rom.py index 4b9680da..a356fb08 100644 --- a/Rom.py +++ b/Rom.py @@ -711,6 +711,12 @@ def patch_rom(world, rom, player, team, enemized): if dr_flags & DROptions.Town_Portal and world.mode[player] == 'inverted': rom.write_byte(0x138006, 1) + # swap in non-ER Lobby Shuffle Inverted - but only then + if world.mode[player] == 'inverted' and world.intensity[player] >= 3 and world.doorShuffle[player] != 'vanilla' and world.shuffle[player] == 'vanilla': + aga_portal = world.get_portal('Agahnims Tower', player) + gt_portal = world.get_portal('Ganons Tower', player) + aga_portal.exit_offset, gt_portal.exit_offset = gt_portal.exit_offset, aga_portal.exit_offset + for portal in world.dungeon_portals[player]: if not portal.default: offset = portal.ent_offset @@ -2093,8 +2099,9 @@ def set_inverted_mode(world, player, rom): if world.shuffle[player] == 'vanilla': rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT rom.write_byte(0xDBB73 + 0x36, 0x24) - write_int16(rom, 0x15AEE + 2*0x38, 0x00E0) - write_int16(rom, 0x15AEE + 2*0x25, 0x000C) + if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3: + write_int16(rom, 0x15AEE + 2*0x38, 0x00E0) + write_int16(rom, 0x15AEE + 2*0x25, 0x000C) if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']: rom.write_byte(0x15B8C, 0x6C) rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house diff --git a/RoomData.py b/RoomData.py index 3fe8d594..f3c82576 100644 --- a/RoomData.py +++ b/RoomData.py @@ -252,6 +252,7 @@ def create_rooms(world, player): world.get_room(0x77, player).swap(0, 1) # fixes Hera Lobby Key Stairs - entrance now at pos 0 if world.enemy_shuffle[player] != 'none': world.get_room(0xc0, player).change(0, DoorKind.Normal) # fix this kill room if enemizer is on + world.get_room(0x0e, player).change(1, DoorKind.TrapTriggerable) # fix this kill room if enemizer is on def reset_rooms(world, player): @@ -369,7 +370,7 @@ class DoorKind(Enum): IncognitoEntrance = 0x12 DungeonChanger = 0x14 ToggleFlag = 0x16 - Trap = 0x18 + Trap = 0x18 # both sides trapped UnknownD6 = 0x1A SmallKey = 0x1C BigKey = 0x1E @@ -382,8 +383,8 @@ class DoorKind(Enum): Bombable = 0x2E BlastWall = 0x30 Hidden = 0x32 - TrapTriggerable = 0x36 - Trap2 = 0x38 + TrapTriggerable = 0x36 # right side trap or south side trap + Trap2 = 0x38 # left side trap or north side trap NormalLow2 = 0x40 TrapTriggerableLow = 0x44 Warp = 0x46 diff --git a/asm/dr_lobby.asm b/asm/dr_lobby.asm index c2f08fa6..cf3ed694 100644 --- a/asm/dr_lobby.asm +++ b/asm/dr_lobby.asm @@ -1,5 +1,6 @@ CheckDarkWorldSanc: STA $A0 : STA $048E ; what we wrote over + LDA.l InvertedMode : BNE + LDA.l SancDarkWorldFlag : BEQ + SEP #$30 LDA $A0 : CMP #$12 : BNE ++ diff --git a/asm/drhooks.asm b/asm/drhooks.asm index 1aa62dde..c4939e9d 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -170,6 +170,9 @@ JSL CheckDarkWorldSanc : NOP org $01891e ; <- Bank 01.asm : 991 Dungeon_LoadType2Object (LDA $00 : XBA : AND.w #$00FF) JSL RainPrevention : NOP #2 +org $1edabf ; <- sprite_energy_ball.asm : 86-7 Sprite_EnergyBall (LDA.b #$10 : LDX.b #$00) +JSL StandardAgaDmg + ; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire ; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes ; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds diff --git a/asm/overrides.asm b/asm/overrides.asm index d47d565f..28eb7f91 100644 --- a/asm/overrides.asm +++ b/asm/overrides.asm @@ -142,3 +142,10 @@ RainPrevention: PLA : LDA #$0008 : RTL .done PLA : RTL +; A should be how much dmg to do to Aga when leaving this function +StandardAgaDmg: + LDX.b #$00 ; part of what we wrote over + LDA.l $7EF3C6 : AND #$04 : BEQ + ; zelda's not been rescued + LDA.b #$10 ; hurt him! + + RTL ; A is zero if the AND results in zero and then Agahnim's invincible! + diff --git a/data/base2current.bps b/data/base2current.bps index 970df14e576c2923e6564beaed7c30e523d35e04..4674a0635dce4700727220b4681a6fc78d7892e8 100644 GIT binary patch delta 17234 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 DK#F>= delta 16883 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 Date: Wed, 10 Feb 2021 15:19:09 -0700 Subject: [PATCH 03/10] Key logic error with odd_counter and child doors Fix the Lone Pot doors (E/W) swapped --- DoorShuffle.py | 2 +- Doors.py | 4 ++-- KeyDoorShuffle.py | 9 ++++++--- Regions.py | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index c2085c50..3a07ff1a 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -2417,7 +2417,7 @@ interior_doors = [ ('Skull Pull Switch S', 'Skull Big Chest N'), ('Skull Left Drop ES', 'Skull Compass Room WS'), ('Skull 2 East Lobby NW', 'Skull Big Key SW'), - ('Skull Big Key WN', 'Skull Lone Pot EN'), + ('Skull Big Key EN', 'Skull Lone Pot WN'), ('Skull Small Hall WS', 'Skull 2 West Lobby ES'), ('Skull 2 West Lobby NW', 'Skull X Room SW'), ('Skull 3 Lobby EN', 'Skull East Bridge WN'), diff --git a/Doors.py b/Doors.py index c3cc969d..af585bad 100644 --- a/Doors.py +++ b/Doors.py @@ -541,8 +541,8 @@ def create_doors(world, player): create_door(player, 'Skull 2 East Lobby WS', Nrml).dir(We, 0x57, Bot, High).pos(4), create_door(player, 'Skull 2 East Lobby NW', Intr).dir(No, 0x57, Left, High).pos(1), create_door(player, 'Skull Big Key SW', Intr).dir(So, 0x57, Left, High).pos(1), - create_door(player, 'Skull Big Key WN', Intr).dir(We, 0x57, Top, High).pos(0), - create_door(player, 'Skull Lone Pot EN', Intr).dir(Ea, 0x57, Top, High).pos(0), + create_door(player, 'Skull Big Key EN', Intr).dir(Ea, 0x57, Top, High).pos(0), + create_door(player, 'Skull Lone Pot WN', Intr).dir(We, 0x57, Top, High).pos(0), create_door(player, 'Skull Small Hall ES', Nrml).dir(Ea, 0x56, Bot, High).pos(3), create_door(player, 'Skull Small Hall WS', Intr).dir(We, 0x56, Bot, High).pos(2), create_door(player, 'Skull 2 West Lobby S', Nrml).dir(So, 0x56, Left, High).pos(1).portal(Z, 0x00), diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index becf6bf8..1a4e1469 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -579,7 +579,7 @@ def progressive_ctr(new_counter, last_counter): def unique_child_door(child, key_counter): if child in key_counter.child_doors or child.dest in key_counter.child_doors: return False - if child in key_counter.open_doors or child.dest in key_counter.child_doors: + if child in key_counter.open_doors or child.dest in key_counter.open_doors: return False if child.bigKey and key_counter.big_key_opened: return False @@ -589,7 +589,7 @@ def unique_child_door(child, key_counter): def unique_child_door_2(child, key_counter): if child in key_counter.child_doors or child.dest in key_counter.child_doors: return False - if child in key_counter.open_doors or child.dest in key_counter.child_doors: + if child in key_counter.open_doors or child.dest in key_counter.open_doors: return False return True @@ -1463,7 +1463,10 @@ def create_odd_key_counter(door, parent_counter, key_layout, world, player): next_counter = find_next_counter(door, parent_counter, key_layout) odd_counter.free_locations = dict_difference(next_counter.free_locations, parent_counter.free_locations) odd_counter.key_only_locations = dict_difference(next_counter.key_only_locations, parent_counter.key_only_locations) - odd_counter.child_doors = dict_difference(next_counter.child_doors, parent_counter.child_doors) + odd_counter.child_doors = {} + for d in next_counter.child_doors: + if d not in parent_counter.child_doors and (d.type == DoorType.SpiralStairs or d.dest not in parent_counter.child_doors): + odd_counter.child_doors[d] = None odd_counter.other_locations = dict_difference(next_counter.other_locations, parent_counter.other_locations) odd_counter.important_locations = dict_difference(next_counter.important_locations, parent_counter.important_locations) for loc in odd_counter.other_locations: diff --git a/Regions.py b/Regions.py index 5d8a1769..87451e6b 100644 --- a/Regions.py +++ b/Regions.py @@ -472,8 +472,8 @@ def create_dungeon_regions(world, player): create_dungeon_region(player, 'Skull Compass Room', 'Skull Woods', ['Skull Woods - Compass Chest'], ['Skull Compass Room NE', 'Skull Compass Room ES', 'Skull Compass Room WS']), create_dungeon_region(player, 'Skull Left Drop', 'Skull Woods', None, ['Skull Left Drop ES']), create_dungeon_region(player, 'Skull 2 East Lobby', 'Skull Woods', None, ['Skull 2 East Lobby NW', 'Skull 2 East Lobby WS', 'Skull 2 East Lobby SW']), - create_dungeon_region(player, 'Skull Big Key', 'Skull Woods', ['Skull Woods - Big Key Chest'], ['Skull Big Key SW', 'Skull Big Key WN']), - create_dungeon_region(player, 'Skull Lone Pot', 'Skull Woods', None, ['Skull Lone Pot EN']), + create_dungeon_region(player, 'Skull Big Key', 'Skull Woods', ['Skull Woods - Big Key Chest'], ['Skull Big Key SW', 'Skull Big Key EN']), + create_dungeon_region(player, 'Skull Lone Pot', 'Skull Woods', None, ['Skull Lone Pot WN']), create_dungeon_region(player, 'Skull Small Hall', 'Skull Woods', None, ['Skull Small Hall ES', 'Skull Small Hall WS']), create_dungeon_region(player, 'Skull Back Drop', 'Skull Woods', None, ['Skull Back Drop Star Path', ]), create_dungeon_region(player, 'Skull 2 West Lobby', 'Skull Woods', ['Skull Woods - West Lobby Pot Key'], ['Skull 2 West Lobby ES', 'Skull 2 West Lobby NW', 'Skull 2 West Lobby S']), From 3b8773ea33a38864b0983d346760da619c5482da Mon Sep 17 00:00:00 2001 From: aerinon Date: Sat, 13 Feb 2021 20:58:59 -0700 Subject: [PATCH 04/10] Update item counter for mystery Fixed bug with door restart Made retro keys more lenient with door shuffle --- DoorShuffle.py | 3 ++- ItemList.py | 5 +++++ Main.py | 2 +- Rom.py | 8 ++++++-- Rules.py | 6 ++++++ asm/hudadditions.asm | 18 ++++++++++++++---- 6 files changed, 34 insertions(+), 8 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index 3a07ff1a..d2cf35f8 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -35,7 +35,7 @@ def link_doors(world, player): door.dest = None door.entranceFlag = False ent = door.entrance - if door.type != DoorType.Logical and ent.connected_region is not None: + if (door.type != DoorType.Logical or door.controller) and ent.connected_region is not None: ent.connected_region.entrances = [x for x in ent.connected_region.entrances if x != ent] ent.connected_region = None for portal in world.dungeon_portals[player]: @@ -2012,6 +2012,7 @@ class DROptions(Flag): OriginalPalettes = 0x20 Open_PoD_Wall = 0x40 # If on, pre opens the PoD wall, no bow required Open_Desert_Wall = 0x80 # If on, pre opens the desert wall, no fire required + Hide_Total = 0x100 # DATA GOES DOWN HERE diff --git a/ItemList.py b/ItemList.py index ddb629ab..9b2de617 100644 --- a/ItemList.py +++ b/ItemList.py @@ -596,6 +596,11 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r pool = [item.replace('Arrow Upgrade (+5)','Rupees (5)') for item in pool] pool = [item.replace('Arrow Upgrade (+10)','Rupees (5)') for item in pool] pool.extend(diff.retro) + if door_shuffle != 'vanilla': # door shuffle needs more keys for retro + replace = 'Rupees (20)' if difficulty == 'normal' else 'Rupees (5)' + indices = [i for i, x in enumerate(pool) if x == replace] + for i in range(0, min(10, len(indices))): + pool[indices[i]] = 'Small Key (Universal)' if mode == 'standard': if door_shuffle == 'vanilla': key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross']) diff --git a/Main.py b/Main.py index 42a45fdd..a11a6dc2 100644 --- a/Main.py +++ b/Main.py @@ -238,7 +238,7 @@ def main(args, seed=None, fish=None): logging.warning(enemizerMsg) raise EnemizerError(enemizerMsg) - patch_rom(world, rom, player, team, enemized) + patch_rom(world, rom, player, team, enemized, bool(args.outputname)) if args.race: patch_race_rom(rom) diff --git a/Rom.py b/Rom.py index a356fb08..27961b5d 100644 --- a/Rom.py +++ b/Rom.py @@ -518,7 +518,8 @@ class Sprite(object): # split into palettes of 15 colors return array_chunk(palette_as_colors, 15) -def patch_rom(world, rom, player, team, enemized): + +def patch_rom(world, rom, player, team, enemized, is_mystery=False): random.seed(world.rom_seeds[player]) # progressive bow silver arrow hint hack @@ -707,7 +708,10 @@ def patch_rom(world, rom, player, team, enemized): rom.write_byte(0x13f000+dungeon_id, opposite_door.roomIndex) elif not opposite_door: rom.write_byte(0x13f000+dungeon_id, 0) # no supertile preceeding boss - rom.write_byte(0x138004, dr_flags.value) + if is_mystery: + dr_flags |= DROptions.Hide_Total + rom.write_byte(0x138004, dr_flags.value & 0xff) + rom.write_byte(0x138005, (dr_flags.value & 0xff00) >> 8) if dr_flags & DROptions.Town_Portal and world.mode[player] == 'inverted': rom.write_byte(0x138006, 1) diff --git a/Rules.py b/Rules.py index 3049dd5b..dd00644f 100644 --- a/Rules.py +++ b/Rules.py @@ -1592,6 +1592,7 @@ def add_key_logic_rules(world, player): if keys.opposite: rule = or_rule(rule, create_advanced_key_rule(d_logic, player, keys.opposite)) add_rule(spot, rule) + for location in d_logic.bk_restricted: if not location.forced_item: forbid_item(location, d_logic.bk_name, player) @@ -1601,6 +1602,11 @@ def add_key_logic_rules(world, player): add_rule(world.get_entrance(door.name, player), create_rule(d_logic.bk_name, player)) for chest in d_logic.bk_chests: add_rule(world.get_location(chest.name, player), create_rule(d_logic.bk_name, player)) + if world.retro[player]: + for d_name, layout in world.key_layout[player].items(): + for door in layout.flat_prop: + if world.mode[player] != 'standard' or not retro_in_hc(door.entrance): + add_rule(door.entrance, create_key_rule('Small Key (Universal)', player, 1)) def retro_in_hc(spot): diff --git a/asm/hudadditions.asm b/asm/hudadditions.asm index 9b78a0a4..4568b12e 100644 --- a/asm/hudadditions.asm +++ b/asm/hudadditions.asm @@ -8,11 +8,21 @@ DrHudOverride: HudAdditions: { lda.l DRFlags : and #$0008 : beq ++ - lda $7EF423 : and #$00ff + LDA.w #$28A4 : STA !GOAL_DRAW_ADDRESS + lda $7EF423 jsr HudHexToDec4DigitCopy - LDX.b $05 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+10 ; draw 100's digit - LDX.b $06 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+12 ; draw 10's digit - LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit + LDX.b $05 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+2 ; draw 100's digit + LDX.b $06 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+4 ; draw 10's digit + LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+6 ; draw 1's digit + LDA.w #$2830 : STA !GOAL_DRAW_ADDRESS+8 ; draw slash + LDA.l DRFlags : AND #$0100 : BNE + + lda $7EF33E + jsr HudHexToDec4DigitCopy + LDX.b $05 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+10 ; draw 100's digit + LDX.b $06 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+12 ; draw 10's digit + LDX.b $07 : TXA : ORA.w #$2400 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit + BRA ++ + + LDA.w #$2405 : STA !GOAL_DRAW_ADDRESS+10 : STA !GOAL_DRAW_ADDRESS+12 : STA !GOAL_DRAW_ADDRESS+14 ++ LDX $1B : BNE + : RTS : + ; Skip if outdoors From 26f7b1c993253d92cc9af65fcf2c4c7a446d87d6 Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 15 Feb 2021 13:36:34 -0700 Subject: [PATCH 05/10] Notes/version Baserom update --- Main.py | 2 +- RELEASENOTES.md | 10 +++++++++- Rom.py | 2 +- data/base2current.bps | Bin 132335 -> 132008 bytes 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Main.py b/Main.py index a11a6dc2..4d429679 100644 --- a/Main.py +++ b/Main.py @@ -25,7 +25,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items from Utils import output_path, parse_player_names -__version__ = '0.3.0.2-u' +__version__ = '0.3.0.3-u' class EnemizerError(RuntimeError): pass diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 339ed2f8..a63ece84 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -7,14 +7,22 @@ any N/S connections. (those that appear to go up one floor are North connection Big thanks to Catobat for doing all the hard work. +## Experimental Item Counter + +New item counter modified to show total? + # Bug Fixes -* 0.3.0.2-u +* 0.3.0.3-u * Disallowed Swamp Lobby in Hyrule Castle in Standard mode * Prevent defeating Aga 1 before Zelda is delivered to the Sanctuary. (He can't take damage) * Fix for Ice Jelly room when going backward and enemizer is on * Fix for inverted - don't start as a bunny in Dark Sanctuary * Fix for non-ER Inverted with Lobby shuffle. Aga Tower's exit works properly now. + * Fix for In-Room Stairs with Trap Doors + * Key logic fix + * Fix for door gen re-start + * More lenient keys in DR+Retro * 0.3.0.1-u * Problem with lobbies on re-rolls corrected * Potential playthrough problem addressed diff --git a/Rom.py b/Rom.py index 27961b5d..20ffe6c2 100644 --- a/Rom.py +++ b/Rom.py @@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3a77558175cf8b2233f87c60329baa5d' +RANDOMIZERBASEHASH = '795290cfff38c1b0b0dca6498e5d107b' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 4674a0635dce4700727220b4681a6fc78d7892e8..97f3e55e8343ea77cd3d23e9cd16da70df54b32a 100644 GIT binary patch delta 17218 zcmZWQc|a4_)4Q7h;SPv^91<3gLj_b+#0yVQsiLAH291h}#shDwNZtkl1PDubh7|&2 zfglFNfQX1!;%(Ym(^h}BsP$^CqOEDQ)#8!wrT>27+nIOl+j-Z_yqU>sIqzr@uOc{l z#&hb#b4oi2D1@^?!{KV7=VP|NeK-$L!$n0(p&B&wXBWu;o}RA|YGuj=BYm!SYWY%G z^SLxyNlFT|{k$`jtd=^ZgfTI@ud`gxNq%vI?Z3n)6ArWe{aGE<)CegxHN9FTocL z2vCtZ<>3H_jgzJUWj}epEIhrinj{qA9k?j=seJ1hD8h$GJg=iK^!HcD`uh)2Sh7Ju za?fg0762vA^Tr)~E0w~nRoea^6{Pl(HljrS@T_)ok(_^uO$ADF!xgsQ1;`hlVk_Xd zVIcRof)p08xpx#~NwIb_B|obO4=7NPdua5DeUy@1bcyZPDoAjN{YF8G%ECiS+9hPu zC6?TM&sDhc9h+FBAk)jk52<&iNfqsYH4CK*;mp^pS9JrK2edXi`>!a-yHc$Sng9l{ zp{VzqbEv{Mzq-FPyt&h2Uo~c%G!4jeio&^41t}{FkC4l^7ldZ`4eDGf_x1TFjlJ_7@Odh%H9oz3!B2PS{y$uK5kl(Ih zg^YqUtJy4>d~uOB6piU$!1hm4D#(gU@L$3|lrCnr*ntlzjv%p0NqYaw_NS_;-{AH@ z@Jc~CpVKl2Li6D`PFT>cGul@>S-@aHVomat^KpW*Ir}061w|++et$GjbZDF>xr6 zqfrY`o49vO_@06YCB;3bAgMoCqmtwt4(|`Rs3N-x(Hz9yQjy2&5F(=F{P}b2SRfakVzug=%;K4aEp%~9q1Oa7CYOI% zxQ`nwcu=UluOyXHt;m;BkQWZKp_M8!?spcr&OD?d9j?G$?g-!ROWHWJ453%iB4-!F zo#CaSG8Gwr6@KFS@KP?b{bsrLG7PZu$E#tyUAE+N7u%sA-*vI+w$;ARzLJ|>vA$H# zT-g=5@)gIu)644-p?X?^6VuP2o%$U`)njSkeaBdn-D z2hn|+X0`I$9qca(GQ1ON?IQ>bz;Eq`5=XDWKkTE%mEDK9nJ1M$rP*E0@~{dvRV}}9 zNjtNMx~EPhC;=@mHE5s9f0eNUje@N0X0xm0(cN&q!$=8a!c);~&$`HZWuTpqevjRZ zvYYSOW^Ep&O=eW2i|s7%%N1k|rG2X;_upsx6N{8&I~qy+arsdyBD<>|8!A;C;FvQ5 zP#;^0wL%2m8?{1MKL2I2qu{O8%oW@_*`HD__dUr5AQR4LkD+Z>tevSaSw*3A#>^JhTi|iy?K`trO z#_Gz zXA@-)_efS&gvuW7rxI0&U`6>nkdq*LK}Wo{r|b@ptxl)vN^S zz7q%lEi~*IMz`RF#HYM z&n>Se8+zE3XU9^}QIz$t{aCq5q2jVul&>N$y+mI=#w;NrOmSBR0Hu(8%Jz%UCLC?l-jEM`$NqRXXDP~_KFNx@ zWF)B$%2uUQ)k0E=I_mdAdvTsrJEDLRN1(kt6*1WU5!aEF@u#%?9n4m)vP?mq0@~bQ zw1;jKXloVZ;{t7(R!Lq#66c0eh+o$B*H#bwAj8go_~Ec@;LagK-b!?yFu+EjR}icF zC>!`+PJztnJ1?q%{F!3SXfXh#wP`N^&oS`06Ja31E0Oko8yWDo_bEh?0KpWy-?-|Nro| z(|F0QM{KTKLB6PFQ_y;soYf+k%Hydyk%}CO8s1S&Y74dGj$fP#+l5*eR5r9z>s9izWJ!rEYEsQU=laA0Qu&c$ZE{H+xwe2M8_#H~0+VW94qjTB zjpPOMUhU_lXbA{aCbrje9H%O-P@|o}xGGrgyq-Yf^B?D-3)U8E_aQ~#RfpC$pAyGW z@+pUG=VV`@_LZERuWa&ICXWMp*ZCD*ppJZc$hKzvhvlS`N{t1pe^d%bskHs4nJp6w za*(uI&x?P-NdG6XS|re(3!>b=k8!m>ih z<^?y6qtma*52DW_&awGEn@!dGz~ABp!!+WQ`^u+Q4)#*L zYu^3xS%1^T)JwIL`k)@{bDw(EI%rGH!)RX^J|S$)`))QAQ0}!&D}sJjz9d&%VRzM2 z2bmdzq%#X_U8nj0x%?EHEM;~iKB*`bfe0DB6WmvO7YGVzI>#Hx>QcS(Y0q1!8hIhb zrX5z2cM*5sR#OyQ{QV>oC4`=M{0f}BE!N1W97iZ#dN z7-;-PMjBycf`C}j3g;z+JGh?Jipi4Rt}heDN+*m)h_B|->oVT zTfx_(7tBuCdIrRjG9@d{27L0?c`a}v-7aVWm;B-a{C(yy*ONc7DKe$$gV}-1>4Sn< zPx%+7gdL?uj0WQZPdNZGr4A07{fu|PGydM?K^}b&PZCc??*N`@t(l8nVH>eWp&c#{ ztE*TuCmwL01B-9lK(?669Nh3j`=G(Tp;2*T$4#FxYq?<~ysEt0QU!g{h?)yK(Ozf9yMYRfi(}MHbe!zJucK1X6lKr#$|J zlYVn2McA_2PM|EV-*tk*R)HC?ec^oKpb~ysI4(n!DlypKh^5ye=z!pwR0#++U^ilG z(r49BPMW==KlB3ji9lzi7p6+2KVwe>OzwyyBc+FLp;r;n$1nqKiZxly9BBh)z)Z2X zQd1=sj#Lg6i%3aEpALI@cj1vLFQf0Qf$lzk^pcJhbaf!N}PzOUD~E%^8V5IT%rl`7FMN|m7ZT=WQc zf8EZ)(G<0`O-fnNvCly8Po_m4v44PmOkb5}XJ=O}NLMO_f0o*dn}V0W>cugv#CId` zpr@xwp2Qy3jPrU`eTgqZpM{SXPa~%H!qBwwl8t9?iqN~dp~<>Gl65bV&jU9hRfMU> zo$BVKB)1}^jr{HHP(f8IoCWHD#ak{gd-gSz%>owA0B{@tn4s&ppzBzhSdZ2v(!t_q z!qNOTVf?1i4T&g647_@V=ZNrM~km?G36tz_g}Zu!Loq7pcf(ftNEu8%zcE5VHjGlTcY>mDvf>n7+B9Ep;u6q0CMs=+jQ zJ_StnmI8`~YfBW7!0b`8XhxmFidr(u173Y+KpW;LSy$~~Ks(pZwtY+H&Q)&?c-3nT zwr!%o*X_1_)mPFoxa6jvg{wikd;p9`YdXYM?dSmKR>8@KWICLge~9waUql&ta|QIu z59vg-;{^ATpczYkB4}Eb^wlhooMGF$ksK@m9rUAm=)WwKvwqfBaQdSSEehFEGaM=W4+(#{t(wXm$ks+>G`M%I+U%6E#H^$)zVS_5OS% z>hY2Q7OR?YC#R#GaL_&3jT`E@_j=8|PK*vW<^iWp%y%OfCP?K^1p8rF(NEE40=S!E z(9;pksKl=KnjW1a<4eY!K5wym8UKQO`I3$_=Go>*v+SA-9kF(ZJ)&1XkUQxJS`3sr z960M>>3M;=Lr3%_>k-YZ*@8tKaOjn>08KVWVA9`sj{b>`>rd#<=y_NKX0b+K0tA0V z(3X!!>DrC2;NS#C&buTqh^e~XM5K1_&o~T4Qs}xoA~8~~@h)v3a~|3a*hW|7nkK89 zZgd4`ceIIScO-YDbYNBt04pXERa98}GLmKX%>vV!4yPuZ@t9Ho_bw0QdOmUm@bL0b zZsnxQFW|-H0mRx*@X_*-DMvc#V!1%k$)raC_3DwpG@_FQ4yb@^V~|i2p!&nmHyX5? zLd^jgY$y_{?EXgQDScIvMU;x1j^u0xv@56f!~NxOdBz9wZWnu%Tfun_{xUA3~{*=wyhXKq-=rLR)mm-PP)5vEs(#y*h#Me=dal# zHoL{z79qw3g7L4fF<~yySs1|U?_!ahe9#4BguaB`NjOL7Pn4g8>xGL(4t&q{6*h?V zp&*vt@g}dyd;HHTeHhB@RLf)*r^ZdYzNb9sVwr`fnUDg16)qyGy5WRO0eNQjvU^B` zBr>8AeJ!iz-;?Ri!lw#ewb}LZ=(uN;piK%7W(vmioYl5p;ob@cu@?2%wX#l=gT
k&4(LBGD$Z_U9~X(EM^oS_B#hR4ntr%Zj44? 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 From f13dba3512a33af61ec7eb97b151caae56fe0de4 Mon Sep 17 00:00:00 2001 From: "Mike A. Trethewey" Date: Mon, 15 Feb 2021 19:36:20 -0800 Subject: [PATCH 06/10] QoL Improvements Update SpriteSomething collections page for Z3Link sprites Add Diagnostics button to the GUI --- source/classes/SpriteSelector.py | 2 +- source/gui/randomize/generation.py | 46 +++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/source/classes/SpriteSelector.py b/source/classes/SpriteSelector.py index 1ab073ad..1c869301 100644 --- a/source/classes/SpriteSelector.py +++ b/source/classes/SpriteSelector.py @@ -38,7 +38,7 @@ class SpriteSelector(object): # Open SpriteSomething directory for Link sprites def open_spritesomething_listing(_evt): - webbrowser.open("https://artheau.github.io/SpriteSomething/resources/app/snes/zelda3/link/sprites.html") + webbrowser.open("https://miketrethewey.github.io/SpriteSomething-collections/snes/zelda3/link/") official_frametitle = Frame(self.window) official_title_text = Label(official_frametitle, text="Official Sprites") diff --git a/source/gui/randomize/generation.py b/source/gui/randomize/generation.py index f358c864..4bcb868c 100644 --- a/source/gui/randomize/generation.py +++ b/source/gui/randomize/generation.py @@ -1,8 +1,11 @@ -from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X +from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X, Text, Tk, INSERT +import source.classes.diags as diagnostics import source.gui.widgets as widgets import json import os +from functools import partial from source.classes.Empty import Empty +from Main import __version__ def generation_page(parent,settings): # Generation Setup @@ -76,4 +79,45 @@ def generation_page(parent,settings): # frame: pack self.widgets[widget].pieces["frame"].pack(fill=X) + ## Run Diagnostics + # This one's more-complicated, build it and stuff it + # widget ID + widget = "diags" + + # Empty object + self.widgets[widget] = Empty() + # pieces + self.widgets[widget].pieces = {} + + # frame + self.frames["diags"] = Frame(self) + self.frames["diags"].pack() + self.widgets[widget].pieces["frame"] = Frame(self.frames["diags"]) + + + def diags(): + # Debugging purposes + dims = { + "window": { + "width": 800, + "height": 500 + }, + "textarea.characters": { + "width": 120, + "height": 50 + } + } + diag = Tk() + diag.title("Door Shuffle " + __version__) + diag.geometry(str(dims["window"]["width"]) + 'x' + str(dims["window"]["height"])) + text = Text(diag, width=dims["textarea.characters"]["width"], height=dims["textarea.characters"]["height"]) + text.pack() + text.insert(INSERT,"\n".join(diagnostics.output(__version__))) + # dialog button + self.widgets[widget].pieces["button"] = Button(self.widgets[widget].pieces["frame"], text='Run Diagnostics', command=partial(diags)) + + # button: pack + self.widgets[widget].pieces["button"].pack(side=LEFT) + # frame: pack + self.widgets[widget].pieces["frame"].pack(fill=X) return self,settings From 5a8139258dba6d7c32cbfaf29e91974551a9c0b7 Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Tue, 16 Feb 2021 20:00:21 +0100 Subject: [PATCH 07/10] PoD Mimics 2 portal flexibility --- Doors.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Doors.py b/Doors.py index 3bc41766..c65346d1 100644 --- a/Doors.py +++ b/Doors.py @@ -1304,7 +1304,6 @@ def create_doors(world, player): world.get_door('GT Petting Zoo SE', player).dead_end() world.get_door('GT DMs Room SW', player).dead_end() world.get_door("GT Bob\'s Room SE", player).passage = False - world.get_door('PoD Mimics 2 SW', player).bk_shuffle_req = True world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note (todo) # can't unlink from boss right now From b36c03a8b406b95a7bf217a938882fc1548dc5f7 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 16 Feb 2021 13:34:00 -0700 Subject: [PATCH 08/10] Pot shuffle repair --- BaseClasses.py | 4 +++- Main.py | 3 ++- RELEASENOTES.md | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 9ac6377b..6c77eb3c 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -146,7 +146,9 @@ class World(object): region.world = self self._region_cache[region.player][region.name] = region for exit in region.exits: - self._entrance_cache[(exit.name, exit.player)] = exit + self._entrance_cache[exit.name, exit.player] = exit + for r_location in region.locations: + self._location_cache[r_location.name, r_location.player] = r_location def initialize_doors(self, doors): for door in doors: diff --git a/Main.py b/Main.py index 4d429679..00de5e19 100644 --- a/Main.py +++ b/Main.py @@ -428,12 +428,13 @@ def copy_world(world): copied_shop.inventory = copy.copy(shop.inventory) # connect copied world + copied_locations = {(loc.name, loc.player): loc for loc in ret.get_locations()} # caches all locations for region in world.regions: copied_region = ret.get_region(region.name, region.player) copied_region.is_light_world = region.is_light_world copied_region.is_dark_world = region.is_dark_world copied_region.dungeon = region.dungeon - copied_region.locations = [ret.get_location(location.name, location.player) for location in region.locations] + copied_region.locations = [copied_locations[(location.name, location.player)] for location in region.locations] for entrance in region.entrances: ret.get_entrance(entrance.name, entrance.player).connect(copied_region) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a63ece84..00956f23 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,7 +9,7 @@ Big thanks to Catobat for doing all the hard work. ## Experimental Item Counter -New item counter modified to show total? +New item counter modified to show total # Bug Fixes @@ -22,7 +22,10 @@ New item counter modified to show total? * Fix for In-Room Stairs with Trap Doors * Key logic fix * Fix for door gen re-start - * More lenient keys in DR+Retro + * More lenient keys in DR+Retro + * Fix for shufflepots option +* 0.3.0.2-u + * Introduced in-room staircases/ladders * 0.3.0.1-u * Problem with lobbies on re-rolls corrected * Potential playthrough problem addressed From 2af9ffbda446b691131cdf144191a895b10cc85b Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 17 Feb 2021 15:23:46 -0700 Subject: [PATCH 09/10] Notes and version update Fix hera double count --- Main.py | 2 +- RELEASENOTES.md | 4 ++++ Rom.py | 2 +- data/base2current.bps | Bin 132008 -> 132014 bytes 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Main.py b/Main.py index 00de5e19..b9880969 100644 --- a/Main.py +++ b/Main.py @@ -25,7 +25,7 @@ from Fill import distribute_items_cutoff, distribute_items_staleness, distribute from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items from Utils import output_path, parse_player_names -__version__ = '0.3.0.3-u' +__version__ = '0.3.0.4-u' class EnemizerError(RuntimeError): pass diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 00956f23..ee589f45 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -13,6 +13,10 @@ New item counter modified to show total # Bug Fixes +* 0.3.0.4-u + * QoL fixes from Mike + * Allow PoD Mimics 2 as a lobby in non-keysanity seeds (Thanks @Catobat) + * Fix for double-counting Hera key in keydropshuffle * 0.3.0.3-u * Disallowed Swamp Lobby in Hyrule Castle in Standard mode * Prevent defeating Aga 1 before Zelda is delivered to the Sanctuary. (He can't take damage) diff --git a/Rom.py b/Rom.py index 20ffe6c2..421ee3a0 100644 --- a/Rom.py +++ b/Rom.py @@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '795290cfff38c1b0b0dca6498e5d107b' +RANDOMIZERBASEHASH = '0a34dc667a29125f09b10aeb1e06b83c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 97f3e55e8343ea77cd3d23e9cd16da70df54b32a..fabbaa269805540d0624e7b29399fdd2e85c4c18 100644 GIT binary patch delta 818 zcmV-21I_%XhX}5R2(T{!1WyaF^pi6ISRM+yq)bnMkpT!60S6e8kz8(;r0Up>BC5iq zD2j>Ylc@oa0d|u*0`~zClQIK20fm!n1LFbolTZYj0lTy71QP-e&cdWbhk@anPy&G< zkBO0!4F{S5{*$N&x&bS*V+a%h0h5z>2_OMDlbH!*0SA-*35W-!!=&o!1jCb%3LulM z3OX2&yQC0;g$M|n11XJgfq^TqnIfcyq#}5;{|a^k0Zg-Y4*e=H+ z4b{D*fC?fMzNCNzB2%-uL`4(dVm2ar!IbukAek&Yakbs!qhtf7nA1l|uA>8jnJ+afE?FkAkZPg@Fy1XMT=>I+ucxXlo*2xSJY&j*%Zo+OH>@Wo?d& zx{JGuuBnO-C-i=gC-i>$Xr~~Pd(|5OeUq2fc@jQ3j-@8_ei&~zP=6^8lZKNMlOooK z2P|NafnJkeld#q%25caJQGhIy+}4y(XE6tW)m+W+1&d3osRx}<4}a+Pj}vz<&DZ=*Y-` z>bt)(lOWnBGI3~tg|9i6Z&{9kD3?%HfRhe#j)7Unf`Mqqf`MtXf|4m|k&_`;j*)#@ ztk?pR+M_&^dD?vsYhn9=XnS~u8d~u`Wr|$01>5l&0TYw=^(7e-yQKPPYss(h@yR6c w?fRbvR_=*tI%}5#lQs5L3O8Sp6bY|$8=FLfl=ioj_5lnH2=6VpA;FO-#|B4hRR910 delta 773 zcmV+g1N!`~hX|;L2(T{!1hEcI@sl$FSRMqsq)bnMkpT!60S6e8kz8(;r0Up>BBa8k zD2j>Slc@oa0dSK#0`~z6lQIK20e_Qh1LFbilTZYj0kyO11QP-e$ik#Vhk@IhPy&G< zkBN(u4F{S5_>-syx&bA#V+a%h0gaP*2_OM7lbH!*0RfZ#35W-u!=&o!1jCb%3LulM z3OX2yyQC0;g$M|n11XJgfq^TqnIfcyq#|;&{|a^k0Y=H+ z4bQ!#fC?fGzNCNzB2BZoL`4(q=G#G$#2jHB22S% zY%~QBf4ror0gdSbuaki=@C71_v$%0%5&>ge)?#q6qA9~8v${Xoz-~~GC7W=CiH$7Z#PhXDG!r|lLwP1)`tfmV32`c zlT(wn)+PpEAb?STCX?dUlsQ{52Y}UF&F}?_ORK2|olp-TslOuU^d2DTzn?ra?VmYl zz>&#?2&uomZY%JUGz`6_5irAn_@ii(uh$j)1Xpfcepd0|N)00t>l{(4) z0I)xo3zG`k8v!PhCfX-5WoUqfuQ``*S&o4ymrz!KlLB&%fmz3bfoR8qfoZdXk|}AC zlNDEvk$qaM*aDN Date: Thu, 18 Feb 2021 10:01:52 -0700 Subject: [PATCH 10/10] Silvers issue in swordless --- Rom.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Rom.py b/Rom.py index 421ee3a0..07d8c0b8 100644 --- a/Rom.py +++ b/Rom.py @@ -925,8 +925,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): if difficulty.progressive_bow_limit < 2 and world.swords == 'swordless': rom.write_bytes(0x180098, [2, overflow_replacement]) - rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon - rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup # set up game internal RNG seed for i in range(1024):