Skip to content

Journal and Georama: Catalogue and Tracker composites, Georama request list, Georama menu on the UI framework - #248

Open
SirFancyBacon wants to merge 13 commits into
TheMoonPeople:masterfrom
SirFancyBacon:journal
Open

SirFancyBacon wants to merge 13 commits into
TheMoonPeople:masterfrom
SirFancyBacon:journal

Conversation

@SirFancyBacon

Copy link
Copy Markdown
Contributor

Summary

This adds the first two composites planned in docs/UI_FRAMEWORK.md section 11, and builds two player-facing features on them:

  • a Georama request list, reached from the Georama menu's Analysis page;
  • spoiler-free chest tracking in the Journal.

It also moves the Georama menu's main menu and Analysis page onto the UI framework, which gives them mouse support.

With these changes the game still plays as retail. The only behaviour change is that Square now does something on the Analysis page.

Changes

UI framework

  • ui::Tracker: groups of goals with progress, on paper under the stone banner. A screen supplies a TrackerSource of strings and callbacks, so the tracker knows nothing about chests. Groups that aren't reached yet are drawn grey.
  • ui::Catalogue: a scrolling list beside a detail panel for the selected entry, with an optional tally and progress bar, fed by a CatalogueSource. List labels are coloured by state and squeezed when too long.
  • TrackerWindow::LoadStoneBanner / ReleaseStoneBanner: the banner picture (wepstatus) is only loaded by the battle menu. A screen drawn elsewhere can now load it into a texture block of its own.
  • Smaller fixes:
    • Labels can draw the game's green and grey; before, both fell back to white.
    • ListView keeps its scroll bar clear of its selection brackets. ListView had no other users.
    • ScrollBar draws a plain thumb where the Options menu's pictures aren't loaded.

Journal: chest tracker

  • Moved onto ui::Tracker: captures are identical to before, state by state.
  • Item classification fixed:
    • "Pockets" counted item 199 (Prickly bait) instead of Pocket (179).
    • "Defense Treats" counted the powders, Pocket and Treasure Key instead of the six treats (Fluffy Doughnut to Carrot Cookie).
    • The world total of stat boosts is now 101, not 84.
  • Unreached towns are hidden: a town is reached once visited or its dungeon entered, the same test the Atla menu uses. An unreached town shows as grey "???" with no breakdown, and the world total counts only reached towns.

Georama request list

  • Opening it: Square on the Analysis page opens the town's request list. Cross and Circle still leave the page, as in retail.
  • What it lists: every building CEditGround::RequestCheck tests, under its retail name. Each one shows as met, not met, unfinished, or "???" until found. "Unfinished" covers incomplete parts, since retail clears a request while its part is incomplete.
  • Residents: the detail panel names the residents who are back in town, and the panel's tally matches the Analysis page's Request bar.
  • Where requests are filed: the town scripts check each villager's request against their home part (VILLAGER_INFO::character_no), so a request is filed under that building.
  • Game text: building and villager names come from the game's own system messages, so all languages work.
  • New strings: the screen's own text is in all four languages.

Georama menu on the UI framework

  • Main menu:
    • The icons, selection frame and hand are retail's pictures.
    • The help box is the town ring's HelpBox, filled from retail's own help message (allmenu.mes), so every language keeps retail's wording.
  • Analysis page: unchanged apart from a controls line.
  • Mouse:
    • Hovering an icon's row selects it and a click opens it.
    • Clicking the Request heading opens the request list.
    • In the list, a building's row follows the pointer and the wheel steps through it.
    • A right click backs out.
    • Hit areas come from the same rectangles the pages draw with (IconRow, AnalyzeHeadingRect).
  • Out of scope: Config/Assembly and Move/Remove stay retail's and leave the mouse to the pad.

