예제 #1
0
        /// <summary>
        /// Add actions doors to block.
        /// </summary>
        public static void AddActionDoors(GameObject go, Dictionary<int, ActionLink> actionLinkDict, ref DFBlock blockData, int[] textureTable, bool serialize = true)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

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

            // Add parent node
            GameObject actionDoorsNode = new GameObject("Action Doors");
            actionDoorsNode.transform.parent = go.transform;

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

                // Look for models in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    if (obj.Type == DFBlock.RdbResourceTypes.Model)
                    {
                        // Create unique LoadID for save sytem
                        long loadID = 0;
                        if (serialize)
                            loadID = (blockData.Index << 24) + obj.This;

                        // Look for action doors
                        int modelReference = obj.Resources.ModelResource.ModelIndex;
                        uint modelId = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;
                        if (IsActionDoor(ref blockData, obj, modelReference))
                        {
                            GameObject cgo = AddActionDoor(dfUnity, modelId, obj, actionDoorsNode.transform, loadID);
                            cgo.GetComponent<DaggerfallMesh>().SetDungeonTextures(textureTable);

                            // Add action component to door if it also has an action
                            if (HasAction(obj))
                            {
                                AddActionModelHelper(cgo, actionLinkDict, obj, ref blockData, serialize);
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Add simple ground plane to block layout.
        /// </summary>
        public static GameObject AddGroundPlane(
            ref DFBlock blockData,
            Transform parent = null,
            ClimateBases climateBase = ClimateBases.Temperate,
            ClimateSeason climateSeason = ClimateSeason.Summer)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return null;

            GameObject go = new GameObject("Ground");
            if (parent != null)
                go.transform.parent = parent;

            // Assign components
            DaggerfallGroundPlane dfGround = go.AddComponent<DaggerfallGroundPlane>();
            MeshFilter meshFilter = go.GetComponent<MeshFilter>();

            // Assign climate and mesh
            Color32[] tileMap;
            Mesh mesh = dfUnity.MeshReader.GetSimpleGroundPlaneMesh(
                ref blockData,
                out tileMap,
                dfUnity.MeshReader.AddMeshTangents,
                dfUnity.MeshReader.AddMeshLightmapUVs);
            if (mesh)
            {
                meshFilter.sharedMesh = mesh;
            }

            // Assign tileMap and climate
            dfGround.tileMap = tileMap;
            dfGround.SetClimate(dfUnity, climateBase, climateSeason);

            // Assign collider
            if (dfUnity.Option_AddMeshColliders)
                go.AddComponent<BoxCollider>();

            // Assign static
            if (dfUnity.Option_SetStaticFlags)
                go.isStatic = true;

            return go;
        }
예제 #3
0
        /// <summary>
        /// Add actions doors to block.
        /// </summary>
        public static void AddActionDoors(GameObject go, ref DFBlock blockData, int[] textureTable)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

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

            // Add parent node
            GameObject actionDoorsNode = new GameObject("Action Doors");
            actionDoorsNode.transform.parent = go.transform;

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

                // Look for models in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    if (obj.Type == DFBlock.RdbResourceTypes.Model)
                    {
                        // Look for action doors
                        int modelReference = obj.Resources.ModelResource.ModelIndex;
                        uint modelId = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;
                        if (IsActionDoor(ref blockData, obj, modelReference))
                        {
                            GameObject cgo = AddActionDoor(dfUnity, modelId, obj, actionDoorsNode.transform);
                            cgo.GetComponent<DaggerfallMesh>().SetDungeonTextures(textureTable);
                        }
                    }
                }
            }
        }
예제 #4
0
        private static void AddLight(DaggerfallUnity dfUnity, DFBlock.RmbBlockFlatObjectRecord obj, Transform parent = null)
        {
            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;

            GameObjectHelper.InstantiatePrefab(dfUnity.Option_CityLightPrefab.gameObject, string.Empty, parent, position);
        }
예제 #5
0
        /// <summary>
        /// Adds models and their actions to scene.
        /// </summary>
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            Dictionary<int, ActionLink> actionLinkDict,
            int[] textureTable,
            bool allowExitDoors,
            out List<StaticDoor> exitDoorsOut,
            bool serialize,
            ModelCombiner combiner = null,
            Transform modelsParent = null,
            Transform actionModelsParent = null)
        {
            exitDoorsOut = new List<StaticDoor>();

            // Iterate object groups
            foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList)
            {
                // Skip empty object groups
                if (null == group.RdbObjects)
                {
                    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)
                            AddActionModelHelper(standaloneObject, actionLinkDict, obj, ref blockData, serialize);
                    }
                }
            }
        }
