Example #1
0
        /// <summary>
        /// Seek and import a GameObject from mods to replace a Daggerfall billboard.
        /// </summary>
        /// <param name="archive">Texture archive for original billboard.</param>
        /// <param name="record">Texture record for original billboard.</param>
        /// <param name="position">Position to assign to GameObject.</param>
        /// <param name="parent">Parent to assign to GameObject.</param>
        /// <param name="inDungeon">Fix position for dungeon models.</param>
        /// <returns>Returns the imported model or null if not found.</returns>
        public static GameObject ImportCustomFlatGameobject(int archive, int record, Vector3 position, Transform parent, bool inDungeon = false)
        {
            GameObject go;

            if (!TryImportGameObject(archive, record, true, out go))
            {
                return(null);
            }

            go.name             = GetFlatReplacementName(archive, record);
            go.transform.parent = parent;

            // Assign position
            AlignToBase(go.transform, position, archive, record, inDungeon);

            // Assign a random rotation
            var iObjectPositioner = go.GetComponent <IObjectPositioner>();

            if (iObjectPositioner == null || iObjectPositioner.AllowFlatRotation)
            {
                Random.InitState((int)position.x);
                go.transform.Rotate(0, Random.Range(0f, 360f), 0);
            }

            // Add NPC trigger collider
            if (RDBLayout.IsNPCFlat(archive))
            {
                Collider col = go.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }

            // Finalise gameobject materials
            FinaliseMaterials(go);
            return(go);
        }
        /// <summary>
        /// Seek and import a GameObject from mods to replace a Daggerfall billboard.
        /// </summary>
        /// <param name="archive">Texture archive for original billboard.</param>
        /// <param name="record">Texture record for original billboard.</param>
        /// <param name="position">Position to assign to GameObject.</param>
        /// <param name="parent">Parent to assign to GameObject.</param>
        /// <param name="inDungeon">Fix position for dungeon models.</param>
        /// <returns>Returns the imported model or null if not found.</returns>
        public static GameObject ImportCustomFlatGameobject(int archive, int record, Vector3 position, Transform parent, bool inDungeon = false)
        {
            GameObject go;

            if (!TryImportGameObject(archive, record, true, out go))
            {
                return(null);
            }

            go.name             = string.Format("DaggerfallBillboard [Replacement] [TEXTURE.{0:000}, Index={1}]", archive, record);
            go.transform.parent = parent;

            // Assign position
            AlignToBase(go.transform, position, archive, record, inDungeon);

            // Assign a random rotation
            if (go.GetComponent <FaceWall>() == null)
            {
                Random.InitState((int)position.x);
                go.transform.Rotate(0, Random.Range(0f, 360f), 0);
            }

            // Add NPC trigger collider
            if (RDBLayout.IsNPCFlat(archive))
            {
                Collider col = go.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }

            // Finalise gameobject materials
            FinaliseMaterials(go);
            return(go);
        }
        private void LayoutDungeon(ref DFLocation location, bool importEnemies = true)
        {
#if SHOW_LAYOUT_TIMES
            // Start timing
            System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
            long startTime = stopwatch.ElapsedMilliseconds;
#endif

            // Get player level - use level 1 if game not running (e.g. importing in editor mode)
            float playerLevel = 1;
            if (Application.isPlaying)
            {
                playerLevel = GameManager.Instance.PlayerEntity.Level;
            }

            // Calculate monster power - this is a clamped 0-1 value based on player's level from 1-20
            float monsterPower = Mathf.Clamp01(playerLevel / 20f);

            // Create dungeon layout
            for (int i = 0; i < summary.LocationData.Dungeon.Blocks.Length; i++)
            {
                DFLocation.DungeonBlock block = summary.LocationData.Dungeon.Blocks[i];
                GameObject go = GameObjectHelper.CreateRDBBlockGameObject(
                    block.BlockName,
                    DungeonTextureTable,
                    block.IsStartingBlock,
                    Summary.DungeonType,
                    monsterPower,
                    RandomMonsterVariance,
                    (int)DateTime.Now.Ticks /*Summary.ID*/,      // TODO: Add more options for seed
                    dfUnity.Option_DungeonBlockPrefab,
                    importEnemies);
                go.transform.parent   = this.transform;
                go.transform.position = new Vector3(block.X * RDBLayout.RDBSide, 0, block.Z * RDBLayout.RDBSide);

                DaggerfallRDBBlock daggerfallBlock = go.GetComponent <DaggerfallRDBBlock>();
                if (block.IsStartingBlock)
                {
                    FindMarkers(daggerfallBlock, ref block, true); // Assign start marker and enter marker
                }
                else
                {
                    FindMarkers(daggerfallBlock, ref block, false); // Only find water level and palaceblock info from start marker
                }
                summary.LocationData.Dungeon.Blocks[i].WaterLevel  = block.WaterLevel;
                summary.LocationData.Dungeon.Blocks[i].CastleBlock = block.CastleBlock;

                // Add water blocks
                RDBLayout.AddWater(go, go.transform.position, block.WaterLevel);
            }

            RemoveOverlappingDoors();

#if SHOW_LAYOUT_TIMES
            // Show timer
            long totalTime = stopwatch.ElapsedMilliseconds - startTime;
            DaggerfallUnity.LogMessage(string.Format("Time to layout dungeon: {0}ms", totalTime), true);
#endif
        }
