Esempio n. 1
0
        /// <summary>
        /// Adds action door to scene.
        /// </summary>
        private static GameObject AddActionDoor(DaggerfallUnity dfUnity, uint modelId, DFBlock.RdbObject obj, Transform parent)
        {
            if (dfUnity.Option_DungeonDoorPrefab == null)
            {
                return(null);
            }

            // Get model data and matrix
            ModelData modelData;

            dfUnity.MeshReader.GetModelData(modelId, out modelData);
            Matrix4x4 modelMatrix = GetModelMatrix(obj);

            // Instantiate door prefab and add model
            GameObject go = GameObjectHelper.InstantiatePrefab(dfUnity.Option_DungeonDoorPrefab.gameObject, string.Empty, parent, Vector3.zero);

            GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, parent, false, go, true);

            // Resize box collider to new mesh bounds
            BoxCollider  boxCollider  = go.GetComponent <BoxCollider>();
            MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>();

            if (boxCollider != null && meshRenderer != null)
            {
                boxCollider.center = meshRenderer.bounds.center;
                boxCollider.size   = meshRenderer.bounds.size;
            }

            // Get rotation angle for each axis
            float degreesX = -obj.Resources.ModelResource.XRotation / BlocksFile.RotationDivisor;
            float degreesY = -obj.Resources.ModelResource.YRotation / BlocksFile.RotationDivisor;
            float degreesZ = -obj.Resources.ModelResource.ZRotation / BlocksFile.RotationDivisor;

            // Apply transforms
            go.transform.Rotate(0, degreesY, 0, Space.World);
            go.transform.Rotate(degreesX, 0, 0, Space.World);
            go.transform.Rotate(0, 0, degreesZ, Space.World);
            go.transform.localPosition = modelMatrix.GetColumn(3);

            return(go);
        }
Esempio n. 2
0
        private void FixEnemyStanding(GameObject go)
        {
            Component[] mobiles = go.GetComponentsInChildren(typeof(DaggerfallMobileUnit));
            if (mobiles == null)
            {
                return;
            }

            foreach (DaggerfallMobileUnit enemy in mobiles)
            {
                // Don't change for flying enemies
                if (enemy.Summary.Enemy.Behaviour == MobileBehaviour.Flying)
                {
                    continue;
                }

                // Align to ground
                Vector2 size = enemy.Summary.RecordSizes[0];
                GameObjectHelper.AlignBillboardToGround(enemy.transform.parent.gameObject, size);
            }
        }
Esempio n. 3
0
        private static void AddEnemy(
            DFBlock.RdbObject obj,
            MobileTypes type,
            Transform parent = null,
            long loadID      = 0)
        {
            // Get default reaction
            MobileReactions reaction = MobileReactions.Hostile;

            if (obj.Resources.FlatResource.Action == (int)DFBlock.EnemyReactionTypes.Passive)
            {
                reaction = MobileReactions.Passive;
            }

            // Just setup demo enemies at this time
            string         name       = string.Format("DaggerfallEnemy [{0}]", type.ToString());
            Vector3        position   = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
            GameObject     go         = GameObjectHelper.InstantiatePrefab(DaggerfallUnity.Instance.Option_EnemyPrefab.gameObject, name, parent, position);
            SetupDemoEnemy setupEnemy = go.GetComponent <SetupDemoEnemy>();

            if (setupEnemy != null)
            {
                // Configure enemy
                setupEnemy.ApplyEnemySettings(type, reaction);

                // Align non-flying units with ground
                DaggerfallMobileUnit mobileUnit = setupEnemy.GetMobileBillboardChild();
                if (mobileUnit.Summary.Enemy.Behaviour != MobileBehaviour.Flying)
                {
                    GameObjectHelper.AlignControllerToGround(go.GetComponent <CharacterController>());
                }
            }

            DaggerfallEnemy enemy = go.GetComponent <DaggerfallEnemy>();

            if (enemy)
            {
                enemy.LoadID = loadID;
            }
        }
