コード例 #1
0
        /// <summary>
        /// Get a new Material based on climate.
        /// </summary>
        /// <param name="key">Material key.</param>
        /// <param name="climate">New climate base.</param>
        /// <param name="season">New season.</param>
        /// <param name="windowStyle">New window style.</param>
        /// <returns>New material.</returns>
        public Material ChangeClimate(int key, ClimateBases climate, ClimateSeason season, WindowStyle windowStyle)
        {
            // Ready check
            if (!IsReady)
            {
                return(null);
            }

            // Reverse key and apply climate
            int archive, record, frame;

            ReverseTextureKey(key, out archive, out record, out frame);
            archive = ClimateSwaps.ApplyClimate(archive, record, climate, season);

            // Get new material
            Material       material;
            CachedMaterial cm = GetMaterialFromCache(archive, record, out material);

            // Handle windows
            if (cm.isWindow)
            {
                ChangeWindowEmissionColor(material, windowStyle);
            }

            return(material);
        }
コード例 #2
0
        public void SetLocation(DFLocation location, bool performLayout = true)
        {
            if (!ReadyCheck())
            {
                return;
            }

            // Validate
            if (this.isSet)
            {
                throw new Exception("This location has already been set.");
            }
            if (!location.Loaded)
            {
                throw new Exception("DFLocation not loaded.");
            }

            // Set summary
            summary           = new LocationSummary();
            summary.MapID     = location.MapTableData.MapId;
            summary.Longitude = (int)location.MapTableData.Longitude;
            summary.Latitude  = (int)location.MapTableData.Latitude;
            DFPosition mapPixel   = MapsFile.LongitudeLatitudeToMapPixel(summary.Longitude, summary.Latitude);
            DFPosition worldCoord = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y);

            summary.MapPixelX      = mapPixel.X;
            summary.MapPixelY      = mapPixel.Y;
            summary.WorldCoordX    = worldCoord.X;
            summary.WorldCoordZ    = worldCoord.Y;
            summary.RegionName     = location.RegionName;
            summary.LocationName   = location.Name;
            summary.WorldClimate   = (MapsFile.Climates)location.Climate.WorldClimate;
            summary.LocationType   = location.MapTableData.LocationType;
            summary.DungeonType    = location.MapTableData.DungeonType;
            summary.HasDungeon     = location.HasDungeon;
            summary.Climate        = ClimateSwaps.FromAPIClimateBase(location.Climate.ClimateType);
            summary.Nature         = ClimateSwaps.FromAPITextureSet(location.Climate.NatureSet);
            summary.SkyBase        = location.Climate.SkyBase;
            summary.BlockWidth     = location.Exterior.ExteriorData.Width;
            summary.BlockHeight    = location.Exterior.ExteriorData.Height;
            summary.LegacyLocation = location;

            // Assign starting climate
            CurrentSeason    = ClimateSeason.Summer;
            CurrentClimate   = summary.Climate;
            CurrentNatureSet = summary.Nature;

            // Perform layout
            if (performLayout)
            {
                LayoutLocation(ref location);
                ApplyClimateSettings();
            }

            // Set location rect
            SetLocationRect();

            // Seal location
            isSet = true;
        }
コード例 #3
0
        /// <summary>
        /// Get model name for current climate and season.
        /// </summary>
        private static string ClimateSeasonName(string modelName)
        {
            if (!GameManager.HasInstance)
            {
                return(modelName);
            }

            // Get climate
            ClimateBases climateBase = ClimateSwaps.FromAPIClimateBase(GameManager.Instance.PlayerGPS.ClimateSettings.ClimateType);
            string       name        = modelName + "_" + climateBase.ToString();

            // Get season
            if (climateBase != ClimateBases.Desert)
            {
                if (DaggerfallUnity.Instance.WorldTime.Now.SeasonValue == DaggerfallDateTime.Seasons.Winter)
                {
                    name += "Winter";
                }
                else
                {
                    name += "Summer";
                }
            }

            return(name);
        }
コード例 #4
0
        /// <summary>
        /// Layout interior for automap 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 DoLayoutAutomap(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(mapBD);

            return(true);
        }
コード例 #5
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, PlayerGPS.DiscoveredBuilding buildingData)
        {
            if (dfUnity == null)
            {
                dfUnity = DaggerfallUnity.Instance;
            }

            // Use specified climate
            this.climateBase = climateBase;

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

            AssignBlockData(door);

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

            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Rebuild materials back to default with no climate modifier.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="climate">Climate to set.</param>
        /// <param name="season">Season to set.</param>
        /// <param name="windowStyle">Style of window to set.</param>
        public void SetClimate(ClimateBases climate, ClimateSeason season, WindowStyle windowStyle)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (defaultTextures.Count == 0)
            {
                return;
            }

            // Get new material array
            Material[] materials = new Material[defaultTextures.Count];
            for (int i = 0; i < defaultTextures.Count; i++)
            {
                materials[i] = dfUnity.MaterialReader.ChangeClimate(defaultTextures[i], climate, season, windowStyle);
            }

            // Assign material array
            if (materials != null)
            {
                GetComponent <MeshRenderer>().sharedMaterials = materials;
            }

            // Store climate settings
            currentClimate     = climate;
            currentSeason      = season;
            currentWindowStyle = windowStyle;
        }
コード例 #7
0
        /// <summary>
        /// Set ground climate.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="climate">Climate to set.</param>
        /// <param name="season">Season to set.</param>
        public void SetClimate(DaggerfallUnity dfUnity, ClimateBases climate, ClimateSeason season)
        {
            int archive = ClimateSwaps.GetGroundArchive(climate, season);

            SetClimate(dfUnity, archive, season);
            summary.climate = climate;
        }
コード例 #8
0
        /// <summary>
        /// Load assets for Winter.
        /// </summary>
        public void UpdateClimateWinter(ClimateBases currentClimate)
        {
            bool drawGrass = IsGrassTransitioning();

            if (drawGrass)
            {
                SetGrassColor();
                SetGrassSize();
            }

            if (!NeedsUpdate(UpdateType.Winter, currentClimate))
            {
                return;
            }

            switch (currentClimate)
            {
            case ClimateBases.Mountain:
                if (drawGrass)
                {
                    SetGrass(brownGrass, brownGrassRealistic);
                }

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsMountainWinter);
                }
                break;

            case ClimateBases.Swamp:
                if (drawGrass)
                {
                    SetGrass(brownGrass, brownGrassRealistic);
                }

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsSwampWinter);
                }
                break;

            case ClimateBases.Temperate:
                if (drawGrass)
                {
                    SetGrass(greenGrass, greenGrassRealistic);
                }

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsTemperateWinter);
                }
                break;

            default:
                Debug.LogError(string.Format("RealGrass: {0} is not a valid climate (Winter)", currentClimate));
                RealGrass.Instance.ToggleMod(false);
                break;
            }
        }
