void BuildAttributes(dynamic item, Saint.Item sItem) { var attr = new JObject(); var attr_hq = new JObject(); var attr_max = new JObject(); if (sItem is Saint.Items.Equipment sEquipment) { item.equip = 1; if (sEquipment.FreeMateriaSlots > 0) { item.sockets = sEquipment.FreeMateriaSlots; // Only equipment with slots should possibly be forbidden. if (!sItem.IsAdvancedMeldingPermitted) { item.advancedMeldingForbidden = 1; } } if (sEquipment.RepairItem != null && sEquipment.RepairItem.Key > 0) { item.repair_item = sEquipment.RepairItem.Key; } if (sEquipment.IsPvP) { item.pvp = 1; } if (sEquipment.IsCrestWorthy) { item.crestworthy = 1; } if (sEquipment.IsGlamourous) { item.glamourous = 1; } var expertSeals = sEquipment.ExpertDeliverySeals; if (expertSeals > 0) { item.delivery = expertSeals; } if (_armoireIndex.Contains(sItem.Key)) { item.storable = 1; } item.slot = sEquipment.EquipSlotCategory.Key; item.elvl = sEquipment.EquipmentLevel; item.jobs = sEquipment.ClassJobCategory.Key; _builder.Localize.Column(item, sEquipment.ClassJobCategory, "Name", "jobCategories"); // Set all normal and hq parameters specified on the item. Saint.BaseParam[] extraParams = null; foreach (var sParameter in sEquipment.AllParameters) { if (_crafterParams.Contains(sParameter.BaseParam)) { extraParams = _crafterParams; } else if (_gathererParams.Contains(sParameter.BaseParam)) { extraParams = _gathererParams; } ParamHelper.SetValue(sParameter, attr, attr_hq, false); } // Set maximums for every parameter. foreach (var sBaseParam in _baseParams) { ParamHelper.SetMaxValue(sEquipment, sBaseParam, attr_max); } // For gatherer and crafter equ, set normal attributes even // if they're 0 so their maximums always show up. if (extraParams != null) { foreach (var sBaseParam in extraParams) { var key = sBaseParam.Name.ToString(); if (attr_max[key] != null && attr[key] == null && attr_hq[key] == null) { attr[key] = 0; } } } var characterType = sEquipment.GetModelCharacterType(); if (characterType != 0 && !Hacks.NoModelCategories.Contains(sEquipment.ItemUICategory.Key)) { // Record model information for viewer. item.models = new JArray(); item.models.Add(sEquipment.PrimaryModelKey.ToString().Replace(", ", "-")); if (!sEquipment.SecondaryModelKey.IsEmpty) { item.models.Add(sEquipment.SecondaryModelKey.ToString().Replace(", ", "-")); } if (sEquipment.Rarity != 7) { var sEquipSlot = sEquipment.EquipSlotCategory.PossibleSlots.First(); var modelKey = sEquipSlot.GetModelKey(sEquipment.PrimaryModelKey, characterType); // We compare only the primary model key for now. // Not sure if the secondary key is valuable too? if (!_itemsBySlotModelId.TryGetValue(modelKey, out var itemsWithModel)) { itemsWithModel = new List <dynamic>(); _itemsBySlotModelId[modelKey] = itemsWithModel; } itemsWithModel.Add(item); } } // ItemSpecialBonus if (sEquipment.ItemSpecialBonus != null && sEquipment.ItemSpecialBonus.Name != "") { item.special = new JObject(); item.special.bonusId = sEquipment.ItemSpecialBonus.Key; if (sEquipment.ItemSpecialBonusParam > 0) { item.special.bonusParam = sEquipment.ItemSpecialBonusParam; } if (sEquipment.ItemSeries.Key > 0) { item.special.seriesId = sEquipment.ItemSeries.Key; if (!_builder.Db.ItemsBySeriesId.TryGetValue(sEquipment.ItemSeries.Key, out var itemsInSeries)) { _builder.Db.ItemsBySeriesId[sEquipment.ItemSeries.Key] = itemsInSeries = new List <dynamic>(); } itemsInSeries.Add(item); } item.special.attr = new JArray(); foreach (var sParam in sEquipment.SecondaryParameters) { foreach (var paramValue in sParam.Values.Select(pv => ParameterInfo.From(pv))) { if (paramValue.Type != Saint.ParameterType.Sanction && paramValue.Type != Saint.ParameterType.SetBonus && paramValue.Type != Saint.ParameterType.SetBonusCapped && paramValue.Type != Saint.ParameterType.EurekaEffect) { continue; } dynamic obj = new JObject(); obj.name = sParam.BaseParam.Name.ToString(); obj.value = (int)paramValue.Amount; obj.index = paramValue.Index; item.special.attr.Add(obj); } } } } if (sItem is Saint.Items.Usable sUsable) { JObject action = new JObject(); JObject action_hq = new JObject(); foreach (var param in sUsable.Parameters) { ParamHelper.SetValue(param, action, action_hq, true); } if (action.Count > 0) { attr.Add("action", action); } if (action_hq.Count > 0) { attr_hq.Add("action", action_hq); } } if (attr.Count > 0) { item.attr = attr; } if (attr_hq.Count > 0) { item.attr_hq = attr_hq; } if (attr_max.Count > 0) { item.attr_max = attr_max; } }