public void Update(UltimaData ultimaData, Avatar avatar, Flags flags, IWorldMap worldMap) { if (flags.Overworld == 5) { Person person = null; // --- Items --- if (ultimaData.Items[ultimaData.ITEM_BELL].Changed) { person = FindPerson("Garam"); person.KeywordResponse2 = ReplaceSextantText(person.KeywordResponse2, GetSextantText(ultimaData.Items[ultimaData.ITEM_BELL])); } if (ultimaData.Items[ultimaData.ITEM_SKULL].Changed) { person = FindPerson("Jude"); person.Yes = ReplaceSextantText(person.Yes, GetSextantText(ultimaData.Items[ultimaData.ITEM_SKULL])); } if (ultimaData.Items[ultimaData.ITEM_NIGHTSHADE].Changed) { person = FindPerson("Virgil"); person.KeywordResponse2 = ReplaceSextantText(person.KeywordResponse2, GetSextantText(ultimaData.Items[ultimaData.ITEM_NIGHTSHADE])); } if (ultimaData.Towns[ultimaData.LOC_MAGINCIA - ultimaData.LOC_TOWNS].IsDirty()) { person = FindPerson("Shawn"); person.No = ReplaceSextantText(person.No, GetSextantText(ultimaData.Towns[ultimaData.LOC_MAGINCIA - ultimaData.LOC_TOWNS])); } // Mandrake if (ultimaData.Items[ultimaData.ITEM_MANDRAKE].Changed || ultimaData.Items[ultimaData.ITEM_MANDRAKE2].Changed) { person = FindPerson("Calumny"); if (!flags.ClothMap) { person.KeywordResponse2 = $"Mandrake is found near {GetSextantText(ultimaData.Items[ultimaData.ITEM_MANDRAKE])}\nand\n{GetSextantText(ultimaData.Items[ultimaData.ITEM_MANDRAKE2])} "; } else { var mandrakeTile = worldMap.GetCoordinate(ultimaData.Items[ultimaData.ITEM_MANDRAKE].X, ultimaData.Items[ultimaData.ITEM_MANDRAKE].Y); IList <ITile> path = null; var mandrakeRegion = worldMap.FindNearestRegion(mandrakeTile, ultimaData, out path); var mandrakeText = "Mandrake root is found only "; if (mandrakeRegion != null && mandrakeRegion.Tiles.Any(c => c.Equals(mandrakeTile))) { mandrakeText += $"in the {mandrakeRegion.Name} "; } else if (path != null && path.Count < 11) { mandrakeText += $"near the {mandrakeRegion.Name} "; } else { mandrakeText += $"near {GetSextantText(ultimaData.Items[ultimaData.ITEM_MANDRAKE])} "; } mandrakeTile = worldMap.GetCoordinate(ultimaData.Items[ultimaData.ITEM_MANDRAKE2].X, ultimaData.Items[ultimaData.ITEM_MANDRAKE2].Y); IList <ITile> path2 = null; var mandrakeRegion2 = worldMap.FindNearestRegion(mandrakeTile, ultimaData, out path2); if (mandrakeRegion == mandrakeRegion2 && path.Count < 11) { path = null; mandrakeRegion = null; } else { mandrakeRegion = mandrakeRegion2; path = path2; if (mandrakeRegion != null && mandrakeRegion.Tiles.Any(c => c == mandrakeTile)) { mandrakeText += $"and in the {mandrakeRegion.Name} "; } else if (path != null && path.Count < 11) { mandrakeText += $"and near the {mandrakeRegion.Name} "; } else { mandrakeText += $"and near {GetSextantText(ultimaData.Items[ultimaData.ITEM_MANDRAKE2])} "; } } mandrakeText += $"where the ground is always damp."; person.KeywordResponse2 = mandrakeText; } } // Horn // TODO make response descriptive if (ultimaData.Items[ultimaData.ITEM_HORN].Changed) { person = FindPerson("Malchor"); person.KeywordResponse2 = $"Some say that\nthe silver horn\nis buried at\n{GetSextantText(ultimaData.Items[ultimaData.ITEM_HORN])}"; } // Wheel // TODO make response descriptive if (ultimaData.Items[ultimaData.ITEM_WHEEL].Changed) { person = FindPerson("Lassorn"); person.KeywordResponse2 = $"She went down in\nthe deep waters\nat\n{GetSextantText(ultimaData.Items[ultimaData.ITEM_WHEEL])}!"; } // TODO Black stone currently at the moongate will need to change this text if we ever do randomize it person = FindPerson("Merlin"); // White stone // TODO make response descriptive if (ultimaData.Items[ultimaData.ITEM_WHITE_STONE].Changed) { person = FindPerson("Isaac"); person.KeywordResponse2 = $"The white stone\nsits atop the\nmountains at\n{GetSextantText(ultimaData.Items[ultimaData.ITEM_WHITE_STONE])}.\nIt can only be\nreached by one\nwho floats\nwithin the\nclouds."; ultimaData.ShrineText[6 * 3 + 2] = $"If thou dost seek the White Stone search not under the ground but at {GetSextantText(ultimaData.Items[ultimaData.ITEM_WHITE_STONE]).Replace('\n', ' ')}"; } // TODO Book, candle, runes, mystic armor and mystic weapons I'm leaving along for now. Not randomizing stuff in towns yet. // --- End Items --- // --- Shrines --- // Humility // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_HUMILITY - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Simple"); person.KeywordResponse2 = $"The shrine lies\nnear\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_HUMILITY - ultimaData.LOC_SHRINES])} and\nis guarded by\nendless hoards\nof daemons!"; person = FindPerson("Wierdrum"); person.KeywordResponse2 = $"Yes, I have been\nto the shrine,\nit lies near\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_HUMILITY - ultimaData.LOC_SHRINES])}!"; } // Compassion // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_COMPASSION - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Shapero"); person.Yes = $"Find the shrine\nof compassion\nat\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_COMPASSION - ultimaData.LOC_SHRINES])}!"; } // Sacrifice // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_SACRIFICE - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Merida"); person.No = $"The shrine is at\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_SACRIFICE - ultimaData.LOC_SHRINES])}!"; } // Justice // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_JUSTICE - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Druid"); person.KeywordResponse2 = $"The shrine is at\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_JUSTICE - ultimaData.LOC_SHRINES])}!"; } // Honesty // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_HONESTY - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Calabrini"); person.No = $"Perhaps, the\nshrine which\nlies at\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_HONESTY - ultimaData.LOC_SHRINES])}!"; } // Honor // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_HONOR - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Dergin"); person.No = $"The shrine lies at\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_HONOR - ultimaData.LOC_SHRINES])}!"; } // TODO Spirituality - Do I move this one? person = FindPerson("the Ankh of\nSpirituality"); // Valor // No on gives the directions to Valor so I grabbed his reponse that talked about the shrine and usurped it // TODO make response descriptive if (ultimaData.Shrines[ultimaData.LOC_VALOR - ultimaData.LOC_SHRINES].IsDirty()) { person = FindPerson("Sir Hrothgar"); person.No = $"Thou should seek\nthe shrine of\nvalor at\n{GetSextantText(ultimaData.Shrines[ultimaData.LOC_VALOR - ultimaData.LOC_SHRINES])}!"; } // --- End Shrines --- // --- Runes --- if (flags.Runes) { for (int i = 0; i < 8; i++) { var itemOption = ultimaData.ItemOptions[UltimaData.ITEM_RUNE_HONESTY + i]; foreach (var newPerson in itemOption.People) { person = FindPerson(newPerson.Name, newPerson.Town); if (newPerson.Health != null) { person.Health = newPerson.Health; } if (newPerson.Job != null) { person.Job = newPerson.Job; } if (newPerson.Keyword1 != null) { person.Keyword1 = newPerson.Keyword1; } if (newPerson.Keyword2 != null) { person.Keyword2 = newPerson.Keyword2; } if (newPerson.Yes != null) { person.Yes = newPerson.Yes; } if (newPerson.No != null) { person.No = newPerson.No; } if (newPerson.Question != null) { person.Question = newPerson.Question; } if (newPerson.KeywordResponse1 != null) { person.KeywordResponse1 = newPerson.KeywordResponse1; } if (newPerson.KeywordResponse2 != null) { person.KeywordResponse2 = newPerson.KeywordResponse2; } } } } // --- End Runes --- if (flags.Mantras) { person = FindPerson("Cromwell"); person.KeywordResponse2 = $"The mantra of the shrine of honesty is {Mantras[0].Text.ToUpper()}."; person = FindPerson("Cricket"); person.KeywordResponse2 = $"The mantra of the shrine of compassion is {Mantras[1].Text.ToUpper()}!"; person = FindPerson("Aesop"); person.KeywordResponse2 = $"The mantra of valor is '{Mantras[2].Text.ToUpper()}'. Use it in the shrine on the next isle!"; person = FindPerson("Silent"); person.Job = $"{Mantras[3].Text}... {Mantras[3].Text}..."; person.Health = $"{Mantras[3].Text}... {Mantras[3].Text}..."; person.Keyword1 = $"{Mantras[3].Text.ToUpper()}..."; person.KeywordResponse1 = $"{Mantras[3].Text}... {Mantras[3].Text}..."; person.Keyword2 = $"{Mantras[3].Text.ToUpper()}"; person.KeywordResponse2 = $"{Mantras[3].Text}... {Mantras[3].Text}..."; person = FindPerson("Singsong"); person.KeywordResponse2 = Mantras[4].Limerick; person = FindPerson("Kline"); person.KeywordResponse1 = $"The mantra is '{Mantras[5].Text}'."; person = FindPerson("Barren", "Skara"); person.KeywordResponse1 = $"I know it well, it is '{Mantras[6].Text.ToUpper()}'."; person = FindPerson("the Ankh of\nSpirituality"); person.Keyword2 = Mantras[6].Text.ToUpper(); person = FindPerson("Faultless"); person.KeywordResponse2 = $"The mantra for pride, being the antithesis of humility, is '{new string(Mantras[7].Text.ToString().ToUpper().Reverse().ToArray())}'."; } if (flags.WordOfPassage) { person = FindPerson("Robert Frasier"); person.Yes = $"It is '{ultimaData.WordTruth.ToLower()}'! Seek ye now the other parts!"; person = FindPerson("Lord Robert", "Empath"); person.Yes = $"It is '{ultimaData.WordLove.ToLower()}'! Seek ye now the other parts!"; person = FindPerson("Sentri"); person.KeywordResponse2 = $"I know but one of three syllables - '{ultimaData.WordCourage.ToLower()}'."; } if (flags.RandomizeSpells) { person = FindPerson("Nigel, at thy\nservice."); person.KeywordResponse2 = $"Yes, resurrection it takes: {GetRecipeText(ultimaData.SpellsRecipes['r' - 'a'].Byte)}!"; person = FindPerson("Mentorian"); if (ultimaData.SpellsRecipes['g' - 'a'].Byte == 0xFF) { person.KeywordResponse2 = $"As thou dost bear the ankh I shall tell thee. A gate spell needs { GetRecipeText(ultimaData.SpellsRecipes['g' - 'a'].Byte)}!"; } else { person.KeywordResponse2 = $"Since thou dost bear the ankh I shall tell thee. A gate spell requires { GetRecipeText(ultimaData.SpellsRecipes['g' - 'a'].Byte)}!"; } } // --- Towns and Castles --- // TODO make response descriptive if (ultimaData.Castles[0].IsDirty()) { ultimaData.LBText[3] = $"He says:\nMany truths can\nbe learned at\nthe Lycaeum. It\nlies to the\n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Castles[0])}!\n"; } if (ultimaData.Castles[1].IsDirty()) { ultimaData.LBText[4] = $"He says:\nLook for the\nmeaning of Love\nat Empath Abbey.\nThe Abbey sits\n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Castles[1])}!\n"; } if (ultimaData.Castles[2].IsDirty()) { ultimaData.LBText[5] = $"\n\nHe says:\nSerpent's Castle\nto the {CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Castles[2])}\nis where\nCourage should\nbe sought!\n"; } if (ultimaData.Towns[ultimaData.LOC_MOONGLOW - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[6] = $"\nHe says:\nThe towne\nof Moonglow to\nthe {CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_MOONGLOW - ultimaData.LOC_TOWNS])} is\nwhere the virtue\nof Honesty\nthrives!\n"; } if (ultimaData.Towns[ultimaData.LOC_BRITAIN - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[7] = $"\n\nHe says:\nThe bards in\nBritain to the\n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_BRITAIN - ultimaData.LOC_TOWNS])}\nare well versed\nin\nCompassion!\n"; } if (ultimaData.Towns[ultimaData.LOC_JHELOM - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[8] = $"\n\nHe says:\nMany valiant\nfighters come\nfrom Jhelom\nto the \n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_JHELOM - ultimaData.LOC_TOWNS])}!\n"; } if (ultimaData.Towns[ultimaData.LOC_YEW - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[9] = $"\n\n\nHe says:\nIn the city of\nYew, to the\n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_YEW - ultimaData.LOC_TOWNS])}, \nJustice is\nserved!\n"; } if (ultimaData.Towns[ultimaData.LOC_MINOC - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[10] = $"\nHe says:\nMinoc, towne of\nself-sacrifice,\nlies {CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_MINOC - ultimaData.LOC_TOWNS])}!\n"; } if (ultimaData.Towns[ultimaData.LOC_TRINSIC - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[11] = $"\nHe says:\nThe Paladins who\nstrive for Honor\nare oft seen in\nTrinsic, to the {CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_TRINSIC - ultimaData.LOC_TOWNS])}!\n"; } if (ultimaData.Towns[ultimaData.LOC_SKARA - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[12] = $"\nHe says:\nIn Skara Brae\nthe Spiritual\npath is taught.\nFind it to the\n{CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_SKARA - ultimaData.LOC_TOWNS])}!\n"; } if (ultimaData.Towns[ultimaData.LOC_MAGINCIA - ultimaData.LOC_TOWNS].IsDirty()) { ultimaData.LBText[13] = $"\n\n\nHe says:\nHumility is the\nfoundation of\nVirtue! The\nruins of proud\nMagincia are a\ntestimony unto\nthe Virtue of\nHumility!\n\nFind the Ruins\nof Magincia to\nthe {CoordinateToCardinal(ultimaData.LCB[0], ultimaData.Towns[ultimaData.LOC_MAGINCIA - ultimaData.LOC_TOWNS])}!\n"; } // --- End Towns and Castles --- // --- Other --- // TODO: Pirate location? Bucaneer's Den? person = FindPerson("Wilmoore"); } else if (flags.Overworld == 2) { var talkToLocation = new Dictionary <Tuple <byte, byte, byte>, Tuple <string, string> >(); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0xB6, 0x36), new Tuple <string, string>("<Item> is found in the Bloody Plains where the ground is always damp.", "<Item> is found in the Bloody Plains where the ground is always damp. Search on the darkest of nights!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0x64, 0xA5), new Tuple <string, string>("<Item> is found in the Fens of the Dead where the ground is always damp.", "<Item> is found in the Fens of the Dead where the ground is always damp. Search on the darkest of nights!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0x2E, 0x95), new Tuple <string, string>("<Item> may be found only near lat-J'F\" long-C'O\"!", "<Item> may be found only near lat-J'F\" long-C'O\" only on the darkest of nights!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0xCD, 0x2C), new Tuple <string, string>("<Item> may be found in the forest outside the shrine in the lake east of the Bloody Plains!", "<Item> may be found in the forest outside the shrine in the lake east of the Bloody Plains only on the darkest of nights!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0xB0, 0xD0), new Tuple <string, string>("<Item> lies at the bottom of a deep well at sea found at lat-N'A\" long-L'A\".", "<Item> lies at the bottom of a deep well at sea found at lat-N'A\" long-L'A\" but can only be found on the darkest of nights.")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0x2D, 0xAD), new Tuple <string, string>("Some say that <Item> is buried on a small isle off the tip of Spiritwood.", "Some say that <Item> is buried on a small isle off the tip of Spiritwood and can be found when the moons go dark.")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0x60, 0xD7), new Tuple <string, string>("Search the deep waters of the bay in the Cape of Heroes!", "Search the deep waters of the bay in the Cape of Heroes when the moons go dark!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0xC5, 0xF5), new Tuple <string, string>("It can be found at lat-P'F\" long-M'F\"!", "It can be found at lat-P'F\" long-M'F\" on the darkest night!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0xE0, 0x85), new Tuple <string, string>("Stand where the gate of both moons dark shall appear.", "Stand where the gate of both moons dark shall appear. Search when the moons go dark!")); talkToLocation.Add(new Tuple <byte, byte, byte>(0x00, 0x40, 0x50), new Tuple <string, string>("<Item> sits atop the Serpent's Spine. It can only be reached by one who floats within the clouds.", "<Item> sits atop the Serpent's Spine. It can only be reached by one who floats within the clouds and when the moons go dark.")); var item = ultimaData.Items[ultimaData.ITEM_BELL]; var talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item1; talkString = talkString.Replace("<Item>", "the bell of courage").CapitalizeFirstLetter(); var person = FindPerson("Garam"); person.KeywordResponse2 = talkString; item = ultimaData.Items[ultimaData.ITEM_SKULL]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item2; talkString = talkString.Replace("<Item>", "the skull").CapitalizeFirstLetter(); person = FindPerson("Jude"); person.Yes = talkString; item = ultimaData.Items[ultimaData.ITEM_NIGHTSHADE]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item2; talkString = talkString.Replace("<Item>", "nightshade").CapitalizeFirstLetter(); person = FindPerson("Virgil"); person.KeywordResponse2 = talkString; item = ultimaData.Items[ultimaData.ITEM_MANDRAKE]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item1; talkString = talkString.Replace("<Item>", "mandrake").CapitalizeFirstLetter(); person = FindPerson("Calumny"); person.KeywordResponse2 = talkString; item = ultimaData.Items[ultimaData.ITEM_HORN]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item1; talkString = talkString.Replace("<Item>", "the silver horn").CapitalizeFirstLetter(); person = FindPerson("Malchor"); person.KeywordResponse2 = talkString; item = ultimaData.Items[ultimaData.ITEM_WHEEL]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item1; talkString = talkString.Replace("<Item>", "the magical wheel").CapitalizeFirstLetter(); person = FindPerson("Lassorn"); person.KeywordResponse2 = talkString; item = ultimaData.Items[ultimaData.ITEM_BLACK_STONE]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item2; talkString = talkString.Replace("<Item>", "the black stone").CapitalizeFirstLetter(); person = FindPerson("Merlin"); person.KeywordResponse1 = talkString; item = ultimaData.Items[ultimaData.ITEM_WHITE_STONE]; talkString = talkToLocation[new Tuple <byte, byte, byte>(item.Location, item.X, item.Y)].Item1; talkString = talkString.Replace("<Item>", "the white stone").CapitalizeFirstLetter(); person = FindPerson("Isaac"); person.KeywordResponse2 = talkString; ultimaData.ShrineText[6 * 3 + 2] = "If thou dost seek the White Stone rest at the Inn of Spirits."; } if (flags.NoRequireFullParty) { ultimaData.LBHelpText[18] = "Thou dost now seem ready to make the final journey into the dark Abyss!\n"; } // --- Fixes --- if (flags.Fixes) { var person = FindPerson("Water"); person.QuestionFlag = 6; SpoilerLog.Add(SpoilerCategory.Fix, $"Water asks question"); person = FindPerson("Estro"); person.Keyword1 = "RESE"; SpoilerLog.Add(SpoilerCategory.Fix, $"Estro keyword fix"); person = FindPerson("a truth\nseeker."); person.KeywordResponse2 = person.KeywordResponse2.Replace("minutes", "cycles"); SpoilerLog.Add(SpoilerCategory.Fix, $"a truth seeker word usage"); person = FindPerson("Catriona"); person.Yes = person.Yes + "."; SpoilerLog.Add(SpoilerCategory.Fix, $"Catriona punctuation"); person = FindPerson("a ranger."); person.Yes = person.Yes.Replace("knowns", "knows"); SpoilerLog.Add(SpoilerCategory.Fix, $"Ranger typo"); person = FindPerson("Calabrini"); person.Keyword2 = "INJU"; person.Question = "Dost thou seek\nan inn or art\nthou injured?"; SpoilerLog.Add(SpoilerCategory.Fix, $"Calabrini heal keyword"); person = FindPerson("Michelle"); person.No = "Then thou should\nvisit our\nphysician!"; person.Keyword2 = "PHYS"; person.KeywordResponse1 = person.KeywordResponse1.Replace("west", "north"); person.KeywordResponse2 = "Got north and take\nthe western door."; SpoilerLog.Add(SpoilerCategory.Fix, $"Michelle heal keyword"); person = FindPerson("Tracie"); person.Look = "A starving journalist"; SpoilerLog.Add(SpoilerCategory.Fix, $"Tracie corrected look"); person = FindPerson("Iolo"); person.Look = "A charming bard"; SpoilerLog.Add(SpoilerCategory.Fix, $"Iolo corrected look"); person = FindPerson("Sir William"); person.KeywordResponse2 = person.KeywordResponse2.Replace("never", "Never"); SpoilerLog.Add(SpoilerCategory.Fix, $"Sir William capitalization"); person = FindPerson("Alkerion"); person.QuestionFlag = 6; SpoilerLog.Add(SpoilerCategory.Fix, $"Alkerion asks question"); person = FindPerson("Dupre"); person.Look = "A handsome fighter"; SpoilerLog.Add(SpoilerCategory.Fix, $"Dupre corrected look"); person = FindPerson("Virgil"); person.Question = "Is it thine?"; SpoilerLog.Add(SpoilerCategory.Fix, $"Virgil question grammar"); person = FindPerson("Shamino"); person.QuestionFlag = 6; person = FindPerson("Traveling Dan"); person.Look = "A short, rotund\nman with a hat\nand vest."; SpoilerLog.Add(SpoilerCategory.Fix, $"Traveling Dan corrected look"); person = FindPerson("Charm"); person.QuestionFlag = 6; SpoilerLog.Add(SpoilerCategory.Fix, $"Charm asks question"); person = FindPerson("Rabindranath\ntagore"); person.Name = "Rabindranath\nTagore"; SpoilerLog.Add(SpoilerCategory.Fix, $"Fix 'Rabindranath tagore' capitalization"); } }
internal TileDirtyWrapper Copy(IWorldMap worldMap) { return(new TileDirtyWrapper(worldMap.GetCoordinate(X, Y), worldMap)); }
public void Load(string path, UltimaData data, IWorldMap worldMap, Flags flags) { var file = Path.Combine(path, filename); if (flags.VGAPatch && HashHelper.BytesToString(HashHelper.GetHashSha256(file)) == upgradeFileHash) { DowngradeVGAPatch(file); } FileHelper.TryBackupOriginalFile(file); // Apply delta file to create new file var newFilePath2 = file; var newFileOutputDirectory = Path.GetDirectoryName(newFilePath2); if (!Directory.Exists(newFileOutputDirectory)) { Directory.CreateDirectory(newFileOutputDirectory); } var deltaApplier = new DeltaApplier { SkipHashCheck = false }; using (var basisStream = new FileStream($"{file}.orig", FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var deltaStream = new MemoryStream(Patches.AVATAR_EXE)) { using (var newFileStream = new FileStream(newFilePath2, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { deltaApplier.Apply(basisStream, new BinaryDeltaReader(deltaStream, new ConsoleProgressReporter()), newFileStream); } } } using (var avatarStream = new System.IO.FileStream(file, System.IO.FileMode.Open)) { avatarBytes = avatarStream.ReadAllBytes(); } AvatarOffset = new AvatarOffsetsNew(avatarBytes, $"{file}.orig"); // Items var items = new List <Item>(); for (int offset = 0; offset < 23; offset++) { items.Add(new Item(avatarBytes[AvatarOffset.ITEM_LOCATIONS_OFFSET + offset * 5], avatarBytes[AvatarOffset.ITEM_LOCATIONS_OFFSET + offset * 5 + 1], avatarBytes[AvatarOffset.ITEM_LOCATIONS_OFFSET + offset * 5 + 2])); } data.SetItems(items); // Moongates var moongates = new List <Tile>(); for (byte offset = 0; offset < 8; offset++) { moongates.Add(worldMap.GetCoordinate(avatarBytes[AvatarOffset.MOONGATE_X_OFFSET + offset], avatarBytes[AvatarOffset.MOONGATE_Y_OFFSET + offset])); } data.SetMoongates(moongates); // LCB var lcb = new List <Tile>(); var lcbLoc = worldMap.GetCoordinate(avatarBytes[AvatarOffset.AREA_X_OFFSET + data.LOC_LCB - 1], avatarBytes[AvatarOffset.AREA_Y_OFFSET + data.LOC_LCB - 1]); lcb.Add(lcbLoc); lcb.Add(worldMap.GetCoordinate(lcbLoc.X - 1, lcbLoc.Y)); lcb.Add(worldMap.GetCoordinate(lcbLoc.X + 1, lcbLoc.Y)); data.SetLCB(lcb); // Castles var castles = new List <TileDirtyWrapper>(); for (byte offset = 0; offset < 3; offset++) { castles.Add(new TileDirtyWrapper(worldMap.GetCoordinate(avatarBytes[AvatarOffset.AREA_X_OFFSET + data.LOC_CASTLES + offset], avatarBytes[AvatarOffset.AREA_Y_OFFSET + data.LOC_CASTLES + offset]), worldMap)); } data.SetCastles(castles); // Towns var towns = new List <TileDirtyWrapper>(); for (byte offset = 0; offset < 8 + 4; offset++) { towns.Add(new TileDirtyWrapper(worldMap.GetCoordinate(avatarBytes[AvatarOffset.AREA_X_OFFSET + data.LOC_TOWNS + offset - 1], avatarBytes[AvatarOffset.AREA_Y_OFFSET + data.LOC_TOWNS + offset - 1]), worldMap)); } data.SetTowns(towns); // Shrines var shrines = new List <TileDirtyWrapper>(); for (byte offset = 0; offset < 8; offset++) { shrines.Add(new TileDirtyWrapper(worldMap.GetCoordinate(avatarBytes[AvatarOffset.AREA_X_OFFSET + data.LOC_SHRINES + offset - 1], avatarBytes[AvatarOffset.AREA_Y_OFFSET + data.LOC_SHRINES + offset - 1]), worldMap)); } data.SetShrines(shrines); // Dungeons var dungeons = new List <Tile>(); for (byte offset = 0; offset < 8; offset++) { dungeons.Add(worldMap.GetCoordinate(avatarBytes[AvatarOffset.AREA_X_OFFSET + data.LOC_DUNGEONS + offset - 1], avatarBytes[AvatarOffset.AREA_Y_OFFSET + data.LOC_DUNGEONS + offset - 1])); } data.SetDungeons(dungeons); // Balloon Spawn data.BalloonSpawn = worldMap.GetCoordinate(avatarBytes[AvatarOffset.BALLOON_SPAWN_LOCATION_X_OFFSET], avatarBytes[AvatarOffset.BALLOON_SPAWN_LOCATION_Y_OFFSET]); OriginalShrineText = new List <string>(); OriginalShrineTextStartOffset = new List <int>(); var shrineTextBytes = new List <byte>(); var textOffset = AvatarOffset.SHRINE_TEXT_OFFSET; for (int i = 0; i < 24; i++) { OriginalShrineTextStartOffset.Add(textOffset); for (; avatarBytes[textOffset] != 0x0A && avatarBytes[textOffset] != 0x00; textOffset++) { shrineTextBytes.Add(avatarBytes[textOffset]); } OriginalShrineText.Add(System.Text.Encoding.Default.GetString(shrineTextBytes.ToArray())); shrineTextBytes.Clear(); if (avatarBytes[textOffset] == 0x0A) { textOffset++; } textOffset++; } data.ShrineText.Clear(); data.ShrineText.AddRange(OriginalShrineText); OriginalLBText = new List <string>(); OriginalLBTextStartOffset = new List <int>(); var lbTextBytes = new List <byte>(); textOffset = AvatarOffset.LB_TEXT_OFFSET; // He has more text than 19 but there is some weird stuff after 19 that doesn't get turned into text well. And as far as I can tell we won't need any text after 19 for (int i = 0; i < 19; i++) { OriginalLBTextStartOffset.Add(textOffset); for (; avatarBytes[textOffset] != 0x00 && avatarBytes[textOffset] != 0xAB; textOffset++) { lbTextBytes.Add(avatarBytes[textOffset]); } OriginalLBText.Add(System.Text.Encoding.Default.GetString(lbTextBytes.ToArray())); lbTextBytes.Clear(); if (avatarBytes[textOffset] == 0x0A || avatarBytes[textOffset] == 0xAB) { textOffset++; } textOffset++; } data.LBText.Clear(); data.LBText.AddRange(OriginalLBText); OriginalLBHelpText = new List <string>(); OriginalLBHelpTextStartOffset = new List <int>(); lbTextBytes = new List <byte>(); textOffset = AvatarOffset.LB_HELP_TEXT_OFFSET; for (int i = 0; i < 21; i++) { OriginalLBHelpTextStartOffset.Add(textOffset); for (; avatarBytes[textOffset] != 0x00 && avatarBytes[textOffset] != 0xAB; textOffset++) { lbTextBytes.Add(avatarBytes[textOffset]); } OriginalLBHelpText.Add(System.Text.Encoding.Default.GetString(lbTextBytes.ToArray())); lbTextBytes.Clear(); if (avatarBytes[textOffset] == 0x0A || avatarBytes[textOffset] == 0xAB) { textOffset++; } textOffset++; } data.LBHelpText.Clear(); data.LBHelpText.AddRange(OriginalLBHelpText); var mantraTextBytes = new List <byte>(); textOffset = AvatarOffset.MANTRA_OFFSET; MantraMaxSize = 0; for (int i = 0; i < 8; i++) { for (; avatarBytes[textOffset] != 0x00; textOffset++) { mantraTextBytes.Add(avatarBytes[textOffset]); } data.Mantras.Add(System.Text.Encoding.Default.GetString(mantraTextBytes.ToArray())); MantraMaxSize += data.Mantras[i].Length + 1; mantraTextBytes.Clear(); textOffset++; } var wordOfPassageTextBytes = new List <byte>(); for (int offSet = 0; offSet < 9; offSet++) { wordOfPassageTextBytes.Add(avatarBytes[AvatarOffset.WORD_OF_PASSAGE + offSet]); } data.WordOfPassage = System.Text.Encoding.Default.GetString(wordOfPassageTextBytes.ToArray()); data.DaemonSpawnX1 = avatarBytes[AvatarOffset.DEMON_SPAWN_TRIGGER_X1_OFFSET]; data.DaemonSpawnX2 = avatarBytes[AvatarOffset.DEMON_SPAWN_TRIGGER_X2_OFFSET]; data.DaemonSpawnY1 = avatarBytes[AvatarOffset.DEMON_SPAWN_TRIGGER_Y1_OFFSET]; data.DaemonSpawnY2 = avatarBytes[AvatarOffset.DEMON_SPAWN_TRIGGER_Y2_OFFSET]; data.DaemonSpawnLocationX = avatarBytes[AvatarOffset.DEMON_SPAWN_LOCATION_X_OFFSET]; for (int i = 0; i < 8; i++) { data.PirateCove.Add(new Coordinate(avatarBytes[i + AvatarOffset.PIRATE_COVE_X_OFFSET], avatarBytes[i + AvatarOffset.PIRATE_COVE_Y_OFFSET])); } data.PirateCoveSpawnTrigger = new Coordinate(avatarBytes[AvatarOffset.PIRATE_COVE_SPAWN_TRIGGER_X_OFFSET1], avatarBytes[AvatarOffset.PIRATE_COVE_SPAWN_TRIGGER_Y_OFFSET1]); data.WhirlpoolExit = new Coordinate(avatarBytes[AvatarOffset.WHIRLPOOL_EXIT_X_OFFSET], avatarBytes[AvatarOffset.WHIRLPOOL_EXIT_Y_OFFSET]); data.SpellsRecipes = new List <ByteDirtyWrapper>(); for (int i = 0; i < 26; i++) { data.SpellsRecipes.Add(new ByteDirtyWrapper(avatarBytes[AvatarOffset.SPELL_RECIPE_OFFSET + i])); } data.BlinkCastExclusionX1 = avatarBytes[AvatarOffset.BLINK_CAST_EXCLUSION_X1_OFFSET]; data.BlinkCastExclusionX2 = avatarBytes[AvatarOffset.BLINK_CAST_EXCLUSION_X2_OFFSET]; data.BlinkCastExclusionY1 = avatarBytes[AvatarOffset.BLINK_CAST_EXCLUSION_Y1_OFFSET]; data.BlinkCastExclusionY2 = avatarBytes[AvatarOffset.BLINK_CAST_EXCLUSION_Y2_OFFSET]; data.BlinkDestinationExclusionX1 = avatarBytes[AvatarOffset.BLINK_DESTINATION_EXCLUSION_X1_OFFSET]; data.BlinkDestinationExclusionX2 = avatarBytes[AvatarOffset.BLINK_DESTINATION_EXCLUSION_X2_OFFSET]; data.BlinkDestinationExclusionY1 = avatarBytes[AvatarOffset.BLINK_DESTINATION_EXCLUSION_Y1_OFFSET]; data.BlinkDestinationExclusionY2 = avatarBytes[AvatarOffset.BLINK_DESTINATION_EXCLUSION_Y2_OFFSET]; data.BlinkDestinationExclusion2X1 = avatarBytes[AvatarOffset.BLINK_DESTINATION2_EXCLUSION_X1_OFFSET]; data.BlinkDestinationExclusion2X2 = avatarBytes[AvatarOffset.BLINK_DESTINATION2_EXCLUSION_X2_OFFSET]; data.BlinkDestinationExclusion2Y1 = avatarBytes[AvatarOffset.BLINK_DESTINATION2_EXCLUSION_Y1_OFFSET]; data.BlinkDestinationExclusion2Y2 = avatarBytes[AvatarOffset.BLINK_DESTINATION2_EXCLUSION_Y2_OFFSET]; for (int i = 0; i < 13; i++) { data.AbyssEjectionLocations.Add(new Coordinate(avatarBytes[i + AvatarOffset.ABYSS_EJECTION_LOCATIONS_X], avatarBytes[i + AvatarOffset.ABYSS_EJECTION_LOCATIONS_Y])); } for (int townIdx = 0; townIdx < 16; townIdx++) { data.ShopLocations.Add(new List <byte>()); for (int shopIdx = 0; shopIdx < 8; shopIdx++) { data.ShopLocations[townIdx].Add(avatarBytes[townIdx * 8 + shopIdx + AvatarOffset.SHOP_LOCATION_OFFSET]); } } }
public TileDirtyWrapper(Tile tile, IWorldMap worldMap) { _original = worldMap.GetCoordinate(tile.X, tile.Y); _current = worldMap.GetCoordinate(tile.X, tile.Y); }