Exemple #1
0
        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();
        }
Exemple #5
0
        /// <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();
            }
        }
Exemple #6
0
        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;
            }
        }
Exemple #7
0
        /// <summary>
        /// Transition player through an exterior door into building interior.
        /// </summary>
        /// <param name="doorOwner">Parent transform owning door array..</param>
        /// <param name="door">Exterior door player clicked on.</param>
        public void TransitionInterior(Transform doorOwner, StaticDoor door, bool doFade = false, bool start = true)
        {
            // Ensure we have component references
            if (!ReferenceComponents())
            {
                return;
            }

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

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

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

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

            // Get climate
            ClimateBases climateBase = ClimateBases.Temperate;

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

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

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

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

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

            // Position player above closest enter marker
            Vector3 marker;

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

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

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

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

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

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

            EnableInteriorParent();

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

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

            // Raise event
            RaiseOnTransitionInteriorEvent(door, interior);

            // Fade in from black
            if (doFade)
            {
                DaggerfallUI.Instance.FadeHUDFromBlack();
            }
        }