コード例 #9
0
        /// <summary>
        /// Load assets for Summer.
        /// </summary>
        public void UpdateClimateSummer(ClimateBases currentClimate)
        {
            RefreshGrassDetails();
            sizeColor.Refresh(currentGrassDetail, currentGrassAccent);

            if ((options.GrassStyle & GrassStyle.Mixed) == GrassStyle.Mixed)
            {
                SetGrassDetail(GrassDetails, grassDetails[currentGrassDetail], ref grassDetailPrefab);
                SetGrassDetail(GrassAccents, grassAccents[currentGrassAccent], ref grassAccentPrefab);
            }

            if (!NeedsUpdate(UpdateType.Summer, currentClimate))
            {
                return;
            }

            ResetColor(DetailPrototypes[WaterPlants]);
            switch (currentClimate)
            {
            case ClimateBases.Mountain:
                SetGrass(brownGrass, realisticGrass);
                if (options.WaterPlants)
                {
                    DetailPrototypes[WaterPlants].healthyColor = new Color(0.66f, 0.88f, 0.20f);
                    DetailPrototypes[WaterPlants].dryColor     = new Color(0.95f, 0.33f, 0.36f);
                    DetailPrototypes[WaterPlants].prototype    = LoadGameObject(plantsMountain);
                }
                break;

            case ClimateBases.Swamp:
                SetGrass(brownGrass, realisticGrass);
                if (options.WaterPlants)
                {
                    DetailPrototypes[WaterPlants].prototype = LoadGameObject(plantsSwamp);
                }
                break;

            case ClimateBases.Temperate:
                SetGrass(greenGrass, realisticGrass);
                if (options.WaterPlants)
                {
                    DetailPrototypes[WaterPlants].prototype = LoadGameObject(plantsTemperate);
                }
                break;

            default:
                throw new ArgumentException("Invalid climate", nameof(currentClimate));
            }

            if (options.TerrainStones)
            {
                DetailPrototypes[Rocks].prototype    = LoadGameObject(rock);
                DetailPrototypes[Rocks].healthyColor = new Color(0.70f, 0.70f, 0.70f);
                DetailPrototypes[Rocks].dryColor     = new Color(0.40f, 0.40f, 0.40f);
            }
        }
コード例 #10
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);
        }
コード例 #11
0
        private Material GetMaterial(RuntimeMaterial runtimeMaterial, ClimateBases climate, ClimateSeason season)
        {
            int archive = runtimeMaterial.Archive;
            int record  = runtimeMaterial.Record;

            if (runtimeMaterial.ApplyClimate)
            {
                archive = ClimateSwaps.ApplyClimate(archive, record, climate, season);
            }

            return(DaggerfallUnity.Instance.MaterialReader.GetMaterial(archive, record));
        }
コード例 #12
0
        /// <summary>
        /// True if season or climate changed and detail prototypes should be updated.
        /// </summary>
        private bool NeedsUpdate(short updateType, ClimateBases climate)
        {
            int key = (updateType << 16) + (short)climate;

            if (key == currentkey)
            {
                return(false);
            }

            currentkey = key;
            return(true);
        }
コード例 #13
0
        private void ApplyMaterials(bool force, int[] dungeonTextureTable = null)
        {
            if (Materials == null || Materials.Length == 0)
            {
                return;
            }

            if (UseDungeonTextureTable && dungeonTextureTable == null)
            {
                return;
            }

            try
            {
                var meshRenderer = GetComponent <MeshRenderer>();
                if (!meshRenderer)
                {
                    Debug.LogErrorFormat("Failed to find MeshRenderer on {0}.", name);
                    return;
                }

                DFLocation.ClimateBaseType climateBaseType = GameManager.Instance.PlayerGPS.ClimateSettings.ClimateType;
                ClimateBases  climate = ClimateSwaps.FromAPIClimateBase(climateBaseType);
                ClimateSeason season  = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue == DaggerfallDateTime.Seasons.Winter ? ClimateSeason.Winter : ClimateSeason.Summer;

                Material[] materials = meshRenderer.sharedMaterials;
                for (int i = 0; i < Materials.Length; i++)
                {
                    int index = Materials[i].Index;

                    if (!force && materials[index])
                    {
                        Debug.LogWarningFormat("A runtime material is being assigned to {0} (index {1}) but current material is not equal to null." +
                                               " Make sure you are not including unnecessary auto-generated materials.", meshRenderer.name, i);
                    }

                    materials[index] = GetMaterial(Materials[i], climateBaseType, climate, season, dungeonTextureTable);
                    if (!materials[index])
                    {
                        Debug.LogErrorFormat("Failed to find material for {0} (index {1}).", meshRenderer.name, i);
                    }
                }
                meshRenderer.sharedMaterials = materials;
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            finally
            {
                hasAppliedMaterials = true;
            }
        }
コード例 #14
0
        /// <summary>
        /// Load assets for Winter.
        /// </summary>
        public void UpdateClimateWinter(ClimateBases currentClimate)
        {
            bool drawGrass = IsGrassTransitioning();

            if (drawGrass)
            {
                sizeColor.Refresh(currentGrassDetail, currentGrassAccent);
            }

            if (!NeedsUpdate(UpdateType.Winter, currentClimate))
            {
                return;
            }

            switch (currentClimate)
            {
            case ClimateBases.Mountain:
                if (drawGrass)
                {
                    SetGrass(brownGrass, realisticGrass);
                }
                break;

            case ClimateBases.Swamp:
                if (drawGrass)
                {
                    SetGrass(brownGrass, realisticGrass);
                }
                break;

            case ClimateBases.Temperate:
                if (drawGrass)
                {
                    SetGrass(greenGrass, realisticGrass);
                }
                break;

            default:
                throw new ArgumentException("Invalid climate", nameof(currentClimate));
            }

            if (options.TerrainStones)
            {
                DetailPrototypes[Rocks].prototype    = LoadGameObject(rockWinter);
                DetailPrototypes[Rocks].healthyColor = new Color(0.70f, 0.70f, 0.70f);
                DetailPrototypes[Rocks].dryColor     = new Color(0.40f, 0.40f, 0.40f);
            }
        }
コード例 #15
0
ファイル: RMBLayout.cs プロジェクト: my0pic/daggerfall-unity
        /// <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;
        }
コード例 #16
0
        ///<summary>
        /// Get all accepted names for a model ordered by priority.
        ///</summary>
        private static string[] GetName(uint modelID)
        {
            if (!GameManager.HasInstance)
            {
                return new string[] { modelID.ToString() }
            }
            ;

            ClimateBases climateBase = ClimateSwaps.FromAPIClimateBase(GameManager.Instance.PlayerGPS.ClimateSettings.ClimateType);
            string       climateName = climateBase == ClimateBases.Desert ?
                                       string.Format("{0}_{1}", modelID, climateBase):
                                       string.Format("{0}_{1}{2}", modelID, climateBase, DaggerfallUnity.Instance.WorldTime.Now.SeasonValue);

            return(new string[]
            {
                climateName,
                modelID.ToString()
            });
        }
コード例 #17
0
        /// <summary>
        /// Get ground archive based on climate.
        /// </summary>
        /// <param name="climateBase">Climate base.</param>
        /// <param name="climateSeason">Season.</param>
        /// <returns>Ground archive matching climate and season.</returns>
        public static int GetGroundArchive(ClimateBases climateBase, ClimateSeason climateSeason)
        {
            // Apply climate
            int archive;

            switch (climateBase)
            {
            case ClimateBases.Desert:
                archive = 2;
                break;

            case ClimateBases.Mountain:
                archive = 102;
                break;

            case ClimateBases.Temperate:
                archive = 302;
                break;

            case ClimateBases.Swamp:
                archive = 402;
                break;

            default:
                archive = 302;
                break;
            }

            // Modify for season
            switch (climateSeason)
            {
            case ClimateSeason.Winter:
                archive += 1;
                break;

            case ClimateSeason.Rain:
                archive += 2;
                break;
            }

            return(archive);
        }
