Finished all of the updates for the SDV 1.4 update!
This commit is contained in:
parent
b4b1f79816
commit
1453812b50
|
@ -2260,5 +2260,48 @@ namespace Omegasis.HappyBirthday
|
|||
}
|
||||
return b.ToString();
|
||||
}
|
||||
|
||||
|
||||
public string getBirthdayMessage(string NPC)
|
||||
{
|
||||
if (Game1.player.friendshipData.ContainsKey(NPC))
|
||||
{
|
||||
if (Game1.player.getSpouse() != null) {
|
||||
if (Game1.player.getSpouse().Name.Equals(NPC))
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.spouseBirthdayWishes[NPC]))
|
||||
{
|
||||
return this.generateSpouseBirthdayDialogue(NPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.spouseBirthdayWishes[NPC];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.birthdayWishes.ContainsKey(NPC))
|
||||
{
|
||||
return this.birthdayWishes[NPC];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.birthdayWishes.ContainsKey(NPC))
|
||||
{
|
||||
return this.birthdayWishes[NPC];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Happy birthday @!";
|
||||
}
|
||||
}
|
||||
return "Happy birthday @!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -636,7 +636,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
conditions.Add(new StardustCore.Events.Preconditions.NPCSpecific.DatingNPC(shane));
|
||||
|
||||
EventHelper e = new EventHelper("BirthdayDating:Shane", 19960, conditions, new EventStartData("playful", 26, 15, new EventStartData.FarmerData(19, 18, EventHelper.FacingDirection.Left), new List<EventStartData.NPCData>() {
|
||||
new EventStartData.NPCData(shane,3,19, EventHelper.FacingDirection.Down),
|
||||
new EventStartData.NPCData(shane,25,16, EventHelper.FacingDirection.Down),
|
||||
}));
|
||||
e.globalFadeIn();
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
|
||||
/// <summary>The player's current birthday season.</summary>
|
||||
private string BirthdaySeason;
|
||||
private string seasonName;
|
||||
|
||||
/// <summary>The player's current birthday day.</summary>
|
||||
private int BirthdayDay;
|
||||
|
@ -46,6 +47,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
: base(Game1.viewport.Width / 2 - (632 + IClickableMenu.borderWidth * 2) / 2, Game1.viewport.Height / 2 - (600 + IClickableMenu.borderWidth * 2) / 2 - Game1.tileSize, 632 + IClickableMenu.borderWidth * 2, 600 + IClickableMenu.borderWidth * 2 + Game1.tileSize)
|
||||
{
|
||||
this.BirthdaySeason = HappyBirthday.Config.translationInfo.getTranslatedString(season);
|
||||
this.seasonName = season;
|
||||
this.BirthdayDay = day;
|
||||
this.OnChanged = onChanged;
|
||||
this.SetUpPositions();
|
||||
|
@ -147,8 +149,9 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
case "Fall":
|
||||
case "Winter":
|
||||
this.BirthdaySeason = HappyBirthday.Config.translationInfo.getTranslatedString(name);
|
||||
this.OnChanged(this.BirthdaySeason, this.BirthdayDay);
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.BirthdaySeason, this.BirthdayDay, this.OnChanged);
|
||||
this.seasonName = name;
|
||||
this.OnChanged(this.seasonName, this.BirthdayDay);
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.seasonName, this.BirthdayDay, this.OnChanged);
|
||||
break;
|
||||
|
||||
// OK button
|
||||
|
@ -160,8 +163,8 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
|
||||
default:
|
||||
this.BirthdayDay = Convert.ToInt32(name);
|
||||
this.OnChanged(this.BirthdaySeason, this.BirthdayDay);
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.BirthdaySeason, this.BirthdayDay, this.OnChanged);
|
||||
this.OnChanged(this.seasonName, this.BirthdayDay);
|
||||
Game1.activeClickableMenu = new BirthdayMenu(this.seasonName, this.BirthdayDay, this.OnChanged);
|
||||
break;
|
||||
}
|
||||
Game1.playSound("coin");
|
||||
|
@ -174,7 +177,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
public override void receiveLeftClick(int x, int y, bool playSound = true)
|
||||
{
|
||||
//If the season is not selected then the day buttons can't be clicked. Thanks to @Potato#5266 on the SDV discord for this tip.
|
||||
if (string.IsNullOrEmpty(this.BirthdaySeason)==false)
|
||||
if (string.IsNullOrEmpty(this.seasonName)==false)
|
||||
{
|
||||
foreach (ClickableTextureComponent button in this.DayButtons)
|
||||
{
|
||||
|
@ -199,7 +202,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
|
||||
if (this.OkButton.containsPoint(x, y))
|
||||
{
|
||||
if (this.BirthdaySeason == "" || this.BirthdayDay == 0) return;
|
||||
if (this.seasonName == "" || this.BirthdayDay == 0) return;
|
||||
this.HandleButtonClick(this.OkButton.name);
|
||||
this.OkButton.scale -= 0.25f;
|
||||
this.OkButton.scale = Math.Max(0.75f, this.OkButton.scale);
|
||||
|
@ -247,7 +250,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
//Game1.player.FarmerSprite.draw(b, new Vector2((this.xPositionOnScreen + Game1.tileSize + Game1.tileSize * 2 / 3 - 2), (this.yPositionOnScreen + IClickableMenu.borderWidth + IClickableMenu.spaceToClearTopBorder - Game1.tileSize / 4)),1f);
|
||||
|
||||
// draw day buttons
|
||||
if (string.IsNullOrEmpty(this.BirthdaySeason)==false)
|
||||
if (string.IsNullOrEmpty(this.seasonName)==false)
|
||||
{
|
||||
foreach (ClickableTextureComponent button in this.DayButtons)
|
||||
button.draw(b);
|
||||
|
@ -273,7 +276,7 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
}
|
||||
|
||||
// draw OK button
|
||||
if (this.BirthdayDay != 0 && this.BirthdaySeason != "")
|
||||
if (this.BirthdayDay != 0 && this.seasonName != "")
|
||||
this.OkButton.draw(b);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -220,11 +220,10 @@ namespace Omegasis.HappyBirthday.Framework
|
|||
|
||||
public string getTranslatedString(string Key)
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(Key)) return "";
|
||||
if (Key.Equals("Birthday"))
|
||||
{
|
||||
string s = Game1.content.LoadString("Strings\\UI:Billboard_Birthday");
|
||||
s = s.Split(' ')[0];
|
||||
string s = Game1.content.LoadString("Strings\\UI:Profile_Birthday");
|
||||
return s;
|
||||
}
|
||||
if (Key.Equals("Spring") || Key.Equals("spring"))
|
||||
|
|
|
@ -96,6 +96,7 @@ namespace Omegasis.HappyBirthday
|
|||
helper.Events.Multiplayer.PeerDisconnected += this.Multiplayer_PeerDisconnected;
|
||||
helper.Events.GameLoop.GameLaunched += this.GameLoop_GameLaunched;
|
||||
helper.Events.Player.Warped += this.Player_Warped;
|
||||
helper.Events.GameLoop.ReturnedToTitle += this.GameLoop_ReturnedToTitle;
|
||||
ModHelper = this.Helper;
|
||||
ModMonitor = this.Monitor;
|
||||
|
||||
|
@ -105,6 +106,11 @@ namespace Omegasis.HappyBirthday
|
|||
|
||||
}
|
||||
|
||||
private void GameLoop_ReturnedToTitle(object sender, ReturnedToTitleEventArgs e)
|
||||
{
|
||||
this.eventManager = new EventManager();
|
||||
}
|
||||
|
||||
private void Player_Warped(object sender, WarpedEventArgs e)
|
||||
{
|
||||
if (e.NewLocation == Game1.getLocationFromName("CommunityCenter"))
|
||||
|
@ -416,132 +422,8 @@ namespace Omegasis.HappyBirthday
|
|||
if ((Game1.player.getFriendshipHeartLevelForNPC(Game1.currentSpeaker.Name) < Config.minimumFriendshipLevelForBirthdayWish)) return;
|
||||
if (Game1.activeClickableMenu is StardewValley.Menus.DialogueBox && this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayWish==false && (Game1.player.getFriendshipHeartLevelForNPC(Game1.currentSpeaker.Name) >= Config.minimumFriendshipLevelForBirthdayWish))
|
||||
{
|
||||
IReflectedField < Dialogue > cDialogue= this.Helper.Reflection.GetField<Dialogue>((Game1.activeClickableMenu as DialogueBox), "characterDialogue", true);
|
||||
IReflectedField<List<string>> dialogues = this.Helper.Reflection.GetField<List<string>>((Game1.activeClickableMenu as DialogueBox), "dialogues", true);
|
||||
string dialogueMessage = "";
|
||||
if (Game1.player.getSpouse() != null)
|
||||
{
|
||||
if (Game1.player.getSpouse().Name.Equals(Game1.currentSpeaker.Name))
|
||||
{
|
||||
if (this.messages.spouseBirthdayWishes.ContainsKey(Game1.currentSpeaker.Name))
|
||||
{
|
||||
dialogueMessage = this.messages.spouseBirthdayWishes[Game1.currentSpeaker.Name];
|
||||
if (string.IsNullOrEmpty(dialogueMessage))
|
||||
{
|
||||
dialogueMessage = this.messages.generateSpouseBirthdayDialogue(Game1.currentSpeaker.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dialogueMessage = this.messages.generateSpouseBirthdayDialogue(Game1.currentSpeaker.Name);
|
||||
if (string.IsNullOrEmpty(dialogueMessage))
|
||||
{
|
||||
dialogueMessage = "Happy Birthday @!";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.messages.birthdayWishes.ContainsKey(Game1.currentSpeaker.Name))
|
||||
{
|
||||
|
||||
dialogueMessage = this.messages.birthdayWishes[Game1.currentSpeaker.Name];
|
||||
}
|
||||
else
|
||||
{
|
||||
dialogueMessage = "Happy Birthday @!";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.messages.birthdayWishes.ContainsKey(Game1.currentSpeaker.Name))
|
||||
{
|
||||
|
||||
dialogueMessage = this.messages.birthdayWishes[Game1.currentSpeaker.Name];
|
||||
}
|
||||
else
|
||||
{
|
||||
dialogueMessage = "Happy Birthday @!";
|
||||
}
|
||||
}
|
||||
dialogueMessage = dialogueMessage.Replace("@", Game1.player.Name);
|
||||
|
||||
|
||||
if (dialogues.GetValue().Contains(dialogueMessage))
|
||||
{
|
||||
string name = Game1.currentSpeaker.Name;
|
||||
this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayWish = true;
|
||||
/*
|
||||
if (this.IsBirthday() && this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayGift==false && Game1.player.getFriendshipHeartLevelForNPC(name) >= Config.minNeutralFriendshipGiftLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.giftManager.SetNextBirthdayGift(Game1.currentSpeaker.Name);
|
||||
this.Monitor.Log("Setting next birthday gift.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log(ex.ToString(), LogLevel.Error);
|
||||
}
|
||||
}
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (cDialogue.GetValue() != null)
|
||||
{
|
||||
if (cDialogue.GetValue().getCurrentDialogue() == dialogueMessage)
|
||||
{
|
||||
string name = Game1.currentSpeaker.Name;
|
||||
this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayWish = true;
|
||||
|
||||
if (this.IsBirthday() && this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayGift == false && Game1.player.getFriendshipHeartLevelForNPC(name) >= Config.minNeutralFriendshipGiftLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.giftManager.SetNextBirthdayGift(Game1.currentSpeaker.Name);
|
||||
this.Monitor.Log("Setting next birthday gift. 3");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log(ex.ToString(), LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Dialogue d;
|
||||
if (Game1.player.getSpouse() != null)
|
||||
{
|
||||
if (this.messages.spouseBirthdayWishes.ContainsKey(Game1.currentSpeaker.Name))
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.messages.spouseBirthdayWishes[Game1.currentSpeaker.Name])== false){
|
||||
d = new Dialogue(this.messages.spouseBirthdayWishes[Game1.currentSpeaker.Name], Game1.currentSpeaker);
|
||||
}
|
||||
else
|
||||
{
|
||||
d =new Dialogue(this.messages.generateSpouseBirthdayDialogue(Game1.currentSpeaker.Name),Game1.currentSpeaker);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new Dialogue("Happy Birthday @!", Game1.currentSpeaker);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.messages.birthdayWishes.ContainsKey(Game1.currentSpeaker.Name))
|
||||
{
|
||||
d = new Dialogue(this.messages.birthdayWishes[Game1.currentSpeaker.Name], Game1.currentSpeaker);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = new Dialogue("Happy Birthday @!", Game1.currentSpeaker);
|
||||
}
|
||||
}
|
||||
//IReflectedField < Dialogue > cDialogue= this.Helper.Reflection.GetField<Dialogue>((Game1.activeClickableMenu as DialogueBox), "characterDialogue", true);
|
||||
//IReflectedField<List<string>> dialogues = this.Helper.Reflection.GetField<List<string>>((Game1.activeClickableMenu as DialogueBox), "dialogues", true);
|
||||
Game1.currentSpeaker.resetCurrentDialogue();
|
||||
Game1.currentSpeaker.resetSeasonalDialogue();
|
||||
this.Helper.Reflection.GetMethod(Game1.currentSpeaker, "loadCurrentDialogue", true).Invoke();
|
||||
|
@ -558,7 +440,8 @@ namespace Omegasis.HappyBirthday
|
|||
this.Monitor.Log(ex.ToString(), LogLevel.Error);
|
||||
}
|
||||
}
|
||||
Game1.activeClickableMenu = new DialogueBox(d);
|
||||
|
||||
Game1.activeClickableMenu = new DialogueBox(new Dialogue(this.messages.getBirthdayMessage(Game1.currentSpeaker.Name),Game1.currentSpeaker));
|
||||
this.VillagerQueue[Game1.currentSpeaker.Name].hasGivenBirthdayWish = true;
|
||||
|
||||
// Set birthday gift for the player to recieve from the npc they are currently talking with.
|
||||
|
@ -612,7 +495,8 @@ namespace Omegasis.HappyBirthday
|
|||
this.CheckedForBirthday = false;
|
||||
|
||||
// load settings
|
||||
this.MigrateLegacyData();
|
||||
//
|
||||
//this.MigrateLegacyData();
|
||||
this.PlayerData = this.Helper.Data.ReadJsonFile<PlayerData>(this.DataFilePath) ?? new PlayerData();
|
||||
|
||||
if (HappyBirthday.Config.autoSetTranslation)
|
||||
|
@ -622,7 +506,7 @@ namespace Omegasis.HappyBirthday
|
|||
|
||||
if (PlayerBirthdayData != null)
|
||||
{
|
||||
ModMonitor.Log("Send all birthday information from " + Game1.player.Name);
|
||||
//ModMonitor.Log("Send all birthday information from " + Game1.player.Name);
|
||||
MultiplayerSupport.SendBirthdayInfoToOtherPlayers();
|
||||
}
|
||||
|
||||
|
@ -715,6 +599,7 @@ namespace Omegasis.HappyBirthday
|
|||
this.eventManager.addEvent(birthdayDating_Harvey);
|
||||
this.eventManager.addEvent(birthdayDating_Elliott);
|
||||
this.eventManager.addEvent(birthdayDating_Sam);
|
||||
this.eventManager.addEvent(birthdayDating_Alex);
|
||||
this.eventManager.addEvent(birthdayDating_Shane);
|
||||
if (Game1.player.eventsSeen.Contains(communityCenterJunimoBirthday.getEventID()))
|
||||
{
|
||||
|
@ -815,7 +700,7 @@ namespace Omegasis.HappyBirthday
|
|||
string starMessage = BirthdayMessages.GetTranslatedString("Happy Birthday: Star Message");
|
||||
|
||||
|
||||
ModMonitor.Log(starMessage);
|
||||
//ModMonitor.Log(starMessage);
|
||||
Messages.ShowStarMessage(starMessage);
|
||||
MultiplayerSupport.SendBirthdayMessageToOtherPlayers();
|
||||
|
||||
|
@ -912,7 +797,6 @@ namespace Omegasis.HappyBirthday
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (Game1.player.CanReadJunimo())
|
||||
{
|
||||
Game1.player.mailbox.Add("birthdayJunimos");
|
||||
|
@ -925,64 +809,10 @@ namespace Omegasis.HappyBirthday
|
|||
{
|
||||
if (npc is Child || npc is Horse || npc is Junimo || npc is Monster || npc is Pet)
|
||||
continue;
|
||||
|
||||
//Add in birthday dialogues for npc.
|
||||
try
|
||||
{
|
||||
if (Game1.player.getFriendshipHeartLevelForNPC(npc.Name) >= Config.minimumFriendshipLevelForBirthdayWish)
|
||||
{
|
||||
bool spouseMessage = false; //Used to determine if there is a valid spouse message for the player. If false load in the generic birthday wish.
|
||||
//Check if npc name is spouse's name. If no spouse then add in generic dialogue.
|
||||
if (this.messages.spouseBirthdayWishes.ContainsKey(npc.Name) && Game1.player.isMarried())
|
||||
{
|
||||
if (Game1.player.getSpouse().Name.Equals(npc.Name))
|
||||
{
|
||||
//this.Monitor.Log("Spouse Checks out");
|
||||
//Check to see if spouse message exists.
|
||||
if (!string.IsNullOrEmpty(this.messages.spouseBirthdayWishes[npc.Name]))
|
||||
{
|
||||
spouseMessage = true;
|
||||
|
||||
string message = this.messages.spouseBirthdayWishes[npc.Name];
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
message = this.messages.generateSpouseBirthdayDialogue(npc.Name);
|
||||
}
|
||||
Dialogue d = new Dialogue(message, npc);
|
||||
npc.CurrentDialogue.Push(d);
|
||||
if (npc.CurrentDialogue.ElementAt(0) != d) npc.setNewDialogue(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
string message = this.messages.generateSpouseBirthdayDialogue(npc.Name);
|
||||
Dialogue d = new Dialogue(message, npc);
|
||||
npc.CurrentDialogue.Push(d);
|
||||
if (npc.CurrentDialogue.ElementAt(0) != d) npc.setNewDialogue(message);
|
||||
spouseMessage = true;
|
||||
this.Monitor.Log("No spouse message???", LogLevel.Warn);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!spouseMessage)
|
||||
{
|
||||
//Load in
|
||||
Dialogue d = new Dialogue(this.messages.birthdayWishes[npc.Name], npc);
|
||||
npc.CurrentDialogue.Push(d);
|
||||
if (npc.CurrentDialogue.Peek() != d) npc.setNewDialogue(this.messages.birthdayWishes[npc.Name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (Game1.player.getFriendshipHeartLevelForNPC(npc.Name) >= Config.minimumFriendshipLevelForBirthdayWish)
|
||||
{
|
||||
Dialogue d = new Dialogue("Happy Birthday @!", npc);
|
||||
npc.CurrentDialogue.Push(d);
|
||||
if (npc.CurrentDialogue.Peek() != d)
|
||||
npc.setNewDialogue("Happy Birthday @!");
|
||||
}
|
||||
}
|
||||
string message = this.messages.getBirthdayMessage(npc.Name);
|
||||
Dialogue d = new Dialogue(message, npc);
|
||||
npc.CurrentDialogue.Push(d);
|
||||
if (npc.CurrentDialogue.ElementAt(0) != d) npc.setNewDialogue(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1034,9 +864,10 @@ namespace Omegasis.HappyBirthday
|
|||
{
|
||||
return
|
||||
this.PlayerData.BirthdayDay == Game1.dayOfMonth
|
||||
&& this.PlayerData.BirthdaySeason.Equals(Game1.currentSeason);
|
||||
&& this.PlayerData.BirthdaySeason.ToLower().Equals(Game1.currentSeason.ToLower());
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>Migrate the legacy settings for the current player.</summary>
|
||||
private void MigrateLegacyData()
|
||||
{
|
||||
|
@ -1072,5 +903,6 @@ namespace Omegasis.HappyBirthday
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"Name": "Happy Birthday",
|
||||
"Author": "Alpha_Omegasis",
|
||||
"Version": "1.10.0",
|
||||
"Version": "1.10.4",
|
||||
"Description": "Adds the farmer's birthday to the game.",
|
||||
"UniqueID": "Omegasis.HappyBirthday",
|
||||
"EntryDll": "HappyBirthday.dll",
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework;
|
||||
using StardewValley;
|
||||
|
||||
namespace Omegasis.SaveAnywhere.Framework
|
||||
{
|
||||
public static class NPCExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Fill in the npcs schedule with a billion end points and hope they find their way again?
|
||||
/// </summary>
|
||||
/// <param name="npc"></param>
|
||||
public static void fillInSchedule(this NPC npc)
|
||||
{
|
||||
if (npc.Schedule == null) return;
|
||||
|
||||
|
||||
|
||||
IDictionary<string, string> rawSchedule = GetRawSchedule(npc.Name);
|
||||
if (rawSchedule == null)
|
||||
return;
|
||||
string schedulekey = GetScheduleKey(npc);
|
||||
rawSchedule.TryGetValue(schedulekey, out string scheduleForTheDay);
|
||||
|
||||
if (string.IsNullOrEmpty(scheduleForTheDay))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// parse entries
|
||||
string[] entries = scheduleForTheDay.Split('/');
|
||||
//make a class to get all of the schedule info.....
|
||||
|
||||
|
||||
int scheduleIndex = 0;
|
||||
|
||||
SortedDictionary<int, SchedulePathInfo> actualScheduleData = new SortedDictionary<int, SchedulePathInfo>(); //time of day and the the path info.
|
||||
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
{
|
||||
|
||||
|
||||
string[] fields = entries[i].Split(' ');
|
||||
|
||||
// handle GOTO command
|
||||
if (fields[0].Equals("GOTO"))
|
||||
{
|
||||
rawSchedule.TryGetValue(fields[1], out scheduleForTheDay);
|
||||
entries = scheduleForTheDay.Split('/');
|
||||
i = -1;
|
||||
}
|
||||
|
||||
|
||||
SchedulePathInfo info2 = new SchedulePathInfo(entries[i]);
|
||||
if (info2.timeToGoTo == 0) continue;
|
||||
|
||||
else
|
||||
{
|
||||
actualScheduleData.Add(info2.timeToGoTo, info2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
List<KeyValuePair<int, SchedulePathInfo>> scheduleData = actualScheduleData.ToList();
|
||||
scheduleData.OrderBy(i => i.Key);
|
||||
|
||||
for (int time = 600; time <= 2600; time += 10)
|
||||
{
|
||||
|
||||
if (index >= scheduleData.Count)
|
||||
{
|
||||
if (actualScheduleData.ContainsKey(time) == false)
|
||||
{
|
||||
actualScheduleData.Add(time, scheduleData[scheduleData.Count-1].Value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == scheduleData.Count - 1)
|
||||
{
|
||||
if (actualScheduleData.ContainsKey(time)==false)
|
||||
{
|
||||
actualScheduleData.Add(time, scheduleData[index].Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (time == scheduleData[index + 1].Key)
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actualScheduleData.ContainsKey(time) == false)
|
||||
{
|
||||
actualScheduleData.Add(time, scheduleData[index].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//SaveAnywhere.ModMonitor.Log("Count of schedule size is: " + npc.Name + " " + actualScheduleData.Count, StardewModdingAPI.LogLevel.Info);
|
||||
//npc.checkSchedule(Game1.timeOfDay);
|
||||
|
||||
|
||||
|
||||
SchedulePathInfo info = actualScheduleData[Game1.timeOfDay];
|
||||
|
||||
SchedulePathDescription schedulePathDescription;
|
||||
schedulePathDescription = SaveAnywhere.ModHelper.Reflection
|
||||
.GetMethod(npc, "pathfindToNextScheduleLocation")
|
||||
.Invoke<SchedulePathDescription>(npc.currentLocation.Name, npc.getTileX(), npc.getTileY(), info.endMap, info.endX, info.endY, info.endDirection, info.endBehavior, info.endMessage);
|
||||
|
||||
npc.DirectionsToNewLocation = schedulePathDescription;
|
||||
npc.controller = new PathFindController(npc.DirectionsToNewLocation.route, npc, Utility.getGameLocationOfCharacter(npc))
|
||||
{
|
||||
finalFacingDirection = npc.DirectionsToNewLocation.facingDirection,
|
||||
endBehaviorFunction = null
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Get an NPC's raw schedule data from the XNB files.</summary>
|
||||
/// <param name="npcName">The NPC name whose schedules to read.</param>
|
||||
/// <returns>Returns the NPC schedule if found, else <c>null</c>.</returns>
|
||||
private static IDictionary<string, string> GetRawSchedule(string npcName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Game1.content.Load<Dictionary<string, string>>($"Characters\\schedules\\{npcName}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetScheduleKey(NPC npc)
|
||||
{
|
||||
string str = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
string scheduleKey = "";
|
||||
if (npc.Name.Equals("Penny") && (str.Equals("Tue") || str.Equals("Wed") || str.Equals("Fri")) || (npc.Name.Equals("Maru") && (str.Equals("Tue") || str.Equals("Thu")) || npc.Name.Equals("Harvey") && (str.Equals("Tue") || str.Equals("Thu"))))
|
||||
{
|
||||
scheduleKey = "marriageJob";
|
||||
}
|
||||
if (!Game1.isRaining && npc.hasMasterScheduleEntry("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
{
|
||||
scheduleKey = "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
}
|
||||
if (npc.hasMasterScheduleEntry(Game1.currentSeason + "_" + Game1.dayOfMonth.ToString()))
|
||||
{
|
||||
scheduleKey = Game1.currentSeason + "_" + Game1.dayOfMonth.ToString();
|
||||
}
|
||||
|
||||
int playerFriendshipLevel1 = Utility.GetAllPlayerFriendshipLevel(npc);
|
||||
if (playerFriendshipLevel1 >= 0)
|
||||
playerFriendshipLevel1 /= 250;
|
||||
for (; playerFriendshipLevel1 > 0; --playerFriendshipLevel1)
|
||||
{
|
||||
if (npc.hasMasterScheduleEntry(Game1.dayOfMonth.ToString() + "_" + (object)playerFriendshipLevel1))
|
||||
scheduleKey = Game1.dayOfMonth.ToString() + "_" + (object)playerFriendshipLevel1;
|
||||
}
|
||||
if (npc.hasMasterScheduleEntry(Game1.dayOfMonth.ToString()))
|
||||
scheduleKey = Game1.dayOfMonth.ToString();
|
||||
if (npc.Name.Equals("Pam") && Game1.player.mailReceived.Contains("ccVault"))
|
||||
scheduleKey = "bus";
|
||||
|
||||
if (Game1.isRaining)
|
||||
{
|
||||
if (Game1.random.NextDouble() < 0.5 && npc.hasMasterScheduleEntry("rain2"))
|
||||
scheduleKey = "rain2";
|
||||
if (npc.hasMasterScheduleEntry("rain"))
|
||||
scheduleKey = "rain";
|
||||
}
|
||||
|
||||
List<string> stringList = new List<string>()
|
||||
{
|
||||
Game1.currentSeason,
|
||||
Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)
|
||||
};
|
||||
int playerFriendshipLevel2 = Utility.GetAllPlayerFriendshipLevel(npc);
|
||||
if (playerFriendshipLevel2 >= 0)
|
||||
playerFriendshipLevel2 /= 250;
|
||||
while (playerFriendshipLevel2 > 0)
|
||||
{
|
||||
stringList.Add(string.Empty + (object)playerFriendshipLevel2);
|
||||
if (npc.hasMasterScheduleEntry(string.Join("_", (IEnumerable<string>)stringList)))
|
||||
{
|
||||
scheduleKey = string.Join("_", (IEnumerable<string>)stringList);
|
||||
break;
|
||||
}
|
||||
--playerFriendshipLevel2;
|
||||
stringList.RemoveAt(stringList.Count - 1);
|
||||
}
|
||||
if (npc.hasMasterScheduleEntry(string.Join("_", (IEnumerable<string>)stringList)))
|
||||
scheduleKey = string.Join("_", (IEnumerable<string>)stringList);
|
||||
if (npc.hasMasterScheduleEntry(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
scheduleKey = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
if (npc.hasMasterScheduleEntry(Game1.currentSeason))
|
||||
scheduleKey = Game1.currentSeason;
|
||||
if (npc.hasMasterScheduleEntry("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
scheduleKey = "spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
|
||||
stringList.RemoveAt(stringList.Count - 1);
|
||||
stringList.Add("spring");
|
||||
int playerFriendshipLevel3 = Utility.GetAllPlayerFriendshipLevel(npc);
|
||||
if (playerFriendshipLevel3 >= 0)
|
||||
playerFriendshipLevel3 /= 250;
|
||||
while (playerFriendshipLevel3 > 0)
|
||||
{
|
||||
stringList.Add(string.Empty + (object)playerFriendshipLevel3);
|
||||
if (npc.hasMasterScheduleEntry(string.Join("_", (IEnumerable<string>)stringList)))
|
||||
scheduleKey = string.Join("_", (IEnumerable<string>)stringList);
|
||||
--playerFriendshipLevel3;
|
||||
stringList.RemoveAt(stringList.Count - 1);
|
||||
}
|
||||
if (npc.hasMasterScheduleEntry("spring"))
|
||||
scheduleKey = "spring";
|
||||
else
|
||||
{
|
||||
scheduleKey = "";
|
||||
}
|
||||
return scheduleKey;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Omegasis.SaveAnywhere.Framework
|
||||
{
|
||||
public class SaveAnywhereAPI
|
||||
{
|
||||
public SaveAnywhereAPI()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void addBeforeSaveEvent(string ID, Action BeforeSave)
|
||||
{
|
||||
SaveAnywhere.Instance.SaveManager.beforeCustomSavingBegins.Add(ID, BeforeSave);
|
||||
}
|
||||
public void addAfterSaveEvent(string ID, Action BeforeSave)
|
||||
{
|
||||
SaveAnywhere.Instance.SaveManager.afterCustomSavingCompleted.Add(ID, BeforeSave);
|
||||
}
|
||||
public void addAfterLoadEvent(string ID, Action BeforeSave)
|
||||
{
|
||||
SaveAnywhere.Instance.SaveManager.afterSaveLoaded.Add(ID, BeforeSave);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -36,6 +36,9 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
private NewSaveGameMenu currentSaveMenu;
|
||||
|
||||
|
||||
public Dictionary<string, Action> beforeCustomSavingBegins;
|
||||
public Dictionary<string, Action> afterCustomSavingCompleted;
|
||||
public Dictionary<string, Action> afterSaveLoaded;
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -50,6 +53,10 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
this.Reflection = reflection;
|
||||
this.OnLoaded = onLoaded;
|
||||
|
||||
this.beforeCustomSavingBegins = new Dictionary<string, Action>();
|
||||
this.afterCustomSavingCompleted = new Dictionary<string, Action>();
|
||||
this.afterSaveLoaded = new Dictionary<string, Action>();
|
||||
|
||||
}
|
||||
|
||||
private void empty(object o, EventArgs args) { }
|
||||
|
@ -74,7 +81,12 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
{
|
||||
this.currentSaveMenu.SaveComplete -= this.CurrentSaveMenu_SaveComplete;
|
||||
this.currentSaveMenu = null;
|
||||
SaveAnywhere.RestoreMonsters();
|
||||
//AfterSave.Invoke(this, EventArgs.Empty);
|
||||
foreach (var v in this.afterCustomSavingCompleted)
|
||||
{
|
||||
v.Value.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Clear saved data.</summary>
|
||||
|
@ -87,16 +99,31 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
this.RemoveLegacyDataForThisPlayer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if a custom save file exists for the player.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool saveDataExists()
|
||||
{
|
||||
return File.Exists(Path.Combine(this.Helper.DirectoryPath, this.RelativeDataPath));
|
||||
}
|
||||
|
||||
/// <summary>Initiate a game save.</summary>
|
||||
public void BeginSaveData()
|
||||
{
|
||||
|
||||
foreach(var v in this.beforeCustomSavingBegins)
|
||||
{
|
||||
v.Value.Invoke();
|
||||
}
|
||||
|
||||
// save game data
|
||||
Farm farm = Game1.getFarm();
|
||||
if (farm.shippingBin.Any())
|
||||
if (farm.getShippingBin(Game1.player)!=null)
|
||||
{
|
||||
|
||||
Game1.activeClickableMenu = new NewShippingMenu(farm.shippingBin, this.Reflection);
|
||||
farm.shippingBin.Clear();
|
||||
Game1.activeClickableMenu = new NewShippingMenu(farm.getShippingBin(Game1.player), this.Reflection);
|
||||
farm.getShippingBin(Game1.player).Clear();
|
||||
farm.lastItemShipped = null;
|
||||
this.WaitingToSave = true;
|
||||
}
|
||||
|
@ -134,6 +161,10 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
this.ResumeSwimming(data);
|
||||
this.SetPositions(data.Characters);
|
||||
this.OnLoaded?.Invoke();
|
||||
foreach (var v in this.afterSaveLoaded)
|
||||
{
|
||||
v.Value.Invoke();
|
||||
}
|
||||
|
||||
// Notify other mods that load is complete
|
||||
//AfterLoad.Invoke(this, EventArgs.Empty);
|
||||
|
@ -197,7 +228,7 @@ namespace Omegasis.SaveAnywhere.Framework
|
|||
{
|
||||
// player
|
||||
{
|
||||
CharacterData data = positions.FirstOrDefault(p => p.Type == CharacterType.Player && p.Name == Game1.player.Name);
|
||||
CharacterData data = positions.FirstOrDefault(p => p.Type == CharacterType.Player && p.Name.Equals(Game1.player.Name));
|
||||
if (data != null)
|
||||
{
|
||||
Game1.player.previousLocationName = Game1.player.currentLocation.Name;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Omegasis.SaveAnywhere.Framework
|
||||
{
|
||||
public class SchedulePathInfo
|
||||
{
|
||||
public int timeToGoTo;
|
||||
public int endX;
|
||||
public int endY;
|
||||
public string endMap;
|
||||
public int endDirection;
|
||||
public string endBehavior;
|
||||
public string endMessage;
|
||||
|
||||
public SchedulePathInfo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SchedulePathInfo(string RawData)
|
||||
{
|
||||
string[] fields = RawData.Split(' ');
|
||||
try
|
||||
{
|
||||
this.timeToGoTo = Convert.ToInt32(fields[0]);
|
||||
}
|
||||
catch(Exception err)
|
||||
{
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
this.endMap = fields[1];
|
||||
this.endX =Convert.ToInt32(fields[2]);
|
||||
this.endY =Convert.ToInt32(fields[3]);
|
||||
this.endDirection =Convert.ToInt32(fields[4]);
|
||||
if (fields.Length >= 6)
|
||||
{
|
||||
if (fields[5][0] == '"')
|
||||
{
|
||||
this.endMessage = fields[5].Substring(fields[5].IndexOf('"'));
|
||||
}
|
||||
}
|
||||
if (fields.Length >= 7)
|
||||
{
|
||||
|
||||
if (fields[5][0] == '"')
|
||||
{
|
||||
this.endBehavior = fields[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.endMessage = fields[6].Substring(fields[6].IndexOf('"'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ namespace Omegasis.SaveAnywhere
|
|||
/// <summary>The mod entry point.</summary>
|
||||
public class SaveAnywhere : Mod
|
||||
{
|
||||
|
||||
public static SaveAnywhere Instance;
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
|
@ -20,7 +22,8 @@ namespace Omegasis.SaveAnywhere
|
|||
private ModConfig Config;
|
||||
|
||||
/// <summary>Provides methods for saving and loading game data.</summary>
|
||||
private SaveManager SaveManager;
|
||||
public SaveManager SaveManager;
|
||||
|
||||
|
||||
/// <summary>The parsed schedules by NPC name.</summary>
|
||||
private readonly IDictionary<string, string> NpcSchedules = new Dictionary<string, string>();
|
||||
|
@ -29,7 +32,7 @@ namespace Omegasis.SaveAnywhere
|
|||
private bool ShouldResetSchedules;
|
||||
|
||||
/// <summary>Whether we're performing a non-vanilla save (i.e. not by sleeping in bed).</summary>
|
||||
private bool IsCustomSaving;
|
||||
public bool IsCustomSaving;
|
||||
|
||||
/// <summary>Used to access the Mod's helper from other files associated with the mod.</summary>
|
||||
public static IModHelper ModHelper;
|
||||
|
@ -37,10 +40,12 @@ namespace Omegasis.SaveAnywhere
|
|||
/// <summary>Used to access the Mod's monitor to allow for debug logging in other files associated with the mod.</summary>
|
||||
public static IMonitor ModMonitor;
|
||||
|
||||
private List<Monster> monsters;
|
||||
private Dictionary<GameLocation, List<Monster>> monsters;
|
||||
|
||||
private bool customMenuOpen;
|
||||
|
||||
private bool firstLoad;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -54,14 +59,27 @@ namespace Omegasis.SaveAnywhere
|
|||
this.SaveManager = new SaveManager(this.Helper, this.Helper.Reflection, onLoaded: () => this.ShouldResetSchedules = true);
|
||||
|
||||
helper.Events.GameLoop.SaveLoaded += this.OnSaveLoaded;
|
||||
helper.Events.GameLoop.Saved += this.OnSaved;
|
||||
helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked;
|
||||
helper.Events.GameLoop.DayStarted += this.OnDayStarted;
|
||||
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
|
||||
helper.Events.GameLoop.ReturnedToTitle += this.GameLoop_ReturnedToTitle;
|
||||
helper.Events.GameLoop.TimeChanged += this.GameLoop_TimeChanged;
|
||||
|
||||
ModHelper = helper;
|
||||
ModMonitor = this.Monitor;
|
||||
this.customMenuOpen = false;
|
||||
Instance = this;
|
||||
this.firstLoad = false;
|
||||
}
|
||||
|
||||
private void GameLoop_TimeChanged(object sender, TimeChangedEventArgs e)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void GameLoop_ReturnedToTitle(object sender, ReturnedToTitleEventArgs e)
|
||||
{
|
||||
this.firstLoad = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,32 +92,20 @@ namespace Omegasis.SaveAnywhere
|
|||
private void OnSaveLoaded(object sender, SaveLoadedEventArgs e)
|
||||
{
|
||||
// reset state
|
||||
this.IsCustomSaving = false;
|
||||
this.ShouldResetSchedules = false;
|
||||
|
||||
// load positions
|
||||
this.SaveManager.LoadData();
|
||||
//this.SaveManager.ClearData();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Raised after the game finishes writing data to the save file (except the initial save creation).</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event arguments.</param>
|
||||
private void OnSaved(object sender, SavedEventArgs e)
|
||||
{
|
||||
// clear custom data after a normal save (to avoid restoring old state)
|
||||
if (!this.IsCustomSaving)
|
||||
this.SaveManager.ClearData();
|
||||
else
|
||||
{
|
||||
this.IsCustomSaving = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Raised after the game state is updated (≈60 times per second).</summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="e">The event arguments.</param>
|
||||
private void OnUpdateTicked(object sender, UpdateTickedEventArgs e)
|
||||
{
|
||||
|
||||
// let save manager run background logic
|
||||
if (Context.IsWorldReady)
|
||||
{
|
||||
|
@ -107,17 +113,16 @@ namespace Omegasis.SaveAnywhere
|
|||
this.SaveManager.Update();
|
||||
}
|
||||
|
||||
// reset NPC schedules
|
||||
if (Context.IsWorldReady && this.ShouldResetSchedules)
|
||||
|
||||
|
||||
if (Game1.activeClickableMenu == null && Context.IsWorldReady)
|
||||
{
|
||||
this.ShouldResetSchedules = false;
|
||||
this.ApplySchedules();
|
||||
this.IsCustomSaving = false;
|
||||
}
|
||||
|
||||
if (Game1.activeClickableMenu == null && !this.customMenuOpen) return;
|
||||
if (Game1.activeClickableMenu == null && this.customMenuOpen)
|
||||
{
|
||||
this.restoreMonsters();
|
||||
this.customMenuOpen = false;
|
||||
return;
|
||||
}
|
||||
|
@ -133,27 +138,37 @@ namespace Omegasis.SaveAnywhere
|
|||
/// <summary>Saves all monsters from the game world.</summary>
|
||||
private void cleanMonsters()
|
||||
{
|
||||
this.monsters = new List<Monster>();
|
||||
this.monsters = new Dictionary<GameLocation, List<Monster>>();
|
||||
|
||||
foreach (var npc in Game1.player.currentLocation.characters)
|
||||
foreach (GameLocation loc in Game1.locations)
|
||||
{
|
||||
try
|
||||
this.monsters.Add(loc, new List<Monster>());
|
||||
foreach (var npc in loc.characters)
|
||||
{
|
||||
if (npc is Monster monster)
|
||||
this.monsters.Add(monster);
|
||||
{
|
||||
this.Monitor.Log(npc.Name);
|
||||
this.monsters[loc].Add(monster);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
foreach (var monster in this.monsters[loc])
|
||||
loc.characters.Remove(monster);
|
||||
}
|
||||
|
||||
foreach (var monster in this.monsters)
|
||||
Game1.player.currentLocation.characters.Remove(monster);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Adds all saved monster back into the game world.</summary>
|
||||
private void restoreMonsters()
|
||||
public static void RestoreMonsters()
|
||||
{
|
||||
foreach (var monster in this.monsters)
|
||||
Game1.player.currentLocation.characters.Add(monster);
|
||||
foreach (var pair in SaveAnywhere.Instance.monsters)
|
||||
{
|
||||
foreach (Monster m in pair.Value)
|
||||
{
|
||||
pair.Key.addCharacter(m);
|
||||
}
|
||||
}
|
||||
SaveAnywhere.Instance.monsters.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Raised after the game begins a new day (including when the player loads a save).</summary>
|
||||
|
@ -161,15 +176,41 @@ namespace Omegasis.SaveAnywhere
|
|||
/// <param name="e">The event arguments.</param>
|
||||
private void OnDayStarted(object sender, DayStartedEventArgs e)
|
||||
{
|
||||
// reload NPC schedules
|
||||
this.ShouldResetSchedules = true;
|
||||
//this.Monitor.Log("On day started called.", LogLevel.Info);
|
||||
|
||||
// update NPC schedules
|
||||
this.NpcSchedules.Clear();
|
||||
foreach (NPC npc in Utility.getAllCharacters())
|
||||
if (this.IsCustomSaving == false)
|
||||
{
|
||||
if (!this.NpcSchedules.ContainsKey(npc.Name))
|
||||
this.NpcSchedules.Add(npc.Name, this.ParseSchedule(npc));
|
||||
if (this.firstLoad == false)
|
||||
{
|
||||
this.firstLoad = true;
|
||||
if (this.SaveManager.saveDataExists())
|
||||
{
|
||||
this.ShouldResetSchedules = false;
|
||||
this.ApplySchedules();
|
||||
}
|
||||
}
|
||||
else if (this.firstLoad == true)
|
||||
{
|
||||
|
||||
this.SaveManager.ClearData(); //Clean the save state on consecutive days to ensure save files aren't lost inbetween incase the player accidently quits.
|
||||
}
|
||||
|
||||
//this.Monitor.Log("Cleaning old save file.", LogLevel.Info);
|
||||
|
||||
// reload NPC schedules
|
||||
this.ShouldResetSchedules = true;
|
||||
|
||||
// reset NPC schedules
|
||||
|
||||
/*
|
||||
// update NPC schedules
|
||||
this.NpcSchedules.Clear();
|
||||
foreach (NPC npc in Utility.getAllCharacters())
|
||||
{
|
||||
if (!this.NpcSchedules.ContainsKey(npc.Name))
|
||||
this.NpcSchedules.Add(npc.Name, this.ParseSchedule(npc));
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,6 +225,9 @@ namespace Omegasis.SaveAnywhere
|
|||
// initiate save (if valid context)
|
||||
if (e.Button == this.Config.SaveKey)
|
||||
{
|
||||
|
||||
if (Game1.eventUp) return;
|
||||
if (Game1.isFestival()) return;
|
||||
if (Game1.client == null)
|
||||
{
|
||||
this.cleanMonsters();
|
||||
|
@ -213,199 +257,25 @@ namespace Omegasis.SaveAnywhere
|
|||
return;
|
||||
|
||||
// apply for each NPC
|
||||
foreach (NPC npc in Utility.getAllCharacters())
|
||||
foreach (GameLocation loc in Game1.locations)
|
||||
{
|
||||
if (npc.DirectionsToNewLocation != null || npc.isMoving() || npc.Schedule == null || npc.controller != null || npc is Horse)
|
||||
continue;
|
||||
|
||||
// get raw schedule from XNBs
|
||||
IDictionary<string, string> rawSchedule = this.GetRawSchedule(npc.Name);
|
||||
if (rawSchedule == null)
|
||||
continue;
|
||||
|
||||
// get schedule data
|
||||
if (!this.NpcSchedules.TryGetValue(npc.Name, out string scheduleData) || string.IsNullOrEmpty(scheduleData))
|
||||
foreach (NPC npc in loc.characters)
|
||||
{
|
||||
//this.Monitor.Log("THIS IS AWKWARD");
|
||||
continue;
|
||||
}
|
||||
|
||||
// get schedule script
|
||||
if (!rawSchedule.TryGetValue(scheduleData, out string script))
|
||||
continue;
|
||||
|
||||
// parse entries
|
||||
string[] entries = script.Split('/');
|
||||
int index = 0;
|
||||
foreach (string _ in entries)
|
||||
{
|
||||
string[] fields = entries[index].Split(' ');
|
||||
|
||||
// handle GOTO command
|
||||
if (fields.Contains("GOTO"))
|
||||
{
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
string s = fields[i];
|
||||
if (s == "GOTO")
|
||||
{
|
||||
rawSchedule.TryGetValue(fields[i + 1], out script);
|
||||
string[] newEntries = script.Split('/');
|
||||
fields = newEntries[0].Split(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse schedule script
|
||||
SchedulePathDescription schedulePathDescription;
|
||||
try
|
||||
{
|
||||
if (Convert.ToInt32(fields[0]) > Game1.timeOfDay) break;
|
||||
string endMap = Convert.ToString(fields[1]);
|
||||
int x = Convert.ToInt32(fields[2]);
|
||||
int y = Convert.ToInt32(fields[3]);
|
||||
int endFacingDir = Convert.ToInt32(fields[4]);
|
||||
|
||||
schedulePathDescription = this.Helper.Reflection
|
||||
.GetMethod(npc, "pathfindToNextScheduleLocation")
|
||||
.Invoke<SchedulePathDescription>(npc.currentLocation.Name, npc.getTileX(), npc.getTileY(), endMap, x, y, endFacingDir, null, null);
|
||||
index++;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (npc.isVillager() == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
npc.DirectionsToNewLocation = schedulePathDescription;
|
||||
npc.controller = new PathFindController(npc.DirectionsToNewLocation.route, npc, Utility.getGameLocationOfCharacter(npc))
|
||||
{
|
||||
finalFacingDirection = npc.DirectionsToNewLocation.facingDirection,
|
||||
endBehaviorFunction = null
|
||||
};
|
||||
npc.fillInSchedule();
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Get an NPC's raw schedule data from the XNB files.</summary>
|
||||
/// <param name="npcName">The NPC name whose schedules to read.</param>
|
||||
/// <returns>Returns the NPC schedule if found, else <c>null</c>.</returns>
|
||||
private IDictionary<string, string> GetRawSchedule(string npcName)
|
||||
public override object GetApi()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Game1.content.Load<Dictionary<string, string>>($"Characters\\schedules\\{npcName}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Load the raw schedule data for an NPC.</summary>
|
||||
/// <param name="npc">The NPC whose schedule to read.</param>
|
||||
private string ParseSchedule(NPC npc)
|
||||
{
|
||||
// set flags
|
||||
if (npc.Name.Equals("Robin") || Game1.player.currentUpgrade != null)
|
||||
npc.IsInvisible = false;
|
||||
if (npc.Name.Equals("Willy") && Game1.stats.DaysPlayed < 2u)
|
||||
npc.IsInvisible = true;
|
||||
else if (npc.Schedule != null)
|
||||
npc.followSchedule = true;
|
||||
|
||||
// read schedule data
|
||||
IDictionary<string, string> schedule = this.GetRawSchedule(npc.Name);
|
||||
if (schedule == null)
|
||||
return "";
|
||||
|
||||
// do stuff
|
||||
if (npc.isMarried())
|
||||
{
|
||||
string dayName = Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
if ((npc.Name.Equals("Penny") && (dayName.Equals("Tue") || dayName.Equals("Wed") || dayName.Equals("Fri"))) || (npc.Name.Equals("Maru") && (dayName.Equals("Tue") || dayName.Equals("Thu"))) || (npc.Name.Equals("Harvey") && (dayName.Equals("Tue") || dayName.Equals("Thu"))))
|
||||
{
|
||||
this.Helper.Reflection
|
||||
.GetField<string>(npc, "nameOfTodaysSchedule")
|
||||
.SetValue("marriageJob");
|
||||
return "marriageJob";
|
||||
}
|
||||
if (!Game1.isRaining && schedule.ContainsKey("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
{
|
||||
this.Helper.Reflection
|
||||
.GetField<string>(npc, "nameOfTodaysSchedule")
|
||||
.SetValue("marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth));
|
||||
return "marriage_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
}
|
||||
npc.followSchedule = false;
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (schedule.ContainsKey(Game1.currentSeason + "_" + Game1.dayOfMonth))
|
||||
return Game1.currentSeason + "_" + Game1.dayOfMonth;
|
||||
int i;
|
||||
Game1.player.friendshipData.TryGetValue(npc.Name, out Friendship f);
|
||||
for (i = (Game1.player.friendshipData.ContainsKey(npc.Name) ? (f.Points / 250) : -1); i > 0; i--)
|
||||
{
|
||||
if (schedule.ContainsKey(Game1.dayOfMonth + "_" + i))
|
||||
return Game1.dayOfMonth + "_" + i;
|
||||
}
|
||||
if (schedule.ContainsKey(string.Empty + Game1.dayOfMonth))
|
||||
return string.Empty + Game1.dayOfMonth;
|
||||
if (npc.Name.Equals("Pam") && Game1.player.mailReceived.Contains("ccVault"))
|
||||
return "bus";
|
||||
if (Game1.isRaining)
|
||||
{
|
||||
if (Game1.random.NextDouble() < 0.5 && schedule.ContainsKey("rain2"))
|
||||
return "rain2";
|
||||
if (schedule.ContainsKey("rain"))
|
||||
return "rain";
|
||||
}
|
||||
List<string> list = new List<string> { Game1.currentSeason, Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth) };
|
||||
Game1.player.friendshipData.TryGetValue(npc.Name, out Friendship friendship);
|
||||
i = (Game1.player.friendshipData.ContainsKey(npc.Name) ? (friendship.Points / 250) : -1);
|
||||
while (i > 0)
|
||||
{
|
||||
list.Add(string.Empty + i);
|
||||
if (schedule.ContainsKey(string.Join("_", list)))
|
||||
{
|
||||
return string.Join("_", list);
|
||||
}
|
||||
i--;
|
||||
list.RemoveAt(list.Count - 1);
|
||||
}
|
||||
if (schedule.ContainsKey(string.Join("_", list)))
|
||||
{
|
||||
return string.Join("_", list);
|
||||
}
|
||||
if (schedule.ContainsKey(Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
{
|
||||
return Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
}
|
||||
if (schedule.ContainsKey(Game1.currentSeason))
|
||||
{
|
||||
return Game1.currentSeason;
|
||||
}
|
||||
if (schedule.ContainsKey("spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth)))
|
||||
{
|
||||
return "spring_" + Game1.shortDayNameFromDayOfSeason(Game1.dayOfMonth);
|
||||
}
|
||||
list.RemoveAt(list.Count - 1);
|
||||
list.Add("spring");
|
||||
Game1.player.friendshipData.TryGetValue(npc.Name, out Friendship friendship2);
|
||||
i = (Game1.player.friendshipData.ContainsKey(npc.Name) ? (friendship2.Points / 250) : -1);
|
||||
while (i > 0)
|
||||
{
|
||||
list.Add(string.Empty + i);
|
||||
if (schedule.ContainsKey(string.Join("_", list)))
|
||||
return string.Join("_", list);
|
||||
i--;
|
||||
list.RemoveAt(list.Count - 1);
|
||||
}
|
||||
return schedule.ContainsKey("spring")
|
||||
? "spring"
|
||||
: null;
|
||||
}
|
||||
return new SaveAnywhereAPI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,10 @@
|
|||
<Compile Include="Framework\Models\PositionData.cs" />
|
||||
<Compile Include="Framework\NewSaveGameMenu.cs" />
|
||||
<Compile Include="Framework\Models\PlayerData.cs" />
|
||||
<Compile Include="Framework\NPCExtensions.cs" />
|
||||
<Compile Include="Framework\SaveAnywhereAPI.cs" />
|
||||
<Compile Include="Framework\SaveManager.cs" />
|
||||
<Compile Include="Framework\SchedulePathInfo.cs" />
|
||||
<Compile Include="SaveAnywhere.cs" />
|
||||
<Compile Include="Framework\NewShippingMenu.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"Name": "Save Anywhere",
|
||||
"Author": "Alpha_Omegasis",
|
||||
"Version": "2.11.0",
|
||||
"Version": "2.12.0",
|
||||
"Description": "Lets you save almost anywhere.",
|
||||
"UniqueID": "Omegasis.SaveAnywhere",
|
||||
"EntryDll": "SaveAnywhere.dll",
|
||||
"MinimumApiVersion": "2.10.1",
|
||||
"UpdateKeys": [ "Nexus:444" ],
|
||||
"Dependencies": [
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"Name": "StardustCore",
|
||||
"Author": "Alpha_Omegasis",
|
||||
"Version": "2.3.0",
|
||||
"Version": "2.4.0",
|
||||
"Description": "A core mod that allows for other mods of mine to be run.",
|
||||
"UniqueID": "Omegasis.StardustCore",
|
||||
"EntryDll": "StardustCore.dll",
|
||||
|
|
Loading…
Reference in New Issue