private static void PlaceWagon(bool fromSave = false) { if (fromSave == false) { WagonMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; if (!transportManager.HasHorse()) { SetWagonPositionAndRotation(true); DaggerfallUI.MessageBox("You have no horse to pull your wagon."); ItemCollection playerItems = GameManager.Instance.PlayerEntity.Items; for (int i = 0; i < playerItems.Count; i++) { DaggerfallUnityItem item = playerItems.GetItem(i); if (item != null && item.IsOfTemplate(ItemGroups.Transportation, (int)Transportation.Small_cart)) { playerItems.RemoveItem(item); } } } else { SetWagonPositionAndRotation(); } } else { PlaceWagonOnGround(); } Wagon = MeshReplacement.ImportCustomGameobject(wagonModelID, null, WagonMatrix); if (Wagon == null) { Wagon = GameObjectHelper.CreateDaggerfallMeshGameObject(wagonModelID, null); } Wagon.transform.SetPositionAndRotation(WagonPosition, WagonRotation); if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon) { Wagon.SetActive(false); } else { Wagon.SetActive(true); } WagonDeployed = true; }
private static void PlayerGPS_OnMapPixelChanged(DFPosition mapPixel) { // Check if near Northrock Fort if (mapPixel.X >= 937 && mapPixel.X <= 939 && mapPixel.Y >= 50 && mapPixel.Y <= 52) { // In Fort MP 2 messages, in adjacent MP message with track direction if (mapPixel.X == 938 && mapPixel.Y == 51) { DaggerfallUI.AddHUDText(FORT_VERYNEAR1, 5); DaggerfallUI.AddHUDText(FORT_VERYNEAR2, 5); } else if (mapPixel.X == 938 && mapPixel.Y == 50) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "south"), 5); } else if (mapPixel.X == 939 && mapPixel.Y == 50) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "south west"), 5); } else if (mapPixel.X == 939 && mapPixel.Y == 51) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "west"), 5); } else if (mapPixel.X == 939 && mapPixel.Y == 52) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "north west"), 5); } else if (mapPixel.X == 938 && mapPixel.Y == 52) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "north"), 5); } else if (mapPixel.X == 937 && mapPixel.Y == 52) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "north east"), 5); } else if (mapPixel.X == 937 && mapPixel.Y == 51) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "east"), 5); } else if (mapPixel.X == 937 && mapPixel.Y == 50) { DaggerfallUI.AddHUDText(String.Format(FORT_NEAR, "south east"), 5); } } }
/// <summary> /// Gets travel time based on overworld map logic. /// </summary> /// <param name="place">Target place resource. If null will use first place defined in quest.</param> /// <param name="returnTrip">Use return trip multiplier.</param> /// <returns>Travel time in seconds.</returns> int GetTravelTimeInSeconds(Place place, bool returnTrip = true) { if (place == null) { // Get first place resource from quest QuestResource[] placeResources = ParentQuest.GetAllResources(typeof(Place)); if (placeResources == null || placeResources.Length == 0) { Debug.LogError("Clock wants a travel time but quest has no Place resources."); return(0); } place = (Place)placeResources[0]; } // Get target location from place resource DFLocation location; if (!DaggerfallUnity.Instance.ContentReader.GetLocation(place.SiteDetails.regionName, place.SiteDetails.locationName, out location)) { Debug.LogErrorFormat("Could not find Quest Place {0}/{1}", place.SiteDetails.regionName, place.SiteDetails.locationName); return(0); } // Get end position in map pixel coordinates DFPosition endPos = MapsFile.WorldCoordToMapPixel(location.Exterior.RecordElement.Header.X, location.Exterior.RecordElement.Header.Y); // Create a path to location // Use the most cautious time possible allowing for player to camp out or stop at inns along the way TravelTimeCalculator travelTimeCalculator = new TravelTimeCalculator(); int travelTimeMinutes = travelTimeCalculator.CalculateTravelTime(endPos, true, false, false, false, true); // Apply return trip multiplier if (returnTrip) { travelTimeMinutes = (int)(travelTimeMinutes * returnTripMultiplier); } // Always allow at least 1 day for travel time if (travelTimeMinutes < 1440) { travelTimeMinutes = 1440; } return(GetTimeInSeconds(0, 0, travelTimeMinutes)); }
void MovingForward() { // Push mobile towards target position Vector3 direction = Vector3.Normalize(targetScenePosition - transform.position); transform.position += (direction * movementSpeed) * Time.deltaTime; // Update distance to target distanceToTarget = Vector3.Distance(transform.position, targetScenePosition); // If distance below threshold start seeking a new tile if (distanceToTarget < 0.1f) { currentNavPosition = targetNavPosition; ChangeState(MobileStates.SeekingTile); moveCount++; } }
int GetNextNavPositionWeight(MobileDirection direction) { // Must have a current position on navgrid if (!cityNavigation || currentNavPosition.X == -1 || currentNavPosition.Y == -1) { return(0); } // Get next nav position and regard occupied tiles as weight 0 DFPosition nextPosition = GetNextNavPosition(direction); if (cityNavigation.HasFlags(nextPosition, CityNavigation.TileFlags.Occupied)) { return(0); } return(cityNavigation.GetNavGridWeightLocal(nextPosition)); }
private static void DeployTent(bool fromSave = false) { if (fromSave == false) { TentMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; SetTentPositionAndRotation(); } //Attempt to load a model replacement Tent = MeshReplacement.ImportCustomGameobject(tentModelID, null, TentMatrix); if (Tent == null) { Tent = GameObjectHelper.CreateDaggerfallMeshGameObject(tentModelID, null); } //Set the model's position in the world Tent.transform.SetPositionAndRotation(TentPosition, TentRotation); Tent.SetActive(true); TentDeployed = true; }
/// <summary> /// Convert local navgrid position into a world position. /// Precision loss expected converting between world and navgrid. /// </summary> /// <param name="localPosition">Local position inside navgrid.</param> /// <returns>World DFPosition.</returns> public DFPosition NavGridToWorldPosition(DFPosition localPosition) { // Validate DaggerfallLocation if (!dfLocation || dfLocation.Summary.MapID == 0) { throw new Exception(noLocationError); } // Get location rect in world space RectOffset rect = dfLocation.LocationRect; // Navgrid fits 1:1 inside location rect but navgrid origin is top-left and world origin is bottom-left DFPosition worldPosition = new DFPosition( rect.left + localPosition.X * DaggerfallUnitsPerTile, rect.bottom - localPosition.Y * DaggerfallUnitsPerTile); return(worldPosition); }
public static void DeployTent(bool fromSave = false) { if (fromSave == false) { CampMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; SetTentPositionAndRotation(); DaggerfallUI.MessageBox("You set up camp"); } else { PlaceTentOnGround(); } //Attempt to load a model replacement Tent = MeshReplacement.ImportCustomGameobject(tentModelID, null, TentMatrix); Fire = GameObjectHelper.CreateDaggerfallBillboardGameObject(210, 1, null); if (Tent == null) { Tent = GameObjectHelper.CreateDaggerfallMeshGameObject(tentModelID, null); } //Set the model's position in the world Tent.transform.SetPositionAndRotation(TentPosition, TentRotation); if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon) { FirePosition = Tent.transform.position + (Tent.transform.up * 0.8f); Tent.SetActive(false); } else { FirePosition = Tent.transform.position + (Tent.transform.forward * 3) + (Tent.transform.up * 0.8f); Tent.SetActive(true); } Fire.transform.SetPositionAndRotation(FirePosition, TentRotation); Fire.SetActive(true); AddTorchAudioSource(Fire); GameObject lightsNode = new GameObject("Lights"); lightsNode.transform.parent = Fire.transform; AddLight(DaggerfallUnity.Instance, Fire, lightsNode.transform); CampDeployed = true; FireLit = true; }
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(); } }
/// <summary> /// Convert a virtual world position back into scene space. /// This is specific to the peered location due to floating origin. /// Some precision loss is expected converting back to scene space. /// </summary> /// <param name="worldPosition">World location to convert to nearest point in scene space.</param> /// <param name="refineY">Attempt to refine Y position to actual terrain data.</param> /// <returns>Scene Vector3 position.</returns> public Vector3 WorldToScenePosition(DFPosition worldPosition, bool refineY = true) { // Validate DaggerfallLocation if (!dfLocation || dfLocation.Summary.MapID == 0) { throw new Exception(noLocationError); } // Get location origin in both scene and world // The SW origin of location in scene spaces aligns with SW terrain tile origin in world space Vector3 locationOrigin = dfLocation.transform.position; DFPosition worldOrigin = MapsFile.MapPixelToWorldCoord(dfLocation.Summary.MapPixelX, dfLocation.Summary.MapPixelY); // Get difference between origin and target position in scene space Vector3 offset = new Vector3( (worldPosition.X - worldOrigin.X) / StreamingWorld.SceneMapRatio, 0, (worldPosition.Y - worldOrigin.Y) / StreamingWorld.SceneMapRatio); // Calculate X-Z position and use Y from location origin // World > scene conversion results in mobile being aligned exactly on edge of tile in scene // Move the mobile transform a half-tile into centre so it appears to be properly aligned Vector3 result = locationOrigin + offset; result.x += HalfTile; result.z -= HalfTile; // Attempt to refine Y by sampling terrain at this map pixel position if (refineY) { GameObject terrainObject = GameManager.Instance.StreamingWorld.GetTerrainFromPixel(dfLocation.Summary.MapPixelX, dfLocation.Summary.MapPixelY); if (terrainObject) { // Sample actual terrain height at this scene position for Y and adjust for world compensation Terrain terrain = terrainObject.GetComponent <Terrain>(); float height = terrain.SampleHeight(result); result.y = height + GameManager.Instance.StreamingWorld.WorldCompensation.y; } } 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; // Handle custom 1x1 location position if (location.HasCustomLocationPosition()) { result.X = 72; result.Y = 55; } return(result); }
void Update() { // Do nothing if not ready if (!ReadyCheck()) { return; } // Update local world information whenever player map pixel changes DFPosition pos = CurrentMapPixel; if (pos.X != lastMapPixelX || pos.Y != lastMapPixelY) { RaiseOnMapPixelChangedEvent(pos); UpdateWorldInfo(pos.X, pos.Y); // Clear non-permanent scenes from cache, unless going to/from owned ship DFPosition shipCoords = DaggerfallBankManager.GetShipCoords(); if (shipCoords == null || (!(pos.X == shipCoords.X && pos.Y == shipCoords.Y) && !(lastMapPixelX == shipCoords.X && lastMapPixelY == shipCoords.Y))) { SaveLoadManager.ClearSceneCache(false); } lastMapPixelX = pos.X; lastMapPixelY = pos.Y; } // Raise other events RaiseEvents(); // Check if player is inside actual location rect PlayerLocationRectCheck(); // Update nearby objects nearbyObjectsUpdateTimer += Time.deltaTime; if (nearbyObjectsUpdateTimer > refreshNearbyObjectsInterval) { UpdateNearbyObjects(); nearbyObjectsUpdateTimer = 0; } }
void SetTargetPosition() { // Get target position on navgrid and in world targetNavPosition = GetNextNavPosition(currentDirection); targetWorldPosition = cityNavigation.NavGridToWorldPosition(targetNavPosition); // Get the target position in scene targetScenePosition = cityNavigation.WorldToScenePosition(targetWorldPosition); distanceToTarget = 0; // Target point will be at ground level (roughly waist-level for mobile), so adjust up by half mobile height targetScenePosition.y += halfMobileHeight; // Mobile now owns target tile and can release current tile cityNavigation.ClearFlags(currentNavPosition, CityNavigation.TileFlags.Occupied); cityNavigation.SetFlags(targetNavPosition, CityNavigation.TileFlags.Occupied); // Change state to moving forwards ChangeState(MobileStates.MovingForward); seekCount = 0; }
void Update() { // Do nothing if not ready if (!ReadyCheck()) { return; } // Update local world information whenever player map pixel changes DFPosition pos = CurrentMapPixel; if (pos.X != lastMapPixelX || pos.Y != lastMapPixelY) { UpdateWorldInfo(pos.X, pos.Y); lastMapPixelX = pos.X; lastMapPixelY = pos.Y; } // Check if player is inside actual location rect PlayerLocationRectCheck(); }
/// <summary> /// Spawn a new pool item within range of player. /// </summary> void SpawnAvailableMobile() { // Player must be in range of location if (!playerInLocationRange) { return; } // Get a free mobile from pool int item = GetNextFreePoolItem(); if (item == -1) { return; } // Get closest point on navgrid to player position in world DFPosition playerWorldPos = new DFPosition(playerGPS.WorldX, playerGPS.WorldZ); DFPosition playerGridPos = cityNavigation.WorldToNavGridPosition(playerWorldPos); // Spawn mobile at a random position and schedule to be live DFPosition spawnPosition; if (cityNavigation.GetRandomSpawnPosition(playerGridPos, out spawnPosition, navGridSpawnRadius)) { PoolItem poolItem = populationPool[item]; // Setup spawn position DFPosition worldPosition = cityNavigation.NavGridToWorldPosition(spawnPosition); Vector3 scenePosition = cityNavigation.WorldToScenePosition(worldPosition); poolItem.npc.Motor.transform.position = scenePosition; GameObjectHelper.AlignBillboardToGround(poolItem.npc.Motor.gameObject, new Vector2(0, 2f)); // Schedule for enabling poolItem.active = true; poolItem.scheduleEnable = true; populationPool[item] = poolItem; } }
void Update() { if (worldTerrainGameObject != null) { // TODO: make sure this block is not executed when in floating origin mode (otherwise position update is done twice) // Handle moving to new map pixel or first-time init DFPosition curMapPixel = playerGPS.CurrentMapPixel; if (curMapPixel.X != MapPixelX || curMapPixel.Y != MapPixelY) { UpdateWorldTerrain(curMapPixel); } Terrain terrain = worldTerrainGameObject.GetComponent <Terrain>(); if (terrain) { setMaterialFogParameters(); #if ENHANCED_SKY_CODE_AVAILABLE if (isActiveEnhancedSkyMod) { if ((sampleFogColorFromSky == true) && (!skyMan.IsOvercast)) { terrain.materialTemplate.SetFloat("_FogFromSkyTex", 1); } else { terrain.materialTemplate.SetFloat("_FogFromSkyTex", 0); } } #endif //terrain.materialTemplate.SetFloat("_BlendFactor", blendFactor); terrain.materialTemplate.SetFloat("_BlendStart", blendStart); terrain.materialTemplate.SetFloat("_BlendEnd", blendEnd); } updateSeasonalTextures(); // this is necessary since climate changes may occur after UpdateWorldTerrain() has been invoked, TODO: an event would be ideal to trigger updateSeasonalTextures() instead } }
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); }
string GetPaperDollBackground(PlayerEntity entity) { // TODO: If player is were-creature and has transformed, use entity.RaceTemplate.TransformedPaperDollBackground regardless of geo backgrounds if (DaggerfallUnity.Settings.EnableGeographicBackgrounds) { PlayerGPS playerGPS = GameManager.Instance.PlayerGPS; PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit; DFPosition position = playerGPS.CurrentMapPixel; int region = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetPoliticIndex(position.X, position.Y) - 128; if (region < 0 || region >= DaggerfallUnity.Instance.ContentReader.MapFileReader.RegionCount || region >= regionBackgroundIdxChars.Length) { return(entity.RaceTemplate.PaperDollBackground); } // Set background based on location. if (playerGPS.IsPlayerInTown(true)) { return("SCBG04I0.IMG"); // Town } else if (playerEnterExit.IsPlayerInsideDungeon) { return("SCBG07I0.IMG"); // Dungeon } else if (playerGPS.CurrentLocation.MapTableData.LocationType == DFRegion.LocationTypes.Graveyard && playerGPS.IsPlayerInLocationRect) { return("SCBG08I0.IMG"); // Graveyard } else { return("SCBG0" + regionBackgroundIdxChars[region] + "I0.IMG"); // Region } } else { return(entity.RaceTemplate.PaperDollBackground); } }
void SelectNextPath() { PlayerGPS playerGPS = GameManager.Instance.PlayerGPS; if (!playerGPS.HasCurrentLocation) { DFPosition currMapPixel = playerGPS.CurrentMapPixel; byte pathsDataPt = GetPathsDataPoint(currMapPixel); byte playerDirection = GetDirection(GetNormalisedPlayerYaw()); if (CountSetBits(pathsDataPt) == 2) { playerDirection = (byte)(pathsDataPt & playerDirection); if (playerDirection == 0) { byte fromDirection = GetDirection(GetNormalisedPlayerYaw(true)); playerDirection = (byte)(pathsDataPt ^ fromDirection); } #if UNITY_EDITOR Debug.LogFormat("Heading {0}", GetDirectionStr(playerDirection)); #endif byte roadDataPt = GetRoadsDataPoint(currMapPixel); road = (roadDataPt & playerDirection) != 0; BeginPathTravel(GetTargetPixel(playerDirection, currMapPixel), false); return; } else { DaggerfallUI.AddHUDText("You've arrived at a junction."); } } else { lastCrossed = GetDirection(GetNormalisedPlayerYaw(true)); } // An intersection, location, or path end then end travel travelControlUI.CloseWindow(); }
/// <summary> /// Convert a scene position back into virtual world space. /// This is specific to the peered location due to floating origin. /// </summary> /// <param name="scenePosition">Scene position to convert to nearest point in world space.</param> /// <returns>World DFPosition.</returns> public DFPosition SceneToWorldPosition(Vector3 scenePosition) { // Validate DaggerfallLocation if (!dfLocation || dfLocation.Summary.MapID == 0) { throw new Exception(noLocationError); } // Get location origin in both scene and world // The SW origin of location in scene spaces aligns with SW terrain tile origin in world space Vector3 locationOrigin = dfLocation.transform.position; DFPosition worldOrigin = MapsFile.MapPixelToWorldCoord(dfLocation.Summary.MapPixelX, dfLocation.Summary.MapPixelY); // Get difference between origin and target position in scene space Vector3 difference = scenePosition - locationOrigin; // Convert difference into Daggerfall units and apply to origin in world space DFPosition result = new DFPosition( (int)(difference.x * StreamingWorld.SceneMapRatio) + worldOrigin.X, (int)(difference.z * StreamingWorld.SceneMapRatio) + worldOrigin.Y); return(result); }
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); }
//overloaded variant void InjectMaterialProperties(DFPosition worldPos) { InjectMaterialProperties(worldPos.X, worldPos.Y); }
/// <summary> /// Gets Texture2D atlas from Daggerfall texture archive. /// Every record and frame in the archive will be added to atlas. /// An array of rects will be returned with sub-texture rect for each record index and frame. /// Currently supports one archive per atlas. Super-atlas packing (multiple archives) is in the works. /// </summary> /// <param name="settings">Get texture settings.</param> /// <param name="alphaTextureFormat">Alpha TextureFormat.</param> /// <param name="nonAlphaFormat">Non-alpha TextureFormat.</param> /// <returns>GetTextureResults.</returns> public GetTextureResults GetTexture2DAtlas( GetTextureSettings settings, SupportedAlphaTextureFormats alphaTextureFormat = SupportedAlphaTextureFormats.RGBA32, SupportedNonAlphaTextureFormats nonAlphaFormat = SupportedNonAlphaTextureFormats.RGB24) { GetTextureResults results = new GetTextureResults(); // Individual textures must remain readable to pack into atlas bool stayReadable = settings.stayReadable; settings.stayReadable = true; // Assign texture file TextureFile textureFile; if (settings.textureFile == null) { textureFile = new TextureFile(Path.Combine(Arena2Path, TextureFile.IndexToFileName(settings.archive)), FileUsage.UseMemory, true); settings.textureFile = textureFile; } else { textureFile = settings.textureFile; } // Create lists results.atlasSizes = new List <Vector2>(textureFile.RecordCount); results.atlasScales = new List <Vector2>(textureFile.RecordCount); results.atlasOffsets = new List <Vector2>(textureFile.RecordCount); results.atlasFrameCounts = new List <int>(textureFile.RecordCount); // Read every texture in archive bool hasNormalMaps = false; bool hasEmissionMaps = false; bool hasAnimation = false; bool allowImport = (settings.atlasMaxSize == 4096); List <Texture2D> albedoTextures = new List <Texture2D>(); List <Texture2D> normalTextures = new List <Texture2D>(); List <Texture2D> emissionTextures = new List <Texture2D>(); List <RecordIndex> indices = new List <RecordIndex>(); for (int record = 0; record < textureFile.RecordCount; record++) { // Get record index and frame count settings.record = record; int frames = textureFile.GetFrameCount(record); if (frames > 1) { hasAnimation = true; } // Get record information DFSize size = textureFile.GetSize(record); DFSize scale = textureFile.GetScale(record); DFPosition offset = textureFile.GetOffset(record); RecordIndex ri = new RecordIndex() { startIndex = albedoTextures.Count, frameCount = frames, width = size.Width, height = size.Height, }; indices.Add(ri); for (int frame = 0; frame < frames; frame++) { settings.frame = frame; GetTextureResults nextTextureResults = GetTexture2D(settings, alphaTextureFormat, nonAlphaFormat, allowImport); albedoTextures.Add(nextTextureResults.albedoMap); if (nextTextureResults.normalMap != null) { normalTextures.Add(nextTextureResults.normalMap); hasNormalMaps = true; } if (nextTextureResults.emissionMap != null) { emissionTextures.Add(nextTextureResults.emissionMap); hasEmissionMaps = true; } } results.atlasSizes.Add(new Vector2(size.Width, size.Height)); results.atlasScales.Add(new Vector2(scale.Width, scale.Height)); results.atlasOffsets.Add(new Vector2(offset.X, offset.Y)); results.atlasFrameCounts.Add(frames); results.textureFile = textureFile; } // Pack albedo textures into atlas and get our rects Texture2D atlasAlbedoMap = new Texture2D(settings.atlasMaxSize, settings.atlasMaxSize, ParseTextureFormat(alphaTextureFormat), MipMaps); Rect[] rects = atlasAlbedoMap.PackTextures(albedoTextures.ToArray(), settings.atlasPadding, settings.atlasMaxSize, !stayReadable); // Pack normal textures into atlas Texture2D atlasNormalMap = null; if (hasNormalMaps) { // Normals must be ARGB32 atlasNormalMap = new Texture2D(settings.atlasMaxSize, settings.atlasMaxSize, TextureFormat.ARGB32, MipMaps); atlasNormalMap.PackTextures(normalTextures.ToArray(), settings.atlasPadding, settings.atlasMaxSize, !stayReadable); } // Pack emission textures into atlas // TODO: Change this as packing not consistent Texture2D atlasEmissionMap = null; if (hasEmissionMaps) { // Repacking to ensure correct mix of lit and unlit atlasEmissionMap = new Texture2D(settings.atlasMaxSize, settings.atlasMaxSize, ParseTextureFormat(alphaTextureFormat), MipMaps); atlasEmissionMap.PackTextures(emissionTextures.ToArray(), settings.atlasPadding, settings.atlasMaxSize, !stayReadable); } // Add to results if (results.atlasRects == null) { results.atlasRects = new List <Rect>(rects.Length); } if (results.atlasIndices == null) { results.atlasIndices = new List <RecordIndex>(indices.Count); } results.atlasRects.AddRange(rects); results.atlasIndices.AddRange(indices); // Shrink UV rect to compensate for internal border float ru = 1f / atlasAlbedoMap.width; float rv = 1f / atlasAlbedoMap.height; int finalBorder = settings.borderSize + settings.atlasShrinkUVs; for (int i = 0; i < results.atlasRects.Count; i++) { Rect rct = results.atlasRects[i]; rct.xMin += finalBorder * ru; rct.xMax -= finalBorder * ru; rct.yMin += finalBorder * rv; rct.yMax -= finalBorder * rv; results.atlasRects[i] = rct; } // Store results results.albedoMap = atlasAlbedoMap; results.normalMap = atlasNormalMap; results.emissionMap = atlasEmissionMap; results.isAtlasAnimated = hasAnimation; results.isEmissive = hasEmissionMaps; return(results); }
// Start new character to location specified in INI void StartNewCharacter() { DaggerfallUnity.ResetUID(); QuestMachine.Instance.ClearState(); RaiseOnNewGameEvent(); DaggerfallUI.Instance.PopToHUD(); ResetWeaponManager(); SaveLoadManager.ClearSceneCache(true); GameManager.Instance.GuildManager.ClearMembershipData(); // 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(); // Set time tracked in playerEntity playerEntity.LastGameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime(); // 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, characterDocument.classIndex, characterDocument.isCustom); // Assign starting spells to player entity SetStartingSpells(playerEntity); // Apply biography effects to player entity BiogFile.ApplyEffects(characterDocument.biographyEffects, playerEntity); // Setup bank accounts and houses Banking.DaggerfallBankManager.SetupAccounts(); Banking.DaggerfallBankManager.SetupHouses(); // Initialize region data playerEntity.InitializeRegionData(); // Randomize weathers GameManager.Instance.WeatherManager.SetClimateWeathers(); // Start game GameManager.Instance.PauseGame(false); DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); DaggerfallUI.PostMessage(PostStartMessage); lastStartMethod = StartMethods.NewCharacter; // Offer main quest during pre-alpha QuestMachine.Instance.InstantiateQuest("__MQSTAGE00"); // Launch startup optional quest if (!string.IsNullOrEmpty(LaunchQuest)) { QuestMachine.Instance.InstantiateQuest(LaunchQuest); LaunchQuest = string.Empty; } // Launch any InitAtGameStart quests GameManager.Instance.QuestListsManager.InitAtGameStartQuests(); if (OnStartGame != null) { OnStartGame(this, null); } }
void DisplaySaveStatsGUI() { if (currentSaveTree == null) { return; } SaveTreeBaseRecord positionRecord = currentSaveTree.FindRecord(RecordTypes.CharacterPositionRecord); EditorGUILayout.Space(); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("Version"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(currentSaveTree.Header.Version.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { string positionText = string.Format("X={0}, Y={1}, Z={2}", positionRecord.RecordRoot.Position.WorldX, positionRecord.RecordRoot.Position.WorldY, positionRecord.RecordRoot.Position.WorldZ); EditorGUILayout.LabelField(new GUIContent("Player Position", "Position of player in the world."), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(positionText, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { DFPosition mapPixel = MapsFile.WorldCoordToMapPixel(positionRecord.RecordRoot.Position.WorldX, positionRecord.RecordRoot.Position.WorldZ); string mapPixelText = string.Format("X={0}, Y={1}", mapPixel.X, mapPixel.Y); EditorGUILayout.LabelField(new GUIContent("Player Map Pixel", "Position of player on small map."), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(mapPixelText, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { DaggerfallDateTime time = new DaggerfallDateTime(); time.FromClassicDaggerfallTime(currentSaveVars.GameTime); EditorGUILayout.LabelField(new GUIContent("Player Time", "World time of this save."), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(time.LongDateTimeString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("Player Environment"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(((Environments)currentSaveTree.Header.Environment).ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); GUILayoutHelper.Horizontal(() => { EditorGUILayout.LabelField(new GUIContent("RecordElement records"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); EditorGUILayout.SelectableLabel(currentSaveTree.RecordDictionary.Count.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); }); //GUILayoutHelper.Horizontal(() => //{ // EditorGUILayout.LabelField(new GUIContent("Header.Unknown"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); // EditorGUILayout.SelectableLabel(currentSaveTree.Header.Unknown.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); //}); //GUILayoutHelper.Horizontal(() => //{ // EditorGUILayout.LabelField(new GUIContent("CharacterPosition.Unknown"), GUILayout.Width(EditorGUIUtility.labelWidth - 4)); // EditorGUILayout.SelectableLabel(currentSaveTree.Header.CharacterPosition.Unknown.ToString(), EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight)); //}); }
/// <summary> /// Force update of world information (climate, politic, etc.) when Update() not running. /// </summary> public void UpdateWorldInfo() { DFPosition pos = CurrentMapPixel; UpdateWorldInfo(pos.X, pos.Y); }
/// <summary> /// Creates a path from player's current location to destination and /// returns minutes taken to travel. /// </summary> /// <param name="endPos">Endpoint in map pixel coordinates.</param> public int CalculateTravelTime(DFPosition endPos, bool speedCautious = false, bool sleepModeInn = false, bool travelShip = false, bool hasHorse = false, bool hasCart = false) { int transportModifier = 0; if (hasHorse) { transportModifier = 128; } else if (hasCart) { transportModifier = 192; } else { transportModifier = 256; } int playerXMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel.X; int playerYMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel.Y; int distanceXMapPixels = endPos.X - playerXMapPixel; int distanceYMapPixels = endPos.Y - playerYMapPixel; int distanceXMapPixelsAbs = Mathf.Abs(distanceXMapPixels); int distanceYMapPixelsAbs = Mathf.Abs(distanceYMapPixels); int furthestOfXandYDistance = 0; if (distanceXMapPixelsAbs <= distanceYMapPixelsAbs) { furthestOfXandYDistance = distanceYMapPixelsAbs; } else { furthestOfXandYDistance = distanceXMapPixelsAbs; } int xPixelMovementDirection; int yPixelMovementDirection; if (distanceXMapPixels >= 0) { xPixelMovementDirection = 1; } else { xPixelMovementDirection = -1; } if (distanceYMapPixels >= 0) { yPixelMovementDirection = 1; } else { yPixelMovementDirection = -1; } int numberOfMovements = 0; int shorterOfXandYDistanceIncrementer = 0; int minutesTakenThisMove = 0; int minutesTakenTotal = 0; DaggerfallConnect.Arena2.MapsFile mapsFile = DaggerfallUnity.Instance.ContentReader.MapFileReader; pixelsTraveledOnOcean = 0; while (numberOfMovements < furthestOfXandYDistance) { if (furthestOfXandYDistance == distanceXMapPixelsAbs) { playerXMapPixel += xPixelMovementDirection; shorterOfXandYDistanceIncrementer += distanceYMapPixelsAbs; if (shorterOfXandYDistanceIncrementer > distanceXMapPixelsAbs) { shorterOfXandYDistanceIncrementer -= distanceXMapPixelsAbs; playerYMapPixel += yPixelMovementDirection; } } else { playerYMapPixel += yPixelMovementDirection; shorterOfXandYDistanceIncrementer += distanceXMapPixelsAbs; if (shorterOfXandYDistanceIncrementer > distanceYMapPixelsAbs) { shorterOfXandYDistanceIncrementer -= distanceYMapPixelsAbs; playerXMapPixel += xPixelMovementDirection; } } int terrainMovementIndex = 0; int terrain = mapsFile.GetClimateIndex(playerXMapPixel, playerYMapPixel); if (terrain == (int)TerrainTypes.Ocean) { ++pixelsTraveledOnOcean; if (travelShip) { minutesTakenThisMove = 51; } else { minutesTakenThisMove = 255; } } else { terrainMovementIndex = terrainMovementModifierIndices[terrain - (int)TerrainTypes.Ocean]; minutesTakenThisMove = (((102 * transportModifier) >> 8) * (256 - terrainMovementModifiers[terrainMovementIndex] + 256)) >> 8; } if (!sleepModeInn) { minutesTakenThisMove = (300 * minutesTakenThisMove) >> 8; } minutesTakenTotal += minutesTakenThisMove; ++numberOfMovements; } if (!speedCautious) { minutesTakenTotal = minutesTakenTotal >> 1; } return(minutesTakenTotal); }
public override void Update(Task caller) { base.Update(caller); // Do nothing while player respawning if (GameManager.Instance.PlayerEnterExit.IsRespawning) { return; } // Handle resume on next tick of action after respawn process complete if (resumePending) { GameObject player = GameManager.Instance.PlayerObject; player.transform.position = resumePosition; resumePending = false; SetComplete(); return; } // Create SiteLink if not already present if (!QuestMachine.HasSiteLink(ParentQuest, targetPlace)) { QuestMachine.CreateSiteLink(ParentQuest, targetPlace); } // Attempt to get Place resource Place place = ParentQuest.GetPlace(targetPlace); if (place == null) { return; } // Get selected spawn QuestMarker for this Place bool usingMarker = false; QuestMarker marker = new QuestMarker(); if (targetMarker >= 0 && targetMarker < place.SiteDetails.questSpawnMarkers.Length) { marker = place.SiteDetails.questSpawnMarkers[targetMarker]; usingMarker = true; } // Attempt to get location data - using GetLocation(regionName, locationName) as it can support all locations DFLocation location; if (!DaggerfallUnity.Instance.ContentReader.GetLocation(place.SiteDetails.regionName, place.SiteDetails.locationName, out location)) { return; } // Spawn inside dungeon at this world position DFPosition mapPixel = MapsFile.LongitudeLatitudeToMapPixel((int)location.MapTableData.Longitude, location.MapTableData.Latitude); DFPosition worldPos = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y); GameManager.Instance.PlayerEnterExit.RespawnPlayer( worldPos.X, worldPos.Y, true, true); // Determine start position if (usingMarker) { // Use specified quest marker Vector3 dungeonBlockPosition = new Vector3(marker.dungeonX * RDBLayout.RDBSide, 0, marker.dungeonZ * RDBLayout.RDBSide); resumePosition = dungeonBlockPosition + marker.flatPosition; } else { // Use first quest marker marker = place.SiteDetails.questSpawnMarkers[0]; Vector3 dungeonBlockPosition = new Vector3(marker.dungeonX * RDBLayout.RDBSide, 0, marker.dungeonZ * RDBLayout.RDBSide); resumePosition = dungeonBlockPosition + marker.flatPosition; } resumePending = true; }
// Set location tilemap data public static void SetLocationTiles(ref MapPixelData mapPixel) { // Get location DaggerfallUnity dfUnity = DaggerfallUnity.Instance; DFLocation location = dfUnity.ContentReader.MapFileReader.GetLocation(mapPixel.mapRegionIndex, mapPixel.mapLocationIndex); // Position tiles inside terrain area 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; 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.tilemapData[JobA.Idx(xpos, ypos, MapsFile.WorldMapTileDim)] = tile.TileBitfield == 0 ? byte.MaxValue : tile.TileBitfield; } } } } } // Update location rect with extra clearance int extraClearance = location.MapTableData.LocationType == DFRegion.LocationTypes.TownCity ? 3 : 2; Rect locationRect = new Rect(); locationRect.xMin = xmin - extraClearance; locationRect.xMax = xmax + extraClearance; locationRect.yMin = ymin - extraClearance; locationRect.yMax = ymax + extraClearance; mapPixel.locationRect = locationRect; }
// 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); } }