bool IsTileInPlace(Vector2Int tile, TileInPlaceReport tileInPlaceReport, LevelDataManager.Descriptor descriptor) { int tileId = TileId(tile, descriptor); int currentTileId = TileId(tileInPlaceReport.current, descriptor); return(tileId <= currentTileId); }
void CheckForTutorialCompletion() { // the application might have been suddenly aborted or crashed // so check for the completeness of the very first two levels in the very first run // the level states are already loaded before MakeReady() if (GlobalManager.MStorage.FirstRound && !GlobalManager.MStorage.BonusCoinsAdded) { /* * LevelDataManager.Descriptor descriptor1 = GlobalManager.MLevel.GetDescriptor(1); * if (!descriptor1.state.Complete) * { * GlobalManager.MHint.ResetHintFlags(1); * GlobalManager.MLevel.ResetLevel(1); * LevelDataManager.Descriptor descriptor0 = GlobalManager.MLevel.GetDescriptor(0); * // ensure descriptor1 has actual level info * descriptor1 = GlobalManager.MLevel.GetDescriptor(1); * if (descriptor0.state.Complete) * { * descriptor1.state.Revealed = true; * descriptor1.state.Playable = true; * } * else * { * // reset remaining hints * GlobalManager.MHint.ResetHintFlags(0); * // totally reset the game * foreach (LevelDataManager.Descriptor descriptor in GlobalManager.MLevel.LevelDescriptors()) * { * GlobalManager.MLevel.ResetLevel(descriptor.init.id); * } * } * } */ LevelDataManager.Descriptor descriptor0 = GlobalManager.MLevel.GetDescriptor(0); if (!descriptor0.state.Complete) { // reset remaining hints GlobalManager.MHint.ResetHintFlags(0); // totally reset the game foreach (LevelDataManager.Descriptor descriptor in GlobalManager.MLevel.LevelDescriptors()) { GlobalManager.MLevel.ResetLevel(descriptor.init.id); } } } }
// this method adds bonus points for each assembled puzzle row void AddPointsBonuses(TileInPlaceReport tileInPlaceReport, LevelDataManager.Descriptor descriptor) { int startId = TileId(tileInPlaceReport.previous, descriptor) + 1; int endId = TileId(tileInPlaceReport.current, descriptor); int puzzleWidth = descriptor.init.width; //bool scoreChanged = false; for (int runId = startId; runId <= endId; runId++) { int x = runId % puzzleWidth; int y = runId / puzzleWidth; if (x == puzzleWidth - 1) { // a row is assembled long earnedPoints = descriptor.state.EarnedPoints; AddPoints(ref earnedPoints, (y + 1) * puzzleAssembledRowBonusStep); descriptor.state.EarnedPoints = earnedPoints; //scoreChanged = true; } } }
void OnPuzzleComplete(object sender, InstantMessageArgs args) { PuzzleCompleteStatus completeStatus = (PuzzleCompleteStatus)args.arg; if (!puzzleCompletionProcessed) { // this may be the first pass at tutorial levels puzzleCompletionProcessed = true; Debug.Log("GameManager.OnPuzzleComplete: set puzzleCompletionProcessed flag to true"); bool firstRound = GlobalManager.MStorage.FirstRound; if (completeStatus != null) { int nextLevelId = GlobalManager.MLevel.NextLevel(completeStatus.descriptor.init.id); int prevLevelId = GlobalManager.MLevel.PreviousLevel(completeStatus.descriptor.init.id); RealmData.Init realmData = RealmData.initializers[completeStatus.descriptor.init.realmId]; // set a message queue for the Victory screen if (completeStatus.firstTime) // a puzzle is assembled for the first time { GlobalManager.MQueue.PostMessage(levelCompletedId); if (completeStatus.descriptor.init.id == 0) // this is the very first puzzle in the game { GlobalManager.MStorage.GalleryLevel = completeStatus.descriptor.init.id; // set the gallery level to the newly completed one GlobalManager.MStorage.FirstGallery = true; // gallery message should be shown GlobalManager.MQueue.PostMessage(galleryOpenedId); // post a message about the gallery } if (completeStatus.descriptor.init.realmId >= 0) // this should always be true, yet... { if (realmData.mainLevelId == completeStatus.descriptor.init.id) { // main (first) level of the realm has been complete GlobalManager.MQueue.PostMessage(realmRevealedId); } } if (nextLevelId >= 0) { // there is another level to play at GlobalManager.MQueue.PostMessage(newLevelPlayableId); } } else { GlobalManager.MQueue.PostMessage(levelCompletedOnceAgainId); } // Do the accounting chores // Also report of achievements long earnedPoints = completeStatus.descriptor.state.EarnedPoints; if (firstRound) { switch (completeStatus.descriptor.init.id) { case 0: completeStatus.descriptor.state.EarnedPoints = ((completeStatus.descriptor.init.height + 1) * completeStatus.descriptor.init.height / 2) * puzzleAssembledRowBonusStep + firstRunLevel0Row0Bonus + puzzleCompleteBonus; GlobalManager.MAchievement.ReportNewAchievement(AchievementType.FirstPuzzleAssembled); break; case 1: completeStatus.descriptor.state.EarnedPoints = ((completeStatus.descriptor.init.height + 1) * completeStatus.descriptor.init.height / 2) * puzzleAssembledRowBonusStep + firstRunLevel1Row0Bonus + firstRunLevel1Row1Bonus + puzzleCompleteBonus; AddBonusCoins(); GlobalManager.MAchievement.ReportNewAchievement(AchievementType.SecondPuzzleAssembled); break; case 2: GlobalManager.MAchievement.ReportNewAchievement(AchievementType.ThirdPuzzleAssembled); break; default: AddPoints(ref earnedPoints, puzzleCompleteBonus); completeStatus.descriptor.state.EarnedPoints = earnedPoints; break; } } else { AddPoints(ref earnedPoints, puzzleCompleteBonus); completeStatus.descriptor.state.EarnedPoints = earnedPoints; } GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.GUIRotoChipsChanged, this, (decimal)completeStatus.descriptor.state.EarnedPoints); earnedPoints = GlobalManager.MStorage.CurrentPoints; AddPoints(ref earnedPoints, completeStatus.descriptor.state.EarnedPoints); GlobalManager.MStorage.CurrentPoints = earnedPoints; //completeStatus.descriptor.state.Complete = true; // set all the levels in the current realm revealed bool realmComplete = true; for (int i = 0; i < realmData.members.Length; i++) { LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(realmData.members[i]); if (!descriptor.state.Revealed) { descriptor.state.Revealed = true; } // check if all other levels in the realm are complete if (descriptor.init.id != completeStatus.descriptor.init.id && !descriptor.state.Complete) { realmComplete = false; } } // now add an achievement if (firstRound) { switch (completeStatus.descriptor.init.id) { case 0: break; case 1: break; } } if (nextLevelId >= 0) { // make next level revealed and playable LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(nextLevelId); descriptor.state.Revealed = true; descriptor.state.Playable = true; completeStatus.descriptor.state.NextPlayableId = nextLevelId; //GlobalManager.MStorage.SelectedLevel = nextLevelId; } if (prevLevelId >= 0) { // link previously completed level to the newly completed one LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(prevLevelId); descriptor.state.NextCompleteId = completeStatus.descriptor.init.id; } // check if the game is complete if (realmComplete) { GlobalManager.MQueue.PostMessage(realmCompletedId); if (realmData.id >= 0 && realmData.id < realmAchievements.Length) { GlobalManager.MAchievement.ReportNewAchievement(realmAchievements[realmData.id]); } if (nextLevelId < 0) // no more new levels { // the game is complete GlobalManager.MStorage.GameFinished = true; GlobalManager.MStorage.FirstRound = false; GlobalManager.MQueue.PostMessage(gameCompletedId); GlobalManager.MAchievement.ReportNewAchievement(AchievementType.FirstRunFinished); } else { GlobalManager.MQueue.PostMessage(realmOpenedId); } } } } // there may be some unshown hints; notify for puzzle processing completion otherwise if (puzzleHintsShown) { // this may be the second pass at tutorial levels (0 and 1) Debug.Log("GameManager.OnPuzzleComplete: all hints are shown, completing the level"); completeStatus.descriptor.state.Complete = true; GlobalManager.MStorage.SelectedLevel = GlobalManager.MLevel.NextLevel(completeStatus.descriptor.init.id); GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.PuzzleCompleteProcessed, this, completeStatus); } else { Debug.Log("GameManager.OnPuzzleComplete: not every hint is shown yet"); } }
// OnPuzzleTileInPlace is called whenever PuzzleController detects a new "good" puzzle state // This happens before any button rotation, so to correctly show a hint we have to wait until ther button rotation ends // Hence the usage of WaitForButtonRotation void OnPuzzleTileInPlace(object sender, InstantMessageArgs args) { bool firstRound = GlobalManager.MStorage.FirstRound; int selectedLevel = GlobalManager.MStorage.SelectedLevel; TileInPlaceReport tilesInPlace = (TileInPlaceReport)args.arg; LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(selectedLevel); if (firstRound) { switch (selectedLevel) { case 0: // only (0,0), (1,0), and (2,0) tiles are counted // the total points value for the completed level is recalculated in OnPuzzleComplete if (IsTileInPlace(new Vector2Int(descriptor.init.width - 1, 0), tilesInPlace, descriptor)) { // tile (2,0) is in place; first row assembled descriptor.state.EarnedPoints = firstRunLevel0Row0Bonus + puzzleAssembledRowBonusStep; //GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.RotoChipsChanged, this, (decimal)descriptor.state.EarnedPoints); StartCoroutine(WaitForButtonRotation(HintType.ThirdTileInPlace)); //GlobalManager.MHint.ShowNewHint(HintType.ThirdTileInPlace); } else if (IsTileInPlace(new Vector2Int(1, 0), tilesInPlace, descriptor)) { // tile (1,0) is in place StartCoroutine(WaitForButtonRotation(HintType.SecondTileInPlace)); //GlobalManager.MHint.ShowNewHint(HintType.SecondTileInPlace); } else if (IsTileInPlace(new Vector2Int(0, 0), tilesInPlace, descriptor)) { // tile (0,0) is in place StartCoroutine(WaitForButtonRotation(HintType.FirstTileInPlace)); //GlobalManager.MHint.ShowNewHint(HintType.FirstTileInPlace); } return; case 1: // only (2,0) and (2,1) tiles are counted // the total points value for the completed level is recalculated in OnPuzzleComplete if (IsTileInPlace(new Vector2Int(descriptor.init.width - 1, 1), tilesInPlace, descriptor)) { // second row assembled if (!puzzleCompletionProcessed) { descriptor.state.EarnedPoints = firstRunLevel1Row1Bonus + firstRunLevel1Row0Bonus + (2 + 1) * puzzleAssembledRowBonusStep; } StartCoroutine(WaitForButtonRotation(HintType.TwoRowsInPlace)); } else if (IsTileInPlace(new Vector2Int(descriptor.init.width - 1, 0), tilesInPlace, descriptor)) { // first row assembled if (!puzzleCompletionProcessed) { descriptor.state.EarnedPoints = firstRunLevel1Row0Bonus + puzzleAssembledRowBonusStep; } StartCoroutine(WaitForButtonRotation(HintType.FirstRowCongratulation)); } return; } } // calculate points bonuses if (!descriptor.state.AutocompleteUsed) { AddPointsBonuses(tilesInPlace, descriptor); } }
int TileId(Vector2Int tile, LevelDataManager.Descriptor descriptor) { return(tile.y * descriptor.init.width + tile.x); }
void OnGUIHintClosed(object sender, InstantMessageArgs args) { HintRequest hintRequest = (HintRequest)args.arg; bool firstRound = GlobalManager.MStorage.FirstRound; int selectedLevel = GlobalManager.MStorage.SelectedLevel; Debug.Log("GameManager.OnGUIHintClosed after " + hintRequest.type.ToString()); switch (sceneType) { case SceneType.World: if (firstRound) { switch (selectedLevel) { case 0: switch (hintRequest.type) { case HintType.FirstTimeWelcome: GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.WorldRotateToSelected, this); GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.RedirectFirstTimeWelcome2, this); worldWaits = StartCoroutine(WorldWaitsForHint()); break; case HintType.FirstTimeWelcome2: if (worldWaits != null) { // if hint has been closed before the world finishes to rotate StopCoroutine(worldWaits); worldWaits = null; GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.WorldRotationEnable, this, true); } break; } break; case 1: switch (hintRequest.type) { case HintType.GalleryOpened: if (worldWaits != null) { // if hint has been closed before the world finishes to rotate StopCoroutine(worldWaits); GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.WorldRotationEnable, this, true); } break; } break; } } break; case SceneType.Puzzle: if (firstRound) { switch (selectedLevel) { case 0: switch (hintRequest.type) { case HintType.PuzzleFirstShuffled: GlobalManager.MHint.ShowNewHint(HintType.FirstLevelChallenge); break; case HintType.FirstLevelChallenge: // this will actually show a FirstTileInPlace hint GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.RedirectFirstTileButtons, this); break; case HintType.FirstTileInPlace: // this will actually show a SecondTileButtonsHint GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.RedirectSecondTileButtons, this); break; case HintType.ThirdTileInPlace: // level 0 challenge complete GlobalManager.MHint.ShowNewHint(HintType.TwoRowsInPlace1); break; case HintType.TwoRowsInPlace1: // special processing for a completed puzzle puzzleHintsShown = true; Debug.Log("GameManager.OnGUIHintClosed: after " + hintRequest.type.ToString() + " puzzleCompletionProcessed is " + puzzleCompletionProcessed.ToString()); if (puzzleCompletionProcessed) { LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(selectedLevel); PuzzleCompleteStatus completeStatus = new PuzzleCompleteStatus { descriptor = descriptor, firstTime = !descriptor.state.Complete }; GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.PuzzleComplete, this, completeStatus); } else { GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.PuzzleAutocomplete, this); } break; } break; case 1: switch (hintRequest.type) { case HintType.TwoRowsInPlace: Debug.Log("GameManager.OnGUIHintClosed: after " + hintRequest.type.ToString() + " show new hint TwoRowsInPlace2"); AddBonusCoins(); GlobalManager.MHint.ShowNewHint(HintType.TwoRowsInPlace2); break; case HintType.TwoRowsInPlace2: // special processing for a completed puzzle puzzleHintsShown = true; Debug.Log("GameManager.OnGUIHintClosed: after " + hintRequest.type.ToString() + " puzzleCompletionProcessed is " + puzzleCompletionProcessed.ToString()); if (puzzleCompletionProcessed) { LevelDataManager.Descriptor descriptor = GlobalManager.MLevel.GetDescriptor(selectedLevel); PuzzleCompleteStatus completeStatus = new PuzzleCompleteStatus { descriptor = descriptor, firstTime = !descriptor.state.Complete }; GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.PuzzleComplete, this, completeStatus); } else { GlobalManager.MInstantMessage.DeliverMessage(InstantMessageType.PuzzleAutocomplete, this); } break; } break; } } break; } }