12137 Commits
Author SHA1 Message Date
Yuri Pourre 74ce5cdb15 Add Lua towns.register with role-based per-town NPCs (#8774) 2026-11-07 18:41:05 +00:00
Developer Guilliman 8a6b857427 Extracted shrine data to shrines.tsv (#8791)
Signed-off-by: Developer Guilliman <[email protected]>
2026-11-07 16:21:30 +00:00
Yuri Pourre 2380e19e74 Build towner menus from a list of entries
Top-level towner menus now collect their rows with small helpers and
StartStore draws them. No behavior change.
2026-11-07 16:16:40 +00:00
staphen d63afe3250 Pick a new multi-page seed that works with spawn.mpq 2026-11-07 02:46:02 +00:00
staphen ee5c761897 Update MacOS version from 14 to 15 in CI runners 2026-11-06 01:57:10 +01:00
staphen 644c289ad1 Pick a better seed to avoid skipping visual store tests 2026-11-06 01:39:14 +01:00
wkdgmrandClaude Opus 5.5 ea7b5be462 Lua: let mods add player classes from TSV
Adds a PlayerDataLoaded event, fired after classdat.tsv loads and before each
class's own data folder is read, plus player.addClassDataFromTsv(path), which
feeds the existing LoadClassDatFromFile. This matches the MonsterDataLoaded /
monsters.addMonsterDataFromTsv pattern. Several mods can each add classes
without overriding the shared classdat.tsv; the existing class limit still
applies.

No handler means no change: class data loads exactly as before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-04 00:24:42 +01:00
Yuri Pourre b325996a89 Load town tile assets from TownConfig with retail fallbacks (#8769) 2026-10-31 14:09:09 +00:00
Yuri Pourre 06d17533e6 Drive town triggers and portal positions from TownConfig.
Move Tristram warp triggers and per-player portal anchors into the town
registry so layout data stays with sectors and entry points.
2026-10-28 22:34:35 +01:00
Yuri Pourre edf77a9139 Add town registry and drive Tristram generation from TownConfig.
Centralize Tristram sectors and spawn entry points in the registry so
CreateTown and load-game initialization share one data path, with unit tests.
2026-10-28 09:43:21 +00:00
Gleb MazovetskiyandClaude Opus 5.5 aa3dc7b10e [Amiga] Disable the sdl2.library wrapper
The updated Amiga SDL2 fork builds an sdl2.library wrapper by default.
We link SDL2 statically so we do not need it, and it fails to link with
LTO enabled.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 21:05:31 +00:00
Anders Jenbo acfa765cd1 Add comment for active portal positoins 2026-10-27 19:45:15 +01:00
Nigel Todman 99ca00b4ae Skip UI test setup/teardown halves when MPQ fixtures are missing 2026-10-27 18:55:33 +01:00
Yuri Pourre d43de149f9 Make portal positions dynamic 2026-10-27 18:55:08 +01:00
Yuri Pourre 8dcb4d2542 Make level's triggers dynamic 2026-10-27 18:53:55 +01:00
Eric Robinson d4c8e11ad7 Fix DamageParryItem 2026-10-27 18:47:15 +01:00
Eric Robinson 627857c863 [Bugfix/Engine] Fix DamageArmor 2026-10-27 18:46:12 +01:00
Eric Robinson 532edb4210 [Bugfix] Fix Resurrect running on wrong levels (#8343) 2026-10-27 18:44:46 +01:00
Rodrigo Vegas Sánchez-Ferrero bbd829b8bd Update es.po 2026-10-27 18:42:33 +01:00
Santaingamba 03398a3139 Validate spell IDs when loading item save data 2026-10-27 18:41:51 +01:00
Roman Stingler 9d2b508566 clamp loaded player class to valid range 2026-10-27 18:41:15 +01:00
Eric Robinson 11f047183b [Engine] Refactor StartPlayerKill 2026-10-27 18:39:53 +01:00
YAOHUI LI 627a998506 Open Fix two crashes when running in HeadlessMode 2026-10-27 18:33:11 +01:00
Blaze Mcszk 4c538a9d3d fix: finding closest controller targets
Start target search from wide bounds (rotations=4, distance=25) instead of 0
so the first candidate is always accepted and the closest target wins,
in FindRangedTarget/FindMeleeTarget/CheckPlayerNearby/FindTrigger.
2026-10-27 18:31:10 +01:00
Eric Robinson 3e24a60c9b Fix Attack Speed Affix Panel Strings 2026-10-27 18:29:01 +01:00
Eric Robinson cd7f9d3065 [Bugfix/Engine] Refactor OperateShrineGloomy (#8380) 2026-10-27 18:28:04 +01:00
Eric Robinson 175d793a0d [Bugfix/Engine] Refactor OperateShrineWeird (#8378) 2026-10-27 18:26:24 +01:00
Ayrton Sanabio 26170ad80e Update Brazilian Portuguese translation 2026-10-27 18:20:22 +01:00
Eric Robinson 36c4a8e158 [Bugfix] Fix Item Delta capacity mismatch with Items array 2026-10-27 17:58:04 +01:00
staphen 137d24c552 Deploy hf.mpq on Android and MacOS 2026-10-27 16:49:57 +01:00
obligaron 9d4871587e Switch from CMakeSettings to CMakePresets 2026-10-25 11:30:51 -04:00
Gleb MazovetskiyandClaude Opus 5.5 5ea9914c5e Deploy the test DLLs in a single step on Windows
With vcpkg on Windows, every executable and DLL gets a post-link step
that runs `vcpkg z-applocal` to copy its DLL dependencies next to it.
All the test binaries share the build directory, so dozens of these
steps ran alongside the links, and the build occasionally failed with
"The process cannot access the file because it is being used by another
process."

Turn off the per-target step for the test binaries and deploy their DLLs
in a single step once they are all linked.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 09:29:24 +00:00
staphen 1368b34afe Log reason for failure when capturing screenshots 2026-10-25 07:07:15 +01:00
Nigel Todman 4ad34d9688 Include SDL_main.h explicitly 2026-10-24 02:24:23 +02:00
staphen 0706e014d6 Add sanitizer to correct broken audio data in hellfire.mpq 2026-10-20 09:54:09 +02:00
staphen 16a6df6c75 Deploy hf.mpq on 3DS and Switch 2026-10-20 04:29:37 +01:00
Gleb MazovetskiyandClaude Opus 5.5 a927236209 Fix PCX scanline padding handling
The PCX specification requires the number of bytes per scanline to be
even. PCX screenshots of an odd width were written without padding,
and `PcxToClx` ignored the header's bytes-per-line value and assumed a
padding byte for odd widths. The screen width can be odd, e.g. 683 with
integer scaling on a 1366x768 display.

`PcxToClx` now:
* Decodes scanlines using the bytes-per-line value from the header, so
  both padded and unpadded files (e.g. older DevilutionX screenshots)
  are read correctly.
* Validates the input (truncated data, runs crossing a scanline, image
  format, frame count) and returns an error message, which is logged,
  instead of reading out of bounds. Previously, the palette separator
  was only checked by an assertion.
* Reads the palette from the end of the file, as per the specification.

The screenshot writer now:
* Pads scanlines to an even length.
* No longer reads one byte past the end of each line.
* Compiles with SDL3, where the surface palette is obtained with
  `SDL_GetSurfacePalette`.
* Returns an error for a surface without a palette (the default for
  indexed surfaces in SDL3), and no longer reads past the end of a
  palette with fewer than 256 colors.

The PCX files from DIABDAT.MPQ, HELLFIRE.MPQ, and the DevilutionX assets
are all padded correctly and load the same as before.

`surface_to_pcx` is now an object library so that it can be tested in
builds with PNG screenshots.

Ported from https://github.com/diasurgical/clx-conversion-tools/commit/4d4debd

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 09:20:04 +01:00
Gleb Mazovetskiy 0011dc9670 CI: Fix packages 2026-10-17 16:18:45 +01:00
Gleb MazovetskiyandClaude Opus 5.5 24113c50af Discover the tests when they are run
`gtest_discover_tests` ran each test executable right after linking it
to list its tests. On Windows, the vcpkg toolchain also copies a test's
DLLs next to it after linking, into the same build directory for every
test. With many tests linking in parallel, a test could be running
while another's copy step tried to replace a DLL it had loaded, which
failed the build with "The process cannot access the file because it is
being used by another process."

With `DISCOVERY_MODE PRE_TEST`, the tests are listed when `ctest` runs
instead, after the build has finished.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 16:18:45 +01:00
staphen 94433061f8 Free pointer returned by SDL_GetDisplays() 2026-10-15 19:53:34 +02:00
Gleb MazovetskiyandClaude Sonnet 5 b0a3b7babb Migrate AnimationInfo's internal fixed-point fields to FixedPoint
Add FixedPoint::divideWithoutWidening for cases where the caller can
already show the wide intermediate isn't needed, and use it in
AnimationInfo::setNewAnimation to avoid a 64-bit division that the
original int32_t arithmetic never required.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-10-11 21:55:08 +01:00
Gleb Mazovetskiy 7fdf19da3a FixedPoint: Implement comparison with int 2026-10-11 21:55:08 +01:00
Gleb Mazovetskiy c361e764cc FixedPoint: Follow C integer promotion rules
Also allow implicit widening conversion.
Narrowing conversion still explicit.
2026-10-11 21:55:08 +01:00
Gleb MazovetskiyandClaude Sonnet 5 92927ca913 Migrate ClassAttributes, player HP/mana, item HP/mana bonuses, and monster HP to Fixed10_6/Fixed26_6
Replaces ParseFixed6/parseFixed6/readFixed6/readDecimal's raw-int
plumbing with the new FixedPoint type, then propagates strongly-typed
fixed-point fields through everywhere that consumed them: player
_pHitPoints/_pMana (and their base/max variants), ClassAttributes'
percentage/multiplier fields, Item::_iPLHP/_iPLMana, and
Monster::hitPoints/maxHitPoints. Eliminates manual <<6/>>6 bit-shifting
at nearly every call site in favor of fromInt/fromRaw/whole() and the
new fixed-point arithmetic operators, while preserving raw() only at
genuine serialization/network wire-format boundaries.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-10-11 21:55:08 +01:00
Gleb MazovetskiyandClaude Sonnet 5 c2080753e6 Add FixedPoint<StorageT, FractionalBits> type
Introduces a strongly-typed wrapper for the 10.6 fixed-point values used
throughout the engine (e.g. hit points, mana), with Fixed10_6 (int16_t
storage) and Fixed26_6 (int32_t storage) aliases.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-10-11 21:55:08 +01:00
Gleb MazovetskiyandClaude Opus 5.5 3755190275 Cl2ToClx: End opaque runs at the end of each line
In CLX, only transparent runs can continue on the next line.
`Cl2ToClx` joined the opaque pixels that end a line with the opaque
pixels that begin the next line into a single run, and the renderer
then drew the second part past the end of the first line instead of
at the beginning of the next one.

CL2 itself has no such runs. Among the player sprites of DIABDAT.MPQ,
the converter produced them in 991 of 78,016 frames (2,236 pixels),
mostly in spell casting animations that reach both edges of the frame.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 19:49:10 +01:00
Gleb MazovetskiyandClaude Opus 5.5 b569d8acfd Don't repeat held actions that need walking while nothing affecting the path has changed
While a mouse button or controller action is held, the last action is
re-sent every game tick. This affects walking, melee attacks on targets
out of reach and operating objects the player isn't next to. If no path
to the target exists, each repeat runs two or three worst-case path
searches for the same result, which noticeably reduces FPS.

Add WalkabilityGeneration, bumped whenever tile solidity, objects or
the tiles occupied by monsters and players change. RepeatPlayerAction
remembers the last request that needed walking and skips an identical
one while the start tile, destination, generation and player life
states are unchanged. A request that finds a path moves the player, so
this only skips requests that failed or are still pending.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 18:18:29 +01:00
Developer Guilliman a461a18275 Golem monster portrait (#8729)
Added option to show summoned monster (Golem) party portrait
Fixed crash when loading .trn files for monsters with missing animations
(Golem is missing standing animation)
2026-10-10 19:20:43 +01:00
Developer Guilliman bf574c9b74 Party portrait fixes (#8725)
When calculating width of mana bars, if another player has a maximum amount of mana of zero (like a Barbarian) would cause a division by zero, crashing the rendering client. Fixed by not rendering the blue portion of the mana bar if the max mana is zero.
Not applying players palette transform, stored in a .trn file. Fixed by applying the trn to the stored portrait sprite, if available.

Created several values in the player classes sprites.tsv to store the offsets of the sprites rendered in the portrait. The new values are:
- **partyOffsetTownX** : X Offset for the portrait when the player is in town
- **partyOffsetTownY** : Y Offset for the portrait when the player is in town
- **partyOffsetDungeonX** : X Offset for the portrait when the player is in dungeon
- **partyOffsetDungeonY** : Y Offset for the portrait when the player is in dungeon
- **partyOffsetDeadX** : X Offset for the portrait when the player is dead
- **partyOffsetDeadY** : Y Offset for the portrait when the player is dead

This new values are documented in the assets/txtdata/classes/README.md file, with also the rest of the possible values for the sprites.tsv files
2026-10-08 20:30:58 +01:00
ajakilas a45c53bd59 Add Tatar translation 2026-10-08 20:29:18 +01:00