/// <summary> /// Add interior people flats. /// </summary> private void AddPeople() { GameObject node = new GameObject("People Flats"); node.transform.parent = this.transform; // Add block flats foreach (DFBlock.RmbBlockPeopleRecord obj in recordData.Interior.BlockPeopleRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import 3D character instead of billboard if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add RMB data to billboard dfBillboard.SetRMBPeopleData(obj); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj); } }
/// <summary> /// Add interior people flats. /// </summary> private void AddPeople(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject("People Flats"); node.transform.parent = this.transform; bool isMemberOfBuildingGuild = GameManager.Instance.GuildManager.GetGuild(buildingData.factionID).IsMember(); // Add block flats foreach (DFBlock.RmbBlockPeopleRecord obj in recordData.Interior.BlockPeopleRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import 3D character instead of billboard if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add RMB data to billboard dfBillboard.SetRMBPeopleData(obj); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, entryDoor.buildingKey); // Disable people if shop or building is closed DFLocation.BuildingTypes buildingType = buildingData.buildingType; if ((RMBLayout.IsShop(buildingType) && !GameManager.Instance.PlayerEnterExit.IsPlayerInsideOpenShop) || (buildingType <= DFLocation.BuildingTypes.Palace && !RMBLayout.IsShop(buildingType) && !PlayerActivate.IsBuildingOpen(buildingType))) { go.SetActive(false); } // Disable people if player owns this house else if (DaggerfallBankManager.IsHouseOwned(buildingData.buildingKey)) { go.SetActive(false); } // Disable people if this is TG/DB house and player is not a member else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID != 0 && !isMemberOfBuildingGuild) { go.SetActive(false); } // Disable people if they are TG spymaster, but not in a legit TG house (TODO: spot any other instances for TG/DB) else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID == 0 && npc.Data.factionID == (int)GuildNpcServices.TG_Spymaster) { go.SetActive(false); } } }
/// <summary> /// Add misc block flats. /// Batching is conditionally supported. /// </summary> public static void AddMiscBlockFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardsAtlas = null, DaggerfallBillboardBatch miscBillboardsBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Add block flats foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Ignore lights as they are handled by AddLights() if (obj.TextureArchive == TextureReader.LightsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Use misc billboard atlas where available if (miscBillboardsAtlas != null && miscBillboardsBatch != null) { TextureAtlasBuilder.AtlasItem item = miscBillboardsAtlas.GetAtlasItem(obj.TextureArchive, obj.TextureRecord); if (item.key != -1) { miscBillboardsBatch.AddItem(item.rect, item.textureItem.size, item.textureItem.scale, billboardPosition); continue; } } // Add to batch where available if (obj.TextureArchive == TextureReader.AnimalsTextureArchive && animalsBillboardBatch != null) { animalsBillboardBatch.AddItem(obj.TextureRecord, billboardPosition); continue; } // Add standalone billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } }
public void RestoreSaveData(object dataIn) { if (!loot) { return; } LootContainerData_v1 data = (LootContainerData_v1)dataIn; if (data.loadID != LoadID) { return; } DaggerfallBillboard billboard = loot.GetComponent <DaggerfallBillboard>(); // Restore position loot.transform.position = data.currentPosition; // Restore appearance if (MeshReplacement.ImportCustomFlatGameobject(data.textureArchive, data.textureRecord, Vector3.zero, loot.transform)) { // Use imported model instead of billboard if (billboard) { Destroy(billboard); } Destroy(GetComponent <MeshRenderer>()); } else if (billboard) { // Restore billboard appearance if present billboard.SetMaterial(data.textureArchive, data.textureRecord); } // Restore items loot.Items.DeserializeItems(data.items); // Restore other data loot.ContainerType = data.containerType; loot.ContainerImage = data.containerImage; loot.LootTableKey = data.lootTableKey; loot.TextureArchive = data.textureArchive; loot.TextureRecord = data.textureRecord; loot.playerOwned = data.playerOwned; loot.customDrop = data.customDrop; loot.name = loot.ContainerType.ToString(); loot.entityName = data.entityName; loot.isEnemyClass = data.isEnemyClass; // Remove loot container if empty if (loot.Items.Count == 0) { GameObjectHelper.RemoveLootContainer(loot); } }
/// <summary> /// Add interior people flats. /// </summary> private void AddPeople(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject(peopleFlats); node.transform.parent = this.transform; IGuild guild = GameManager.Instance.GuildManager.GetGuild(buildingData.factionID); bool isMemberOfBuildingGuild = guild.IsMember(); // Add block flats foreach (DFBlock.RmbBlockPeopleRecord obj in recordData.Interior.BlockPeopleRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Make person gameobject GameObject go = MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform); if (!go) { // Spawn billboard gameobject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add RMB data to billboard dfBillboard.SetRMBPeopleData(obj); } // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, entryDoor.buildingKey); // Disable people if shop or building is closed DFLocation.BuildingTypes buildingType = buildingData.buildingType; if ((RMBLayout.IsShop(buildingType) && !GameManager.Instance.PlayerEnterExit.IsPlayerInsideOpenShop) || (buildingType <= DFLocation.BuildingTypes.Palace && !RMBLayout.IsShop(buildingType) && !(PlayerActivate.IsBuildingOpen(buildingType) || buildingType == DFLocation.BuildingTypes.GuildHall && guild.HallAccessAnytime()))) { go.SetActive(false); } // Disable people if player owns this house else if (DaggerfallBankManager.IsHouseOwned(buildingData.buildingKey)) { go.SetActive(false); } // Disable people if this is TG/DB house and player is not a member else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID != 0 && !isMemberOfBuildingGuild) { go.SetActive(false); } } }
/// <summary> /// Adds light flats and prefabs. /// </summary> public static void AddLights( ref DFBlock blockData, Transform flatsParent, Transform lightsParent, DaggerfallBillboardBatch billboardBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Do nothing if import option not enabled or missing prefab if (!dfUnity.Option_ImportLightPrefabs || dfUnity.Option_CityLightPrefab == null) { return; } // Iterate block flats for lights foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Add billboard to batch or standalone if (billboardBatch != null) { billboardBatch.AddItem(obj.TextureRecord, billboardPosition); } else { GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } // Import light prefab AddLight(dfUnity, obj, lightsParent); } } }
/// <summary> /// Add nature billboards. /// </summary> public static void AddNatureFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch billboardBatch = null, ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland, ClimateSeason climateSeason = ClimateSeason.Summer) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { // Get scenery item - ignore indices -1 (empty) and 0 (marker/waypoint of some kind) DFBlock.RmbGroundScenery scenery = blockData.RmbBlock.FldHeader.GroundData.GroundScenery[x, 15 - y]; if (scenery.TextureRecord < 1) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( x * BlocksFile.TileDimension, natureFlatsOffsetY, y * BlocksFile.TileDimension + BlocksFile.TileDimension) * MeshReader.GlobalScale; // Get Archive int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason); // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(natureArchive, scenery.TextureRecord, billboardPosition, flatsParent) != null) { continue; } // Add billboard to batch or standalone if (billboardBatch != null) { billboardBatch.AddItem(scenery.TextureRecord, billboardPosition); } else { GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(natureArchive, scenery.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } } } }
/// <summary> /// Add interior flats. /// </summary> private void AddFlats() { GameObject node = new GameObject("Interior Flats"); node.transform.parent = this.transform; // Add block flats markers.Clear(); foreach (DFBlock.RmbBlockFlatObjectRecord obj in recordData.Interior.BlockFlatObjectRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add editor markers to list if (obj.TextureArchive == TextureReader.EditorFlatsTextureArchive) { InteriorEditorMarker marker = new InteriorEditorMarker(); marker.type = (InteriorMarkerTypes)obj.TextureRecord; marker.gameObject = go; markers.Add(marker); } // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { AddLight(obj, go.transform); } } }
/// <summary> /// Add interior flats. /// </summary> private void AddFlats() { GameObject node = new GameObject("Interior Flats"); node.transform.parent = this.transform; // Add block flats markers.Clear(); foreach (DFBlock.RmbBlockFlatObjectRecord obj in recordData.Interior.BlockFlatObjectRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add to enter marker list, which is TEXTURE.199, index 8. // Sometimes marker 199.4 is used where the 199.8 enter marker should be // Being a little forgiving and also accepting 199.4 as enter marker // Will add more of these cases if I find them if (obj.TextureArchive == TextureReader.EditorFlatsTextureArchive && (obj.TextureRecord == 8 || obj.TextureRecord == 4)) { markers.Add(go); } // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { AddLight(obj, go.transform); } } }
public static GameObject AddFlatObject(DFBlock.RdbObject obj) { int archive = obj.Resources.FlatResource.TextureArchive; int record = obj.Resources.FlatResource.TextureRecord; // Add GameObject to scene Vector3 targetPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; GameObject go = MeshReplacement.ImportCustomFlatGameobject(archive, record, targetPosition, null, true); if (!go) { // Setup standard billboard and assign RDB data go = GameObjectHelper.CreateDaggerfallBillboardGameObject(archive, record, null); go.transform.position = targetPosition; Billboard dfBillboard = go.GetComponent <Billboard>(); dfBillboard.SetRDBResourceData(obj.Resources.FlatResource); } return(go); }
/// <summary> /// Add interior flats. /// </summary> private void AddFlats(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject("Interior Flats"); node.transform.parent = this.transform; // Add block flats markers.Clear(); foreach (DFBlock.RmbBlockFlatObjectRecord obj in recordData.Interior.BlockFlatObjectRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add editor markers to list if (obj.TextureArchive == TextureReader.EditorFlatsTextureArchive) { InteriorEditorMarker marker = new InteriorEditorMarker(); marker.type = (InteriorMarkerTypes)obj.TextureRecord; marker.gameObject = go; markers.Add(marker); // Add loot containers for treasure markers (always use pile of clothes icon) if (marker.type == InteriorMarkerTypes.Treasure) { // Create unique LoadID for save system, using 9 lsb and the sign bit from each coord pos int ulong loadID = ((ulong)buildingData.buildingKey) << 30 | (uint)(obj.XPos << 1 & posMask) << 20 | (uint)(obj.YPos << 1 & posMask) << 10 | (uint)(obj.ZPos << 1 & posMask); DaggerfallLoot loot = GameObjectHelper.CreateLootContainer( LootContainerTypes.RandomTreasure, InventoryContainerImages.Chest, billboardPosition, node.transform, DaggerfallLootDataTables.clothingArchive, 0, loadID); if (!LootTables.GenerateLoot(loot, (int)GameManager.Instance.PlayerGPS.CurrentLocationType)) { DaggerfallUnity.LogMessage(string.Format("DaggerfallInterior: Location type {0} is out of range or unknown.", GameManager.Instance.PlayerGPS.CurrentLocationType), true); } } } // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { AddLight(obj, go.transform); } } }
/// <summary> /// Add misc block flats. /// Batching is conditionally supported. /// </summary> public static void AddMiscBlockFlats( ref DFBlock blockData, Transform flatsParent, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardsAtlas = null, DaggerfallBillboardBatch miscBillboardsBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Add block flats foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Ignore lights as they are handled by AddLights() if (obj.TextureArchive == TextureReader.LightsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent) != null) { continue; } //// Use misc billboard atlas where available //if (miscBillboardsAtlas != null && miscBillboardsBatch != null) //{ // TextureAtlasBuilder.AtlasItem item = miscBillboardsAtlas.GetAtlasItem(obj.TextureArchive, obj.TextureRecord); // if (item.key != -1) // { // miscBillboardsBatch.AddItem(item.rect, item.textureItem.size, item.textureItem.scale, billboardPosition); // continue; // } //} // Add to batch where available //if (obj.TextureArchive == TextureReader.AnimalsTextureArchive && animalsBillboardBatch != null) //{ // animalsBillboardBatch.AddItem(obj.TextureRecord, billboardPosition); // continue; //} // Add standalone billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); // Add animal sound if (obj.TextureArchive == TextureReader.AnimalsTextureArchive) { AddAnimalAudioSource(go); } // If flat record has a non-zero faction id, then it's an exterior NPC if (obj.FactionID != 0) { // Add RMB data to billboard DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); dfBillboard.SetRMBPeopleData(obj.FactionID, obj.Flags, obj.Position); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj); } } }
public static GameObject CreatePlacedObject(PlacedObjectData_v2 data, Transform parent, bool previewGo = false) { // Custom models like Handpainted Models have insanley different scales (< 0.0 to 200+) Set all models as a child to a parent, so // EditMode can uniformly scale properly. GameObject parentGo = new GameObject(); GameObject childGo; parentGo.transform.parent = parent; if (data.modelID == 0) { childGo = MeshReplacement.ImportCustomFlatGameobject(data.archive, data.record, Vector3.zero, parentGo.transform); if (childGo == null) { childGo = GameObjectHelper.CreateDaggerfallBillboardGameObject(data.archive, data.record, parentGo.transform); } } else { Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one); childGo = MeshReplacement.ImportCustomGameobject(data.modelID, parentGo.transform, matrix); if (childGo == null) { childGo = GameObjectHelper.CreateDaggerfallMeshGameObject(data.modelID, parentGo.transform); } } parentGo.transform.eulerAngles = Vector3.zero; childGo.transform.eulerAngles = Vector3.zero; if (previewGo) { data.isLight = true; } BoxCollider parentCollider = parentGo.AddComponent <BoxCollider>(); BoxCollider childCollider; //Expanding collider a little gives better hit detection. float buffer = 0.02f; // Some custom models have a box collider and are made of multiple smaller models. Get the parent collider size. if (childCollider = childGo.GetComponent <BoxCollider>()) { parentCollider.size = new Vector3((childCollider.size.x * childGo.transform.localScale.x) + buffer, (childCollider.size.y * childGo.transform.localScale.y) + buffer, (childCollider.size.z * childGo.transform.localScale.z) + buffer); parentCollider.center = new Vector3(childCollider.center.x * childGo.transform.localScale.x, childCollider.center.y * childGo.transform.localScale.y, childCollider.center.z * childGo.transform.localScale.z); // Child colliders screw with EditMode. GameObject.Destroy(childCollider); } else { Bounds childBounds = childGo.GetComponent <MeshFilter>().sharedMesh.bounds; parentCollider.size = new Vector3((childBounds.size.x * childGo.transform.localScale.x) + buffer, (childBounds.size.y * childGo.transform.localScale.y) + buffer, (childBounds.size.z * childGo.transform.localScale.z) + buffer); parentCollider.center = new Vector3(childBounds.center.x * childGo.transform.localScale.x, childBounds.center.y * childGo.transform.localScale.y, childBounds.center.z * childGo.transform.localScale.z); } parentCollider.isTrigger = true; parentGo.AddComponent <PlacedObject>(); SetPlacedObject(data, parentGo); return(parentGo); }
/// <summary> /// Add subrecord (building) exterior block flats. /// </summary> public static void AddExteriorBlockFlats( ref DFBlock blockData, Transform flatsParent, Transform lightsParent, int mapId, int locationIndex, ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland, ClimateSeason climateSeason = ClimateSeason.Summer) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Get Nature Archive int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason); foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords) { Vector3 subRecordPosition = new Vector3(subRecord.XPos, 0, -subRecord.ZPos) * MeshReader.GlobalScale; foreach (DFBlock.RmbBlockFlatObjectRecord obj in subRecord.Exterior.BlockFlatObjectRecords) { // Don't add building exterior editor flats since they can't be used by any DFU systems int archive = obj.TextureArchive; if (archive == TextureReader.EditorFlatsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; billboardPosition += subRecordPosition; // Add natures using correct climate set archive if (archive >= (int)DFLocation.ClimateTextureSet.Nature_RainForest && archive <= (int)DFLocation.ClimateTextureSet.Nature_Mountains_Snow) { archive = natureArchive; billboardPosition.z = natureFlatsOffsetY; } GameObject go = MeshReplacement.ImportCustomFlatGameobject(archive, obj.TextureRecord, billboardPosition, flatsParent); bool isImported = go != null; if (!isImported) { // Add standalone billboard gameobject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(archive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } // Add animal sound if (archive == TextureReader.AnimalsTextureArchive) { AddAnimalAudioSource(go, obj.TextureRecord); } // If flat record has a non-zero faction id, then it's an exterior NPC if (obj.FactionID != 0) { // Add RMB data to billboard Billboard dfBillboard = go.GetComponent <Billboard>(); if (dfBillboard != null) { dfBillboard.SetRMBPeopleData(obj.FactionID, obj.Flags, obj.Position); } // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, mapId, locationIndex); } // If this is a light flat, import light prefab if (archive == TextureReader.LightsTextureArchive && !isImported) { if (dfUnity.Option_CityLightPrefab == null) { return; } Vector2 size = dfUnity.MeshReader.GetScaledBillboardSize(210, obj.TextureRecord); Vector3 position = new Vector3( obj.XPos, -obj.YPos + size.y, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; position += subRecordPosition; GameObjectHelper.InstantiatePrefab(dfUnity.Option_CityLightPrefab.gameObject, string.Empty, lightsParent, position); } } } }
/// <summary> /// Add misc block flats. /// Batching is conditionally supported. /// </summary> public static void AddMiscBlockFlats( ref DFBlock blockData, Transform flatsParent, int mapId, int locationIndex, DaggerfallBillboardBatch animalsBillboardBatch = null, TextureAtlasBuilder miscBillboardsAtlas = null, DaggerfallBillboardBatch miscBillboardsBatch = null) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return; } // Add block flats foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords) { // Ignore lights as they are handled by AddLights() if (obj.TextureArchive == TextureReader.LightsTextureArchive) { continue; } // Calculate position Vector3 billboardPosition = new Vector3( obj.XPos, -obj.YPos + blockFlatsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale; GameObject go = MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, flatsParent); if (go == null) { // Add standalone billboard gameobject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, flatsParent); go.transform.position = billboardPosition; AlignBillboardToBase(go); } // Add animal sound if (obj.TextureArchive == TextureReader.AnimalsTextureArchive) { AddAnimalAudioSource(go, obj.TextureRecord); } // If flat record has a non-zero faction id, then it's an exterior NPC if (obj.FactionID != 0) { // Add RMB data to billboard Billboard dfBillboard = go.GetComponent <Billboard>(); if (dfBillboard != null) { dfBillboard.SetRMBPeopleData(obj.FactionID, obj.Flags, obj.Position); } // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, mapId, locationIndex); } } }
public void RestoreSaveData(object dataIn) { if (!loot) { return; } LootContainerData_v1 data = (LootContainerData_v1)dataIn; if (data.loadID != LoadID) { return; } // Restore billboard only if this is a billboard-based loot container if (loot.ContainerType == LootContainerTypes.RandomTreasure || loot.ContainerType == LootContainerTypes.CorpseMarker || loot.ContainerType == LootContainerTypes.DroppedLoot) { DaggerfallBillboard billboard = loot.GetComponent <DaggerfallBillboard>(); // Interiors and exteriors need special handling to ensure loot is always placed correctly for pre and post floating y saves // Dungeons are not involved with floating y and don't need any changes WorldContext lootContext = GetLootWorldContext(loot); if (lootContext == WorldContext.Interior) { RestoreInteriorPositionHandler(loot, data, lootContext); } else if (lootContext == WorldContext.Exterior) { RestoreExteriorPositionHandler(loot, data, lootContext); } else { loot.transform.position = data.currentPosition; } // Restore appearance if (MeshReplacement.ImportCustomFlatGameobject(data.textureArchive, data.textureRecord, Vector3.zero, loot.transform)) { // Use imported model instead of billboard if (billboard) { Destroy(billboard); } Destroy(GetComponent <MeshRenderer>()); } else if (billboard) { // Restore billboard appearance if present billboard.SetMaterial(data.textureArchive, data.textureRecord); } } // Restore items loot.Items.DeserializeItems(data.items); // Restore other data loot.ContainerType = data.containerType; loot.ContainerImage = data.containerImage; loot.TextureArchive = data.textureArchive; loot.TextureRecord = data.textureRecord; loot.stockedDate = data.stockedDate; loot.playerOwned = data.playerOwned; loot.customDrop = data.customDrop; loot.entityName = data.entityName; loot.isEnemyClass = data.isEnemyClass; // Remove loot container if empty if (loot.Items.Count == 0) { GameObjectHelper.RemoveLootContainer(loot); } }