Refactor collectible handling and scoring system
- Introduced `CollectiblePickupContext` and `CollectiblePickupEffect` to streamline the collectible pickup logic in the Player class. - Updated the `tryPickup` method in the Player class to utilize the new effect system for health, ammo, score, keys, and weapons. - Refactored collectible classes to implement the new `tryCollect` method, returning a `CollectiblePickupEffect`. - Enhanced enemy classes to expose score values based on their type. - Added unit tests for scoring ownership and shareware menu module functionality. - Updated rendering logic in various renderer classes to use the new mapped picture retrieval system. - Improved the `WolfClassicMenuArt` class to utilize a more structured approach for image retrieval based on registry keys. Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -98,103 +98,45 @@ class WolfClassicMenuArt {
|
||||
|
||||
WolfClassicMenuArt(this.data);
|
||||
|
||||
int? _resolvedIndexOffset;
|
||||
|
||||
VgaImage? get controlBackground {
|
||||
final preferred = mappedPic(WolfMenuPic.cControl);
|
||||
if (_looksLikeMenuBackdrop(preferred)) {
|
||||
return preferred;
|
||||
}
|
||||
|
||||
// Older data layouts may shift/control-panel art around nearby indices.
|
||||
for (int delta = -4; delta <= 4; delta++) {
|
||||
final candidate = mappedPic(WolfMenuPic.cControl + delta);
|
||||
if (_looksLikeMenuBackdrop(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return preferred;
|
||||
return _imageForKey(MenuPicKey.controlBackground);
|
||||
}
|
||||
|
||||
VgaImage? get title => mappedPic(WolfMenuPic.title);
|
||||
VgaImage? get title => _imageForKey(MenuPicKey.title);
|
||||
|
||||
VgaImage? get heading => mappedPic(WolfMenuPic.hTopWindow);
|
||||
VgaImage? get heading => _imageForKey(MenuPicKey.heading);
|
||||
|
||||
VgaImage? get selectedMarker => mappedPic(WolfMenuPic.cSelected);
|
||||
VgaImage? get selectedMarker => _imageForKey(MenuPicKey.markerSelected);
|
||||
|
||||
VgaImage? get unselectedMarker => mappedPic(WolfMenuPic.cNotSelected);
|
||||
VgaImage? get unselectedMarker => _imageForKey(MenuPicKey.markerUnselected);
|
||||
|
||||
VgaImage? get optionsLabel => mappedPic(WolfMenuPic.cOptions);
|
||||
VgaImage? get optionsLabel => _imageForKey(MenuPicKey.optionsLabel);
|
||||
|
||||
VgaImage? get credits => mappedPic(WolfMenuPic.credits);
|
||||
VgaImage? get credits => _imageForKey(MenuPicKey.credits);
|
||||
|
||||
VgaImage? episodeOption(int episodeIndex) {
|
||||
if (episodeIndex < 0 || episodeIndex >= WolfMenuPic.episodePics.length) {
|
||||
if (episodeIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return mappedPic(WolfMenuPic.episodePics[episodeIndex]);
|
||||
final key = data.registry.menu.episodeKey(episodeIndex);
|
||||
return _imageForKey(key);
|
||||
}
|
||||
|
||||
VgaImage? difficultyOption(Difficulty difficulty) {
|
||||
switch (difficulty) {
|
||||
case Difficulty.baby:
|
||||
return mappedPic(WolfMenuPic.cBabyMode);
|
||||
case Difficulty.easy:
|
||||
return mappedPic(WolfMenuPic.cEasy);
|
||||
case Difficulty.medium:
|
||||
return mappedPic(WolfMenuPic.cNormal);
|
||||
case Difficulty.hard:
|
||||
return mappedPic(WolfMenuPic.cHard);
|
||||
}
|
||||
final key = data.registry.menu.difficultyKey(difficulty);
|
||||
return _imageForKey(key);
|
||||
}
|
||||
|
||||
/// Returns [index] after applying a detected version/layout offset.
|
||||
/// Legacy numeric lookup API retained for existing renderer call sites.
|
||||
///
|
||||
/// Known legacy indices are mapped through symbolic registry keys first.
|
||||
/// Unknown indices fall back to direct picture-table indexing.
|
||||
VgaImage? mappedPic(int index) {
|
||||
return pic(index + _indexOffset);
|
||||
}
|
||||
|
||||
int get _indexOffset {
|
||||
if (_resolvedIndexOffset != null) {
|
||||
return _resolvedIndexOffset!;
|
||||
final key = _legacyKeyForIndex(index);
|
||||
if (key != null) {
|
||||
return _imageForKey(key);
|
||||
}
|
||||
|
||||
// Retail and shareware generally place STATUSBAR/TITLE/PG13/CREDITS as a
|
||||
// contiguous block. If files are from a different release, infer a shift.
|
||||
for (int i = 0; i < data.vgaImages.length - 3; i++) {
|
||||
final status = data.vgaImages[i];
|
||||
if (!_looksLikeStatusBar(status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final title = data.vgaImages[i + 1];
|
||||
final pg13 = data.vgaImages[i + 2];
|
||||
final credits = data.vgaImages[i + 3];
|
||||
if (_looksLikeFullScreen(title) &&
|
||||
_looksLikeFullScreen(pg13) &&
|
||||
_looksLikeFullScreen(credits)) {
|
||||
_resolvedIndexOffset = i - WolfMenuPic.statusBar;
|
||||
return _resolvedIndexOffset!;
|
||||
}
|
||||
}
|
||||
|
||||
_resolvedIndexOffset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool _looksLikeStatusBar(VgaImage image) {
|
||||
return image.width >= 280 && image.height >= 24 && image.height <= 64;
|
||||
}
|
||||
|
||||
bool _looksLikeFullScreen(VgaImage image) {
|
||||
return image.width >= 280 && image.height >= 140;
|
||||
}
|
||||
|
||||
bool _looksLikeMenuBackdrop(VgaImage? image) {
|
||||
if (image == null) {
|
||||
return false;
|
||||
}
|
||||
return image.width >= 180 && image.height >= 100;
|
||||
return pic(index);
|
||||
}
|
||||
|
||||
VgaImage? pic(int index) {
|
||||
@@ -203,14 +145,67 @@ class WolfClassicMenuArt {
|
||||
}
|
||||
final image = data.vgaImages[index];
|
||||
|
||||
// Ignore known gameplay HUD art in menu composition.
|
||||
if (index == WolfMenuPic.statusBar + _indexOffset) {
|
||||
return null;
|
||||
}
|
||||
if (image.width <= 0 || image.height <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
VgaImage? _imageForKey(MenuPicKey key) {
|
||||
final ref = data.registry.menu.resolve(key);
|
||||
if (ref == null) {
|
||||
return null;
|
||||
}
|
||||
return pic(ref.pictureIndex);
|
||||
}
|
||||
|
||||
MenuPicKey? _legacyKeyForIndex(int index) {
|
||||
switch (index) {
|
||||
case WolfMenuPic.hTopWindow:
|
||||
return MenuPicKey.heading;
|
||||
case WolfMenuPic.cOptions:
|
||||
return MenuPicKey.optionsLabel;
|
||||
case WolfMenuPic.cCursor1:
|
||||
return MenuPicKey.cursorActive;
|
||||
case WolfMenuPic.cCursor2:
|
||||
return MenuPicKey.cursorInactive;
|
||||
case WolfMenuPic.cNotSelected:
|
||||
return MenuPicKey.markerUnselected;
|
||||
case WolfMenuPic.cSelected:
|
||||
return MenuPicKey.markerSelected;
|
||||
case 15:
|
||||
return MenuPicKey.footer;
|
||||
case WolfMenuPic.cBabyMode:
|
||||
return MenuPicKey.difficultyBaby;
|
||||
case WolfMenuPic.cEasy:
|
||||
return MenuPicKey.difficultyEasy;
|
||||
case WolfMenuPic.cNormal:
|
||||
return MenuPicKey.difficultyNormal;
|
||||
case WolfMenuPic.cHard:
|
||||
return MenuPicKey.difficultyHard;
|
||||
case WolfMenuPic.cControl:
|
||||
return MenuPicKey.controlBackground;
|
||||
case WolfMenuPic.cEpisode1:
|
||||
return MenuPicKey.episode1;
|
||||
case WolfMenuPic.cEpisode2:
|
||||
return MenuPicKey.episode2;
|
||||
case WolfMenuPic.cEpisode3:
|
||||
return MenuPicKey.episode3;
|
||||
case WolfMenuPic.cEpisode4:
|
||||
return MenuPicKey.episode4;
|
||||
case WolfMenuPic.cEpisode5:
|
||||
return MenuPicKey.episode5;
|
||||
case WolfMenuPic.cEpisode6:
|
||||
return MenuPicKey.episode6;
|
||||
case WolfMenuPic.title:
|
||||
return MenuPicKey.title;
|
||||
case WolfMenuPic.pg13:
|
||||
return MenuPicKey.pg13;
|
||||
case WolfMenuPic.credits:
|
||||
return MenuPicKey.credits;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user