public static string GetShopName(ScriptInstruction si) { if (si.Label.Contains("FCCSHOP")) { return("Spend company credits (items)"); } else if (si.Label == "MOBSHOP1") { return("Exchange Centurio Seals"); } else if (si.Label == "MOBSHOP2") { return("Exchange Centurio Seals (Advanced)"); } else if (si.Label == "SHOP_SPOIL") { return("Exchange Spoils"); } else if (si.Label == "SPECIAL_SHOP0" && si.Argument == 1769813) { return("Achievement Rewards"); } else if (si.Label == "SPECIAL_SHOP1" && si.Argument == 1769845) { return("Achievement Rewards 2"); } else if (si.Label == "SPECIAL_SHOP2" && si.Argument == 1769846) { return("Achievement Rewards 3"); } else if (si.Label == "SHOP_0" && si.Argument == 1769842) { return("Gold Certificates of Commendation"); } else if (si.Label == "SHOP_1" && si.Argument == 1769841) { return("Silver Certificates of Commendation"); } else if (si.Label == "SHOP" && si.Argument == 1769812) { return("PVP Rewards"); } else if (si.Label == "REPLICA_SHOP0" && si.Argument == 262918) { return("Purchase a Eureka weapon replica (DoW)."); } else if (si.Label == "REPLICA_SHOP1" && si.Argument == 262922) { return("Purchase a Eureka weapon replica (DoM)."); } else if (si.Label == "FREE_SHOP_BATTLE" && si.Argument == 1769898) { return("Battle Achievement Rewards"); } else if (si.Label == "FREE_SHOP_PVP" && si.Argument == 1769899) { return("PvP Achievement Rewards"); } else if (si.Label == "FREE_SHOP_CHARACTER" && si.Argument == 1769900) { return("Character Achievement Rewards"); } else if (si.Label == "FREE_SHOP_ITEM" && si.Argument == 1769901) { return("Item Achievement Rewards"); } else if (si.Label == "FREE_SHOP_CRAFT" && si.Argument == 1769902) { return("Crafting Achievement Rewards"); } else if (si.Label == "FREE_SHOP_GATHERING" && si.Argument == 1769903) { return("Gathering Achievement Rewards"); } else if (si.Label == "FREE_SHOP_QUEST" && si.Argument == 1769904) { return("Quest Achievement Rewards"); } else if (si.Label == "FREE_SHOP_EXPLORATION" && si.Argument == 1769905) { return("Exploration Achievement Rewards"); } else if (si.Label == "FREE_SHOP_GRANDCOMPANY" && si.Argument == 1769906) { return("Grand Company Achievement Rewards"); } else { DatabaseBuilder.PrintLine($"Unknown shop label {si.Label}, arg {si.Argument}."); return(si.Label); } }
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; } }
private void OptimiseIncrementsAndDecrements(int iIndex) { // ADD var, 1 => INC var // ADD var, -1 => DEC var // SUB var, 1 => DEC var // SUB var, -1 => INC var ScriptInstruction scriptInstruction = m_scriptExecutable.InstructionsInternal[iIndex]; // must be ADD or SUB if (scriptInstruction.Opcode != Opcode.ADD && scriptInstruction.Opcode != Opcode.SUB) { return; } // destination must be simple or array variable if (scriptInstruction.Operand0.Type != OperandType.Variable && scriptInstruction.Operand0.Type != OperandType.LiteralIndexedVariable && scriptInstruction.Operand0.Type != OperandType.VariableIndexedVariable) { return; } // source must be literal if (scriptInstruction.Operand1.Type != OperandType.Literal) { return; } // source literal must be numeric object objectLiteral = scriptInstruction.Operand1.Value; Type typeLiteral = objectLiteral.GetType(); if (typeLiteral != typeof(int) && typeLiteral != typeof(float)) { return; } // if int literal, value must be 1 or -1 if (typeLiteral == typeof(int) && Math.Abs((int)objectLiteral) != 1) { return; } // if float literal, value must be 1.0 or -1.0 if (typeLiteral == typeof(float) && Math.Abs((float)objectLiteral) != 1.0f) { return; } InsertOptimiserInfo(iIndex, "Increment/Decrement Optimisation"); float fValue = 0.0f; if (typeLiteral == typeof(int)) { // int fValue = (float)(int)objectLiteral; } else { // floar fValue = (float)objectLiteral; } Opcode opcodeOld = scriptInstruction.Opcode; bool bIncrement = opcodeOld == Opcode.ADD && fValue > 0.0f || opcodeOld == Opcode.SUB && fValue < 0.0f; scriptInstruction.Opcode = bIncrement ? Opcode.INC : Opcode.DEC; scriptInstruction.Operand1 = null; m_bOptimisationComplete = false; }
public void Write(ScriptInstruction instruction) { base.Write((byte)instruction); }
private void EliminateSelfAssignments(int iIndex) { // MOV v, v => NOP // or // MOV v1[v2], v1[v2] => NOP // or // MOV v[lit], v[lit] => NOP ScriptInstruction scriptInstruction = m_scriptExecutable.InstructionsInternal[iIndex]; // must be MOV if (scriptInstruction.Opcode != Opcode.MOV) { return; } // dest and source must be same type Operand operand0 = scriptInstruction.Operand0; Operand operand1 = scriptInstruction.Operand1; if (operand0.Type != operand1.Type) { return; } // dest and source must be simple or array ref if (operand0.Type != OperandType.Variable && operand0.Type != OperandType.LiteralIndexedVariable && operand1.Type != OperandType.VariableIndexedVariable) { return; } // simple or array ids must be same if (operand0.Value.ToString() != operand1.Value.ToString()) { return; } // match indices if applicable switch (operand0.Type) { case OperandType.LiteralIndexedVariable: if (operand0.IndexLiteral.ToString() != operand1.IndexLiteral.ToString()) { return; } break; case OperandType.VariableIndexedVariable: if (operand0.IndexIdentifier != operand1.IndexIdentifier) { return; } break; } InsertOptimiserInfo(iIndex, "Self Assignment Removal"); scriptInstruction.Opcode = Opcode.NOP; scriptInstruction.Operand0 = null; scriptInstruction.Operand1 = null; m_bOptimisationComplete = false; }
private void OptimiseArrayIndices(int iIndex) { // MOV tmp, (idx) => MOV var(idx), (expr) // MOV var[tmp], (expr) NOP List <ScriptInstruction> listInstructions = m_scriptExecutable.InstructionsInternal; ScriptInstruction scriptInstruction0 = listInstructions[iIndex]; ScriptInstruction scriptInstruction1 = listInstructions[iIndex + 1]; // opcode check if (scriptInstruction0.Opcode != Opcode.MOV) { return; } if (scriptInstruction1.Opcode != Opcode.MOV) { return; } // verify idx is simple variable if (scriptInstruction0.Operand1.Type != OperandType.Variable) { return; } // check position of dest array if (scriptInstruction1.Operand0.Type != OperandType.VariableIndexedVariable) { return; } // specific vars are tmps if (!IsTemporaryVariable(scriptInstruction0.Operand0)) { return; } if (!IsTemporaryVariableIndex(scriptInstruction1.Operand0)) { return; } // must be same tmps if (scriptInstruction0.Operand0.Value.ToString() != scriptInstruction1.Operand0.IndexIdentifier) { return; } InsertOptimiserInfo(iIndex, "Array Index"); scriptInstruction0.Operand0 = scriptInstruction1.Operand0; scriptInstruction0.Operand0.IndexIdentifier = scriptInstruction0.Operand1.Value.ToString(); scriptInstruction0.Operand1 = scriptInstruction1.Operand1; scriptInstruction1.Opcode = Opcode.NOP; scriptInstruction1.Operand0 = null; scriptInstruction1.Operand1 = null; m_bOptimisationComplete = false; }
private void OptimiseBinaryExpressionAssignment(int iIndex) { // MOV tmp, (src0) MOV dest, (src0) // (OP) tmp, (src1) => (OP) dest, (src1) // MOV dest, tmp NOP List <ScriptInstruction> listInstructions = m_scriptExecutable.InstructionsInternal; ScriptInstruction scriptInstruction0 = listInstructions[iIndex]; ScriptInstruction scriptInstruction1 = listInstructions[iIndex + 1]; ScriptInstruction scriptInstruction2 = listInstructions[iIndex + 2]; // opcode matches if (scriptInstruction0.Opcode != Opcode.MOV) { return; } if (!IsBinaryOperator(scriptInstruction1.Opcode)) { return; } if (scriptInstruction2.Opcode != Opcode.MOV) { return; } // specific variables are tmps if (!IsTemporaryVariable(scriptInstruction0.Operand0)) { return; } if (!IsTemporaryVariable(scriptInstruction1.Operand0)) { return; } if (!IsTemporaryVariable(scriptInstruction2.Operand1)) { return; } // same tmp ids if (scriptInstruction0.Operand0.Value.ToString() != scriptInstruction1.Operand0.Value.ToString()) { return; } if (scriptInstruction0.Operand0.Value.ToString() != scriptInstruction2.Operand1.Value.ToString()) { return; } InsertOptimiserInfo(iIndex, "Binary Expression Assignment"); scriptInstruction0.Operand0 = scriptInstruction2.Operand0; scriptInstruction1.Operand0 = scriptInstruction2.Operand0; scriptInstruction2.Opcode = Opcode.NOP; scriptInstruction2.Operand0 = null; scriptInstruction2.Operand1 = null; m_bOptimisationComplete = false; }
void UpdateText(int score) { string scriptString = ""; // Get newLocation newLocation = startingPoint + journeyDirection * score; int x = (int)newLocation.x; int y = (int)newLocation.y; // Debug.Log(newLocation); // Get string scriptString = script[x, y]; // Parse string string[] splitArray = scriptString.Split(new string[] { "#" }, StringSplitOptions.RemoveEmptyEntries); string defaultText = splitArray[0]; ScriptInstruction[] instructions = new ScriptInstruction[splitArray.Length - 1]; for (int i = 0; i < splitArray.Length - 1; i++) { string[] toParse = splitArray[i + 1].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); if (toParse[0].Contains("?")) { instructions[i].condition = toParse[0]; instructions[i].actions = toParse[1].Split(new string[] { "*" }, StringSplitOptions.RemoveEmptyEntries); } else { instructions[i].condition = ""; instructions[i].actions = toParse[0].Split(new string[] { "*" }, StringSplitOptions.RemoveEmptyEntries); } } flavourText.text = defaultText; // Check instructions for (int i = 0; i < instructions.Length; i++) { // visited current location if (instructions[i].condition.Contains("?hVL")) { bool v = instructions[i].condition.Contains("==T") ? true : false; if (hasVisited[x, y] == v) { CheckActions(instructions[i].actions); } } // inventory look up if (instructions[i].condition.Contains("?iLU")) { bool v = instructions[i].condition.Contains("==T") ? true : false; string itemToLookUp = instructions[i].condition.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries)[1]; if (inventoryLookUp[itemToLookUp] == v) { CheckActions(instructions[i].actions); } } // check Journey Direction if (instructions[i].condition.Contains("?cJD")) { Vector2 v = Vector2.zero; switch (instructions[i].condition.Replace("?cJD==", "")) { case "up": v = Vector2.up; break; case "down": v = Vector2.down; break; case "right": v = Vector2.right; break; case "left": v = Vector2.left; break; } if (journeyDirection == v) { CheckActions(instructions[i].actions); } } if (instructions[i].condition == "") { CheckActions(instructions[i].actions); } } // Update Text // flavourText.text = newText; // Update Metrics hasVisited[x, y] = true; locationVisitTimes[x, y]++; }
dynamic ImportInstruction(ScriptInstruction instruction) { // Not currently used. dynamic ins = new JObject(); ins.text = instruction.Label; var arg = (int)instruction.Argument; if (instruction.Argument > 0) { ins.arg = instruction.Argument; } string refname = null; if (instruction.Label.StartsWith("ACTOR") || instruction.Label.StartsWith("LOC_ACTOR")) { ins.type = "npc"; if (arg == 5010000) // From EventSystemDefine? { refname = "Player"; } else if (!_builder.Db.NpcsById.ContainsKey(arg)) { var sENpcs = _builder.Sheet <Saint.ENpcResident>(); if (sENpcs.ContainsRow(arg)) { refname = Utils.CapitalizeWords(sENpcs[arg].Singular.ToString()); } } } else if (instruction.Label.StartsWith("ITEM") || instruction.Label.StartsWith("RITEM")) { ins.type = "item"; if (!_builder.Db.ItemsById.ContainsKey(arg)) { refname = _builder.Realm.GameData.Items[arg].Name.ToString(); } } else if (instruction.Label.StartsWith("INSTANCEDUNGEON")) { ins.type = "instance"; if (!_builder.Db.InstancesById.ContainsKey(arg)) { refname = _builder.Sheet <Saint.InstanceContent>()[arg].Name.ToString(); } } else if (instruction.Label.StartsWith("ENEMY")) { ins.type = "mob"; if (!_builder.Db.MobsById.ContainsKey(arg)) { var bnpcs = _builder.Sheet <Saint.BNpcName>(); if (bnpcs.ContainsRow(arg)) { refname = Utils.CapitalizeWords(bnpcs[arg].Singular.ToString()); } // else possible Level reference - location? } } else if (instruction.Label.StartsWith("EOBJECT")) { //ins.type = "object"; var eventitems = _builder.Sheet <Saint.EventItem>(); if (eventitems.ContainsRow(arg)) { refname = eventitems[arg].Name.ToString(); } } else if (instruction.Label.StartsWith("TERRITORYTYPE")) { var territoryType = _builder.Sheet <Saint.TerritoryType>()[arg]; refname = territoryType.PlaceName.ToString(); } else if (instruction.Label.Contains("EMOTE") || instruction.Label.StartsWith("MOTION") || instruction.Label == "EVENT_ACTION_" || instruction.Label.StartsWith("LOC_FACE")) { _builder.EmoteNamesById.TryGetValue(arg, out refname); } else if (instruction.Label.StartsWith("LOC_ACTION")) { ins.type = "action"; if (_builder.Db.ActionsById.ContainsKey(arg)) { refname = _builder.Db.ActionsById[arg].name; } else { var sActions = _builder.Sheet <Saint.Action>(); if (sActions.ContainsRow(arg)) { refname = sActions[arg].Name.ToString(); } else { refname = "Unknown"; } } } if (!string.IsNullOrEmpty(refname)) { ins.refname = refname; } return(ins); }