/// <summary> /// Sets NPC data from RMB layout flat record. (exterior NPCs) /// Requires mapID and locationIndex to be passed in as layout may occur without player being in the location. /// </summary> public void SetLayoutData(DFBlock.RmbBlockFlatObjectRecord obj, int mapId, int locationIndex) { // Gender flag is invalid for RMB exterior NPCs: get it from FLATS.CFG instead int flatID = FlatsFile.GetFlatID(obj.TextureArchive, obj.TextureRecord); if (DaggerfallUnity.Instance.ContentReader.FlatsFileReader.GetFlatData(flatID, out FlatsFile.FlatData flatCFG)) { if (flatCFG.gender.Contains("2")) { obj.Flags |= 32; } else { obj.Flags &= 223; } } SetLayoutData(ref npcData, obj.XPos, obj.YPos, obj.ZPos, obj.Flags, obj.FactionID, obj.TextureArchive, obj.TextureRecord, obj.Position, mapId, locationIndex, 0); npcData.context = Context.Custom; }
string GetFlatDetailsString() { // Get billboard texture data FactionFile.FlatData flatData; if (IsIndividualNPC) { // Individuals are always flat1 no matter gender flatData = FactionFile.GetFlatData(FactionData.flat1); } if (Gender == Genders.Male) { // Male has flat1 flatData = FactionFile.GetFlatData(FactionData.flat1); } else { // Female has flat2 flatData = FactionFile.GetFlatData(FactionData.flat2); } // Get flat ID for this person int flatID = FlatsFile.GetFlatID(flatData.archive, flatData.record); // Get flat caption for this ID, e.g. "young lady in green", or fallback to race FlatsFile.FlatData flatCFG; if (DaggerfallUnity.Instance.ContentReader.FlatsFileReader.GetFlatData(flatID, out flatCFG)) { return(TextManager.Instance.GetLocalizedText(flatID.ToString(), TextCollections.TextFlats)); } else { return(RaceTemplate.GetRaceDictionary()[(int)race].Name); } }
/// <summary> /// get portrait archive and texture record index for current set target static npc /// </summary> /// <returns></returns> private void getPortraitIndexFromStaticNPCBillboard(out DaggerfallTalkWindow.FacePortraitArchive facePortraitArchive, out int recordIndex) { FactionFile.FactionData factionData; GameManager.Instance.PlayerEntity.FactionData.GetFactionData(targetStaticNPC.Data.factionID, out factionData); FactionFile.FlatData factionFlatData = FactionFile.GetFlatData(factionData.flat1); FactionFile.FlatData factionFlatData2 = FactionFile.GetFlatData(factionData.flat2); // get face for special npcs here and return in this case if (factionData.type == 4) { facePortraitArchive = DaggerfallTalkWindow.FacePortraitArchive.SpecialFaces; recordIndex = factionData.face; return; } // if no special npc, resolving process for common faces starts here facePortraitArchive = DaggerfallTalkWindow.FacePortraitArchive.CommonFaces; // use oops as default - so use it if we fail to resolve face later on in this resolving process recordIndex = 410; FlatsFile.FlatData flatData; // resolve face from npc's faction data as default int archive = factionFlatData.archive; int record = factionFlatData.record; if (targetStaticNPC.Data.gender == Genders.Female) { archive = factionFlatData2.archive; record = factionFlatData2.record; } if (DaggerfallUnity.Instance.ContentReader.FlatsFileReader.GetFlatData(FlatsFile.GetFlatID(archive, record), out flatData)) // (if flat data exists in FlatsFile, overwrite index) { recordIndex = flatData.faceIndex; } // overwrite if target npc's billboard archive and record index can be resolved (more specific than just the factiondata - which will always resolve to same portrait for a specific faction) if (DaggerfallUnity.Instance.ContentReader.FlatsFileReader.GetFlatData(FlatsFile.GetFlatID(targetStaticNPC.Data.billboardArchiveIndex, targetStaticNPC.Data.billboardRecordIndex), out flatData)) { recordIndex = flatData.faceIndex; } }
private static void OnTransitionToInterior_VariantResidenceNPCsprites(PlayerEnterExit.TransitionEventArgs args) { if (villagerVarietyMod != null && villagerVarietyNumVariants == 0) { ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getNumVariants", null, (string message, object data) => { villagerVarietyNumVariants = (int)data; }); } PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit; DFLocation.BuildingData buildingData = playerEnterExit.Interior.BuildingData; if (RMBLayout.IsResidence(buildingData.BuildingType)) { Races race = GetClimateRace(); int gender = -1; Billboard[] dfBillboards = playerEnterExit.Interior.GetComponentsInChildren <Billboard>(); foreach (Billboard billboard in dfBillboards) { if (billboard.Summary.Archive == 182) { gender = GetGender182(billboard.Summary.Record); } else if (billboard.Summary.Archive == 184) { gender = GetGender184(billboard.Summary.Record); } if (gender != -1) { StaticNPC npc = billboard.GetComponent <StaticNPC>(); if (npc && npc.Data.factionID == 0) { int faceVariant = npc.Data.nameSeed % 29; Debug.LogFormat("Replace house NPC {0}.{1} with faceVariant {2} - {3}", billboard.Summary.Archive, billboard.Summary.Record, faceVariant, faceVariant < 24); if (faceVariant < 24) { int outfitVariant = npc.Data.nameSeed % 4; int archive = gender == (int)Genders.Male ? raceArchivesMale[race][outfitVariant] : raceArchivesFemale[race][outfitVariant]; int record = 5; int faceRecord = gender == (int)Genders.Male ? raceFaceRecordMale[race][outfitVariant] : raceFaceRecordFemale[race][outfitVariant]; faceRecord += faceVariant; bool materialSet = false; if (villagerVarietyMod != null) { int variant = npc.Data.nameSeed % villagerVarietyNumVariants; string season = ""; //ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getSeasonStr", null, (string message, object data) => { season = (string)data; }); Debug.LogFormat("Replace house NPC {0}.{1} with {2}.{3}, outfit: {4} faceRecord: {5} ({6}) variant: {7} season: {8}", billboard.Summary.Archive, billboard.Summary.Record, archive, record, outfitVariant, faceRecord, faceVariant, variant, season); string imageName = null; ModManager.Instance.SendModMessage(VILLAGERVARIETY_MODNAME, "getImageName", new object[] { archive, record, 0, faceRecord, variant, season }, (string message, object data) => { imageName = (string)data; }); if (!string.IsNullOrEmpty(imageName) && villagerVarietyMod.HasAsset(imageName)) { // Get texture and create material Texture2D texture = villagerVarietyMod.GetAsset <Texture2D>(imageName); Material material = MaterialReader.CreateStandardMaterial(MaterialReader.CustomBlendMode.Cutout); material.mainTexture = texture; // Apply material to mesh renderer MeshRenderer meshRenderer = billboard.GetComponent <MeshRenderer>(); meshRenderer.sharedMaterial = material; // Create mesh and setup UV map for mesh filter Vector2 size; Mesh mesh = DaggerfallUnity.Instance.MeshReader.GetBillboardMesh(new Rect(0, 0, 1, 1), archive, record, out size); mesh.uv = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(0, 0), new Vector2(1, 0) }; MeshFilter meshFilter = billboard.GetComponent <MeshFilter>(); Destroy(meshFilter.sharedMesh); meshFilter.sharedMesh = mesh; materialSet = true; } } if (!materialSet) { billboard.SetMaterial(archive, record); billboard.FramesPerSecond = 1; } GameObjectHelper.AlignBillboardToGround(billboard.gameObject, billboard.Summary.Size); Dictionary <int, FlatsFile.FlatData> flatsDict = DaggerfallUnity.Instance.ContentReader.FlatsFileReader.FlatsDict; int flatId = FlatsFile.GetFlatID(npc.Data.billboardArchiveIndex, npc.Data.billboardRecordIndex); #if UNITY_EDITOR Debug.LogFormat("Replacing face dict for {0} with {1} (for {2}.{3} / {4}.{5})", flatsDict[flatId].faceIndex, faceRecord, npc.Data.billboardArchiveIndex, npc.Data.billboardRecordIndex, billboard.Summary.Archive, billboard.Summary.Record); #endif flatsDict[flatId] = new FlatsFile.FlatData() { archive = billboard.Summary.Archive, record = billboard.Summary.Record, faceIndex = faceRecord, }; } } } } } }