Skip to content

Commit

Permalink
When Special Order dialogue replaces NPC dialogue, queues it up for 1…
Browse files Browse the repository at this point in the history
… in game hour later.
  • Loading branch information
atravita-mods committed Jan 26, 2022
1 parent 6fc47dd commit 8d91da8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
73 changes: 73 additions & 0 deletions SpecialOrdersExtended/DialogueManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,54 @@

namespace SpecialOrdersExtended;

/// <summary>
/// A dialogue to delay.
/// </summary>
internal struct DelayedDialogue
{
private readonly int time;
private readonly Dialogue dialogue;
private readonly NPC npc;

/// <summary>
/// Initializes a new instance of the <see cref="DelayedDialogue"/> struct.
/// </summary>
/// <param name="time">Time to delay to.</param>
/// <param name="dialogue">Dialogue to delay.</param>
/// <param name="npc">Speaking NPC.</param>
public DelayedDialogue(int time, Dialogue dialogue, NPC npc)
{
this.time = time;
this.dialogue = dialogue;
this.npc = npc;
}

/// <summary>
/// Pushes the delayed dialogue onto the NPC's stack if it's past time to do so..
/// </summary>
/// <param name="currenttime">The current in-game time.</param>
/// <returns>True if pushed, false otherwise.</returns>
public bool PushIfPastTime(int currenttime)
{
if (currenttime > this.time)
{
this.npc.CurrentDialogue.Push(this.dialogue);
return true;
}
return false;
}
}

/// <summary>
/// Static. Handles logic, patches, and console commands related to the special order dialogues.
/// </summary>
internal class DialogueManager
{
/// <summary>
/// A queue of delayed dialogues.
/// </summary>
private static readonly PerScreen<Queue<DelayedDialogue>> DelayedDialogues = new(createNewState: () => new Queue<DelayedDialogue>());

/// <summary>
/// Backing field for PerScreened Dialogue Logs.
/// </summary>
Expand Down Expand Up @@ -302,6 +345,29 @@ public static void PostfixCheckDialogue(ref bool __result, ref NPC __instance, i
}
}

/// <summary>
/// Clears the Delayed Dialogue queue. Call at end of day.
/// </summary>
public static void ClearDelayedDialogue() => DelayedDialogues.Value.Clear();

/// <summary>
/// Push any available dialogues to the NPC's dialogue stacks.
/// </summary>
public static void PushPossibleDelayedDialogues()
{
while (DelayedDialogues.Value.TryPeek(out DelayedDialogue result))
{
if (result.PushIfPastTime(Game1.timeOfDay))
{
_ = DelayedDialogues.Value.Dequeue();
}
else
{
return;
}
}
}

/// <summary>
/// Checks to see if a dialoguekey has been said already, and if not said, pushes the dialogue
/// onto the dialogue stack.
Expand All @@ -315,6 +381,13 @@ private static bool PushAndSaveDialogue(string dialogueKey, NPC npc)
{// I have already said this dialogue
return false;
}
while (npc.CurrentDialogue.TryPop(out Dialogue? result))
{
DelayedDialogues.Value.Enqueue(new DelayedDialogue(
time: Game1.timeOfDay + 100,
npc: npc,
dialogue: result));
}
npc.CurrentDialogue.Push(new Dialogue(npc.Dialogue[dialogueKey], npc) { removeOnNextMove = true });
if (ModEntry.Config.Verbose)
{
Expand Down
16 changes: 12 additions & 4 deletions SpecialOrdersExtended/ModEntry.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Reflection;
using HarmonyLib;
using SpecialOrdersExtended.Integrations;
using StardewModdingAPI.Events;
using StardewValley.GameData;

namespace SpecialOrdersExtended;
Expand Down Expand Up @@ -110,15 +111,21 @@ public override void Entry(IModHelper helper)
helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
helper.Events.GameLoop.SaveLoaded += this.SaveLoaded;
helper.Events.GameLoop.Saving += this.Saving;
helper.Events.GameLoop.TimeChanged += this.OnTimeChanged;
helper.Events.GameLoop.OneSecondUpdateTicking += this.OneSecondUpdateTicking;
}

private void OneSecondUpdateTicking(object? sender, StardewModdingAPI.Events.OneSecondUpdateTickingEventArgs e)
private void OnTimeChanged(object? sender, TimeChangedEventArgs e)
{
DialogueManager.PushPossibleDelayedDialogues();
}

private void OneSecondUpdateTicking(object? sender, OneSecondUpdateTickingEventArgs e)
{
RecentSOManager.GrabNewRecentlyCompletedOrders();
}

private void OnGameLaunched(object? sender, StardewModdingAPI.Events.GameLaunchedEventArgs e)
private void OnGameLaunched(object? sender, GameLaunchedEventArgs e)
{
// Bind Spacecore API
IModInfo spacecore = this.Helper.ModRegistry.Get("spacechase0.SpaceCore");
Expand All @@ -141,11 +148,12 @@ private void OnGameLaunched(object? sender, StardewModdingAPI.Events.GameLaunche
api.RegisterToken(this.ModManifest, "RecentCompleted", new Tokens.RecentCompletedSO());
}

private void Saving(object? sender, StardewModdingAPI.Events.SavingEventArgs e)
private void Saving(object? sender, SavingEventArgs e)
{
this.Monitor.DebugLog("Event Saving raised");

DialogueManager.Save(); // Save dialogue
DialogueManager.ClearDelayedDialogue();

if (Context.IsSplitScreen && Context.ScreenId != 0)
{// Some properties only make sense for a single player to handle in splitscreen.
Expand All @@ -159,7 +167,7 @@ private void Saving(object? sender, StardewModdingAPI.Events.SavingEventArgs e)
RecentSOManager.Save();
}

private void SaveLoaded(object? sender, StardewModdingAPI.Events.SaveLoadedEventArgs e)
private void SaveLoaded(object? sender, SaveLoadedEventArgs e)
{
this.Monitor.DebugLog("Event SaveLoaded raised");
DialogueManager.Load(Game1.player.UniqueMultiplayerID);
Expand Down

0 comments on commit 8d91da8

Please sign in to comment.