Example #4
0
        /// <summary>
        /// Import a GameObject from mods instead of billboard.
        /// </summary>
        /// <param name="inDungeon">Fix position for dungeon models.</param>
        /// <returns>Returns the imported model or null.</returns>
        public static GameObject ImportCustomFlatGameobject(int archive, int record, Vector3 position, Transform parent, bool inDungeon = false)
        {
            // Check user settings
            if (!DaggerfallUnity.Settings.MeshAndTextureReplacement)
            {
                return(null);
            }

            // Get GameObject
            GameObject prefab;
            string     name = archive.ToString("D3") + "_" + record.ToString();

            if (!LoadGameObjectFromMods("Flats", name, out prefab))
            {
                return(null);
            }

            // Instantiate GameObject
            GameObject go = GameObject.Instantiate(prefab, parent);

            go.name = string.Format("DaggerfallBillboard [Replacement] [TEXTURE.{0:000}, Index={1}]", archive, record);

            // Assign position
            if (inDungeon)
            {
                // Fix origin position for dungeon flats
                int height = ImageReader.GetImageData("TEXTURE." + archive.ToString("D3"), record, createTexture: false).height;
                position.y -= height / 2 * MeshReader.GlobalScale;
            }
            go.transform.localPosition = position;

            // Assign a random rotation
            if (go.GetComponent <FaceWall>() == null)
            {
                Random.InitState((int)position.x);
                go.transform.Rotate(0, Random.Range(0f, 360f), 0);
            }

            // Add NPC trigger collider
            if (RDBLayout.IsNPCFlat(archive))
            {
                Collider col = go.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }

            // Finalise gameobject materials
            FinaliseMaterials(go);
            return(go);
        }
        // Orsinium defines two blocks at [-1,-1]
        private void LayoutOrsinium(ref DFLocation location, bool importEnemies = true)
        {
            // Calculate monster power - this is a clamped 0-1 value based on player's level from 1-20
            float monsterPower = Mathf.Clamp01(GameManager.Instance.PlayerEntity.Level / 20f);

            // Create dungeon layout and handle misplaced block
            for (int i = 0; i < summary.LocationData.Dungeon.Blocks.Length; i++)
            {
                DFLocation.DungeonBlock block = summary.LocationData.Dungeon.Blocks[i];
                if (block.X == -1 && block.Z == -1 && block.BlockName == "N0000065.RDB")
                {
                    continue;
                }

                GameObject go = GameObjectHelper.CreateRDBBlockGameObject(
                    block.BlockName,
                    DungeonTextureTable,
                    block.IsStartingBlock,
                    Summary.DungeonType,
                    monsterPower,
                    RandomMonsterVariance,
                    (int)DateTime.Now.Ticks /*Summary.ID*/,      // TODO: Add more options for seed
                    dfUnity.Option_DungeonBlockPrefab,
                    importEnemies);
                go.transform.parent   = this.transform;
                go.transform.position = new Vector3(block.X * RDBLayout.RDBSide, 0, block.Z * RDBLayout.RDBSide);

                DaggerfallRDBBlock daggerfallBlock = go.GetComponent <DaggerfallRDBBlock>();
                if (block.IsStartingBlock)
                {
                    FindMarkers(daggerfallBlock, ref block, true); // Assign start marker and enter marker
                }
                else
                {
                    FindMarkers(daggerfallBlock, ref block, false); // Only find water level and castle block info from start marker
                }
                summary.LocationData.Dungeon.Blocks[i].WaterLevel  = block.WaterLevel;
                summary.LocationData.Dungeon.Blocks[i].CastleBlock = block.CastleBlock;

                // Add water blocks
                RDBLayout.AddWater(go, go.transform.position, block.WaterLevel);
            }

            RemoveOverlappingDoors();
        }