Esempio n. 4
0
        private static GameObject AddStandaloneModel(
            DaggerfallUnity dfUnity,
            ref ModelData modelData,
            Matrix4x4 matrix,
            Transform parent)
        {
            uint modelID = (uint)modelData.DFMesh.ObjectId;

            // Add GameObject
            GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(modelID, parent, dfUnity.Option_SetStaticFlags);

            go.transform.position = matrix.GetColumn(3);
            go.transform.rotation = GameObjectHelper.QuaternionFromMatrix(matrix);

            // Is this a city gate?
            if (IsCityGate(modelID))
            {
                go.AddComponent <DaggerfallCityGate>();
            }

            return(go);
        }
Esempio n. 5
0
        private static void AddProps(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut = new List <StaticDoor>();

            // Iterate through all misc records
            foreach (DFBlock.RmbBlock3dObjectRecord obj in blockData.RmbBlock.Misc3dObjectRecords)
            {
                // Get model transform
                Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos + propsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;
                Vector3   modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 modelMatrix   = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                // Get model data
                ModelData modelData;
                dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                // Does this model have doors?
                if (modelData.Doors != null)
                {
                    doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));
                }

                // Add or combine
                if (combiner == null)
                {
                    AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                }
                else
                {
                    combiner.Add(ref modelData, modelMatrix);
                }
            }
        }
Esempio n. 6
0
        private void AddEnemy(DFBlock.RdbObject obj, MobileTypes type)
        {
            // Get default reaction
            MobileReactions reaction = MobileReactions.Hostile;

            if (obj.Resources.FlatResource.FlatData.Reaction == (int)DFBlock.EnemyReactionTypes.Passive)
            {
                reaction = MobileReactions.Passive;
            }

            // Spawn enemy gameobject
            GameObject go = GameObjectHelper.CreateDaggerfallEnemyGameObject(type, enemiesNode.transform, reaction);

            if (go == null)
            {
                return;
            }

            // Set transform
            Vector3 enemyPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;

            go.transform.position = enemyPosition;
        }