コード例 #18
0
        /// <summary>
        /// Rebuild materials back to default with no climate modifier.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="climate">Climate to set.</param>
        /// <param name="season">Season to set.</param>
        /// <param name="windowStyle">Style of window to set.</param>
        public void SetClimate(DaggerfallUnity dfUnity, ClimateBases climate, ClimateSeason season, WindowStyle windowStyle)
        {
            if (defaultTextures.Count == 0)
            {
                return;
            }

            // Get new material array
            Material[] materials = new Material[defaultTextures.Count];
            for (int i = 0; i < defaultTextures.Count; i++)
            {
                materials[i] = dfUnity.MaterialReader.ChangeClimate(defaultTextures[i], climate, season, windowStyle);
            }

            // Assign material array
            if (materials != null)
            {
                GetComponent <MeshRenderer>().sharedMaterials = materials;
            }
        }
コード例 #19
0
        /// <summary>
        /// Convert DaggerfallUnity climate base to API equivalent.
        /// </summary>
        /// <param name="climate">ClimateBases.</param>
        /// <returns>DFLocation.ClimateBaseType.</returns>
        public static DFLocation.ClimateBaseType FromUnityClimateBase(ClimateBases climate)
        {
            switch (climate)
            {
            case ClimateBases.Desert:
                return(DFLocation.ClimateBaseType.Desert);

            case ClimateBases.Mountain:
                return(DFLocation.ClimateBaseType.Mountain);

            case ClimateBases.Temperate:
                return(DFLocation.ClimateBaseType.Temperate);

            case ClimateBases.Swamp:
                return(DFLocation.ClimateBaseType.Swamp);

            default:
                return(DFLocation.ClimateBaseType.None);
            }
        }
コード例 #20
0
        /// <summary>
        /// Layout interior for automap 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 DoLayoutAutomap(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;

            AssignBlockData(door);

            // Layout interior data
            AddModels(mapBD);

            return(true);
        }
コード例 #21
0
        private void Display3dModelSelection(int selectedIdx)
        {
            if (goModel)
            {
                Object.Destroy(goModel);
                goModel = null;
            }

            // Position camera and set model id
            uint modelId = 0;

            if (housesForSale == null)
            {
                camera.transform.position = new Vector3(0, 12, DaggerfallBankManager.GetShipCameraDist((ShipType)selectedIdx));
                modelId = DaggerfallBankManager.GetShipModelId((ShipType)selectedIdx);
            }
            else
            {
                camera.transform.position = new Vector3(0, 3, -20);
                BuildingSummary house = housesForSale[selectedIdx];
                modelId = house.ModelID;
            }

            // Inject custom GameObject if available else create standard mesh game object for the model
            goModel = MeshReplacement.ImportCustomGameobject(modelId, goBankPurchase.transform, new Matrix4x4());
            if (goModel == null)
            {
                goModel = GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, goBankPurchase.transform);
            }

            goModel.layer = layer;

            // Apply current climate
            ClimateBases   climateBase = ClimateSwaps.FromAPIClimateBase(GameManager.Instance.PlayerGPS.ClimateSettings.ClimateType);
            ClimateSeason  season      = (DaggerfallUnity.WorldTime.Now.SeasonValue == DaggerfallDateTime.Seasons.Winter) ? ClimateSeason.Winter : ClimateSeason.Summer;
            DaggerfallMesh dfMesh      = goModel.GetComponent <DaggerfallMesh>();

            dfMesh.SetClimate(climateBase, season, WindowStyle.Day);
        }
コード例 #22
0
        /// <summary>
        /// Converts an archive index to new climate and season.
        /// Will return same index if climate or season not supported.
        /// </summary>
        /// <param name="archive">Archive index of starting texture.</param>
        /// <param name="climate">Climate base to apply.</param>
        /// <param name="season">Climate season to apply</param>
        /// <returns>Archive index of new texture.</returns>
        public static int ApplyClimate(int archive, int record, ClimateBases climate, ClimateSeason season)
        {
            // Get climate texture info
            ClimateTextureInfo ci = ClimateSwaps.GetClimateTextureInfo(archive);

            // Ignore non-climate textures
            if (ci.textureSet == DFLocation.ClimateTextureSet.None)
            {
                return(archive);
            }

            // Handle missing Swamp textures
            if (climate == ClimateBases.Swamp)
            {
                switch (ci.textureSet)
                {
                case DFLocation.ClimateTextureSet.Interior_TempleInt:
                case DFLocation.ClimateTextureSet.Interior_MarbleFloors:
                    return(archive);
                }
            }

            // Bypass winter swaps in desert climates entirely
            // There are too many bad swaps, and you never see this variant in game
            if (climate == ClimateBases.Desert)
            {
                ci.supportsWinter = false;
            }

            // Handle swamp climate sets with missing winter textures
            if (climate == ClimateBases.Swamp)
            {
                switch (ci.textureSet)
                {
                case DFLocation.ClimateTextureSet.Exterior_Castle:
                case DFLocation.ClimateTextureSet.Exterior_MagesGuild:
                    ci.supportsWinter = false;
                    break;
                }
            }

            // Handle archives with missing winter textures
            if (archive == 82 && record > 1 ||
                archive == 77)
            {
                ci.supportsWinter = false;
            }

            // Flag to suppress climate index
            // Certain textures have a winter variant but are climate-specific
            bool suppressClimateIndex = false;

            switch (archive)
            {
            case 75:
            case 76:
            case 77:
            case 79:
            case 80:
            case 82:
            case 83:
                suppressClimateIndex = true;
                break;
            }

            // Calculate new index
            int climateIndex = 0;

            if (archive < 500 && !suppressClimateIndex)
            {
                climateIndex = (int)FromUnityClimateBase(climate) + (int)ci.textureSet;
                if (season == ClimateSeason.Winter && ci.supportsWinter)
                {
                    climateIndex += (int)DFLocation.ClimateWeather.Winter;
                }
                else if (season == ClimateSeason.Rain && ci.supportsRain)
                {
                    climateIndex += (int)DFLocation.ClimateWeather.Rain;
                }
            }
            else
            {
                climateIndex = archive;
                if (season == ClimateSeason.Winter && ci.supportsWinter)
                {
                    climateIndex += (int)DFLocation.ClimateWeather.Winter;
                }
            }

            return(climateIndex);
        }
