public IEnumerable <SpriteRequirement> GetPossibleEnemySprites(Room room, OptionFlags optionFlags = null) { // TODO: add more logic to this? // needs to check for two subgroups, etc. return(spriteRequirementsCollection.GetUsableDungeonEnemySprites().Where(x => x.SpriteInGroup(this) && x.CanSpawnInRoom(room))); }
public void RandomizeDungeonEnemies(OptionFlags optionFlags) { GenerateGroups(); RandomizeRooms(optionFlags); WriteRom(); }
public BossRandomizer(Random rand, OptionFlags optionFlags, StringBuilder spoilerFile, Graph graph) { this.rand = rand; this.optionFlags = optionFlags; this.spoilerFile = spoilerFile; this.graph = graph; this.bossPool = new BossPool(rand); }
public void SetRomInfoOptionFlags(OptionFlags optionFlags) { var optionByteArray = optionFlags.ToByteArray(); if (optionByteArray.Length > 0x100 - EnemizerInfoFlagsOffset) { throw new Exception("Option flags is too long to fit in the space allocated. Need to move data/code in asm file."); } Array.Copy(optionByteArray, 0, romData, EnemizerInfoTableBaseAddress + EnemizerInfoFlagsOffset, optionByteArray.Length); SetPatchBytes(EnemizerInfoTableBaseAddress + EnemizerInfoFlagsOffset, optionByteArray.Length); }
public void RandomizeOverworldEnemies(OptionFlags optionFlags) { // TODO: replace this with something less hard coded because we also need to move squirrels and stuff in MS glade and probably Zora romData[0x04CF4F] = 0x10; //move bird from tree stump in lost woods // TODO: did this cause a crash? GenerateGroups(); RandomizeAreas(optionFlags); WriteRom(); }
private void RandomizeAreas(OptionFlags optionFlags) { areas.RandomizeAreaSpriteGroups(spriteGroupCollection); foreach (var area in areas.OverworldAreas.Where(x => OverworldAreaConstants.DoNotRandomizeAreas.Contains(x.AreaId) == false)) { // pick random sprite group //area.GraphicsBlockId = ??; area.RandomizeSprites(optionFlags); area.RandomizeBushSprite(); } }
public void RandomizeRoomSpriteGroups(SpriteGroupCollection spriteGroups, OptionFlags optionFlags) { // skip rooms that are set to do not randomize because that would be pointless to process them foreach (var r in Rooms) { if (RoomIdConstants.DontRandomizeRooms.Contains(r.RoomId)) { continue; } if (optionFlags.EasyModeEscape && RoomIdConstants.NoSpecialEnemiesRoomsInStandardMode.Contains(r.RoomId)) { continue; } List <SpriteRequirement> doNotUpdateSprites = spriteRequirementCollection .DoNotRandomizeSprites .Where(x => x.CanSpawnInRoom(r) && r.Sprites.Select(y => y.SpriteId).ToList().Contains(x.SpriteId) ) .ToList(); /* TODO: put this back after I figure out what I screwed up * List<SpriteRequirement> forcedSprites = spriteRequirementCollection.SpriteRequirements * .Where(x => false == x.CanBeRandomizedInRoom(r)) * .Where(x => x.CanSpawnInRoom(r) * && r.Sprites.Select(y => y.SpriteId).ToList().Contains(x.SpriteId) * ) * .ToList(); * doNotUpdateSprites.AddRange(forcedSprites); * * //*/ var possibleSpriteGroups = spriteGroups.GetPossibleDungeonSpriteGroups(r, doNotUpdateSprites).ToList(); //Debug.Assert(possibleSpriteGroups.Count > 0); if (possibleSpriteGroups.Count > 0) { r.GraphicsBlockId = possibleSpriteGroups[rand.Next(possibleSpriteGroups.Count)].DungeonGroupId; } } // force any rooms we need to foreach (var sg in spriteGroups.SpriteGroups.Where(x => x.ForceRoomsToGroup != null && x.ForceRoomsToGroup.Count > 0)) { foreach (var forcedR in Rooms.Where(x => sg.ForceRoomsToGroup.Contains(x.RoomId))) { forcedR.GraphicsBlockId = sg.DungeonGroupId; } } }
public void RandomizeSprites(OptionFlags optionFlags) { var spriteGroup = spriteGroupCollection.SpriteGroups.First(x => x.GroupId == this.GraphicsBlockId); var possibleSprites = spriteGroup.GetPossibleEnemySprites(this, optionFlags).Select(x => x.SpriteId).ToArray(); if (possibleSprites.Length > 0) { var spritesToUpdate = this.Sprites.Where(x => spriteRequirementCollection.RandomizableSprites.Select(y => y.SpriteId).Contains(x.SpriteId)) .ToList(); spritesToUpdate /*.Where(x => x.SpriteId != SpriteConstants.RavenSprite)*/.ToList() .ForEach(x => x.SpriteId = possibleSprites[rand.Next(possibleSprites.Length)]); if (spritesToUpdate.Count(x => x.SpriteId == SpriteConstants.FloppingFishSprite) > 1) { possibleSprites = possibleSprites.Where(x => x != SpriteConstants.FloppingFishSprite).ToArray(); if (possibleSprites.Length > 0) { bool first = true; foreach (var s in spritesToUpdate.Where(x => x.SpriteId == SpriteConstants.FloppingFishSprite).ToList()) { if (first) { first = false; continue; } s.SpriteId = possibleSprites[rand.Next(possibleSprites.Length)]; } } } // Kodongo are not allowed in overworld for now, until ASM can be fixed, then this won't be needed at all. /* * // Kodongo in Raven place will crash the game * possibleSprites = possibleSprites.Where(x => x != SpriteConstants.KodongosSprite).ToArray(); * * if (possibleSprites.Length == 0) * { * // TODO: should throw an error but let's just leave it for now * return; * } * spritesToUpdate.Where(x => x.SpriteId == SpriteConstants.RavenSprite).ToList() * .ForEach(x => x.SpriteId = possibleSprites[rand.Next(possibleSprites.Length)]); * //*/ } }
void UpdateFromOptions(OptionFlags optionFlags, RawRoomEdgeCollection rawRoomEdgeCollection) { if (optionFlags.RandomizeEnemies && (optionFlags.RandomizeEnemiesType == RandomizeEnemiesType.Chaos || optionFlags.RandomizeEnemiesType == RandomizeEnemiesType.Insanity)) // TODO: what else? { foreach (var r in rawRoomEdgeCollection.RawRoomEdges.Where(x => x.requirements.Contains("Bow"))) { r.requirements = r.requirements.Replace(",Bow,", ""); r.requirements = r.requirements.Replace("Bow,", ""); r.requirements = r.requirements.Replace(",Bow", ""); r.requirements = r.requirements.Replace("Bow", ""); } } }
private void RandomizeRooms(OptionFlags optionFlags) { roomCollection.LoadRooms(); roomCollection.RandomizeRoomSpriteGroups(spriteGroupCollection); foreach (var room in roomCollection.Rooms.Where(x => RoomIdConstants.DontRandomizeRooms.Contains(x.RoomId) == false)) { room.RandomizeSprites(rand, optionFlags, spriteGroupCollection, spriteRequirementCollection); // randomize the pot sprite table // this isn't actually used yet (needs asm changes), but we will write it anyways room.RandomizePotSprites(rand, spriteGroupCollection, spriteRequirementCollection); } }
public GraphData(RomData romData, OptionFlags optionFlags, RomEntranceCollection romEntrances, RomExitCollection romExits, RomChestCollection romChests) { this.romData = romData; this.romEntrances = romEntrances; this.romExits = romExits; this.romChests = romChests; RawEntranceCollection rawEntranceCollection = new RawEntranceCollection(); RawExitCollection rawExitCollection = new RawExitCollection(); RawItemLocationCollection rawItemLocationCollection = new RawItemLocationCollection(); RawItemEdgeCollection rawItemEdgeCollection = new RawItemEdgeCollection(); RawRoomEdgeCollection rawRoomEdgeCollection = new RawRoomEdgeCollection(); romChests.LoadChests(rawItemLocationCollection); UpdateFromRom(rawEntranceCollection, rawExitCollection, rawItemLocationCollection, rawItemEdgeCollection); UpdateFromOptions(optionFlags, rawRoomEdgeCollection); FillNodesAndEdges(rawEntranceCollection, rawExitCollection, rawItemLocationCollection, rawItemEdgeCollection, rawRoomEdgeCollection); _rawItemLocationCollection = rawItemLocationCollection; }
private void RandomizeRooms(OptionFlags optionFlags) { roomCollection.LoadRooms(); roomCollection.RandomizeRoomSpriteGroups(spriteGroupCollection, optionFlags); foreach (var room in roomCollection.Rooms) { if (RoomIdConstants.DontRandomizeRooms.Contains(room.RoomId)) { continue; } if (optionFlags.EasyModeEscape && RoomIdConstants.NoSpecialEnemiesRoomsInStandardMode.Contains(room.RoomId)) { continue; } room.RandomizeSprites(rand, optionFlags, spriteGroupCollection, spriteRequirementCollection); // randomize the pot sprite table // this isn't actually used yet (needs asm changes), but we will write it anyways room.RandomizePotSprites(rand, spriteGroupCollection, spriteRequirementCollection); } }
public Bees(RomData romData, OptionFlags optionFlags, Random rand) { this.romData = romData; this.optionFlags = optionFlags; this.rand = rand; }
public IEnumerable <SpriteRequirement> GetPossibleEnemySprites(OverworldArea area, OptionFlags optionFlags = null) { // TODO: add more logic to this? // needs to check for two subgroups, etc. return(spriteRequirementsCollection.GetUsableOverworldEnemySprites().Where(x => x.SpriteInGroup(this))); }
public DebugMode(RomData romData, OptionFlags optionFlags) { this.romData = romData; this.optionFlags = optionFlags; }
public ManualBossRandomizer(Random rand, OptionFlags optionFlags, StringBuilder spoilerFile, Graph graph) : base(rand, optionFlags, spoilerFile, graph) { }
public GraphData(RomData romData, OptionFlags optionFlags) : this(romData, optionFlags, new RomEntranceCollection(romData), new RomExitCollection(romData), new RomChestCollection(romData)) { }
public OverworldGlitchedGraphData(RomData romData, OptionFlags optionFlags, RomEntranceCollection romEntrances, RomExitCollection romExits, RomChestCollection romChests) : base(romData, optionFlags, romEntrances, romExits, romChests) { }
public void RandomizeSprites(Random rand, OptionFlags optionFlags, SpriteGroupCollection spriteGroupCollection, SpriteRequirementCollection spriteRequirementCollection) { SpriteGroup spriteGroup = null; int[] possibleSprites = new int[0]; spriteGroup = spriteGroupCollection.SpriteGroups.First(x => x.DungeonGroupId == this.GraphicsBlockId); possibleSprites = spriteGroup.GetPossibleEnemySprites(this, optionFlags).Select(x => x.SpriteId).ToArray(); if (possibleSprites.Length > 0) { var spritesToUpdate = this.Sprites.Where(x => spriteRequirementCollection.RandomizableSprites.Select(y => y.SpriteId).Contains(x.SpriteId)) .ToList(); // TODO: something less hacky for shutters. var keySprites = spritesToUpdate.Where(x => x.HasAKey).ToList(); var shutterSprites = spritesToUpdate.Where(x => this.IsShutterRoom && !x.HasAKey).ToList(); var killableSprites = spriteRequirementCollection.KillableSprites.Where(x => possibleSprites.Contains(x.SpriteId)).Select(x => x.SpriteId).ToList(); var killableKeySprites = spriteRequirementCollection.KillableSprites.Where(x => x.CannotHaveKey == false && possibleSprites.Contains(x.SpriteId)).Select(x => x.SpriteId).ToList(); var waterSprites = spriteRequirementCollection.WaterSprites.Where(x => possibleSprites.Contains(x.SpriteId)).Select(x => x.SpriteId).ToList(); if (keySprites.Count > 0 && killableKeySprites.Count == 0) { throw new Exception("Key in room without any killable enemies"); } if (shutterSprites.Count > 0 && killableSprites.Count == 0) { throw new Exception("Shutter room without any killable enemies"); } if (this.IsWaterRoom && waterSprites.Count == 0) { throw new Exception("Water room without any water sprites"); } Debug.Assert(possibleSprites.Contains(SpriteConstants.EmptySprite) == false); Debug.Assert(killableSprites.Contains(SpriteConstants.EmptySprite) == false); Debug.Assert(killableKeySprites.Contains(SpriteConstants.EmptySprite) == false); Debug.Assert(waterSprites.Contains(SpriteConstants.EmptySprite) == false); int[] possibleAbsorbableSprites = GetAbsorbableSprites(spriteRequirementCollection, optionFlags); int stalCount = 0; if (this.IsWaterRoom) { spritesToUpdate.ToList() .ForEach(x => x.SpriteId = waterSprites[rand.Next(waterSprites.Count)]); return; } else { // remove water sprites possibleSprites = possibleSprites.Where(x => waterSprites.Contains(x) == false).ToArray(); } foreach (var s in spritesToUpdate.Where(x => x.HasAKey == false).ToList()) { int spriteId = -1; // don't put stal in shutter rooms if (false == this.IsShutterRoom && rand.Next(0, 100) <= 5) { //spawn a stal spriteId = SpriteConstants.StalSprite; } else { spriteId = possibleSprites[rand.Next(possibleSprites.Length)]; } if (optionFlags.EnemiesAbsorbable && optionFlags.AbsorbableSpawnRate > 0 && optionFlags.AbsorbableTypes.Where(x => x.Value).Count() > 0) { if (rand.Next(0, 100) <= optionFlags.AbsorbableSpawnRate) { spriteId = possibleAbsorbableSprites[rand.Next(possibleAbsorbableSprites.Length)]; } } s.SpriteId = spriteId; if (spriteId == SpriteConstants.StalSprite) { stalCount++; if (stalCount > 2)// && possibleSprites.Count() > 1) // max 2 in a room { possibleSprites = possibleSprites.Where(x => x != SpriteConstants.StalSprite).ToArray(); } } //*/ } spritesToUpdate.Where(x => x.HasAKey).ToList() .ForEach(x => x.SpriteId = killableKeySprites[rand.Next(killableKeySprites.Count)]); // TODO: something less hacky for shutters. spritesToUpdate.Where(x => !x.HasAKey && this.IsShutterRoom).ToList() .ForEach(x => x.SpriteId = killableSprites[rand.Next(killableSprites.Count)]); } else if (!RoomIdConstants.BossRooms.Contains(this.RoomId)) { // TODO: log this because it's not a boss room Debug.WriteLine($"Skipped randomizing sprites in room {this.RoomId}"); } }
public ChaosBossRandomizer(Random rand, OptionFlags optionFlags, StringBuilder spoilerFile, Graph graph) : base(rand, optionFlags, spoilerFile, graph) { this.bossPool = new ChaosBossPool(rand); }
public int[] GetAbsorbableSprites(SpriteRequirementCollection spriteRequirementCollection, OptionFlags optionFlags) { var absorbables = spriteRequirementCollection.SpriteRequirements .Where(x => x.Absorbable == true) .Where(x => optionFlags.AbsorbableTypes .Where(y => y.Value) .Select(y => (int)y.Key + 0xD8) .Contains(x.SpriteId) ) .Select(x => x.SpriteId) .ToArray(); return(absorbables); }