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> /// 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; }
/// <summary> /// Setup API file readers. /// </summary> private void SetupReaders() { // Try to setup Arena2-dependent content readers if (blockFileReader == null) { blockFileReader = new BlocksFile(Path.Combine(arena2Path, BlocksFile.Filename), FileUsage.UseMemory, true); } if (mapFileReader == null) { mapFileReader = new MapsFile(Path.Combine(arena2Path, MapsFile.Filename), FileUsage.UseMemory, true); } if (monsterFileReader == null) { monsterFileReader = new MonsterFile(Path.Combine(arena2Path, MonsterFile.Filename), FileUsage.UseMemory, true); } if (woodsFileReader == null) { woodsFileReader = new WoodsFile(Path.Combine(arena2Path, WoodsFile.Filename), FileUsage.UseMemory, true); } if (factionFileReader == null) { factionFileReader = new FactionFile(GetFactionFilePath(), FileUsage.UseMemory, true); } if (flatsFileReader == null) { flatsFileReader = new FlatsFile(Path.Combine(arena2Path, FlatsFile.Filename), FileUsage.UseMemory, true); } if (paintFileReader == null) { paintFileReader = new PaintFile(Path.Combine(arena2Path, PaintFile.Filename), FileUsage.UseMemory, true); } // Raise ready flag isReady = true; }
/// <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; } }
/// <summary> /// Setup API file readers. /// </summary> private void SetupReaders() { // Try to setup Arena2-dependent content readers if (blockFileReader == null) { blockFileReader = new BlocksFile(Path.Combine(arena2Path, BlocksFile.Filename), FileUsage.UseMemory, true); } if (mapFileReader == null) { mapFileReader = new MapsFile(Path.Combine(arena2Path, MapsFile.Filename), FileUsage.UseMemory, true); } if (monsterFileReader == null) { monsterFileReader = new MonsterFile(Path.Combine(arena2Path, MonsterFile.Filename), FileUsage.UseMemory, true); } if (woodsFileReader == null) { woodsFileReader = new WoodsFile(Path.Combine(arena2Path, WoodsFile.Filename), FileUsage.UseMemory, true); } if (factionFileReader == null) { factionFileReader = new FactionFile(Path.Combine(arena2Path, FactionFile.Filename), FileUsage.UseMemory, true); } if (flatsFileReader == null) { flatsFileReader = new FlatsFile(Path.Combine(arena2Path, FlatsFile.Filename), FileUsage.UseMemory, true); } //if (spellIconCollection == null) // spellIconCollection = new SpellIconCollection(); // Build map lookup dictionary if (mapDict == null && mapFileReader != null) { EnumerateMaps(); } // Raise ready flag isReady = true; }
/// <summary> /// Imports FLATS.CFG EN strings from embedded classic game data into specified StringTable. /// </summary> /// <param name="target">Target string table collection name.</param> /// <param name="overwriteExistingKeys">When true will overwrite existing keys with source string. When false existing keys are left unchanged.</param> public static void CopyTextFlatsToStringTable(string target, bool overwriteExistingKeys) { // Use default Internal_Flat collection with EN locale code as source // Note: Internal_Flats is reserved for future use string sourceCollectionName = TextManager.defaultInternalFlatsCollectionName; // Do nothing if target not set if (string.IsNullOrEmpty(target)) { return; } // Target cannot be same as default if (string.Compare(target, sourceCollectionName, true) == 0) { Debug.LogError("CopyTextFlatsToStringTable() target cannot be same as default"); return; } // Load default FLATS.CFG file FlatsFile flatsFile = new FlatsFile(Path.Combine(DaggerfallUnity.Instance.Arena2Path, FlatsFile.Filename), DaggerfallConnect.FileUsage.UseMemory, true); if (flatsFile == null) { Debug.LogError("CopyTextFlatsToStringTable() could not find default FLATS.CFG file"); return; } // Get target string table collection var targetCollection = LocalizationEditorSettings.GetStringTableCollection(target); if (targetCollection == null) { Debug.LogErrorFormat("CopyTextFlatsToStringTable() could not find target string table collection '{0}'", target); return; } // Copy source strings to all tables in target collection int totalSourceEntries = flatsFile.FlatsDict.Count; int copiedNew = 0; int copiedOverwrite = 0; foreach (StringTable targetTable in targetCollection.StringTables) { foreach (var item in flatsFile.FlatsDict) { string key = item.Key.ToString(); string text = item.Value.caption; var targetEntry = targetTable.GetEntry(key); if (targetEntry == null) { targetTable.AddEntry(key, text); copiedNew++; } else if (targetEntry != null && overwriteExistingKeys) { if (targetTable.RemoveEntry(key)) { targetTable.AddEntry(key, text); copiedOverwrite++; } else { Debug.LogErrorFormat("CopyTextFlatsToStringTable() could not remove key '{0}'. Overwrite failed.", key); } } } // Set table dirty EditorUtility.SetDirty(targetTable); } // Set target collection shared data dirty EditorUtility.SetDirty(targetCollection.SharedData); Debug.LogFormat("Source collection FLATS.CFG has a total of {0} entries.\nTarget collection '{1}' received {2} new entries, {3} entries were overwritten.", totalSourceEntries, target, copiedNew, copiedOverwrite); }
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, }; } } } } } }