예제 #1
0
        void CustomTalkShops()
        {
            foreach (var sCustomTalk in _builder.Sheet("CustomTalk"))
            {
                var instructions = ScriptInstruction.Read(sCustomTalk, 30);

                var shopInstructions = instructions.Where(i => i.Label.Contains("SHOP") && !i.Label.Contains("LOGMSG")).ToArray();
                if (shopInstructions.Length == 0)
                {
                    continue;
                }

                var sNpcs = sCustomTalk.Sheet.Collection.ENpcs.FindWithData(sCustomTalk.Key).ToArray();
                if (sNpcs.Length == 0)
                {
                    continue;
                }

                foreach (var shopInstruction in shopInstructions)
                {
                    var shopKey = (int)shopInstruction.Argument;
                    if (Hacks.ExcludedShops.Contains(shopKey))
                    {
                        continue;
                    }

                    // Setup a disposal shop.
                    if (shopInstruction.Label == "SHOP_DISPOSAL")
                    {
                        DisposalShops.BuildShop(_builder, sNpcs, (int)shopInstruction.Argument);
                        continue;
                    }

                    // Missing shop definitions?
                    if (!_shopsByKey.TryGetValue(shopKey, out var shop))
                    {
                        // todo: print relevant NPCs, text?
                        DatabaseBuilder.PrintLine($"Shop {shopKey} not found, skipping.");
                        continue;
                    }

                    if (shop.Name == "Unknown Shop")
                    {
                        var name = Hacks.GetShopName((SaintCoinach.Text.XivString)sCustomTalk.GetRaw("Name"), shopInstruction);
                        if (name.Contains("[not in Saint]"))
                        {
                            DatabaseBuilder.PrintLine($"{string.Join(", ", sNpcs.Select(e => e.Singular.ToString()))} has shop {name}");
                            continue;
                        }
                        shop.Name = name;
                    }

                    shop.ENpcs = sNpcs.Union(shop.ENpcs).Distinct().ToArray();
                }
            }
        }