コード例 #23
0
        /// <summary>
        /// Transition player through an exterior door into building interior.
        /// </summary>
        /// <param name="doorOwner">Parent transform owning door array..</param>
        /// <param name="door">Exterior door player clicked on.</param>
        public void TransitionInterior(Transform doorOwner, StaticDoor door, bool doFade = false, bool start = true)
        {
            // Ensure we have component references
            if (!ReferenceComponents())
            {
                return;
            }

            // Copy owner position to door
            // This ensures the door itself is all we need to reposition interior
            // Useful when loading a save and doorOwner is null (as outside world does not exist)
            if (doorOwner)
            {
                door.ownerPosition = doorOwner.position;
                door.ownerRotation = doorOwner.rotation;
            }

            if (!start)
            {
                // Update scene cache from serializable state for exterior->interior transition
                SaveLoadManager.CacheScene(world.SceneName);
                // Explicitly deregister all stateful objects since exterior isn't destroyed
                SaveLoadManager.DeregisterAllSerializableGameObjects(true);
                // Clear all stateful objects from world loose object tracking
                world.ClearStatefulLooseObjects();
            }

            // Raise event
            RaiseOnPreTransitionEvent(TransitionType.ToBuildingInterior, door);

            // Ensure expired rooms are removed
            GameManager.Instance.PlayerEntity.RemoveExpiredRentedRooms();

            // Get climate
            ClimateBases climateBase = ClimateBases.Temperate;

            if (OverrideLocation)
            {
                climateBase = OverrideLocation.Summary.Climate;
            }
            else if (playerGPS)
            {
                climateBase = ClimateSwaps.FromAPIClimateBase(playerGPS.ClimateSettings.ClimateType);
            }

            // Layout interior
            // This needs to be done first so we know where the enter markers are
            GameObject newInterior = new GameObject(DaggerfallInterior.GetSceneName(playerGPS.CurrentLocation, door));

            newInterior.hideFlags = defaultHideFlags;
            interior = newInterior.AddComponent <DaggerfallInterior>();

            // Try to layout interior
            // If we fail for any reason, use that old chestnut "this house has nothing of value"
            try
            {
                interior.DoLayout(doorOwner, door, climateBase, buildingDiscoveryData);
            }
            catch
            {
                DaggerfallUI.AddHUDText(HardStrings.thisHouseHasNothingOfValue);
                Destroy(newInterior);
                return;
            }

            // Position interior directly inside of exterior
            // This helps with finding closest enter/exit point relative to player position
            interior.transform.position = door.ownerPosition + (Vector3)door.buildingMatrix.GetColumn(3);
            interior.transform.rotation = GameObjectHelper.QuaternionFromMatrix(door.buildingMatrix);

            // Position player above closest enter marker
            Vector3 marker;

            if (!interior.FindClosestEnterMarker(transform.position, out marker))
            {
                // Could not find an enter marker, probably not a valid interior
                Destroy(newInterior);
                return;
            }

            // Enumerate all exterior doors belonging to this building
            DaggerfallStaticDoors exteriorStaticDoors = interior.ExteriorDoors;

            if (exteriorStaticDoors && doorOwner)
            {
                List <StaticDoor> buildingDoors = new List <StaticDoor>();
                for (int i = 0; i < exteriorStaticDoors.Doors.Length; i++)
                {
                    if (exteriorStaticDoors.Doors[i].recordIndex == door.recordIndex)
                    {
                        StaticDoor newDoor = exteriorStaticDoors.Doors[i];
                        newDoor.ownerPosition = doorOwner.position;
                        newDoor.ownerRotation = doorOwner.rotation;
                        buildingDoors.Add(newDoor);
                    }
                }
                SetExteriorDoors(buildingDoors.ToArray());
            }

            // Assign new interior to parent
            if (InteriorParent != null)
            {
                newInterior.transform.parent = InteriorParent.transform;
            }

            // Cache some information about this interior
            buildingType = interior.BuildingData.BuildingType;
            factionID    = interior.BuildingData.FactionId;

            // Set player to marker position
            // TODO: Find closest door for player facing
            transform.position = marker + Vector3.up * (controller.height * 0.6f);
            SetStanding();

            EnableInteriorParent();

            // Add quest resources
            GameObjectHelper.AddQuestResourceObjects(SiteTypes.Building, interior.transform, interior.EntryDoor.buildingKey);

            // Update serializable state from scene cache for exterior->interior transition (unless new/load game)
            if (!start)
            {
                SaveLoadManager.RestoreCachedScene(interior.name);
            }

            // Raise event
            RaiseOnTransitionInteriorEvent(door, interior);

            // Fade in from black
            if (doFade)
            {
                DaggerfallUI.Instance.FadeHUDFromBlack();
            }
        }
コード例 #24
0
        /// <summary>
        /// Load assets for Summer.
        /// </summary>
        public void UpdateClimateSummer(ClimateBases currentClimate)
        {
            RefreshGrassDetails();
            SetGrassColor();
            SetGrassSize();

            if (RealGrass.Instance.RealisticGrass)
            {
                SetGrassDetail(GrassDetails, grassDetails[currentGrassDetail], ref grassDetailPrefab);
                SetGrassDetail(GrassAccents, grassAccents[currentGrassAccent], ref grassAccentPrefab);
            }

            if (RealGrass.Instance.Flowers)
            {
                detailPrototypes[Flowers].prototype = LoadGameObject(GetRandomFlowers());
            }

            if (!NeedsUpdate(UpdateType.Summer, currentClimate))
            {
                return;
            }

            switch (currentClimate)
            {
            case ClimateBases.Mountain:

                // Mountain
                SetGrass(brownGrass, realisticGrass);

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsMountain);
                }
                break;

            case ClimateBases.Swamp:

                // Swamp
                SetGrass(brownGrass, realisticGrass);

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsSwamp);
                }
                break;

            case ClimateBases.Temperate:

                // Temperate
                SetGrass(greenGrass, realisticGrass);

                if (RealGrass.Instance.WaterPlants)
                {
                    detailPrototypes[WaterPlants].prototype = LoadGameObject(plantsTemperate);
                }
                break;

            default:
                Debug.LogError(string.Format("RealGrass: {0} is not a valid climate (Summer)", currentClimate));
                RealGrass.Instance.ToggleMod(false);
                break;
            }

            if (RealGrass.Instance.TerrainStones)
            {
                detailPrototypes[Rocks].prototype    = LoadGameObject(rock);
                detailPrototypes[Rocks].healthyColor = new Color(0.70f, 0.70f, 0.70f);
                detailPrototypes[Rocks].dryColor     = new Color(0.40f, 0.40f, 0.40f);
            }
        }
コード例 #25
0
 /// <summary>
 /// Set ground climate.
 /// </summary>
 /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
 /// <param name="climate">Climate to set.</param>
 /// <param name="season">Season to set.</param>
 public void SetClimate(DaggerfallUnity dfUnity, ClimateBases climate, ClimateSeason season)
 {
     int archive = ClimateSwaps.GetGroundArchive(climate, season);
     SetClimate(dfUnity, archive, season);
     summary.climate = climate;
 }
コード例 #26
0
 /// <summary>
 /// Convert DaggerfallUnity climate base to API equivalent.
 /// </summary>
 /// <param name="climate">ClimateBases.</param>
 /// <returns>DFLocation.ClimateBaseType.</returns>
 public static DFLocation.ClimateBaseType FromUnityClimateBase(ClimateBases climate)
 {
     switch (climate)
     {
         case ClimateBases.Desert:
             return DFLocation.ClimateBaseType.Desert;
         case ClimateBases.Mountain:
             return DFLocation.ClimateBaseType.Mountain;
         case ClimateBases.Temperate:
             return DFLocation.ClimateBaseType.Temperate;
         case ClimateBases.Swamp:
             return DFLocation.ClimateBaseType.Swamp;
         default:
             return DFLocation.ClimateBaseType.None;
     }
 }