예제 #6
0
        private static GameObject AddFlat(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;

            // Disable enemy flats
            if (archive == TextureReader.EditorFlatsTextureArchive && (record == 15 || record == 16))
                go.SetActive(false);

            // Add torch burning sound
            if (archive == TextureReader.LightsTextureArchive)
            {
                switch (record)
                {
                    case 0:
                    case 1:
                    case 6:
                    case 16:
                    case 17:
                    case 18:
                    case 19:
                    case 20:
                        AddTorchAudioSource(go);
                        break;
                }
            }

            return go;
        }
예제 #7
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;
            }
        }
예제 #8
0
        private static void AddActionFlatHelper(
            GameObject go,
            Dictionary<int, ActionLink> actionLinkDict,
            ref DFBlock blockData,
            DFBlock.RdbObject rdbObj,
            bool serialize = true)
        {
            DFBlock.RdbFlatResource obj = rdbObj.Resources.FlatResource;
            string description = "FLT";
            int soundID_Index = obj.Sound_index;
            float duration = 0.0f;
            float magnitude = obj.Magnitude;
            int axis = obj.Magnitude;
            DFBlock.RdbTriggerFlags triggerFlag = DFBlock.RdbTriggerFlags.None;
            DFBlock.RdbActionFlags actionFlag = DFBlock.RdbActionFlags.None;

            //set action flag if valid / known
            if (Enum.IsDefined(typeof(DFBlock.RdbActionFlags), (DFBlock.RdbActionFlags)obj.Action))
                actionFlag = (DFBlock.RdbActionFlags)obj.Action;

            //set trigger flag if valid / known
            if (Enum.IsDefined(typeof(DFBlock.RdbTriggerFlags), (DFBlock.RdbTriggerFlags)obj.TriggerFlag))
                triggerFlag = (DFBlock.RdbTriggerFlags)obj.TriggerFlag;

            //add action node to actionLink dictionary
            if (!actionLinkDict.ContainsKey(rdbObj.This))
            {
                ActionLink link;
                link.nextKey = obj.NextObjectOffset;
                link.prevKey = -1;
                link.gameObject = go;
                actionLinkDict.Add(rdbObj.This, link);
            }

            // Create unique LoadID for save sytem
            long loadID = 0;
            if (serialize)
                loadID = (blockData.Index << 24) + rdbObj.This;

            AddAction(go, description, soundID_Index, duration, magnitude, axis, triggerFlag, actionFlag, loadID);
        }
예제 #9
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>
        /// <param name="serialize">Allow for serialization of supported sub-objects.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(
            ref DFBlock blockData,
            Dictionary<int, ActionLink> actionLinkDict,
            int[] textureTable = null,
            bool allowExitDoors = true,
            DaggerfallRDBBlock cloneFrom = null,
            bool serialize = true)
        {
            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,
                actionLinkDict,
                textureTable,
                allowExitDoors,
                out exitDoors,
                serialize,
                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;
        }
예제 #10
0
        /// <summary>
        /// Extracts correct matrix from model data.
        /// </summary>
        private static Matrix4x4 GetModelMatrix(DFBlock.RdbObject obj)
        {
            // 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);

            return modelMatrix;
        }
