//##Lypyl /// <summary> /// Get distance between 2 world points represented by DFPosition objects /// Returns -1 on error /// </summary> public double Distance(DFPosition pos) { double dist = -1; try { dist = Math.Sqrt(Math.Pow(Math.Abs(X - pos.X), 2) + Math.Pow(Math.Abs(Y - pos.Y), 2)); } catch (Exception ex) { DaggerfallWorkshop.DaggerfallUnity.LogMessage(ex.Message, true); } return dist; }
void CreateCrossHair(DFPosition pos, int regionIndex = -1) { if (regionIndex == -1) regionIndex = GetPlayerRegion(); CreateCrossHair(pos.X, pos.Y, regionIndex); }
// Teleports player to a random location in a random region IEnumerator TeleportRandomLocation() { if (!CanTeleport()) yield break; // Find a random location UnityEngine.Random.seed = UnityEngine.Time.renderedFrameCount; DFPosition mapPos = new DFPosition(); bool found = false; while (!found) { // Get random region int regionIndex = UnityEngine.Random.Range(0, dfUnity.ContentReader.MapFileReader.RegionCount); DFRegion region = dfUnity.ContentReader.MapFileReader.GetRegion(regionIndex); if (region.LocationCount == 0) continue; // Get random location int locationIndex = UnityEngine.Random.Range(0, region.MapTable.Length); DFLocation location = dfUnity.ContentReader.MapFileReader.GetLocation(regionIndex, locationIndex); if (!location.Loaded) continue; // Check inside range mapPos = MapsFile.LongitudeLatitudeToMapPixel((int)location.MapTableData.Longitude, (int)location.MapTableData.Latitude); if ((mapPos.X >= TerrainHelper.minMapPixelX + 2 && mapPos.X < TerrainHelper.maxMapPixelX - 2) && (mapPos.Y >= TerrainHelper.minMapPixelY + 2 && mapPos.Y < TerrainHelper.maxMapPixelY - 2)) { found = true; } } // Teleport if (titleScreen) titleScreen.ShowTitle = true; yield return new WaitForEndOfFrame(); streamingWorld.TeleportToCoordinates(mapPos.X, mapPos.Y); }
//overloaded variant void InjectMaterialProperties(DFPosition worldPos) { InjectMaterialProperties(worldPos.X, worldPos.Y); }
protected virtual void RaiseOnMapPixelChangedEvent(DFPosition mapPixel) { if (OnMapPixelChanged != null) OnMapPixelChanged(mapPixel); }
bool CheckPosition() { DFPosition mapPixel = StreamingWorld.LocalPlayerGPS.CurrentMapPixel; if (mapPixel.X != currentMapPixel.X || mapPixel.Y != currentMapPixel.Y) { lastMapPixel = currentMapPixel; currentMapPixel = mapPixel; return true; } return false; }
// Start new character to location specified in INI void StartNewCharacter() { DaggerfallUI.Instance.PopToHUD(); // Assign character sheet PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterSheet); // Set game time DaggerfallUnity.Instance.WorldTime.Now.SetClassicGameStartTime(); // Get start parameters DFPosition mapPixel = new DFPosition(DaggerfallUnity.Settings.StartCellX, DaggerfallUnity.Settings.StartCellY); bool startInDungeon = DaggerfallUnity.Settings.StartInDungeon; // Read location if any DFLocation location = new DFLocation(); ContentReader.MapSummary mapSummary; bool hasLocation = DaggerfallUnity.Instance.ContentReader.HasLocation(mapPixel.X, mapPixel.Y, out mapSummary); if (hasLocation) { if (!DaggerfallUnity.Instance.ContentReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex, out location)) hasLocation = false; } // Start at specified location StreamingWorld streamingWorld = FindStreamingWorld(); if (hasLocation && startInDungeon && location.HasDungeon) { if (streamingWorld) { streamingWorld.TeleportToCoordinates(mapPixel.X, mapPixel.Y); streamingWorld.suppressWorld = true; } playerEnterExit.EnableDungeonParent(); playerEnterExit.StartDungeonInterior(location); } else { playerEnterExit.EnableExteriorParent(); if (streamingWorld) { streamingWorld.SetAutoReposition(StreamingWorld.RepositionMethods.Origin, Vector3.zero); streamingWorld.suppressWorld = false; } } // Start game GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); }
/// <summary> /// Converts world coord back to longitude and latitude. /// </summary> /// <param name="worldX">World X position in native Daggerfall units.</param> /// <param name="worldZ">World Z position in native Daggerfall units.</param> /// <returns>Longitude and latitude.</returns> public static DFPosition WorldCoordToLongitudeLatitude(int worldX, int worldZ) { DFPosition mapPixel = WorldCoordToMapPixel(worldX, worldZ); DFPosition pos = new DFPosition(); pos.X = mapPixel.X * 128; pos.Y = (499 - mapPixel.Y) * 128; return pos; }
// Determines tile origin of location inside terrain area. // This is not always centred precisely but rather seems to follow some other // logic/formula for locations of certain RMB dimensions (e.g. 1x1). // Unknown if there are more exceptions or if a specific formula is needed. // This method will be used in the interim pending further research. public static DFPosition GetLocationTerrainTileOrigin(int width, int height) { DFPosition result = new DFPosition(); result.X = (RMBLayout.RMBTilesPerTerrain - width * RMBLayout.RMBTilesPerBlock) / 2; result.Y = (RMBLayout.RMBTilesPerTerrain - height * RMBLayout.RMBTilesPerBlock) / 2; // 1x1 locations seem to always use 72, 55 as origin rather than 56, 56 as expected if (width == 1 && height == 1) { result.X = 72; result.Y = 55; } return result; }
// Determines tile origin of location inside terrain area. // This is not always centred precisely but rather seems to follow some other // logic/formula for locations of certain RMB dimensions (e.g. 1x1). // Unknown if there are more exceptions or if a specific formula is needed. // This method will be used in the interim pending further research. public static DFPosition GetLocationTerrainTileOrigin(DFLocation location) { // Get map width and height int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; // Centring works nearly all the time DFPosition result = new DFPosition(); result.X = (RMBLayout.RMBTilesPerTerrain - width * RMBLayout.RMBTilesPerBlock) / 2; result.Y = (RMBLayout.RMBTilesPerTerrain - height * RMBLayout.RMBTilesPerBlock) / 2; // But some 1x1 locations (e.g. Privateer's Hold exterior) are positioned differently // Seems to be 1x1 blocks using CUST prefix, but possibly more research needed const int custPrefixIndex = 40; if (width == 1 && height == 1) { if (location.Exterior.ExteriorData.BlockIndex[0] == custPrefixIndex) { result.X = 72; result.Y = 55; } } return result; }
void UpdateWorldTerrain(DFPosition worldPos) { if (worldTerrainGameObject != null) // sometimes it can happen that this point is reached before worldTerrainGameObject was created, in such case we just skip { // do not forget to update shader parameters (needed for correct fragment discarding for terrain tiles of map pixels inside TerrainDistance-1 area (the detailed terrain)) Terrain terrain = worldTerrainGameObject.GetComponent<Terrain>(); terrain.materialTemplate.SetInt("_PlayerPosX", this.playerGPS.CurrentMapPixel.X); terrain.materialTemplate.SetInt("_PlayerPosY", this.playerGPS.CurrentMapPixel.Y); Vector3 offset = new Vector3(0.0f, 0.0f, 0.0f); updatePositionWorldTerrain(ref worldTerrainGameObject, offset); bool doSeasonalTexturesUpdate = shouldUpdateSeasonalTextures(); if (doSeasonalTexturesUpdate) { Material mat = terrain.materialTemplate; updateMaterialSeasonalTextures(ref mat, currentSeason); // this is necessary since climate changes may occur after UpdateWorldTerrain() has been invoked, TODO: an event would be ideal to trigger updateSeasonalTextures() instead terrain.materialTemplate = mat; } // make terrain transition ring update on next iteration in Update() as soon as no terrain transition ring update is still in progress updateTerrainTransitionRing = true; if (doSeasonalTexturesUpdate) { //updateSeasonalTexturesTerrainTransitionRing(); terrainTransitionRingUpdateSeasonalTextures = true; } Resources.UnloadUnusedAssets(); //System.GC.Collect(); } }
//player teleporting /// <summary> /// Updates enhanced sky objects /// </summary> /// <param name="worldPos"></param> public void EnhancedSkyUpdate(DFPosition worldPos) { //Debug.Log("EnhancedSkyUpdate"); if (updateSkyEvent != null && SkyManager.instance.EnhancedSkyCurrentToggle) //only trigger if eSky on { //Debug.Log("triggering fastTravelEvent"); updateSkyEvent(IsOvercast); } }
//// Find location by name //bool FindLocation(string name, out DFRegion.RegionMapTable locationInfo) //{ // locationInfo = new DFRegion.RegionMapTable(); // if (string.IsNullOrEmpty(name)) // { // return false; // } // string[] locations = regionRecord.Region.MapNames.OrderBy(p => p).ToArray(); // name = name.ToLower(); // for (int i = 0; i < locations.Count(); i++) // { // if (locations[i].ToLower().StartsWith(name)) // Valid location found, // { // if (!regionRecord.Region.MapNameLookup.ContainsKey(locations[i])) // { // DaggerfallUnity.LogMessage("Error: location name key not found in Region MapNameLookup dictionary"); // return false; // } // int index = regionRecord.Region.MapNameLookup[locations[i]]; // locationInfo = regionRecord.Region.MapTable[index]; // return true; // } // else if (locations[i][0] > name[0]) // { // return false; // } // } // return false; //} // Teleports player to position void TravelToLocation(DFPosition pos) { TravelToLocation(pos.X, pos.Y); }
// Gets current player position in map pixels DFPosition GetPlayerMapPosition() { DFPosition position = new DFPosition(); PlayerGPS playerGPS = GameManager.Instance.PlayerGPS; if (playerGPS) position = playerGPS.CurrentMapPixel; return position; }
// Init world at startup or when player teleports private void InitWorld(bool repositionPlayer = false) { // Cannot init world without a player, as world positions around player if (LocalPlayerGPS == null) return; // Player must be at origin on init for proper world sync // Starting position will be assigned when terrain ready LocalPlayerGPS.transform.position = Vector3.zero; // Init streaming world ClearStreamingWorld(); worldCompensation = Vector3.zero; mapOrigin = LocalPlayerGPS.CurrentMapPixel; MapPixelX = mapOrigin.X; MapPixelY = mapOrigin.Y; playerStartPos = new Vector3(LocalPlayerGPS.transform.position.x, 0, LocalPlayerGPS.transform.position.z); lastPlayerPos = playerStartPos; // This value is the amount of scene player movement equivalent to 1 native world map unit sceneMapRatio = 1f / MeshReader.GlobalScale; // Set player world position to match PlayerGPS // StreamingWorld will then sync player to world worldX = LocalPlayerGPS.WorldX; worldZ = LocalPlayerGPS.WorldZ; init = true; this.repositionPlayer = repositionPlayer; RaiseOnInitWorldEvent(); }
/// <summary> /// Converts map pixel coord to longitude and latitude. /// </summary> /// <param name="mapPixelX">Map pixel X.</param> /// <param name="mapPixelY">Map pixel Y.</param> /// <returns></returns> public static DFPosition MapPixelToLongitudeLatitude(int mapPixelX, int mapPixelY) { DFPosition pos = new DFPosition(); pos.X = mapPixelX * 128; pos.Y = (499 - mapPixelY) * 128; return pos; }
/// <summary> /// Converts map pixel to world coord. /// </summary> /// <param name="worldX">Map pixel X.</param> /// <param name="worldZ">Map pixel Y.</param> /// <returns>World position.</returns> public static DFPosition MapPixelToWorldCoord(int mapPixelX, int mapPixelY) { DFPosition pos = new DFPosition(); pos.X = mapPixelX * 32768; pos.Y = (499 - mapPixelY) * 32768; return pos; }
/// <summary> /// Returns terrain GameObject from mapPixel, or null if /// no terrain objects are mapped to that pixel /// </summary> public GameObject GetTerrainFromPixel(DFPosition mapPixel) { return GetTerrainFromPixel(mapPixel.X, mapPixel.Y); }
/// <summary> /// Converts world coord to nearest map pixel. /// </summary> /// <param name="worldX">World X position in native Daggerfall units.</param> /// <param name="worldZ">World Z position in native Daggerfall units.</param> /// <returns>Map pixel position.</returns> public static DFPosition WorldCoordToMapPixel(int worldX, int worldZ) { DFPosition pos = new DFPosition(); pos.X = worldX / 32768; pos.Y = 499 - (worldZ / 32768); return pos; }
protected virtual void RaiseOnTeleportToCoordinatesEvent(DFPosition worldPos) { if (OnTeleportToCoordinates != null) OnTeleportToCoordinates(worldPos); }
// Copies a subset of Color32 array into XY position of another Color32 array public static void CopyColors(ref Color32[] src, ref Color32[] dst, DFSize srcSize, DFSize dstSize, DFPosition srcPos, DFPosition dstPos, DFSize copySize) { for (int y = 0; y < copySize.Height; y++) { for (int x = 0; x < copySize.Width; x++) { Color32 col = src[(srcPos.Y + y) * srcSize.Width + (srcPos.X + x)]; dst[(dstPos.Y + y) * dstSize.Width + (dstPos.X + x)] = col; } } }
// Init world at startup or when player teleports private void InitWorld() { // Cannot init world without a player, as world positions around player // Also do nothing if world is on hold at start if (LocalPlayerGPS == null || suppressWorld) return; // Player must be at origin on init for proper world sync // Starting position will be assigned when terrain ready based on respositionMethod LocalPlayerGPS.transform.position = Vector3.zero; // Raise OnPreInitWorld event RaiseOnPreInitWorldEvent(); // Init streaming world ClearStreamingWorld(); worldCompensation = Vector3.zero; mapOrigin = LocalPlayerGPS.CurrentMapPixel; MapPixelX = mapOrigin.X; MapPixelY = mapOrigin.Y; playerStartPos = new Vector3(LocalPlayerGPS.transform.position.x, 0, LocalPlayerGPS.transform.position.z); lastPlayerPos = playerStartPos; // Set player world position to match PlayerGPS // StreamingWorld will then sync player to world worldX = LocalPlayerGPS.WorldX; worldZ = LocalPlayerGPS.WorldZ; init = true; RaiseOnInitWorldEvent(); }
void Initialize() { playerMotor.ClearActivePlatform(); DFPosition mapPixel = StreamingWorld.LocalPlayerGPS.CurrentMapPixel; currentMapPixel = mapPixel; lastMapPixel = mapPixel; }
//Gets path from player location to destination void GetPath(DFPosition endPos) { Vector2[] directions = new Vector2[] { new Vector2(0, 1), new Vector2(1, 0), new Vector2(0, -1), new Vector2(-1, 0), new Vector2(1, 1), new Vector2(-1, 1), new Vector2(1, -1), new Vector2(-1, -1) }; //Vector2[] directions = new Vector2[] { new Vector2(0, 1), new Vector2(1, 0), new Vector2(0, -1), new Vector2(-1, 0)}; //4 direction movement Vector2 current = new Vector2(GameManager.Instance.PlayerGPS.CurrentMapPixel.X, GameManager.Instance.PlayerGPS.CurrentMapPixel.Y); Vector2 end = new Vector2(endPos.X, endPos.Y); terrains.Clear(); while(current != end) { float distance = Vector2.Distance(current,end); int selection = 0; for (int i = 0; i < directions.Length; i++) { Vector2 next = current + directions[i]; if (current.x < 0 || current.y < 0 || current.x >= DaggerfallConnect.Arena2.MapsFile.MaxMapPixelX || current.y >= DaggerfallConnect.Arena2.MapsFile.MaxMapPixelY) continue; float check = Vector2.Distance(next, end); if(check < distance) { distance = check; selection = i; } } current += directions[selection]; terrains.Add((TerrainTypes)DaggerfallUnity.Instance.ContentReader.MapFileReader.GetClimateIndex((int)current.x, (int)current.y)); } }
// Calculate location rect in world units private void CalculateWorldLocationRect() { if (!hasCurrentLocation) return; // Convert world coords to map pixel coords then back again // This finds the SW origin of this map pixel in world coords DFPosition mapPixel = CurrentMapPixel; DFPosition worldOrigin = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y); // Calculate centre point of this terrain area in world coords DFPosition centrePoint = new DFPosition( worldOrigin.X + (int)MapsFile.WorldMapTerrainDim / 2, worldOrigin.Y + (int)MapsFile.WorldMapTerrainDim / 2); // Get width and height of location in world units int width = currentLocation.Exterior.ExteriorData.Width * (int)MapsFile.WorldMapRMBDim; int height = currentLocation.Exterior.ExteriorData.Height * (int)MapsFile.WorldMapRMBDim; // Set true location rect in world coordinates locationWorldRectMinX = centrePoint.X - width / 2; locationWorldRectMaxX = centrePoint.X + width / 2; locationWorldRectMinZ = centrePoint.Y - height / 2; locationWorldRectMaxZ = centrePoint.Y + height / 2; }
public static Texture2D GetTextureFromCifRci(string name, int record, out DFPosition offset, int frame = 0, TextureFormat format = TextureFormat.ARGB32) { offset = new DFPosition(); DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return null; CifRciFile cifRciFile = new CifRciFile(Path.Combine(dfUnity.Arena2Path, name), FileUsage.UseMemory, true); cifRciFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, cifRciFile.PaletteName)); DFBitmap bitmap = cifRciFile.GetDFBitmap(record, frame); Texture2D texture = new Texture2D(bitmap.Width, bitmap.Height, format, false); texture.SetPixels32(cifRciFile.GetColor32(bitmap, 0)); texture.Apply(false, true); texture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; offset = cifRciFile.GetOffset(record); return texture; }
// Start new character to location specified in INI void StartNewCharacter() { DaggerfallUnity.ResetUID(); RaiseOnNewGameEvent(); DaggerfallUI.Instance.PopToHUD(); ResetWeaponManager(); // Must have a character document if (characterDocument == null) characterDocument = new CharacterDocument(); // Assign character sheet PlayerEntity playerEntity = FindPlayerEntity(); playerEntity.AssignCharacter(characterDocument); // Set game time DaggerfallUnity.Instance.WorldTime.Now.SetClassicGameStartTime(); // Get start parameters DFPosition mapPixel = new DFPosition(DaggerfallUnity.Settings.StartCellX, DaggerfallUnity.Settings.StartCellY); bool startInDungeon = DaggerfallUnity.Settings.StartInDungeon; // Read location if any DFLocation location = new DFLocation(); ContentReader.MapSummary mapSummary; bool hasLocation = DaggerfallUnity.Instance.ContentReader.HasLocation(mapPixel.X, mapPixel.Y, out mapSummary); if (hasLocation) { if (!DaggerfallUnity.Instance.ContentReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex, out location)) hasLocation = false; } if (NoWorld) { playerEnterExit.DisableAllParents(); } else { // Start at specified location StreamingWorld streamingWorld = FindStreamingWorld(); if (hasLocation && startInDungeon && location.HasDungeon) { if (streamingWorld) { streamingWorld.TeleportToCoordinates(mapPixel.X, mapPixel.Y); streamingWorld.suppressWorld = true; } playerEnterExit.EnableDungeonParent(); playerEnterExit.StartDungeonInterior(location); } else { playerEnterExit.EnableExteriorParent(); if (streamingWorld) { streamingWorld.SetAutoReposition(StreamingWorld.RepositionMethods.Origin, Vector3.zero); streamingWorld.suppressWorld = false; } } } // Assign starting gear to player entity DaggerfallUnity.Instance.ItemHelper.AssignStartingGear(playerEntity); // Start game GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); if (OnStartGame != null) OnStartGame(this, null); }
public static Texture2D GetTextureFromImg(string name, out DFPosition offset, TextureFormat format = TextureFormat.ARGB32) { offset = new DFPosition(); DaggerfallUnity dfUnity = DaggerfallUnity.Instance; if (!dfUnity.IsReady) return null; ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, name), FileUsage.UseMemory, true); imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName)); Texture2D texture = GetTextureFromImg(imgFile, format); texture.filterMode = DaggerfallUI.Instance.GlobalFilterMode; offset = imgFile.ImageOffset; return texture; }
/// <summary> /// Converts longitude and latitude to map pixel coordinates. /// The world is 1000x500 map pixels. /// </summary> /// <param name="longitude">Longitude position.</param> /// <param name="latitude">Latitude position.</param> /// <returns>Map pixel position.</returns> public static DFPosition LongitudeLatitudeToMapPixel(int longitude, int latitude) { DFPosition pos = new DFPosition(); pos.X = longitude / 128; pos.Y = 499 - (latitude / 128); return pos; }
void UpdateWorldTerrain(DFPosition worldPos) { if (worldTerrainGameObject != null) // sometimes it can happen that this point is reached before worldTerrainGameObject was created, in such case we just skip { // do not forget to update shader parameters (needed for correct fragment discarding for terrain tiles of map pixels inside TerrainDistance-1 area (the detailed terrain)) Terrain terrain = worldTerrainGameObject.GetComponent<Terrain>(); terrain.materialTemplate.SetInt("_PlayerPosX", this.playerGPS.CurrentMapPixel.X); terrain.materialTemplate.SetInt("_PlayerPosY", this.playerGPS.CurrentMapPixel.Y); Vector3 offset = new Vector3(0.0f, 0.0f, 0.0f); updatePositionWorldTerrain(ref worldTerrainGameObject, offset); updateSeasonalTextures(); Resources.UnloadUnusedAssets(); //System.GC.Collect(); } }