namespace Cthangover.Mods.Rpg.Tests { using System; using System.Collections.Generic; using System.Text.Json; using Cthangover.Core.Mods.Testing; using Cthangover.Core.Utils; using Godot; /// Event pages pick the last page whose condition holds; routes resolve their steps. public class RpgEventPagesTests { private static RpgMapEvent Chest() => JsonSerializer.Deserialize(@"{ ""Id"": ""chest"", ""X"": 3, ""Y"": 2, ""Tile"": 40, ""Commands"": [""flag chest_open 1""], ""Pages"": [ { ""Condition"": ""chest_open == 1"", ""Icon"": ""rpg_demo/coin"", ""Commands"": [""text \""Empty.\""""] }, { ""Condition"": ""guard_back == 1"", ""Sprite"": ""village/guard"", ""Dir"": ""left"", ""Solid"": true } ] }", JsonOptionsProvider.ReadOptions); private static Func Flags(params string[] holding) => c => Array.IndexOf(holding, c) >= 0; [ModTest("pages/last_holding_page_wins")] static void LastHoldingPageWins(ModTestContext ctx) { var chest = Chest(); ModAssert.Equal(0, RpgEventPages.ActiveIndex(chest, Flags()), "no page holds: the event itself"); ModAssert.Equal(1, RpgEventPages.ActiveIndex(chest, Flags("chest_open == 1")), "the opened page"); ModAssert.Equal(2, RpgEventPages.ActiveIndex(chest, Flags("chest_open == 1", "guard_back == 1")), "the later page wins"); } [ModTest("pages/own_condition_only_turns_off_page_zero")] static void OwnConditionOnlyTurnsOffPageZero(ModTestContext ctx) { var chest = Chest(); chest.Condition = "chest_here == 1"; ModAssert.Equal(-1, RpgEventPages.ActiveIndex(chest, Flags()), "nothing holds: hidden"); ModAssert.Equal(1, RpgEventPages.ActiveIndex(chest, Flags("chest_open == 1")), "a page shows it without the own condition"); ModAssert.Equal(0, RpgEventPages.ActiveIndex(new RpgMapEvent { Id = "plain" }, Flags()), "an event without pages and condition"); } [ModTest("pages/effective_merges_page_over_event")] static void EffectiveMergesPageOverEvent(ModTestContext ctx) { var chest = Chest(); ModAssert.True(ReferenceEquals(chest, RpgEventPages.Effective(chest, 0)), "page 0 is the event itself"); var open = RpgEventPages.Effective(chest, 1); ModAssert.Equal("chest", open.Id, "id kept"); ModAssert.Equal(3, open.X, "cell kept"); ModAssert.Equal("rpg_demo/coin", open.Icon, "the page's icon"); ModAssert.Equal(-1, open.Tile, "a page look replaces the whole look"); ModAssert.Equal("text \"Empty.\"", open.Commands[0], "the page's commands"); ModAssert.True(open.Trigger == RpgEventTrigger.Action, "trigger inherited"); var guard = RpgEventPages.Effective(chest, 2); ModAssert.Equal("village/guard", guard.Sprite, "charset of page 2"); ModAssert.True(guard.Dir == RpgDirection.Left, "facing of page 2"); ModAssert.True(guard.IsSolid, "solid"); ModAssert.Equal("flag chest_open 1", guard.Commands[0], "commands inherited from the event"); ModAssert.Null(RpgEventPages.Effective(chest, 3), "out of range"); } [ModTest("routes/steps_resolve")] static void StepsResolve(ModTestContext ctx) { var self = new Vector2I(5, 5); var player = new Vector2I(2, 6); var left = RpgRouteStep.Resolve("Left", self, player, null); ModAssert.True(left.Moves && left.Direction == RpgDirection.Left, "a walk, any case"); var face = RpgRouteStep.Resolve("face_up", self, player, null); ModAssert.True(!face.Moves && face.Direction == RpgDirection.Up, "a turn"); ModAssert.Null(RpgRouteStep.Resolve("wait", self, player, null).Direction, "wait stands"); ModAssert.Null(RpgRouteStep.Resolve("dance", self, player, null).Direction, "an unknown word stands"); ModAssert.True(RpgRouteStep.Resolve("toward", self, player, null).Direction == RpgDirection.Left, "toward along the longer axis"); ModAssert.True(RpgRouteStep.Resolve("away", self, player, null).Direction == RpgDirection.Right, "away is the opposite"); ModAssert.Null(RpgRouteStep.Toward(self, self), "already there"); var random = RpgRouteStep.Resolve("random", self, player, new Random(7)); ModAssert.True(random.Moves && random.Direction.HasValue, "random walks somewhere"); } [ModTest("routes/json_defaults")] static void JsonDefaults(ModTestContext ctx) { var mapEvent = JsonSerializer.Deserialize(@"{ ""Id"": ""cat"", ""Route"": { ""Steps"": [""random""] } }", JsonOptionsProvider.ReadOptions); ModAssert.CloseTo(1.0, mapEvent.Route.Every, what: "a step a second by default"); ModAssert.True(mapEvent.Route.Repeat, "repeats by default"); ModAssert.Null(mapEvent.Pages, "no pages"); } } }