예제 #11
0
        /// <summary>
        /// Layout interior based on data in exterior door and optional location for climate settings.
        /// </summary>
        /// <param name="doorOwner">Parent transform owning door array.</param>
        /// <param name="door">Exterior door player clicked on.</param>
        /// <returns>True if successful.</returns>
        public bool DoLayout(Transform doorOwner, StaticDoor door, ClimateBases climateBase)
        {
            if (dfUnity == null)
                dfUnity = DaggerfallUnity.Instance;

            // Use specified climate
            this.climateBase = climateBase;

            // Save exterior information
            this.entryDoor = door;
            this.doorOwner = doorOwner;

            // Get block data
            blockData = dfUnity.ContentReader.BlockFileReader.GetBlock(door.blockIndex);
            if (blockData.Type != DFBlock.BlockTypes.Rmb)
                throw new Exception(string.Format("Could not load RMB block index {0}", door.blockIndex), null);

            // Get record data
            recordData = blockData.RmbBlock.SubRecords[door.recordIndex];
            if (recordData.Interior.Header.Num3dObjectRecords == 0)
                throw new Exception(string.Format("No interior 3D models found for record index {0}", door.recordIndex), null);

            // Layout interior data
            AddModels();
            AddFlats();
            AddPeople();
            AddActionDoors();

            return true;
        }
        /// <summary>
        /// Adds interior point light.
        /// </summary>
        private static void AddLight(DFBlock.RmbBlockFlatObjectRecord obj, Transform parent = null)
        {
            if (DaggerfallUnity.Instance.Option_InteriorLightPrefab == null)
                return;

            // Create gameobject
            GameObject go = GameObjectHelper.InstantiatePrefab(DaggerfallUnity.Instance.Option_InteriorLightPrefab.gameObject, string.Empty, parent, Vector3.zero);

            // Set local position to billboard origin, otherwise light transform is at base of billboard
            go.transform.localPosition = Vector3.zero;

            // Adjust position of light for standing lights as their source comes more from top than middle
            Vector2 size = DaggerfallUnity.Instance.MeshReader.GetScaledBillboardSize(210, obj.TextureRecord) * MeshReader.GlobalScale;
            switch (obj.TextureRecord)
            {
                case 0:         // Bowl with fire
                    go.transform.localPosition += new Vector3(0, -0.1f, 0);
                    break;
                case 1:         // Campfire
                    // todo
                    break;
                case 2:         // Skull candle
                    go.transform.localPosition += new Vector3(0, 0.1f, 0);
                    break;
                case 3:         // Candle
                    go.transform.localPosition += new Vector3(0, 0.1f, 0);
                    break;
                case 4:         // Candle in bowl
                    // todo
                    break;
                case 5:         // Candleholder with 3 candles
                    go.transform.localPosition += new Vector3(0, 0.15f, 0);
                    break;
                case 6:         // Skull torch
                    go.transform.localPosition += new Vector3(0, 0.6f, 0);
                    break;
                case 7:         // Wooden chandelier with extinguished candles
                    // todo
                    break;
                case 8:         // Turkis lamp
                    // do nothing
                    break;
                case 9:        // Metallic chandelier with burning candles
                    go.transform.localPosition += new Vector3(0, 0.4f, 0);
                    break;
                case 10:         // Metallic chandelier with extinguished candles
                    // todo
                    break;
                case 11:        // Candle in lamp
                    go.transform.localPosition += new Vector3(0, -0.4f, 0);
                    break;
                case 12:         // Extinguished lamp
                    // todo
                    break;
                case 13:        // Round lamp (e.g. main lamp in mages guild)
                    go.transform.localPosition += new Vector3(0, -0.35f, 0);
                    break;
                case 14:        // Standing lantern
                    go.transform.localPosition += new Vector3(0, size.y / 2, 0);
                    break;
                case 15:        // Standing lantern round
                    go.transform.localPosition += new Vector3(0, size.y / 2, 0);
                    break;
                case 16:         // Mounted Torch with thin holder
                    // todo
                    break;
                case 17:        // Mounted torch 1
                    go.transform.localPosition += new Vector3(0, 0.2f, 0);
                    break;
                case 18:         // Mounted Torch 2
                    // todo
                    break;
                case 19:         // Pillar with firebowl
                    // todo
                    break;
                case 20:        // Brazier torch
                    go.transform.localPosition += new Vector3(0, 0.6f, 0);
                    break;
                case 21:        // Standing candle
                    go.transform.localPosition += new Vector3(0, size.y / 2.4f, 0);
                    break;
                case 22:         // Round lantern with medium chain
                    go.transform.localPosition += new Vector3(0, -0.5f, 0);
                    break;
                case 23:         // Wooden chandelier with burning candles
                    // todo
                    break;
                case 24:        // Lantern with long chain
                    go.transform.localPosition += new Vector3(0, -1.85f, 0);
                    break;
                case 25:        // Lantern with medium chain
                    go.transform.localPosition += new Vector3(0, -1.0f, 0);
                    break;
                case 26:        // Lantern with short chain
                    // todo
                    break;
                case 27:        // Lantern with no chain
                    go.transform.localPosition += new Vector3(0, -0.02f, 0);
                    break;
                case 28:        // Street Lantern 1
                    // todo
                    break;
                case 29:        // Street Lantern 2
                    // todo
                    break;
            }

            // adjust properties of light sources (e.g. Shrink light radius of candles)
            Light light = go.GetComponent<Light>();
            switch (obj.TextureRecord)
            {
                case 0:         // Bowl with fire
                    light.range = 20.0f;
                    light.intensity = 1.1f;
                    light.color = new Color(0.95f, 0.91f, 0.63f);
                    break;
                case 1:         // Campfire
                    // todo
                    break;
                case 2:         // Skull candle
                    light.range /= 3f;
                    light.intensity = 0.6f;
                    light.color = new Color(1.0f, 0.99f, 0.82f);
                    break;
                case 3:         // Candle
                    light.range /= 3f;
                    break;
                case 4:         // Candle with base
                    light.range /= 3f;
                    break;
                case 5:         // Candleholder with 3 candles
                    light.range = 7.5f;
                    light.intensity = 0.33f;
                    light.color = new Color(1.0f, 0.89f, 0.61f);
                    break;
                case 6:         // Skull torch
                    light.range = 15.0f;
                    light.intensity = 0.75f;
                    light.color = new Color(1.0f, 0.93f, 0.62f);
                    break;
                case 7:         // Wooden chandelier with extinguished candles
                    // todo
                    break;
                case 8:         // Turkis lamp
                    light.color = new Color(0.68f, 1.0f, 0.94f);
                    break;
                case 9:        // metallic chandelier with burning candles
                    light.range = 15.0f;
                    light.intensity = 0.65f;
                    light.color = new Color(1.0f, 0.92f, 0.6f);
                    break;
                case 10:         // Metallic chandelier with extinguished candles
                    // todo
                    break;
                case 11:        // Candle in lamp
                    light.range = 5.0f;
                    light.intensity = 0.5f;
                    break;
                case 12:         // Extinguished lamp
                    // todo
                    break;
                case 13:        // Round lamp (e.g. main lamp in mages guild)
                    light.range *= 1.2f;
                    light.intensity = 1.1f;
                    light.color = new Color(0.93f, 0.84f, 0.49f);
                    break;
                case 14:        // Standing lantern
                    // todo
                    break;
                case 15:        // Standing lantern round
                    // todo
                    break;
                case 16:         // Mounted Torch with thin holder
                    // todo
                    break;
                case 17:        // Mounted torch 1
                    light.intensity = 0.8f;
                    light.color = new Color(1.0f, 0.97f, 0.87f);
                    break;
                case 18:         // Mounted Torch 2
                    // todo
                    break;
                case 19:         // Pillar with firebowl
                    // todo
                    break;
                case 20:        // Brazier torch
                    light.range = 12.0f;
                    light.intensity = 0.75f;
                    light.color = new Color(1.0f, 0.92f, 0.72f);
                    break;
                case 21:        // Standing candle
                    light.range /= 3f;
                    light.intensity = 0.5f;
                    light.color = new Color(1.0f, 0.95f, 0.67f);
                    break;
                case 22:         // Round lantern with medium chain
                    light.intensity = 1.5f;
                    light.color = new Color(1.0f, 0.95f, 0.78f);
                    break;
                case 23:         // Wooden chandelier with burning candles
                    // todo
                    break;
                case 24:        // Lantern with long chain
                    light.intensity = 1.4f;
                    light.color = new Color(1.0f, 0.98f, 0.64f);
                    break;
                case 25:        // Lantern with medium chain
                    light.intensity = 1.4f;
                    light.color = new Color(1.0f, 0.98f, 0.64f);
                    break;
                case 26:        // Lantern with short chain
                    light.intensity = 1.4f;
                    light.color = new Color(1.0f, 0.98f, 0.64f);
                    break;
                case 27:        // Lantern with no chain
                    light.intensity = 1.4f;
                    light.color = new Color(1.0f, 0.98f, 0.64f);
                    break;
                case 28:        // Street Lantern 1
                    // todo
                    break;
                case 29:        // Street Lantern 2
                    // todo
                    break;
            }

            // TODO: Could also adjust light colour and intensity, or change prefab entirely above for any obj.TextureRecord
        }
        /// <summary>
        /// Attempts to get a Daggerfall block from BLOCKS.BSA.
        /// </summary>
        /// <param name="name">Name of block.</param>
        /// <param name="blockOut">DFBlock data out.</param>
        /// <returns>True if successful.</returns>
        public bool GetBlock(string name, out DFBlock blockOut)
        {
            blockOut = new DFBlock();

            if (!isReady)
                return false;

            // Get block data
            blockOut = blockFileReader.GetBlock(name);
            if (blockOut.Type == DFBlock.BlockTypes.Unknown)
            {
                DaggerfallUnity.LogMessage(string.Format("Unknown block '{0}'.", name), true);
                return false;
            }

            return true;
        }
