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
13 changes: 13 additions & 0 deletions APRandomizerMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -604,14 +604,27 @@ void Cutscene_Play(On.Cutscene.orig_Play orig, Cutscene self)
}
}
}

if (ArchipelagoClient.EventsICareAbout.Contains(eventName) && ArchipelagoClient.Authenticated)
{
ArchipelagoClient.Session.DataStorage[Scope.Slot, "Events"] +=
new List<string> { eventName };
}

if (eventName.EndsWith("PortalOpeningCutscene"))
{
self.onDone += OnAnyPortalOpeningCutsceneDone;
}

orig(self);
}

private static void OnAnyPortalOpeningCutsceneDone(Cutscene cutscene)
{
cutscene.onDone -= OnAnyPortalOpeningCutsceneDone;
ArchipelagoClient.ReconciliateUnlockedPortals();
}

void PhantomIntro_OnEnterRoom(On.PhantomIntroCutscene.orig_OnEnterRoom orig, PhantomIntroCutscene self,
bool teleportedInRoom)
{
Expand Down
30 changes: 29 additions & 1 deletion Archipelago/ArchipelagoClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,34 @@ public static void SyncEvents()
}
}

public static List<string> AddVisitedEntrance(string entrance)
{
if (!Authenticated) return [];

var visitedEntrances = Session.DataStorage[Scope.Slot, "VisitedEntrances"].To<List<string>>();
if (visitedEntrances.Contains(entrance)) return visitedEntrances;

Console.WriteLine("Adding visited entrance: " + entrance);
visitedEntrances.Add(entrance);
visitedEntrances.Sort();
Session.DataStorage[Scope.Slot, "VisitedEntrances"] = visitedEntrances;

return visitedEntrances;
}

public static void ReconciliateUnlockedPortals()
{
if (!Authenticated) return;

var unlockedPortals = RandoPortalManager.UnlockedPortals;
unlockedPortals.UnionWith(Session.DataStorage[Scope.Slot, "UnlockedPortals"].To<List<string>>());

var unlockedPortalsList = unlockedPortals.ToList();
unlockedPortalsList.Sort();
Console.WriteLine($"Updating unlocked portals with Data Storage. Unlocked portals are {string.Join(", ", [.. unlockedPortalsList])}");
Session.DataStorage[Scope.Slot, "UnlockedPortals"] = unlockedPortalsList;
}

private static void OnItemReceived(ReceivedItemsHelper helper)
{
var itemToUnlock = helper.DequeueItem();
Expand Down Expand Up @@ -558,4 +586,4 @@ public static void ClearMessages()
DialogQueue = new Queue();
}
}
}
}
4 changes: 3 additions & 1 deletion Archipelago/ItemsAndLocationsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,8 @@ public static void ReSync()
{
Synced = true;
ArchipelagoClient.SyncEvents();
ArchipelagoClient.ReconciliateUnlockedPortals();

var receivedItems = new Dictionary<long, int>();

for (int i = 0; i < ArchipelagoClient.ServerData.Index; i++)
Expand All @@ -565,4 +567,4 @@ public static void ReSync()
}
}
}
}
}
35 changes: 34 additions & 1 deletion GameOverrideManagers/RandoLevelManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class RandoLevelManager

// ReSharper disable once UnassignedField.Global
public static Dictionary<string, LevelConstants.RandoLevel> RandoLevelMapping;
public static List<string> VisitedEntrances = [];

