void TeleportPlayer() { // Validate references if (!serializablePlayer || !playerEnterExit) { return; } // Get anchor position from player entity anchorPosition = GameManager.Instance.PlayerEntity.AnchorPosition; // Is player in same interior as anchor? if (IsSameInterior()) { // Just need to move player serializablePlayer.RestorePosition(anchorPosition); } else { // When teleporting to interior anchor, restore world compensation height early before initworld // Ensures exterior world level is aligned with building height at time of anchor // Only works with floating origin v3 saves and above with both serialized world compensation and context if (anchorPosition.worldContext == WorldContext.Interior) { GameManager.Instance.StreamingWorld.RestoreWorldCompensationHeight(anchorPosition.worldCompensation.y); } else { GameManager.Instance.StreamingWorld.RestoreWorldCompensationHeight(0); } // Cache scene before departing if (!playerEnterExit.IsPlayerInside) { SaveLoadManager.CacheScene(GameManager.Instance.StreamingWorld.SceneName); // Player is outside } else if (playerEnterExit.IsPlayerInsideBuilding) { SaveLoadManager.CacheScene(playerEnterExit.Interior.name); // Player inside a building } else // Player inside a dungeon { playerEnterExit.TransitionDungeonExteriorImmediate(); } // Need to load some other part of the world again - player could be anywhere PlayerEnterExit.OnRespawnerComplete += PlayerEnterExit_OnRespawnerComplete; playerEnterExit.RestorePositionHelper(anchorPosition, false, true); // Restore building summary data if (anchorPosition.insideBuilding) { playerEnterExit.BuildingDiscoveryData = anchorPosition.buildingDiscoveryData; } // When moving anywhere other than same interior trigger a fade so transition appears smoother DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); } }
// perform fast travel actions private void performFastTravel() { RaiseOnPreFastTravelEvent(); // Cache scene first, if fast travelling while on ship. if (GameManager.Instance.TransportManager.IsOnShip()) { SaveLoadManager.CacheScene(GameManager.Instance.StreamingWorld.SceneName); } GameManager.Instance.StreamingWorld.TeleportToCoordinates((int)endPos.X, (int)endPos.Y, StreamingWorld.RepositionMethods.DirectionFromStartMarker); if (speedCautious) { GameManager.Instance.PlayerEntity.CurrentHealth = GameManager.Instance.PlayerEntity.MaxHealth; GameManager.Instance.PlayerEntity.CurrentFatigue = GameManager.Instance.PlayerEntity.MaxFatigue; if (!GameManager.Instance.PlayerEntity.Career.NoRegenSpellPoints) { GameManager.Instance.PlayerEntity.CurrentMagicka = GameManager.Instance.PlayerEntity.MaxMagicka; } } DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(travelTimeMinutes * 60); // Halt random enemy spawns for next playerEntity update so player isn't bombarded by spawned enemies at the end of a long trip GameManager.Instance.PlayerEntity.PreventEnemySpawns = true; // Vampires and characters with Damage from Sunlight disadvantage always arrive just after 6pm regardless of travel type // Otherwise raise arrival time to just after 7am if cautious travel would arrive at night if (GameManager.Instance.PlayerEffectManager.HasVampirism() || GameManager.Instance.PlayerEntity.Career.DamageFromSunlight) { DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.RaiseTime((DaggerfallDateTime.DuskHour - DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.Hour) * 3600); } else if (speedCautious) { if ((DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour < 7) || ((DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour == 7) && (DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute < 10))) { float raiseTime = (((7 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour) * 3600) + ((10 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute) * 60) - DaggerfallUnity.WorldTime.DaggerfallDateTime.Second); DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(raiseTime); } else if (DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour > 17) { float raiseTime = (((31 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour) * 3600) + ((10 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute) * 60) - DaggerfallUnity.WorldTime.DaggerfallDateTime.Second); DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(raiseTime); } } DaggerfallUI.Instance.UserInterfaceManager.PopWindow(); travelWindow.CloseTravelWindows(true); GameManager.Instance.PlayerEntity.RaiseSkills(); DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); RaiseOnPostFastTravelEvent(); }
void TeleportPlayer() { // Validate references if (!serializablePlayer || !playerEnterExit) { return; } // Is player in same interior as anchor? if (IsSameInterior()) { // Just need to move player serializablePlayer.RestorePosition(anchorPosition); return; } else { // Cache scene before departing if (!playerEnterExit.IsPlayerInside) { SaveLoadManager.CacheScene(GameManager.Instance.StreamingWorld.SceneName); // Player is outside } else if (playerEnterExit.IsPlayerInsideBuilding) { SaveLoadManager.CacheScene(playerEnterExit.Interior.name); // Player inside a building } else // Player inside a dungeon { playerEnterExit.TransitionDungeonExteriorImmediate(); } // Need to load some other part of the world again - player could be anywhere PlayerEnterExit.OnRespawnerComplete += PlayerEnterExit_OnRespawnerComplete; playerEnterExit.RestorePositionHelper(anchorPosition, false, true); // Restore building summary data if (anchorPosition.insideBuilding) { playerEnterExit.BuildingDiscoveryData = anchorPosition.buildingDiscoveryData; } // When moving anywhere other than same interior trigger a fade so transition appears smoother DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); } // End and resign // Player will need to create a new teleport with a new anchor from here // This is same behaviour as classic forcedRoundsRemaining = 0; ResignAsIncumbent(); anchorSet = false; }
// perform fast travel actions private void performFastTravel() { // Cache scene first, if fast travelling while on ship. if (GameManager.Instance.TransportManager.IsOnShip()) { SaveLoadManager.CacheScene(GameManager.Instance.StreamingWorld.SceneName); } GameManager.Instance.StreamingWorld.TeleportToCoordinates((int)endPos.X, (int)endPos.Y, StreamingWorld.RepositionMethods.DirectionFromStartMarker); if (speedCautious) { GameManager.Instance.PlayerEntity.CurrentHealth = GameManager.Instance.PlayerEntity.MaxHealth; GameManager.Instance.PlayerEntity.CurrentFatigue = GameManager.Instance.PlayerEntity.MaxFatigue; GameManager.Instance.PlayerEntity.CurrentMagicka = GameManager.Instance.PlayerEntity.MaxMagicka; } DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(travelTimeMinutes * 60); // Halt random enemy spawns for next playerEntity update so player isn't bombarded by spawned enemies at the end of a long trip GameManager.Instance.PlayerEntity.PreventEnemySpawns = true; // Raise arrival time to just after 7am if cautious travel would otherwise arrive at night // Increasing this from 6am to 7am as game is quite dark on at 6am (in Daggerfall Unity, Daggerfall is lighter) // Will consider retuning lighting so this can be like classic, although +1 hours to travel time isn't likely to be a problem for now if (speedCautious) { if ((DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour < 7) || ((DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour == 7) && (DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute < 10))) { float raiseTime = (((7 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour) * 3600) + ((10 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute) * 60) - DaggerfallUnity.WorldTime.DaggerfallDateTime.Second); DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(raiseTime); } else if (DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour > 17) { float raiseTime = (((31 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Hour) * 3600) + ((10 - DaggerfallUnity.WorldTime.DaggerfallDateTime.Minute) * 60) - DaggerfallUnity.WorldTime.DaggerfallDateTime.Second); DaggerfallUnity.WorldTime.DaggerfallDateTime.RaiseTime(raiseTime); } } DaggerfallUI.Instance.UserInterfaceManager.PopWindow(); travelWindow.CloseTravelWindows(true); GameManager.Instance.PlayerEntity.RaiseSkills(); DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); }
/// <summary> /// Transition player through an interior door to building exterior. Player must be inside. /// Interior stores information about exterior, no need for extra params. /// </summary> public void TransitionExterior(bool doFade = false) { // Exit if missing required components or not currently inside if (!ReferenceComponents() || !interior || !isPlayerInside) { return; } // Raise event RaiseOnPreTransitionEvent(TransitionType.ToBuildingExterior); // Update scene cache from serializable state for interior->exterior transition SaveLoadManager.CacheScene(interior.name); // Find closest door and position player outside of it StaticDoor closestDoor; Vector3 closestDoorPos = DaggerfallStaticDoors.FindClosestDoor(transform.position, ExteriorDoors, out closestDoor); Vector3 normal = DaggerfallStaticDoors.GetDoorNormal(closestDoor); Vector3 position = closestDoorPos + normal * (controller.radius * 3f); world.SetAutoReposition(StreamingWorld.RepositionMethods.Offset, position); EnableExteriorParent(); // Player is now outside building isPlayerInside = false; // Update serializable state from scene cache for interior->exterior transition SaveLoadManager.RestoreCachedScene(world.SceneName); // Fire event RaiseOnTransitionExteriorEvent(); // Fade in from black if (doFade) { DaggerfallUI.Instance.FadeHUDFromBlack(); } }
private void UpdateMode(TransportModes transportMode) { // Update the transport mode and stop any riding sounds playing. mode = transportMode; if (ridingAudioSource.isPlaying) { ridingAudioSource.Stop(); } if (mode == TransportModes.Horse || mode == TransportModes.Cart) { // Tell player motor we're riding. playerMotor.IsRiding = true; // Setup appropriate riding sounds. SoundClips sound = (mode == TransportModes.Horse) ? horseRidingSound2 : cartRidingSound; ridingAudioSource.clip = dfAudioSource.GetAudioClip((int)sound); // Setup appropriate riding textures. string textureName = (mode == TransportModes.Horse) ? horseTextureName : cartTextureName; for (int i = 0; i < 4; i++) { ridingTexures[i] = ImageReader.GetImageData(textureName, 0, i, true, true); } ridingTexture = ridingTexures[0]; // Initialise neighing timer. neighTime = Time.time + Random.Range(1, 5); } else { // Tell player motor we're not riding. playerMotor.IsRiding = false; } if (mode == TransportModes.Ship) { GameManager.Instance.PlayerMotor.CancelMovement = true; SerializablePlayer serializablePlayer = GetComponent <SerializablePlayer>(); DaggerfallUI.Instance.FadeBehaviour.SmashHUDToBlack(); StreamingWorld world = GameManager.Instance.StreamingWorld; DFPosition shipCoords = DaggerfallBankManager.GetShipCoords(); // Is there recorded position before boarding and is player on the ship? if (IsOnShip()) { // Check for terrain sampler changes. (so don't fall through floor) StreamingWorld.RepositionMethods reposition = StreamingWorld.RepositionMethods.None; if (boardShipPosition.terrainSamplerName != DaggerfallUnity.Instance.TerrainSampler.ToString() || boardShipPosition.terrainSamplerVersion != DaggerfallUnity.Instance.TerrainSampler.Version) { reposition = StreamingWorld.RepositionMethods.RandomStartMarker; if (DaggerfallUI.Instance.DaggerfallHUD != null) { DaggerfallUI.Instance.DaggerfallHUD.PopupText.AddText("Terrain sampler changed. Repositioning player."); } } // Restore player position from before boarding ship, caching ship scene first. SaveLoadManager.CacheScene(world.SceneName); // TODO: Should this should move into teleport to support other teleports? Issue only if inside. (e.g. recall) DFPosition mapPixel = MapsFile.WorldCoordToMapPixel(boardShipPosition.worldPosX, boardShipPosition.worldPosZ); world.TeleportToCoordinates(mapPixel.X, mapPixel.Y, reposition); serializablePlayer.RestorePosition(boardShipPosition); boardShipPosition = null; // Restore cached scene (ship is special case, cache will not be cleared) SaveLoadManager.RestoreCachedScene(world.SceneName); } else { // Record current player position before boarding ship, and cache scene. (ship is special case, cache will not be cleared) boardShipPosition = serializablePlayer.GetPlayerPositionData(); SaveLoadManager.CacheScene(world.SceneName); // Teleport to the players ship, restoring cached scene. world.TeleportToCoordinates(shipCoords.X, shipCoords.Y, StreamingWorld.RepositionMethods.RandomStartMarker); SaveLoadManager.RestoreCachedScene(world.SceneName); } DaggerfallUI.Instance.FadeBehaviour.FadeHUDFromBlack(); mode = TransportModes.Foot; } }
/// <summary> /// Transition player through an exterior door into building interior. /// </summary> /// <param name="doorOwner">Parent transform owning door array..</param> /// <param name="door">Exterior door player clicked on.</param> public void TransitionInterior(Transform doorOwner, StaticDoor door, bool doFade = false, bool start = true) { // Ensure we have component references if (!ReferenceComponents()) { return; } // Copy owner position to door // This ensures the door itself is all we need to reposition interior // Useful when loading a save and doorOwner is null (as outside world does not exist) if (doorOwner) { door.ownerPosition = doorOwner.position; door.ownerRotation = doorOwner.rotation; } if (!start) { // Update scene cache from serializable state for exterior->interior transition SaveLoadManager.CacheScene(world.SceneName); // Explicitly deregister all stateful objects since exterior isn't destroyed SaveLoadManager.DeregisterAllSerializableGameObjects(true); // Clear all stateful objects from world loose object tracking world.ClearStatefulLooseObjects(); } // Raise event RaiseOnPreTransitionEvent(TransitionType.ToBuildingInterior, door); // Ensure expired rooms are removed GameManager.Instance.PlayerEntity.RemoveExpiredRentedRooms(); // Get climate ClimateBases climateBase = ClimateBases.Temperate; if (OverrideLocation) { climateBase = OverrideLocation.Summary.Climate; } else if (playerGPS) { climateBase = ClimateSwaps.FromAPIClimateBase(playerGPS.ClimateSettings.ClimateType); } // Layout interior // This needs to be done first so we know where the enter markers are GameObject newInterior = new GameObject(DaggerfallInterior.GetSceneName(playerGPS.CurrentLocation, door)); newInterior.hideFlags = defaultHideFlags; interior = newInterior.AddComponent <DaggerfallInterior>(); // Try to layout interior // If we fail for any reason, use that old chestnut "this house has nothing of value" try { interior.DoLayout(doorOwner, door, climateBase, buildingDiscoveryData); } catch { DaggerfallUI.AddHUDText(HardStrings.thisHouseHasNothingOfValue); Destroy(newInterior); return; } // Position interior directly inside of exterior // This helps with finding closest enter/exit point relative to player position interior.transform.position = door.ownerPosition + (Vector3)door.buildingMatrix.GetColumn(3); interior.transform.rotation = GameObjectHelper.QuaternionFromMatrix(door.buildingMatrix); // Position player above closest enter marker Vector3 marker; if (!interior.FindClosestEnterMarker(transform.position, out marker)) { // Could not find an enter marker, probably not a valid interior Destroy(newInterior); return; } // Enumerate all exterior doors belonging to this building DaggerfallStaticDoors exteriorStaticDoors = interior.ExteriorDoors; if (exteriorStaticDoors && doorOwner) { List <StaticDoor> buildingDoors = new List <StaticDoor>(); for (int i = 0; i < exteriorStaticDoors.Doors.Length; i++) { if (exteriorStaticDoors.Doors[i].recordIndex == door.recordIndex) { StaticDoor newDoor = exteriorStaticDoors.Doors[i]; newDoor.ownerPosition = doorOwner.position; newDoor.ownerRotation = doorOwner.rotation; buildingDoors.Add(newDoor); } } SetExteriorDoors(buildingDoors.ToArray()); } // Assign new interior to parent if (InteriorParent != null) { newInterior.transform.parent = InteriorParent.transform; } // Cache some information about this interior buildingType = interior.BuildingData.BuildingType; factionID = interior.BuildingData.FactionId; // Set player to marker position // TODO: Find closest door for player facing transform.position = marker + Vector3.up * (controller.height * 0.6f); SetStanding(); EnableInteriorParent(); // Add quest resources GameObjectHelper.AddQuestResourceObjects(SiteTypes.Building, interior.transform, interior.EntryDoor.buildingKey); // Update serializable state from scene cache for exterior->interior transition (unless new/load game) if (!start) { SaveLoadManager.RestoreCachedScene(interior.name); } // Raise event RaiseOnTransitionInteriorEvent(door, interior); // Fade in from black if (doFade) { DaggerfallUI.Instance.FadeHUDFromBlack(); } }