예제 #14
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);
            }
        }
예제 #15
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List<StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent = null)
        {
            doorsOut = new List<StaticDoor>();

            // 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
                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));

                    // 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++;
            }
        }
예제 #16
0
        /// <summary>
        /// Add random enemies from encounter tables based on dungeon type, monster power, and seed.
        /// </summary>
        /// <param name="go">GameObject to add monsters to.</param>
        /// <param name="editorObjects">Editor objects containing flats.</param>
        /// <param name="dungeonType">Dungeon type selects the encounter table.</param>
        /// <param name="monsterPower">Value between 0-1 for lowest monster power to highest.</param>
        /// <param name="monsterVariance">Adjust final index +/- this value in encounter table.</param>
        /// <param name="seed">Random seed for encounters.</param>
        /// <param name="serialize">Allow for serialization when available.</param>
        public static void AddRandomEnemies(
            GameObject go,
            DFBlock.RdbObject[] editorObjects,
            DFRegion.DungeonTypes dungeonType,
            float monsterPower,
            ref DFBlock blockData,
            int monsterVariance = 4,
            int seed = 0,
            bool serialize = true)
        {
            const int randomMonsterFlatIndex = 15;

            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

            // Must have import enabled and prefab set
            if (!dfUnity.Option_ImportEnemyPrefabs || dfUnity.Option_EnemyPrefab == null)
                return;

            // Editor objects array must be populated
            if (editorObjects == null || editorObjects.Length == 0)
                return;

            // Add parent node
            GameObject randomEnemiesNode = new GameObject("Random Enemies");
            randomEnemiesNode.transform.parent = go.transform;

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

            // Iterate editor flats for enemies
            for (int i = 0; i < editorObjects.Length; i++)
            {
                // Add random enemy objects
                if (editorObjects[i].Resources.FlatResource.TextureRecord == randomMonsterFlatIndex)
                    AddRandomRDBEnemy(editorObjects[i], dungeonType, monsterPower, monsterVariance, randomEnemiesNode.transform, ref blockData, serialize);
            }
        }