コード例 #27
0
        /// <summary>
        /// Set density for Winter.
        /// </summary>
        public void SetDensityWinter(Terrain terrain, Color32[] tilemap, ClimateBases currentClimate)
        {
            float grassChance = GetWinterGrassChance();
            bool  shores      = currentClimate != ClimateBases.Mountain;

            for (int y = 0; y < tilemapSize; y++)
            {
                for (int x = 0; x < tilemapSize; x++)
                {
                    switch (tilemap[(y * tilemapSize) + x].r)
                    {
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        if (terrainStones)
                        {
                            int rocks = RandomRocks();
                            if (rocks != 0)
                            {
                                var index = RandomPosition(y, x);
                                Rocks[index.First, index.Second] = rocks;
                            }
                        }
                        break;

                    // Grass growing/dying
                    case 8:
                    case 9:
                    case 10:
                    case 11:
                        if (grassChance != 0)
                        {
                            if (Random.value < grassChance)
                            {
                                Grass[y * 2, x * 2]       = RandomThick();
                                Grass[y * 2, (x * 2) + 1] = RandomThick();
                            }
                            if (Random.value < grassChance)
                            {
                                Grass[(y * 2) + 1, x * 2]       = RandomThick();
                                Grass[(y * 2) + 1, (x * 2) + 1] = RandomThick();
                            }
                        }
                        if (terrainStones)
                        {
                            int rocks = RandomRocks();
                            if (rocks != 0)
                            {
                                var index = RandomPosition(y, x);
                                Rocks[index.First, index.Second] = rocks;
                            }
                        }
                        break;

                    // Left side
                    case 84:
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                            WaterPlants[y * 2, x * 2]       = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, x * 2] = RandomRocksDesert();
                        }
                        break;

                    // Lower side
                    case 85:
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[y * 2, (x * 2)]     = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, x * 2] = RandomRocksDesert();
                        }
                        break;

                    // Right side
                    case 86:
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[y * 2, (x * 2) + 1]       = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[(y * 2) + 1, (x * 2) + 1] = RandomRocksDesert();
                        }
                        break;

                    // Upper side
                    case 87:
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2]       = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[(y * 2) + 1, (x * 2) + 1] = RandomRocksDesert();
                        }
                        break;

                    // Corners
                    case 88:
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, x * 2]             = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, x * 2] = RandomRocksDesert();
                        }
                        break;

                    case 89:
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, (x * 2) + 1] = RandomRocksDesert();
                        }
                        break;

                    case 90:
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, x * 2]             = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, x * 2] = RandomRocksDesert();
                        }
                        break;

                    case 91:
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                        }
                        if (terrainStones)
                        {
                            Rocks[y * 2, (x * 2) + 1] = RandomRocksDesert();
                        }
                        break;
                    }
                }
            }
        }
コード例 #28
0
        /// <summary>
        /// Get a new Material based on climate.
        /// </summary>
        /// <param name="key">Material key.</param>
        /// <param name="climate">New climate base.</param>
        /// <param name="season">New season.</param>
        /// <param name="windowStyle">New window style.</param>
        /// <returns>New material.</returns>
        public Material ChangeClimate(int key, ClimateBases climate, ClimateSeason season, WindowStyle windowStyle)
        {
            // Ready check
            if (!IsReady)
                return null;

            // Reverse key and apply climate
            int archive, record, frame;
            ReverseTextureKey(key, out archive, out record, out frame);
            archive = ClimateSwaps.ApplyClimate(archive, record, climate, season);

            // Get new material
            Material material;
            CachedMaterial cm = GetMaterialFromCache(archive, record, out material);

            // Handle windows
            if (cm.isWindow)
            {
                ChangeWindowEmissionColor(material, windowStyle);
            }

            return material;
        }
コード例 #29
0
        /// <summary>
        /// Transition player through an exterior door into building interior.
        /// </summary>
        /// <param name="doorOwner">Parent transform owning door array.</param>
        /// <param name="door">Exterior door player clicked on.</param>
        public void TransitionInterior(Transform doorOwner, StaticDoor door)
        {
            // Ensure we have component references
            if (!ReferenceComponents())
            {
                return;
            }

            // Get current climate
            ClimateBases climateBase = ClimateBases.Temperate;

            if (playerGPS)
            {
                climateBase = ClimateSwaps.FromAPIClimateBase(playerGPS.ClimateSettings.ClimateType);
            }

            // Layout interior
            // This needs to be done first so we know where the enter markers are
            GameObject newInterior = new GameObject(string.Format("DaggerfallInterior [Block={0}, Record={1}]", door.blockIndex, door.recordIndex));

            newInterior.hideFlags = HideFlags.HideAndDontSave;
            interior = newInterior.AddComponent <DaggerfallInterior>();
            interior.DoLayout(doorOwner, door, climateBase);

            // Position interior directly inside of exterior
            // This helps with finding closest enter/exit point relative to player position
            interior.transform.position = doorOwner.position + (Vector3)door.buildingMatrix.GetColumn(3);
            interior.transform.rotation = GameObjectHelper.QuaternionFromMatrix(door.buildingMatrix);

            // Position player above closest enter marker
            Vector3 marker;

            if (!interior.FindClosestEnterMarker(transform.position, out marker))
            {
                // Could not find an enter marker, probably not a valid interior
                Destroy(newInterior);
                return;
            }

            // Assign new interior to parent
            if (InteriorParent != null)
            {
                newInterior.transform.parent = InteriorParent.transform;
            }

            // Disable exterior parent
            if (ExteriorParent != null)
            {
                ExteriorParent.SetActive(false);
            }

            // Enable interior parent
            if (InteriorParent != null)
            {
                InteriorParent.SetActive(true);
            }

            // Cache some information about this interior
            buildingType = interior.BuildingData.BuildingType;

            // Set player to marker position
            // Not sure how to set facing here as player transitions to a marker, not a door
            // Could always find closest door and use that
            transform.position = marker + Vector3.up * (controller.height * 0.6f);
            SetStanding();

            // Player is now inside building
            isPlayerInside = true;
        }
コード例 #30
0
        private Material GetMaterial(RuntimeMaterial runtimeMaterial, DFLocation.ClimateBaseType climateBaseType, ClimateBases climate, ClimateSeason season, int[] dungeonTextureTable)
        {
            int archive = runtimeMaterial.Archive;
            int record  = runtimeMaterial.Record;

            if (dungeonTextureTable != null)
            {
                archive = DungeonTextureTables.ApplyTextureTable(archive, dungeonTextureTable, climateBaseType);
            }
            else if (runtimeMaterial.ApplyClimate)
            {
                archive = ClimateSwaps.ApplyClimate(archive, record, climate, season);
            }

            return(DaggerfallUnity.Instance.MaterialReader.GetMaterial(archive, record));
        }
