diff --git a/src/TrackerCouncil.Smz3.Data/Configuration/ConfigTypes/ItemData.cs b/src/TrackerCouncil.Smz3.Data/Configuration/ConfigTypes/ItemData.cs
index df3d024bc..153674ff9 100644
--- a/src/TrackerCouncil.Smz3.Data/Configuration/ConfigTypes/ItemData.cs
+++ b/src/TrackerCouncil.Smz3.Data/Configuration/ConfigTypes/ItemData.cs
@@ -301,6 +301,7 @@ public bool IsJunk(Config? config)
/// configuration, assuming one is provided.
///
/// The randomizer configuration.
+ /// If the item is for the local player
///
/// true if the item is considered progression; otherwise, false.
///
@@ -308,10 +309,10 @@ public bool IsJunk(Config? config)
/// This method only considers the item's value on its own. Call TrackerBase.IsWorth(ItemData) to include
/// items that this item might logically lead to.
///
- public bool IsProgression(Config? config)
+ public bool IsProgression(Config? config, bool isLocalPlayerItem)
{
// Todo: We can add special logic like checking if it's one of the first two swords
- return InternalItemType.IsPossibleProgression(config?.ZeldaKeysanity == true, config?.MetroidKeysanity == true);
+ return InternalItemType.IsPossibleProgression(config?.ZeldaKeysanity == true, config?.MetroidKeysanity == true, isLocalPlayerItem);
}
///
diff --git a/src/TrackerCouncil.Smz3.Data/Options/Sprite.cs b/src/TrackerCouncil.Smz3.Data/Options/Sprite.cs
index 212b9342c..65039cac8 100644
--- a/src/TrackerCouncil.Smz3.Data/Options/Sprite.cs
+++ b/src/TrackerCouncil.Smz3.Data/Options/Sprite.cs
@@ -61,9 +61,9 @@ private Sprite(string name, SpriteType spriteType, bool isDefault, bool isRandom
[YamlIgnore]
public string Author { get; set; }
- public string FilePath { get; } = "";
+ public string FilePath { get; set; } = "";
- public SpriteType SpriteType { get; }
+ public SpriteType SpriteType { get; set; }
[YamlIgnore]
public string PreviewPath { get; set; }
diff --git a/src/TrackerCouncil.Smz3.Data/RandomizerDirectories.cs b/src/TrackerCouncil.Smz3.Data/RandomizerDirectories.cs
index 9c5c3fb70..e4c1893bb 100644
--- a/src/TrackerCouncil.Smz3.Data/RandomizerDirectories.cs
+++ b/src/TrackerCouncil.Smz3.Data/RandomizerDirectories.cs
@@ -67,6 +67,8 @@ public static string SpritePath
}
}
+ public static bool DeleteSprites => SpritePath == Path.Combine(AppContext.BaseDirectory, "Sprites");
+
public static string UserSpritePath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"SMZ3CasRandomizer", "Sprites");
@@ -105,4 +107,6 @@ public static string TrackerSpritePath
#endif
public static string TrackerSpriteInitialJsonFilePath => Path.Combine(TrackerSpritePath, "tracker-sprites.json");
+
+ public static bool DeleteTrackerSprites => SpritePath == Path.Combine(AppContext.BaseDirectory, "Sprites");
}
diff --git a/src/TrackerCouncil.Smz3.Data/Services/GitHubFileSynchronizerService.cs b/src/TrackerCouncil.Smz3.Data/Services/GitHubFileSynchronizerService.cs
index 239da47be..26392c9a9 100644
--- a/src/TrackerCouncil.Smz3.Data/Services/GitHubFileSynchronizerService.cs
+++ b/src/TrackerCouncil.Smz3.Data/Services/GitHubFileSynchronizerService.cs
@@ -62,6 +62,18 @@ public class GitHubFileDownloaderRequest
/// Timeout value for each individual request
///
public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(5);
+
+ ///
+ /// If any files that exist on the local computer but not on GitHub should be deleted
+ ///
+ public bool DeleteExtraFiles { get; set; }
+}
+
+public enum GitHubFileAction
+{
+ Nothing,
+ Download,
+ Delete
}
///
@@ -87,17 +99,12 @@ public class GitHubFileDetails
///
/// The hash of the file on GitHub to track if the file was previously downloaded
///
- public required string RemoteHash { get; set; }
+ public required string Hash { get; set; }
///
- /// If the file is found on the local computer
+ /// What needs to happen for the file
///
- public required bool FileExistsLocally { get; set; }
-
- ///
- /// If there is a difference in the file between the local computer and Github
- ///
- public required bool FileMatchesLocally { get; set; }
+ public required GitHubFileAction Action { get; set; }
///
/// The path to the file to save the GitHub hash to
@@ -132,6 +139,8 @@ public async Task> GetGitHubFileDetailsAsync(GitHubFileD
var previousHashes = GetPreviousHashes(request);
+ _logger.LogInformation("{Count} previous file hashes found", previousHashes.Count);
+
var fileList = new ConcurrentBag();
Parallel.ForEach(files, parallelOptions: new ParallelOptions { MaxDegreeOfParallelism = 4 },
@@ -140,15 +149,15 @@ public async Task> GetGitHubFileDetailsAsync(GitHubFileD
var localPath = ConvertToLocalPath(request, fileData.Key);
var currentHash = fileData.Value;
previousHashes.TryGetValue(localPath, out var prevHash);
+ var needToDownload = !File.Exists(localPath) || prevHash != currentHash;
fileList.Add(new GitHubFileDetails()
{
Path = fileData.Key,
LocalPath = localPath,
DownloadUrl = $"https://raw.githubusercontent.com/{request.RepoOwner}/{request.RepoName}/main/{fileData.Key}",
- RemoteHash = fileData.Value,
- FileExistsLocally = File.Exists(localPath),
- FileMatchesLocally = File.Exists(localPath) && prevHash == currentHash,
+ Hash = fileData.Value,
+ Action = needToDownload ? GitHubFileAction.Download : GitHubFileAction.Nothing,
HashPath = request.HashPath
});
});
@@ -159,21 +168,21 @@ public async Task> GetGitHubFileDetailsAsync(GitHubFileD
foreach (var file in Directory.EnumerateFiles(request.DestinationFolder, "*", SearchOption.AllDirectories).Where(x => !foundLocalFiles.Contains(x) && IsValidPath(request, x)))
{
+ previousHashes.TryGetValue(file, out var previousHash);
+
fileList.Add(new GitHubFileDetails()
{
Path = file,
LocalPath = file,
DownloadUrl = "",
- RemoteHash = "",
- FileExistsLocally = true,
- FileMatchesLocally = false,
+ Hash = previousHash ?? "",
+ Action = request.DeleteExtraFiles ? GitHubFileAction.Delete : GitHubFileAction.Nothing,
HashPath = request.HashPath
});
}
}
-
- return fileList.Where(x => !x.FileMatchesLocally).ToList();
+ return fileList.ToList();
}
public async Task SyncGitHubFilesAsync(GitHubFileDownloaderRequest request)
@@ -190,7 +199,7 @@ public async Task SyncGitHubFilesAsync(List fileDetails)
return;
}
- var filesToProcess = fileDetails.Where(x => !x.FileMatchesLocally).ToList();
+ var filesToProcess = fileDetails.Where(x => x.Action != GitHubFileAction.Nothing).ToList();
var total = filesToProcess.Count;
var completed = 0;
@@ -216,9 +225,9 @@ public async Task SyncGitHubFilesAsync(List fileDetails)
foreach (var hashPath in fileDetails.Select(x => x.HashPath).Distinct())
{
- SaveFileHashYaml(hashPath,
- fileDetails.Where(x => x.HashPath == hashPath && !string.IsNullOrEmpty(x.DownloadUrl))
- .ToDictionary(x => x.LocalPath, x => x.RemoteHash));
+ var hashDetails = fileDetails.Where(x => x.HashPath == hashPath && !string.IsNullOrEmpty(x.Hash))
+ .ToDictionary(x => x.LocalPath, x => x.Hash);
+ SaveFileHashYaml(hashPath, hashDetails);
}
}
diff --git a/src/TrackerCouncil.Smz3.Data/Services/OptionsWindowService.cs b/src/TrackerCouncil.Smz3.Data/Services/OptionsWindowService.cs
index d3e299a44..0e7eb1eb8 100644
--- a/src/TrackerCouncil.Smz3.Data/Services/OptionsWindowService.cs
+++ b/src/TrackerCouncil.Smz3.Data/Services/OptionsWindowService.cs
@@ -216,6 +216,7 @@ private async Task UpdateSpritesAsync()
InitialJsonPath = RandomizerDirectories.SpriteInitialJsonFilePath,
ValidPathCheck = p => p.StartsWith("Sprites/") && p.Contains('.'),
ConvertGitHubPathToLocalPath = p => p.Replace("Sprites/", ""),
+ DeleteExtraFiles = RandomizerDirectories.DeleteSprites
};
var sprites = await gitHubFileSynchronizerService.GetGitHubFileDetailsAsync(spriteDownloadRequest);
@@ -228,11 +229,12 @@ private async Task UpdateSpritesAsync()
HashPath = RandomizerDirectories.TrackerSpritePath,
InitialJsonPath = RandomizerDirectories.TrackerSpritePath,
ValidPathCheck = p => p.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || p.EndsWith(".gif", StringComparison.OrdinalIgnoreCase),
+ DeleteExtraFiles = RandomizerDirectories.DeleteTrackerSprites
};
sprites.AddRange(await gitHubFileSynchronizerService.GetGitHubFileDetailsAsync(spriteDownloadRequest));
- if (sprites.Count > 0)
+ if (sprites.Any(x => x.Action != GitHubFileAction.Nothing))
{
SpriteDownloadStarted?.Invoke(this, EventArgs.Empty);
await gitHubFileSynchronizerService.SyncGitHubFilesAsync(sprites);
diff --git a/src/TrackerCouncil.Smz3.Data/Services/SpriteService.cs b/src/TrackerCouncil.Smz3.Data/Services/SpriteService.cs
index 423cfc170..56ad04d2a 100644
--- a/src/TrackerCouncil.Smz3.Data/Services/SpriteService.cs
+++ b/src/TrackerCouncil.Smz3.Data/Services/SpriteService.cs
@@ -210,7 +210,7 @@ public Sprite GetSprite(SpriteType type)
if (sprite.IsRandomSprite)
{
- var spriteType = sprite.SpriteType;
+ var spriteType = type;
var searchText = spriteType switch
{
diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs
index 21812fd72..7c7c6109d 100644
--- a/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs
+++ b/src/TrackerCouncil.Smz3.Data/WorldData/Location.cs
@@ -136,7 +136,7 @@ public ItemType? MarkedItem
if (value != null)
{
State.MarkedUsefulness =
- Item.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity)
+ Item.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity, Item.IsLocalPlayerItem)
? LocationUsefulness.NiceToHave
: LocationUsefulness.Useless;
}
diff --git a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/SuperMetroid/Norfair/LowerNorfairEast.cs b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/SuperMetroid/Norfair/LowerNorfairEast.cs
index 2a3e5f621..8a8c7ed09 100644
--- a/src/TrackerCouncil.Smz3.Data/WorldData/Regions/SuperMetroid/Norfair/LowerNorfairEast.cs
+++ b/src/TrackerCouncil.Smz3.Data/WorldData/Regions/SuperMetroid/Norfair/LowerNorfairEast.cs
@@ -81,7 +81,8 @@ public bool CanBeatBoss(Progression items)
private bool CanExit(Progression items)
{
return items.CardNorfairL2 /*Bubble Mountain*/ ||
- (items.Gravity && items.Wave /* Volcano Room and Blue Gate */ && (items.Grapple || items.SpaceJump /*Spikey Acid Snakes and Croc Escape*/));
+ items is { Gravity: true, SpaceJump: true } /* Path back to Mire*/ ||
+ (items is { Gravity: true, Wave: true } /* Volcano Room and Blue Gate */ && (items.Grapple || items.SpaceJump /*Spikey Acid Snakes and Croc Escape*/));
}
public class SpringBallMazeRoom : Room
diff --git a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/GameHintService.cs b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/GameHintService.cs
index 1dcebbf07..862dd4508 100644
--- a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/GameHintService.cs
+++ b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/GameHintService.cs
@@ -419,7 +419,7 @@ private PlayerHintTile GetBasicLocationHint(Location location)
Locations = [location.Id],
Usefulness =
location.ItemType.IsPossibleProgression(location.World.Config.ZeldaKeysanity,
- location.World.Config.MetroidKeysanity)
+ location.World.Config.MetroidKeysanity, location.Item.IsLocalPlayerItem)
? LocationUsefulness.NiceToHave
: LocationUsefulness.Useless
};
diff --git a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/MultiplayerFiller.cs b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/MultiplayerFiller.cs
index 91074ba41..44cf22aad 100644
--- a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/MultiplayerFiller.cs
+++ b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/MultiplayerFiller.cs
@@ -76,7 +76,7 @@ private void FillItems(World world, List worlds)
var generatedData = generatedLocationData.Single(x => x.Id == location.Id);
var itemType = generatedData.Item;
var itemWorld = worlds.Single(x => x.Id == generatedData.ItemWorldId);
- location.Item = new Item(itemType, itemWorld, isProgression: itemType.IsPossibleProgression(itemWorld.Config.ZeldaKeysanity, itemWorld.Config.MetroidKeysanity));
+ location.Item = new Item(itemType, itemWorld, isProgression: itemType.IsPossibleProgression(itemWorld.Config.ZeldaKeysanity, itemWorld.Config.MetroidKeysanity, itemWorld == world));
_logger.LogDebug("Fast-filled {Item} at {Location}", generatedData.Item, location.Name);
}
EnsureLocationsHaveItems(world);
diff --git a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3GeneratedRomLoader.cs b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3GeneratedRomLoader.cs
index cbd8f7177..f6199b480 100644
--- a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3GeneratedRomLoader.cs
+++ b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3GeneratedRomLoader.cs
@@ -71,7 +71,7 @@ public List LoadGeneratedRom(GeneratedRom rom)
location.Item = new Item(locationState.Item, itemWorld,
itemState.ItemName, itemMetadata, itemState,
locationState.Item.IsPossibleProgression(itemWorld.Config.ZeldaKeysanity,
- itemWorld.Config.MetroidKeysanity),
+ itemWorld.Config.MetroidKeysanity, itemWorld == location.World),
locationState.ItemOwnerName, locationState.ItemName
);
}
diff --git a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3RomParser.cs b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3RomParser.cs
index 649dec836..97feff44d 100644
--- a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3RomParser.cs
+++ b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/Smz3RomParser.cs
@@ -36,102 +36,118 @@ public ParsedRomDetails ParseRomFile(string filePath)
var exampleWorld = new World(new Config(), "", 1, "");
var rom = File.ReadAllBytes(filePath);
- var isMultiworldEnabled = MetadataPatch.IsRomMultiworldEnabled(rom);
- var isKeysanityEnabled = MetadataPatch.IsRomKeysanityEnabled(rom);
- var romTitle = MetadataPatch.GetGameTitle(rom);
- var playerNames = isMultiworldEnabled ? MetadataPatch.GetPlayerNames(rom): [ "Player" ];
- var playerIndex = MetadataPatch.GetPlayerIndex(rom);
- var players = playerNames.Select((name, index) => new ParsedRomPlayer()
+ try
{
- PlayerName = name.Trim(), PlayerIndex = index, IsLocalPlayer = index == playerIndex,
- }).ToList();
- logger.LogInformation("Parsed players {PlayerList}", string.Join(", ", players.Select(p => p.PlayerName)));
-
- var itemTypes = configs.Items.Where(x => x.InternalItemType != ItemType.Nothing)
- .Select(x => (int)x.InternalItemType).ToList();
- var locations = LocationsPatch.GetLocationsFromRom(rom, playerNames, exampleWorld, isMultiworldEnabled, itemTypes);
- var prerequisites = MedallionPatch.GetPrerequisitesFromRom(rom, exampleWorld.PrerequisiteRegions);
- var bosses = exampleWorld.BossRegions.Select(x => new ParsedRomBossDetails()
- {
- RegionType = x.GetType(), RegionName = x.Name, BossType = x.BossType
- }).ToList();
-
- var keysanityMode = KeysanityMode.None;
- if (isKeysanityEnabled)
- {
- var isMetroidKeysanity = MetroidKeysanityPatch.GetIsMetroidKeysanity(rom);
- var isZeldaKeysanity = ZeldaKeysanityPatch.GetIsZeldaKeysanity(rom);
+ var isMultiworldEnabled = MetadataPatch.IsRomMultiworldEnabled(rom);
+ var isKeysanityEnabled = MetadataPatch.IsRomKeysanityEnabled(rom);
+ var romTitle = MetadataPatch.GetGameTitle(rom);
+ var playerNames = isMultiworldEnabled ? MetadataPatch.GetPlayerNames(rom) : ["Player"];
+ var playerIndex = MetadataPatch.GetPlayerIndex(rom);
+ var players = playerNames.Select((name, index) => new ParsedRomPlayer()
+ {
+ PlayerName = name.Trim(), PlayerIndex = index, IsLocalPlayer = index == playerIndex,
+ }).ToList();
+ logger.LogInformation("Parsed players {PlayerList}", string.Join(", ", players.Select(p => p.PlayerName)));
+
+ var itemTypes = configs.Items.Where(x => x.InternalItemType != ItemType.Nothing)
+ .Select(x => (int)x.InternalItemType).ToList();
+ var locations =
+ LocationsPatch.GetLocationsFromRom(rom, playerNames, exampleWorld, isMultiworldEnabled, itemTypes);
+ var prerequisites = MedallionPatch.GetPrerequisitesFromRom(rom, exampleWorld.PrerequisiteRegions);
+ var bosses = exampleWorld.BossRegions.Select(x => new ParsedRomBossDetails()
+ {
+ RegionType = x.GetType(), RegionName = x.Name, BossType = x.BossType
+ }).ToList();
- if (isMetroidKeysanity && isZeldaKeysanity)
+ var keysanityMode = KeysanityMode.None;
+ if (isKeysanityEnabled)
{
- keysanityMode = KeysanityMode.Both;
+ var isMetroidKeysanity = MetroidKeysanityPatch.GetIsMetroidKeysanity(rom);
+ var isZeldaKeysanity = ZeldaKeysanityPatch.GetIsZeldaKeysanity(rom);
+
+ if (isMetroidKeysanity && isZeldaKeysanity)
+ {
+ keysanityMode = KeysanityMode.Both;
+ }
+ else if (isMetroidKeysanity)
+ {
+ keysanityMode = KeysanityMode.SuperMetroid;
+ }
+ else if (isZeldaKeysanity)
+ {
+ keysanityMode = KeysanityMode.Zelda;
+ }
}
- else if (isMetroidKeysanity)
+
+ logger.LogInformation("Keysanity: {Mode}", keysanityMode);
+
+ var hardLogic = false;
+ var seedNumber = 0;
+ RomGenerator? romGenerator = null;
+
+ if (romTitle.StartsWith("ZSM"))
{
- keysanityMode = KeysanityMode.SuperMetroid;
+ romGenerator = playerNames.First() == "Archipelago" ? RomGenerator.Archipelago : RomGenerator.Mainline;
+
+ var flags = romTitle[3..];
+ var flagIndex = flags.IndexOf(flags.FirstOrDefault(char.IsLetter));
+ flags = flags.Substring(flagIndex, 2);
+ hardLogic = flags[1] == 'H';
+
+ var seedString = romTitle[(3 + flagIndex + 2)..];
+ var seed = romGenerator == RomGenerator.Archipelago
+ ? seedString[playerIndex.ToString().Length..]
+ : seedString;
+ var match = HexRegex().Match(seed);
+ seedNumber = match.Success ? Convert.ToInt32(seed, 16) : new Random().Next();
}
- else if (isZeldaKeysanity)
+ else if (romTitle.StartsWith("SMZ3 Cas"))
{
- keysanityMode = KeysanityMode.Zelda;
+ romGenerator = RomGenerator.Cas;
}
- }
-
- logger.LogInformation("Keysanity: {Mode}", keysanityMode);
- var hardLogic = false;
- var seedNumber = 0;
- var isCasRom = false;
- var romGenerator = RomGenerator.Cas;
+ if (romGenerator == null)
+ {
+ throw new InvalidOperationException("Could not determine rom generator from the rom details");
+ }
- if (romTitle.StartsWith("ZSM"))
- {
- romGenerator = playerNames.First() == "Archipelago" ? RomGenerator.Archipelago : RomGenerator.Mainline;
+ var rewards =
+ ZeldaRewardsPatch.GetRewardsFromRom(rom, exampleWorld.RewardRegions, romGenerator == RomGenerator.Cas);
+ var startingItems = StartingEquipmentPatch.GetStartingItemList(rom, romGenerator == RomGenerator.Cas);
+ var gtCrystalCount = GoalsPatch.GetGanonsTowerCrystalCountFromRom(rom);
+ var ganonCrystalCount = GoalsPatch.GetGanonCrystalCountFromRom(rom);
+ var tourianBossCount = GoalsPatch.GetTourianBossCountFromRom(rom, romGenerator == RomGenerator.Cas);
+ var text = ZeldaTextsPatch.ParseRomText(rom);
- var flags = romTitle[3..];
- var flagIndex = flags.IndexOf(flags.FirstOrDefault(char.IsLetter));
- flags = flags.Substring(flagIndex, 2);
- hardLogic = flags[1] == 'H';
+ logger.LogInformation("Imported {Title} (Seed {SeedNumber})", romTitle, seedNumber);
- var seedString = romTitle[(3 + flagIndex + 2)..];
- var seed = romGenerator == RomGenerator.Archipelago ? seedString[playerIndex.ToString().Length..] : seedString;
- var match = HexRegex().Match(seed);
- seedNumber = match.Success ? Convert.ToInt32(seed, 16) : new Random().Next();
+ return new ParsedRomDetails
+ {
+ OriginalPath = filePath,
+ OriginalFilename = Path.GetFileNameWithoutExtension(filePath),
+ RomTitle = romTitle,
+ Seed = seedNumber,
+ IsMultiworld = isMultiworldEnabled,
+ IsHardLogic = hardLogic,
+ KeysanityMode = keysanityMode,
+ GanonsTowerCrystalCount = gtCrystalCount,
+ GanonCrystalCount = ganonCrystalCount,
+ TourianBossCount = tourianBossCount,
+ RomGenerator = romGenerator.Value,
+ Players = players,
+ Locations = locations,
+ Rewards = rewards,
+ Bosses = bosses,
+ Prerequisites = prerequisites,
+ StartingItems = startingItems,
+ ParsedText = text
+ };
}
- else if (romTitle.StartsWith("SMZ3 Cas"))
+ catch (Exception e)
{
- isCasRom = true;
+ logger.LogError(e, "Error while parsing rom");
+ throw;
}
-
- var rewards = ZeldaRewardsPatch.GetRewardsFromRom(rom, exampleWorld.RewardRegions, isCasRom);
- var startingItems = StartingEquipmentPatch.GetStartingItemList(rom, isCasRom);
- var gtCrystalCount = GoalsPatch.GetGanonsTowerCrystalCountFromRom(rom);
- var ganonCrystalCount = GoalsPatch.GetGanonCrystalCountFromRom(rom);
- var tourianBossCount = GoalsPatch.GetTourianBossCountFromRom(rom, isCasRom);
- var text = ZeldaTextsPatch.ParseRomText(rom);
-
- logger.LogInformation("Imported {Title} (Seed {SeedNumber})", romTitle, seedNumber);
-
- return new ParsedRomDetails()
- {
- OriginalPath = filePath,
- OriginalFilename = Path.GetFileNameWithoutExtension(filePath),
- RomTitle = romTitle,
- Seed = seedNumber,
- IsMultiworld = isMultiworldEnabled,
- IsHardLogic = hardLogic,
- KeysanityMode = keysanityMode,
- GanonsTowerCrystalCount = gtCrystalCount,
- GanonCrystalCount = ganonCrystalCount,
- TourianBossCount = tourianBossCount,
- RomGenerator = romGenerator,
- Players = players,
- Locations = locations,
- Rewards = rewards,
- Bosses = bosses,
- Prerequisites = prerequisites,
- StartingItems = startingItems,
- ParsedText = text
- };
}
public SeedData GenerateSeedData(RandomizerOptions options, ParsedRomDetails parsedRomDetails, CancellationToken cancellationToken = default)
diff --git a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/StatGenerator.cs b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/StatGenerator.cs
index 1a3245ed1..068a04104 100644
--- a/src/TrackerCouncil.Smz3.SeedGenerator/Generation/StatGenerator.cs
+++ b/src/TrackerCouncil.Smz3.SeedGenerator/Generation/StatGenerator.cs
@@ -209,7 +209,7 @@ int GetLocationProgressionCount(LocationId locationId)
return itemCounts.Where(x =>
x.Key.locationId == locationId &&
!items[x.Key.itemId].IsInAnyCategory(ItemCategory.BigKey, ItemCategory.SmallKey, ItemCategory.Compass, ItemCategory.Map) &&
- items[x.Key.itemId].IsPossibleProgression(false, false))
+ items[x.Key.itemId].IsPossibleProgression(false, false, true))
.Sum(x => x.Value);
}
}
diff --git a/src/TrackerCouncil.Smz3.Shared/Enums/ItemType.cs b/src/TrackerCouncil.Smz3.Shared/Enums/ItemType.cs
index 10262d76c..bee8edb1c 100644
--- a/src/TrackerCouncil.Smz3.Shared/Enums/ItemType.cs
+++ b/src/TrackerCouncil.Smz3.Shared/Enums/ItemType.cs
@@ -615,9 +615,11 @@ public enum ItemType : byte
[ItemCategory(ItemCategory.Metroid, ItemCategory.MetroidMap)]
SmMapLowerNorfair = 0xCD,
+ [Description("Other Game Item")]
[ItemCategory(ItemCategory.NonRandomized)]
OtherGameItem = 0xFE,
+ [Description("Important Other Game Item")]
[ItemCategory(ItemCategory.NonRandomized)]
OtherGameProgressionItem = 0xFF
}
diff --git a/src/TrackerCouncil.Smz3.Shared/Enums/ItemTypeExtensions.cs b/src/TrackerCouncil.Smz3.Shared/Enums/ItemTypeExtensions.cs
index 7ffaee13a..53ef4dcb8 100644
--- a/src/TrackerCouncil.Smz3.Shared/Enums/ItemTypeExtensions.cs
+++ b/src/TrackerCouncil.Smz3.Shared/Enums/ItemTypeExtensions.cs
@@ -62,22 +62,23 @@ public static ItemCategory[] GetCategories(this ItemType itemType)
/// The type of item.
/// If playing with Zelda Key Sanity enabled.
/// If playing with Metroid Key Sanity enabled.
+ ///
///
/// if matches any of
/// could possibly be progression; otherwise, .
///
- public static bool IsPossibleProgression(this ItemType itemType, bool isZeldaKeysanity, bool isMetroidKeysanity)
+ public static bool IsPossibleProgression(this ItemType itemType, bool isZeldaKeysanity, bool isMetroidKeysanity, bool isLocalPlayerItem)
{
- if (itemType.IsInAnyCategory(new[] { ItemCategory.SmallKey, ItemCategory.BigKey }))
- return isZeldaKeysanity;
+ if (itemType.IsInAnyCategory(ItemCategory.SmallKey, ItemCategory.BigKey))
+ return isZeldaKeysanity || !isLocalPlayerItem;
if (itemType.IsInCategory(ItemCategory.Keycard))
- return isMetroidKeysanity;
+ return isMetroidKeysanity || !isLocalPlayerItem;
if (itemType == ItemType.OtherGameProgressionItem)
return true;
- if (itemType == ItemType.Nothing || itemType.IsInAnyCategory(new[] { ItemCategory.Junk, ItemCategory.Scam, ItemCategory.NonRandomized, ItemCategory.Map, ItemCategory.Compass, ItemCategory.Nice }))
+ if (itemType == ItemType.Nothing || itemType.IsInAnyCategory(ItemCategory.Junk, ItemCategory.Scam, ItemCategory.NonRandomized, ItemCategory.Map, ItemCategory.Compass, ItemCategory.Nice))
return false;
return true;
diff --git a/src/TrackerCouncil.Smz3.Tracking/AutoTracking/GameService.cs b/src/TrackerCouncil.Smz3.Tracking/AutoTracking/GameService.cs
index 4d7e68d20..92de30794 100644
--- a/src/TrackerCouncil.Smz3.Tracking/AutoTracking/GameService.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/AutoTracking/GameService.cs
@@ -27,6 +27,9 @@ public class GameService : TrackerModule, IGameService
private readonly ILogger _logger;
private readonly int _trackerPlayerId;
private readonly Dictionary _emulatorActions = new();
+ private int _giveItemCountAddress = 0xA26602;
+ private int _giveItemDetailLength = 4;
+ private int _giveItemDetailStartingIndex = 2;
///
/// Initializes a new instance of the
@@ -117,11 +120,18 @@ public async Task TryGiveItemsAsync(List- items, int fromPlayerId)
/// False if it is currently unable to give the items to the player
public async Task TryGiveItemTypesAsync(List<(ItemType type, int fromPlayerId)> items)
{
- if (!IsInGame())
+ if (!IsInGame() || TrackerBase.World.Config.RomGenerator != RomGenerator.Cas)
{
return false;
}
+ if (TrackerBase.World.Config.RomGenerator == RomGenerator.Archipelago)
+ {
+ _giveItemCountAddress = 0xA26D38;
+ _giveItemDetailLength = 2;
+ _giveItemDetailStartingIndex = 0;
+ }
+
// Get the first block of memory
var firstBlockResponse = await _snesConnectorService.MakeMemoryRequestAsync(new SnesSingleMemoryRequest()
{
@@ -156,9 +166,11 @@ public async Task TryGiveItemTypesAsync(List<(ItemType type, int fromPlaye
// Each item takes up two words and we're interested in the second word in each pair.
var data = firstDataSet.Raw.Concat(secondDataSet.Raw).ToArray();
var itemCounter = 0;
- for (var i = 2; i < 0x600; i += 4)
+ for (var i = _giveItemDetailStartingIndex; i < 0x600; i += _giveItemDetailLength)
{
- var item = (ItemType)BitConverter.ToUInt16(data.AsSpan(i, 2));
+ var item = _giveItemDetailLength == 4
+ ? (ItemType)BitConverter.ToUInt16(data.AsSpan(i, 2))
+ : (ItemType)data[i + 1];
if (item != ItemType.Nothing)
{
itemCounter++;
@@ -172,8 +184,16 @@ public async Task TryGiveItemTypesAsync(List<(ItemType type, int fromPlaye
var bytes = new List();
foreach (var item in batch)
{
- bytes.AddRange(Int16ToBytes(item.fromPlayerId));
- bytes.AddRange(Int16ToBytes((int)item.type));
+ if (_giveItemDetailLength == 4)
+ {
+ bytes.AddRange(Int16ToBytes(item.fromPlayerId));
+ bytes.AddRange(Int16ToBytes((int)item.type));
+ }
+ else
+ {
+ bytes.Add((byte)item.fromPlayerId);
+ bytes.Add((byte)item.type);
+ }
}
_snesConnectorService.MakeMemoryRequest(new SnesSingleMemoryRequest()
@@ -182,7 +202,7 @@ public async Task TryGiveItemTypesAsync(List<(ItemType type, int fromPlaye
SnesMemoryDomain = SnesMemoryDomain.CartridgeSave,
AddressFormat = AddressFormat.Snes9x,
SniMemoryMapping = MemoryMapping.ExHiRom,
- Address = 0xA26000 + (itemCounter * 4),
+ Address = 0xA26000 + (itemCounter * _giveItemDetailLength),
Data = bytes
});
@@ -196,7 +216,7 @@ public async Task TryGiveItemTypesAsync(List<(ItemType type, int fromPlaye
SnesMemoryDomain = SnesMemoryDomain.CartridgeSave,
AddressFormat = AddressFormat.Snes9x,
SniMemoryMapping = MemoryMapping.ExHiRom,
- Address = 0xA26602,
+ Address = _giveItemCountAddress,
Data = Int16ToBytes(itemCounter)
});
diff --git a/src/TrackerCouncil.Smz3.Tracking/NaturalLanguage.cs b/src/TrackerCouncil.Smz3.Tracking/NaturalLanguage.cs
index 20ee97be1..4e10b29bb 100644
--- a/src/TrackerCouncil.Smz3.Tracking/NaturalLanguage.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/NaturalLanguage.cs
@@ -98,8 +98,8 @@ public static string Join(IEnumerable
- items, Config config)
return (item, count);
}).ToList();
- var interestingItems = groupedItems.Where(x => x.item.Metadata.IsProgression(config)).ToList();
- var junkItems = groupedItems.Where(x => !x.item.Metadata.IsProgression(config)).OrderBy(x => x.item.IsDungeonItem).ToList();
+ var interestingItems = groupedItems.Where(x => x.item.Metadata.IsProgression(config, x.item.IsLocalPlayerItem)).ToList();
+ var junkItems = groupedItems.Where(x => !x.item.Metadata.IsProgression(config, x.item.IsLocalPlayerItem)).OrderBy(x => x.item.IsDungeonItem).ToList();
if (junkItems.Count == 0)
{
diff --git a/src/TrackerCouncil.Smz3.Tracking/Services/WorldQueryService.cs b/src/TrackerCouncil.Smz3.Tracking/Services/WorldQueryService.cs
index c20abcef5..29535fc27 100644
--- a/src/TrackerCouncil.Smz3.Tracking/Services/WorldQueryService.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/Services/WorldQueryService.cs
@@ -146,7 +146,7 @@ private bool IsValidLocation(Location location, bool unclearedOnly, bool outOfLo
///
/// A collection of items.
public IEnumerable- LocalPlayersItems()
- => AllItems().Where(x => x.World.Id == World.Id);
+ => AllItems().Where(x => x.World.Id == World.Id && x.IsLocalPlayerItem);
///
/// Enumerates all rewards that can be tracked for all players.
diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs
index 4344756b3..1f2a06e8f 100644
--- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerItemService.cs
@@ -222,7 +222,7 @@ public bool TrackItem(Item item, string? trackedAs = null, float? confidence = n
var addedEvent = History.AddEvent(
HistoryEventType.TrackedItem,
- item.Metadata.IsProgression(World.Config),
+ item.Metadata.IsProgression(World.Config, item.IsLocalPlayerItem),
item.Metadata.NameWithArticle,
location
);
@@ -528,11 +528,11 @@ private void AnnounceTrackedItems(List
- items)
}
else
{
- var itemsToSay = items.Where(x => x.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity)).Take(2).ToList();
+ var itemsToSay = items.Where(x => x.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity, x.IsLocalPlayerItem)).Take(2).ToList();
if (itemsToSay.Count() < 2)
{
var numToTake = 2 - itemsToSay.Count();
- itemsToSay.AddRange(items.Where(x => !x.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity)).Take(numToTake));
+ itemsToSay.AddRange(items.Where(x => !x.Type.IsPossibleProgression(World.Config.ZeldaKeysanity, World.Config.MetroidKeysanity, x.IsLocalPlayerItem)).Take(numToTake));
}
Tracker.Say(x => x.TrackedManyItems, args: [itemsToSay[0].Metadata.NameWithArticle, itemsToSay[1].Metadata.NameWithArticle, items.Count - 2]);
diff --git a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs
index 6d78a6338..33f2a6955 100644
--- a/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/TrackingServices/TrackerLocationService.cs
@@ -452,7 +452,7 @@ private void GiveLocationComment(ItemType item, Location location, bool isTracki
}
// Give some sass if the user tracks or marks the wrong item at a
// location unless the user is clearing a useless item like missiles
- else if (location.Item.Type != ItemType.Nothing && !item.IsEquivalentTo(location.Item.Type) && (item != ItemType.Nothing || location.Item.Metadata.IsProgression(World.Config)))
+ else if (location.Item.Type != ItemType.Nothing && !item.IsEquivalentTo(location.Item.Type) && (item != ItemType.Nothing || location.Item.Metadata.IsProgression(World.Config, location.Item.IsLocalPlayerItem)))
{
if (confidence == null || confidence < Options.MinimumSassConfidence)
return;
diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/MultiplayerModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/MultiplayerModule.cs
index 64bf4cb19..94768d5d0 100644
--- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/MultiplayerModule.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/MultiplayerModule.cs
@@ -152,7 +152,7 @@ private void PlayerTrackedLocation(PlayerTrackedLocationEventHandlerArgs args)
if (item == null)
throw new InvalidOperationException($"Player retrieved invalid item {args.ItemToGive}");
_ = TrackerBase.GameService!.TryGiveItemAsync(item, args.PlayerId);
- if (item.Type.IsPossibleProgression(item.World.Config.ZeldaKeysanity, item.World.Config.MetroidKeysanity))
+ if (item.Type.IsPossibleProgression(item.World.Config.ZeldaKeysanity, item.World.Config.MetroidKeysanity, item.IsLocalPlayerItem))
{
TrackerBase.Say(x => x.Multiplayer.ReceivedUsefulItemFromOtherPlayer,
args: [args.PhoneticName, item.Metadata.Name, item.Metadata.NameWithArticle]);
diff --git a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/SpoilerModule.cs b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/SpoilerModule.cs
index 8b5d35dbf..c608bffcd 100644
--- a/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/SpoilerModule.cs
+++ b/src/TrackerCouncil.Smz3.Tracking/VoiceCommands/SpoilerModule.cs
@@ -126,7 +126,7 @@ private void GiveAreaHint(IHasLocations area)
{
var config = area.Region.Config;
var anyPossibleProgression = area.Locations.Any(x =>
- x.ItemType.IsPossibleProgression(config.ZeldaKeysanity, config.MetroidKeysanity));
+ x.ItemType.IsPossibleProgression(config.ZeldaKeysanity, config.MetroidKeysanity, x.Item.IsLocalPlayerItem));
if (anyPossibleProgression)
{
TrackerBase.Say(x => x.Hints.AreaHasNonCasPossibleProgression, args: [area.GetName()]);
@@ -450,7 +450,7 @@ private bool GiveLocationHints(Location location)
if (HintsGiven(location) == 0)
{
if (location.ItemType.IsPossibleProgression(location.World.Config.ZeldaKeysanity,
- location.World.Config.MetroidKeysanity))
+ location.World.Config.MetroidKeysanity, location.Item.IsLocalPlayerItem))
{
return GiveLocationHint(x => x.LocationHasNonCasProgressionItem, location, location.Item.PlayerName);
}
diff --git a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
index 00497e858..7a7271e52 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
@@ -33,12 +33,10 @@ public class MainWindowService(
Configs configs) : ControlService
{
private MainWindowViewModel _model = new();
- private MainWindow _window = null!;
private RandomizerOptions _options = null!;
public MainWindowViewModel InitializeModel(MainWindow window)
{
- _window = window;
_options = optionsFactory.Create();
_model.OpenSetupWindow = !_options.GeneralOptions.HasOpenedSetupWindow;
ITaskService.Run(CheckForUpdates);
@@ -141,6 +139,7 @@ public async Task DownloadSpritesAsync()
InitialJsonPath = RandomizerDirectories.SpriteInitialJsonFilePath,
ValidPathCheck = p => Sprite.ValidDownloadExtensions.Contains(Path.GetExtension(p).ToLowerInvariant()),
ConvertGitHubPathToLocalPath = p => p.Replace("Sprites/", ""),
+ DeleteExtraFiles = RandomizerDirectories.DeleteSprites
};
var toDownload = await gitHubFileSynchronizerService.GetGitHubFileDetailsAsync(spriteDownloadRequest);
@@ -153,15 +152,14 @@ public async Task DownloadSpritesAsync()
HashPath = RandomizerDirectories.TrackerSpriteHashYamlFilePath,
InitialJsonPath = RandomizerDirectories.TrackerSpriteInitialJsonFilePath,
ValidPathCheck = p => p.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || p.EndsWith(".gif", StringComparison.OrdinalIgnoreCase),
+ DeleteExtraFiles = RandomizerDirectories.DeleteSprites
};
toDownload.AddRange(await gitHubFileSynchronizerService.GetGitHubFileDetailsAsync(spriteDownloadRequest));
- if (toDownload is not { Count: > 4 })
- {
- await gitHubFileSynchronizerService.SyncGitHubFilesAsync(toDownload);
- }
- else
+ var numToDownload = toDownload.Count(x => x.Action != GitHubFileAction.Nothing);
+
+ if (numToDownload > 4)
{
await Dispatcher.UIThread.InvokeAsync(async () =>
{
@@ -170,6 +168,10 @@ await Dispatcher.UIThread.InvokeAsync(async () =>
SpriteDownloadEnd?.Invoke(this, EventArgs.Empty);
});
}
+ else if (numToDownload > 0)
+ {
+ await gitHubFileSynchronizerService.SyncGitHubFilesAsync(toDownload);
+ }
await spriteService.LoadSpritesAsync();
trackerSpriteService.LoadSprites();
diff --git a/src/TrackerCouncil.Smz3.UI/Services/SoloRomListService.cs b/src/TrackerCouncil.Smz3.UI/Services/SoloRomListService.cs
index 9bf292c07..d250264b0 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/SoloRomListService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/SoloRomListService.cs
@@ -1,7 +1,6 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
-using System.Web;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using AvaloniaControls;
@@ -164,7 +163,7 @@ public async Task LaunchTracker(GeneratedRomViewModel rom)
await sharedCrossplatformService.LaunchTrackerAsync(rom.Rom);
}
- public async Task OpenArchipelagoModeAsync()
+ public async Task OpenArchipelagoModeAsync()
{
var storageItem = await CrossPlatformTools.OpenFileDialogAsync(ParentWindow, FileInputControlType.OpenFile,
"Rom file (*.sfc)|*.sfc|All files (*.*)|*.*", "/home/matt/Games/Randomizers/Archipelago");
@@ -173,7 +172,7 @@ public async Task OpenArchipelagoModeAsync()
if (pathString == null)
{
- return;
+ return false;
}
var parsedRomDetails = smz3RomParser.ParseRomFile(pathString);
@@ -181,48 +180,10 @@ public async Task OpenArchipelagoModeAsync()
if (await sharedCrossplatformService.OpenGenerationWindow(importDetails: parsedRomDetails) != null)
{
UpdateList();
+ return true;
}
- // archipelagoScannerService.ScanArchipelagoRom(rom);
-
- /*var rom = await File.ReadAllBytesAsync(pathString);
- romGenerationService.ApplyCasPatches(rom, new PatchOptions()
- {
- CasPatches = new CasPatches()
- {
- AimAnyButton = true,
- DisableFlashing = true,
- DisableScreenShake = true,
- EasierWallJumps = true,
- FastDoors = true,
- FastElevators = true,
- InfiniteSpaceJump = true,
- MetroidAutoSave = true,
- NerfedCharge = true,
- SnapMorph = true,
- Respin = true,
- RefillAtSaveStation = true,
- SandPitPlatforms = true,
- },
- MetroidControls = new MetroidControlOptions()
- {
- RunButtonBehavior = RunButtonBehavior.AutoRun,
- ItemCancelBehavior = ItemCancelBehavior.HoldSupersOnly,
- AimButtonBehavior = AimButtonBehavior.UnifiedAim,
- Shoot = MetroidButton.Y,
- Jump = MetroidButton.B,
- Dash = MetroidButton.X,
- ItemSelect = MetroidButton.Select,
- ItemCancel = MetroidButton.R,
- AimUp = MetroidButton.L,
- AimDown = MetroidButton.R
- }
- });
-
- var folder = Path.GetDirectoryName(pathString)!;
- var fileName = Path.GetFileNameWithoutExtension(pathString)+"_updated";
- var extension = Path.GetExtension(pathString);
- await File.WriteAllBytesAsync(Path.Combine(folder, fileName + extension), rom);*/
+ return false;
}
private void OpenMessageWindow(string message, MessageWindowIcon icon = MessageWindowIcon.Error, MessageWindowButtons buttons = MessageWindowButtons.OK)
diff --git a/src/TrackerCouncil.Smz3.UI/Services/TrackerWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/TrackerWindowService.cs
index ff3ee963b..1d8211dd9 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/TrackerWindowService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/TrackerWindowService.cs
@@ -525,11 +525,11 @@ private TrackerWindowPanelViewModel GetItemPanelViewModel(UIGridLocation gridLoc
if (items.Count == 1)
{
- model.Clicked += (_, _) => tracker.ItemTracker.TrackItem(items.Keys.First());
+ model.Clicked += (_, _) => tracker.ItemTracker.TrackItem(items.Keys.First(), force: true);
}
- model.ItemGiven += (_, args) => tracker.ItemTracker.TrackItem(args.Item);
- model.ItemRemoved += (_, args) => tracker.ItemTracker.UntrackItem(args.Item);
+ model.ItemGiven += (_, args) => tracker.ItemTracker.TrackItem(args.Item, force: true);
+ model.ItemRemoved += (_, args) => tracker.ItemTracker.UntrackItem(args.Item, force: true);
model.ItemSetAsDungeonRequirement += (_, args) =>
{
var item = items.Keys.First();
diff --git a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
index 40ac3512f..631dc7092 100644
--- a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
+++ b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
@@ -6,7 +6,7 @@
true
app.manifest
true
- 9.9.0
+ 9.9.0-rc.3
SMZ3CasRandomizer
Assets\smz3.ico
$(MSBuildProjectName.Replace(" ", "_"))
diff --git a/src/TrackerCouncil.Smz3.UI/ViewModels/MarkedLocationViewModel.cs b/src/TrackerCouncil.Smz3.UI/ViewModels/MarkedLocationViewModel.cs
index 82dabe312..25c710f9d 100644
--- a/src/TrackerCouncil.Smz3.UI/ViewModels/MarkedLocationViewModel.cs
+++ b/src/TrackerCouncil.Smz3.UI/ViewModels/MarkedLocationViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using AvaloniaControls.Models;
using ReactiveUI.Fody.Helpers;
using TrackerCouncil.Smz3.Data.WorldData;
using TrackerCouncil.Smz3.Shared.Enums;
@@ -9,7 +10,10 @@ public class MarkedLocationViewModel(Location location, Item? itemData, string?
{
public Location Location => location;
public string? ItemSprite { get; init; } = itemSprite;
- [Reactive] public bool IsAvailable { get; set; } = location.Accessibility is Accessibility.Available or Accessibility.AvailableWithKeys;
+
+ [Reactive, ReactiveLinkedProperties(nameof(Opacity))]
+ public bool IsAvailable { get; set; } = location.Accessibility is Accessibility.Available or Accessibility.AvailableWithKeys;
+
public bool ShowOutOfLogic { get; set; }
public double Opacity => ShowOutOfLogic || IsAvailable ? 1.0 : 0.33;
public string Item { get; init; }= itemData?.Name ?? "";
diff --git a/src/TrackerCouncil.Smz3.UI/Views/SoloRomListPanel.axaml.cs b/src/TrackerCouncil.Smz3.UI/Views/SoloRomListPanel.axaml.cs
index 0a8c184b1..a54b8fb9c 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/SoloRomListPanel.axaml.cs
+++ b/src/TrackerCouncil.Smz3.UI/Views/SoloRomListPanel.axaml.cs
@@ -4,7 +4,7 @@
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
-using AvaloniaControls;
+using AvaloniaControls.Controls;
using AvaloniaControls.Services;
using TrackerCouncil.Smz3.UI.Services;
using TrackerCouncil.Smz3.UI.ViewModels;
@@ -217,8 +217,19 @@ private bool GetRomFromControl(object? control, out GeneratedRomViewModel? mo
private async void ArchipelagoButton_OnClick(object? sender, RoutedEventArgs e)
{
- if (_service == null) return;
- await _service.OpenArchipelagoModeAsync();
+ try
+ {
+ if (_service == null) return;
+ if (await _service.OpenArchipelagoModeAsync())
+ {
+ await MessageWindow.ShowInfoDialog(
+ "ROM successfully parsed and updated into a new file. The original ROM has been been left alone with no modifications. You will need to launch the ROM from SZM3 Cas' or right click on the entry in the list to open the folder and find the updated ROM file.");
+ }
+ }
+ catch
+ {
+ await MessageWindow.ShowErrorDialog("Invalid ROM file. Please select a valid generated SMZ3 rom.");
+ }
}
}