예제 #17
0
        /// <summary>
        /// Create base RDB block by name and get back DFBlock data.
        /// </summary>
        /// <param name="blockName">Name of block.</param>
        /// <param name="blockDataOut">DFBlock data out.</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>
        /// <param name="serialize">Allow for serialization of supported sub-objects.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(
            string blockName,
            Dictionary<int, ActionLink> actionLinkDict,
            out DFBlock blockDataOut,
            int[] textureTable = null,
            bool allowExitDoors = true,
            DaggerfallRDBBlock cloneFrom = null,
            bool serialize = true)
        {
            blockDataOut = new DFBlock();

            // Validate
            if (string.IsNullOrEmpty(blockName))
                return null;
            if (!blockName.EndsWith(".RDB", StringComparison.InvariantCultureIgnoreCase))
                return null;
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return null;

            // Get block data
            blockDataOut = dfUnity.ContentReader.BlockFileReader.GetBlock(blockName);

            return CreateBaseGameObject(ref blockDataOut, actionLinkDict, textureTable, allowExitDoors, cloneFrom, serialize);
        }
예제 #18
0
        /// <summary>
        /// Constructs a Vector3 from magnitude and direction in RDB action resource.
        /// </summary>
        private static void GetRotationActionVector(ref DaggerfallAction action, DFBlock.RdbActionAxes axis)
        {
            Vector3 vector = Vector3.zero;
            float magnitude = action.Magnitude;
            switch (axis)
            {
                case DFBlock.RdbActionAxes.NegativeX:
                    vector.x = -magnitude;
                    break;
                case DFBlock.RdbActionAxes.NegativeY:
                    vector.y = -magnitude;
                    break;
                case DFBlock.RdbActionAxes.NegativeZ:
                    vector.z = -magnitude;
                    break;

                case DFBlock.RdbActionAxes.PositiveX:
                    vector.x = magnitude;
                    break;
                case DFBlock.RdbActionAxes.PositiveY:
                    vector.y = magnitude;
                    break;
                case DFBlock.RdbActionAxes.PositiveZ:
                    vector.z = magnitude;
                    break;
                default:
                    magnitude = 0f;
                    break;
            }

            action.ActionRotation = vector / BlocksFile.RotationDivisor;
        }