public static void LoadLevel(On.LevelManager.orig_LoadLevel orig, LevelManager self, LevelLoadingInfo levelInfo)
{
Expand Down Expand Up @@ -119,6 +120,32 @@ public static LevelConstants.RandoLevel FindEntrance()
}
}
Console.WriteLine(entrance);
string sourceExit;
if (LevelConstants.SpecialConnectionSourceExits.TryGetValue(entrance, out var specialSource))
{
sourceExit = specialSource + " exit";
}
else if (entrance.Equals("Corrupted Future"))
{
sourceExit = "HQ - Artificer's Portal";
}
else if (entrance.Equals("Tower of Time - Left"))
{
sourceExit = "HQ - Artificer's Challenge";
}
else if (entrance.Equals("Glacial Peak - Left"))
{
sourceExit = "Elemental Skylands - Right exit";
}
else if (!LevelConstants.TransitionToEntranceName.TryGetValue(new LevelConstants.Transition(currentLevel, lastLevel), out sourceExit))
{
sourceExit = entrance;
}
else
{
sourceExit = sourceExit + " exit";
}
AddVisitedEntrance(sourceExit);
return RandoLevelMapping[entrance];
} catch (Exception e){ Console.WriteLine(e);}
return new LevelConstants.RandoLevel(ELevel.NONE, new Vector3());
Expand Down Expand Up @@ -291,4 +318,10 @@ public static void CleanupAfterTeleport()
Manager<UIManager>.Instance.CloseAllScreensOfType<SavingScreen>(false);
Manager<UIManager>.Instance.CloseAllScreensOfType<LoadingAnimation>(false);
}
}

public static void AddVisitedEntrance(string entrance)
{
if (VisitedEntrances.Contains(entrance)) return;
VisitedEntrances = ArchipelagoClient.AddVisitedEntrance(entrance);
}
}
36 changes: 34 additions & 2 deletions GameOverrideManagers/RandoPortalManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,37 @@ public Portal(int portalWarp)
};

private static readonly List<string> AccessedStartingPortals = new List<string>();

public static HashSet<string> UnlockedPortals
{
get
{
var unlockedPortals = new HashSet<string>();

var progressManager = Manager<ProgressionManager>.Instance;
if (progressManager.cutscenesPlayed.Contains("PortalOpeningCutscene"))
{
unlockedPortals.Add("Autumn Hills Portal");
unlockedPortals.Add("Howling Grotto Portal");
unlockedPortals.Add("Glacial Peak Portal");
}
if (progressManager.cutscenesPlayed.Contains("SunkenShrinePortalOpeningCutscene"))
{
unlockedPortals.Add("Sunken Shrine Portal");
}
if (progressManager.cutscenesPlayed.Contains("SearingCragsPortalOpeningCutscene"))
{
unlockedPortals.Add("Searing Crags Portal");
}
if (progressManager.cutscenesPlayed.Contains("RiviereTurquoisePortalOpeningCutscene"))
{
unlockedPortals.Add("Riviere Turquoise Portal");
}

return unlockedPortals;
}
}

public static bool ShouldPortalBeOpen(string portal)
{
return AccessedStartingPortals.Contains(portal);
Expand Down Expand Up @@ -365,7 +396,7 @@ public static void OpenPortalEvent(On.PortalOpeningCutscene.orig_OnOpenPortalEve
break;
}
}

private static LevelConstants.RandoLevel GetPortalExit(string enteredPortal)
{
Console.WriteLine($"getting portal. entered {enteredPortal}");
Expand Down Expand Up @@ -416,6 +447,7 @@ public static void Teleport()
return;
}

RandoLevelManager.AddVisitedEntrance("HQ - " + portal.Replace("- ", ""));
RandoLevelManager.TeleportInArea(newLevel.LevelName, newLevel.PlayerPos, newLevel.Dimension);
}
catch (Exception e)
Expand All @@ -436,4 +468,4 @@ public static void LeaveHQ(On.TotHQ.orig_LeaveToLevel orig, TotHQ self, bool pla
orig(self, playLevelMusic, loadingNewLevel);
}
}
}
}
13 changes: 13 additions & 0 deletions Utils/Constants/LevelConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,19 @@ public static Transition TransitionFromName(string name)
"Quillshroom Marsh - Right", "Searing Crags - Left"
};

