Bringing in Unstable2 changes

This commit is contained in:
aerinon
2021-02-18 13:19:08 -07:00
13 changed files with 118 additions and 30 deletions

View File

@@ -148,7 +148,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:

View File

@@ -2418,7 +2418,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'),

View File

@@ -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),
@@ -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)
world.get_door('Swamp Lobby S', player).standard_restricted = True # key-drop note (todo)

View File

@@ -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:

View File

@@ -401,12 +401,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)

View File

@@ -122,15 +122,32 @@ Added to CLI only now.
The Mystery.py file has been updated for those who like to use that for generating games. Supports keydropshuffle,
shopsanity, and other settings that have been included.
## Experimental Item Counter
New item counter modified to show total
# Bug Fixes
* 0.3.1.1-u
* 0.3.1.0-u
* Shopsanity introduced
* Minor fix to Standard generation
* 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)
* 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.
* Minor fix to Standard generation
* Fix for In-Room Stairs with Trap Doors
* Key logic fix
* Fix for door gen re-start
* 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

View File

@@ -473,8 +473,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']),

4
Rom.py
View File

@@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '6a4096235f682b7e4e1a65f274c7037b'
RANDOMIZERBASEHASH = '0a34dc667a29125f09b10aeb1e06b83c'
class JsonRom(object):
@@ -942,8 +942,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):

View File

@@ -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.

View File

@@ -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

Binary file not shown.

View File

@@ -43,7 +43,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")

View File

@@ -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