fix(ui): restore retail skill training confirmation
Route untrained-skill promotion through DialogFactory with retail's exact prompt and stored skill/credit properties. Defer the character-sheet refresh until accept or reject completes while leaving trained-skill XP raises immediate. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
66bdae7a83
commit
85980fe13f
7 changed files with 341 additions and 14 deletions
|
|
@ -674,7 +674,8 @@ public class CharacterStatControllerTests
|
|||
(CharacterStatController.ListBoxId, list));
|
||||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter, onRaiseRequest: requests.Add);
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
list.Children.OfType<UiClickablePanel>().ToList()[4].OnClick!();
|
||||
btn1.OnClick!();
|
||||
|
|
@ -696,7 +697,8 @@ public class CharacterStatControllerTests
|
|||
(CharacterStatController.ListBoxId, list));
|
||||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter, onRaiseRequest: requests.Add);
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
list.Children.OfType<UiClickablePanel>().ToList()[4].OnClick!();
|
||||
Assert.Equal("Normal", btn1.ActiveState);
|
||||
|
|
@ -717,7 +719,8 @@ public class CharacterStatControllerTests
|
|||
(CharacterStatController.ListBoxId, list));
|
||||
var requests = new List<CharacterStatController.RaiseRequest>();
|
||||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter, onRaiseRequest: requests.Add);
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
list.Children.OfType<UiClickablePanel>().ToList()[6].OnClick!();
|
||||
btn1.OnClick!();
|
||||
|
|
@ -745,7 +748,8 @@ public class CharacterStatControllerTests
|
|||
AttributeRaise10Costs = new long[] { 0L, 0L, 0L, 0L, 1_100L, 0L, 0L, 0L, 0L },
|
||||
};
|
||||
|
||||
CharacterStatController.Bind(layout, () => sheet, onRaiseRequest: requests.Add);
|
||||
CharacterStatController.Bind(layout, () => sheet,
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
list.Children.OfType<UiClickablePanel>().ToList()[4].OnClick!();
|
||||
btn10.OnClick!();
|
||||
|
|
@ -1004,7 +1008,7 @@ public class CharacterStatControllerTests
|
|||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
onRaiseRequest: requests.Add);
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
SkillRows(list)[1].OnClick!();
|
||||
|
|
@ -1063,7 +1067,7 @@ public class CharacterStatControllerTests
|
|||
|
||||
CharacterStatController.Bind(layout, SampleData.SampleCharacter,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
onRaiseRequest: requests.Add);
|
||||
onRaiseRequest: (request, completed) => { requests.Add(request); completed(); });
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
SkillRows(list)[5].OnClick!();
|
||||
|
|
@ -1107,7 +1111,7 @@ public class CharacterStatControllerTests
|
|||
|
||||
CharacterStatController.Bind(layout, () => sheet,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
onRaiseRequest: request =>
|
||||
onRaiseRequest: (request, completed) =>
|
||||
{
|
||||
requests.Add(request);
|
||||
sheet = new CharacterSheet
|
||||
|
|
@ -1124,9 +1128,10 @@ public class CharacterStatControllerTests
|
|||
TrainedCost: 4,
|
||||
SpecializedCost: 0,
|
||||
RaiseCost: 10,
|
||||
Raise10Cost: 100),
|
||||
Raise10Cost: 100),
|
||||
},
|
||||
};
|
||||
completed();
|
||||
});
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
|
|
@ -1144,6 +1149,58 @@ public class CharacterStatControllerTests
|
|||
Assert.Equal("Normal", btn10.ActiveState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkillsTab_DeferredTrainRefreshesOnlyWhenRequestCompletes()
|
||||
{
|
||||
var list = new UiPanel { Width = 300 };
|
||||
var btn1 = MakeButton();
|
||||
var btn10 = MakeButton();
|
||||
CharacterSheet sheet = TrainingSheet(CharacterSkillAdvancementClass.Untrained);
|
||||
var layout = Fake(
|
||||
(CharacterStatController.ListBoxId, list),
|
||||
(CharacterStatController.RaiseOneId, btn1),
|
||||
(CharacterStatController.RaiseTenId, btn10));
|
||||
Action? completeRaise = null;
|
||||
|
||||
CharacterStatController.Bind(layout, () => sheet,
|
||||
spriteResolve: id => (id, 16, 16),
|
||||
onRaiseRequest: (_, completed) => completeRaise = completed);
|
||||
|
||||
ClickTab(layout, left: 92f);
|
||||
SkillRows(list).Single().OnClick!();
|
||||
btn1.OnClick!();
|
||||
sheet = TrainingSheet(CharacterSkillAdvancementClass.Trained);
|
||||
|
||||
Assert.NotNull(completeRaise);
|
||||
Assert.False(btn10.Visible);
|
||||
|
||||
completeRaise!();
|
||||
|
||||
Assert.True(btn10.Visible);
|
||||
|
||||
static CharacterSheet TrainingSheet(CharacterSkillAdvancementClass advancement)
|
||||
=> new()
|
||||
{
|
||||
SkillCredits = advancement == CharacterSkillAdvancementClass.Untrained ? 10 : 6,
|
||||
UnassignedXp = 1_000,
|
||||
Skills =
|
||||
[
|
||||
new CharacterSkill(
|
||||
100u,
|
||||
"Train Me",
|
||||
0x06000001u,
|
||||
advancement,
|
||||
BaseLevel: 5,
|
||||
CurrentLevel: 5,
|
||||
UsableUntrained: true,
|
||||
TrainedCost: 4,
|
||||
SpecializedCost: 0,
|
||||
RaiseCost: advancement == CharacterSkillAdvancementClass.Untrained ? 0 : 10,
|
||||
Raise10Cost: advancement == CharacterSkillAdvancementClass.Untrained ? 0 : 100),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkillsTab_BindsCharacterScrollbarToScrollableViewport()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
using AcDream.App.UI;
|
||||
using AcDream.App.UI.Layout;
|
||||
using AcDream.App.Tests.UI.Layout;
|
||||
|
||||
namespace AcDream.App.Tests.UI;
|
||||
|
||||
public sealed class RetailSkillTrainingConfirmationControllerTests
|
||||
{
|
||||
private const uint Healing = 21u;
|
||||
|
||||
[Fact]
|
||||
public void AcceptSendsStoredSkillAndCreditsOnlyAfterConfirmation()
|
||||
{
|
||||
var root = new UiRoot { Width = 800f, Height = 600f };
|
||||
ImportedLayout? shown = null;
|
||||
var factory = new RetailDialogFactory(root, _ =>
|
||||
shown = FixtureLoader.LoadConfirmationDialog());
|
||||
var controller = new RetailSkillTrainingConfirmationController(factory);
|
||||
var sent = new List<CharacterStatController.RaiseRequest>();
|
||||
bool completed = false;
|
||||
|
||||
controller.Request(Request(), Sheet(), sent.Add, () => completed = true);
|
||||
|
||||
Assert.Empty(sent);
|
||||
Assert.False(completed);
|
||||
Assert.Equal(
|
||||
"Are you sure you want to spend 6 credits to train Healing?",
|
||||
string.Join(" ", Assert.IsType<UiText>(shown!.FindElement(
|
||||
RetailConfirmationDialogView.MessageElementId)).LinesProvider().Select(static line => line.Text)));
|
||||
|
||||
Assert.IsType<UiButton>(shown.FindElement(
|
||||
RetailConfirmationDialogView.AcceptButtonId)).OnClick!();
|
||||
|
||||
CharacterStatController.RaiseRequest request = Assert.Single(sent);
|
||||
Assert.Equal(CharacterStatController.RaiseTargetKind.TrainSkill, request.Kind);
|
||||
Assert.Equal(Healing, request.StatId);
|
||||
Assert.Equal(6L, request.Cost);
|
||||
Assert.Equal(1, request.Amount);
|
||||
Assert.True(completed);
|
||||
Assert.False(factory.IsOpen);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RejectCompletesWithoutSendingTrainingRequest()
|
||||
{
|
||||
var root = new UiRoot { Width = 800f, Height = 600f };
|
||||
ImportedLayout? shown = null;
|
||||
var factory = new RetailDialogFactory(root, _ =>
|
||||
shown = FixtureLoader.LoadConfirmationDialog());
|
||||
var controller = new RetailSkillTrainingConfirmationController(factory);
|
||||
var sent = new List<CharacterStatController.RaiseRequest>();
|
||||
bool completed = false;
|
||||
|
||||
controller.Request(Request(), Sheet(), sent.Add, () => completed = true);
|
||||
Assert.IsType<UiButton>(shown!.FindElement(
|
||||
RetailConfirmationDialogView.RejectButtonId)).OnClick!();
|
||||
|
||||
Assert.Empty(sent);
|
||||
Assert.True(completed);
|
||||
Assert.False(factory.IsOpen);
|
||||
}
|
||||
|
||||
private static CharacterStatController.RaiseRequest Request()
|
||||
=> new(CharacterStatController.RaiseTargetKind.TrainSkill, Healing, 6L, 1);
|
||||
|
||||
private static CharacterSheet Sheet()
|
||||
=> new()
|
||||
{
|
||||
SkillCredits = 10,
|
||||
Skills =
|
||||
[
|
||||
new CharacterSkill(
|
||||
Healing,
|
||||
"Healing",
|
||||
0x06000133u,
|
||||
CharacterSkillAdvancementClass.Untrained,
|
||||
BaseLevel: 10,
|
||||
CurrentLevel: 10,
|
||||
UsableUntrained: true,
|
||||
TrainedCost: 6,
|
||||
SpecializedCost: 10,
|
||||
RaiseCost: 0L),
|
||||
],
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue