public static void ApplyEdeaFix(FileSource battleSource, FileSource fieldSource) { // clone encounter var encFile = EncounterFile.FromSource(battleSource); encFile.Encounters[845] = encFile.Encounters[136]; battleSource.ReplaceFile(EncounterFile.Path, encFile.Encode()); // redirect field script to clone var fieldName = "glyagu1"; var field = Field.FieldScript.FromSource(fieldSource, fieldName); var script = field.Entities[2].Scripts[4].Instructions; for (int i = 0; i < script.Count - 2; i++) { if (script[i].OpCode == Field.FieldScript.OpCodesReverse["pshn_l"] && script[i].Param == 136) { if (script[i + 2].OpCode == Field.FieldScript.OpCodesReverse["battle"]) { field.Entities[2].Scripts[4].Instructions[i].Param = 845; } } } StorySkip.SaveToSource(fieldSource, fieldName, field.Encode()); }
public static Dictionary <int, int> Shuffle(FileSource battleSource, bool rebalance, int seed) { var random = new Random(seed); var encFilePath = EncounterFile.Path; var sourceFile = EncounterFile.FromSource(battleSource, encFilePath); var newFile = EncounterFile.FromSource(battleSource, encFilePath); var bossEncounterIds = Encounters.Keys.ToList(); var matchIdPool = Encounters.Keys.ToList(); var encIdMap = new Dictionary <int, int>(); foreach (var encId in bossEncounterIds) { // pick an encounter from the pool var matchedId = matchIdPool[random.Next(matchIdPool.Count)]; matchIdPool.Remove(matchedId); encIdMap.Add(encId, matchedId); // copy the monster slots from the other encounter for (int i = 0; i < 8; i++) { var monsterId = sourceFile.Encounters[matchedId].Slots[i].MonsterID; newFile.Encounters[encId].Slots[i] = sourceFile.Encounters[matchedId].Slots[i]; if (rebalance) { // retain level newFile.Encounters[encId].Slots[i].Level = sourceFile.Encounters[encId].Slots[i].Level; } // update any encounter ID checks in the monster's AI scripts foreach (var ec in EncounterChecks.Where(ec => ec.MonsterID == monsterId && ec.EncounterID == matchedId)) { var monster = sourceFile.Encounters[matchedId].Slots[i].GetMonster(battleSource); var script = monster.AI.Scripts.EventScripts[ec.Script]; script[ec.Instruction].Args[3] = (short)encId; battleSource.ReplaceFile(Monster.GetPath(monsterId), monster.Encode()); } } // force the nameless sorceresses to fight in the commencement room // so they can do the melty background thing without crashing the game if (matchedId == 813) { var sorceressEncounter = sourceFile.Encounters[813]; newFile.Encounters[encId].Scene = sorceressEncounter.Scene; newFile.Encounters[encId].MainCamera = sorceressEncounter.MainCamera; newFile.Encounters[encId].MainCameraAnimation = sorceressEncounter.MainCameraAnimation; newFile.Encounters[encId].SecondaryCamera = sorceressEncounter.SecondaryCamera; newFile.Encounters[encId].SecondaryCameraAnimation = sorceressEncounter.SecondaryCameraAnimation; } } // save new encounter file battleSource.ReplaceFile(encFilePath, newFile.Encode()); return(encIdMap); }
public static void SetRewards(FileSource battleSource, FileSource fieldSource, int seed) { var random = new Random(seed + 11); var major = new List <Reward>(Major); var minor = new List <Reward>(Minor); var encounterFile = EncounterFile.FromSource(battleSource); // bosses with no fixed location are assigned rewards that don't require field scripting foreach (var boss in Boss.Bosses.Where(b => !b.FixedField)) { var battleOnlyMajor = major.Where(r => r.Type == RewardType.GF || r.Type == RewardType.Item).ToList(); var majorIndex = random.Next(0, battleOnlyMajor.Count); var minorIndex = random.Next(0, minor.Count); // remove any existing item drops ClearDrops(battleSource, encounterFile, boss.EncounterID); switch (battleOnlyMajor[majorIndex].Type) { case RewardType.GF: GiveGF(battleSource, encounterFile, boss.EncounterID, battleOnlyMajor[majorIndex].ID); break; case RewardType.Item: GiveItem(battleSource, encounterFile, boss.EncounterID, battleOnlyMajor[majorIndex].ID); break; } // minor rewards are all items GiveItem(battleSource, encounterFile, boss.EncounterID, minor[minorIndex].ID); // remove rewards from the pool major.Remove(battleOnlyMajor[majorIndex]); battleOnlyMajor.RemoveAt(majorIndex); minor.RemoveAt(minorIndex); } // the rest of the bosses can be assigned anything foreach (var boss in Boss.Bosses.Where(b => b.FixedField)) { if (major.Count > 0) { var majorIndex = random.Next(0, major.Count); // remove any existing item drops ClearDrops(battleSource, encounterFile, boss.EncounterID); switch (major[majorIndex].Type) { case RewardType.Character: GiveCharacter(fieldSource, boss.EncounterID, major[majorIndex]); break; case RewardType.GF: GiveGF(battleSource, encounterFile, boss.EncounterID, major[majorIndex].ID); break; case RewardType.Special: GiveSpecial(fieldSource, boss.EncounterID, major[majorIndex]); break; case RewardType.Seal: break; case RewardType.Item: GiveItem(battleSource, encounterFile, boss.EncounterID, major[majorIndex].ID); break; } major.RemoveAt(majorIndex); } // minor rewards are all items var minorIndex = random.Next(0, minor.Count); GiveItem(battleSource, encounterFile, boss.EncounterID, minor[minorIndex].ID); minor.RemoveAt(minorIndex); } }
public static void Apply(FileSource battleSource, Dictionary <int, int> encounterMap) { var cleanEncFile = EncounterFile.FromSource(battleSource, EncounterFile.Path); var newEncFile = EncounterFile.FromSource(battleSource, EncounterFile.Path); foreach (var encID in encounterMap.Keys) { var matchedEncID = encounterMap[encID]; // copy monster slots from the incoming encounter for (int i = 0; i < 8; i++) { var newMonsterID = cleanEncFile.Encounters[matchedEncID].Slots[i].MonsterID; newEncFile.Encounters[encID].Slots[i] = cleanEncFile.Encounters[matchedEncID].Slots[i]; // update any encounter ID checks in the monster's AI scripts FixEncounterChecks(battleSource, newMonsterID, encID, matchedEncID); // tonberry king var tonberryIDs = new List <int>() { 236, 237, 238 }; if (tonberryIDs.Contains(matchedEncID)) { if (i == 0) { // enable tonberry king newEncFile.Encounters[encID].Slots[i].Enabled = true; newEncFile.Encounters[encID].Slots[i].Hidden = false; newEncFile.Encounters[encID].Slots[i].Unloaded = false; newEncFile.Encounters[encID].Slots[i].Untargetable = false; } else { // disable everything else newEncFile.Encounters[encID].Slots[i].Enabled = false; newEncFile.Encounters[encID].Slots[i].Hidden = true; newEncFile.Encounters[encID].Slots[i].Unloaded = true; newEncFile.Encounters[encID].Slots[i].Untargetable = true; } } if (tonberryIDs.Contains(encID)) { // disable tonberry king's replacement, to be summoned by tonberry newEncFile.Encounters[encID].Slots[i].Enabled = false; break; } } // award diablos GF for beating whoever is in the lamp to avoid softlock if (encID == 811) { FixDiablos(battleSource, newEncFile, matchedEncID); } // force the sorceresses to fight in their normal scene to avoid crash if (matchedEncID == 813) { FixSorceresses(cleanEncFile, newEncFile, encID); } } // skip shot tutorial for iguion fight if irvine isn't present FixIguions(battleSource, cleanEncFile); // remove odin's instakill attack FixOdin(battleSource, cleanEncFile); // save changes battleSource.ReplaceFile(EncounterFile.Path, newEncFile.Encode()); }