Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,17 +597,18 @@ literal, in this order:
(`D2C_UnitTypes`), `D2Monsters.h` (`D2C_MonTypeFlags`). Most are already in scope
through `imports/D2Common.h`. Platform values likewise: `WM_LBUTTONDOWN`, not `0x201`.
2. **`src/contract/game/`** - `Constants.h` and the enums in `Types.h` (`UnitType`,
`MonsterSpecType`, `ItemLocation`, ...). The frontend and the contract cannot see
D2MOO, so these mirror the handful of values the JS API needs; use them there
instead of re-typing the literal.
`Stat`, `State`, `Skill`, `StatListFlags`, `ItemLocation`, ...). The frontend and the
contract cannot see D2MOO, so these mirror the values the JS API needs; use them there
instead of re-typing the literal. A backend takes the contract enum in its typed
imports and `static_assert`s it against D2MOO's constant where the two meet.
3. **The backend's shared headers** - e.g. `SUBTILE_SCALE` in
`backends/lod114d/game/DrlgHelpers.h`.

When a value genuinely has to be restated, derive it from the canonical definition
rather than repeating the literal:

```cpp
constexpr uint32_t STAT_FIXED_POINT_FIRST = STAT_HITPOINTS;
constexpr uint32_t UNIT_TYPE_NPC = UNIT_MONSTER;
```

**Scope it to its use.** A constant used by one file stays in that file's anonymous
Expand Down
4 changes: 4 additions & 0 deletions scripts/gen_dts.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def ts_type(t, *, is_return=False):
t = str(t).strip()
if t in _NUMBER_TYPES:
return "number"
# A bitfield / namespace name inside a composite type (`CollisionFlag[][]`,
# `{flags:StatListFlags}`) is `number` too.
if _NUMBER_TYPES:
t = re.sub(r"\b(?:" + "|".join(map(re.escape, sorted(_NUMBER_TYPES))) + r")\b", "number", t)
if is_return and t == "null":
return "void" # "returns null" is the API's way of saying "no result"
# a bare `function` param type with no callback detail -> the Function type
Expand Down
7 changes: 2 additions & 5 deletions src/backends/lod114d/game/Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,12 @@ uint32_t Control::SelectEnd() const {
return ctrl ? ctrl->dwSelectEnd : 0U;
}

bool Control::HasLocaleText(int32_t localeId) const {
if (localeId < 0) {
return false;
}
bool Control::HasLocaleText(uint16_t localeId) const {
const auto ctrl = Resolve<D2WinControlStrc>();
if (!ctrl) {
return false;
}
const auto* localeText = lod114d::imports::d2lang::D2LANG_GetLocaleText(static_cast<uint16_t>(localeId));
const auto* localeText = lod114d::imports::d2lang::D2LANG_GetLocaleText(localeId);
if (localeText == nullptr) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/backends/lod114d/game/DrlgHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ constexpr int32_t SUBTILE_SCALE = 5;
// `D2UnitStrc::pDrlgAct` is typed as D2MOO's `::D2DrlgActStrc*`, but the bytes
// at that address follow the 1.14d allocation modeled by
// `extras::D2DrlgActStrc`. Reinterpret at the unit boundary.
inline D2DrlgLevelStrc* FindLevelInChain(uint32_t levelId) {
inline D2DrlgLevelStrc* FindLevelInChain(LevelId levelId) {
auto* player = lod114d::imports::d2client::UNITS_GetPlayerUnit();
if (player == nullptr) {
return nullptr;
Expand All @@ -48,7 +48,7 @@ inline D2DrlgLevelStrc* FindLevelInChain(uint32_t levelId) {
return nullptr;
}
for (auto* level = act->pDrlg->pLevel; level != nullptr; level = level->pNextLevel) {
if (static_cast<uint32_t>(level->nLevelId) != levelId) {
if (static_cast<LevelId>(level->nLevelId) != levelId) {
continue;
}
if (level->pFirstRoomEx == nullptr) {
Expand Down
Loading
Loading