public static string Execute(params string[] args) { DaggerfallWorkshop.StreamingWorld streamingWorld = GameManager.Instance.StreamingWorld;//GameObject.FindObjectOfType<DaggerfallWorkshop.StreamingWorld>(); DaggerfallWorkshop.DaggerfallUnity daggerfallUnity = DaggerfallUnity.Instance; DaggerfallSongPlayer songPlayer = GameObject.FindObjectOfType <DaggerfallSongPlayer>(); DefaultCommands.showDebugStrings = !DefaultCommands.showDebugStrings; bool show = DefaultCommands.showDebugStrings; if (streamingWorld) { streamingWorld.ShowDebugString = show; } if (daggerfallUnity) { daggerfallUnity.WorldTime.ShowDebugString = show; } if (songPlayer) { songPlayer.ShowDebugString = show; } if (FPSDisplay.fpsDisplay == null) { GameManager.Instance.gameObject.AddComponent <FPSDisplay>(); } FPSDisplay.fpsDisplay.ShowDebugString = show; return(string.Format("Debug string show: {0}", show)); }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) return false; return true; }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (nameHelper == null) nameHelper = new NameHelper(); return true; }
/// <summary> /// Set ground climate by texture archive index. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index.</param> /// <param name="season">Season to set.</param> public void SetClimate(DaggerfallUnity dfUnity, int archive, ClimateSeason season) { // Create tileMap texture Texture2D tileMapTexture = new Texture2D(tileMapDim, tileMapDim, TextureFormat.RGB24, false); tileMapTexture.SetPixels32(tileMap); tileMapTexture.Apply(false, true); tileMapTexture.filterMode = FilterMode.Point; tileMapTexture.wrapMode = TextureWrapMode.Clamp; // Get tileMap material Material material = Instantiate(dfUnity.MaterialReader.GetTerrainTilesetMaterial(archive)) as Material; material.SetTexture("_TilemapTex", tileMapTexture); material.SetInt("_TilemapDim", tileMapDim); // Assign new season summary.archive = archive; summary.season = season; GetComponent<MeshRenderer>().material = material; }
public static string Execute(params string[] args) { int speed; DaggerfallWorkshop.DaggerfallUnity daggerfallUnity = DaggerfallWorkshop.DaggerfallUnity.Instance; if (daggerfallUnity == null) { return(error); } if (args == null || args.Length < 1) { try { Console.Log(string.Format("Current TimeScale: {0}", DaggerfallWorkshop.DaggerfallUnity.Instance.WorldTime.TimeScale)); return(HelpCommand.Execute(SetTimeScale.name)); } catch { return(HelpCommand.Execute(SetTimeScale.name)); } } else if (!int.TryParse(args[0], out speed)) { return(error); } else { try { DaggerfallWorkshop.DaggerfallUnity.Instance.WorldTime.TimeScale = speed; return(string.Format("Time Scale set to: {0}", speed)); } catch { return("Unspecified error; failed to set timescale"); } } }
void Start() { dfUnity = DaggerfallUnity.Instance; songPlayer = GetComponent<DaggerfallSongPlayer>(); // Get local player GPS if not set if (LocalPlayerGPS == null) LocalPlayerGPS = GameManager.Instance.PlayerGPS; // Get streaming world if not set if (StreamingWorld == null) StreamingWorld = GameManager.Instance.StreamingWorld; // Get required player components if (LocalPlayerGPS) { playerEnterExit = LocalPlayerGPS.GetComponent<PlayerEnterExit>(); playerWeather = LocalPlayerGPS.GetComponent<PlayerWeather>(); } }
public static bool FindDaggerfallUnity(out DaggerfallUnity dfUnityOut) { dfUnityOut = GameObject.FindObjectOfType(typeof(DaggerfallUnity)) as DaggerfallUnity; if (dfUnityOut == null) { LogMessage("Could not locate DaggerfallUnity GameObject instance in scene!", true); return false; } return true; }
/// <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; }
public override void OnInspectorGUI() { // Update dfUnity.EditorUpdate(); #if UNITY_EDITOR_LINUX string message = string.Empty; message += "Linux users please set your Daggerfall installation path (i.e. parent folder of complete Daggerfall install) in Resources/defaults.ini then click 'Update Path' below."; message += " This is a temporary limitation to work around Inspector bugs in experimental Linux build."; EditorGUILayout.HelpBox(message, MessageType.Info); EditorGUILayout.SelectableLabel(dfUnity.Arena2Path, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (GUILayout.Button("Update Path")) { dfUnity.Arena2Path = string.Empty; dfUnity.EditorResetArena2Path(); } #else // Get properties var propArena2Path = Prop("Arena2Path"); // Browse for Arena2 path EditorGUILayout.Space(); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("Arena2 Path", "The local Arena2 path used for development only."), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(dfUnity.Arena2Path, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); if (GUILayout.Button("Browse...")) { string path = EditorUtility.OpenFolderPanel("Locate Arena2 Path", "", ""); if (!string.IsNullOrEmpty(path)) { if (!DaggerfallUnity.ValidateArena2Path(path)) { EditorUtility.DisplayDialog("Invalid Path", "The selected Arena2 path is invalid", "Close"); } else { dfUnity.Arena2Path = path; propArena2Path.stringValue = path; dfUnity.EditorResetArena2Path(); } } } if (GUILayout.Button("Clear")) { dfUnity.EditorClearArena2Path(); EditorUtility.SetDirty(target); } }); // Prompt user to set Arena2 path if (string.IsNullOrEmpty(dfUnity.Arena2Path)) { EditorGUILayout.HelpBox("Please set the Arena2 path of your Daggerfall installation.", MessageType.Info); return; } #endif // Display other GUI items DisplayOptionsGUI(); DisplayImporterGUI(); // Save modified properties serializedObject.ApplyModifiedProperties(); if (GUI.changed) { EditorUtility.SetDirty(target); } }
public override void GenerateSamples(ref MapPixelData mapPixel) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Divisor ensures continuous 0-1 range of tile samples float div = (float)TerrainHelper.terrainTileDim / 3f; // Read neighbouring height samples for this map pixel int mx = mapPixel.mapPixelX; int my = mapPixel.mapPixelY; byte[,] shm = dfUnity.ContentReader.WoodsFileReader.GetHeightMapValuesRange(mx - 2, my - 2, 4); byte[,] lhm = dfUnity.ContentReader.WoodsFileReader.GetLargeHeightMapValuesRange(mx - 1, my, 3); // Extract height samples for all chunks float averageHeight = 0; float maxHeight = float.MinValue; float baseHeight, noiseHeight; float x1, x2, x3, x4; int dim = TerrainHelper.terrainSampleDim; mapPixel.samples = new WorldSample[dim * dim]; for (int y = 0; y < dim; y++) { for (int x = 0; x < dim; x++) { float rx = (float)x / div; float ry = (float)y / div; int ix = Mathf.FloorToInt(rx); int iy = Mathf.FloorToInt(ry); float sfracx = (float)x / (float)(dim - 1); float sfracy = (float)y / (float)(dim - 1); float fracx = (float)(x - ix * div) / div; float fracy = (float)(y - iy * div) / div; float scaledHeight = 0; // Bicubic sample small height map for base terrain elevation x1 = TerrainHelper.CubicInterpolator(shm[0, 3], shm[1, 3], shm[2, 3], shm[3, 3], sfracx); x2 = TerrainHelper.CubicInterpolator(shm[0, 2], shm[1, 2], shm[2, 2], shm[3, 2], sfracx); x3 = TerrainHelper.CubicInterpolator(shm[0, 1], shm[1, 1], shm[2, 1], shm[3, 1], sfracx); x4 = TerrainHelper.CubicInterpolator(shm[0, 0], shm[1, 0], shm[2, 0], shm[3, 0], sfracx); baseHeight = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, sfracy); scaledHeight += baseHeight * baseHeightScale; // Bicubic sample large height map for noise mask over terrain features x1 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 0], lhm[ix + 1, iy + 0], lhm[ix + 2, iy + 0], lhm[ix + 3, iy + 0], fracx); x2 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 1], lhm[ix + 1, iy + 1], lhm[ix + 2, iy + 1], lhm[ix + 3, iy + 1], fracx); x3 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 2], lhm[ix + 1, iy + 2], lhm[ix + 2, iy + 2], lhm[ix + 3, iy + 2], fracx); x4 = TerrainHelper.CubicInterpolator(lhm[ix, iy + 3], lhm[ix + 1, iy + 3], lhm[ix + 2, iy + 3], lhm[ix + 3, iy + 3], fracx); noiseHeight = TerrainHelper.CubicInterpolator(x1, x2, x3, x4, fracy); scaledHeight += noiseHeight * noiseMapScale; // Additional noise mask for small terrain features at ground level float latitude = mapPixel.mapPixelX * MapsFile.WorldMapTileDim + x; float longitude = MapsFile.MaxWorldTileCoordZ - mapPixel.mapPixelY * MapsFile.WorldMapTileDim + y; float lowFreq = TerrainHelper.GetNoise(dfUnity.ContentReader.Noise, latitude, longitude, 0.1f, 0.5f, 0.5f, 1); float highFreq = TerrainHelper.GetNoise(dfUnity.ContentReader.Noise, latitude, longitude, 6f, 0.5f, 0.5f, 1); scaledHeight += (lowFreq * highFreq) * extraNoiseScale; // Clamp lower values to ocean elevation if (scaledHeight < scaledOceanElevation) { scaledHeight = scaledOceanElevation; } // Accumulate average height averageHeight += scaledHeight; // Get max height if (scaledHeight > maxHeight) { maxHeight = scaledHeight; } // Set sample mapPixel.samples[y * dim + x] = new WorldSample() { scaledHeight = scaledHeight, record = 2, }; } } // Average and max heights are passed back for locations mapPixel.averageHeight = averageHeight /= (float)(dim * dim); mapPixel.maxHeight = maxHeight; }
private bool ReadyCheck() { // Ensure we have a DaggerfallUnity reference if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; // Force first update to set lights lastCityLightsFlag = !dfUnity.WorldTime.Now.IsCityLightsOn; } // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("DaggerfallLight: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } // Must have a light component added if (!myLight) return false; return true; }
void Start() { dfUnity = DaggerfallUnity.Instance; useDeferredReflections = (GameManager.Instance.MainCamera.renderingPath == RenderingPath.DeferredShading); if (!streamingWorld) streamingWorld = GameObject.Find("StreamingWorld").GetComponent<StreamingWorld>(); if (!streamingWorld) { DaggerfallUnity.LogMessage("InjectReflectiveMaterialProperty: Missing StreamingWorld reference.", true); if (Application.isEditor) Debug.Break(); else Application.Quit(); } if (GameObject.Find("IncreasedTerrainDistanceMod") != null) { if (DaggerfallUnity.Settings.Nystul_IncreasedTerrainDistance) { extraTranslationY = GameObject.Find("IncreasedTerrainDistanceMod").GetComponent<ProjectIncreasedTerrainDistance.IncreasedTerrainDistance>().ExtraTranslationY; } } gameObjectReflectionPlaneGroundLevel = GameObject.Find("ReflectionPlaneBottom"); gameObjectReflectionPlaneSeaLevel = GameObject.Find("ReflectionPlaneSeaLevel"); gameObjectReflectionPlaneLowerLevel = gameObjectReflectionPlaneSeaLevel; // get inactive gameobject StreamingTarget (just GameObject.Find() would fail to find inactive gameobjects) GameObject[] gameObjects = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject currentGameObject in gameObjects) { string objectPathInHierarchy = GetGameObjectPath(currentGameObject); if (objectPathInHierarchy == "/Exterior/StreamingTarget") { gameObjectStreamingTarget = currentGameObject; } } iniData = getIniParserConfigInjectionTextures(); }
// Set location tilemap data public static void SetLocationTiles(ref MapPixelData mapPixel) { //const int tileDim = 16; //const int chunkDim = 8; DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Get location DFLocation location = dfUnity.ContentReader.MapFileReader.GetLocation(mapPixel.mapRegionIndex, mapPixel.mapLocationIndex); // Centre location tiles inside terrain area //int startX = ((chunkDim * tileDim) - location.Exterior.ExteriorData.Width * tileDim) / 2; //int startY = ((chunkDim * tileDim) - location.Exterior.ExteriorData.Height * tileDim) / 2; // Position tiles inside terrain area //int width = location.Exterior.ExteriorData.Width; //int height = location.Exterior.ExteriorData.Height; DFPosition tilePos = TerrainHelper.GetLocationTerrainTileOrigin(location); // Full 8x8 locations have "terrain blend space" around walls to smooth down random terrain towards flat area. // This is indicated by texture index > 55 (ground texture range is 0-55), larger values indicate blend space. // We need to know rect of actual city area so we can use blend space outside walls. int xmin = int.MaxValue, ymin = int.MaxValue; int xmax = 0, ymax = 0; // Iterate blocks of this location for (int blockY = 0; blockY < location.Exterior.ExteriorData.Height; blockY++) { for (int blockX = 0; blockX < location.Exterior.ExteriorData.Width; blockX++) { // Get block data DFBlock block; string blockName = dfUnity.ContentReader.MapFileReader.GetRmbBlockName(ref location, blockX, blockY); if (!dfUnity.ContentReader.GetBlock(blockName, out block)) { continue; } // Copy ground tile info for (int tileY = 0; tileY < RMBLayout.RMBTilesPerBlock; tileY++) { for (int tileX = 0; tileX < RMBLayout.RMBTilesPerBlock; tileX++) { DFBlock.RmbGroundTiles tile = block.RmbBlock.FldHeader.GroundData.GroundTiles[tileX, (RMBLayout.RMBTilesPerBlock - 1) - tileY]; int xpos = tilePos.X + blockX * RMBLayout.RMBTilesPerBlock + tileX; int ypos = tilePos.Y + blockY * RMBLayout.RMBTilesPerBlock + tileY; int record = tile.TextureRecord; if (tile.TextureRecord < 56) { // Track interior bounds of location tiled area if (xpos < xmin) { xmin = xpos; } if (xpos > xmax) { xmax = xpos; } if (ypos < ymin) { ymin = ypos; } if (ypos > ymax) { ymax = ypos; } // Store texture data from block mapPixel.tilemapSamples[xpos, ypos].record = record; mapPixel.tilemapSamples[xpos, ypos].flip = tile.IsFlipped; mapPixel.tilemapSamples[xpos, ypos].rotate = tile.IsRotated; mapPixel.tilemapSamples[xpos, ypos].location = true; } } } } } // Update location rect with extra clearance const int extraClearance = 2; Rect locationRect = new Rect(); locationRect.xMin = xmin - extraClearance; locationRect.xMax = xmax + extraClearance; locationRect.yMin = ymin - extraClearance; locationRect.yMax = ymax + extraClearance; mapPixel.locationRect = locationRect; }
/// <summary> /// Gets Unity Mesh from Daggerfall model. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleon for loading content.</param> /// <param name="modelID">Daggerfall model ID to load..</param> /// <param name="cachedMaterialsOut">Array of cached materials in order of submesh.</param> /// <param name="textureKeysOut">Array of original texture keys in order of submesh.</param> /// <param name="hasAnimationsOut">True if one or more materials have animations.</param> /// <param name="solveTangents">Solve tangents for this mesh.</param> /// <param name="lightmapUVs">Add secondary lightmap UVs to this mesh.</param> /// <returns>Mesh object or null.</returns> public Mesh GetMesh( DaggerfallUnity dfUnity, uint modelID, out CachedMaterial[] cachedMaterialsOut, out int[] textureKeysOut, out bool hasAnimationsOut, bool solveTangents = false, bool lightmapUVs = false) { cachedMaterialsOut = null; hasAnimationsOut = false; textureKeysOut = null; // Ready check if (!IsReady) { return(null); } // Get model data ModelData model; if (!GetModelData(modelID, out model)) { DaggerfallUnity.LogMessage(string.Format("Unknown ModelID {0}.", modelID.ToString()), true); return(null); } // Load materials cachedMaterialsOut = new CachedMaterial[model.SubMeshes.Length]; textureKeysOut = new int[model.SubMeshes.Length]; for (int i = 0; i < model.SubMeshes.Length; i++) { int archive = model.DFMesh.SubMeshes[i].TextureArchive; int record = model.DFMesh.SubMeshes[i].TextureRecord; textureKeysOut[i] = MaterialReader.MakeTextureKey((short)archive, (byte)record, (byte)0); // Add material to array CachedMaterial cachedMaterial; dfUnity.MaterialReader.GetCachedMaterial(archive, record, 0, out cachedMaterial); cachedMaterialsOut[i] = cachedMaterial; // Set animation flag if (cachedMaterial.singleFrameCount > 1 && !hasAnimationsOut) { hasAnimationsOut = true; } } // Create mesh Mesh mesh = new Mesh(); mesh.name = modelID.ToString(); mesh.vertices = model.Vertices; mesh.normals = model.Normals; mesh.uv = model.UVs; mesh.subMeshCount = model.SubMeshes.Length; // Set submesh triangles for (int s = 0; s < mesh.subMeshCount; s++) { var sub = model.SubMeshes[s]; int[] triangles = new int[sub.PrimitiveCount * 3]; for (int t = 0; t < sub.PrimitiveCount * 3; t++) { triangles[t] = model.Indices[sub.StartIndex + t]; } mesh.SetTriangles(triangles, s); } // Finalise mesh if (solveTangents) { TangentSolver(mesh); } if (lightmapUVs) { AddLightmapUVs(mesh); } mesh.RecalculateBounds(); return(mesh); }
/// <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> /// <param name="dungeon">This is a dungeon billboard.</param> /// <returns>Material.</returns> public Material SetMaterial(int archive, int record, int frame, bool dungeon) { // Get DaggerfallUnity DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) { return(null); } // Get references meshRenderer = GetComponent <MeshRenderer>(); Vector2 size; Mesh mesh = null; Material material = null; if (dfUnity.MaterialReader.AtlasTextures) { material = dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 2048, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false); mesh = dfUnity.MeshReader.GetBillboardMesh( summary.AtlasRects[summary.AtlasIndices[record].startIndex], archive, record, out size, dungeon); 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); mesh = dfUnity.MeshReader.GetBillboardMesh( summary.Rect, archive, record, out size, dungeon); summary.AtlasedMaterial = false; summary.AnimatedMaterial = false; } // Update material properties MaterialReader.SetBlendMode(material, MaterialReader.CustomBlendMode.Cutout); // Set summary summary.InDungeon = dungeon; 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); } // 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 Destroy(oldMesh); } // Standalone billboards never cast shadows meshRenderer.shadowCastingMode = ShadowCastingMode.Off; return(material); }
private bool InitSynth() { // Get peer AudioSource audioSource = GetComponent <AudioSource>(); if (audioSource == null) { DaggerfallUnity.LogMessage("DaggerfallSongPlayer: Could not find AudioSource component."); return(false); } // Create synthesizer and load bank if (midiSynthesizer == null) { // Get number of channels if (AudioSettings.driverCapabilities.ToString() == "Mono") { channels = 1; } else { channels = 2; } // Create synth AudioSettings.GetDSPBufferSize(out bufferLength, out numBuffers); midiSynthesizer = new Synthesizer(sampleRate, channels, bufferLength / numBuffers, numBuffers, polyphony); // Load bank data string filename = DaggerfallUnity.Settings.SoundFont; byte[] bankData = LoadBank(filename); if (bankData == null) { // Attempt to fallback to default internal soundfont bankData = LoadDefaultSoundFont(); filename = defaultSoundFontFilename; Debug.LogFormat("Using default SoundFont {0}", defaultSoundFontFilename); } else { Debug.LogFormat("Trying custom SoundFont {0}", filename); } // Assign to synth if (bankData == null) { return(false); } else { midiSynthesizer.LoadBank(new MyMemoryFile(bankData, filename)); midiSynthesizer.ResetSynthControls(); // Need to do this for bank to load properly, don't know why } } // Create sequencer if (midiSequencer == null) { midiSequencer = new MidiFileSequencer(midiSynthesizer); } // Check init if (midiSynthesizer == null || midiSequencer == null) { DaggerfallUnity.LogMessage("DaggerfallSongPlayer: Failed to init synth."); return(false); } return(true); }
/// <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); }
/// <summary> /// Apply current sound index and behaviour to AudioSource. /// </summary> private void Apply(float spatialBlend = 1) { // Do nothing if not ready if (!ReadyCheck() || !audioSource.enabled) { return; } // Do nothing if out of range if (SoundIndex < minIndex || SoundIndex >= maxIndex) { return; } // Get new clip audioClip = dfUnity.SoundReader.GetAudioClip(SoundIndex); if (audioClip == null) { DaggerfallUnity.LogMessage("Failed to load Daggerfall audio clip."); return; } // Set spatial blend audioSource.spatialBlend = spatialBlend; // Apply preset switch (Preset) { case AudioPresets.OnDemand: audioSource.playOnAwake = false; audioSource.loop = false; playerCheck = false; playRandomly = false; break; case AudioPresets.LoopOnAwake: audioSource.playOnAwake = true; audioSource.loop = true; playerCheck = false; playRandomly = false; break; case AudioPresets.LoopOnDemand: audioSource.playOnAwake = false; audioSource.loop = true; playerCheck = false; playRandomly = false; break; case AudioPresets.LoopIfPlayerNear: audioSource.playOnAwake = true; audioSource.loop = true; playerCheck = true; playRandomly = false; break; case AudioPresets.PlayRandomlyIfPlayerNear: audioSource.playOnAwake = false; audioSource.loop = false; playerCheck = true; playRandomly = true; break; default: break; } // Assign clip to Unity AudioSource only if app playing if (Application.isPlaying) { audioSource.clip = audioClip; } // Manually start sound if playOnAwake true. // This is necessary as sound is procedurally created after awake. if (audioSource.playOnAwake) { audioSource.Play(); } }
private bool ReadyCheck() { // Ensure we have a DaggerfallUnity reference if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; } // Do nothing until DaggerfallUnity is ready if (!dfUnity.IsReady) return false; return true; }
void Awake() { dfUnity = DaggerfallUnity.Instance; }
void Start() { dfUnity = DaggerfallUnity.Instance; }
//void ShowUnknownGUI() //{ // EditorGUILayout.Space(); // showUnknownFoldout = GUILayoutHelper.Foldout(showUnknownFoldout, new GUIContent("Unknown"), () => // { // EditorGUILayout.Space(); // GUILayoutHelper.Indent(() => // { // EditorGUILayout.LabelField("Unknown1 [1 Bytes]"); // EditorGUILayout.SelectableLabel(selectedCareer.RawData.Unknown1.ToString("X2"), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); // }); // GUILayoutHelper.Indent(() => // { // EditorGUILayout.LabelField("Unknown2 [8 Bytes]"); // string valuesString = string.Empty; // for (int i = 0; i < selectedCareer.RawData.Unknown2.Length; i++) // { // valuesString += selectedCareer.RawData.Unknown2[i].ToString("X2") + " "; // } // EditorGUILayout.SelectableLabel(valuesString, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); // }); // }); //} bool IsReady() { dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) { return(false); } // Read all CLASS*.CFG files if (classTemplates == null) { string[] files = Directory.GetFiles(dfUnity.Arena2Path, "class*.cfg"); if (files != null && files.Length > 0) { classTemplates = new DFCareer[files.Length - 1]; classNames = new GUIContent[files.Length - 1]; for (int i = 0; i < files.Length - 1; i++) { ClassFile classFile = new ClassFile(files[i]); classTemplates[i] = classFile.Career; classNames[i] = new GUIContent(classTemplates[i].Name); } } } // Read all ENEMY*.CFG files if (monsterTemplates == null) { MonsterFile monsterFile = new MonsterFile(); if (monsterFile.Load(Path.Combine(dfUnity.Arena2Path, MonsterFile.Filename), FileUsage.UseMemory, true)) { // First pass locates CFG record indices List <int> cfgIndices = new List <int>(); for (int i = 0; i < monsterFile.Count; i++) { string recordName = monsterFile.GetRecordName(i); if (recordName.EndsWith(".cfg", StringComparison.InvariantCultureIgnoreCase)) { cfgIndices.Add(i); } } // Second pass populates arrays monsterTemplates = new DFCareer[cfgIndices.Count]; monsterNames = new GUIContent[cfgIndices.Count]; for (int i = 0; i < cfgIndices.Count; i++) { // Read ENEMY.CFG class file from stream ClassFile classFile = new ClassFile(); byte[] data = monsterFile.GetRecordBytes(cfgIndices[i]); MemoryStream stream = new MemoryStream(data); BinaryReader reader = new BinaryReader(stream); classFile.Load(reader); reader.Close(); // Add to arrays monsterTemplates[i] = classFile.Career; monsterNames[i] = new GUIContent(monsterTemplates[i].Name); } } else { return(false); } } return(true); }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (itemHelper == null) itemHelper = new ItemHelper(); if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) return false; if (factionFile == null) factionFile = new FactionFile(Path.Combine(dfUnity.Arena2Path, FactionFile.Filename), FileUsage.UseMemory, true); if (saveGames == null || saveTrees == null || saveNames == null) { saveGames = new SaveGames(); saveNames = new GUIContent[6]; saveTrees = new SaveTree[6]; saveVars = new SaveVars[6]; saveTextures = new Texture2D[6]; if (saveGames.OpenSavesPath(Path.GetDirectoryName(DaggerfallUnity.Instance.Arena2Path))) { for (int i = 0; i < 6; i++) { if (saveGames.HasSave(i)) { saveGames.OpenSave(i); saveTrees[i] = saveGames.SaveTree; saveVars[i] = saveGames.SaveVars; saveNames[i] = new GUIContent(saveGames.SaveName); saveTextures[i] = TextureReader.CreateFromAPIImage(saveGames.SaveImage); saveTextures[i].filterMode = FilterMode.Point; } else { saveTrees[i] = null; saveVars[i] = null; saveTextures[i] = null; saveNames[i] = new GUIContent("Empty"); } } } } return true; }
/// <summary> /// Precalculate and cache billboard scale for every record. /// This will change based on animation state and orientation. /// Cache this to array so it only needs to be calculated once. /// Also store number of frames for state animations. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index derived from type and gender.</param> private void CacheRecordSizesAndFrames(DaggerfallUnity dfUnity, int archive) { // Open texture file string path = Path.Combine(dfUnity.Arena2Path, TextureFile.IndexToFileName(archive)); TextureFile textureFile = new TextureFile(path, FileUsage.UseMemory, true); // Cache size and scale for each record summary.RecordSizes = new Vector2[textureFile.RecordCount]; summary.RecordFrames = new int[textureFile.RecordCount]; for (int i = 0; i < textureFile.RecordCount; i++) { // Get size and scale of this texture DFSize size = textureFile.GetSize(i); DFSize scale = textureFile.GetScale(i); // Set start size Vector2 startSize; startSize.x = size.Width; startSize.y = size.Height; // Apply scale Vector2 finalSize; int xChange = (int)(size.Width * (scale.Width / BlocksFile.ScaleDivisor)); int yChange = (int)(size.Height * (scale.Height / BlocksFile.ScaleDivisor)); finalSize.x = (size.Width + xChange); finalSize.y = (size.Height + yChange); // Store final size and frame count summary.RecordSizes[i] = finalSize * MeshReader.GlobalScale; summary.RecordFrames[i] = textureFile.GetFrameCount(i); } }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) return false; if (regionNames.Length == 0) { regionNames = (string[])dfUnity.ContentReader.MapFileReader.RegionNames.Clone(); System.Array.Sort(regionNames); } return true; }
private bool ReadyCheck() { // Ensure we have a DaggerfallUnity reference if (dfUnity == null) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return false; // Get audio source audioSource = GetComponent<AudioSource>(); if (audioSource == null) { DaggerfallUnity.LogMessage("DaggerfallAudioSource: Could not find AudioSource component."); return false; } return true; }
private void UpdateWorldInfo(int x, int y) { // Requires DaggerfallUnity to be ready if (!ReadyCheck()) { return; } // Requires MAPS.BSA connection if (dfUnity.ContentReader.MapFileReader == null) { return; } // Get climate and politic data currentClimateIndex = dfUnity.ContentReader.MapFileReader.GetClimateIndex(x, y); currentPoliticIndex = dfUnity.ContentReader.MapFileReader.GetPoliticIndex(x, y); climateSettings = MapsFile.GetWorldClimateSettings(currentClimateIndex); if (currentPoliticIndex > 128) { regionName = dfUnity.ContentReader.MapFileReader.GetRegionName(currentPoliticIndex - 128); } else if (currentPoliticIndex == 64) { regionName = "Ocean"; } else { regionName = "Unknown"; } // Get region data currentRegion = dfUnity.ContentReader.MapFileReader.GetRegion(CurrentRegionIndex); // Get location data ContentReader.MapSummary mapSummary; if (dfUnity.ContentReader.HasLocation(x, y, out mapSummary)) { currentLocation = dfUnity.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex); hasCurrentLocation = true; CalculateWorldLocationRect(); } else { currentLocation = new DFLocation(); hasCurrentLocation = false; ClearWorldLocationRect(); } // Get location type if (hasCurrentLocation) { if (currentRegion.MapTable == null) { DaggerfallUnity.LogMessage(string.Format("PlayerGPS: Location {0} in region{1} has a null MapTable.", currentLocation.Name, currentLocation.RegionName)); } else { currentLocationType = currentRegion.MapTable[mapSummary.MapIndex].LocationType; } } }
/// <summary> /// Updates enemy state based on current settings. /// Called automatially by SetEnemyType(). /// This should be called after changing enemy state (e.g. from in code or in editor). /// </summary> private void ApplyEnemyState() { // Get state animations summary.StateAnims = GetStateAnims(summary.EnemyState); if (summary.EnemyState == MobileStates.PrimaryAttack) { int random = Dice100.Roll(); if (random <= summary.Enemy.ChanceForAttack2) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames2; } else { random -= summary.Enemy.ChanceForAttack2; if (random <= summary.Enemy.ChanceForAttack3) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames3; } else { random -= summary.Enemy.ChanceForAttack3; if (random <= summary.Enemy.ChanceForAttack4) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames4; } else { random -= summary.Enemy.ChanceForAttack4; if (random <= summary.Enemy.ChanceForAttack5) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames5; } else { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames; } } } } // Set to the first frame of this animation, and prepare frameIterator to start from the second frame when AnimateEnemy() next runs currentFrame = summary.StateAnimFrames[0]; frameIterator = 1; } if (summary.EnemyState == MobileStates.RangedAttack1 || summary.EnemyState == MobileStates.RangedAttack2) { summary.StateAnimFrames = summary.Enemy.RangedAttackAnimFrames; // Set to the first frame of this animation, and prepare frameIterator to start from the second frame when AnimateEnemy() next runs currentFrame = summary.StateAnimFrames[0]; frameIterator = 1; } if (summary.EnemyState == MobileStates.Spell) { summary.StateAnimFrames = summary.Enemy.SpellAnimFrames; // Set to the first frame of this animation, and prepare frameIterator to start from the second frame when AnimateEnemy() next runs currentFrame = summary.StateAnimFrames[0]; frameIterator = 1; } if (summary.StateAnims == null) { // Log error message DaggerfallUnity.LogMessage(string.Format("DaggerfalMobileUnit: Enemy does not have animation for {0} state. Defaulting to Idle state.", summary.EnemyState.ToString()), true); // Set back to idle (which every enemy has in one form or another) summary.EnemyState = MobileStates.Idle; summary.StateAnims = GetStateAnims(summary.EnemyState); } // One of the frost daedra's sets of attack frames starts with the hit frame (-1), so we need to check for that right away before updating orientation. if (currentFrame == -1 && summary.EnemyState == MobileStates.PrimaryAttack) { doMeleeDamage = true; if (frameIterator < summary.StateAnimFrames.Length) { currentFrame = summary.StateAnimFrames[frameIterator++]; } } // Orient enemy relative to camera UpdateOrientation(); }
/// <summary> /// Sets new enemy type. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="enemyType">Enemy type.</param> public void SetEnemy(DaggerfallUnity dfUnity, MobileEnemy enemy, MobileReactions reaction) { // Initial enemy settings summary.Enemy = enemy; summary.EnemyState = MobileStates.Move; summary.Enemy.Reactions = reaction; // Load enemy content int archive = GetTextureArchive(); CacheRecordSizesAndFrames(dfUnity, archive); AssignMeshAndMaterial(dfUnity, archive); // Apply enemy state and update orientation lastOrientation = -1; ApplyEnemyState(); // Raise setup flag summary.IsSetup = true; }
/// <summary> /// Gets Unity Mesh from previously combined model data. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleon for loading content.</param> /// <param name="combiner">ModelCombiner to build from.</param> /// <param name="cachedMaterialsOut">Array of cached materials in order of submesh.</param> /// <param name="textureKeysOut">Array of original texture keys in order of submesh.</param> /// <param name="hasAnimationsOut">True if one or more materials have animations.</param> /// <param name="solveTangents">Solve tangents for this mesh.</param> /// <param name="lightmapUVs">Add secondary lightmap UVs to this mesh.</param> /// <returns>Mesh object or null.</returns> public Mesh GetCombinedMesh( DaggerfallUnity dfUnity, ModelCombiner combiner, out CachedMaterial[] cachedMaterialsOut, out int[] textureKeysOut, out bool hasAnimationsOut, bool solveTangents = false, bool lightmapUVs = false) { cachedMaterialsOut = null; hasAnimationsOut = false; textureKeysOut = null; // Ready check if (!IsReady) { return(null); } // Get combined model ModelCombiner.CombinedModel combinedModel; if (!combiner.GetCombinedModel(out combinedModel)) { return(null); } // Load materials cachedMaterialsOut = new CachedMaterial[combinedModel.SubMeshes.Length]; textureKeysOut = new int[combinedModel.SubMeshes.Length]; for (int i = 0; i < combinedModel.SubMeshes.Length; i++) { int archive = combinedModel.SubMeshes[i].TextureArchive; int record = combinedModel.SubMeshes[i].TextureRecord; textureKeysOut[i] = MaterialReader.MakeTextureKey((short)archive, (byte)record, (byte)0); // Add material to array CachedMaterial cachedMaterial; dfUnity.MaterialReader.GetCachedMaterial(archive, record, 0, out cachedMaterial); cachedMaterialsOut[i] = cachedMaterial; // Set animation flag if (cachedMaterial.singleFrameCount > 1 && !hasAnimationsOut) { hasAnimationsOut = true; } } // Create mesh Mesh mesh = new Mesh(); mesh.name = "CombinedMesh"; mesh.vertices = combinedModel.Vertices; mesh.normals = combinedModel.Normals; mesh.uv = combinedModel.UVs; mesh.subMeshCount = combinedModel.SubMeshes.Length; // Set submesh triangles for (int s = 0; s < mesh.subMeshCount; s++) { var sub = combinedModel.SubMeshes[s]; int[] triangles = new int[sub.PrimitiveCount * 3]; for (int t = 0; t < sub.PrimitiveCount * 3; t++) { triangles[t] = combinedModel.Indices[sub.StartIndex + t]; } mesh.SetTriangles(triangles, s); } // Finalise mesh if (solveTangents) { TangentSolver(mesh); } if (lightmapUVs) { AddLightmapUVs(mesh); } mesh.RecalculateBounds(); mesh.Optimize(); return(mesh); }
/// <summary> /// Creates mesh and material for this enemy. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index derived from type and gender.</param> private void AssignMeshAndMaterial(DaggerfallUnity dfUnity, int archive) { // Get mesh filter if (meshFilter == null) meshFilter = GetComponent<MeshFilter>(); // Vertices for a 1x1 unit quad // This is scaled to correct size depending on facing and orientation float hx = 0.5f, hy = 0.5f; Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(hx, hy, 0); vertices[1] = new Vector3(-hx, hy, 0); vertices[2] = new Vector3(hx, -hy, 0); vertices[3] = new Vector3(-hx, -hy, 0); // Indices int[] indices = new int[6] { 0, 1, 2, 3, 2, 1, }; // Normals Vector3 normal = Vector3.Normalize(Vector3.up + Vector3.forward); Vector3[] normals = new Vector3[4]; normals[0] = normal; normals[1] = normal; normals[2] = normal; normals[3] = normal; // Create mesh Mesh mesh = new Mesh(); mesh.name = string.Format("MobileEnemyMesh"); mesh.vertices = vertices; mesh.triangles = indices; mesh.normals = normals; // Assign mesh meshFilter.sharedMesh = mesh; // Load material atlas Material material = dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 1024, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false, true); // Set new enemy material GetComponent<MeshRenderer>().sharedMaterial = material; }
void Start() { dfUnity = DaggerfallUnity.Instance; reflectionTexturesScript = GameObject.Find("ReflectionsMod").GetComponent<UpdateReflectionTextures>(); if (!streamingWorld) streamingWorld = GameObject.Find("StreamingWorld").GetComponent<StreamingWorld>(); if (!streamingWorld) { DaggerfallUnity.LogMessage("InjectReflectiveMaterialProperty: Missing StreamingWorld reference.", true); if (Application.isEditor) Debug.Break(); else Application.Quit(); } gameObjectReflectionPlaneGroundLevel = GameObject.Find("ReflectionPlaneBottom"); gameObjectReflectionPlaneSeaLevel = GameObject.Find("ReflectionPlaneSeaLevel"); gameObjectReflectionPlaneLowerLevel = gameObjectReflectionPlaneSeaLevel; // get inactive gameobject StreamingTarget (just GameObject.Find() would fail to find inactive gameobjects) GameObject[] gameObjects = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject currentGameObject in gameObjects) { string objectPathInHierarchy = GetGameObjectPath(currentGameObject); if (objectPathInHierarchy == "/Exterior/StreamingTarget") { gameObjectStreamingTarget = currentGameObject; } } iniData = getIniParserConfigInjectionTextures(); }
/// <summary> /// Performs a fully standalone in-place location layout. /// This method is used only by editor layouts, not by streaming world. /// </summary> private void LayoutLocation(ref DFLocation location) { #if SHOW_LAYOUT_TIMES // Start timing System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); long startTime = stopwatch.ElapsedMilliseconds; #endif // Get city dimensions int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; // Create billboard batch game objects for this location //TextureAtlasBuilder miscBillboardAtlas = null; summary.NatureBillboardBatch = null; DaggerfallBillboardBatch lightsBillboardBatch = null; DaggerfallBillboardBatch animalsBillboardBatch = null; //DaggerfallBillboardBatch miscBillboardBatch = null; if (dfUnity.Option_BatchBillboards) { //miscBillboardAtlas = dfUnity.MaterialReader.MiscBillboardAtlas; int natureArchive = ClimateSwaps.GetNatureArchive(CurrentNatureSet, CurrentSeason); summary.NatureBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(natureArchive, transform); lightsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.LightsTextureArchive, transform); animalsBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(TextureReader.AnimalsTextureArchive, transform); //miscBillboardBatch = GameObjectHelper.CreateBillboardBatchGameObject(miscBillboardAtlas.AtlasMaterial, transform); } // Import blocks for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (dfUnity.Option_BatchBillboards) { // Set block origin for billboard batches // This causes next additions to be offset by this position Vector3 blockOrigin = new Vector3((x * RMBLayout.RMBSide), 0, (y * RMBLayout.RMBSide)); summary.NatureBillboardBatch.BlockOrigin = blockOrigin; lightsBillboardBatch.BlockOrigin = blockOrigin; animalsBillboardBatch.BlockOrigin = blockOrigin; //miscBillboardBatch.BlockOrigin = blockOrigin; } string blockName = dfUnity.ContentReader.BlockFileReader.CheckName(dfUnity.ContentReader.MapFileReader.GetRmbBlockName(ref location, x, y)); GameObject go = GameObjectHelper.CreateRMBBlockGameObject( blockName, x, y, dfUnity.Option_RMBGroundPlane, dfUnity.Option_CityBlockPrefab, summary.NatureBillboardBatch, lightsBillboardBatch, animalsBillboardBatch, null, //miscBillboardAtlas, null, //miscBillboardBatch, CurrentNatureSet, CurrentSeason); go.transform.parent = this.transform; go.transform.position = new Vector3((x * RMBLayout.RMBSide), 0, (y * RMBLayout.RMBSide)); } } // Apply batches if (summary.NatureBillboardBatch) { summary.NatureBillboardBatch.Apply(); } if (lightsBillboardBatch) { lightsBillboardBatch.Apply(); } if (animalsBillboardBatch) { animalsBillboardBatch.Apply(); } //if (miscBillboardBatch) miscBillboardBatch.Apply(); // Enumerate start marker game objects EnumerateStartMarkers(); #if SHOW_LAYOUT_TIMES // Show timer long totalTime = stopwatch.ElapsedMilliseconds - startTime; DaggerfallUnity.LogMessage(string.Format("Time to layout location: {0}ms", totalTime), true); #endif }
bool IsReady() { if (!dfUnity) { dfUnity = DaggerfallUnity.Instance; } if (itemHelper == null) { itemHelper = new ItemHelper(); } if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) { return(false); } if (factionFile == null) { factionFile = new FactionFile(dfUnity.ContentReader.GetFactionFilePath(), FileUsage.UseMemory, true); } if (saveGames == null || saveTrees == null || saveNames == null) { saveGames = new SaveGames(); saveNames = new GUIContent[6]; saveTrees = new SaveTree[6]; saveVars = new SaveVars[6]; saveTextures = new Texture2D[6]; if (saveGames.OpenSavesPath(Path.GetDirectoryName(DaggerfallUnity.Instance.Arena2Path))) { for (int i = 0; i < 6; i++) { if (saveGames.HasSave(i)) { saveGames.OpenSave(i, false); saveTrees[i] = saveGames.SaveTree; saveVars[i] = saveGames.SaveVars; saveNames[i] = new GUIContent(saveGames.SaveName); saveTextures[i] = TextureReader.CreateFromAPIImage(saveGames.SaveImage); saveTextures[i].filterMode = FilterMode.Point; } else { saveTrees[i] = null; saveVars[i] = null; saveTextures[i] = null; saveNames[i] = new GUIContent("Empty"); } } } // Prevent duplicate names so save games aren't automatically removed from the Save Select GUI for (int i = 0; i < saveNames.Length; i++) { int duplicateCount = 0; for (int j = i + 1; j < saveNames.Length; j++) { if (saveNames[j].text == saveNames[i].text) { bool unique = false; while (!unique) { unique = true; string replaceText = saveNames[j].text + "(" + ++duplicateCount + ")"; for (int k = 0; k < saveNames.Length; k++) { if (saveNames[k].text == replaceText) { unique = false; break; } } if (unique) { saveNames[j].text = replaceText; } } } } } } return(true); }
//void ShowUnknownGUI() //{ // EditorGUILayout.Space(); // showUnknownFoldout = GUILayoutHelper.Foldout(showUnknownFoldout, new GUIContent("Unknown"), () => // { // EditorGUILayout.Space(); // GUILayoutHelper.Indent(() => // { // EditorGUILayout.LabelField("Unknown1 [1 Bytes]"); // EditorGUILayout.SelectableLabel(selectedCareer.RawData.Unknown1.ToString("X2"), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); // }); // GUILayoutHelper.Indent(() => // { // EditorGUILayout.LabelField("Unknown2 [8 Bytes]"); // string valuesString = string.Empty; // for (int i = 0; i < selectedCareer.RawData.Unknown2.Length; i++) // { // valuesString += selectedCareer.RawData.Unknown2[i].ToString("X2") + " "; // } // EditorGUILayout.SelectableLabel(valuesString, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); // }); // }); //} bool IsReady() { dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) return false; // Read all CLASS*.CFG files if (classTemplates == null) { string[] files = Directory.GetFiles(dfUnity.Arena2Path, "class*.cfg"); if (files != null && files.Length > 0) { classTemplates = new DFCareer[files.Length - 1]; classNames = new GUIContent[files.Length - 1]; for (int i = 0; i < files.Length - 1; i++) { ClassFile classFile = new ClassFile(files[i]); classTemplates[i] = classFile.Career; classNames[i] = new GUIContent(classTemplates[i].Name); } } } // Read all ENEMY*.CFG files if (monsterTemplates == null) { MonsterFile monsterFile = new MonsterFile(); if (monsterFile.Load(Path.Combine(dfUnity.Arena2Path, MonsterFile.Filename), FileUsage.UseMemory, true)) { // First pass locates CFG record indices List<int> cfgIndices = new List<int>(); for (int i = 0; i < monsterFile.Count; i++) { string recordName = monsterFile.GetRecordName(i); if (recordName.EndsWith(".cfg", StringComparison.InvariantCultureIgnoreCase)) cfgIndices.Add(i); } // Second pass populates arrays monsterTemplates = new DFCareer[cfgIndices.Count]; monsterNames = new GUIContent[cfgIndices.Count]; for (int i = 0; i < cfgIndices.Count; i++) { // Read ENEMY.CFG class file from stream ClassFile classFile = new ClassFile(); byte[] data = monsterFile.GetRecordBytes(cfgIndices[i]); MemoryStream stream = new MemoryStream(data); BinaryReader reader = new BinaryReader(stream); classFile.Load(reader); reader.Close(); // Add to arrays monsterTemplates[i] = classFile.Career; monsterNames[i] = new GUIContent(monsterTemplates[i].Name); } } else { return false; } } return true; }
/// <summary> /// Creates mesh and material for this enemy. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index derived from type and gender.</param> private void AssignMeshAndMaterial(DaggerfallUnity dfUnity, int archive) { // Get mesh filter if (meshFilter == null) { meshFilter = GetComponent <MeshFilter>(); } // Vertices for a 1x1 unit quad // This is scaled to correct size depending on facing and orientation float hx = 0.5f, hy = 0.5f; Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(hx, hy, 0); vertices[1] = new Vector3(-hx, hy, 0); vertices[2] = new Vector3(hx, -hy, 0); vertices[3] = new Vector3(-hx, -hy, 0); // Indices int[] indices = new int[6] { 0, 1, 2, 3, 2, 1, }; // Normals Vector3 normal = Vector3.Normalize(Vector3.up + Vector3.forward); Vector3[] normals = new Vector3[4]; normals[0] = normal; normals[1] = normal; normals[2] = normal; normals[3] = normal; // Create mesh Mesh mesh = new Mesh(); mesh.name = string.Format("MobileEnemyMesh"); mesh.vertices = vertices; mesh.triangles = indices; mesh.normals = normals; // Assign mesh meshFilter.sharedMesh = mesh; // Load material atlas Material material = dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 1024, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false, true); // Set new enemy material GetComponent <MeshRenderer>().sharedMaterial = material; }
private void SetupSingleton() { if (instance == null) instance = this; else if (instance != this) { if (Application.isPlaying) { LogMessage("Multiple DaggerfallUnity instances detected in scene!", true); Destroy(gameObject); } } }
void Start() { dfUnity = DaggerfallUnity.Instance; // Try to find local player GPS if not set if (LocalPlayerGPS == null) { GameObject player = GameObject.FindGameObjectWithTag("Player"); if (player) { LocalPlayerGPS = player.GetComponent<PlayerGPS>(); } } // Find main camera gameobject GameObject go = GameObject.FindGameObjectWithTag("MainCamera"); if (go) { mainCamera = go.GetComponent<Camera>(); } // Check main camera component if (!mainCamera) { DaggerfallUnity.LogMessage("DaggerfallSky could not find MainCamera object. Disabling sky.", true); gameObject.SetActive(false); return; } // Save starting clear flags initialClearFlags = mainCamera.clearFlags; // Get my camera myCamera = GetComponent<Camera>(); if (!myCamera) { DaggerfallUnity.LogMessage("DaggerfallSky could not find local camera. Disabling sky.", true); gameObject.SetActive(false); return; } // My camera must not be on the same GameObject as MainCamera if (myCamera == mainCamera) { DaggerfallUnity.LogMessage("DaggerfallSky must not be attached to same GameObject as MainCamera. Disabling sky.", true); gameObject.SetActive(false); return; } // Setup cameras SetupCameras(); }
/// <summary> /// Add interior flats. /// </summary> private void AddFlats(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject("Interior Flats"); node.transform.parent = this.transform; // Add block flats markers.Clear(); foreach (DFBlock.RmbBlockFlatObjectRecord obj in recordData.Interior.BlockFlatObjectRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import custom 3d gameobject instead of flat if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add editor markers to list if (obj.TextureArchive == TextureReader.EditorFlatsTextureArchive) { InteriorEditorMarker marker = new InteriorEditorMarker(); marker.type = (InteriorMarkerTypes)obj.TextureRecord; marker.gameObject = go; markers.Add(marker); // Add loot containers for treasure markers for TG, DB & taverns (uses pile of clothes icon) if (marker.type == InteriorMarkerTypes.Treasure && (buildingData.buildingType == DFLocation.BuildingTypes.Tavern || buildingData.factionID == ThievesGuild.FactionId || buildingData.factionID == DarkBrotherhood.FactionId)) { // Create unique LoadID for save system, using 9 lsb and the sign bit from each coord pos int ulong loadID = ((ulong)buildingData.buildingKey) << 30 | (uint)(obj.XPos << 1 & posMask) << 20 | (uint)(obj.YPos << 1 & posMask) << 10 | (uint)(obj.ZPos << 1 & posMask); DaggerfallLoot loot = GameObjectHelper.CreateLootContainer( LootContainerTypes.RandomTreasure, InventoryContainerImages.Chest, billboardPosition, node.transform, DaggerfallLootDataTables.clothingArchive, 0, loadID); if (!LootTables.GenerateLoot(loot, (int)GameManager.Instance.PlayerGPS.CurrentLocationType)) { DaggerfallUnity.LogMessage(string.Format("DaggerfallInterior: Location type {0} is out of range or unknown.", GameManager.Instance.PlayerGPS.CurrentLocationType), true); } } } // Add point lights if (obj.TextureArchive == TextureReader.LightsTextureArchive) { AddLight(obj, go.transform); } } }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path)) return false; if (saveGames == null || saveTrees == null || saveNames == null) { saveGames = new SaveGames(); saveNames = new GUIContent[6]; saveTrees = new SaveTree[6]; saveTextures = new Texture2D[6]; if (saveGames.OpenSavesPath(Path.GetDirectoryName(DaggerfallUnity.Instance.Arena2Path))) { for (int i = 0; i < 6; i++) { if (saveGames.HasSave(i)) { saveGames.OpenSave(i); saveTrees[i] = saveGames.SaveTree; saveNames[i] = new GUIContent(saveGames.SaveName); saveTextures[i] = TextureReader.CreateFromAPIImage(saveGames.SaveImage); saveTextures[i].filterMode = FilterMode.Point; } else { saveTrees[i] = null; saveTextures[i] = null; saveNames[i] = new GUIContent("Empty"); } } } } return true; }
/// <summary> /// Updates enemy state based on current settings. /// Called automatially by SetEnemyType(). /// This should be called after changing enemy state (e.g. from in code or in editor). /// </summary> private void ApplyEnemyState() { // Get state animations summary.StateAnims = GetStateAnims(summary.EnemyState); if (summary.EnemyState == MobileStates.PrimaryAttack) { int random = UnityEngine.Random.Range(1, 101); if (random <= summary.Enemy.ChanceForAttack2) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames2; } else { random -= summary.Enemy.ChanceForAttack2; if (random <= summary.Enemy.ChanceForAttack3) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames3; } else { random -= summary.Enemy.ChanceForAttack3; if (random <= summary.Enemy.ChanceForAttack4) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames4; } else { random -= summary.Enemy.ChanceForAttack4; if (random <= summary.Enemy.ChanceForAttack5) { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames5; } else { summary.StateAnimFrames = summary.Enemy.PrimaryAttackAnimFrames; } } } } // Set to the first frame of this animation, and prepare frameIterator to start from the second frame when AnimateEnemy() next runs currentFrame = summary.StateAnimFrames[0]; frameIterator = 1; } if (summary.EnemyState == MobileStates.RangedAttack1 || summary.EnemyState == MobileStates.RangedAttack2) { summary.StateAnimFrames = summary.Enemy.RangedAttackAnimFrames; // Set to the first frame of this animation, and prepare frameIterator to start from the second frame when AnimateEnemy() next runs currentFrame = summary.StateAnimFrames[0]; frameIterator = 1; } if (summary.StateAnims == null) { // Log error message DaggerfallUnity.LogMessage(string.Format("DaggerfalMobileUnit: Enemy does not have animation for {0} state. Defaulting to Idle state.", summary.EnemyState.ToString()), true); // Set back to idle (which every enemy has in one form or another) summary.EnemyState = MobileStates.Idle; summary.StateAnims = GetStateAnims(summary.EnemyState); } // Orient enemy relative to camera UpdateOrientation(); }
/// <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; }
void SetupControl() { dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return; // Load highlight texture ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, highlightImgName), FileUsage.UseMemory, true); imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName)); highlightTexture = TextureReader.CreateFromAPIImage(imgFile, 0, 0, 0); highlightTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; // Add buttons Vector2 buttonPos = new Vector2(0, 0); Vector2 buttonSize = new Vector2(66, 9); for (int i = 0; i < 5; i++) { selectButtons[i] = new Button(); this.Components.Add(selectButtons[i]); selectButtons[i].Position = buttonPos; selectButtons[i].Size = buttonSize; selectButtons[i].Tag = i; selectButtons[i].OnMouseClick += ReflexButton_OnMouseClick; buttonPos.y += buttonSize.y; } // Set size of this panel Size = new Vector2(66, 45); // Set starting value PlayerReflexes = PlayerReflexes.Average; }
private bool ReadyCheck() { if (suppressWorld) return false; if (isReady) return true; if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; } if (LocalPlayerGPS == null) return false; else InitWorld(); // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("StreamingWorld: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } // Perform initial runtime setup if (Application.isPlaying) { // Fix coastal climate data TerrainHelper.DilateCoastalClimate(dfUnity.ContentReader, 2); // Smooth steep location on steep gradients TerrainHelper.SmoothLocationNeighbourhood(dfUnity.ContentReader); } // Raise ready flag isReady = true; RaiseOnReadyEvent(); return true; }
private bool ReadyCheck() { // Ensure we have a DaggerfallUnity reference if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; } // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("MaterialReader: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } // Ensure texture reader is ready if (textureReader == null) { textureReader = new TextureReader(dfUnity.Arena2Path); } return true; }
bool IsReady() { if (!dfUnity) dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return false; return true; }
private bool ReadyCheck() { // Ensure we have a DaggerfallUnity reference if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; } // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("SoundReader: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } // Ensure sound reader is ready if (soundFile == null) { soundFile = new SndFile(Path.Combine(dfUnity.Arena2Path, SndFile.Filename), FileUsage.UseMemory, true); } return true; }
void Start() { // Reference components dfUnity = DaggerfallUnity.Instance; mainCamera = Camera.main; // Adjust scale based on resolution // You can plug in your own UI scaling here instead if (Screen.currentResolution.height >= 1080 && Screen.currentResolution.height < 1440) scale = 3; if (Screen.currentResolution.height >= 1440) scale = 4; }
private bool ReadyCheck() { if (ready) return true; // Ensure we have a DaggerfallUnity reference if (dfUnity == null) { dfUnity = DaggerfallUnity.Instance; } // Do nothing if DaggerfallUnity not ready if (!dfUnity.IsReady) { DaggerfallUnity.LogMessage("DaggerfallTerrain: DaggerfallUnity component is not ready. Have you set your Arena2 path?"); return false; } // Raise ready flag ready = true; return true; }
/// <summary> /// Creates mesh and material for this enemy. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index derived from type and gender.</param> private void AssignMeshAndMaterial(DaggerfallUnity dfUnity, int archive) { // Get mesh filter if (meshFilter == null) { meshFilter = GetComponent <MeshFilter>(); } // Vertices for a 1x1 unit quad // This is scaled to correct size depending on facing and orientation float hx = 0.5f, hy = 0.5f; Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(hx, hy, 0); vertices[1] = new Vector3(-hx, hy, 0); vertices[2] = new Vector3(hx, -hy, 0); vertices[3] = new Vector3(-hx, -hy, 0); // Indices int[] indices = new int[6] { 0, 1, 2, 3, 2, 1, }; // Normals Vector3 normal = Vector3.Normalize(Vector3.up + Vector3.forward); Vector3[] normals = new Vector3[4]; normals[0] = normal; normals[1] = normal; normals[2] = normal; normals[3] = normal; // Create mesh Mesh mesh = new Mesh(); mesh.name = string.Format("MobileEnemyMesh"); mesh.vertices = vertices; mesh.triangles = indices; mesh.normals = normals; // Assign mesh meshFilter.sharedMesh = mesh; // Create material Material material = TextureReplacement.GetMobileBillboardMaterial(archive, GetComponent <MeshFilter>(), ref summary.ImportedTextures) ?? dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 1024, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false, true); // Update cached record values in case of non-classic texture if (summary.RecordSizes == null || summary.RecordSizes.Length == 0) { if (summary.ImportedTextures.Albedo != null && summary.ImportedTextures.Albedo.Length > 0) { int recordCount = summary.ImportedTextures.Albedo.Length; // Cache size and scale for each record summary.RecordSizes = new Vector2[recordCount]; summary.RecordFrames = new int[recordCount]; for (int i = 0; i < recordCount; i++) { // Get size and scale of this texture Texture2D firstFrame = summary.ImportedTextures.Albedo[i][0]; Vector2 size = new Vector2(firstFrame.width, firstFrame.height); // Set optional scale TextureReplacement.SetBillboardScale(archive, i, ref size); // Store final size and frame count summary.RecordSizes[i] = size * MeshReader.GlobalScale; summary.RecordFrames[i] = summary.ImportedTextures.Albedo[i].Length; } } else { Debug.LogError($"Texture archive {archive} has no valid records"); } } // Set new enemy material GetComponent <MeshRenderer>().sharedMaterial = material; }