public static readonly Dictionary<string, string> SpecialConnectionSourceExits =
new Dictionary<string, string>
{
{ "Howling Grotto - Right", "Quillshroom Marsh - Top Left" },
{ "Howling Grotto - Top", "Quillshroom Marsh - Bottom Left" },
{ "Quillshroom Marsh - Bottom Left", "Howling Grotto - Top" },
{ "Quillshroom Marsh - Top Left", "Howling Grotto - Right" },
{ "Quillshroom Marsh - Top Right", "Searing Crags - Left" },
{ "Quillshroom Marsh - Bottom Right", "Searing Crags - Bottom" },
{ "Searing Crags - Left", "Quillshroom Marsh - Top Right" },
{ "Searing Crags - Bottom", "Quillshroom Marsh - Bottom Right" },
};

public static readonly List<string> TransitionNames = new List<string>
{
"Ninja Village - Right",
Expand Down
49 changes: 28 additions & 21 deletions Utils/RandomizerStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,52 +99,59 @@ public static void InitializeSeed()
Instance.SkipMusicBox = !Convert.ToBoolean(slotData["music_box"]);
RandoShopManager.ShopPrices = ((JObject)slotData["shop"]).ToObject<Dictionary<EShopUpgradeID, int>>();
RandoShopManager.FigurePrices = ((JObject)slotData["figures"]).ToObject<Dictionary<EFigurine, int>>();

if (slotData.TryGetValue("starting_portals", out var portals))
{
var startingPortals = ((JArray)portals).ToObject<List<string>>();
RandoPortalManager.StartingPortals = [];
foreach (var portal in startingPortals)
{
Console.WriteLine(portal);
Console.WriteLine($"Starting portal: {portal}");

@alwaysintreble alwaysintreble Jun 13, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we instead have this write

Starting portals:
	Searing Crags
	Howling Grotto

etc

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can do that

RandoPortalManager.StartingPortals.Add(portal);
}
}
else
{
RandoPortalManager.StartingPortals =
[
"AutumnHillsPortal",
"RiviereTurquoisePortal",
"HowlingGrottoPortal",
"SunkenShrinePortal",
"SearingCragsPortal",
"GlacialPeakPortal"
];
}

var portalExits = ((JArray)slotData["portal_exits"]).ToObject<List<int>>();
if (slotData.TryGetValue("portal_exits", out var portalExitsJson))
{
var portalExits = ((JArray)portalExitsJson).ToObject<List<int>>();
RandoPortalManager.PortalMapping = [];
foreach (var portalExit in portalExits)
{
RandoPortalManager.PortalMapping.Add(new RandoPortalManager.Portal(portalExit));
}
}

if (!slotData.TryGetValue("transitions", out var transitions)) return;
RandoLevelManager.RandoLevelMapping =
new Dictionary<string, LevelConstants.RandoLevel>();
if (slotData.TryGetValue("transitions", out var transitions))
{
var transitionPairs = ((JArray)transitions).ToObject<List<List<int>>>();
if (transitionPairs.Count == 0) RandoLevelManager.RandoLevelMapping = null;
if (transitionPairs.Count == 0)
{
RandoLevelManager.RandoLevelMapping = null;
}
else
{
RandoLevelManager.RandoLevelMapping = [];
foreach (var pairing in transitionPairs)
{
var orig = LevelConstants.TransitionNames[pairing[0]];
var replacement =
LevelConstants.EntranceNameToRandoLevel[LevelConstants.TransitionNames[pairing[1]]];
var replacement = LevelConstants.EntranceNameToRandoLevel[LevelConstants.TransitionNames[pairing[1]]];
RandoLevelManager.RandoLevelMapping[orig] = replacement;
Console.WriteLine($"{orig}: {LevelConstants.TransitionNames[pairing[1]]}");
Console.WriteLine($"Setting transition from {orig} to {LevelConstants.TransitionNames[pairing[1]]}");
}
}
}
else
{
RandoPortalManager.StartingPortals =
[
"AutumnHillsPortal",
"RiviereTurquoisePortal",
"HowlingGrottoPortal",
"SunkenShrinePortal",
"SearingCragsPortal",
"GlacialPeakPortal"
];
}

if (ArchipelagoClient.Session.Locations.AllLocations.Any(location =>
ItemsAndLocationsHandler.IDtoLocationsLookup.TryGetValue(location, out var loc)
Expand Down