예제 #1
0
        public IEnumerator SendPlayerToStartupPosition(PlayerStartupPosition startupPosition)
        {
            if (mSpawningPlayer)
            {
                //whoops
                yield break;
            }

            mSpawningPlayer = true;

            if (!GUILoading.IsLoading)
            {
                //let that go on its own, don't wait for it
                StartCoroutine(GUILoading.LoadStart(GUILoading.Mode.FullScreenBlack));
            }

            //if the startup position is null
            //use the character's state as a startup position
            if (startupPosition == null)
            {
                //the player state should be not-null by now
                Debug.Log("Using player startup position");
                startupPosition = Player.Local.GetStartupPosition();
            }

            if (Player.Local.HasSpawned)
            {
                Player.Local.Despawn();
            }
            //set the current spawn position
            CurrentStartupPosition = startupPosition;
            yield return(null);

            //set all existing world chunks to unclaimed
            mLoadingInfo = "Unloading chunks";
            //suspend chunk loading so the player's position doesn't get the world confused
            GameWorld.Get.SuspendChunkLoading = true;
            for (int i = 0; i < GameWorld.Get.WorldChunks.Count; i++)
            {
                if (GameWorld.Get.WorldChunks [i].State.ID != startupPosition.ChunkID)
                {
                    GameWorld.Get.WorldChunks [i].TargetMode = ChunkMode.Unloaded;
                }
            }
            //suspend worlditem loading so worlditems don't start spawning stuff till we're ready
            WorldItems.Get.SuspendWorldItemUpdates = true;
            //WorldItems.Get.SetAllWorldItemsToInvisible();
            //wait a moment to let that sink in
            yield return(null);

            //put the player in the middle of the chunk to be loaded first
            WorldChunk startChunk = null;

            if (GameWorld.Get.ChunkByID(startupPosition.ChunkID, out startChunk))
            {
                Player.Local.Position = startChunk.ChunkOffset + startupPosition.ChunkPosition.Position;
            }
            else
            {
                mLoadingInfo = "ERROR: Couldn't find startup chunk";
            }
            //we send the player to the chunk / location specified in the world settings
            mLoadingInfo = "Sending player to startup position";
            //re-enable chunk loading so everything can load
            GameWorld.Get.SuspendChunkLoading      = false;
            WorldItems.Get.SuspendWorldItemUpdates = false;
            //set the primary chunk and let it load
            //put the player in the middle of the chunk to be loaded first
            mLoadingInfo = "Waiting for chunks to load";
            while (!GameWorld.Get.ChunksLoaded)
            {
                yield return(null);
            }
            if (startupPosition.ForceUnloadAllNonPrimaryChunks)
            {
                Debug.Log("Force-unloading all primary chunks, structures, worlditems");
                //unload all chunks except the primary chunk
                var unloadChunks = GameWorld.Get.UnloadAllChunks(startupPosition.ChunkID);
                while (unloadChunks.MoveNext())
                {
                    mLoadingInfo = "Unloading all chunks...";
                    yield return(unloadChunks.Current);
                }
                var unloadStructures = Structures.Get.UnloadAllStructures();
                while (unloadStructures.MoveNext())
                {
                    mLoadingInfo = "Unloading all structures...";
                    yield return(unloadStructures.Current);
                }
                var unloadWorldItems = WorldItems.Get.UnloadAllWorldItems();
                while (unloadWorldItems.MoveNext())
                {
                    mLoadingInfo = "Unloading all worlditems...";
                    yield return(unloadWorldItems.Current);
                }
                Resources.UnloadUnusedAssets();
            }
            mLoadingInfo = "Chunks unloaded, setting primary chunk";
            //set all the non-distant chunks to load
            GameWorld.Get.SetDistantChunks(Player.Local.Position);
            if (!GameWorld.Get.SetPrimaryChunk(startupPosition.ChunkID))
            {
                mLoadingInfo = "Couldn't set primary chunk, halting load: " + startupPosition.ChunkID.ToString();
                yield break;
            }
            //set the startup position so managers know where the player will end up
            startupPosition.WorldPosition.Position = (GameWorld.Get.PrimaryChunk.ChunkOffset + startupPosition.ChunkPosition.Position);
            startupPosition.WorldPosition.Rotation = startupPosition.ChunkPosition.Rotation;
            //set all the non-distant chunks to load
            GameWorld.Get.SetDistantChunks(startupPosition.WorldPosition.Position);
            //wait for the rest of the chunk to load
            while (GameWorld.Get.PrimaryChunk.CurrentMode != ChunkMode.Primary)
            {
                //turn on the camera so it starts rendering grass meshes
                //this will fight with camera FX but that's ok
                CameraFX.Get.Default.cam.enabled     = true;
                CameraFX.Get.Default.cam.cullingMask = CameraFX.Get.Default.CullingMask;
                mLoadingInfo = "Waiting for primary chunk to load";
                //Debug.Log("waiting for primary chunk to load");
                yield return(null);
            }

            //initialize time
            if (startupPosition.RequiresStructure)
            {
                mLoadingInfo = "Loading structures";
                yield return(StartCoroutine(SendPlayerToStructure(
                                                startupPosition.ChunkID,
                                                startupPosition.LocationReference,
                                                startupPosition.StructureName,
                                                startupPosition.Interior,
                                                startupPosition.ChunkPosition,
                                                startChunk.ChunkOffset)));
            }
            else
            {
                mLoadingInfo = "Loading location";
                yield return(StartCoroutine(SendPlayerToLocation(
                                                startupPosition.ChunkID,
                                                startupPosition.LocationReference.GroupPath,
                                                startupPosition.LocationReference.FileName,
                                                startupPosition.ChunkPosition,
                                                startChunk.ChunkOffset,
                                                0.1f)));

                //since we're not inside a structure
                //we could be standing on something
                //either a minor structure or chunk prefab
                if (startupPosition.RequiresMeshTerrain)
                {
                    //wait for something to show up below the player before letting them go
                    GameWorld.TerrainHeightSearch terrainHit = new GameWorld.TerrainHeightSearch();
                    terrainHit.feetPosition   = startupPosition.WorldPosition.Position;
                    terrainHit.groundedHeight = Globals.DefaultCharacterGroundedHeight;
                    terrainHit.overhangHeight = Globals.DefaultCharacterHeight;
                    bool   foundSomethingBelowPlayer = false;
                    double timeOut = WorldClock.RealTime + 30f;
                    mLoadingInfo = "Waiting for mesh below player's feet";
                    while (WorldClock.RealTime < timeOut)
                    {
                        GameWorld.Get.TerrainHeightAtInGamePosition(ref terrainHit);
                        //see if we hit a mesh
                        if (terrainHit.hitTerrainMesh)
                        {
                            break;
                        }
                        yield return(null);
                    }
                }
            }

            //immediately add the game offset
            if (startupPosition.AbsoluteTime)
            {
                WorldClock.ResetAbsoluteTime();
                Profile.Get.CurrentGame.SetWorldTimeOffset(
                    startupPosition.TimeHours,
                    startupPosition.TimeDays,
                    startupPosition.TimeMonths,
                    startupPosition.TimeYears);
            }
            else
            {
                Profile.Get.CurrentGame.AddWorldTimeOffset(
                    startupPosition.TimeHours,
                    startupPosition.TimeDays,
                    startupPosition.TimeMonths,
                    startupPosition.TimeYears);
            }

            //unload anything we're not using
            //GC.Collect();
            //Resources.UnloadUnusedAssets();
            //yield return null;
            yield return(null);

            if (GUILoading.IsLoading)
            {
                StartCoroutine(GUILoading.LoadFinish());
            }

            Player.Local.SpawnAtPosition(startupPosition.WorldPosition);

            mSpawningPlayer = false;
            yield break;
        }
