Add shareware HUD module and integrate with asset registry for improved HUD handling
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:wolf_3d_dart/src/registry/asset_registry.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/retail_hud_module.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/retail_sfx_module.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/shareware_entity_module.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/shareware_hud_module.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/shareware_menu_module.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/built_in/shareware_music_module.dart';
|
||||
|
||||
@@ -10,7 +10,7 @@ import 'package:wolf_3d_dart/src/registry/built_in/shareware_music_module.dart';
|
||||
/// - SFX slots are identical to retail (same AUDIOT layout).
|
||||
/// - Music routing uses the 10-level shareware table.
|
||||
/// - Entity definitions are limited to the three shareware enemies.
|
||||
/// - HUD indices are identical to retail (same relative VGA layout).
|
||||
/// - HUD indices are shareware-aware and offset from retail layout.
|
||||
/// - Menu picture indices are resolved via runtime heuristic offset; call
|
||||
/// [SharewareMenuPicModule.initWithImageSizes] after the VGA images are
|
||||
/// available so the shift is computed correctly.
|
||||
@@ -20,7 +20,9 @@ class SharewareAssetRegistry extends AssetRegistry {
|
||||
sfx: const RetailSfxModule(),
|
||||
music: const SharewareMusicModule(),
|
||||
entities: const SharewareEntityModule(),
|
||||
hud: const RetailHudModule(),
|
||||
hud: SharewareHudModule(
|
||||
useOriginalWl1Map: strictOriginalShareware,
|
||||
),
|
||||
menu: SharewareMenuPicModule(
|
||||
useOriginalWl1Map: strictOriginalShareware,
|
||||
),
|
||||
@@ -28,4 +30,7 @@ class SharewareAssetRegistry extends AssetRegistry {
|
||||
|
||||
/// Convenience accessor to the menu module for post-load initialisation.
|
||||
SharewareMenuPicModule get sharewareMenu => menu as SharewareMenuPicModule;
|
||||
|
||||
/// Convenience accessor to the HUD module for post-load initialisation.
|
||||
SharewareHudModule get sharewareHud => hud as SharewareHudModule;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:wolf_3d_dart/src/registry/keys/hud_key.dart';
|
||||
import 'package:wolf_3d_dart/src/registry/modules/hud_module.dart';
|
||||
|
||||
/// Built-in HUD module for Wolf3D shareware data variants.
|
||||
///
|
||||
/// For known original WL1 data, the HUD picture table is shifted by +12 from
|
||||
/// retail indices. For unknown shareware-like data, the offset is detected from
|
||||
/// the STATUSBARPIC landmark at runtime.
|
||||
class SharewareHudModule extends HudModule {
|
||||
SharewareHudModule({this.useOriginalWl1Map = false});
|
||||
|
||||
final bool useOriginalWl1Map;
|
||||
|
||||
static const int _originalWl1Offset = 12;
|
||||
static const int _retailStatusBarIndex = 83;
|
||||
|
||||
static const List<HudKey> _faceBands = [
|
||||
HudKey.faceHealthy,
|
||||
HudKey.faceScratched,
|
||||
HudKey.faceHurt,
|
||||
HudKey.faceWounded,
|
||||
HudKey.faceBadlyWounded,
|
||||
HudKey.faceDying,
|
||||
HudKey.faceNearDeath,
|
||||
];
|
||||
|
||||
static final Map<HudKey, int> _retailBaseline = {
|
||||
HudKey.statusBar: 83,
|
||||
HudKey.digit0: 96,
|
||||
HudKey.digit1: 97,
|
||||
HudKey.digit2: 98,
|
||||
HudKey.digit3: 99,
|
||||
HudKey.digit4: 100,
|
||||
HudKey.digit5: 101,
|
||||
HudKey.digit6: 102,
|
||||
HudKey.digit7: 103,
|
||||
HudKey.digit8: 104,
|
||||
HudKey.digit9: 105,
|
||||
HudKey.faceHealthy: 106,
|
||||
HudKey.faceScratched: 109,
|
||||
HudKey.faceHurt: 112,
|
||||
HudKey.faceWounded: 115,
|
||||
HudKey.faceBadlyWounded: 118,
|
||||
HudKey.faceDying: 121,
|
||||
HudKey.faceNearDeath: 124,
|
||||
HudKey.faceDead: 127,
|
||||
HudKey.pistolIcon: 89,
|
||||
HudKey.machineGunIcon: 90,
|
||||
HudKey.chainGunIcon: 91,
|
||||
};
|
||||
|
||||
int? _offset;
|
||||
|
||||
void initWithImageSizes(List<({int width, int height})> imageSizes) {
|
||||
_offset = _computeOffset(imageSizes);
|
||||
}
|
||||
|
||||
int _computeOffset(List<({int width, int height})> sizes) {
|
||||
for (int i = 0; i < sizes.length; i++) {
|
||||
final s = sizes[i];
|
||||
if (s.width >= 280 && s.height >= 24 && s.height <= 64) {
|
||||
return i - _retailStatusBarIndex;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get _effectiveOffset => useOriginalWl1Map ? _originalWl1Offset : (_offset ?? 0);
|
||||
|
||||
@override
|
||||
HudAssetRef? resolve(HudKey key) {
|
||||
final base = _retailBaseline[key];
|
||||
if (base == null) return null;
|
||||
return HudAssetRef(base + _effectiveOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
HudKey faceKeyForHealth(int health) {
|
||||
if (health <= 0) return HudKey.faceDead;
|
||||
final band = ((100 - health) ~/ 16).clamp(0, _faceBands.length - 1);
|
||||
return _faceBands[band];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user