Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RandomizerCore/Hyrule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3846,6 +3846,7 @@ private void ApplyAsmPatches(RandomizerProperties props, Assembler engine, Rando
rom.FixItemPickup(engine);
rom.FixMinibossGlitchyAppearance(engine);
rom.FixBossKillPaletteGlitch(engine);
rom.ThunderbirdEnterLeftFix(engine);
rom.FixBigBubbleSplit(engine, randomizedStats);
StatTracking(props, engine);
AddCredits(engine);
Expand Down
81 changes: 78 additions & 3 deletions RandomizerCore/ROM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,80 @@ bne @CopyLoop
""");
}

public void ThunderbirdEnterLeftFix(Assembler asm)
{
var a = asm.Module();
a.Code(/* lang=s */"""
.include "z2r.inc"
.import ElevatorBossFix

.segment "PRG5"

DrawThunderbird = $9ebf
ThunderbirdMainRoutineStart = $a359
ThunderbirdMainRoutine = $a36b
ThunderbirdNoRoutine = $a3bd

; Do a much finer scroll position check so we can get into position
; when entering from the right as well.
.org $94d1
.word ThunderbirdFixedScrollCheck

; When entering from the right, Thunderbird would be visible before the combat starts.
; While it's not a problem, it feels a bit jank, so lets not draw Thunderbird pre-battle.
.org $95a9
.word ConditionalDrawThunderbird


.org ThunderbirdMainRoutineStart
FREE_UNTIL ThunderbirdMainRoutine

.reloc
ThunderbirdFixedScrollCheck:
lda ScrollLeftPage
cmp #$01
bne @DontSpawn

lda ScrollLeftX
cmp #$04 ; need at least 3 pixel margin so dash speed can't skip the trigger point
bcs @DontSpawn

lda ScrollFrozen
bne @TimerRunning
jsr ElevatorBossFix ; will freeze the scrolling (and more)
lda #$90
sta $0504,x ; set timer for Thunderbird to begin

@TimerRunning:
lda ScrollLeftX
beq @NoScroll

lda FrameCounter
and #$01
bne @NoScroll ; slow down screen scroll to every other frame

lda ScrollLeftX
sbc #$00 ; subtracts 1 because carry is cleared by cmp
bcs @SetScrollX
lda #$00 ; clamp to 0
@SetScrollX:
sta ScrollLeftX
sta ScrollPosShadow
@NoScroll:
jmp ThunderbirdMainRoutine
@DontSpawn:
jmp ThunderbirdNoRoutine

.reloc
ConditionalDrawThunderbird:
lda ScrollFrozen
beq @NotInBattle
jmp DrawThunderbird
@NotInBattle:
rts
""");
}

public void BuffCarrock(Assembler a)
{
a.Module().Code(Util.ReadResource("Z2Randomizer.RandomizerCore.Asm.BuffCarock.s"), "buff_carock.s");
Expand Down Expand Up @@ -2166,9 +2240,10 @@ jsr ElevatorBossFix
jsr ElevatorBossFix

; Screen lock tbird set at bank 5 A363 (0x16373)
.segment "PRG5"
.org $a363
jsr ElevatorBossFix
; ThunderbirdEnterLeftFix does this call now
;.segment "PRG5"
;.org $a363
; jsr ElevatorBossFix

.segment "PRG7"

Expand Down
3 changes: 1 addition & 2 deletions RandomizerCore/Sidescroll/ChaosPalaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ internal override async Task<Palace> GeneratePalace(RandomizerProperties props,
};

//Chaos palaces do not check for inescapable drops. They are inherently insane and not remotely beginner-friendly.

palace.IsValid = palace.AllReachable(true);
palace.IsValid = palace.AllReachable(allowBacktracking: true, allowBossEnterLeft: palace.Number == 7);
return palace;
}
}
26 changes: 16 additions & 10 deletions RandomizerCore/Sidescroll/Palace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,20 @@ private void CheckSpecialPaths(Room r)
}
}

public IEnumerable<Room> GetReachableRooms(bool allowBacktracking = false)
public IEnumerable<Room> GetReachableRooms(bool allowBacktracking = false, bool allowBossEnterLeft = false)
{
if(Entrance == null)
{
throw new Exception("Palace Entrance is missing");
}
foreach (Room r in AllRooms)
if (!allowBossEnterLeft)
{
if (r.HasBoss && CanEnterBossFromLeft(r))
foreach (Room r in AllRooms)
{
return [Entrance];
if (r.HasBoss && CanEnterBossFromLeft(r))
{
return [Entrance];
}
}
}
HashSet<Room> reachedRooms = [];
Expand All @@ -117,13 +120,16 @@ public IEnumerable<Room> GetReachableRooms(bool allowBacktracking = false)
while (roomsToCheck.Count > 0)
{
var (room, originDirection) = roomsToCheck.Pop();

//For required thunderbird, you can't path backwards into tbird room
if ((Number == 7 && room.IsThunderBirdRoom)
|| (Number < 7 && room.IsBossRoom))
if (!allowBossEnterLeft)
{
if (originDirection == Direction.EAST)
if ((Number == 7 && room.IsThunderBirdRoom) || (Number < 7 && room.IsBossRoom))
{
return [Entrance];
if (originDirection == Direction.EAST)
{
return [Entrance];
}
}
}

Expand Down Expand Up @@ -244,9 +250,9 @@ public static bool BossRoomMinDistanceShape(Dictionary<Coord, RoomExitType> shap
return false; // Boss room not found?
}

public bool AllReachable(bool allowBacktracking = false)
public bool AllReachable(bool allowBacktracking = false, bool allowBossEnterLeft = false)
{
var reachableRooms = GetReachableRooms(allowBacktracking);
var reachableRooms = GetReachableRooms(allowBacktracking: allowBacktracking, allowBossEnterLeft: allowBossEnterLeft);
return AllRooms.All(i => reachableRooms.Contains(i));
}

Expand Down
13 changes: 5 additions & 8 deletions RandomizerCore/Sidescroll/ReconstructedLoopyPalaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,6 @@ internal override Task<Palace> GeneratePalace(RandomizerProperties props, RoomPo

public override void Consolidate(List<Room> openRooms, RandomizerProperties props, int palaceNumber)
{
if (palaceNumber == 7 && !props.RequireTbird && !props.RemoveTbird)
{
// Connecting rooms at maximum distance increases the likelihood that Thunderbird
// will be required by too much. (Dark Link is the only dead-end possible.)
// Lets use old Reconstructed loops for this case.
base.Consolidate(openRooms, props, palaceNumber);
return;
}
Room[] openCopy = new Room[openRooms.Count];
openRooms.CopyTo(openCopy); // shallow copy
foreach (Room r2 in openCopy)
Expand All @@ -43,4 +35,9 @@ public override void Consolidate(List<Room> openRooms, RandomizerProperties prop
}
}
}

public override bool AllReachable(Palace palace)
{
return palace.AllReachable(allowBossEnterLeft: palace.Number == 7);
}
}
7 changes: 6 additions & 1 deletion RandomizerCore/Sidescroll/ReconstructedPalaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ internal override async Task<Palace> GeneratePalace(RandomizerProperties props,
palace.ResetRooms();
count++;
palace.ShuffleRooms(r);
reachable = palace.AllReachable();
reachable = AllReachable(palace);
tries++;
logger.Debug("Palace room shuffle attempt #" + tries);
}
Expand Down Expand Up @@ -343,6 +343,11 @@ public virtual void Consolidate(List<Room> openRooms, RandomizerProperties props
}
}

public virtual bool AllReachable(Palace palace)
{
return palace.AllReachable(allowBossEnterLeft: false);
}

/// <summary>
/// Attach the provided room to the open room if there is a compatable pair of exits between the two rooms.
/// Rooms attempt to use the exits in the following order (from the perspective of open):
Expand Down