Esempio n. 7
0
        private void AddRDBLight(DFBlock.RdbObject obj, Transform parent)
        {
            // Do nothing if import option not enabled
            if (!dfUnity.Option_ImportPointLights)
            {
                return;
            }

            // Spawn light gameobject
            float      radius        = obj.Resources.LightResource.Radius * MeshReader.GlobalScale;
            GameObject go            = GameObjectHelper.CreateDaggerfallRDBPointLight(radius, parent);
            Vector3    lightPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;

            // Add component
            DaggerfallLight c = go.AddComponent <DaggerfallLight>();

            if (dfUnity.Option_AnimatedPointLights)
            {
                c.Animate = true;
            }

            // Set transform
            go.transform.position = lightPosition;
        }
        public static void AddBlockFlats(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            Transform parent = null)
        {
            // Add block flats
            foreach (DFBlock.RmbBlockFlatObjectRecord obj in blockData.RmbBlock.MiscFlatObjectRecords)
            {
                // Spawn billboard gameobject
                GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, parent);
                go.transform.position = new Vector3(
                    obj.XPos,
                    -obj.YPos + BlockFlatsOffsetY,
                    obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;

                // Add lights
                if (obj.TextureArchive == 210 && dfUnity.Option_ImportPointLights)
                {
                    // Spawn light gameobject
                    Vector2    size    = dfUnity.MeshReader.GetScaledBillboardSize(210, obj.TextureRecord);
                    GameObject lightgo = GameObjectHelper.CreateDaggerfallRMBPointLight(go.transform);
                    lightgo.transform.position = new Vector3(
                        obj.XPos,
                        -obj.YPos + size.y,
                        obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;

                    // Animate light
                    DaggerfallLight c = lightgo.AddComponent <DaggerfallLight>();
                    c.ParentBillboard = go.GetComponent <DaggerfallBillboard>();
                    if (dfUnity.Option_AnimatedPointLights)
                    {
                        c.Animate = true;
                    }
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Instantiate base RMB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <param name="layoutX">X coordinate in parent map layout.</param>
        /// /// <param name="layoutY">Y coordinate in parent map layout.</param>
        /// <param name="cloneFrom">Prefab to clone from.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(ref DFBlock blockData, int layoutX, int layoutY, DaggerfallRMBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor>     modelDoors;
            List <StaticDoor>     propDoors;
            List <StaticBuilding> modelBuildings;

            // Add models and static props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, layoutX, layoutY, ref blockData, out modelDoors, out modelBuildings, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Combine list of doors found in models and props
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }

            // Assign building key to each door
            for (int i = 0; i < allDoors.Count; i++)
            {
                StaticDoor door = allDoors[i];
                door.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)door.recordIndex);
                allDoors[i]      = door;
            }

            // Assign building key to each building
            for (int i = 0; i < modelBuildings.Count; i++)
            {
                StaticBuilding building = modelBuildings[i];
                building.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)building.recordIndex);
                modelBuildings[i]    = building;
            }

            // Add static doors component
            if (allDoors.Count > 0)
            {
                AddStaticDoors(allDoors.ToArray(), go);
            }

            // Add static buildings component
            if (modelBuildings.Count > 0)
            {
                AddStaticBuildings(modelBuildings.ToArray(), go);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Esempio n. 10
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            out List <StaticBuilding> buildingsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut     = new List <StaticDoor>();
            buildingsOut = new List <StaticBuilding>();

            // Iterate through all subrecords
            int recordCount = 0;

            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3   subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3   subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix   = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                bool firstModel = true;
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3   modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                    Matrix4x4 modelMatrix   = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    if (modelData.Doors != null)
                    {
                        doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix));
                    }

                    // Store building information for first model of record
                    // First model is main record structure, others are attachments like posts
                    // Only main structure is needed to resolve building after hit-test
                    if (firstModel)
                    {
                        StaticBuilding staticBuilding = new StaticBuilding();
                        staticBuilding.modelMatrix = modelMatrix;
                        staticBuilding.recordIndex = recordCount;
                        staticBuilding.centre      = new Vector3(modelData.DFMesh.Centre.X, modelData.DFMesh.Centre.Y, modelData.DFMesh.Centre.Z) * MeshReader.GlobalScale;
                        staticBuilding.size        = new Vector3(modelData.DFMesh.Size.X, modelData.DFMesh.Size.Y, modelData.DFMesh.Size.Z) * MeshReader.GlobalScale;
                        buildingsOut.Add(staticBuilding);
                        firstModel = false;
                    }

                    // Import custom GameObject
                    if (MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix) != null)
                    {
                        continue;
                    }

                    // Use Daggerfall Model
                    // Add or combine
                    if (combiner == null || IsCityGate(obj.ModelIdNum))
                    {
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    }
                    else
                    {
                        combiner.Add(ref modelData, modelMatrix);
                    }
                }

                // Increment record count
                recordCount++;
            }
        }
Esempio n. 11
0
        /// <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;
                }

                if (!TextureReplacement.CustomTextureExist(obj.TextureArchive, obj.TextureRecord))
                {
                    // 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);
            }
        }