예제 #19
0
        private static void AddAction(
            GameObject go,
            string description,
            int soundID_and_index,
            float duration,
            float magnitude,
            int axis_raw,
            DFBlock.RdbTriggerFlags triggerFlag,
            DFBlock.RdbActionFlags actionFlag,
            long loadID = 0
            )
        {
            DaggerfallAction action = go.AddComponent<DaggerfallAction>();
            action.ModelDescription = description;
            action.ActionDuration = duration;
            action.Magnitude = magnitude;
            action.Index = soundID_and_index;
            action.TriggerFlag = triggerFlag;
            action.ActionFlag = actionFlag;
            action.LoadID = loadID;

            // If SaveLoadManager present in game then attach SerializableActionObject
            if (SaveLoadManager.Instance != null)
            {
                go.AddComponent<SerializableActionObject>();
            }

            //if a collision type action or action flat, add DaggerFallActionCollision component
            if (action.TriggerFlag == DFBlock.RdbTriggerFlags.Collision01 || action.TriggerFlag == DFBlock.RdbTriggerFlags.Collision03 ||
                action.TriggerFlag == DFBlock.RdbTriggerFlags.DualTrigger || action.TriggerFlag == DFBlock.RdbTriggerFlags.Collision09)
            {
                DaggerfallActionCollision collision = go.AddComponent<DaggerfallActionCollision>();
                collision.isFlat = false;
            }
            else if (description == "FLT")
            {
                DaggerfallActionCollision collision = go.AddComponent<DaggerfallActionCollision>();
                collision.isFlat = true;
            }

            switch (action.ActionFlag)
            {
                case DFBlock.RdbActionFlags.Translation:
                    {
                        action.Magnitude = magnitude;
                        GetTranslationActionVector(ref action, (DFBlock.RdbActionAxes)axis_raw);
                    }
                    break;

                case DFBlock.RdbActionFlags.Rotation:
                    {
                        action.Magnitude = magnitude;
                        GetRotationActionVector(ref action, (DFBlock.RdbActionAxes)axis_raw);
                    }
                    break;
                case DFBlock.RdbActionFlags.PositiveX:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.PositiveX);
                    }
                    break;
                case DFBlock.RdbActionFlags.NegativeX:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.NegativeX);
                    }
                    break;
                case DFBlock.RdbActionFlags.PositiveY:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.PositiveY);
                    }
                    break;
                case DFBlock.RdbActionFlags.NegativeY:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.NegativeY);

                    }
                    break;
                case DFBlock.RdbActionFlags.PositiveZ:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.PositiveZ);
                    }
                    break;
                case DFBlock.RdbActionFlags.NegativeZ:
                    {
                        action.ActionDuration = 50;
                        action.Magnitude = axis_raw * 8;
                        GetTranslationActionVector(ref action, DFBlock.RdbActionAxes.NegativeZ);
                    }
                    break;
                default:
                    {
                        //Dmg actions use axis value to modifiy tot. dmg.
                        action.Magnitude = axis_raw;
                    }
                    break;
            }

            // A quick hack to fix special-case rotation issues.
            // Currently unknown if there is data indicating different rotation behaviour or if something else is happening.
            switch (description)
            {
                case "LID":
                    action.ActionRotation = new Vector3(0, 0, -90f);       // Coffin lids (e.g. Scourg barrow)
                    break;
                case "WHE":
                    action.ActionRotation = new Vector3(0, -360f, 0);      // Wheels (e.g. Direnni Tower)
                    break;
            }

            //Add audio
            AddActionAudioSource(go, (uint)action.Index);
        }
예제 #20
0
        /// <summary>
        /// Constructs a Vector3 from magnitude and direction in RDB action resource.
        /// </summary>
        private static void GetTranslationActionVector(ref DaggerfallAction action, DFBlock.RdbActionAxes axis)
        {
            Vector3 vector = Vector3.zero;
            float magnitude = action.Magnitude;
            switch (axis)
            {
                case DFBlock.RdbActionAxes.NegativeX:
                    vector.x = magnitude;
                    break;
                case DFBlock.RdbActionAxes.NegativeY:
                    vector.y = -magnitude;
                    break;
                case DFBlock.RdbActionAxes.NegativeZ:
                    vector.z = magnitude;
                    break;

                case DFBlock.RdbActionAxes.PositiveX:
                    vector.x = -magnitude;
                    break;
                case DFBlock.RdbActionAxes.PositiveY:
                    vector.y = magnitude;
                    break;
                case DFBlock.RdbActionAxes.PositiveZ:
                    vector.z = -magnitude;
                    break;
                default:
                    magnitude = 0f;
                    break;
            }
            action.ActionTranslation = vector * MeshReader.GlobalScale;
        }
예제 #21
0
        /// <summary>
        /// Adds action door to scene.
        /// </summary>
        private static GameObject AddActionDoor(DaggerfallUnity dfUnity, uint modelId, DFBlock.RdbObject obj, Transform parent, long loadID = 0)
        {
            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);

            // Get action door script
            DaggerfallActionDoor actionDoor = go.GetComponent<DaggerfallActionDoor>();

            // Set starting lock value
            if (obj.Resources.ModelResource.TriggerFlag_StartingLock >= 16)
            {
                actionDoor.StartingLockValue = (int)obj.Resources.ModelResource.TriggerFlag_StartingLock;
            }

            // Set LoadID
            actionDoor.LoadID = loadID;

            return go;
        }
예제 #22
0
        /// <summary>
        /// Add fixed enemies.
        /// </summary>
        /// <param name="go">GameObject to add monsters to.</param>
        /// <param name="editorObjects">Editor objects containing flats.</param>
        /// <param name="serialize">Allow for serialization when available.</param>
        public static void AddFixedEnemies(
            GameObject go,
            DFBlock.RdbObject[] editorObjects,
            ref DFBlock blockData,
            bool serialize = true)
        {
            const int fixedMonsterFlatIndex = 16;

            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

            // Must have import enabled and prefab set
            if (!dfUnity.Option_ImportEnemyPrefabs || dfUnity.Option_EnemyPrefab == null)
                return;

            // Editor objects array must be populated
            if (editorObjects == null || editorObjects.Length == 0)
                return;

            // Add parent node
            GameObject fixedEnemiesNode = new GameObject("Fixed Enemies");
            fixedEnemiesNode.transform.parent = go.transform;

            // Iterate editor flats for enemies
            for (int i = 0; i < editorObjects.Length; i++)
            {
                // Add fixed enemy objects
                if (editorObjects[i].Resources.FlatResource.TextureRecord == fixedMonsterFlatIndex)
                    AddFixedRDBEnemy(editorObjects[i], fixedEnemiesNode.transform, ref blockData, serialize);
            }
        }
