From 01e4c2bff7eb317b739f12690374a30b8b79b53b Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:58:01 +0100 Subject: [PATCH 1/5] Include bottle refills in spoiler --- BaseClasses.py | 15 +++++++++++++++ ItemList.py | 9 +++++++++ Main.py | 1 + Rom.py | 8 ++------ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 58530558..d7625a33 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -97,6 +97,7 @@ class World(object): set_player_attr('player_names', []) set_player_attr('remote_items', False) set_player_attr('required_medallions', ['Ether', 'Quake']) + set_player_attr('bottle_refills', ['Bottle (Green Potion)', 'Bottle (Green Potion)']) set_player_attr('swamp_patch_required', False) set_player_attr('powder_patch_required', False) set_player_attr('ganon_at_pyramid', True) @@ -2272,6 +2273,7 @@ class Spoiler(object): self.doorTypes = {} self.lobbies = {} self.medallions = {} + self.bottles = {} self.playthrough = {} self.unreachables = [] self.startinventory = [] @@ -2315,6 +2317,15 @@ class Spoiler(object): self.medallions[f'Misery Mire ({self.world.get_player_names(player)})'] = self.world.required_medallions[player][0] self.medallions[f'Turtle Rock ({self.world.get_player_names(player)})'] = self.world.required_medallions[player][1] + self.bottles = OrderedDict() + if self.world.players == 1: + self.bottles['Waterfall Bottle'] = self.world.bottle_refills[1][0] + self.bottles['Pyramid Bottle'] = self.world.bottle_refills[1][1] + else: + for player in range(1, self.world.players + 1): + self.bottles[f'Waterfall Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][0] + self.bottles[f'Pyramid Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][1] + self.startinventory = list(map(str, self.world.precollected_items)) self.locations = OrderedDict() @@ -2434,6 +2445,7 @@ class Spoiler(object): out.update(self.locations) out['Starting Inventory'] = self.startinventory out['Special'] = self.medallions + out['Bottles'] = self.bottles if self.hashes: out['Hashes'] = {f"{self.world.player_names[player][team]} (Team {team+1})": hash for (player, team), hash in self.hashes.items()} if self.shops: @@ -2519,6 +2531,9 @@ class Spoiler(object): outfile.write('\n\nMedallions:\n') for dungeon, medallion in self.medallions.items(): outfile.write(f'\n{dungeon}: {medallion} Medallion') + outfile.write('\n\nBottle Refills:\n') + for fairy, bottle in self.bottles.items(): + outfile.write(f'\n{fairy}: {bottle}') if self.startinventory: outfile.write('\n\nStarting Inventory:\n\n') outfile.write('\n'.join(self.startinventory)) diff --git a/ItemList.py b/ItemList.py index c0f2f86c..9e0b0411 100644 --- a/ItemList.py +++ b/ItemList.py @@ -370,6 +370,15 @@ def generate_itempool(world, player): tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)] world.required_medallions[player] = (mm_medallion, tr_medallion) + # shuffle bottle refills + if world.difficulty[player] in ['hard', 'expert']: + waterfall_bottle = hardbottles[random.randint(0, 5)] + pyramid_bottle = hardbottles[random.randint(0, 5)] + else: + waterfall_bottle = normalbottles[random.randint(0, 6)] + pyramid_bottle = normalbottles[random.randint(0, 6)] + world.bottle_refills[player] = (waterfall_bottle, pyramid_bottle) + set_up_shops(world, player) if world.retro[player]: diff --git a/Main.py b/Main.py index 75fe9242..e13eda0d 100644 --- a/Main.py +++ b/Main.py @@ -364,6 +364,7 @@ def copy_world(world): ret.player_names = copy.deepcopy(world.player_names) ret.remote_items = world.remote_items.copy() ret.required_medallions = world.required_medallions.copy() + ret.bottle_refills = world.bottle_refills.copy() ret.swamp_patch_required = world.swamp_patch_required.copy() ret.ganon_at_pyramid = world.ganon_at_pyramid.copy() ret.powder_patch_required = world.powder_patch_required.copy() diff --git a/Rom.py b/Rom.py index 2ea49059..fad83d84 100644 --- a/Rom.py +++ b/Rom.py @@ -1066,12 +1066,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): ]) # set Fountain bottle exchange items - if world.difficulty[player] in ['hard', 'expert']: - rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) - rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) - else: - rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)]) - rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)]) + rom.write_byte(0x348FF, ItemFactory(world.bottle_refills[player][0], player).code) + rom.write_byte(0x3493B, ItemFactory(world.bottle_refills[player][1], player).code) #enable Fat Fairy Chests rom.write_bytes(0x1FC16, [0xB1, 0xC6, 0xF9, 0xC9, 0xC6, 0xF9]) From 5bac1ba5cc10126a496db1a597b6a2e578f4903c Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:04:54 +0100 Subject: [PATCH 2/5] Add support for Subweights --- Mystery.py | 13 +++++++- mystery_example_subweights.yml | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 mystery_example_subweights.yml diff --git a/Mystery.py b/Mystery.py index 73644500..d3d05fa0 100644 --- a/Mystery.py +++ b/Mystery.py @@ -99,7 +99,8 @@ def get_weights(path): raise Exception(f'Failed to read weights file: {e}') def roll_settings(weights): - def get_choice(option, root=weights): + def get_choice(option, root=None): + root = weights if root is None else root if option not in root: return None if type(root[option]) is not dict: @@ -114,6 +115,16 @@ def roll_settings(weights): return default return choice + while True: + subweights = weights.get('subweights', {}) + if len(subweights) == 0: + break + chances = ({k: int(v['chance']) for (k, v) in subweights.items()}) + subweight_name = random.choices(list(chances.keys()), weights=list(chances.values()))[0] + subweights = weights.get('subweights', {}).get(subweight_name, {}).get('weights', {}) + subweights['subweights'] = subweights.get('subweights', {}) + weights = {**weights, **subweights} + ret = argparse.Namespace() glitches_required = get_choice('glitches_required') diff --git a/mystery_example_subweights.yml b/mystery_example_subweights.yml new file mode 100644 index 00000000..1ec43cac --- /dev/null +++ b/mystery_example_subweights.yml @@ -0,0 +1,57 @@ + description: Example for subweights + glitches_required: none + world_state: open + goals: ganon + weapons: randomized + entrance_shuffle: none + intensity: 3 + subweights: + vanilla: + chance: 25 + weights: + door_shuffle: vanilla + keydropshuffle: + on: 40 + off: 60 + basic: + chance: 25 + weights: + door_shuffle: basic + keydropshuffle: + on: 70 + off: 30 + crossed: + chance: 25 + weights: + door_shuffle: crossed + keydropshuffle: + on: 90 + off: 10 + chaos: + chance: 25 + weights: + door_shuffle: crossed + entrance_shuffle: + none: 30 + crossed: 70 + keydropshuffle: + on: 90 + off: 10 + shopsanity: + on: 50 + off: 50 + bombbag: + on: 25 + off: 75 + subweights: + normal: + chance: 40 + weights: {} + swordless: + chance: 20 + weights: + weapons: swordless + keysanity: + chance: 40 + weights: + dungeon_items: full From 59dd62e3ce2aae97e8c017991e293fb9e85c1dde Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:24:54 +0100 Subject: [PATCH 3/5] Fix some settings being mandatory in weight files --- Mystery.py | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Mystery.py b/Mystery.py index d3d05fa0..9cf0e729 100644 --- a/Mystery.py +++ b/Mystery.py @@ -128,10 +128,11 @@ def roll_settings(weights): ret = argparse.Namespace() glitches_required = get_choice('glitches_required') - if glitches_required not in ['none', 'no_logic']: - print("Only NMG and No Logic supported") - glitches_required = 'none' - ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] + if glitches_required is not None: + if glitches_required not in ['none', 'no_logic']: + print("Only NMG and No Logic supported") + glitches_required = 'none' + ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] item_placement = get_choice('item_placement') # not supported in ER @@ -163,26 +164,27 @@ def roll_settings(weights): ret.standardize_palettes = get_choice('standardize_palettes') if 'standardize_palettes' in weights else 'standardize' goal = get_choice('goals') - ret.goal = {'ganon': 'ganon', - 'fast_ganon': 'crystals', - 'dungeons': 'dungeons', - 'pedestal': 'pedestal', - 'triforce-hunt': 'triforcehunt' - }[goal] + if goal is not None: + ret.goal = {'ganon': 'ganon', + 'fast_ganon': 'crystals', + 'dungeons': 'dungeons', + 'pedestal': 'pedestal', + 'triforce-hunt': 'triforcehunt' + }[goal] ret.openpyramid = goal == 'fast_ganon' if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False ret.crystals_gt = get_choice('tower_open') ret.crystals_ganon = get_choice('ganon_open') - - if ret.goal == 'triforcehunt': - goal_min = get_choice_default('triforce_goal_min', default=20) - goal_max = get_choice_default('triforce_goal_max', default=20) - pool_min = get_choice_default('triforce_pool_min', default=30) - pool_max = get_choice_default('triforce_pool_max', default=30) - ret.triforce_goal = random.randint(int(goal_min), int(goal_max)) - min_diff = get_choice_default('triforce_min_difference', default=10) - ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max)) + + goal_min = get_choice_default('triforce_goal_min', default=20) + goal_max = get_choice_default('triforce_goal_max', default=20) + pool_min = get_choice_default('triforce_pool_min', default=30) + pool_max = get_choice_default('triforce_pool_max', default=30) + ret.triforce_goal = random.randint(int(goal_min), int(goal_max)) + min_diff = get_choice_default('triforce_min_difference', default=10) + ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max)) + ret.mode = get_choice('world_state') if ret.mode == 'retro': ret.mode = 'open' @@ -193,11 +195,13 @@ def roll_settings(weights): ret.hints = get_choice('hints') == 'on' - ret.swords = {'randomized': 'random', - 'assured': 'assured', - 'vanilla': 'vanilla', - 'swordless': 'swordless' - }[get_choice('weapons')] + swords = get_choice('weapons') + if swords is not None: + ret.swords = {'randomized': 'random', + 'assured': 'assured', + 'vanilla': 'vanilla', + 'swordless': 'swordless' + }[swords] ret.difficulty = get_choice('item_pool') From 1b1292f6b8f5c05ce0a3511dbcad42a872adb50d Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 23:29:06 +0100 Subject: [PATCH 4/5] ROM fixes --- Rom.py | 2 +- asm/doorrando.asm | 1 + asm/doortables.asm | 2 ++ asm/drhooks.asm | 3 +++ asm/gfx.asm | 10 ++++++++++ asm/normal.asm | 15 ++++++++++----- asm/scroll.asm | 6 +++++- data/base2current.bps | Bin 136114 -> 136201 bytes 8 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Rom.py b/Rom.py index fad83d84..1153da24 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '11daec4f3e1afc96cd044585dfba9df8' +RANDOMIZERBASEHASH = 'bcce69ecfff6c169371afc84193c0402' class JsonRom(object): diff --git a/asm/doorrando.asm b/asm/doorrando.asm index 807095c7..8cceeba0 100644 --- a/asm/doorrando.asm +++ b/asm/doorrando.asm @@ -9,6 +9,7 @@ ; Normal doors use $FE to store the trap door indicator ; Normal doors use $045e to store Y coordinate when transitioning to in-room stairs ; Normal doors use $045f to determine the order in which supertile quadrants are drawn +; Straight stairs use $046d to store X coordinate on animation start ; Spiral doors use $045e to store stair type ; Gfx uses $b1 to for sub-sub-sub-module thing diff --git a/asm/doortables.asm b/asm/doortables.asm index eae16430..90678ca3 100644 --- a/asm/doortables.asm +++ b/asm/doortables.asm @@ -681,6 +681,8 @@ db $00,$07,$20,$20,$07,$07,$07,$07,$07,$20,$20,$07,$20,$20,$20,$20 db $07,$07,$02,$02,$02,$02,$07,$07,$07,$20,$20,$07,$20,$20,$20,$07 ;27f300 +DungeonTilesets: +db $04,$04,$05,$12,$04,$08,$07,$0C,$09,$0B,$05,$0A,$0D,$0E,$06,$06 ; ;org $27ff00 diff --git a/asm/drhooks.asm b/asm/drhooks.asm index 1d3b485b..f067dad4 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -76,6 +76,9 @@ nop : jsl OverridePaletteHeader org $02817e ; Bank02.asm : 414 (LDA $02811E, X) jsl FixAnimatedTiles +org $0aef43 ; UnderworldMap_RecoverGFX +jsl FixCloseDungeonMap + org $028a06 ; Bank02.asm : 1941 Dungeon_ResetTorchBackgroundAndPlayer JSL FixWallmasterLamp diff --git a/asm/gfx.asm b/asm/gfx.asm index b22fba62..94cb8848 100644 --- a/asm/gfx.asm +++ b/asm/gfx.asm @@ -45,6 +45,16 @@ FixAnimatedTiles: + LDA $02802E, X ; what we wrote over RTL +FixCloseDungeonMap: + LDA.l DRMode : CMP #$02 : BNE .vanilla + LDA $040C : BMI .vanilla + LSR : TAX + LDA.l DungeonTilesets,x + RTL + .vanilla + LDA $7EC20E + RTL + FixWallmasterLamp: ORA $0458 STY $1C : STA $1D : RTL ; what we wrote over diff --git a/asm/normal.asm b/asm/normal.asm index 3bdf9622..13323d88 100644 --- a/asm/normal.asm +++ b/asm/normal.asm @@ -150,15 +150,14 @@ LoadRoomVert: .notEdge lda $01 : and #$03 : cmp #$03 : bne .normal jsr ScrollToInroomStairs + stz $046d bra .end .normal ldy #$01 : jsr ShiftVariablesMainDir jsr PrepScrollToNormal .scroll - lda $01 : and #$40 : pha + lda $01 : and #$40 : sta $046d jsr ScrollX - pla : beq .end - ldy #$00 : jsr ApplyScroll .end plb ; restore db register rts @@ -291,6 +290,11 @@ StraightStairsAdj: stx $0464 : sty $012e ; what we wrote over lda.l DRMode : beq + lda $045e : bne .toInroom + lda $046d : beq .noScroll + sta $22 + ldy #$00 : jsr ApplyScroll + stz $046d + .noScroll jsr GetTileAttribute : tax lda $11 : cmp #$12 : beq .goingNorth lda $a2 : cmp #$51 : bne ++ @@ -338,9 +342,10 @@ db $d0, $f6, $10, $1a, $f0, $00 StraightStairsFix: { + pha lda.l DRMode : bne + - !add $20 : sta $20 ;what we wrote over - + rtl + pla : !add $20 : sta $20 : rtl ;what we wrote over + + pla : rtl } StraightStairLayerFix: diff --git a/asm/scroll.asm b/asm/scroll.asm index f66918c8..435b5c98 100644 --- a/asm/scroll.asm +++ b/asm/scroll.asm @@ -168,7 +168,11 @@ ScrollX: ;change the X offset variables pla : sta $00 sep #$30 - lda $04 : sta $22 + lda $04 : ldx $046d : bne .straight + sta $22 : bra + + .straight + sta $046d ; set X position later + + lda $00 : sta $23 : sta $0609 : sta $060d lda $01 : sta $a9 lda $0e : asl : ora $ac : sta $ac diff --git a/data/base2current.bps b/data/base2current.bps index a0d85faa0dc758ea3e0d3f04179760dc1e401269..7d88566a4996c6ae95d21586ca043435130550ef 100644 GIT binary patch delta 2460 zcmW+$dsGuw9-cdyJO~Mdpcr0t7}RNeW~mRXtfkaNMAZ7MMWpE#TiWQctMnnYa3^8F z2q78nh5=GccuX}=1dLm?iv?}Fg`Tp;-PInqwY9QPiLX&X)YIw?{bzoU@80izXYTKQ z#}2FPM^s%IU`bEq3q?i!Zt89|9SWI~p_{6zrXfJhY0pD0L>V0P*7AC4xr6QkX48=U z{8z0cyzhsV5LRYnugLFJum{n8yNmIM`{6^y-tZ7phaheFiuYP!JYpiZ7^ z)xh6jB1Bj@>Tx9-P1C^aSZin7>-(l zG_p+aZ?sWXF=JIVy~58?tz~rR2YX8eZE|x|v{d}cQ46GiNy?r@k7WzMlE8doF8~(; z&GLmf_!@nuya+C#qpG|JT{ZosKs`J8tEk!40YljH0E`53)h_|CD{w4)9thJh4(do1 zjXeom)qEoZFQX1!I%p2u(%pC(Yz%zAbTa^E^oM0Rz#J%9_VHi9jlj%~hf7M&GXgds z3#!R-XJOY$)(2lG6nuy1f4&M8Ebha|-xvWHp*XEo(f34D3V^h7P%eej92sweGIEJc z!qcKmR4-bELO*Ufsx%1?#kd&?zd zJ1YdAF>)X>s4lotaMeGZ{h1vyOI#*C9A%BH#ODLVjbwu~^ux#+b5gDzq8aP-u)DA$ zp9mIo>>@-pOQD73m!vbv%eFQlYCtb02+afQgSxY%-{95Cf7QZCr1!RshOt+$pjz-r zDB)iW!&`6lVIsKJJ8Gk|_^kfz=!0M4OMkJA&4qc1XK*uiKh6-78oaNI6S1sL9MVB$ zA&Q+~Eroo_oL`${!YxZL^#!n?Y=>KnC=6<{Jju{OuxkrzR)#~j<*1}lR@3LVe3DOy zVS|&E^Iz5bpd)AsxM{!WG5Wpy&^WWN;Qr3?(F$&WnPc;@MH~{Lx)RkYFh&lg2~9*knhT z!l8B6qIID+Rcbq*#AWjvj`Vs?$I`9G35;vkNC_YJsh55*g>&W5FbfCIGJsfP#vq32$nhl{2M8y zfLvNh-aSzKs2y40@JIQ?cj8;tBj!fNVl~H7 z{xKLXy`oGh{YR32f+bsW<@F4X_SB%T*Kugi`TIeSE(eE>oP$OMO84@+(Zd@lAOp?4 z83&f3l{b?$dk)kKc?o1ij=ZZ-keV--j)P^^SHu5|g zy-6vwEsV^QhoWw!l*XDL49Z#gsUERSkT)6>adC}timRlV$1@(Veoz~^Z z**wOGFjzCw$618#;QE%#QawDhR$y~~LNhyWZ)$D`=R03c)I(>Jn;fVb>9%-gv~mUA zBV88n+k_tSGF>!eqyBq%Cmsz2qOA~uN4@h+5cj@Y^|Pi!LztA=ZN1n%+R_ECpU9akK@Q6oT+Am`S;ehldbfc-n7KJ z!OJcwkL5_cYZ4Y@tglS*#ne-$2_p=K2?Prye}r0r@a`{nliOU9OL{kT2UeYIoLpd# z79dR%E2_PVe3Tm+Bm*>~(e^DTFTCXvWRm%r$$c(?ByBEZIz|qn>N|-U3rsU5dkA}5Q_^+sgN@1I*pOokyD-DTff8(kFM$f`bBrYBh`1 zWlK`wWpf{fiBCIuCYiT7&LSAgAE^Hh!APEuG0@CFB);V*3WW z=VP?#MSDF4f^_Hdd+jFvr)h7ZHDfTUk#{!pMZ4gc)~`!Wn?$k^{W#`|_Sd5QjG)AV zvK)V{KkDhu^l-$CPbZVyw4wBmZu&^CS)}V%#Ps+3$7e{fMY~vRQjzbYzVVrQMXKmo zW3xy0?yt?-`H4e8cA|;#jObt7o_BN&oJ3i~qYTJs__tBc{keF29V)(`2!>JJ{k5~{ z&%48=VeT3$iStUIN4w!mCc8b?hjkueu*09$7n@n1qnhAT%t$veH{unAhdpbWrVV<3%J;$>hW@}qs#7P{2!--AQ}Jw delta 2460 zcmX9;dsGuw8lRa=9)!dY&=@f4I8eu^RF)P=wXI0CrHGAS0`q{=g7`d0z+gYVRNPFqVxIZNiimoSs==PHUn zC&+4_*<;-R>>rj>xRoVqpbOI#6qivrV9C7CTR!n%z3s9yJHb7q&?&go5=g$E^=6m=UMWRjk?(Ubi*jT zsG?ou3s5b28SR1_B;`rE8frz*MIJ4qM*eHJms2So7by`pzq!cSVn9S<^WlVK5sHTv z;d@cEDby@|7DJE1Z{%O0Ct$lGZ^|{6`h+LtlQ%_`tdM5-qj}o~qAQeNUi#51x8B~vI!12W>Z^0x10 zfyPotVaFCG05&M#n*`eHxGY;!5fomsx@S z|Ddd-j@fy{QAQ&$-pU;)NB~}hZ))vE{9Ms)nq@G30apyaAIMGIVddrku@~0YsBPh} zCZf#0k$*EdoB4scWfqC0a7MU(@D(go3XctDqnYr>!PW0ln_~e?%8dmBZ=BhNM>Y~y zZLPdE94i?3rtrE*%q1eI_vaq|RShPQo?A8w#NR+7NcyKX@Zn@u!23O z_DA2I2EvC?r!*LY0^BtGHex1L9tk5tQdlk+!lnLbVWrWN zR{Eyj+NduVxhyJoYB@LDTYO6bWN^udLAO0w3;dhsYXML42$RT0$yl}HC_FH-Td}`_ zQ?t!`SvWMZPz~)cqX8D^y>?=v0?xVfT&V(`0UiYq;+IOkHJg!%8o{zn12RF)$dvkm zR;D$8I?g**Lx!z%9356awd_NFhm3!oO9fA^ap*@?~~IJnHQAl z3kZe?-q9D33<>mb?-6@!@Cj!+mJFu;Srd;WR_Y7j_jgpf*;V2xf{}}ApIt?KQ&IG! z4eq4fcMYf%&b;fuQg*?!cQY4%?PSQ{D2NuPEzZS||C$pVXNYFA)JtQ~wSj zbCGq;v8A!#_!^$sd>y9wALP61qq+8{X2t?Xqlc)i9z199CAGNn&kc51{LkaDfXmgy z0Y>}nNfQeuly12dD;P#QqdX}f?w!62HYdO4Xi^*(0$OWS zTHrpI47_IJ1Zo;UxR)-}JoA7%{MSEz68el2$SEEn;vs|aa&aSO;@cTD$f+(LuAOMW zh!-G(@G5SlVcd(G1xXM=xy3uu#;!8>%@lJt(#J@Kx)1g-^2rp3MP0PQVLc<|apG&| zP`9^_iH1$A%52p5-kbvqACfZDoaumxgU*M9atmX-|zybpm=$sl#vB2#e9+>0Q>JO@W7a#q#>K|ELCZGk{T6u}vztBfB* zZmTD#Km<#B;%EtRh8sVy&h9$_-_5mq5i~-zzxZ=o3U~c4h0rkyv~O{aCT`z5;NzB0 zOS)48;w?x#a=x~|78cXI9EnJB_SXir^V&Bn>$`$6^H`;hovLGJ>Db#khhGYkrZ-_o z5JB{%_m5KgQl*DF)ngVY?+RUifACR~7@Mgyp;1AsgxJ_qu|&GyTWzyzdWvha-agIB zh+_EMSZ3ULk53a*?-GBuoP(KwR&h#LGqw;L;^4)xndnFG+p#tCKj=Oeo!#2gFnE+dZb2;1LYvT*29FqE&ODPAACG4TOg6W~^@nm^y zHdsn@9=N^bu(wma;!bVehv!4z{_*})b*b%=j^4V9-lYO-c6V-%L*t&7N9A?WD?Tmk lJhU8jPs8H&a_UW}0b9DJbHOI`tBZ;+eo07s)1UnQ{{Ucq8Pxy) From 90f7016f497ca0d74a8937bc201c19d228fb082f Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 2 Nov 2021 15:25:34 -0600 Subject: [PATCH 5/5] Update release notes and version Remove tileset fix (I like the other more visually) --- Main.py | 2 +- RELEASENOTES.md | 8 +++++++- Rom.py | 2 +- asm/drhooks.asm | 3 --- asm/gfx.asm | 10 ---------- data/base2current.bps | Bin 136201 -> 136415 bytes 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Main.py b/Main.py index e13eda0d..453e33e8 100644 --- a/Main.py +++ b/Main.py @@ -29,7 +29,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names -__version__ = '0.5.1.4-u' +__version__ = '0.5.1.5-u' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 75c18e0d..c1a7a62c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -19,7 +19,13 @@ CLI: ```--bombbag``` * Fix for hard pool capacity upgrades missing * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable * Bug fix for retro + enemizer and arrows appearing under pots - * Add bombbag and shufflelinks to settings code + * Added bombbag and shufflelinks to settings code + * Catobat fixes: + * Fairy refills in spoiler + * Subweights support in mystery + * More defaults for mystery weights + * Less camera jank for straight stair transitions + * Bug with Straight stairs with vanilla doors where Link's walking animation stopped early is fixed * 0.5.1.4 * Revert quadrant glitch fix for baserom * Fix for inverted diff --git a/Rom.py b/Rom.py index f0484b02..f3b3cb68 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'bcce69ecfff6c169371afc84193c0402' +RANDOMIZERBASEHASH = '2cfa164d4b66a15406f53ca4750ef59a' class JsonRom(object): diff --git a/asm/drhooks.asm b/asm/drhooks.asm index f067dad4..1d3b485b 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -76,9 +76,6 @@ nop : jsl OverridePaletteHeader org $02817e ; Bank02.asm : 414 (LDA $02811E, X) jsl FixAnimatedTiles -org $0aef43 ; UnderworldMap_RecoverGFX -jsl FixCloseDungeonMap - org $028a06 ; Bank02.asm : 1941 Dungeon_ResetTorchBackgroundAndPlayer JSL FixWallmasterLamp diff --git a/asm/gfx.asm b/asm/gfx.asm index 94cb8848..b22fba62 100644 --- a/asm/gfx.asm +++ b/asm/gfx.asm @@ -45,16 +45,6 @@ FixAnimatedTiles: + LDA $02802E, X ; what we wrote over RTL -FixCloseDungeonMap: - LDA.l DRMode : CMP #$02 : BNE .vanilla - LDA $040C : BMI .vanilla - LSR : TAX - LDA.l DungeonTilesets,x - RTL - .vanilla - LDA $7EC20E - RTL - FixWallmasterLamp: ORA $0458 STY $1C : STA $1D : RTL ; what we wrote over diff --git a/data/base2current.bps b/data/base2current.bps index 7d88566a4996c6ae95d21586ca043435130550ef..328d0f8196c9f52c4e8bb095e2ff83a9157dc2ea 100644 GIT binary patch delta 9649 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

$LjCK)|i1Hr6i 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 QYsU+Z_FC}AysV!81Gzb&;{X5v delta 9515 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