コード例 #31
0
        /// <summary>
        /// Add Grass and other details on terrain.
        /// </summary>
        private void AddTerrainDetails(DaggerfallTerrain daggerTerrain, TerrainData terrainData)
        {
#if TEST_PERFORMANCE
            var stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
#endif

            UnityEngine.Random.InitState(TerrainHelper.MakeTerrainKey(daggerTerrain.MapPixelX, daggerTerrain.MapPixelY));

            // Terrain settings
            terrainData.SetDetailResolution(256, 8);
            terrainData.wavingGrassTint = Color.gray;
            Terrain terrain = daggerTerrain.gameObject.GetComponent <Terrain>();
            terrain.detailObjectDistance = options.DetailObjectDistance;
            terrain.detailObjectDensity  = options.DetailObjectDensity;

            // Get the current season and climate
            var          currentSeason = DaggerfallUnity.Instance.WorldTime.Now.SeasonValue;
            ClimateBases climate       = GetClimate(daggerTerrain.MapData.worldClimate);

            // Update detail layers
            Color32[] tilemap = daggerTerrain.TileMap;
            densityManager.InitDetailsLayers();
            switch (climate)
            {
            case ClimateBases.Temperate:
            case ClimateBases.Mountain:
            case ClimateBases.Swamp:
                if (currentSeason != DaggerfallDateTime.Seasons.Winter)
                {
                    detailPrototypesManager.UpdateClimateSummer(climate);
                    densityManager.SetDensitySummer(terrain, tilemap, climate);
                }
                else
                {
                    detailPrototypesManager.UpdateClimateWinter(climate);
                    densityManager.SetDensityWinter(terrain, tilemap, climate);
                }
                break;

            case ClimateBases.Desert:
                detailPrototypesManager.UpdateClimateDesert();
                densityManager.SetDensityDesert(tilemap);
                break;
            }

            // Assign detail prototypes to the terrain
            terrainData.detailPrototypes = detailPrototypesManager.DetailPrototypes;

            // Assign detail layers to the terrain
            terrainData.SetDetailLayer(0, 0, detailPrototypesManager.Grass, densityManager.Grass);
            if ((options.GrassStyle & GrassStyle.Mixed) == GrassStyle.Mixed && climate != ClimateBases.Desert)
            {
                terrainData.SetDetailLayer(0, 0, detailPrototypesManager.GrassDetails, densityManager.GrassDetails);
                terrainData.SetDetailLayer(0, 0, detailPrototypesManager.GrassAccents, densityManager.GrassAccents);
            }
            if (options.WaterPlants)
            {
                terrainData.SetDetailLayer(0, 0, detailPrototypesManager.WaterPlants, densityManager.WaterPlants);
            }
            if (options.TerrainStones)
            {
                terrainData.SetDetailLayer(0, 0, detailPrototypesManager.Rocks, densityManager.Rocks);
            }

#if TEST_PERFORMANCE
            stopwatch.Stop();
            Debug.LogFormat("RealGrass - Time elapsed: {0} ms.", stopwatch.Elapsed.Milliseconds);
#endif
        }
コード例 #32
0
        public void SetLocation(DFLocation location, bool performLayout = true)
        {
            if (!ReadyCheck())
                return;

            // Validate
            if (this.isSet)
                throw new Exception("This location has already been set.");
            if (!location.Loaded)
                throw new Exception("DFLocation not loaded.");

            // Set summary
            summary = new LocationSummary();
            summary.ID = location.MapTableData.MapId;
            summary.Longitude = (int)location.MapTableData.Longitude;
            summary.Latitude = (int)location.MapTableData.Latitude;
            DFPosition mapPixel = MapsFile.LongitudeLatitudeToMapPixel(summary.Longitude, summary.Latitude);
            DFPosition worldCoord = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y);
            summary.MapPixelX = mapPixel.X;
            summary.MapPixelY = mapPixel.Y;
            summary.WorldCoordX = worldCoord.X;
            summary.WorldCoordZ = worldCoord.Y;
            summary.RegionName = location.RegionName;
            summary.LocationName = location.Name;
            summary.WorldClimate = location.Climate.WorldClimate;
            summary.LocationType = location.MapTableData.LocationType;
            summary.DungeonType = location.MapTableData.DungeonType;
            summary.HasDungeon = location.HasDungeon;
            summary.Climate = ClimateSwaps.FromAPIClimateBase(location.Climate.ClimateType);
            summary.Nature = ClimateSwaps.FromAPITextureSet(location.Climate.NatureSet);
            summary.SkyBase = location.Climate.SkyBase;
            summary.BlockWidth = location.Exterior.ExteriorData.Width;
            summary.BlockHeight = location.Exterior.ExteriorData.Height;

            // Assign starting climate
            CurrentSeason = ClimateSeason.Summer;
            CurrentClimate = summary.Climate;
            CurrentNatureSet = summary.Nature;

            // Perform layout
            if (performLayout)
            {
                LayoutLocation(ref location);
                ApplyClimateSettings();
            }

            // Seal location
            isSet = true;
        }
コード例 #33
0
        /// <summary>
        /// Transition player through an exterior door into building interior.
        /// </summary>
        /// <param name="doorOwner">Parent transform owning door array..</param>
        /// <param name="door">Exterior door player clicked on.</param>
        public void TransitionInterior(Transform doorOwner, StaticDoor door, bool doFade = false)
        {
            // Ensure we have component references
            if (!ReferenceComponents())
            {
                return;
            }

            // Copy owner position to door
            // This ensures the door itself is all we need to reposition interior
            // Useful when loading a save and doorOwner is null (as outside world does not exist)
            if (doorOwner)
            {
                door.ownerPosition = doorOwner.position;
                door.ownerRotation = doorOwner.rotation;
            }

            // Raise event
            RaiseOnPreTransitionEvent(TransitionType.ToBuildingInterior, door);

            // Get climate
            ClimateBases climateBase = ClimateBases.Temperate;

            if (OverrideLocation)
            {
                climateBase = OverrideLocation.Summary.Climate;
            }
            else if (playerGPS)
            {
                climateBase = ClimateSwaps.FromAPIClimateBase(playerGPS.ClimateSettings.ClimateType);
            }

            // Layout interior
            // This needs to be done first so we know where the enter markers are
            GameObject newInterior = new GameObject(string.Format("DaggerfallInterior [Block={0}, Record={1}]", door.blockIndex, door.recordIndex));

            newInterior.hideFlags = defaultHideFlags;
            interior = newInterior.AddComponent <DaggerfallInterior>();

            // Try to layout interior
            // If we fail for any reason, use that old chestnut "this house has nothing of value"
            try
            {
                interior.DoLayout(doorOwner, door, climateBase);
            }
            catch
            {
                DaggerfallUI.AddHUDText(UserInterfaceWindows.HardStrings.thisHouseHasNothingOfValue);
                Destroy(newInterior);
                return;
            }

            // Position interior directly inside of exterior
            // This helps with finding closest enter/exit point relative to player position
            interior.transform.position = door.ownerPosition + (Vector3)door.buildingMatrix.GetColumn(3);
            interior.transform.rotation = GameObjectHelper.QuaternionFromMatrix(door.buildingMatrix);

            // Position player above closest enter marker
            Vector3 marker;

            if (!interior.FindClosestEnterMarker(transform.position, out marker))
            {
                // Could not find an enter marker, probably not a valid interior
                Destroy(newInterior);
                return;
            }

            // Enumerate all exterior doors belonging to this building
            DaggerfallStaticDoors exteriorStaticDoors = interior.ExteriorDoors;

            if (exteriorStaticDoors && doorOwner)
            {
                List <StaticDoor> buildingDoors = new List <StaticDoor>();
                for (int i = 0; i < exteriorStaticDoors.Doors.Length; i++)
                {
                    if (exteriorStaticDoors.Doors[i].recordIndex == door.recordIndex)
                    {
                        StaticDoor newDoor = exteriorStaticDoors.Doors[i];
                        newDoor.ownerPosition = doorOwner.position;
                        newDoor.ownerRotation = doorOwner.rotation;
                        buildingDoors.Add(newDoor);
                    }
                }
                SetExteriorDoors(buildingDoors.ToArray());
            }

            // Assign new interior to parent
            if (InteriorParent != null)
            {
                newInterior.transform.parent = InteriorParent.transform;
            }

            // Cache some information about this interior
            buildingType = interior.BuildingData.BuildingType;

            // Set player to marker position
            // TODO: Find closest door for player facing
            transform.position = marker + Vector3.up * (controller.height * 0.6f);
            SetStanding();

            EnableInteriorParent();

            // Raise event
            RaiseOnTransitionInteriorEvent(door, interior);

            // Fade in from black
            if (doFade)
            {
                DaggerfallUI.Instance.FadeHUDFromBlack();
            }
        }