예제 #23
0
        private static void AddActionModelHelper(
            GameObject go,
            Dictionary<int, ActionLink> actionLinkDict,
            DFBlock.RdbObject rdbObj,
            ref DFBlock blockData,
            bool serialize)
        {
            DFBlock.RdbModelResource obj = rdbObj.Resources.ModelResource;
            string description = blockData.RdbBlock.ModelReferenceList[obj.ModelIndex].Description;
            int soundID_Index = obj.SoundIndex;
            float duration = obj.ActionResource.Duration;
            float magnitude = obj.ActionResource.Magnitude;
            int axis = obj.ActionResource.Axis;
            DFBlock.RdbTriggerFlags triggerFlag = DFBlock.RdbTriggerFlags.None;
            DFBlock.RdbActionFlags actionFlag = DFBlock.RdbActionFlags.None;

            if (actionLinkDict != null)
            {
                // Set action flag if valid / known
                if (Enum.IsDefined(typeof(DFBlock.RdbActionFlags), (DFBlock.RdbActionFlags)obj.ActionResource.Flags))
                    actionFlag = (DFBlock.RdbActionFlags)obj.ActionResource.Flags;

                // Set trigger flag if valid / known
                if (Enum.IsDefined(typeof(DFBlock.RdbTriggerFlags), (DFBlock.RdbTriggerFlags)obj.TriggerFlag_StartingLock))
                    triggerFlag = (DFBlock.RdbTriggerFlags)obj.TriggerFlag_StartingLock;

                // Add action node to actionLink dictionary
                if (!actionLinkDict.ContainsKey(rdbObj.This))
                {
                    ActionLink link;
                    link.nextKey = obj.ActionResource.NextObjectOffset;
                    link.prevKey = obj.ActionResource.PreviousObjectOffset;
                    link.gameObject = go;
                    actionLinkDict.Add(rdbObj.This, link);
                }
            }

            // Create unique LoadID for save sytem
            long loadID = 0;
            if (serialize)
                loadID = (blockData.Index << 24) + rdbObj.This;

            AddAction(go, description, soundID_Index, duration, magnitude, axis, triggerFlag, actionFlag, loadID);
        }
예제 #24
0
 /// <summary>
 /// Check is model has action record.
 /// </summary>
 private static bool HasAction(DFBlock.RdbObject obj)
 {
     DFBlock.RdbActionResource action = obj.Resources.ModelResource.ActionResource;
     if (action.Flags != 0)
         return true;
     return false;
 }
예제 #25
0
        private static void AddFixedRDBEnemy(DFBlock.RdbObject obj, Transform parent, ref DFBlock blockData, bool serialize)
        {
            // Get type value and ignore known invalid types
            int typeValue = (int)(obj.Resources.FlatResource.FactionMobileId & 0xff);
            if (typeValue == 99)
                return;

            // Create unique LoadID for save sytem
            long loadID = 0;
            if (serialize)
                loadID = (blockData.Index << 24) + obj.This;

            // Cast to enum
            MobileTypes type = (MobileTypes)(obj.Resources.FlatResource.FactionMobileId & 0xff);

            AddEnemy(obj, type, parent, loadID);
        }
예제 #26
0
        /// <summary>
        /// Check if model is a hinged action door.
        /// </summary>
        private static bool IsActionDoor(ref DFBlock blockData, DFBlock.RdbObject obj, int modelReference)
        {
            // Always reject red brick doors, they are not action doors despite having "DOR" attached
            if (blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum == redBrickDoorModelID)
                return false;

            // Otherwise Check if this is a door (DOR) or double-door (DDR)
            string description = blockData.RdbBlock.ModelReferenceList[modelReference].Description;
            if (description == "DOR" || description == "DDR")
                return true;

            return false;
        }
예제 #27
0
        private static GameObject AddLight(DaggerfallUnity dfUnity, DFBlock.RdbObject obj, Transform parent)
        {
            // Spawn light gameobject
            float range = obj.Resources.LightResource.Radius * MeshReader.GlobalScale;
            Vector3 position = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
            GameObject go = GameObjectHelper.InstantiatePrefab(dfUnity.Option_DungeonLightPrefab.gameObject, string.Empty, parent, position);
            Light light = go.GetComponent<Light>();
            if (light != null)
            {
                light.range = range * 3;
            }

            return go;
        }