예제 #2
0
        protected IEnumerator SpawnPlayerOverTime(LocalPlayer player)
        {
            mWaitingForFade = true;
            //add a request to spawn a healer character near the player
            Frontiers.GUI.CameraFade.StartAlphaFade(Color.red, false, 3.0f, 0f, () => {
                mWaitingForFade = false;
            });
            while (mWaitingForFade)
            {
                yield return(null);
            }
            //now fade out red
            Frontiers.GUI.CameraFade.StartAlphaFade(Color.red, true, 3.0f);
            //now that the screen is covered
            //move the player
            GameWorld.TerrainHeightSearch terrainHit = new GameWorld.TerrainHeightSearch();
            //search for an appropriate spot within a radius around the player
            bool foundGoodSpot = false;
            int  maxTries      = 50;
            int  numTriesSoFar = 0;

            while (!foundGoodSpot)
            {
                Vector3 randomSpot = (UnityEngine.Random.onUnitSphere * 25f) + player.Surroundings.LastPositionOnland;
                randomSpot.y             += 150;
                terrainHit.feetPosition   = randomSpot;
                terrainHit.overhangHeight = Globals.DefaultCharacterHeight;
                terrainHit.groundedHeight = 200f;                //we don't care about being grounded, just find the floor
                terrainHit.feetPosition.y = GameWorld.Get.TerrainHeightAtInGamePosition(ref terrainHit);
                if (!terrainHit.hitWater && !terrainHit.hitTerrainMesh && terrainHit.hitTerrain)
                {
                    Debug.Log("Found spot to spawn: " + terrainHit.feetPosition.ToString());
                    foundGoodSpot = true;
                    break;
                }
                else
                {
                    numTriesSoFar++;
                    if (numTriesSoFar > maxTries)
                    {
                        Debug.Log("Couldn't find good place to spawn, going with last position on land");
                        terrainHit.feetPosition = player.Surroundings.LastPositionOnland;
                        break;
                    }
                }
            }
            terrainHit.feetPosition.y += 0.25f;
            player.Position            = terrainHit.feetPosition;
            //spawn the player
            player.Spawn();
            //finally spawn the healer nearby
            CharacterSpawnRequest spawnRequest = new CharacterSpawnRequest();

            spawnRequest.ActionNodeName            = "HealerActionNode";
            spawnRequest.CharacterName             = "Healer";
            spawnRequest.UseGenericTemplate        = true;
            spawnRequest.CustomConversation        = Globals.HouseOfHealingExteriorConversation;
            spawnRequest.FinishOnSpawn             = true;
            spawnRequest.SpawnBehindPlayer         = true;
            spawnRequest.MinimumDistanceFromPlayer = 1f;
            player.CharacterSpawner.AddSpawnRequest(spawnRequest);
            //take the player's money
            //take 1/2 (or whatever global value is) reduced by skill value
            int moneyToTake = Mathf.FloorToInt(player.Inventory.InventoryBank.BaseCurrencyValue * (Globals.HouseOfHealingRevivalCost * (1f - State.NormalizedUsageLevel)));

            player.Inventory.InventoryBank.TryToRemove(moneyToTake);
            //and we're done!
            mSpawningPlayerOverTime = false;
            yield break;
        }