Esempio n. 12
0
        /// <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);
                    }
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Adds models and their actions to scene.
        /// </summary>
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            int[] textureTable,
            bool allowExitDoors,
            out List <StaticDoor> exitDoorsOut,
            ModelCombiner combiner       = null,
            Transform modelsParent       = null,
            Transform actionModelsParent = null)
        {
            exitDoorsOut = new List <StaticDoor>();

            // Action record linkages
            Dictionary <int, ActionLink> actionLinkDict = new Dictionary <int, ActionLink>();

            // Iterate object groups
            int groupIndex = 0;

            foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList)
            {
                // Skip empty object groups
                if (null == group.RdbObjects)
                {
                    groupIndex++;
                    continue;
                }

                // Iterate objects in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    // Add models
                    if (obj.Type == DFBlock.RdbResourceTypes.Model)
                    {
                        // Get model reference index and id
                        int  modelReference = obj.Resources.ModelResource.ModelIndex;
                        uint modelId        = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;

                        // Filter exit door models where flag not set
                        if (modelId == exitDoorModelID && !allowExitDoors)
                        {
                            continue;
                        }

                        // Filter action door models
                        // These must be added by AddActionDoors()
                        if (IsActionDoor(ref blockData, obj, modelReference))
                        {
                            continue;
                        }

                        // Get matrix
                        Matrix4x4 modelMatrix = GetModelMatrix(obj);

                        // Get model data
                        ModelData modelData;
                        dfUnity.MeshReader.GetModelData(modelId, out modelData);

                        // Add to static doors
                        exitDoorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));

                        // Check if model has an action record
                        bool hasAction = HasAction(obj);

                        // Special handling for tapestries and banners
                        // Some of these are so far out from wall player can become stuck behind them
                        // Adding model invidually without collider to avoid problem
                        // Not sure if these object ever actions, but bypass this hack if they do
                        if (modelId >= minTapestryID && modelId <= maxTapestryID && !hasAction)
                        {
                            AddStandaloneModel(dfUnity, ref modelData, modelMatrix, modelsParent, hasAction, true);
                            continue;
                        }

                        // Add or combine
                        GameObject standaloneObject = null;
                        Transform  parent           = (hasAction) ? actionModelsParent : modelsParent;
                        if (combiner == null || hasAction)
                        {
                            standaloneObject = AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent, hasAction);
                            standaloneObject.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);
                        }
                        else
                        {
                            combiner.Add(ref modelData, modelMatrix);
                        }

                        // Add action
                        if (hasAction && standaloneObject != null)
                        {
                            AddAction(standaloneObject, blockData, obj, modelReference, groupIndex, actionLinkDict);
                        }
                    }
                }

                // Increment group index
                groupIndex++;
            }

            // Link action nodes
            LinkActionNodes(actionLinkDict);
        }
Esempio n. 14
0
        /// <summary>
        /// Instantiate base RDB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <param name="textureTable">Optional texture table for dungeon.</param>
        /// <param name="allowExitDoors">Add exit doors to block.</param>
        /// <param name="cloneFrom">Clone and build on a prefab object template.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(
            ref DFBlock blockData,
            int[] textureTable           = null,
            bool allowExitDoors          = true,
            DaggerfallRDBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Use default texture table if one not specified
            if (textureTable == null)
            {
                textureTable = StaticTextureTables.DefaultTextureTable;
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent <DaggerfallRDBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRDB)
            {
                combiner = new ModelCombiner();
            }

            // Add parent node
            GameObject modelsNode       = new GameObject("Models");
            GameObject actionModelsNode = new GameObject("Action Models");

            modelsNode.transform.parent       = go.transform;
            actionModelsNode.transform.parent = go.transform;

            // Add models
            List <StaticDoor> exitDoors;

            AddModels(
                dfUnity,
                ref blockData,
                textureTable,
                allowExitDoors,
                out exitDoors,
                combiner,
                modelsNode.transform,
                actionModelsNode.transform);

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObject cgo = GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                    cgo.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);
                }
            }

            // Add exit doors
            if (exitDoors.Count > 0)
            {
                DaggerfallStaticDoors c = go.AddComponent <DaggerfallStaticDoors>();
                c.Doors = exitDoors.ToArray();
            }

            return(go);
        }
Esempio n. 15
0
        /// <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);
                }
            }
        }
Esempio n. 16
0
        /// <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);
                }
            }
        }