예제 #28
0
        /// <summary>
        /// Add all block flats.
        /// </summary>
        public static void AddFlats(
            GameObject go,
            Dictionary<int, ActionLink> actionLinkDict,
            ref DFBlock blockData,
            out DFBlock.RdbObject[] editorObjectsOut,
            out GameObject[] startMarkersOut,
            out GameObject[] enterMarkersOut)
        {
            List<DFBlock.RdbObject> editorObjects = new List<DFBlock.RdbObject>();
            List<GameObject> startMarkers = new List<GameObject>();
            List<GameObject> enterMarkers = new List<GameObject>();
            editorObjectsOut = null;
            startMarkersOut = null;
            enterMarkersOut = null;

            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

            // Add parent node
            GameObject flatsNode = new GameObject("Flats");
            flatsNode.transform.parent = go.transform;

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

                // Look for flats in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    if (obj.Type == DFBlock.RdbResourceTypes.Flat)
                    {
                        // Add flat
                        GameObject flatObject = AddFlat(obj, flatsNode.transform);

                        // Store editor objects and start markers
                        int archive = obj.Resources.FlatResource.TextureArchive;
                        int record = obj.Resources.FlatResource.TextureRecord;
                        if (archive == TextureReader.EditorFlatsTextureArchive)
                        {
                            editorObjects.Add(obj);
                            if (record == 10)
                                startMarkers.Add(flatObject);
                            else if (record == 8)
                                enterMarkers.Add(flatObject);

                            //add editor flats to actionLinkDict
                            if (!actionLinkDict.ContainsKey(obj.This))
                            {
                                ActionLink link;
                                link.gameObject = flatObject;
                                link.nextKey = obj.Resources.FlatResource.NextObjectOffset;
                                link.prevKey = -1;
                                actionLinkDict.Add(obj.This, link);
                            }

                        }

                        //add action component to flat if it has an action
                        if (obj.Resources.FlatResource.Action > 0)
                        {
                            AddActionFlatHelper(flatObject, actionLinkDict, ref blockData, obj);
                        }

                    }
                }
            }

            // Output editor objects
            editorObjectsOut = editorObjects.ToArray();
            startMarkersOut = startMarkers.ToArray();
            enterMarkersOut = enterMarkers.ToArray();
        }
예제 #29
0
        private static void AddRandomRDBEnemy(
            DFBlock.RdbObject obj,
            DFRegion.DungeonTypes dungeonType,
            float monsterPower,
            int monsterVariance,
            Transform parent,
            ref DFBlock blockData,
            bool serialize)
        {
            // Must have a dungeon type
            if (dungeonType == DFRegion.DungeonTypes.NoDungeon)
                return;

            // Get dungeon type index
            int dungeonIndex = (int)dungeonType >> 8;
            if (dungeonIndex < RandomEncounters.EncounterTables.Length)
            {
                // Get encounter table
                RandomEncounterTable table = RandomEncounters.EncounterTables[dungeonIndex];

                // Get base monster index into table
                int baseMonsterIndex = (int)((float)table.Enemies.Length * monsterPower);

                // Set min index
                int minMonsterIndex = baseMonsterIndex - monsterVariance;
                if (minMonsterIndex < 0)
                    minMonsterIndex = 0;

                // Set max index
                int maxMonsterIndex = baseMonsterIndex + monsterVariance;
                if (maxMonsterIndex >= table.Enemies.Length)
                    maxMonsterIndex = table.Enemies.Length;

                // Get random monster from table
                MobileTypes type = table.Enemies[UnityEngine.Random.Range(minMonsterIndex, maxMonsterIndex)];

                // Create unique LoadID for save sytem
                long loadID = 0;
                if (serialize)
                    loadID = (blockData.Index << 24) + obj.This;

                // Add enemy
                AddEnemy(obj, type, parent, loadID);
            }
            else
            {
                DaggerfallUnity.LogMessage(string.Format("RDBLayout: Dungeon type {0} is out of range or unknown.", dungeonType), true);
            }
        }
예제 #30
0
        /// <summary>
        /// Add light prefabs.
        /// </summary>
        public static void AddLights(GameObject go, ref DFBlock blockData)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return;

            // Do nothing if import option not enabled or missing prefab
            if (!dfUnity.Option_ImportLightPrefabs || dfUnity.Option_DungeonLightPrefab == null)
                return;

            // Add parent node
            GameObject lightsNode = new GameObject("Lights");
            lightsNode.transform.parent = go.transform;

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

                // Look for lights in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    if (obj.Type == DFBlock.RdbResourceTypes.Light)
                        AddLight(dfUnity, obj, lightsNode.transform);
                }
            }
        }