Example #6
0
        // Orsinium defines two blocks at [-1,-1]
        private void LayoutOrsinium(ref DFLocation location)
        {
            // Create dungeon layout and handle misplaced block
            foreach (var block in location.Dungeon.Blocks)
            {
                if (block.X == -1 && block.Z == -1 && block.BlockName == "N0000065.RDB")
                {
                    continue;
                }

                GameObject go = RDBLayout.CreateGameObject(block.BlockName, block.IsStartingBlock, DungeonTextureTable, Summary.DungeonType, Summary.ID);
                go.transform.parent   = this.transform;
                go.transform.position = new Vector3(block.X * RDBLayout.RDBSide, 0, block.Z * RDBLayout.RDBSide);

                DaggerfallRDBBlock daggerfallBlock = go.GetComponent <DaggerfallRDBBlock>();
                if (block.IsStartingBlock)
                {
                    FindStartMarker(daggerfallBlock);
                }
            }
        }
        /// <summary>
        /// Seek and import a GameObject from mods to replace a Daggerfall billboard.
        /// </summary>
        /// <param name="archive">Texture archive for original billboard.</param>
        /// <param name="record">Texture record for original billboard.</param>
        /// <param name="position">Position to assign to GameObject.</param>
        /// <param name="parent">Parent to assign to GameObject.</param>
        /// <param name="inDungeon">Fix position for dungeon models.</param>
        /// <returns>Returns the imported model or null if not found.</returns>
        public static GameObject ImportCustomFlatGameobject(int archive, int record, Vector3 position, Transform parent, bool inDungeon = false)
        {
            GameObject go;

            if (!TryImportGameObject(archive, record, true, out go))
            {
                return(null);
            }

            go.name             = string.Format("DaggerfallBillboard [Replacement] [TEXTURE.{0:000}, Index={1}]", archive, record);
            go.transform.parent = parent;

            // Assign position
            if (inDungeon)
            {
                // Fix origin position for dungeon flats
                int height = ImageReader.GetImageData(TextureFile.IndexToFileName(archive), record, createTexture: false).height;
                position.y -= height / 2 * MeshReader.GlobalScale;
            }
            go.transform.localPosition = position;

            // Assign a random rotation
            if (go.GetComponent <FaceWall>() == null)
            {
                Random.InitState((int)position.x);
                go.transform.Rotate(0, Random.Range(0f, 360f), 0);
            }

            // Add NPC trigger collider
            if (RDBLayout.IsNPCFlat(archive))
            {
                Collider col = go.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }

            // Finalise gameobject materials
            FinaliseMaterials(go);
            return(go);
        }
        /// <summary>
        /// Assign parent, position, rotation and texture filtermode.
        /// </summary>
        static private void InstantiateCustomFlat(GameObject go, ref Vector3 position, Transform parent, int archive, int record, bool inDungeon)
        {
            // Fix origin position for dungeon flats
            if (inDungeon)
            {
                // Get height
                int height = ImageReader.GetImageData("TEXTURE." + archive.ToString("D3"), record, createTexture: false).height;

                // Correct transform
                position.y -= height / 2 * MeshReader.GlobalScale;
            }

            // Assign transform properties
            go.transform.parent        = parent;
            go.transform.localPosition = position;

            // Assign a random rotation so that flats in group won't look all aligned.
            // We use a seed becuse we want the models to have the same
            // rotation every time the same location is loaded.
            if (go.GetComponent <FaceWall>() == null)
            {
                UnityEngine.Random.InitState((int)position.x);
                go.transform.Rotate(0, UnityEngine.Random.Range(0f, 360f), 0);
            }

            // Assign name
            go.name = string.Format("DaggerfallBillboard [Replacement] [TEXTURE.{0:000}, Index={1}]", archive, record);

            // Finalise gameobject material
            FinaliseMaterials(go);

            // Add NPC trigger collider
            if (RDBLayout.IsNPCFlat(archive))
            {
                Collider col = go.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }
        }