コード例 #34
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;
        }
コード例 #35
0
        /// <summary>
        /// Rebuild materials back to default with no climate modifier.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param>
        /// <param name="climate">Climate to set.</param>
        /// <param name="season">Season to set.</param>
        /// <param name="windowStyle">Style of window to set.</param>
        public void SetClimate(ClimateBases climate, ClimateSeason season, WindowStyle windowStyle)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (defaultTextures.Count == 0)
                return;

            // Get new material array
            Material[] materials = new Material[defaultTextures.Count];
            for (int i = 0; i < defaultTextures.Count; i++)
            {
                materials[i] = dfUnity.MaterialReader.ChangeClimate(defaultTextures[i], climate, season, windowStyle);
            }

            // Assign material array
            if (materials != null)
                GetComponent<MeshRenderer>().sharedMaterials = materials;

            // Store climate settings
            currentClimate = climate;
            currentSeason = season;
            currentWindowStyle = windowStyle;
        }
コード例 #36
0
        /// <summary>
        /// Set density for Summer.
        /// </summary>
        public void SetDensitySummer(Terrain terrain, Color32[] tilemap, ClimateBases currentClimate)
        {
            float seasonalDetailsChance = GetGrassDetailsChance();
            bool  isNight = DaggerfallUnity.Instance.WorldTime.Now.IsNight;
            bool  shores  = currentClimate != ClimateBases.Mountain;

            for (int y = 0; y < tilemapSize; y++)
            {
                for (int x = 0; x < tilemapSize; x++)
                {
                    switch (tilemap[(y * tilemapSize) + x].r)
                    {
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        if (terrainStones)
                        {
                            int rocks = RandomRocks();
                            if (rocks != 0)
                            {
                                var index = RandomPosition(y, x);
                                Rocks[index.First, index.Second] = rocks;
                            }
                        }
                        break;

                    // Four corner tiles
                    case 8:
                    case 9:
                    case 10:
                    case 11:
                        SetGrassDensity(y * 2, x * 2, RandomThick(), seasonalDetailsChance);
                        SetGrassDensity(y * 2, (x * 2) + 1, RandomThick(), seasonalDetailsChance);
                        SetGrassDensity((y * 2) + 1, x * 2, RandomThick(), seasonalDetailsChance);
                        SetGrassDensity((y * 2) + 1, (x * 2) + 1, RandomThick(), seasonalDetailsChance);

                        if (flowers)
                        {
                            int commonFlowers = RandomFlowers();
                            if (commonFlowers != 0)
                            {
                                var index = RandomPosition(y, x);
                                Flowers[index.First, index.Second] = commonFlowers;
                            }
                        }
                        if (terrainStones)
                        {
                            int rocks = RandomRocks();
                            if (rocks != 0)
                            {
                                var index = RandomPosition(y, x);
                                Rocks[index.First, index.Second] = rocks;
                            }
                        }
                        break;

                    // Upper left corner
                    case 40:
                    case 224:
                    case 164:
                    case 176:
                    case 181:
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        break;

                    // Lower left corner
                    case 41:
                    case 221:
                    case 165:
                    case 177:
                    case 182:
                        Grass[y * 2, x * 2] = RandomThin();
                        break;

                    // Lower right corner
                    case 42:
                    case 222:
                    case 166:
                    case 178:
                    case 183:
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        break;

                    // Upper right corner
                    case 43:
                    case 223:
                    case 167:
                    case 179:
                    case 180:
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        break;

                    // Left side
                    case 44:
                    case 66:
                    case 160:
                    case 168:
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        Grass[y * 2, x * 2]       = RandomThin();
                        break;

                    // Left side: grass and plants
                    case 84:
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        Grass[y * 2, x * 2]       = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                            WaterPlants[y * 2, x * 2]       = RandomWaterPlants();
                        }
                        if (terrainStones && Random.value < 0.3f)
                        {
                            Rocks[(y * 2) + 1, x * 2] = Random.Range(0, 4);
                            Rocks[y * 2, x * 2]       = Random.Range(0, 4);
                        }
                        break;

                    // Lower side
                    case 45:
                    case 67:
                    case 161:
                    case 169:
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        Grass[y * 2, x * 2]       = RandomThin();
                        break;

                    // Lower side: grass and plants
                    case 85:
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        Grass[y * 2, x * 2]       = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[y * 2, (x * 2)]     = RandomWaterPlants();
                        }
                        if (terrainStones && Random.value < 0.3f)
                        {
                            Rocks[y * 2, (x * 2) + 1] = Random.Range(0, 4);
                            Rocks[y * 2, (x * 2)]     = Random.Range(0, 4);
                        }
                        break;

                    // Right side
                    case 46:
                    case 64:
                    case 162:
                    case 170:
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        break;

                    // Right side: grass and plants
                    case 86:
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[y * 2, (x * 2) + 1]       = RandomWaterPlants();
                        }
                        if (terrainStones && Random.value < 0.3f)
                        {
                            Rocks[(y * 2) + 1, (x * 2) + 1] = Random.Range(0, 4);
                            Rocks[y * 2, (x * 2) + 1]       = Random.Range(0, 4);
                        }
                        break;

                    // Upper side
                    case 47:
                    case 65:
                    case 163:
                    case 171:
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        break;

                    // Upper side: grass and plants
                    case 87:
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2]       = RandomWaterPlants();
                        }
                        if (terrainStones && Random.value < 0.3f)
                        {
                            Rocks[(y * 2) + 1, (x * 2) + 1] = Random.Range(0, 4);
                            Rocks[(y * 2) + 1, x * 2]       = Random.Range(0, 4);
                        }
                        break;

                    // All expect lower right
                    case 48:
                    case 62:
                    case 156:
                        Grass[y * 2, x * 2]             = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        break;

                    // All expect lower right: grass and plants
                    case 88:
                        Grass[y * 2, x * 2]             = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, x * 2]             = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                        }
                        break;

                    // All expect upper right
                    case 49:
                    case 63:
                    case 157:
                        Grass[y * 2, x * 2]       = RandomThin();
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        break;

                    // All expect upper right: grass and plants
                    case 89:
                        Grass[y * 2, x * 2]       = RandomThin();
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                        }
                        break;


                    // All expect upper left
                    case 50:
                    case 60:
                    case 158:
                        Grass[y * 2, x * 2]             = RandomThin();
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        break;

                    // All expect upper left: grass and plants
                    case 90:
                        Grass[y * 2, x * 2]             = RandomThin();
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, x * 2]             = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                        }
                        break;

                    // All expect lower left
                    case 51:
                    case 61:
                    case 159:
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        break;

                    // All expect lower left: grass and plants
                    case 91:
                        Grass[y * 2, (x * 2) + 1]       = RandomThin();
                        Grass[(y * 2) + 1, x * 2]       = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        if (waterPlants && shores)
                        {
                            WaterPlants[y * 2, (x * 2) + 1] = RandomWaterPlants();
                            WaterPlants[(y * 2) + 1, x * 2] = RandomWaterPlants();
                        }
                        break;

                    // Left to right
                    case 204:
                    case 206:
                    case 214:
                        Grass[y * 2, x * 2]             = RandomThin();
                        Grass[(y * 2) + 1, (x * 2) + 1] = RandomThin();
                        break;

                    // Right to left
                    case 205:
                    case 207:
                    case 213:
                        Grass[(y * 2) + 1, x * 2] = RandomThin();
                        Grass[y * 2, (x * 2) + 1] = RandomThin();
                        break;

                    // Swamp upper right corner
                    case 81:
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2), (x * 2)] = RandomWaterPlants();
                        }
                        break;

                    // Swamp lower left corner
                    case 83:
                        if (waterPlants && shores)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = RandomWaterPlants();
                        }
                        break;

                    // In-water grass
                    // case 0 is not enabled because is used for the sea
                    case 1:
                    case 2:
                    case 3:
                        if (waterPlants && Random.value < 0.6f)
                        {
                            switch (currentClimate)
                            {
                            case ClimateBases.Mountain:
                                WaterPlants[(y * 2) + 1, (x * 2) + 1] = Random.Range(5, 10);
                                break;

                            case ClimateBases.Swamp:
                                WaterPlants[(y * 2) + 1, (x * 2) + 1] = Random.Range(0, 3);
                                WaterPlants[(y * 2), (x * 2) + 1]     = Random.Range(0, 3);
                                WaterPlants[(y * 2) + 1, (x * 2)]     = Random.Range(0, 3);
                                WaterPlants[(y * 2), (x * 2)]         = Random.Range(0, 3);
                                break;

                            case ClimateBases.Temperate:
                                WaterPlants[y * 2, x * 2]             = Random.Range(2, 5);
                                WaterPlants[(y * 2) + 1, (x * 2) + 1] = Random.Range(2, 5);
                                WaterPlants[(y * 2) + 1, x * 2]       = Random.Range(2, 5);
                                WaterPlants[y * 2, (x * 2) + 1]       = Random.Range(2, 5);
                                break;
                            }
                        }

                        // Insects
                        if (RealGrass.Instance.FlyingInsects && Random.value < 0.2f)
                        {
                            RealGrass.Instance.DoInsects(isNight, GetTileWorldPosition(terrain, x, y));
                        }
                        break;

                    case 116:
                    case 117:
                    case 118:
                    case 119:
                        if (waterPlants && currentClimate == ClimateBases.Swamp)
                        {
                            WaterPlants[(y * 2) + 1, (x * 2) + 1] = Random.Range(0, 2);
                            WaterPlants[(y * 2), (x * 2) + 1]     = Random.Range(0, 2);
                            WaterPlants[(y * 2) + 1, (x * 2)]     = Random.Range(0, 2);
                            WaterPlants[(y * 2), (x * 2)]         = Random.Range(0, 2);
                        }
                        break;

                    // Little stones
                    case 216:
                    case 217:
                    case 218:
                    case 219:
                        if (terrainStones && Random.value > 0.8f)
                        {
                            Rocks[y * 2, x * 2]             = Random.Range(1, 3);
                            Rocks[(y * 2) + 1, (x * 2) + 1] = Random.Range(1, 3);
                        }
                        break;
                    }

                    if (RealGrass.Instance.FlyingInsects && Random.value < 0.001f)
                    {
                        RealGrass.Instance.DoInsects(isNight, GetTileWorldPosition(terrain, x, y));
                    }
                }
            }
        }
