Delay Alms guidance after Improve dialogue (#8681)

This commit is contained in:
2026-07-17 15:10:53 -07:00
committed by GitHub
parent 1f18f3296d
commit 4dd30a9863
2 changed files with 80 additions and 0 deletions
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Reflection;
using Eagle0.Tutorial;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using NUnit.Framework;
using Shardok;
using UnityEngine;
@@ -430,6 +432,31 @@ namespace eagle0.Tests {
} finally { Object.DestroyImmediate(gameObject); }
}
[Test]
public void AlmsDialogueWaitsForTheMonthAfterImproveDialogueWasPresented() {
var gameObject = new GameObject("DialogueManager test");
try {
var manager = gameObject.AddComponent<DialogueManager>();
var updater = new eagle.GameModelUpdater(987654321, null, null);
var model = GetPrivateField<eagle.IGameModel>(updater, "_currentModel");
SetCurrentDate(model, year: 12, month: 4);
manager.OnEagleModelUpdated(model);
InvokePrivate(manager, "RecordPresentedMonth", "post_battle_rebuild");
Assert.IsTrue(
InvokePrivate<bool>(manager, "ShouldWaitToPresent", "post_battle_alms"));
SetCurrentDate(model, year: 12, month: 5);
Assert.IsFalse(
InvokePrivate<bool>(manager, "ShouldWaitToPresent", "post_battle_alms"));
Assert.IsFalse(InvokePrivate<bool>(
manager,
"ShouldWaitToPresent",
"tutorial_attack_ready"));
} finally { Object.DestroyImmediate(gameObject); }
}
[Test]
public void FinalUiHighlightsPersistUntilPlayerActs() {
var managerObject = new GameObject("DialogueManager test");
@@ -510,6 +537,14 @@ namespace eagle0.Tests {
return (T)method.Invoke(target, null);
}
private static T InvokePrivate<T>(object target, string methodName, params object[] args) {
var method = target.GetType().GetMethod(
methodName,
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(method, $"Missing private method '{methodName}'");
return (T)method.Invoke(target, args);
}
private static void InvokePrivate(object target, string methodName, params object[] args) {
var method = target.GetType().GetMethod(
methodName,
@@ -543,5 +578,14 @@ namespace eagle0.Tests {
Assert.NotNull(property);
property.SetValue(controller, model);
}
private static void SetCurrentDate(eagle.IGameModel model, int year, int month) {
var property = model.GetType().GetProperty(
"GsView",
BindingFlags.Instance | BindingFlags.Public);
Assert.NotNull(property);
var gameState = (GameStateView)property.GetValue(model);
gameState.CurrentDate = new Date { Year = year, Month = month };
}
}
}
@@ -33,6 +33,8 @@ namespace Eagle0.Tutorial {
public Color unitHighlightSecondaryColor = new Color(1f, 0.85f, 0f, 0.2f);
private const string TutorialUnitOverlayIdPrefix = "tutorial_unit_highlight_";
private const string PostBattleRebuildDialogueId = "post_battle_rebuild";
private const string PostBattleAlmsDialogueId = "post_battle_alms";
private DialogueScript _activeScript;
private int _currentStepIndex;
@@ -51,6 +53,7 @@ namespace Eagle0.Tutorial {
private readonly HashSet<string> _receivedServerDialogueIds = new HashSet<string>();
private bool _persistingHighlight;
private long? _progressGameId;
private int? _postBattleRebuildPresentedMonth;
/// <summary>
/// Whether a dialogue is currently being displayed.
@@ -134,6 +137,7 @@ namespace Eagle0.Tutorial {
TryPlayPendingServerDialogue();
return;
}
if (ShouldWaitToPresent(dialogue.Id)) return;
var model = _eagleModel;
if (model == null || !TryCreateServerScript(
@@ -292,6 +296,7 @@ namespace Eagle0.Tutorial {
foreach (var id in TutorialDialogueProgressStore.LoadCompletedScriptIds(gameId)) {
_completedScriptIds.Add(id);
}
_postBattleRebuildPresentedMonth = null;
}
private void StartScript(DialogueScript script) {
@@ -303,6 +308,7 @@ namespace Eagle0.Tutorial {
_activeScript = script;
_currentStepIndex = 0;
RecordPresentedMonth(script.id);
// In combat, always anchor to top so the panel doesn't cover the hex grid.
// On the strategic map, always use the default position.
var position = _shardokController?.Model != null ? "top" : null;
@@ -379,6 +385,9 @@ namespace Eagle0.Tutorial {
_completedScriptIds.Remove(id);
_receivedServerDialogueIds.Remove(id);
}
if (ids.Contains(PostBattleRebuildDialogueId)) {
_postBattleRebuildPresentedMonth = null;
}
RemovePendingServerDialogues(ids, _pendingServerDialogues);
RemovePendingServerDialogues(ids, _pendingTacticalServerDialogues);
@@ -404,6 +413,7 @@ namespace Eagle0.Tutorial {
_receivedServerDialogueIds.Clear();
_pendingServerDialogues.Clear();
_pendingTacticalServerDialogues.Clear();
_postBattleRebuildPresentedMonth = null;
SaveProgress();
}
@@ -415,6 +425,32 @@ namespace Eagle0.Tutorial {
_receivedServerDialogueIds.Clear();
_pendingServerDialogues.Clear();
_pendingTacticalServerDialogues.Clear();
_postBattleRebuildPresentedMonth = null;
}
private bool ShouldWaitToPresent(string dialogueId) {
if (dialogueId != PostBattleAlmsDialogueId ||
!_postBattleRebuildPresentedMonth.HasValue) {
return false;
}
// Strategic dialogue can remain queued while a tactical battle is open. Use the
// month John was actually presented, rather than the server emission month, so Elena
// cannot appear directly behind him after returning to the strategic map.
var currentMonth = CurrentMonth();
return currentMonth.HasValue &&
currentMonth.Value <= _postBattleRebuildPresentedMonth.Value;
}
private void RecordPresentedMonth(string dialogueId) {
if (dialogueId == PostBattleRebuildDialogueId) {
_postBattleRebuildPresentedMonth = CurrentMonth();
}
}
private int? CurrentMonth() {
var date = _eagleModel?.CurrentDate;
return date == null ? null : date.Year * 12 + date.Month;
}
/// <summary>