Example #9
0
        private void LayoutDungeon(ref DFLocation location)
        {
            //// Start timing
            //Stopwatch stopwatch = Stopwatch.StartNew();
            //long startTime = stopwatch.ElapsedMilliseconds;

            // Create dungeon layout
            foreach (var block in location.Dungeon.Blocks)
            {
                GameObject go = RDBLayout.CreateGameObject(block.BlockName, block.IsStartingBlock, DungeonTextureTable, Summary.DungeonType, Summary.ID);
                go.transform.parent   = this.transform;
                go.transform.position = new Vector3(block.X * RDBLayout.RDBSide, 0, block.Z * RDBLayout.RDBSide);

                DaggerfallRDBBlock daggerfallBlock = go.GetComponent <DaggerfallRDBBlock>();
                if (block.IsStartingBlock)
                {
                    FindStartMarker(daggerfallBlock);
                }
            }

            //// Show timer
            //long totalTime = stopwatch.ElapsedMilliseconds - startTime;
            //DaggerfallUnity.LogMessage(string.Format("Time to layout dungeon: {0}ms", totalTime), true);
        }
Example #10
0
        /// <summary>
        /// Sets new Daggerfall material and recreates mesh.
        /// Will use an atlas if specified in DaggerfallUnity singleton.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="archive">Texture archive index.</param>
        /// <param name="record">Texture record index.</param>
        /// <param name="frame">Frame index.</param>
        /// <returns>Material.</returns>
        public Material SetMaterial(int archive, int record, int frame = 0)
        {
            // Get DaggerfallUnity
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

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

            // Get references
            meshRenderer = GetComponent <MeshRenderer>();

            Vector2  size;
            Vector2  scale;
            Mesh     mesh     = null;
            Material material = null;

            if (material = TextureReplacement.GetStaticBillboardMaterial(gameObject, archive, record, ref summary, out scale))
            {
                mesh  = dfUnity.MeshReader.GetBillboardMesh(summary.Rect, archive, record, out size);
                size *= scale;
                summary.AtlasedMaterial  = false;
                summary.AnimatedMaterial = summary.ImportedTextures.FrameCount > 1;
            }
            else if (dfUnity.MaterialReader.AtlasTextures)
            {
                material = dfUnity.MaterialReader.GetMaterialAtlas(
                    archive,
                    0,
                    4,
                    2048,
                    out summary.AtlasRects,
                    out summary.AtlasIndices,
                    4,
                    true,
                    0,
                    false,
                    true);
                mesh = dfUnity.MeshReader.GetBillboardMesh(
                    summary.AtlasRects[summary.AtlasIndices[record].startIndex],
                    archive,
                    record,
                    out size);
                summary.AtlasedMaterial = true;
                if (summary.AtlasIndices[record].frameCount > 1)
                {
                    summary.AnimatedMaterial = true;
                }
                else
                {
                    summary.AnimatedMaterial = false;
                }
            }
            else
            {
                material = dfUnity.MaterialReader.GetMaterial(
                    archive,
                    record,
                    frame,
                    0,
                    out summary.Rect,
                    4,
                    true,
                    true);
                mesh = dfUnity.MeshReader.GetBillboardMesh(
                    summary.Rect,
                    archive,
                    record,
                    out size);
                summary.AtlasedMaterial  = false;
                summary.AnimatedMaterial = false;
            }

            // Set summary
            summary.FlatType = MaterialReader.GetFlatType(archive);
            summary.Archive  = archive;
            summary.Record   = record;
            summary.Size     = size;

            // Set editor flat types
            if (summary.FlatType == FlatTypes.Editor)
            {
                summary.EditorFlatType = MaterialReader.GetEditorFlatType(summary.Record);
            }

            // Set NPC flat type based on archive
            if (RDBLayout.IsNPCFlat(summary.Archive))
            {
                summary.FlatType = FlatTypes.NPC;
            }

            // Assign mesh and material
            MeshFilter meshFilter = GetComponent <MeshFilter>();
            Mesh       oldMesh    = meshFilter.sharedMesh;

            if (mesh)
            {
                meshFilter.sharedMesh       = mesh;
                meshRenderer.sharedMaterial = material;
            }
            if (oldMesh)
            {
                // The old mesh is no longer required
#if UNITY_EDITOR
                DestroyImmediate(oldMesh);
#else
                Destroy(oldMesh);
#endif
            }

            // General billboard shadows if enabled
            bool isLightArchive = (archive == TextureReader.LightsTextureArchive);
            meshRenderer.shadowCastingMode = (DaggerfallUnity.Settings.GeneralBillboardShadows && !isLightArchive) ? ShadowCastingMode.TwoSided : ShadowCastingMode.Off;

            // Add NPC trigger collider
            if (summary.FlatType == FlatTypes.NPC)
            {
                Collider col = gameObject.AddComponent <BoxCollider>();
                col.isTrigger = true;
            }

            return(material);
        }
        public void CreateDungeonBlock()
        {
            DungeonGenerator myGen = GetComponent <DungeonRecord>().MyGenerator;

            Debug.LogWarning("Creating dungeon block: " + blockIndex + " isStarting block: " + isStartBlock);
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                Debug.LogError("CreateDungeonBlock found dfUnity not ready; stopping");
                return;
            }

            // Create base object
            DFBlock blockData = dfUnity.ContentReader.BlockFileReader.GetBlock(blockIndex);

            if (blockData.Type != DFBlock.BlockTypes.Rdb)
            {
                Debug.LogError(string.Format("Invalid block index : {0} | block name: {1} | block type: {2}, returning", blockIndex, blockData.Name, blockData.Type));
                return;
            }

            GameObject go = RDBLayout.CreateBaseGameObject(blockData.Name, actLink, textureTable, true, cloneFrom);

            // Add exit doors
            if (isStartBlock)
            {
                StaticDoor[] doorsOut;
                RDBLayout.AddActionDoors(go, actLink, ref blockData, textureTable);
            }

            // Add action doors
            RDBLayout.AddActionDoors(go, actLink, ref blockData, textureTable);

            // Add lights
            RDBLayout.AddLights(go, ref blockData);

            // Add flats
            DFBlock.RdbObject[] editorObjectsOut = new DFBlock.RdbObject[0];
            GameObject[]        startMarkersOut  = null;
            GameObject[]        enterMarkersOut  = null;

            if (myGen.GenerateTreasure)
            {
                RDBLayout.AddFlats(go, actLink, ref blockData, out editorObjectsOut, out startMarkersOut, out enterMarkersOut, dungeonType);
            }

            // Set start markers
            DaggerfallRDBBlock dfBlock = (cloneFrom != null) ? cloneFrom : go.GetComponent <DaggerfallRDBBlock>();

            if (dfBlock != null)
            {
                dfBlock.SetMarkers(startMarkersOut, enterMarkersOut);
            }

            // Add enemies
            if (myGen.GenerateEnemies)
            {
                RDBLayout.AddRandomEnemies(go, editorObjectsOut, dungeonType, 0.5f, ref blockData, startMarkersOut);
            }

            go.transform.SetParent(this.transform);
            go.transform.localPosition = new Vector3(position.x, 0, position.y);
        }