Esempio n. 17
0
        private void AddRDBModel(DFBlock.RdbObject obj, out List <StaticDoor> doorsOut, Transform parent)
        {
            bool overrideCombine = false;

            doorsOut = new List <StaticDoor>();

            // Get model reference index and id
            int  modelReference = obj.Resources.ModelResource.ModelIndex;
            uint modelId        = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;

            // Get rotation angle for each axis
            float degreesX = -obj.Resources.ModelResource.XRotation / BlocksFile.RotationDivisor;
            float degreesY = -obj.Resources.ModelResource.YRotation / BlocksFile.RotationDivisor;
            float degreesZ = -obj.Resources.ModelResource.ZRotation / BlocksFile.RotationDivisor;

            // Calcuate transform
            Vector3 position = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;

            // Calculate matrix
            Vector3   rx          = new Vector3(degreesX, 0, 0);
            Vector3   ry          = new Vector3(0, degreesY, 0);
            Vector3   rz          = new Vector3(0, 0, degreesZ);
            Matrix4x4 modelMatrix = Matrix4x4.identity;

            modelMatrix *= Matrix4x4.TRS(position, Quaternion.identity, Vector3.one);
            modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(rz), Vector3.one);
            modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(rx), Vector3.one);
            modelMatrix *= Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(ry), Vector3.one);

            // Get model data
            ModelData modelData;

            dfUnity.MeshReader.GetModelData(modelId, out modelData);

            // Discard static exit doors not in starting block
            // Exit doors are just a model slapped over wall or doorway
            // This allows Daggerfall to toggle exits on and off
            if (modelData.DFMesh.ObjectId == 70300)
            {
                if (!isStartingBlock)
                {
                    return;
                }
            }

            // Doors - there are no working static building doors inside dungeons, just the exits and action doors
            bool isActionDoor = IsActionDoor(blockData, obj, modelReference);

            if (isActionDoor)
            {
                parent = doorsNode.transform;
            }
            else if (modelData.Doors != null)
            {
                doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));
            }

            // Action records
            bool hasAction = HasAction(blockData, obj, modelReference);

            if (hasAction)
            {
                parent = actionModelsNode.transform;
            }

            // Flags
            bool isStatic = dfUnity.Option_SetStaticFlags;

            if (isActionDoor || hasAction)
            {
                // Moving objects are never static or combined
                isStatic        = false;
                overrideCombine = true;
            }

            // Add to scene
            if (dfUnity.Option_CombineRDB && !overrideCombine)
            {
                combiner.Add(ref modelData, modelMatrix);
            }
            else
            {
                // Spawn mesh gameobject
                GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, parent, isStatic);
                go.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);

                // Apply transforms
                go.transform.Rotate(0, degreesY, 0, Space.World);
                go.transform.Rotate(degreesX, 0, 0, Space.World);
                go.transform.Rotate(0, 0, degreesZ, Space.World);
                go.transform.localPosition = position;

                // Add action door
                if (isActionDoor)
                {
                    DaggerfallActionDoor dfActionDoor = go.AddComponent <DaggerfallActionDoor>();

                    // Add action door audio
                    if (dfUnity.Option_DefaultSounds)
                    {
                        AddActionDoorAudioSource(go);
                        dfActionDoor.SetDungeonDoorSounds();
                    }
                }

                // Add action component
                if (hasAction && !isActionDoor)
                {
                    AddAction(go, blockData, obj, modelReference);
                }
            }
        }
Esempio n. 18
0
        private void AddRDBFlat(DFBlock.RdbObject obj, Transform parent)
        {
            int archive = obj.Resources.FlatResource.TextureArchive;
            int record  = obj.Resources.FlatResource.TextureRecord;

            // Spawn billboard gameobject
            GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(archive, record, parent, true);
            Vector3    billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;

            // Add RDB data to billboard
            DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>();

            dfBillboard.SetResourceData(obj.Resources.FlatResource);

            // Set transform
            go.transform.position = billboardPosition;

            // Handle supported editor flats
            if (archive == 199)
            {
                switch (record)
                {
                case 10:                            // Start marker
                    startMarkers.Add(go);
                    break;

                case 15:                            // Random enemy
                    if (dfUnity.Option_ImportEnemies)
                    {
                        AddRandomRDBEnemy(obj);
                        go.SetActive(false);
                    }
                    break;

                case 16:                            // Fixed enemy
                    if (dfUnity.Option_ImportEnemies)
                    {
                        AddFixedRDBEnemy(obj);
                        go.SetActive(false);
                    }
                    break;
                }
            }

            // Add torch burning sound
            if (dfUnity.Option_DefaultSounds && archive == 210)
            {
                switch (record)
                {
                case 0:
                case 1:
                case 6:
                case 16:
                case 17:
                case 18:
                case 19:
                case 20:
                    AddTorchAudioSource(go);
                    break;
                }
            }
        }