예제 #2
0
        void BuildQuests()
        {
            var lQuestsByKey = _builder.Libra.Table <Libra.Quest>().ToDictionary(q => q.Key);

            foreach (var sQuest in _builder.Sheet <Saint.Quest>())
            {
                if (sQuest.Key == 65536 || sQuest.Name == "")
                {
                    continue; // Test quests
                }
                dynamic quest = new JObject();
                quest.id = sQuest.Key;
                _builder.Localize.Strings((JObject)quest, sQuest, Utils.SanitizeQuestName, "Name");
                quest.patch = PatchDatabase.Get("quest", sQuest.Key);
                quest.sort  = sQuest.SortKey;

                // Quest location
                var questIssuer = (sQuest.IssuingENpc?.Locations?.Count() ?? 0) > 0 ? sQuest.IssuingENpc : null;
                var sPlaceName  = sQuest.PlaceName;
                if (sPlaceName.Name == "" && questIssuer != null)
                {
                    sPlaceName = questIssuer.Locations.First().PlaceName;
                }

                _builder.Localize.Column((JObject)quest, sPlaceName, "Name", "location",
                                         x => x == "" ? "???" : x.ToString());

                // Repeatability
                if (sQuest.RepeatInterval == Saint.QuestRepeatInterval.Daily)
                {
                    quest.interval = "daily";
                }
                else if (sQuest.RepeatInterval == Saint.QuestRepeatInterval.Weekly)
                {
                    quest.interval = "weekly";
                }

                if (sQuest.IsRepeatable)
                {
                    quest.repeatable = 1;
                }

                // Miscellaneous
                if (sQuest.Icon != null)
                {
                    quest.icon = IconDatabase.EnsureEntry("quest", sQuest.Icon);
                }

                if (sQuest.BeastTribe.Key != 0)
                {
                    quest.beast = sQuest.BeastTribe.Key;
                }

                ImportQuestEventIcon(quest, sQuest);

                // Quest issuer
                if (questIssuer != null)
                {
                    var npc = AddQuestNpc(quest, questIssuer);
                    if (npc != null)
                    {
                        quest.issuer = questIssuer.Key;
                    }
                }

                // Quest target
                var questTarget = sQuest.TargetENpc;
                if (questTarget != null)
                {
                    var npc = AddQuestNpc(quest, questTarget);
                    if (npc != null)
                    {
                        quest.target = questTarget.Key;
                    }
                }

                // Involved
                if (_npcsByQuestKey.TryGetValue(sQuest.Key, out var involvedNpcKeys))
                {
                    foreach (var npcKey in involvedNpcKeys)
                    {
                        var sInvolvedEnpc = _builder.Realm.GameData.ENpcs[npcKey];
                        if (sInvolvedEnpc == null || sInvolvedEnpc == questTarget || sInvolvedEnpc == questIssuer)
                        {
                            continue;
                        }

                        var npc = AddQuestNpc(quest, sInvolvedEnpc);
                        if (npc == null)
                        {
                            continue;
                        }

                        if (quest.involved == null)
                        {
                            quest.involved = new JArray();
                        }
                        quest.involved.Add(npcKey);
                    }
                }

                // Journal Genre
                quest.genre = sQuest.JournalGenre.Key;

                // Rewards
                dynamic rewards = new JObject();
                if (sQuest.Rewards.Gil > 0)
                {
                    rewards.gil = sQuest.Rewards.Gil;
                }

                if (sQuest.Rewards.Emote.Key > 0)
                {
                    rewards.emote = sQuest.Rewards.Emote.Name.ToString();
                }

                if (sQuest.Rewards.ClassJob.Key > 0)
                {
                    rewards.job = sQuest.Rewards.ClassJob.Key;
                }

                if (sQuest.AsInt32("CurrencyRewardCount") > 0)
                {
                    rewards.gcseal = sQuest.AsInt32("CurrencyRewardCount");
                }

                if (sQuest.Rewards.Action.Key > 0)
                {
                    rewards.action = sQuest.Rewards.Action.Key;

                    _builder.Db.AddReference(quest, "action", sQuest.Rewards.Action.Key, false);
                }

                var sInstanceContentReward = sQuest.Rewards.InstanceContent;
                if (sInstanceContentReward.Key > 0)
                {
                    var instance = _builder.Db.Instances.FirstOrDefault(i => i.id == sInstanceContentReward.Key);
                    if (instance != null)
                    {
                        instance.unlockedByQuest = sQuest.Key;
                        rewards.instance         = sInstanceContentReward.Key;

                        _builder.Db.AddReference(quest, "instance", sInstanceContentReward.Key, false);
                        _builder.Db.AddReference(instance, "quest", sQuest.Key, false);
                    }
                }

                if (sQuest.Rewards.Reputation > 0)
                {
                    rewards.reputation = sQuest.Rewards.Reputation;
                }

                if (sQuest.Rewards.QuestRewardOther.Name == "Aether Current")
                {
                    rewards.aetherCurrent = 1;
                }

                foreach (var sQuestRewardItemGroup in sQuest.Rewards.Items)
                {
                    foreach (var sQuestRewardItem in sQuestRewardItemGroup.Items)
                    {
                        if (rewards.items == null)
                        {
                            rewards.items = new JArray();
                        }

                        var maxCount = sQuestRewardItem.Counts.Max();

                        dynamic o = new JObject();
                        if (maxCount > 1)
                        {
                            o.num = maxCount;
                        }
                        o.id = sQuestRewardItem.Item.Key;

                        if (sQuestRewardItemGroup.Type == Saint.QuestRewardGroupType.One)
                        {
                            o.one = 1;
                        }

                        if (sQuestRewardItem.IsHq)
                        {
                            o.hq = 1;
                        }

                        rewards.items.Add(o);

                        try
                        {
                            var item = _builder.Db.ItemsById[sQuestRewardItem.Item.Key];
                            if (item.quests == null)
                            {
                                item.quests = new JArray();
                            }
                            JArray quests = item.quests;

                            if (!quests.Any(id => ((int)id) == sQuest.Key))
                            {
                                quests.Add(sQuest.Key);
                            }
                            _builder.Db.AddReference(item, "quest", sQuest.Key, false);
                        }
                        catch (KeyNotFoundException ignored)
                        {
                            DatabaseBuilder.PrintLine($"Reward item '{sQuestRewardItem.Item.Key}' not found for Quest '{quest.Key}'.");
                        }

                        _builder.Db.AddReference(quest, "item", sQuestRewardItem.Item.Key, false);
                    }
                }

                // Libra supplemental rewards.
                if (lQuestsByKey.TryGetValue(sQuest.Key, out var lQuest))
                {
                    dynamic data = JsonConvert.DeserializeObject(lQuest.data);
                    int     xp   = 0;
                    if (data.exp != null && int.TryParse((string)data.exp, out xp))
                    {
                        rewards.xp = xp;
                    }
                }

                // Scripts
                var instructions = ScriptInstruction.Read(sQuest, 50);

                // Script instance unlocks.
                if (!sQuest.IsRepeatable)
                {
                    var instanceReferences = instructions.Where(i => i.Label.StartsWith("INSTANCEDUNGEON")).ToArray();
                    foreach (var instanceReference in instanceReferences)
                    {
                        var key      = (int)instanceReference.Argument;
                        var instance = _builder.Db.Instances.FirstOrDefault(i => ((int)i.id) == key);
                        if (instance == null)
                        {
                            continue; // Probably a guildhest.
                        }
                        if (instance.unlockedByQuest != null)
                        {
                            continue;
                        }

                        if (!instructions.Any(i => i.Label == "UNLOCK_ADD_NEW_CONTENT_TO_CF" || i.Label.StartsWith("UNLOCK_DUNGEON")))
                        {
                            // Some quests reference instances for the retrieval of items.
                            // Don't treat these as unlocks.
                            if (instructions.Any(i => i.Label.StartsWith("LOC_ITEM")))
                            {
                                continue;
                            }
                        }

                        instance.unlockedByQuest = sQuest.Key;
                        rewards.instance         = key;

                        _builder.Db.AddReference(quest, "instance", key, false);
                        _builder.Db.AddReference(instance, "quest", sQuest.Key, false);
                    }
                }

                // Used items.
                foreach (var instruction in instructions)
                {
                    if (!instruction.Label.StartsWith("RITEM") && !instruction.Label.StartsWith("QUEST_ITEM"))
                    {
                        continue;
                    }

                    var key = (int)instruction.Argument;
                    if (_builder.Db.ItemsById.TryGetValue(key, out var item))
                    {
                        if (item.usedInQuest == null)
                        {
                            item.usedInQuest = new JArray();
                        }

                        JArray usedInQuest = item.usedInQuest;
                        if (usedInQuest.Any(i => (int)i == sQuest.Key))
                        {
                            continue;
                        }

                        item.usedInQuest.Add(sQuest.Key);

                        if (quest.usedItems == null)
                        {
                            quest.usedItems = new JArray();
                        }
                        quest.usedItems.Add(key);

                        _builder.Db.AddReference(item, "quest", sQuest.Key, false);
                        _builder.Db.AddReference(quest, "item", key, false);
                    }
                }

                ImportQuestLore(quest, sQuest, instructions);

                if (((JObject)rewards).Count > 0)
                {
                    quest.reward = rewards;
                }

                ImportQuestRequirements(quest, sQuest);

                _builder.Db.Quests.Add(quest);
                _builder.Db.QuestsById[sQuest.Key] = quest;
            }
        }