Testing

  • Parity: headless captures on lavapipe, compared before and after each move. The chest tracker and the Analysis page are pixel-identical. On the Georama main menu only the help box differs, across opening, selecting and closing.
  • Scripted runs:
    • The request list in Norune and Muska Lacka.
    • The chest tracker with unreached towns.
    • The full mouse path: hover, open Analysis, click Request, wheel, right click back.
  • Real hardware: played in the Flatpak build on a real GPU.
  • Test suite: ctest -j4 passes, apart from five Kazarov GPU and validation tests that also fail on lavapipe without this branch. The localization tests check that every new string exists in all four languages.
  • Not covered: Matataki, Queens and Yellow Drops weren't captured headless.

Docs

  • docs/UI_FRAMEWORK.md: the screens table, section 11 (Catalogue and Tracker built), and notes on the Georama menu, the request list and the banner loader.
  • docs/PC.md: the Georama menu's mouse table.

The vanilla item documents were made at start-up from the compiled tables.
They are now tracked in port/gameplay/items, as Dark Cloud 2's gameplay
documents are, and the build seals them into Kazarov's gameplay seed
(assets/data.zip beside dcdata). dcdata extract, or the new
publish-gameplay command on data extracted before, writes them into the
data under gameplay/.

A document is tried from the datapacks down, then the data's own, then the
compiled table, which data without the documents (from the first-run window,
or extracted before) uses. The items now load once RunGame has indexed the
data; indexing it once more beforehand cost 0.6 s per start in a debug build.

The Windows and macOS packages carry assets/ beside dcdata; the Flatpak
installs the seed there.

Tests: the tracked documents hold the tables as compiled, and the data's
own document is read under the packs.

Pins Kazarov to its game-neutral gameplay seed (gameplay_publish).
The Flatpak removed /bin/data.zip, Kazarov's seed, when Chronicle had no
gameplay documents. The seed now installs to /app/bin/assets, where dcdata
looks for it, and a fresh configure keeps it there with Kazarov's fix.
A datapack or the data can add a bag item as a document of its own,
gameplay/items/custom/<namespace>.<name>.json: its ID, retail's item
fields, prices, a retail icon and model, its text by language, and
optionally bait. Packs are read before the data, and every pack's items
load. A document that cannot be read is reported and left out.

Custom items are numbered from 0x800 in ID order, so the same items get
the same numbers every run. An item's name is message number + 100 in the
system messages, which go up to 2080, so 0x800 keeps custom names clear of
retail's. Their descriptions are at number + 500, as retail's are.

The game's own lookups answer for them: GetCommonItemInfo and GetItemData,
the shop prices, the model paths, and the item rows the dungeon reads. When
a message file lacks a custom item's name or description, the lookup gives
the item's own text in the current language, or English. The disc's own
messages always win.

Tests: custom items get numbers, rows, prices and models of their own; are
read from every pack and the data; a bad document is left out; and their
text answers the game's message lookups.
Retail tells weapons from items by number, and often takes anything from
ITEM_WEAPON_START up for a weapon. A custom item, numbered from 0x800, was
taken for one: picking it up in a dungeon read past WeaponList, and the
shop, the menus, storage and the obtained message treated it as a weapon,
or refused it as a bag item.

item::KindOf gives a number's kind: an attachment, a bag item (with every
custom item), a weapon, or none. The sites that would misclassify a custom
item ask it. Below the custom numbers it keeps retail's ranges, one-sided
weapon checks included, so retail's items behave as before. Storage keeps
retail's ITEM_DUNGEON_END for its own items.

--give takes a custom item's ID, since its number depends on the packs
loaded.

Test: a custom item has the kind of a bag item, and picked up in a dungeon
it goes into the bag.
A custom item's document may declare what each copy keeps, as names and
the numbers a new copy starts with ("state"), and the version of those
names ("state_version"). item::NewCopy makes such a copy: a permanent
instance, from a counter the save will keep, and a handle, a number of its
own from 0x1000. Retail's code carries the handle wherever it carries an
item number, so the copy keeps its identity through the bag, storage and
the menus, and copies never stack. Handles stop at 0x7E00, since a
description is looked up at the number + 500, an s16.

