// Define the executable and variables state("Worms W.M.D") { // Game is loading (true between the menu and game music playing) bool loading : "Worms W.M.D.exe", 0xE0FBA12; // Only true when player's turn hotseat timer bool playerHotseatTimer : "Worms W.M.D.exe", 0xF10384D; // Not the timer the player can see, but a general timer with microseconds precision // starting from level load and ending on results page. // Only pauses when pausing the game float levelTimer : "Worms W.M.D.exe", 0xDCCF090; // Training time looks like mm:ss.ms string8 displayedTimer: "Worms W.M.D.exe", 0x0F103838, 0x2A8; // Current training mission name if selected string33 selectedTrainingMission : "Worms W.M.D.exe", 0x0F103540, 0xE8, 0x1C0, 0xDC, 0xAAC; // True when replaying bool replay : "Worms W.M.D.exe", 0x00415D8C, 0x0; // True when on the results page bool resultsPage : "Worms W.M.D.exe", 0xF10388D; } init { // Whether the first hotseat timer of a level is active vars.firstHotseatTimerEnded = false; // Training vars.isTraining = false; // whether we need to handle milliseconds vars.lastEnteredLevelTotalMillisecondsPlayed = 0; // sum of seconds played on the same level, including restarts vars.sumOfTurnTimesMs = 0; // SOTT, sum of turn times vars.currentTimerMilliseconds = 0; // milliseconds elapsed since start or restart of a level // bugfix #1: fixes restarting a level sometimes ignores the last game seconds. // this temp var keeps the last game timer in memory vars.tmpPreviousTimerMilliseconds = 0; // Campaign vars.currentTimerSecondsRemaining = 0; // seconds remaining since start or restart of a level // Helper vars vars.inGame = false; vars.comingFromMainMenu = true; vars.isFirstLevel = true; vars.shouldReset = false; } reset { if (vars.shouldReset) { return true; } } onReset { // Needed as init{} is entered on game launch only vars.sumOfTurnTimesMs = 0; } // State management update { //// Order of the following conditions matters if (current.replay) { // Fixes bug where timer would show replay time return false; } if (current.levelTimer < old.levelTimer && vars.inGame && !current.replay) { // fixes bug where game replay triggers a restart) print("Current level restarted"); if (vars.isFirstLevel) { vars.shouldReset = true; } else { // Sum timers if (vars.isTraining) { if (vars.currentTimerMilliseconds == 0) { // For bugfix #1: use previous timer value when occasionally the previous game timer already reset to 0 vars.lastEnteredLevelTotalMillisecondsPlayed += vars.tmpPreviousTimerMilliseconds; } else { vars.lastEnteredLevelTotalMillisecondsPlayed += vars.currentTimerMilliseconds; } } } } // When the mission timer is visible and it just changed if (current.displayedTimer != null && current.displayedTimer != old.displayedTimer || vars.shouldReset) { string displayedTimer = current.displayedTimer; double milliseconds = -1; vars.isTraining = displayedTimer.IndexOf('.') != -1 && ( current.selectedTrainingMission.Contains("Basic") || current.selectedTrainingMission.Contains("Training") || current.selectedTrainingMission.Contains("Advanced")); if (vars.isTraining) { string[] splitDurationMs = displayedTimer.Split('.'); milliseconds = Convert.ToInt32(splitDurationMs[1]); displayedTimer = splitDurationMs[0]; } string[] splitDuration = displayedTimer.Split(':'); int minutes = Convert.ToInt32(splitDuration[0]); int seconds = minutes * 60 + Convert.ToInt32(splitDuration[1]); if (vars.isTraining && milliseconds != -1) { milliseconds *= 10; milliseconds += 1000 * seconds; vars.tmpPreviousTimerMilliseconds = vars.currentTimerMilliseconds; // bugfix #1: keep previous timer value vars.currentTimerMilliseconds = milliseconds; } else if (seconds > 0) { vars.currentTimerSecondsRemaining = seconds; } } if (vars.comingFromMainMenu && (vars.currentTimerSecondsRemaining > 0 || vars.currentTimerMilliseconds > 0)) { print("New level started"); // Set state vars.inGame = true; vars.comingFromMainMenu = false; vars.isFirstLevel = false; } vars.firstHotseatTimerEnded = !current.playerHotseatTimer && current.playerHotseatTimer != old.playerHotseatTimer; } start { if (current.displayedTimer != null && vars.firstHotseatTimerEnded) { print("First level started"); if (vars.shouldReset) { vars.shouldReset = false; } // Set state vars.inGame = true; vars.comingFromMainMenu = false; vars.isFirstLevel = true; return true; } } split { if (current.resultsPage && vars.inGame) { print("Exited level, split"); // Sum & reset timers if (vars.isTraining) { vars.sumOfTurnTimesMs += vars.lastEnteredLevelTotalMillisecondsPlayed + vars.currentTimerMilliseconds; vars.currentTimerMilliseconds = 0; vars.lastEnteredLevelTotalMillisecondsPlayed = 0; } else { vars.currentTimerSecondsRemaining = 0; } // Set state vars.inGame = false; vars.comingFromMainMenu = true; return true; } } gameTime { if (vars.isTraining) { return TimeSpan.FromMilliseconds( vars.sumOfTurnTimesMs + vars.lastEnteredLevelTotalMillisecondsPlayed + vars.currentTimerMilliseconds); } } isLoading { if (vars.isTraining) { // Needed to prevent the timer from flashing (adding 0.01s) when paused return true; } return current.loading; }