Esempio n. 19
0
        public static GameObject CreateGameObject(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            bool disableGround = false,
            DaggerfallBillboardBatch natureBatch = null)
        {
            // Create gameobject
            GameObject go = new GameObject(string.Format("DaggerfallBlock [Name={0}]", blockData.Name));
            //go.AddComponent<DaggerfallBlock>();

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor> modelDoors;
            List <StaticDoor> propDoors;

            // Add models and props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Add doors
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }
            if (allDoors.Count > 0)
            {
                AddDoors(allDoors.ToArray(), go);
            }

            // Add block flats
            GameObject flatsNode = new GameObject("Flats");

            flatsNode.transform.parent = go.transform;
            AddBlockFlats(dfUnity, ref blockData, flatsNode.transform);

            // Add nature flats
            if (natureBatch == null)
            {
                AddNatureFlats(dfUnity, ref blockData, flatsNode.transform);
            }
            else
            {
                AddNatureFlatsToBatch(natureBatch, ref blockData);
            }

            // Add ground plane
            if (dfUnity.Option_SimpleGroundPlane && !disableGround)
            {
                AddSimpleGroundPlane(dfUnity, ref blockData, go.transform);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Esempio n. 20
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            int layoutX,
            int layoutY,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            out List <StaticBuilding> buildingsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut     = new List <StaticDoor>();
            buildingsOut = new List <StaticBuilding>();

            // Iterate through all subrecords
            int recordCount = 0;

            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3   subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3   subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix   = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                bool firstModel = true;
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3   modelRotation = new Vector3(-obj.XRotation / BlocksFile.RotationDivisor, -obj.YRotation / BlocksFile.RotationDivisor, -obj.ZRotation / BlocksFile.RotationDivisor);
                    Vector3   modelScale    = GetModelScaleVector(obj);
                    Matrix4x4 modelMatrix   = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), modelScale);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    StaticDoor[] staticDoors = null;
                    if (modelData.Doors != null)
                    {
                        staticDoors = GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix);
                    }

                    // Store building information for first model of record
                    // First model is main record structure, others are attachments like posts
                    // Only main structure is needed to resolve building after hit-test
                    int buildingKey = 0;
                    if (firstModel)
                    {
                        // Create building key for this record - considered experimental for now
                        buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)recordCount);

                        StaticBuilding staticBuilding = new StaticBuilding();
                        staticBuilding.modelMatrix = modelMatrix;
                        staticBuilding.recordIndex = recordCount;
                        staticBuilding.centre      = new Vector3(modelData.DFMesh.Centre.X, modelData.DFMesh.Centre.Y, modelData.DFMesh.Centre.Z) * MeshReader.GlobalScale;
                        staticBuilding.size        = new Vector3(modelData.DFMesh.Size.X, modelData.DFMesh.Size.Y, modelData.DFMesh.Size.Z) * MeshReader.GlobalScale;
                        buildingsOut.Add(staticBuilding);
                        firstModel = false;
                    }

                    bool dontCreateStaticDoors = false;

                    // Import custom GameObject or use Daggerfall Model
                    GameObject go;
                    if (go = MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix))
                    {
                        // Find doors
                        if (staticDoors != null && staticDoors.Length > 0)
                        {
                            CustomDoor.InitDoors(go, staticDoors, buildingKey, out dontCreateStaticDoors);
                        }
                    }
                    else if (combiner == null || IsCityGate(obj.ModelIdNum) || IsBulletinBoard(obj.ModelIdNum) || PlayerActivate.HasCustomActivation(obj.ModelIdNum))
                    {
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    }
                    else
                    {
                        combiner.Add(ref modelData, modelMatrix);
                    }

                    if (modelData.Doors != null && !dontCreateStaticDoors)
                    {
                        doorsOut.AddRange(staticDoors);
                    }
                }

                // Increment record count
                recordCount++;
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Creates a new RDB GameObject and performs block layout.
        /// Can pass information about dungeon for texture swaps and random enemies.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="blockName">Name of RDB block to build.</param>
        /// <param name="isStartingBlock">True if this is the starting block. Controls exit doors.</param>
        /// <param name="textureTable">Dungeon texture table.</param>
        /// <param name="dungeonType">Type of dungeon for random encounter tables.</param>
        /// <param name="seed">Seed for random encounters.</param>
        /// <returns>GameObject.</returns>
        public static GameObject CreateGameObject(
            string blockName,
            bool isStartingBlock,
            int[] textureTable = null,
            DFRegion.DungeonTypes dungeonType = DFRegion.DungeonTypes.HumanStronghold,
            int seed = 0)
        {
            // Validate
            if (string.IsNullOrEmpty(blockName))
            {
                return(null);
            }
            if (!blockName.ToUpper().EndsWith(".RDB"))
            {
                return(null);
            }
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create gameobject
            GameObject         go      = new GameObject(string.Format("DaggerfallBlock [Name={0}]", blockName));
            DaggerfallRDBBlock dfBlock = go.AddComponent <DaggerfallRDBBlock>();

            // Start new layout
            RDBLayout layout = new RDBLayout(blockName);

            layout.isStartingBlock  = isStartingBlock;
            layout.textureTable     = textureTable;
            layout.dungeonType      = dungeonType;
            layout.staticModelsNode = new GameObject("Static Models");
            layout.actionModelsNode = new GameObject("Action Models");
            layout.doorsNode        = new GameObject("Doors");
            layout.flatsNode        = new GameObject("Flats");
            layout.lightsNode       = new GameObject("Lights");
            layout.enemiesNode      = new GameObject("Enemies");

            // Parent child game objects
            layout.staticModelsNode.transform.parent = go.transform;
            layout.actionModelsNode.transform.parent = go.transform;
            layout.doorsNode.transform.parent        = go.transform;
            layout.flatsNode.transform.parent        = go.transform;
            layout.lightsNode.transform.parent       = go.transform;
            layout.enemiesNode.transform.parent      = go.transform;

            // List to receive any exit doors found
            List <StaticDoor> allDoors = new List <StaticDoor>();

            // Seed random generator
            UnityEngine.Random.seed = seed;

            // Iterate object groups
            layout.groupIndex = 0;
            DFBlock blockData = dfUnity.ContentReader.BlockFileReader.GetBlock(blockName);

            foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList)
            {
                // Skip empty object groups
                if (null == group.RdbObjects)
                {
                    layout.groupIndex++;
                    continue;
                }

                // Iterate objects in this group
                List <StaticDoor> modelDoors;
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    // Handle by object type
                    switch (obj.Type)
                    {
                    case DFBlock.RdbResourceTypes.Model:
                        layout.AddRDBModel(obj, out modelDoors, layout.staticModelsNode.transform);
                        if (modelDoors.Count > 0)
                        {
                            allDoors.AddRange(modelDoors);
                        }
                        break;

                    case DFBlock.RdbResourceTypes.Flat:
                        layout.AddRDBFlat(obj, layout.flatsNode.transform);
                        break;

                    case DFBlock.RdbResourceTypes.Light:
                        layout.AddRDBLight(obj, layout.lightsNode.transform);
                        break;

                    default:
                        break;
                    }
                }

                // Increment group index
                layout.groupIndex++;
            }

            // Link action nodes
            layout.LinkActionNodes();

            // Combine meshes
            if (dfUnity.Option_CombineRDB)
            {
                layout.combiner.Apply();
                GameObject cgo = GameObjectHelper.CreateCombinedMeshGameObject(layout.combiner, "CombinedMeshes", layout.staticModelsNode.transform, dfUnity.Option_SetStaticFlags);
                cgo.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);
            }

            // Fix enemy standing positions for this block
            // Some enemies are floating in air or sunk into ground
            // Can only adjust this after geometry instantiated
            layout.FixEnemyStanding(go);

            // Store start markers in block
            dfBlock.SetStartMarkers(layout.startMarkers.ToArray());

            // Add doors
            if (allDoors.Count > 0)
            {
                layout.AddDoors(allDoors.ToArray(), go);
            }

            return(go);
        }