Everything the host answers for a custom item resolves a handle to its
item first: the item tables, the name and description, the kind, the
price and the model. A copy whose item is not registered keeps its ID and
state and finds its item again when it returns; item::RestoreCopy takes
back a copy kept in a save either way.

Between areas, where no menu holds an item, the handles of copies in none
of the bag, its quick slots or storage are freed. An item's own number in
the bag stands for a copy with the starting state. --give makes a copy of
an item with state.

Tests: copies get handles and instances of their own and answer as their
item; a freed handle is used again; a copy keeps its state while its item
is gone; a copy kept in a save comes back under a free handle; state that
is not numbers is refused.
save.dat stays retail's image: custom items and copies leave the bag,
quick slots and storage before the checksums are made, and go into
chronicle.dat, chunks kept under a hash of the save.dat they belong to
and written so an interruption leaves a matching pair. An item whose
definition is missing loads as an inert orphan that keeps its ID and
state until the definition returns.
The save and load screens show a "!" after the number of a save whose
chronicle.dat names an item that would load as an orphan.
The UI framework gains ui::Tracker (docs/UI_FRAMEWORK.md, section 11):
groups of goals with progress on paper under a stone banner, the group list
and every group's tally on the left, the selected group's rows, tally and
progress bar on the right, an optional filter line, and the hand and
brackets. It reads the pad, says where its rows are for the mouse, and takes
its content from a TrackerSource of strings and callbacks, so it knows nothing
of chests.

The chest tracker becomes such a source with its own data and counting
unchanged. Its captures are identical to before, state by state.
Pockets were counted from item 199, the Prickly bait, and defense treats from
the powders, Pocket and Treasure Key. Count Pocket (179) and the six treats from
the Fluffy Doughnut to the Carrot Cookie, and name the Eden and Gourd items too.
… page

The UI framework gains ui::Catalogue (docs/UI_FRAMEWORK.md, section 11): a
scrolling list of entries coloured by their state beside the selected one's
detail, on the tracker's paper under its banner, with an optional tally and
progress bar. It takes its content from a CatalogueSource, so it knows nothing
of buildings.

Square on the Analysis page opens the town's request list; Cross and Circle
leave the page as in retail. Each building CEditGround::RequestCheck tests is
listed under its own name, met, not met, unfinished (retail counts a request
only once its part is complete) or "???" until found, with the residents back
in town and the town's tally. A villager's request is about their home part,
so it is filed there; names are the game's messages.

The stone banner's picture is only loaded by the battle menu, so a screen
drawn elsewhere loads it into a block of its own (LoadStoneBanner). The labels
draw the game's green and grey, and ListView keeps its scroll bar clear of
its brackets, with a plain thumb where the options menu's pictures are not
loaded.
A town the player has not reached, neither visited nor its dungeon entered
(the test the Atla menu lists a town's parts by), is listed in grey as "???"
with no breakdown and no tally, so the world total counts only the towns
reached and nothing ahead is named. The Tracker draws a group it is told is
locked in grey.
…work

The main menu keeps retail's icons, selection frame and hand; its help is
the town ring's HelpBox, filled from retail's own help message, so every
language keeps retail's wording. Captures match the menu before the move,
state by state, except that box; the Analysis page and the request list are
identical.

The icon rows and the Analysis headings say where they are, and the menu
takes the mouse on those pages: hovering an icon's row selects it and a click
opens it, the Request heading opens the request list, the wheel steps the
list and a right click backs out. Config/Assembly and Move/Remove stay
retail's and leave the mouse to the pad.
Once a building stands in the town whole, the request list's detail pages
through its residents back in town, each with their request once they have
said it: retail's line from the town's talk messages, a page for each of
the message window's, with the hero's name filled in. Before then it names
no one, and a resident not yet heard says to talk to them.

A request counts as heard when its villager says the line in a town
conversation, the one EdTalkMode shows when the request is not met. The
journal keeps which in chronicle.dat's JRNL chunk, a bit per villager of
each town; a new game and a save without it have heard nothing.

The Catalogue's detail takes pages, which Left, Right and the page arrows
turn, and its tally moves under the list to give them room.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant