dynamic AddQuestNpc(dynamic quest, Saint.ENpc sNpc) { if (Hacks.IsNpcSkipped(sNpc)) { return(null); } var npc = _builder.Db.NpcsById[sNpc.Key]; if (npc.quests == null) { npc.quests = new JArray(); } var questId = (int)quest.id; JArray quests = npc.quests; if (!quests.Any(id => ((int)id) == questId)) { quests.Add(questId); _builder.Db.AddReference(npc, "quest", questId, false); _builder.Db.AddReference(quest, "npc", (int)npc.id, false); } return(npc); }
dynamic AddQuestNpc(dynamic quest, Saint.ENpc sNpc) { var questId = (int)quest.id; var npc = _builder.GetOrCreateNpc(sNpc); if (npc == null) { return(null); } if (npc.quests == null) { npc.quests = new JArray(); } JArray quests = npc.quests; if (!quests.Any(id => ((int)id) == questId)) { quests.Add(questId); _builder.Db.AddReference(npc, "quest", questId, false); _builder.Db.AddReference(quest, "npc", (int)npc.id, false); } return(npc); }
void BuildAppearanceData(dynamic npc, Saint.ENpc sNpc) { var race = (Saint.Race)sNpc.Base["Race"]; if (race == null || race.Key == 0) { return; // Unique or beast NPCs, can't do appearance now. } dynamic appearance = new JObject(); npc.appearance = appearance; var gender = (byte)sNpc.Base["Gender"]; var isMale = gender == 0; appearance.gender = isMale ? "Male" : "Female"; appearance.race = isMale ? race.Masculine.ToString() : race.Feminine.ToString(); var tribe = (Saint.Tribe)sNpc.Base["Tribe"]; appearance.tribe = isMale ? tribe.Masculine.ToString() : tribe.Feminine.ToString(); appearance.height = sNpc.Base["Height"]; var bodyType = (byte)sNpc.Base["BodyType"]; if (bodyType != 1) { appearance.bodyType = GetBodyType(bodyType); } // Faces var baseFace = (byte)sNpc.Base["Face"]; var face = baseFace % 100; // Value matches the asset number, % 100 approximate face # nicely. appearance.face = face; var isValidFace = face < 8; var isCustomFace = baseFace > 7; if (isCustomFace) { appearance.customFace = 1; } appearance.jaw = 1 + (byte)sNpc.Base["Jaw"]; appearance.eyebrows = 1 + (byte)sNpc.Base["Eyebrows"]; appearance.nose = 1 + (byte)sNpc.Base["Nose"]; appearance.skinColor = FormatColorCoordinates((byte)sNpc.Base["SkinColor"]); appearance.skinColorCode = FormatColor((byte)sNpc.Base["SkinColor"], GetSkinColorMapIndex(tribe.Key, isMale)); // Bust & Muscles - flex fields. if (race.Key == 5 || race.Key == 1) { // Roegadyn & Hyur appearance.muscle = (byte)sNpc.Base["BustOrTone1"]; if (!isMale) { appearance.bust = (byte)sNpc.Base["ExtraFeature2OrBust"]; } } else if (race.Key == 6 && isMale) { // Au Ra male muscles appearance.muscle = (byte)sNpc.Base["BustOrTone1"]; } else if (!isMale) { // Other female bust sizes appearance.bust = (byte)sNpc.Base["BustOrTone1"]; } // Hair & Highlights var hairstyle = (byte)sNpc.Base["HairStyle"]; var hairstyleIcon = CustomizeIcon(GetHairstyleCustomizeIndex(tribe.Key, isMale), 100, hairstyle, npc, appearance); if (hairstyleIcon > 0) { appearance.hairStyle = hairstyleIcon; } appearance.hairColor = FormatColorCoordinates((byte)sNpc.Base["HairColor"]); appearance.hairColorCode = FormatColor((byte)sNpc.Base["HairColor"], GetHairColorMapIndex(tribe.Key, isMale)); var highlights = Unpack2((byte)sNpc.Base["HairHighlight"]); if (highlights.Item1 == 1) { appearance.highlightColor = FormatColorCoordinates((byte)sNpc.Base["HairHighlightColor"]); appearance.highlightColorCode = FormatColor((byte)sNpc.Base["HairHighlightColor"], HairHighlightColorOffset); } // Eyes & Heterochromia var eyeShape = Unpack2((byte)sNpc.Base["EyeShape"]); appearance.eyeSize = eyeShape.Item1 == 1 ? "Small" : "Large"; appearance.eyeShape = 1 + eyeShape.Item2; var eyeColor = (byte)sNpc.Base["EyeColor"]; appearance.eyeColor = FormatColorCoordinates(eyeColor); appearance.eyeColorCode = FormatColor(eyeColor, EyeColorOffset); var heterochromia = (byte)sNpc.Base["EyeHeterochromia"]; if (heterochromia != eyeColor) { appearance.heterochromia = FormatColorCoordinates(heterochromia); appearance.heterochromiaCode = FormatColor(heterochromia, EyeColorOffset); } // Mouth & Lips var mouth = Unpack2((byte)sNpc.Base["Mouth"]); appearance.mouth = 1 + mouth.Item2; if (mouth.Item1 == 1) { var lipColor = Unpack2((byte)sNpc.Base["LipColor"]); appearance.lipShade = lipColor.Item1 == 1 ? "Light" : "Dark"; appearance.lipColor = FormatColorCoordinates(lipColor.Item2); appearance.lipColorCode = FormatColor(lipColor.Item2, lipColor.Item1 == 1 ? LightLipFacePaintColorOffset : DarkLipFacePaintColorOffset); } // Extra Features var extraFeatureName = ExtraFeatureName(race.Key); if (extraFeatureName != null) { appearance.extraFeatureName = extraFeatureName; appearance.extraFeatureShape = (byte)sNpc.Base["ExtraFeature1"]; appearance.extraFeatureSize = (byte)sNpc.Base["ExtraFeature2OrBust"]; } // Facepaint var facepaint = Unpack2((byte)sNpc.Base["FacePaint"]); var facepaintIcon = CustomizeIcon(GetFacePaintCustomizeIndex(tribe.Key, isMale), 50, facepaint.Item2, npc, appearance); if (facepaintIcon > 0) { appearance.facepaint = facepaintIcon; if (facepaint.Item1 == 1) { appearance.facepaintReverse = 1; } var facepaintColor = Unpack2((byte)sNpc.Base["FacePaintColor"]); appearance.facepaintShade = facepaintColor.Item1 == 1 ? "Light" : "Dark"; appearance.facepaintColor = FormatColorCoordinates(facepaintColor.Item2); appearance.facepaintColorCode = FormatColor(facepaintColor.Item2, facepaintColor.Item1 == 1 ? LightLipFacePaintColorOffset : DarkLipFacePaintColorOffset); } // Facial Features var facialfeature = (byte)sNpc.Base["FacialFeature"]; if (facialfeature != 0 && isValidFace) { var type = CharaMakeTypeRow(tribe.Key, gender); appearance.facialfeatures = new JArray(); // There are only 7 groups of facial features at the moment. var facialfeatures = new System.Collections.BitArray(new byte[] { facialfeature }); for (var i = 0; i < 7; i++) { if (!facialfeatures[i]) { continue; } var iconIndex = face; // If it's not hrotgar, shift to -1 if (race.Key != 7) { iconIndex--; } var column = "FacialFeatureOption[" + iconIndex + "][" + i + "]"; var icon = (ImageFile)type[column]; if (icon == null) { continue; // Nothing to show. } appearance.facialfeatures.Add(IconDatabase.EnsureEntry("customize", icon)); } appearance.facialfeatureColor = FormatColorCoordinates((byte)sNpc.Base["FacialFeatureColor"]); appearance.facialfeatureColorCode = FormatColor((byte)sNpc.Base["FacialFeatureColor"], 0); } // todo: CharaMakeType ExtraFeatureData for faces, extra feature icons. }
public dynamic GetOrCreateNpc(Saint.ENpc sNpc) { if (_db.NpcsById.TryGetValue(sNpc.Key, out var npc)) { return(npc); } if (string.IsNullOrWhiteSpace(sNpc.Singular)) { return(null); // Bad or unreferenced NPC. } npc = new JObject(); npc.id = sNpc.Key; Localize.Column((JObject)npc, sNpc.Resident, "Singular", "name", Utils.CapitalizeWords); string name = npc.en.name; npc.patch = PatchDatabase.Get("npc", sNpc.Key); // Set base information. if (!_db.NpcAlternatesByName.TryGetValue(name, out var alts)) { alts = new List <dynamic>(); _db.NpcAlternatesByName[name] = alts; } alts.Add(npc); var title = sNpc.Title.ToString(); if (!string.IsNullOrEmpty(title)) { npc.title = title; } // Map and coordinates. if (LevelByNpcObjectKey.TryGetValue(sNpc.Key, out var level) && LocationInfoByMapId.TryGetValue(level.Map.Key, out var locationInfo)) { npc.zoneid = locationInfo.PlaceName.Key; npc.coords = GetCoords(level); _db.AddLocationReference(locationInfo.PlaceName.Key); } else { if (_db.NpcZoneByNpcId.ContainsKey(sNpc.Key)) { var zoneid = _db.NpcZoneByNpcId[sNpc.Key]; npc.zoneid = zoneid; _db.AddLocationReference(zoneid); } if (_libraNpcIndex.TryGetValue(sNpc.Key, out var lNpc)) { dynamic data = JsonConvert.DeserializeObject((string)lNpc.data); var zone = Utils.GetPair(data.coordinate); npc.coords = Utils.GetFirst(zone.Value); npc.approx = 1; } } // Closest map marker. if (level != null) { var marker = MapMarker.FindClosest(this, level.Map, level.MapX, level.MapY); if (marker != null) { npc.areaid = marker.PlaceName.Key; _db.AddLocationReference(marker.PlaceName.Key); } } _db.Npcs.Add(npc); _db.NpcsById[sNpc.Key] = npc; return(npc); }