Esempio n. 22
0
        /// <summary>
        /// Instantiate base RMB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(ref DFBlock blockData, DaggerfallRMBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent <DaggerfallRMBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor> modelDoors;
            List <StaticDoor> propDoors;

            // Add models and static props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Add doors
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }
            if (allDoors.Count > 0)
            {
                AddStaticDoors(allDoors.ToArray(), go);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Esempio n. 23
0
        /// <summary>
        /// Layout a complete RMB block game object.
        /// Can be used standalone or as part of a city build.
        /// </summary>
        public static GameObject CreateRMBBlockGameObject(
            string blockName,
            bool addGroundPlane          = true,
            DaggerfallRMBBlock cloneFrom = null,
            DaggerfallBillboardBatch natureBillboardBatch  = null,
            DaggerfallBillboardBatch lightsBillboardBatch  = null,
            DaggerfallBillboardBatch animalsBillboardBatch = null,
            TextureAtlasBuilder miscBillboardAtlas         = null,
            DaggerfallBillboardBatch miscBillboardBatch    = null,
            ClimateNatureSets climateNature = ClimateNatureSets.TemperateWoodland,
            ClimateSeason climateSeason     = ClimateSeason.Summer)
        {
            // Get DaggerfallUnity
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create base object
            DFBlock    blockData;
            GameObject go = RMBLayout.CreateBaseGameObject(blockName, out blockData, cloneFrom);

            // Create flats node
            GameObject flatsNode = new GameObject("Flats");

            flatsNode.transform.parent = go.transform;

            // Create lights node
            GameObject lightsNode = new GameObject("Lights");

            lightsNode.transform.parent = go.transform;

            // If billboard batching is enabled but user has not specified
            // a batch, then make our own auto batch for this block
            bool autoLightsBatch  = false;
            bool autoNatureBatch  = false;
            bool autoAnimalsBatch = false;

            if (dfUnity.Option_BatchBillboards)
            {
                if (natureBillboardBatch == null)
                {
                    autoNatureBatch = true;
                    int natureArchive = ClimateSwaps.GetNatureArchive(climateNature, climateSeason);
                    natureBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(natureArchive, flatsNode.transform);
                }
                if (lightsBillboardBatch == null)
                {
                    autoLightsBatch      = true;
                    lightsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.LightsTextureArchive, flatsNode.transform);
                }
                if (animalsBillboardBatch == null)
                {
                    autoAnimalsBatch      = true;
                    animalsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.AnimalsTextureArchive, flatsNode.transform);
                }
            }

            // Layout light billboards and gameobjects
            RMBLayout.AddLights(ref blockData, flatsNode.transform, lightsNode.transform, lightsBillboardBatch);

            // Layout nature billboards
            RMBLayout.AddNatureFlats(ref blockData, flatsNode.transform, natureBillboardBatch, climateNature, climateSeason);

            // Layout all other flats
            RMBLayout.AddMiscBlockFlats(ref blockData, flatsNode.transform, animalsBillboardBatch, miscBillboardAtlas, miscBillboardBatch);

            // Add ground plane
            if (addGroundPlane)
            {
                RMBLayout.AddGroundPlane(ref blockData, go.transform);
            }

            // Apply auto batches
            if (autoNatureBatch)
            {
                natureBillboardBatch.Apply();
            }
            if (autoLightsBatch)
            {
                lightsBillboardBatch.Apply();
            }
            if (autoAnimalsBatch)
            {
                animalsBillboardBatch.Apply();
            }

            return(go);
        }