/// <summary> /// Raised after a mod message is received over the network. /// </summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void MessageReceived(object sender, ModMessageReceivedEventArgs e) { // Has a message been received from CustomDeathPenaltyPlus of the type IDied? if (e.FromModID == this.ModManifest.UniqueID && e.Type == "IDied") { // Read data from message into a new class instance of Multiplayer Multiplayer multiplayer = e.ReadAs <Multiplayer>(); // Display a new HUD message to say that the dead player needs a new day to be started Game1.addHUDMessage(new HUDMessage($"{multiplayer.PlayerWhoDied} will need the rest of the day to recover.", null)); } }
/// <summary>Raised after the game state is updated</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void OnUpdateTicked(object sender, UpdateTickedEventArgs e) { // Reload events if needed if (true // Player has died, before killscreen is true && Game1.player.health <= 0 // death state has not been saved && PlayerStateRestorer.statedeathps.Value == null // location of death hasn't been saved && location == null // MoreRealisticWarps is true && this.config.OtherPenalties.MoreRealisticWarps == true) { // Save location of death location = Game1.currentLocation.NameOrUniqueName; // Reload events this.Helper.Content.InvalidateCache("Data\\Events\\Hospital"); } // Check if player died each half second if (e.IsMultipleOf(30)) { if (true // Has player died? && Game1.killScreen == true // Has the players death state been saved? && PlayerStateRestorer.statedeathps.Value == null) { // Save playerstate using DeathPenalty values PlayerStateRestorer.SaveStateDeath(); // Reload asset upon death to reflect amount lost this.Helper.Content.InvalidateCache("Strings\\StringsFromCSFiles"); // Will a new day be loaded in multiplayer after death? if (true // It is multiplayer && Context.IsMultiplayer == true // WakeupNextDayinClinic is true && this.config.OtherPenalties.WakeupNextDayinClinic == true) { // Set warptoinvisiblelocation to true togglesperscreen.Value.warptoinvisiblelocation = true; } } } if (true // Player death state has been saved && PlayerStateRestorer.statedeathps.Value != null // An event is in progress, this would be the PlayerKilled event && Game1.CurrentEvent != null) { // Set loadstate to true so state will be loaded after event togglesperscreen.Value.loadstate = true; // Current active menu can be downcast to an itemlistmenu if (Game1.activeClickableMenu as ItemListMenu != null) { // Will items be restored? if (this.config.DeathPenalty.RestoreItems == true) { // Yes, we don't want that menu, so close it and end the event // Close the menu Game1.activeClickableMenu.exitThisMenuNoSound(); // End the event Game1.CurrentEvent.exitEvent(); } // Load state earlier in multiplayer if (Context.IsMultiplayer == true) { // Restore playerstate using DeathPenalty values PlayerStateRestorer.LoadStateDeath(); // Clear state if WakeupNextDayinClinic is false, other stuff needs to be done if it's true if (this.config.OtherPenalties.WakeupNextDayinClinic == false) { // Reset PlayerStateRestorer class with the statedeath field PlayerStateRestorer.statedeathps.Value = null; // State already loaded and cleared, set loadstate to false togglesperscreen.Value.loadstate = false; } } // Should the player be warped where they can't be seen? if (togglesperscreen.Value.warptoinvisiblelocation == true) { // Yes, warp player to an invisible location Game1.warpFarmer(Game1.currentLocation.NameOrUniqueName, 1000, 1000, false); // Set warptoinvisiblelocation to false to stop endless warp loop togglesperscreen.Value.warptoinvisiblelocation = false; } // Set player exit location for event else if (true && this.config.OtherPenalties.MoreRealisticWarps == true && location != null) { if (location == "SkullCave" || (location.StartsWith("UndergroundMine") == true && Game1.currentLocation.NameOrUniqueName != "Mine")) { Game1.CurrentEvent.setExitLocation("SkullCave", 3, 5); } else if (true && (false || ModEntry.location.StartsWith("Farm") == true || Game1.getLocationFromName(ModEntry.location) as FarmHouse != null) && location.StartsWith("IslandFarm") == false) { int tileX = 12; int tileY = 18; switch (Game1.player.houseUpgradeLevel) { case 0: tileX = 3; tileY = 9; break; case 1: tileX = 9; tileY = 8; break; default: break; } Game1.CurrentEvent.setExitLocation(Game1.player.homeLocation.Value, tileX, tileY); } location = null; } } } if (true // Player death state has been saved && PlayerStateRestorer.statedeathps.Value != null // Player isn't warping && Game1.isWarping == false // No events are running && Game1.CurrentEvent == null // state should be loaded && togglesperscreen.Value.loadstate == true) { // Set loadstate to false togglesperscreen.Value.loadstate = false; // Start new day if necessary if (this.config.OtherPenalties.WakeupNextDayinClinic == true) { // Save necessary data to data model Game1.player.modData[$"{this.ModManifest.UniqueID}.DidPlayerWakeupinClinic"] = "true"; // Is the game multiplayer? if (Context.IsMultiplayer == false) { // No, load new day immediately Game1.NewDay(1.1f); } else { // Yes, inform other players you're ready for a new day Game1.player.team.SetLocalReady("sleep", true); // Ensures new day will load, will become false after new day is loaded Game1.player.passedOut = true; // Create class instance to hold player's name Multiplayer multiplayer = new Multiplayer { PlayerWhoDied = Game1.player.Name }; // Send data from class instance to other players, message type is IDied this.Helper.Multiplayer.SendMessage(multiplayer, "IDied", modIDs: new[] { this.ModManifest.UniqueID }); // Bring up a new menu that will launch a new day when all player's are ready Game1.activeClickableMenu = (IClickableMenu) new ReadyCheckDialog("sleep", false, (ConfirmationDialog.behavior)(_ => Game1.NewDay(1.1f))); // Reset PlayerStateRestorer class with the statedeath field PlayerStateRestorer.statedeathps.Value = null; // Add player to list of ready farmers if needed if (Game1.player.team.announcedSleepingFarmers.Contains(Game1.player) == true) { return; } Game1.player.team.announcedSleepingFarmers.Add(Game1.player); } } // Restore state after PlayerKilled event ends if new day hasn't been loaded else { // Restore Player state using DeathPenalty values PlayerStateRestorer.LoadStateDeath(); // Reset PlayerStateRestorer class with the statedeath field PlayerStateRestorer.statedeathps.Value = null; } } // Check if time is 2am or the player has passed out if (Game1.timeOfDay == 2600 || Game1.player.stamina <= -15) { // Set DidPlayerPassOutYesterday to true and DidPlayerWakeupinClinic to false in data model Game1.player.modData[$"{this.ModManifest.UniqueID}.DidPlayerPassOutYesterday"] = "true"; Game1.player.modData[$"{this.ModManifest.UniqueID}.DidPlayerWakeupinClinic"] = "false"; if (true // Player is not in FarmHouse && Game1.player.currentLocation as FarmHouse == null // Player is not in Cellar && Game1.player.currentLocation as Cellar == null // Player pass out state has not been saved && PlayerStateRestorer.statepassoutps.Value == null) { // Save playerstate using PassOutPenalty values PlayerStateRestorer.SaveStatePassout(); // Save amount lost to data model Game1.player.modData[$"{this.ModManifest.UniqueID}.MoneyLostLastPassOut"] = $"{(int)Math.Round(PlayerStateRestorer.statepassoutps.Value.moneylost)}"; } } // Load state earlier if it is multiplayer and it isn't 2AM or later if (Game1.timeOfDay < 2600 && Game1.player.canMove == true && Context.IsMultiplayer == true && PlayerStateRestorer.statepassoutps.Value != null) { // Load state and fix stamina PlayerStateRestorer.LoadStatePassout(); Game1.player.stamina = (int)(Game1.player.maxStamina * this.config.PassOutPenalty.EnergytoRestorePercentage); // Reset state PlayerStateRestorer.statepassoutps.Value = null; // Set shouldtogglepassoutdata to false, this prevents DidPlayerPassOutYesterday from becoming false when player goes to bed togglesperscreen.Value.shouldtogglepassoutdata = false; } // If player can stay up past 2am, discard saved values and reset changed properties in data model if (Game1.timeOfDay == 2610 && PlayerStateRestorer.statepassoutps.Value != null) { Game1.player.modData[$"{this.ModManifest.UniqueID}.DidPlayerPassOutYesterday"] = "false"; Game1.player.modData[$"{this.ModManifest.UniqueID}.MoneyLostLastPassOut"] = "0"; PlayerStateRestorer.statepassoutps.Value = null; } }
/// <summary>Raised after the game state is updated</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event data.</param> private void OnUpdateTicked(object sender, UpdateTickedEventArgs e) { //Check if player died each half second if (e.IsMultipleOf(30)) { if (true // Has player died? && Game1.killScreen // Has the players death state been saved? && PlayerStateRestorer.statedeath == null) { // Save playerstate using DeathPenalty values PlayerStateRestorer.SaveStateDeath(); // Reload asset upon death to reflect amount lost this.Helper.Content.InvalidateCache("Strings\\StringsFromCSFiles"); // Will a new day be loaded in multiplayer after death? if (true // It is multiplayer && Context.IsMultiplayer == true // WakeupNextDayinClinic is true && this.config.DeathPenalty.WakeupNextDayinClinic == true) { // Set warptoinvisiblelocation to true warptoinvisiblelocation = true; } } } if (true // Player death state has been saved && PlayerStateRestorer.statedeath != null // An event is in progress, this would be the PlayerKilled event && Game1.CurrentEvent != null // The current clickable menu can be downcast to an ItemListMenu && Game1.activeClickableMenu as ItemListMenu != null) { // Will items be restored? if (this.config.DeathPenalty.RestoreItems == true) { // Yes, we don't want that menu, so close it and end the event // Close the menu Game1.activeClickableMenu.exitThisMenuNoSound(); // End the event Game1.CurrentEvent.exitEvent(); } // Should the player be warped where they can't be seen? if (warptoinvisiblelocation == true) { // Yes, warp player to an invisible location Game1.warpFarmer(Game1.currentLocation.NameOrUniqueName, 1000, 1000, false); // Set warptoinvisiblelocation to false to stop endless warp loop warptoinvisiblelocation = false; } } // Restore state after PlayerKilled event ends if (true // Player death state has been saved && PlayerStateRestorer.statedeath != null // No events are running && Game1.CurrentEvent == null // Player can move && Game1.player.canMove) { // Check if WakeupNextDayinClinic is true if (this.config.DeathPenalty.WakeupNextDayinClinic == true) { // Yes, do some extra stuff // Save necessary data to data model ModEntry.PlayerData.DidPlayerWakeupinClinic = true; // Write data model to JSON file this.Helper.Data.WriteJsonFile <PlayerData>($"data\\{Constants.SaveFolderName}.json", ModEntry.PlayerData); // Is the game in multiplayer? if (Context.IsMultiplayer == false) { // No, new day can be loaded immediately // Warp player to clinic if it is not the current location if (Game1.currentLocation.NameOrUniqueName == "Mine") { Game1.warpFarmer("Hospital", 20, 12, false); } // Load new day Game1.NewDay(1.1f); } else { // Yes, inform other players you're ready for a new day Game1.player.team.SetLocalReady("sleep", true); // Ensures new day will load, will become false after new day is loaded Game1.player.passedOut = true; // Create class instance to hold player's name Multiplayer multiplayer = new Multiplayer { PlayerWhoDied = Game1.player.Name }; // Send data from class instance to other players, message type is IDied this.Helper.Multiplayer.SendMessage(multiplayer, "IDied", modIDs: new[] { this.ModManifest.UniqueID }); // Bring up a new menu that will launch a new day when all player's are ready Game1.activeClickableMenu = (IClickableMenu) new ReadyCheckDialog("sleep", false, (ConfirmationDialog.behavior)(_ => Game1.NewDay(1.1f))); // Add player to list of ready farmers if needed if (Game1.player.team.announcedSleepingFarmers.Contains(Game1.player)) { return; } Game1.player.team.announcedSleepingFarmers.Add(Game1.player); } } // Restore Player state using DeathPenalty values PlayerStateRestorer.LoadStateDeath(); // Write data model to JSON file this.Helper.Data.WriteJsonFile <PlayerData>($"data\\{Constants.SaveFolderName}.json", ModEntry.PlayerData); // Reset PlayerStateRestorer class with the statedeath field PlayerStateRestorer.statedeath = null; } // Chack if time is 2am or the player has passed out if (Game1.timeOfDay == 2600 || Game1.player.stamina <= -15) { // Set DidPlayerPassOutYesterday to true and DidPlayerWakeupinClinic to false in data model ModEntry.PlayerData.DidPlayerPassOutYesterday = true; ModEntry.PlayerData.DidPlayerWakeupinClinic = false; if (true // Player is not in FarmHouse && Game1.player.currentLocation as FarmHouse == null // Player is not in Cellar && Game1.player.currentLocation as Cellar == null // Player pass out state has not been saved && PlayerStateRestorer.statepassout == null) { // Save playerstate using PassOutPenalty values PlayerStateRestorer.SaveStatePassout(); // Save amount lost to data model ModEntry.PlayerData.MoneyLostLastPassOut = (int)Math.Round(PlayerStateRestorer.statepassout.moneylost); } } // If player can stay up past 2am, discard saved values and reset changed properties in data model if (Game1.timeOfDay == 2610) { if (PlayerStateRestorer.statepassout != null) { ModEntry.PlayerData.DidPlayerPassOutYesterday = false; ModEntry.PlayerData.MoneyLostLastPassOut = 0; PlayerStateRestorer.statepassout = null; } } }