コード例 #37
0
        /// <summary>
        /// Converts an archive index to new climate and season.
        /// Will return same index if climate or season not supported.
        /// </summary>
        /// <param name="archive">Archive index of starting texture.</param>
        /// <param name="climate">Climate base to apply.</param>
        /// <param name="season">Climate season to apply</param>
        /// <returns>Archive index of new texture.</returns>
        public static int ApplyClimate(int archive, int record, ClimateBases climate, ClimateSeason season)
        {
            // Get climate texture info
            ClimateTextureInfo ci = ClimateSwaps.GetClimateTextureInfo(archive);

            // Ignore non-climate textures
            if (ci.textureSet == DFLocation.ClimateTextureSet.None)
                return archive;

            // Handle missing Swamp textures
            if (climate == ClimateBases.Swamp)
            {
                switch (ci.textureSet)
                {
                    case DFLocation.ClimateTextureSet.Interior_TempleInt:
                    case DFLocation.ClimateTextureSet.Interior_MarbleFloors:
                        return archive;
                }
            }

            // Bypass winter swaps in desert climates entirely
            // There are too many bad swaps, and you never see this variant in game
            if (climate == ClimateBases.Desert)
                ci.supportsWinter = false;

            // Handle swamp climate sets with missing winter textures
            if (climate == ClimateBases.Swamp)
            {
                switch (ci.textureSet)
                {
                    case DFLocation.ClimateTextureSet.Exterior_Castle:
                    case DFLocation.ClimateTextureSet.Exterior_MagesGuild:
                        ci.supportsWinter = false;
                        break;
                }
            }

            // Handle archives with missing winter textures
            if (archive == 82 && record > 1 ||
                archive == 77)
            {
                ci.supportsWinter = false;
            }

            // Flag to suppress climate index
            // Certain textures have a winter variant but are climate-specific
            bool suppressClimateIndex = false;
            switch (archive)
            {
                case 75:
                case 76:
                case 77:
                case 79:
                case 80:
                case 82:
                case 83:
                    suppressClimateIndex = true;
                    break;
            }

            // Calculate new index
            int climateIndex = 0;
            if (archive < 500 && !suppressClimateIndex)
            {
                climateIndex = (int)FromUnityClimateBase(climate) + (int)ci.textureSet;
                if (season == ClimateSeason.Winter && ci.supportsWinter)
                    climateIndex += (int)DFLocation.ClimateWeather.Winter;
                else if (season == ClimateSeason.Rain && ci.supportsRain)
                    climateIndex += (int)DFLocation.ClimateWeather.Rain;
            }
            else
            {
                climateIndex = archive;
                if (season == ClimateSeason.Winter && ci.supportsWinter)
                    climateIndex += (int)DFLocation.ClimateWeather.Winter;
            }

            return climateIndex;
        }
コード例 #38
0
        /// <summary>
        /// Get ground archive based on climate.
        /// </summary>
        /// <param name="climateBase">Climate base.</param>
        /// <param name="climateSeason">Season.</param>
        /// <returns>Ground archive matching climate and season.</returns>
        public static int GetGroundArchive(ClimateBases climateBase, ClimateSeason climateSeason)
        {
            // Apply climate
            int archive;
            switch (climateBase)
            {
                case ClimateBases.Desert:
                    archive = 2;
                    break;
                case ClimateBases.Mountain:
                    archive = 102;
                    break;
                case ClimateBases.Temperate:
                    archive = 302;
                    break;
                case ClimateBases.Swamp:
                    archive = 402;
                    break;
                default:
                    archive = 302;
                    break;
            }

            // Modify for season
            switch (climateSeason)
            {
                case ClimateSeason.Winter:
                    archive += 1;
                    break;
                case ClimateSeason.Rain:
                    archive += 2;
                    break;
            }

            return archive;
        }