private void LevelMetadataToUI(LevelMetadata data) { for (int i = 0; i < 3; i++) { TeamDatas[i].Data = data.TeamDatas[i]; } txtMusicName.Text = data.MusicName; pltPalette4.Data = data.Palette4; ckbAllies12.Checked = data.Alliances[0]; ckbAllies13.Checked = data.Alliances[1]; ckbAllies23.Checked = data.Alliances[2]; lstUnitReplacements.Datas = data.UnitReplacements; CurrentLevel = data.Name; CurrentFile = data.Name; Dirty = false; }
/// <summary> /// Callback that results from testing whether or not the community server is active. /// </summary> /// <param name="resultObj"></param> public void Callback_Ping(AsyncResult resultObj) { AsyncResult result = (AsyncResult)resultObj; if (result.Success) { // Read it back from disk and start uploading it to the community. BokuShared.Wire.WorldPacket packet = XmlDataHelper.ReadWorldPacketFromDisk(result.Param as string); LevelMetadata level = XmlDataHelper.LoadMetadataByGenre(packet.Info.WorldId, (BokuShared.Genres)packet.Info.Genres); UploadWorldData(packet, level); } else { ShowShareErrorDialog("Login failed."); } } // end of Callback_Ping()
internal void ContinueCommunityShare() { LevelMetadata level = CurWorld; //TODO: check for broken links? //always start the share on the first level in the set level = level.FindFirstLink(); string folderName = Utils.FolderNameFromFlags(level.Genres); string fullPath = BokuGame.Settings.MediaPath + folderName + level.WorldId.ToString() + @".Xml"; // Share. // Check to see if the community server is reachable before sharing level. if (!Web.Community.Async_Ping(Callback_Ping, fullPath)) { ShowNoCommunityDialog(); } } // end of PopupOnCommunityShare()
/** * Setup and prepare for the next state */ private void transitionState(State nextState) { leaveState(); if (nextState == State.LEVEL_STARTING) { cameraFollowing.target = player; levelMetadata = FindObjectOfType <LevelMetadata>(); SpawnPoint spawn = FindObjectOfType <SpawnPoint>(); spawnPoint = spawn.gameObject; levelTimer = 0; deaths = 0; collectablesGot = 0; playerWolf.setFacingDirection(spawn.facingDirection); playerWolf.setPosition(spawn.transform.position); playerWolf.setToLevelStartState(); levelStart.show(); UIlevelTimer.SetActive(true); } else if (nextState == State.IN_LEVEL) { } else if (nextState == State.PAUSED) { playerWolf.setPaused(true); } else if (nextState == State.LEVEL_ENDING) { playerWolf.setToLevelEndState(); levelEnd.show(); } else if (nextState == State.LEVEL_LOADING) { UIlevelTimer.SetActive(false); } else if (nextState == State.MAIN_MENU) { cameraFollowing.enabled = false; player.SetActive(false); cam.transform.position = mainMenuCameraPosition.transform.position; } currentState = nextState; }
/// <summary> /// Loads the correct "level" data to each of the grid elements, /// </summary> /// <param name="cursor"></param> public void Reload(ILevelSetCursor cursor) { Log("Begin Reload"); for (int i = 0; i < kWidth; ++i) { LevelMetadata level = cursor[i - kFront]; UIGridLevelElement existing = Get(i); // If they already match then we're good. if (existing != null && existing.Level == level) { continue; } // If there's no element and no level, also good. if (existing == null && level == null) { continue; } if (level != null) { // Need to create a new element if (existing == null) { existing = CreateElement(level); Add(existing, i, 0); existing.SetOrientation(baseOrients[i]); } existing.Level = level; } else { // No level, so set element's ref to null. existing.Level = null; } } Log("End Reload"); }
public IEnumerator GenerateSite(LevelMetadata levelMetadata, LevelMetadata attemptMetadata) { UIManager.Instance.Prompt("Generating level..."); // Generate level based on level metadata yield return(GenerateSite( (int)levelMetadata.SiteDimensionsMetadata.SiteDimensions.x, (int)levelMetadata.SiteDimensionsMetadata.SiteDimensions.y, (int)levelMetadata.SiteDimensionsMetadata.SiteDimensions.z)); yield return(landmarkManager.GenerateLandmarks(levelMetadata.LandmarkMetadataList)); yield return(trafficManager.GenerateAccessPoints(levelMetadata.TrafficMetadataList)); yield return(roadManager.GenerateArterials(levelMetadata.RoadMetadataList)); // Generate site based on attempt metadata yield return(roadManager.GenerateRoads(attemptMetadata.RoadMetadataList)); UIManager.Instance.Prompt("Level generated successfully"); }
public ProceduralLevel(LevelGraph graph, LevelGeneratorPreset preset, bool setIsStatic) { //IMPORTANT, multiply with the door size. Doors require the chunk to be aligned on the grid on GENERATION time //Ensure, that chunks are on the grid, since the doors align to the grid regardless of the chunk position, which //Will result in shifted doorpositions on repositioning the chunks tmpChunkPos = DoorDefinition.GlobalSize * -5000f; tmpChunkStep = DoorDefinition.GlobalSize * -50f; isGenerating = true; this.preset = preset; this.hallwayTiling = preset.HallwayTiling; this.distance = preset.RoomDistance; this.rootnode = graph.Rootnode; this.spacing = preset.Spacing; this.isSeparate = preset.IsSeparateRooms; this.hallwayMaterials = preset.HallwayMaterials; this.helper = new ChunkHelper(preset); this.debugData = new DebugData(); this.chunkInstantiator = ChunkInstantiator.Instance; this.hallwayMeta = new List <HallwayMeta> (); this.positionMeta = new List <RoomTransformation>(); this.levelMetadata = new LevelMetadata(); this.setIsStatic = setIsStatic; GenerateLevel(graph); if (!isConstraintError) { ApplyTransformation(); CreateHallways(); } else { HandleRollback(); } helper.CleanUp(); ChunkInstantiator.RemoveManualProperties(); isGenerating = false; }
} // end of OnSaveLevelDialogButton() /// <summary> /// OnSelect method used by mini-hub grid. If the level is dirty and needs to /// be saved the SaveChagesDialog will be activated. Upon its deactivation /// the level should no longer be marked dirty and OnSelect() will get called /// again allowing the user's action to be executed. /// </summary> /// <param name="grid"></param> public void OnSelect(ModularMenu menu) { // Prevent the button pressed from leaking into runtime. GamePadInput.IgnoreUntilReleased(Buttons.A); // In every case, we need to reset the level to its starting state. InGame.inGame.ResetSim(preserveScores: false, removeCreatablesFromScene: false, keepPersistentScores: false); // Resetting the sim just started up all game audio, let's pause it down again. // It will be resumed when we go back into sim mode. BokuGame.Audio.PauseGameAudio(); // Flag to let us know if the level needs saving. If the save changes // dialog has already been activated then just set this to false. bool needToSaveLevel = (InGame.IsLevelDirty || InGame.AutoSaved) && !saveChangesActivated; // Does the current world belong to the user. Required to share to community. // Test the genre flag and also special case look at empty world. bool isMyWorld = false; if (InGame.XmlWorldData != null) { bool genreTest = ((int)InGame.XmlWorldData.genres & (int)Genres.MyWorlds) != 0; bool newWorldTest = InGame.XmlWorldData.Filename == emptyWorldFileName; if (genreTest && !newWorldTest) { isMyWorld = true; } } // Normally there would be a switch here but if we compare strings // we proof ourselves against changes in the order of the elements. if (menu.CurString == Strings.Localize("miniHub.reset")) { // Reset. // We've already done a Reset, so force to RunSim mode if we already aren't. Deactivate(); InGame.inGame.Activate(); InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.RunSim; InGame.inGame.RestorePlayModeCamera(); // The ResetSim above doesn't ApplyInlining since it's generally // meant for resetting into the editor. In this case we're going // into RunSim mode so be sure to apply inlining first. InGame.ApplyInlining(); if (InGame.inGame.PreGame != null) { InGame.inGame.PreGame.Active = true; } } else if (menu.CurString == Strings.Localize("miniHub.edit")) { // Edit level. Deactivate(); InGame.inGame.Activate(); InGame.inGame.CurrentUpdateMode = InGame.UpdateMode.ToolMenu; } else if (menu.CurString == Strings.Localize("miniHub.save")) { // Save saveLevelDialog.Activate(); } else if (menu.CurString == Strings.Localize("miniHub.publish")) { // Offer to save first. Need to save if world has changed or is world doesn't belong to user. if (needToSaveLevel || !isMyWorld) { saveChangesActivated = true; saveChangesMessage.Activate(); } else { var level = LevelMetadata.CreateFromXml(InGame.XmlWorldData); shared.communityShareMenu.Activate(level); } } else if (menu.CurString == Strings.Localize("miniHub.load")) { // Load. // If we're back here and saveChangesActivated is true then the // user was given the option to save changes and chose Discard. // So don't offer to save again. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Deactivate mini-hub and bring up loading menu. Deactivate(); //InGame.inGame.DiscardTerrain(); BokuGame.bokuGame.loadLevelMenu.LocalLevelMode = LoadLevelMenu.LocalLevelModes.General; BokuGame.bokuGame.loadLevelMenu.ReturnToMenu = LoadLevelMenu.ReturnTo.MiniHub; BokuGame.bokuGame.loadLevelMenu.Activate(); } } else if (menu.CurString == Strings.Localize("miniHub.emptyLevel")) { // Empty Level. // If saveChangesActivated is already true then user chose Discard and // we can ignore the needToSaveLevel flag. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Undo any previous warping. ScreenWarp.FitRtToScreen(BokuGame.ScreenSize); newWorldDialog.Active = true; } } else if (menu.CurString == Strings.Localize("miniHub.print")) { Print.PrintProgramming(); // We don't want to exit the mini-hub so re-activate the menu. shared.menu.Active = true; } else if (menu.CurString == Strings.Localize("miniHub.quit")) { // Exit to main menu. // If we're back here and saveChangesActivated is true then the // user was given the option to save changes and chose Discard. // So don't offer to save again. if (!saveChangesActivated && needToSaveLevel) { saveChangesActivated = true; saveChangesWithDiscardMessage.Activate(); } else { saveChangesActivated = false; // Wave bye, bye. Go back to the main menu Deactivate(); InGame.inGame.StopAllSounds(); BokuGame.bokuGame.mainMenu.Activate(); } } } // end of MiniHub OnSelect()
public IEnumerator Load(int level_guid) { loadedInDebug = false; AsyncPropAndTileSetup.Instance.LoadConfigs(); while (!TileProperties.Loaded || !PropProperties.Loaded) { yield return(new WaitForEndOfFrame()); } if (!didTriggerMetaUpdate) { StartCoroutine(RefreshLevelData()); } while (!hasUpdatedMetas) { yield return(new WaitForEndOfFrame()); } Unload(); //Find our metadata LevelMetadata ourMeta = null; foreach (LevelMetadata meta in LevelMetadata) { if (meta.levelGUID == level_guid) { ourMeta = meta; break; } } if (ourMeta == null) { Debug.LogError("Cannot find requested level GUID!"); yield break; } metadata = ourMeta; metadata.SetLoadState(false); Debug.Log("Loading level: " + metadata.levelName + " (GUID " + metadata.levelGUID + ")"); int invisibleProps = 0; int invisibleTiles = 0; string configFile = Application.streamingAssetsPath + "/LEVELS/" + metadata.levelName + ".dwb"; #if !UNITY_WEBGL if (File.Exists(configFile)) //It's ok not to exist if we're in editor { #endif //Load our level config levelData = null; StartCoroutine(FileLoader.Instance.LoadAsBytes(configFile, LoadCallback)); while (levelData == null || !levelData.CanRead) { yield return(new WaitForEndOfFrame()); } //Read our level config BinaryReader reader = new BinaryReader(levelData); int versionNum = reader.ReadInt32(); if (!(versionNum == LevelFileVersion.VERSION_NUM)) //This can allow through back-supported config versions { Debug.LogError("Tried to load an outdated level file!"); reader.Close(); yield break; } if (versionNum != LevelFileVersion.VERSION_NUM) { Debug.LogWarning("This level uses file version " + versionNum + " (latest is " + LevelFileVersion.VERSION_NUM + "). While this version is supported, please re-save the level in editor ASAP to keep updated with the latest features."); } int tileCount = reader.ReadInt32(); Vector2 gridDims = new Vector2(reader.ReadInt16(), reader.ReadInt16()); if (gridDims != theGrid.GridTileDims) { Debug.LogError("Grid resizing is unsupported! This level is invalid."); reader.Close(); yield break; } //Load occupiers int tileOccupierCount = reader.ReadInt32(); for (int i = 0; i < tileOccupierCount; i++) { Tile parentTile = theGrid.AllTiles[reader.ReadInt32()]; int enumIndex = reader.ReadInt16(); if (!Enum.IsDefined(typeof(TileTypes), enumIndex)) { Debug.LogError("ERROR! When loading, a tile's occupier was of a type that no longer exists."); continue; } //Populate the tile's occupier GameObject parentTileObject = null; parentTileObject = Instantiate(worldTileObject, parentTile.Position, Quaternion.identity) as GameObject; TileTypes tileType = (TileTypes)enumIndex; #if UNITY_EDITOR if (!TileProperties.IsVisibleInEditor(tileType)) { invisibleTiles++; } #endif parentTileObject.GetComponent <LevelTileEntity>().Initialise(tileType, parentTile, false); } //Load props int tilePropCount = reader.ReadInt32(); for (int i = 0; i < tilePropCount; i++) { if (versionNum == 13) { reader.BaseStream.Position += 4; } int enumIndex = reader.ReadInt16(); PropRotation rotation = (PropRotation)reader.ReadInt16(); int propTileCount = reader.ReadInt32(); List <Tile> propTiles = new List <Tile>(); for (int x = 0; x < propTileCount; x++) { propTiles.Add(theGrid.AllTiles[reader.ReadInt32()]); } if (!Enum.IsDefined(typeof(PropTypes), enumIndex)) { Debug.LogError("ERROR! When loading, a tile's prop was of a type that no longer exists."); continue; } PropTypes propType = (PropTypes)enumIndex; GameObject parentTileDecoratorObject = Instantiate(worldPropObject, propTiles[0].Position, Quaternion.identity) as GameObject; #if UNITY_EDITOR if (!PropProperties.IsVisibleInEditor(propType)) { invisibleProps++; } #endif parentTileDecoratorObject.GetComponent <LevelPropEntity>().Initialise(propType, propTiles, rotation, false); } //Load some metadata metadata.SetGoonCount(reader.ReadInt32()); metadata.SetHazardCount(reader.ReadInt32()); reader.Close(); //Refresh all sprites to get the right contexts for (int i = 0; i < Grid.AllTiles.Count; i++) { if (Grid.AllTiles[i].IsOccupied) { Grid.AllTiles[i].Occupier.RefreshSprite(); } } metadata.SetLoadState(true); #if !UNITY_WEBGL } else { //User is just starting to create this level metadata.SetLoadState(true); LevelEditor.Instance.SaveLevel(); } #endif //Show/hide grid depending on editor state GetComponent <SpriteRenderer>().enabled = IsInEditor; if (invisibleProps == 0 && invisibleTiles == 0) { Debug.Log("Level loaded without warnings!"); } else { Debug.LogWarning("Level loaded successfully, but contains " + invisibleProps + " deprecated props and " + invisibleTiles + " deprecated tiles. Consider updating this content."); } LevelLoadCompleted?.Invoke(); validateNextTick = true; }
private void Update() { LevelMetadata meta = GameManager.i().levelMetadata; lbl_CollectablesCounter.text = string.Format("{0}/{1}", GameManager.i().collectablesGot, meta.totalCollectables); }
/// <summary> /// Reads a directory, building the list of level metadata available for browsing. /// </summary> /// <param name="dataSource"></param> /// <returns></returns> private void ReadDataSource(string folder, Genres tag, StorageSource sources) { string path = Path.Combine(BokuGame.Settings.MediaPath, BokuGame.LevelsPath, folder); string[] files = null; try { #if NETFX_CORE files = Storage4.GetFiles(path, @"*.Xml", sources); #else files = Storage4.GetFiles(path, @"*.Xml", sources, SearchOption.TopDirectoryOnly); #endif } catch { } if (files != null) { // Filter out AutoSave.Xml List <string> filteredFiles = new List <string>(); for (int i = 0; i < files.Length; ++i) { if (files[i].ToUpper().Contains("AUTOSAVE")) { continue; } filteredFiles.Add(files[i]); } files = filteredFiles.ToArray(); // Load level metadata records for (int i = 0; running && i < files.Length; i++) { try { string filename = Path.GetFileName(files[i]); string fullPath = Path.Combine(path, filename); XmlWorldData xml = XmlWorldData.Load(fullPath, XnaStorageHelper.Instance, (int)sources); if (xml == null) { continue; } LevelMetadata level = new LevelMetadata(); level.FromXml(xml); level.Genres |= tag; LevelBrowserState state = new LevelBrowserState(); state.level = level; level.BrowserState = state; // Force the creator name of built-ins to "Microsoft" if ((level.Genres & Genres.BuiltInWorlds) != 0) { level.Creator = "Kodu Team"; } AddLevel(level); } catch (Exception e) { Debug.WriteLine(e.Message); } } } }
/// <summary> /// This is the worker thread that loads the datasources from disk. /// </summary> private void ReadLevelsProc() { ReadDataSource("BuiltInWorlds", Genres.BuiltInWorlds, StorageSource.TitleSpace); ReadDataSource("MyWorlds", Genres.MyWorlds, StorageSource.UserSpace); ReadDataSource("Downloads", Genres.Downloads, StorageSource.UserSpace); #if NETFX_CORE working = false; #else thread = null; #endif for (; ;) { if (!running || !BokuGame.Running) { break; } // Wait for a wake-up signal #if NETFX_CORE if (!signal.WaitOne(10)) { continue; } #else if (!signal.WaitOne(10, false)) { continue; } #endif // Process all queued thumbnail load requests. for (; ;) { lock (Synch) { if (thumbnailQueue.Count == 0 || !running || !BokuGame.Running) { break; } LevelMetadata level = thumbnailQueue[thumbnailQueue.Count - 1]; thumbnailQueue.RemoveAt(thumbnailQueue.Count - 1); try { string texFilename = BokuGame.Settings.MediaPath + Utils.FolderNameFromFlags(level.Genres) + level.WorldId.ToString(); Stream texStream = OpenTextureStream(texFilename); if (texStream != null) { level.ThumbnailBytes = new byte[texStream.Length]; texStream.Read(level.ThumbnailBytes, 0, (int)texStream.Length); Storage4.Close(texStream); thumbnailCompletions.Add(level); } } catch { } } // Let the main thread have the cpu so it can deliver the thumbnail to the level. #if NETFX_CORE { System.Threading.Tasks.Task delayTask = System.Threading.Tasks.Task.Delay(1); delayTask.ConfigureAwait(false); delayTask.Wait(); } #else Thread.Sleep(1); #endif } } }
public void InitializeLevel(int levelId, string levelMetadata, string attemptMetadata) { this.levelId = levelId; this.levelMetadata = new LevelMetadata(levelMetadata); this.attemptMetadata = new LevelMetadata(attemptMetadata); }
public void Activate(LevelMetadata level) { CurWorld = level; PopupOnCommunityShare(); Activate(); }
public CommunityShareMenu() { // signedInMessage { ModularMessageDialog.ButtonHandler handlerA = delegate(ModularMessageDialog dialog) { // User chose "upload" //find the first link LevelMetadata level = CurWorld; level = level.FindFirstLink(); string folderName = Utils.FolderNameFromFlags(level.Genres); string fullPath = BokuGame.Settings.MediaPath + folderName + level.WorldId.ToString() + @".Xml"; // Read it back from disk and start uploading it to the community. BokuShared.Wire.WorldPacket packet = XmlDataHelper.ReadWorldPacketFromDisk(fullPath); UploadWorldData(packet, level); // Deactivate dialog. dialog.Deactivate(); Deactivate(); }; ModularMessageDialog.ButtonHandler handlerB = delegate(ModularMessageDialog dialog) { // User chose "cancel" // Deactivate dialog. dialog.Deactivate(); Deactivate(); }; ModularMessageDialog.ButtonHandler handlerY = delegate(ModularMessageDialog dialog) { // Deactivate dialog. dialog.Deactivate(); Deactivate(); }; } // signedOutMessage { ModularMessageDialog.ButtonHandler handlerA = delegate(ModularMessageDialog dialog) { // Deactivate dialog. dialog.Deactivate(); }; ModularMessageDialog.ButtonHandler handlerB = delegate(ModularMessageDialog dialog) { // User chose "cancel" // Deactivate dialog. dialog.Deactivate(); Deactivate(); }; ModularMessageDialog.ButtonHandler handlerY = delegate(ModularMessageDialog dialog) { // User chose "upload anonymous" LevelMetadata level = CurWorld; //find the first link level = level.FindFirstLink(); string folderName = Utils.FolderNameFromFlags(level.Genres); string fullPath = BokuGame.Settings.MediaPath + folderName + level.WorldId.ToString() + @".Xml"; // Share. // Check to see if the community server is reachable before sharing level. if (!Web.Community.Async_Ping(Callback_Ping, fullPath)) { ShowNoCommunityDialog(); } // Deactivate dialog. dialog.Deactivate(); Deactivate(); }; } }
static void DrawGame() { if (Game.editing) { foreach (Button button in _levelEditorButtons) { if (button.id == "editor.playPause") { button.text = Game.music.Status switch { SoundStatus.Playing => "║", _ => "►" } } ; if (button.Draw()) { switch (button.text) { case "►": Game.music.Play(); break; case "║": Game.music.Pause(); Game.steps = Game.roundedSteps; Game.UpdateTime(); break; } switch (button.id) { case "editor.hp.drain.up": Map.currentLevel.metadata.hpDrain++; break; case "editor.hp.drain.down": Map.currentLevel.metadata.hpDrain--; break; case "editor.hp.restorage.up": Map.currentLevel.metadata.hpRestorage++; break; case "editor.hp.restorage.down": Map.currentLevel.metadata.hpRestorage--; break; case "editor.music.offset.up": Map.currentLevel.metadata.initialOffsetMs++; break; case "editor.music.offset.down": Map.currentLevel.metadata.initialOffsetMs--; break; } } } Core.renderer.DrawText(bpmPos, $"BPM: {Game.currentBPM.ToString()}", ColorScheme.GetColor("bpm")); TimeSpan curTime = TimeSpan.FromMilliseconds(Game.timeFromStart.AsMilliseconds()); Core.renderer.DrawText(timePos, $"TIME: {(curTime < TimeSpan.Zero ? "'-'" : "")}{curTime.ToString($"{(curTime.Hours != 0 ? "h':'mm" : "m")}':'ss")}", ColorScheme.GetColor("time")); Core.renderer.DrawText(offsetPos, $"OFFSET: {Game.roundedOffset.ToString()} ({Game.roundedSteps.ToString()})", ColorScheme.GetColor("offset")); Core.renderer.DrawText(hpDrainPos, $" HP DRAIN: {Map.currentLevel.metadata.hpDrain.ToString()}", ColorScheme.GetColor("hp_drain")); Core.renderer.DrawText(hpRestoragePos, $" HP RESTORAGE: {Map.currentLevel.metadata.hpRestorage.ToString()}", ColorScheme.GetColor("hp_restorage")); Core.renderer.DrawText(musicOffsetPos, $" MUSIC OFFSET: {Map.currentLevel.metadata.initialOffsetMs.ToString()} MS", ColorScheme.GetColor("music_offset")); if (_musicSpeedSlider.Draw()) { Game.music.Pitch = _musicSpeedSlider.value / 100f; } DrawProgress(); DrawLevelName(levelNamePos, ColorScheme.GetColor("game_level_name")); DrawEditorDifficulty(musicTimePos, ColorScheme.GetColor("game_music_time")); } else { DrawHealth(); DrawProgress(); DrawScore(scorePos, ColorScheme.GetColor("score")); DrawAccuracy(accPos); DrawCombo(comboPos); DrawMiniScores(miniScoresPos, Game.scores); DrawLevelName(levelNamePos, ColorScheme.GetColor("game_level_name")); DrawMusicTime(musicTimePos, ColorScheme.GetColor("game_music_time")); LevelMetadata metadata = Map.currentLevel.metadata; if (metadata.skippable && Game.music.PlayingOffset.AsMilliseconds() < Map.currentLevel.metadata.skipTime && _skipButton.Draw()) { Game.music.PlayingOffset = Time.FromMilliseconds(Map.currentLevel.metadata.skipTime); } } }