Skip to content

contract: type more of the game values the API passes as numbers - #64

Merged
ResurrectedTrader merged 3 commits into
mainfrom
contract-typed-values
Oct 7, 2026
Merged

ResurrectedTrader merged 3 commits into
mainfrom
contract-typed-values

Conversation

@ResurrectedTrader

Copy link
Copy Markdown
Owner

Summary

Continues #60: more contract signatures take and return enums, or the narrowest integer the game uses, instead of bare uint32_t / int32_t; the bindings convert at the edge, so scripts see the same numbers.

  • GetGameType() returns GameType, which gains RotW = 2; the settings panel names the mode from the enum. 1.14d never reports RotW.
  • createCharacter(name, class, hardcore, ladder, gameType?): optional GameType, RotW by default for a Warlock and Expansion otherwise; impossible combinations (Warlock outside RotW, Classic Assassin / Druid) throw. 1.14d creates only Expansion characters, so createCharacter(name, 7) there now returns false instead of throwing.
  • createGame's difficulty default is Difficulty::HighestAvailable.
  • Unit::RunWalk returns MoveMode; a Language enum for GetLocale / me.locale; MonEnchant, ArenaFlag, ClickOnMapFlag get fixed underlying types.
  • LevelId types area numbers across the contract, bindings, navigation code and tests.
  • Stat, State, Skill, Quest and StatListFlags enums replace loose constants; 1.14d static_asserts them against D2MOO.
  • Narrower types: Party::ClassId -> CharacterClass; Party::CharacterLevel, Unit::SuperUniqueId, NPC menu ids, locale string ids, stat / skill point counts -> uint16_t; gold amounts unsigned; redundant binding casts dropped.
  • UnitFlagEx bit 0x08000000 is named AnimEndOfCycle.

CLAUDE.md's constants guidance names the new enums. Generated enum names rerun.

Stack

Stacked on #63 (this PR's base branch); it depends on that change and the ones below it. Merge in order; once the base merges, this PR is retargeted to main (automatically when the merged branch is deleted).

Verification

  • build.ps1 Release (Win32, the 1.14d DLL): builds
  • build.ps1 test: 169/169 pass
  • build.ps1 check-format: clean
  • scripts/gen_enum_names.py --check: up to date

🤖 Generated with Claude Code

}
EnumRow("Difficulty", game::GetDifficulty());
DisplayRow("Mode", "%s", game::GetGameType() == 0 ? "Classic" : "Expansion");
EnumRow("Mode", game::GetGameType());

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be game type

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5eddbd9: the row reads the GameType enum (EnumRow prints its name) and is now labelled Game type instead of Mode.

/// @returns {boolean} - Result of the creation attempt; undefined if not at the menu. Throws on invalid arguments.
/// @throws {Error} - Character type is outside the valid class range (0-6).
/// @throws {Error} - Character type is outside the valid class range (0-7), the game type is not a GameType, or
/// the class cannot be created with that game type.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should state that Warlock and ROTW does nothing on 1.14d

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5eddbd9: the createCharacter doc now says the Warlock class and the RotW game type do nothing on 1.14d - it creates only Expansion characters and returns false for any other game type, so a Warlock is never created there.

@ResurrectedTrader
ResurrectedTrader added this pull request to stack #78 October 6, 2026 23:12
Base automatically changed from contract-common-helpers to main October 7, 2026 06:53
ResurrectedTrader and others added 3 commits October 7, 2026 07:58
Continues the typed-enum work: contract signatures take and return
enums and the narrowest integer the game uses instead of bare uint32_t /
int32_t, and the JS bindings convert at the edge, so scripts see the
same numbers.

- GetGameType() returns GameType, which gains RotW = 2; the settings
  panel names the mode from the enum. 1.14d is unchanged (never RotW).
- createCharacter(name, class, hardcore, ladder, gameType?): an optional
  GameType, RotW by default for a Warlock and Expansion otherwise; a
  Warlock must be RotW and a Classic Assassin / Druid is impossible (both
  throw). Class and game type are read as enums. 1.14d creates only
  Expansion characters, so createCharacter(name, 7) returns false there
  instead of throwing. createGame's difficulty default is named
  Difficulty::HighestAvailable.
- Unit::RunWalk returns MoveMode; the always-run import is
  GameVar<MoveMode>.
- A Language enum (GetLocale / me.locale), pinned to D2MOO's values;
  MonEnchant gets a uint8_t underlying type, ArenaFlag / ClickOnMapFlag
  uint32_t.
- LevelId types area numbers across the contract, the bindings, the
  navigation code and the tests.
- Stat, State, Skill, Quest and StatListFlags enums replace the loose
  constants; 1.14d static_asserts them against D2MOO where they meet.
- Narrower types: Party::ClassId -> CharacterClass; Party::CharacterLevel,
  Unit::SuperUniqueId, NPC menu ids and locale string ids -> uint16_t;
  stat and skill point counts -> uint16_t; gold amounts unsigned;
  redundant casts in the bindings dropped.
- UnitFlagEx bit 0x08000000 is named AnimEndOfCycle.

CLAUDE.md's constants guidance names the new enums. Generated enum names
rerun.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The `///` docs of the bindings whose values come from a contract enum
name it instead of `{number}`, so the API docs render its value table and
the d.ts types it: getItemCost (ItemCostMode, Difficulty), shop
(ShopMode), cancel (CancelMode), getStatLists (StatListFlags, Stat),
room.getCollision (CollisionFlag), getUnit (UnitType), getSkillById
(Skill), getTradeInfo (TradeInfoMode), getControl (ControlType),
clickItem (BodyLocation, ClickButton, ItemLocation), clickParty
(PartyMode), gold (GoldActionMode), acceptTrade (AcceptTradeQueryMode),
createGame and addProfile (Difficulty). Value lists that only restated
the enum leave the descriptions.

gen_dts.py maps a bitfield or namespace name to `number` inside a
composite type as well (`CollisionFlag[][]`, `{flags:StatListFlags}`),
not only when it is the whole type.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d limits

The console settings panel labels the GameType row "Game type".
createCharacter's doc says the Warlock class and the RotW game type do
nothing on 1.14d.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ResurrectedTrader
ResurrectedTrader merged commit f1c1eff into main Oct 7, 2026
1 check passed
@ResurrectedTrader
ResurrectedTrader deleted the contract-typed-values branch October 7, 2026 07:42
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