[Scummvm-git-logs] scummvm master -> 7a5326ad82f3a5991d4435d1f2003641481132e5
sev-
noreply at scummvm.org
Sun Mar 1 12:20:24 UTC 2026
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
5f4f2857b5 ALG: Refactoring, moved game-specific fields
7444a45dd9 ALG: Bugfixes for Graphics, script bugfix for SP
51a5e63af7 ALG: Refactoring, improve support for LBH
3d5a98788b ALG: Refactoring, further implementations for LBH
8ef78e5e6d ALG: Bugfixes for LBH and SP, refactoring
90a83d7322 ALG: minor style cleanup
597d22e7f0 ALG: fix clang warnings of unused fields
854c9aa33b ALG: bugfix, do not assign int to string
8e49de7a26 ALG: add GUIO docs
d3b5625ea2 ALG: enable build-by-default
7a5326ad82 NEWS: add ALG games
Commit: 5f4f2857b57088226d720fb177500b0eae711aa2
https://github.com/scummvm/scummvm/commit/5f4f2857b57088226d720fb177500b0eae711aa2
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: Refactoring, moved game-specific fields
Changed paths:
engines/alg/game.cpp
engines/alg/game.h
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_bountyhunter.h
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_crimepatrol.h
engines/alg/logic/game_drugwars.cpp
engines/alg/logic/game_drugwars.h
engines/alg/logic/game_johnnyrock.cpp
engines/alg/logic/game_johnnyrock.h
engines/alg/logic/game_maddog.cpp
engines/alg/logic/game_maddog.h
engines/alg/logic/game_maddog2.cpp
engines/alg/logic/game_maddog2.h
engines/alg/logic/game_spacepirates.cpp
engines/alg/logic/game_spacepirates.h
diff --git a/engines/alg/game.cpp b/engines/alg/game.cpp
index bee89e52426..8b9c0e4bbd4 100644
--- a/engines/alg/game.cpp
+++ b/engines/alg/game.cpp
@@ -23,7 +23,6 @@
#include "audio/decoders/raw.h"
#include "common/events.h"
#include "common/substream.h"
-#include "common/timer.h"
#include "graphics/cursorman.h"
#include "graphics/paletteman.h"
@@ -65,14 +64,6 @@ Game::~Game() {
delete item;
}
}
- delete _saveSound;
- delete _loadSound;
- delete _easySound;
- delete _avgSound;
- delete _hardSound;
- delete _skullSound;
- delete _shotSound;
- delete _emptySound;
}
void Game::init() {
@@ -224,10 +215,10 @@ Zone *Game::checkZonesV1(Scene *scene, Rect *&hitRect, Common::Point *point) {
}
// This is used by later games
-Zone *Game::checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point) {
+Zone *Game::checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point, uint8 difficulty) {
for (auto &zone : scene->_zones) {
- uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((_difficulty - 1) * _videoFrameSkip);
- uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((_difficulty - 1) * _videoFrameSkip);
+ uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((difficulty - 1) * _videoFrameSkip);
+ uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((difficulty - 1) * _videoFrameSkip);
if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
hitRect = checkZone(zone, point);
if (hitRect != nullptr) {
@@ -289,30 +280,6 @@ int8 Game::skipToNewScene(Scene *scene) {
return 0;
}
-uint16 Game::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
- if (max == 1) {
- return 0;
- }
- // reset mask if full
- uint16 fullMask = 0xFFFF >> (16 - max);
- if (*mask == fullMask) {
- *mask = 0;
- }
- uint16 randomNum = 0;
- // find an unused random number
- while (true) {
- randomNum = _rnd->getRandomNumber(max - 1);
- // check if bit is already used
- uint16 bit = 1 << randomNum;
- if (!((*mask & bit) || randomNum == exclude)) {
- // set the bit in mask
- *mask |= bit;
- break;
- }
- }
- return randomNum;
-}
-
// Sound
Audio::SeekableAudioStream *Game::loadSoundFile(const Common::Path &path) {
Common::File *file = new Common::File();
@@ -332,73 +299,6 @@ void Game::playSound(Audio::SeekableAudioStream *stream) {
}
}
-void Game::doDiffSound(uint8 difficulty) {
- switch (difficulty) {
- case 1:
- return playSound(_easySound);
- case 2:
- return playSound(_avgSound);
- case 3:
- return playSound(_hardSound);
- }
-}
-
-void Game::doSaveSound() {
- playSound(_saveSound);
-}
-
-void Game::doLoadSound() {
- playSound(_loadSound);
-}
-
-void Game::doSkullSound() {
- playSound(_skullSound);
-}
-
-void Game::doShot() {
- playSound(_shotSound);
-}
-
-// Timer
-static void cursorTimerCallback(void *refCon) {
- Game *game = static_cast<Game *>(refCon);
- game->runCursorTimer();
-}
-
-void Game::setupCursorTimer() {
- g_system->getTimerManager()->installTimerProc(&cursorTimerCallback, 1000000 / 50, (void *)this, "cursortimer");
-}
-
-void Game::removeCursorTimer() {
- g_system->getTimerManager()->removeTimerProc(&cursorTimerCallback);
-}
-
-void Game::runCursorTimer() {
- _thisGameTimer += 2;
- if (_whichGun == 9) {
- if (_emptyCount > 0) {
- _emptyCount--;
- } else {
- _whichGun = 0;
- }
- } else {
- if (_shotFired) {
- _whichGun++;
- if (_whichGun > 5) {
- _whichGun = 0;
- _shotFired = false;
- }
- } else {
- if (_inHolster > 0) {
- _inHolster--;
- if (_inHolster == 0 && _whichGun == 7) {
- _whichGun = 6;
- }
- }
- }
- }
-}
-
// Script functions: Zone
void Game::zoneGlobalHit(Common::Point *point) {
// do nothing
@@ -409,32 +309,6 @@ void Game::rectHitDoNothing(Rect *rect) {
// do nothing
}
-void Game::rectNewScene(Rect *rect) {
- _score += rect->_score;
- if (!rect->_scene.empty()) {
- _curScene = rect->_scene;
- }
-}
-
-void Game::rectEasy(Rect *rect) {
- doDiffSound(1);
- _difficulty = 1;
-}
-
-void Game::rectAverage(Rect *rect) {
- doDiffSound(2);
- _difficulty = 2;
-}
-
-void Game::rectHard(Rect *rect) {
- doDiffSound(3);
- _difficulty = 3;
-}
-
-void Game::rectExit(Rect *rect) {
- shutdown();
-}
-
// Script functions: Scene PreOps
void Game::scenePsoDrawRct(Scene *scene) {
}
@@ -519,13 +393,6 @@ void Game::sceneSmDonothing(Scene *scene) {
// do nothing
}
-// Script functions: ScnScr
-void Game::sceneDefaultScore(Scene *scene) {
- if (scene->_scnscrParam > 0) {
- _score += scene->_scnscrParam;
- }
-}
-
// Script functions: ScnNxtFrm
void Game::sceneNxtfrm(Scene *scene) {
}
@@ -534,7 +401,7 @@ void Game::sceneNxtfrm(Scene *scene) {
void Game::debug_drawZoneRects() {
if (_debug_drawRects || debugChannelSet(1, Alg::kAlgDebugGraphics)) {
if (_inMenu) {
- for (auto rect : _submenzone->_rects) {
+ for (auto rect : _subMenuZone->_rects) {
_screen->drawLine(rect->left, rect->top, rect->right, rect->top, 1);
_screen->drawLine(rect->left, rect->top, rect->left, rect->bottom, 1);
_screen->drawLine(rect->right, rect->bottom, rect->right, rect->top, 1);
diff --git a/engines/alg/game.h b/engines/alg/game.h
index 783c770e111..25667054121 100644
--- a/engines/alg/game.h
+++ b/engines/alg/game.h
@@ -41,7 +41,6 @@ public:
virtual void init();
virtual Common::Error run();
bool debug_dumpLibFile();
- void runCursorTimer();
bool _debug_drawRects = false;
bool _debug_godMode = false;
bool _debug_unlimitedAmmo = false;
@@ -63,19 +62,10 @@ protected:
Common::Array<Graphics::Surface *> *_gun;
Common::Array<Graphics::Surface *> *_numbers;
- Audio::SeekableAudioStream *_saveSound = nullptr;
- Audio::SeekableAudioStream *_loadSound = nullptr;
- Audio::SeekableAudioStream *_easySound = nullptr;
- Audio::SeekableAudioStream *_avgSound = nullptr;
- Audio::SeekableAudioStream *_hardSound = nullptr;
- Audio::SeekableAudioStream *_skullSound = nullptr;
- Audio::SeekableAudioStream *_shotSound = nullptr;
- Audio::SeekableAudioStream *_emptySound = nullptr;
-
Audio::SoundHandle _sfxAudioHandle;
- Zone *_menuzone;
- Zone *_submenzone;
+ Zone *_menuZone;
+ Zone *_subMenuZone;
bool _leftDown = false;
bool _rightDown = false;
@@ -95,33 +85,17 @@ protected:
bool fired(Common::Point *point);
Rect *checkZone(Zone *zone, Common::Point *point);
Zone *checkZonesV1(Scene *scene, Rect *&hitRect, Common::Point *point);
- Zone *checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point);
+ Zone *checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point, uint8 difficulty);
uint32 getFrame(Scene *scene);
void adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty);
int8 skipToNewScene(Scene *scene);
- uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
void debug_drawZoneRects();
- // Sounds
- void doDiffSound(uint8 difficulty);
- void doSaveSound();
- void doLoadSound();
- void doSkullSound();
- void doShot();
-
- // Timer
- void setupCursorTimer();
- void removeCursorTimer();
-
// Script functions: Zone
void zoneGlobalHit(Common::Point *point);
// Script functions: RectHit
void rectHitDoNothing(Rect *rect);
void rectNewScene(Rect *rect);
- void rectExit(Rect *rect);
- void rectEasy(Rect *rect);
- void rectAverage(Rect *rect);
- void rectHard(Rect *rect);
// Script functions: Scene PreOps
void scenePsoDrawRct(Scene *scene);
void scenePsoPause(Scene *scene);
@@ -139,45 +113,23 @@ protected:
void sceneDefaultNxtscn(Scene *scene);
// Script functions: ShowMsg
void sceneSmDonothing(Scene *scene);
- // Script functions: ScnScr
- void sceneDefaultScore(Scene *scene);
// Script functions: ScnNxtFrm
void sceneNxtfrm(Scene *scene);
bool _buttonDown = false;
- uint8 _difficulty = 1;
- uint8 _emptyCount = 0;
- bool _fired = false;
+ bool _fired = 0;
uint32 _currentFrame;
bool _gameInProgress = false;
- uint32 _thisGameTimer = 0;
bool _hadPause = false;
- bool _holster = false;
bool _inMenu = false;
- uint8 _inHolster = 0;
- int8 _lives = 0;
- long int _minF;
- long int _maxF;
- uint8 _oldWhichGun = 0xFF;
- uint8 _oldDifficulty = 1;
- int8 _oldLives = 0;
- int32 _oldScore = -1;
- uint8 _oldShots = 0;
uint32 _pauseTime = 0;
bool _sceneSkipped = false;
- int32 _score = 0;
- bool _shotFired = false;
- uint16 _shots = 0;
uint32 _videoFrameSkip = 3;
uint32 _nextFrameTime = 0;
uint16 _videoPosX;
uint16 _videoPosY;
- uint8 _whichGun = 0;
Common::String _curScene;
- Common::String _subScene;
- Common::String _retScene;
- Common::String _lastScene;
Common::String _startScene;
};
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index c30f9c9f26f..e57f584523b 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -88,7 +88,12 @@ GameBountyHunter::~GameBountyHunter() {
item->free();
delete item;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _skullSound;
+ delete _shotSound;
delete _shotgunSound;
+ delete _emptySound;
}
void GameBountyHunter::init() {
@@ -109,23 +114,23 @@ void GameBountyHunter::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0, 0, 0x78, 0x3C, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0xC8, 0, 0x0140, 0x3C, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0xC8, 0x3C, 0x0140, 0x78, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0, 0x3C, 0x78, 0x78, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0, 0x78, 0x78, 0xB4, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xC8, 0x78, 0x0140, 0xB4, nullptr, 0, "TOGGLEPLAYERS", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0, 0, 0x78, 0x3C, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0xC8, 0, 0x0140, 0x3C, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0xC8, 0x3C, 0x0140, 0x78, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0, 0x3C, 0x78, 0x78, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0, 0x78, 0x78, 0xB4, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xC8, 0x78, 0x0140, 0xB4, nullptr, 0, "TOGGLEPLAYERS", "0");
_shotSound = loadSoundFile("blow.8b");
+ _shotgunSound = loadSoundFile("shotgun.8b");
_emptySound = loadSoundFile("empty.8b");
_saveSound = loadSoundFile("saved.8b");
_loadSound = loadSoundFile("loaded.8b");
_skullSound = loadSoundFile("skull.8b");
- _shotgunSound = loadSoundFile("shotgun.8b");
_gun = AlgGraphics::loadScreenCoordAniImage("bh_gun.ani", _palette);
_shotgun = AlgGraphics::loadScreenCoordAniImage("bh_buck.ani", _palette);
@@ -390,7 +395,7 @@ Common::Error GameBountyHunter::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else {
@@ -399,9 +404,9 @@ Common::Error GameBountyHunter::run() {
_playerShots[_player]--;
}
displayShotFiredImage(&firedCoords);
- doShot();
+ playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -487,7 +492,7 @@ void GameBountyHunter::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -703,6 +708,30 @@ uint16 GameBountyHunter::beginLevel(uint8 levelNumber) {
return sceneNum;
}
+uint16 GameBountyHunter::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
+ if (max == 1) {
+ return 0;
+ }
+ // reset mask if full
+ uint16 fullMask = 0xFFFF >> (16 - max);
+ if (*mask == fullMask) {
+ *mask = 0;
+ }
+ uint16 randomNum = 0;
+ // find an unused random number
+ while (1) {
+ randomNum = _rnd->getRandomNumber(max - 1);
+ // check if bit is already used
+ uint16 bit = 1 << randomNum;
+ if (!((*mask & bit) || randomNum == exclude)) {
+ // set the bit in mask
+ *mask |= bit;
+ break;
+ }
+ }
+ return randomNum;
+}
+
uint16 GameBountyHunter::pickRandomScene(uint16 *sceneList, uint8 max) {
if (max == 0) {
return 0;
@@ -802,19 +831,26 @@ void GameBountyHunter::doShotgunSound() {
}
// Script functions: RectHit
+void GameBountyHunter::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameBountyHunter::rectShotMenu(Rect *rect) {
doMenu();
}
void GameBountyHunter::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameBountyHunter::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
setNextScene(_restartScene);
_restartScene = 0;
@@ -852,6 +888,22 @@ void GameBountyHunter::rectStart(Rect *rect) {
newGame();
}
+void GameBountyHunter::rectEasy(Rect *rect) {
+ _difficulty = 1;
+}
+
+void GameBountyHunter::rectAverage(Rect *rect) {
+ _difficulty = 2;
+}
+
+void GameBountyHunter::rectHard(Rect *rect) {
+ _difficulty = 3;
+}
+
+void GameBountyHunter::rectExit(Rect *rect) {
+ shutdown();
+}
+
void GameBountyHunter::rectTogglePlayers(Rect *rect) {
if (_numPlayers == 1) {
_numPlayers = 2;
@@ -867,7 +919,7 @@ void GameBountyHunter::rectTogglePlayers(Rect *rect) {
AlgGraphics::drawImage(_screen, _textMenuIcon, 0x0C, 0xBF);
AlgGraphics::drawImage(_screen, _textBlackBarIcon, 0x50, 0xBE);
}
- doSkullSound();
+ playSound(_skullSound);
_screen->copyRectToSurface(_background->getBasePtr(_videoPosX, _videoPosY), _background->pitch, _videoPosX, _videoPosY, _videoDecoder->getWidth(), _videoDecoder->getHeight());
}
@@ -1313,6 +1365,13 @@ void GameBountyHunter::sceneDefaultWepdwn(Scene *scene) {
}
}
+// Script functions: ScnScr
+void GameBountyHunter::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameBountyHunter::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_bountyhunter.h b/engines/alg/logic/game_bountyhunter.h
index 98ecc7c2673..55d1ac769f1 100644
--- a/engines/alg/logic/game_bountyhunter.h
+++ b/engines/alg/logic/game_bountyhunter.h
@@ -91,7 +91,12 @@ private:
Common::Array<Graphics::Surface *> *_shotgun;
// sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
Audio::SeekableAudioStream *_shotgunSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
// constants
uint16 _randomHarry1[7] = {0x01B9, 0x01B7, 0x01B5, 0x01B3, 0x01AF, 0x01AD, 0};
@@ -128,6 +133,18 @@ private:
const uint16 _allPlayersDead = 0x108;
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _oldDifficulty = 1;
+ bool _holster = false;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+
uint16 _restartScene = 0;
uint8 _numPlayers = 1;
uint8 _player = 0;
@@ -142,6 +159,7 @@ private:
uint8 _levelDoneMask = 0;
uint8 _numSubLevelsDone = 0;
+ // TODO remove?
// uint16 _usedScenes = 0;
// int16 _lastPick = -1;
// int16 _initted = 0;
@@ -175,6 +193,8 @@ private:
uint8 _unk_2ADA6 = 0;
+ Common::String _subScene;
+
// base functions
void newGame();
void doMenu();
@@ -195,6 +215,7 @@ private:
void iconShotgun();
void iconReset();
uint16 beginLevel(uint8 levelNumber);
+ uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint16 *sceneList, uint8 max);
uint16 pickGunfightScene();
uint16 pickInnocentScene();
@@ -204,11 +225,16 @@ private:
void doShotgunSound();
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectTogglePlayers(Rect *rect);
void rectHitIconJug(Rect *rect);
void rectHitIconLantern(Rect *rect);
@@ -270,6 +296,9 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerBountyHunter : public GUI::Debugger {
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index d77abace7e8..800d1b90f36 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -60,6 +60,11 @@ GameCrimePatrol::~GameCrimePatrol() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _skullSound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameCrimePatrol::init() {
@@ -82,18 +87,18 @@ void GameCrimePatrol::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x1C, 0x11, 0x5D, 0x20, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x1C, 0x31, 0x5D, 0x40, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0x1C, 0x51, 0x5D, 0x60, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0x1C, 0x71, 0x5D, 0x80, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0x1C, 0x91, 0x5D, 0xA0, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xDD, 0x3C, 0x010A, 0x4B, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0xDD, 0x5C, 0x010A, 0x6B, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0xDD, 0x7C, 0x010A, 0x8B, nullptr, 0, "RECTHARD", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x1C, 0x11, 0x5D, 0x20, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x1C, 0x31, 0x5D, 0x40, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0x1C, 0x51, 0x5D, 0x60, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0x1C, 0x71, 0x5D, 0x80, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0x1C, 0x91, 0x5D, 0xA0, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xDD, 0x3C, 0x010A, 0x4B, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0xDD, 0x5C, 0x010A, 0x6B, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0xDD, 0x7C, 0x010A, 0x8B, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("blow.8b");
_emptySound = loadSoundFile("empty.8b");
@@ -339,7 +344,7 @@ Common::Error GameCrimePatrol::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -347,9 +352,9 @@ Common::Error GameCrimePatrol::run() {
_shots--;
}
displayShotFiredImage(&firedCoords);
- doShot();
+ playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -441,7 +446,7 @@ void GameCrimePatrol::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -648,6 +653,30 @@ uint16 GameCrimePatrol::sceneToNumber(Scene *scene) {
return atoi(scene->_name.substr(5).c_str());
}
+uint16 GameCrimePatrol::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
+ if (max == 1) {
+ return 0;
+ }
+ // reset mask if full
+ uint16 fullMask = 0xFFFF >> (16 - max);
+ if (*mask == fullMask) {
+ *mask = 0;
+ }
+ uint16 randomNum = 0;
+ // find an unused random number
+ while (1) {
+ randomNum = _rnd->getRandomNumber(max - 1);
+ // check if bit is already used
+ uint16 bit = 1 << randomNum;
+ if (!((*mask & bit) || randomNum == exclude)) {
+ // set the bit in mask
+ *mask |= bit;
+ break;
+ }
+ }
+ return randomNum;
+}
+
uint16 GameCrimePatrol::pickRandomScene(uint8 index, uint8 max) {
if (max != 0) {
_randomMax = max;
@@ -726,19 +755,26 @@ void GameCrimePatrol::sceneIsoGotToGeneric(uint8 index, uint16 sceneId) {
}
// Script functions: RectHit
+void GameCrimePatrol::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameCrimePatrol::rectShotMenu(Rect *rect) {
doMenu();
}
void GameCrimePatrol::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameCrimePatrol::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -767,6 +803,22 @@ void GameCrimePatrol::rectStart(Rect *rect) {
newGame();
}
+void GameCrimePatrol::rectEasy(Rect *rect) {
+ _difficulty = 1;
+}
+
+void GameCrimePatrol::rectAverage(Rect *rect) {
+ _difficulty = 2;
+}
+
+void GameCrimePatrol::rectHard(Rect *rect) {
+ _difficulty = 3;
+}
+
+void GameCrimePatrol::rectExit(Rect *rect) {
+ shutdown();
+}
+
void GameCrimePatrol::rectTargetPractice(Rect *rect) {
uint16 nextScene = 0;
Scene *scene = _sceneInfo->findScene(_curScene);
@@ -1281,6 +1333,13 @@ void GameCrimePatrol::sceneDefaultWepdwn(Scene *scene) {
_shots = 10;
}
+// Script functions: ScnScr
+void GameCrimePatrol::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameCrimePatrol::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_crimepatrol.h b/engines/alg/logic/game_crimepatrol.h
index 373a2d821d0..bdf1aaadae7 100644
--- a/engines/alg/logic/game_crimepatrol.h
+++ b/engines/alg/logic/game_crimepatrol.h
@@ -81,6 +81,13 @@ private:
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
const int16 _scenesLevel0[2] = {0x0191, 0};
const int16 _scenesLevel1[3] = {0x27, 0x01B7, 0};
@@ -133,6 +140,18 @@ private:
const int16 _practiceTargetBottom[5] = {0x3D, 0x79, 0x7B, 0xA1, 0xA1};
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _oldDifficulty = 1;
+ bool _holster = false;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+
uint16 _gotTo[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int8 _stage = 0;
int8 _oldStage = -1;
@@ -166,6 +185,7 @@ private:
void displayShotFiredImage(Common::Point *point);
void enableVideoFadeIn();
uint16 sceneToNumber(Scene *scene);
+ uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint8 index, uint8 max);
uint16 pickDeathScene();
void sceneNxtscnGeneric(uint8 index);
@@ -173,11 +193,16 @@ private:
void sceneIsoGotToGeneric(uint8 index, uint16 sceneId);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectTargetPractice(Rect *rect);
void rectSelectTargetPractice(Rect *rect);
void rectSelectGangFight(Rect *rect);
@@ -261,7 +286,11 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
void debugDrawPracticeRects();
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerCrimePatrol : public GUI::Debugger {
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index 15b45ef7bfa..eccc18345f6 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -60,6 +60,11 @@ GameDrugWars::~GameDrugWars() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _skullSound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameDrugWars::init() {
@@ -82,18 +87,18 @@ void GameDrugWars::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x1C, 0x13, 0x5D, 0x22, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x1C, 0x33, 0x5D, 0x42, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0x1C, 0x53, 0x5D, 0x62, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0x1C, 0x73, 0x5D, 0x82, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0x1C, 0x93, 0x5D, 0xA2, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xDD, 0x34, 0x10A, 0x43, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0xDD, 0x55, 0x10A, 0x64, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0xDD, 0x75, 0x10A, 0x84, nullptr, 0, "RECTHARD", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x1C, 0x13, 0x5D, 0x22, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x1C, 0x33, 0x5D, 0x42, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0x1C, 0x53, 0x5D, 0x62, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0x1C, 0x73, 0x5D, 0x82, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0x1C, 0x93, 0x5D, 0xA2, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xDD, 0x34, 0x10A, 0x43, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0xDD, 0x55, 0x10A, 0x64, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0xDD, 0x75, 0x10A, 0x84, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("blow.8b");
_emptySound = loadSoundFile("empty.8b");
@@ -283,7 +288,7 @@ Common::Error GameDrugWars::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -291,9 +296,9 @@ Common::Error GameDrugWars::run() {
_shots--;
}
displayShotFiredImage(&firedCoords);
- doShot();
+ playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -384,7 +389,7 @@ void GameDrugWars::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -600,6 +605,30 @@ uint16 GameDrugWars::sceneToNumber(Scene *scene) {
return atoi(scene->_name.substr(5).c_str());
}
+uint16 GameDrugWars::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
+ if (max == 1) {
+ return 0;
+ }
+ // reset mask if full
+ uint16 fullMask = 0xFFFF >> (16 - max);
+ if (*mask == fullMask) {
+ *mask = 0;
+ }
+ uint16 randomNum = 0;
+ // find an unused random number
+ while (1) {
+ randomNum = _rnd->getRandomNumber(max - 1);
+ // check if bit is already used
+ uint16 bit = 1 << randomNum;
+ if (!((*mask & bit) || randomNum == exclude)) {
+ // set the bit in mask
+ *mask |= bit;
+ break;
+ }
+ }
+ return randomNum;
+}
+
uint16 GameDrugWars::pickRandomScene(uint8 index, uint8 max) {
if (_randomScenes[index] == nullptr) {
error("GameDrugWars::pickRandomScene(): called with illegal index: %d", index);
@@ -678,19 +707,26 @@ void GameDrugWars::rectSelectGeneric(uint8 index) {
}
// Script functions: RectHit
+void GameDrugWars::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameDrugWars::rectShotMenu(Rect *rect) {
doMenu();
}
void GameDrugWars::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameDrugWars::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -720,6 +756,22 @@ void GameDrugWars::rectStart(Rect *rect) {
newGame();
}
+void GameDrugWars::rectEasy(Rect *rect) {
+ _difficulty = 1;
+}
+
+void GameDrugWars::rectAverage(Rect *rect) {
+ _difficulty = 2;
+}
+
+void GameDrugWars::rectHard(Rect *rect) {
+ _difficulty = 3;
+}
+
+void GameDrugWars::rectExit(Rect *rect) {
+ shutdown();
+}
+
void GameDrugWars::rectSelectTargetPractice(Rect *rect) {
rectSelectGeneric(0);
_gotTo[0] = 0;
@@ -978,6 +1030,13 @@ void GameDrugWars::sceneDefaultWepdwn(Scene *scene) {
_shots = 10;
}
+// Script functions: ScnScr
+void GameDrugWars::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameDrugWars::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_drugwars.h b/engines/alg/logic/game_drugwars.h
index 32abe178780..74c821644b5 100644
--- a/engines/alg/logic/game_drugwars.h
+++ b/engines/alg/logic/game_drugwars.h
@@ -81,6 +81,13 @@ private:
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
const int16 _randomScenes0[7] = {0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0};
const int16 _randomScenes1[6] = {0x37, 0x39, 0x3B, 0x3D, 0x3F, 0};
@@ -111,6 +118,18 @@ private:
const uint16 _scenarioStartScenes[14] = {0x27, 0x36, 0x4A, 0x57, 0x9D, 0x8B, 0x74, 0xD8, 0xBF, 0xB8, 0x0160, 0x010A, 0x0137, 0x017F};
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _oldDifficulty = 1;
+ bool _holster = false;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+
uint8 _continues = 0;
uint16 _gotTo[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int8 _gotToIndex = 0;
@@ -145,17 +164,23 @@ private:
void displayShotFiredImage(Common::Point *point);
void enableVideoFadeIn();
uint16 sceneToNumber(Scene *scene);
+ uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint8 index, uint8 max);
uint16 pickDeathScene();
void sceneNxtscnGeneric(uint8 index);
void rectSelectGeneric(uint8 index);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectSelectTargetPractice(Rect *rect);
void rectSelectBar(Rect *rect);
void rectSelectCarChase(Rect *rect);
@@ -188,6 +213,9 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerDrugWars : public GUI::Debugger {
diff --git a/engines/alg/logic/game_johnnyrock.cpp b/engines/alg/logic/game_johnnyrock.cpp
index 7f909e749fa..ae50f81853b 100644
--- a/engines/alg/logic/game_johnnyrock.cpp
+++ b/engines/alg/logic/game_johnnyrock.cpp
@@ -23,6 +23,7 @@
#include "common/rect.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/timer.h"
#include "graphics/cursorman.h"
@@ -48,6 +49,11 @@ GameJohnnyRock::~GameJohnnyRock() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _moneySound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameJohnnyRock::init() {
@@ -70,24 +76,24 @@ void GameJohnnyRock::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xBB, 0x3C, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xBB, 0x3C, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x10, 0x0F, 0x78, 0x34, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x10, 0x8E, 0x8A, 0xAF, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0x10, 0x3A, 0x6A, 0x5C, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0x10, 0x64, 0x84, 0x99, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0xD2, 0x8D, 0x12F, 0xB0, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xD0, 0x35, 0x123, 0x51, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0xD2, 0x50, 0x125, 0x6B, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0xD2, 0x6D, 0x122, 0x86, nullptr, 0, "RECTHARD", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x10, 0x0F, 0x78, 0x34, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x10, 0x8E, 0x8A, 0xAF, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0x10, 0x3A, 0x6A, 0x5C, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0x10, 0x64, 0x84, 0x99, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0xD2, 0x8D, 0x12F, 0xB0, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xD0, 0x35, 0x123, 0x51, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0xD2, 0x50, 0x125, 0x6B, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0xD2, 0x6D, 0x122, 0x86, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("blow.8b");
_emptySound = loadSoundFile("empty.8b");
_saveSound = loadSoundFile("saved.8b");
_loadSound = loadSoundFile("loaded.8b");
- _skullSound = loadSoundFile("money.8b");
+ _moneySound = loadSoundFile("money.8b");
_gun = AlgGraphics::loadScreenCoordAniImage("gun.ani", _palette);
_numbers = AlgGraphics::loadAniImage("numbers.ani", _palette);
@@ -334,7 +340,7 @@ Common::Error GameJohnnyRock::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -513,7 +519,7 @@ void GameJohnnyRock::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -791,7 +797,7 @@ bool GameJohnnyRock::loadState() {
}
void GameJohnnyRock::doMoneySound() {
- playSound(_skullSound);
+ playSound(_moneySound);
}
// Misc game functions
@@ -843,7 +849,7 @@ void GameJohnnyRock::defaultBullethole(Common::Point *point) {
AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
updateCursor();
_shotFired = true;
- doShot();
+ playSound(_shotSound);
}
}
@@ -896,24 +902,72 @@ void GameJohnnyRock::showCombination() {
_curScene = numToScene(offset + 0xDB);
}
+// Timer
+static void cursorTimerCallback(void *refCon) {
+ GameJohnnyRock *game = static_cast<GameJohnnyRock *>(refCon);
+ game->runCursorTimer();
+}
+
+void GameJohnnyRock::setupCursorTimer() {
+ g_system->getTimerManager()->installTimerProc(&cursorTimerCallback, 1000000 / 50, (void *)this, "cursortimer");
+}
+
+void GameJohnnyRock::removeCursorTimer() {
+ g_system->getTimerManager()->removeTimerProc(&cursorTimerCallback);
+}
+
+void GameJohnnyRock::runCursorTimer() {
+ _thisGameTimer += 2;
+ if (_whichGun == 9) {
+ if (_emptyCount > 0) {
+ _emptyCount--;
+ } else {
+ _whichGun = 0;
+ }
+ } else {
+ if (_shotFired) {
+ _whichGun++;
+ if (_whichGun > 5) {
+ _whichGun = 0;
+ _shotFired = false;
+ }
+ } else {
+ if (_inHolster > 0) {
+ _inHolster--;
+ if (_inHolster == 0 && _whichGun == 7) {
+ _whichGun = 6;
+ }
+ }
+ }
+ }
+}
+
// Script functions: Zone
void GameJohnnyRock::zoneBullethole(Common::Point *point) {
defaultBullethole(point);
}
+// Script functions: RectHit
+void GameJohnnyRock::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameJohnnyRock::rectShotMenu(Rect *rect) {
doMenu();
}
void GameJohnnyRock::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameJohnnyRock::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -951,6 +1005,22 @@ void GameJohnnyRock::rectStart(Rect *rect) {
updateStat();
}
+void GameJohnnyRock::rectEasy(Rect *rect) {
+ _difficulty = 1;
+}
+
+void GameJohnnyRock::rectAverage(Rect *rect) {
+ _difficulty = 2;
+}
+
+void GameJohnnyRock::rectHard(Rect *rect) {
+ _difficulty = 3;
+}
+
+void GameJohnnyRock::rectExit(Rect *rect) {
+ shutdown();
+}
+
void GameJohnnyRock::rectKillInnocent(Rect *rect) {
_inOffice = sceneToNum(_curScene);
if (_inOffice >= 0x13) {
@@ -1725,6 +1795,13 @@ void GameJohnnyRock::sceneDefaultWepdwn(Scene *scene) {
updateMouse();
}
+// Script functions: ScnScr
+void GameJohnnyRock::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameJohnnyRock::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_johnnyrock.h b/engines/alg/logic/game_johnnyrock.h
index 83423d462a8..d426e00d941 100644
--- a/engines/alg/logic/game_johnnyrock.h
+++ b/engines/alg/logic/game_johnnyrock.h
@@ -56,6 +56,7 @@ public:
~GameJohnnyRock() override;
Common::Error run() override;
void debugWarpTo(int val);
+ void runCursorTimer();
private:
void init() override;
@@ -83,6 +84,13 @@ private:
Graphics::Surface *_levelIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_moneySound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
const int16 _randomRooftop[6] = {2, -4, 0x104, 0x1E, 0x100, 0x102};
const int16 _randomTheater[9] = {5, -5, 0x111, 0x1E, 0x107, 0x109, 0x10B, 0x10D, 0x10F};
@@ -104,6 +112,21 @@ private:
const uint16 _diffPos[4][2] = {{0, 0}, {0xCD, 0x35}, {0xD2, 0x53}, {0xD2, 0x6E}};
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _emptyCount = 0;
+ bool _holster = false;
+ uint8 _oldDifficulty = 1;
+ uint8 _inHolster = 0;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ bool _shotFired = false;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+
uint16 _totalDies = 0;
int16 _gameMoney = 0;
int16 _oldGameMoney = 0;
@@ -153,6 +176,11 @@ private:
uint8 _mgunCnt = 0;
uint32 _machGunTimer = 0;
+ Common::String _retScene;
+ Common::String _subScene;
+
+ uint32 _thisGameTimer = 0;
+
// base functions
bool fired(Common::Point *point);
void newGame();
@@ -182,15 +210,24 @@ private:
void shotCombination(uint8 combination, bool combinationB);
void shotLuckyNumber(uint8 number);
+ // Timer
+ void setupCursorTimer();
+ void removeCursorTimer();
+
// Script functions: Zone
void zoneBullethole(Common::Point *point);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectKillInnocent(Rect *rect);
void rectSelectCasino(Rect *rect);
void rectSelectPoolhall(Rect *rect);
@@ -268,6 +305,9 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerJohnnyRock : public GUI::Debugger {
diff --git a/engines/alg/logic/game_maddog.cpp b/engines/alg/logic/game_maddog.cpp
index 8f1f7be009d..db17bf58b4c 100644
--- a/engines/alg/logic/game_maddog.cpp
+++ b/engines/alg/logic/game_maddog.cpp
@@ -23,6 +23,7 @@
#include "common/rect.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/timer.h"
#include "graphics/cursorman.h"
@@ -68,6 +69,14 @@ GameMaddog::~GameMaddog() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _easySound;
+ delete _avgSound;
+ delete _hardSound;
+ delete _skullSound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameMaddog::init() {
@@ -85,21 +94,21 @@ void GameMaddog::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAC, 0x3D, 0xBF, nullptr, 0, "SHOTMENU", "0");
- _menuzone->addRect(0x00, 0xA6, 0x013F, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_bott
- _menuzone->addRect(0x00, 0x00, 0x3B, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_left
-
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x8A, 0x3B, 0xC2, 0x48, nullptr, 0, "STARTBOT", "0");
- _submenzone->addRect(0x8A, 0x4E, 0xC2, 0x59, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x8A, 0x60, 0xC2, 0x6B, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0xE3, 0x3B, 0x011B, 0x48, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0xE3, 0x4E, 0x011B, 0x59, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0xE3, 0x60, 0x011B, 0x6B, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0x42, 0x34, 0x5C, 0x4E, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0x42, 0x53, 0x5C, 0x70, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0x42, 0x72, 0x62, 0x8A, nullptr, 0, "RECTHARD", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAC, 0x3D, 0xBF, nullptr, 0, "SHOTMENU", "0");
+ _menuZone->addRect(0x00, 0xA6, 0x013F, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_bott
+ _menuZone->addRect(0x00, 0x00, 0x3B, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_left
+
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x8A, 0x3B, 0xC2, 0x48, nullptr, 0, "STARTBOT", "0");
+ _subMenuZone->addRect(0x8A, 0x4E, 0xC2, 0x59, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x8A, 0x60, 0xC2, 0x6B, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0xE3, 0x3B, 0x011B, 0x48, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0xE3, 0x4E, 0x011B, 0x59, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0xE3, 0x60, 0x011B, 0x6B, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0x42, 0x34, 0x5C, 0x4E, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0x42, 0x53, 0x5C, 0x70, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0x42, 0x72, 0x62, 0x8A, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("blow.8b");
_emptySound = loadSoundFile("empty.8b");
@@ -352,7 +361,7 @@ Common::Error GameMaddog::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -471,7 +480,7 @@ void GameMaddog::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -686,7 +695,7 @@ void GameMaddog::defaultBullethole(Common::Point *point) {
AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
updateCursor();
_shotFired = true;
- doShot();
+ playSound(_shotSound);
}
}
@@ -845,6 +854,46 @@ Common::String GameMaddog::mapLeft() {
}
}
+// Timer
+static void cursorTimerCallback(void *refCon) {
+ GameMaddog *game = static_cast<GameMaddog *>(refCon);
+ game->runCursorTimer();
+}
+
+void GameMaddog::setupCursorTimer() {
+ g_system->getTimerManager()->installTimerProc(&cursorTimerCallback, 1000000 / 50, (void *)this, "cursortimer");
+}
+
+void GameMaddog::removeCursorTimer() {
+ g_system->getTimerManager()->removeTimerProc(&cursorTimerCallback);
+}
+
+void GameMaddog::runCursorTimer() {
+ _thisGameTimer += 2;
+ if (_whichGun == 9) {
+ if (_emptyCount > 0) {
+ _emptyCount--;
+ } else {
+ _whichGun = 0;
+ }
+ } else {
+ if (_shotFired) {
+ _whichGun++;
+ if (_whichGun > 5) {
+ _whichGun = 0;
+ _shotFired = false;
+ }
+ } else {
+ if (_inHolster > 0) {
+ _inHolster--;
+ if (_inHolster == 0 && _whichGun == 7) {
+ _whichGun = 6;
+ }
+ }
+ }
+ }
+}
+
// Script functions: Zone
void GameMaddog::zoneBullethole(Common::Point *point) {
defaultBullethole(point);
@@ -859,14 +908,21 @@ void GameMaddog::zoneSkullhole(Common::Point *point) {
_shotFired = true;
if (_hadSkull) {
- doShot();
+ playSound(_shotSound);
} else {
- doSkullSound();
+ playSound(_skullSound);
}
}
}
// Script functions: RectHit
+void GameMaddog::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameMaddog::rectHideFront(Rect *rect) {
if (_hideOutFront) {
_curScene = "scene214";
@@ -1047,13 +1103,13 @@ void GameMaddog::rectContinue(Rect *rect) {
void GameMaddog::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameMaddog::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -1079,6 +1135,25 @@ void GameMaddog::rectStartBottles(Rect *rect) {
updateStat();
}
+void GameMaddog::rectEasy(Rect *rect) {
+ playSound(_easySound);
+ _difficulty = 1;
+}
+
+void GameMaddog::rectAverage(Rect *rect) {
+ playSound(_avgSound);
+ _difficulty = 2;
+}
+
+void GameMaddog::rectHard(Rect *rect) {
+ playSound(_hardSound);
+ _difficulty = 3;
+}
+
+void GameMaddog::rectExit(Rect *rect) {
+ shutdown();
+}
+
// Script functions: Scene PreOps
void GameMaddog::scenePsoShootout(Scene *scene) {
sscanf(scene->_preopParam.c_str(), "#%ldto%ld", &_minF, &_maxF);
@@ -1482,6 +1557,13 @@ void GameMaddog::sceneDefaultWepdwn(Scene *scene) {
}
}
+// Script functions: ScnScr
+void GameMaddog::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameMaddog::debugWarpTo(int val) {
switch (val) {
diff --git a/engines/alg/logic/game_maddog.h b/engines/alg/logic/game_maddog.h
index f6290becef8..85a5e5fbb84 100644
--- a/engines/alg/logic/game_maddog.h
+++ b/engines/alg/logic/game_maddog.h
@@ -56,6 +56,7 @@ public:
~GameMaddog() override;
Common::Error run() override;
void debugWarpTo(int val);
+ void runCursorTimer();
private:
void init() override;
@@ -88,6 +89,16 @@ private:
Graphics::Surface *_knifeIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_easySound = nullptr;
+ Audio::SeekableAudioStream *_avgSound = nullptr;
+ Audio::SeekableAudioStream *_hardSound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
const uint16 _fight[3] = {208, 228, 243};
const uint16 _ambush[3] = {192, 193, 192};
@@ -99,6 +110,23 @@ private:
const uint16 _shotPos[12][2] = {{0x3, 0x5}, {0x0D, 0x5}, {0x17, 0x5}, {0x21, 0x5}, {0x3, 0x21}, {0x0D, 0x21}, {0x17, 0x21}, {0x21, 0x21}, {0x3, 0x3D}, {0x0D, 0x3D}, {0x17, 0x3D}, {0x21, 0x3D}};
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _emptyCount = 0;
+ bool _holster = false;
+ uint8 _oldDifficulty = 1;
+ uint8 _inHolster = 0;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ bool _shotFired = false;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+ long int _minF;
+ long int _maxF;
+
uint8 _badMen = 0;
uint8 _badMenBits = 0;
bool _bartenderAlive = false;
@@ -122,6 +150,11 @@ private:
uint8 _sheriffCnt = 0; // unused
uint8 _shootOutCnt = 0;
+ Common::String _retScene;
+ Common::String _subScene;
+
+ uint32 _thisGameTimer = 0;
+
// base functions
void newGame();
void resetParams();
@@ -148,17 +181,26 @@ private:
Common::String mapRight();
Common::String mapLeft();
+ // Timer
+ void setupCursorTimer();
+ void removeCursorTimer();
+
// Script functions: Zone
void zoneBullethole(Common::Point *point);
void zoneSkullhole(Common::Point *point);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectContinue(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectStart(Rect *rect);
void rectStartBottles(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectHideFront(Rect *rect);
void rectHideRear(Rect *rect);
void rectMenuSelect(Rect *rect);
@@ -220,6 +262,9 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerMaddog : public GUI::Debugger {
diff --git a/engines/alg/logic/game_maddog2.cpp b/engines/alg/logic/game_maddog2.cpp
index cd0ad42fc76..85738b8ad48 100644
--- a/engines/alg/logic/game_maddog2.cpp
+++ b/engines/alg/logic/game_maddog2.cpp
@@ -23,6 +23,7 @@
#include "common/rect.h"
#include "common/savefile.h"
#include "common/system.h"
+#include "common/timer.h"
#include "graphics/cursorman.h"
@@ -68,6 +69,11 @@ GameMaddog2::~GameMaddog2() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _skullSound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameMaddog2::init() {
@@ -90,19 +96,19 @@ void GameMaddog2::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _menuzone->addRect(0x08, 0xA9, 0x013C, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_bott
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone->addRect(0x08, 0xA9, 0x013C, 0xC7, nullptr, 0, "DEFAULT", "0"); // _mm_bott
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x2F, 0x16, 0x64, 0x2B, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x2F, 0xA0, 0x8D, 0xC7, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0x2F, 0x40, 0x64, 0x54, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0x2F, 0x6E, 0x7B, 0x86, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0xEC, 0x15, 0x0122, 0x2C, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xAD, 0x58, 0xF2, 0x70, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0xBC, 0x78, 0xF2, 0x93, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0xB8, 0x9D, 0xF2, 0xC7, nullptr, 0, "RECTHARD", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x2F, 0x16, 0x64, 0x2B, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x2F, 0xA0, 0x8D, 0xC7, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0x2F, 0x40, 0x64, 0x54, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0x2F, 0x6E, 0x7B, 0x86, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0xEC, 0x15, 0x0122, 0x2C, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xAD, 0x58, 0xF2, 0x70, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0xBC, 0x78, 0xF2, 0x93, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0xB8, 0x9D, 0xF2, 0xC7, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("blow.8b");
_emptySound = loadSoundFile("empty.8b");
@@ -363,7 +369,7 @@ Common::Error GameMaddog2::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -483,7 +489,7 @@ void GameMaddog2::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -755,7 +761,7 @@ void GameMaddog2::defaultBullethole(Common::Point *point) {
AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
updateCursor();
_shotFired = true;
- doShot();
+ playSound(_shotSound);
}
}
@@ -975,6 +981,46 @@ void GameMaddog2::playerWon() {
}
}
+// Timer
+static void cursorTimerCallback(void *refCon) {
+ GameMaddog2 *game = static_cast<GameMaddog2 *>(refCon);
+ game->runCursorTimer();
+}
+
+void GameMaddog2::setupCursorTimer() {
+ g_system->getTimerManager()->installTimerProc(&cursorTimerCallback, 1000000 / 50, (void *)this, "cursortimer");
+}
+
+void GameMaddog2::removeCursorTimer() {
+ g_system->getTimerManager()->removeTimerProc(&cursorTimerCallback);
+}
+
+void GameMaddog2::runCursorTimer() {
+ _thisGameTimer += 2;
+ if (_whichGun == 9) {
+ if (_emptyCount > 0) {
+ _emptyCount--;
+ } else {
+ _whichGun = 0;
+ }
+ } else {
+ if (_shotFired) {
+ _whichGun++;
+ if (_whichGun > 5) {
+ _whichGun = 0;
+ _shotFired = false;
+ }
+ } else {
+ if (_inHolster > 0) {
+ _inHolster--;
+ if (_inHolster == 0 && _whichGun == 7) {
+ _whichGun = 6;
+ }
+ }
+ }
+ }
+}
+
// Script functions: Zone
void GameMaddog2::zoneBullethole(Common::Point *point) {
defaultBullethole(point);
@@ -989,14 +1035,21 @@ void GameMaddog2::zoneSkullhole(Common::Point *point) {
_shotFired = true;
if (_hadSkull) {
- doShot();
+ playSound(_shotSound);
} else {
- doSkullSound();
+ playSound(_skullSound);
}
}
}
// Script functions: RectHit
+void GameMaddog2::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameMaddog2::rectSkull(Rect *rect) {
if (_hadSkull) {
return;
@@ -1154,13 +1207,13 @@ void GameMaddog2::rectShotmenu(Rect *rect) {
void GameMaddog2::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameMaddog2::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -1193,6 +1246,22 @@ void GameMaddog2::rectStart(Rect *rect) {
updateStat();
}
+void GameMaddog2::rectEasy(Rect *rect) {
+ _difficulty = 1;
+}
+
+void GameMaddog2::rectAverage(Rect *rect) {
+ _difficulty = 2;
+}
+
+void GameMaddog2::rectHard(Rect *rect) {
+ _difficulty = 3;
+}
+
+void GameMaddog2::rectExit(Rect *rect) {
+ shutdown();
+}
+
// Script functions: Scene PreOps
void GameMaddog2::scenePsoShootout(Scene *scene) {
sscanf(scene->_preopParam.c_str(), "#%ldto%ld", &_minF, &_maxF);
@@ -1378,7 +1447,7 @@ void GameMaddog2::sceneNxtscnShootSkull(Scene *scene) {
return;
}
_hadSkull = true;
- doSkullSound();
+ playSound(_skullSound);
_shots = 12;
_score += 1000;
updateStat();
@@ -1678,6 +1747,13 @@ void GameMaddog2::sceneDefaultWepdwn(Scene *scene) {
}
}
+// Script functions: ScnScr
+void GameMaddog2::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameMaddog2::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_maddog2.h b/engines/alg/logic/game_maddog2.h
index 7497c4007c2..2e05e5ea65e 100644
--- a/engines/alg/logic/game_maddog2.h
+++ b/engines/alg/logic/game_maddog2.h
@@ -56,6 +56,7 @@ public:
~GameMaddog2() override;
Common::Error run() override;
void debugWarpTo(int val);
+ void runCursorTimer();
private:
void init() override;
@@ -88,6 +89,13 @@ private:
Graphics::Surface *_knifeIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
const int16 _sbClue[3] = {0x67, 0x68, 0x69};
const int16 _bbClue[3] = {0x47, 0x49, 0x48};
@@ -109,6 +117,23 @@ private:
const uint16 _shotPos[12][2] = {{0x96, 0xBD}, {0x9A, 0xBD}, {0x9E, 0xBD}, {0x0A2, 0xBD}, {0x0A6, 0xBD}, {0x0AA, 0xBD}, {0x0AE, 0xBD}, {0x0B2, 0xBD}, {0x0B6, 0xBD}, {0x0BA, 0xBD}, {0x0BE, 0xBD}, {0x0C2, 0xBD}};
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _emptyCount = 0;
+ bool _holster = false;
+ uint8 _oldDifficulty = 1;
+ uint8 _inHolster = 0;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ bool _shotFired = false;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+ long int _minF;
+ long int _maxF;
+
uint16 _dieBits = 0;
uint16 _gotTo = 0;
uint16 _sbGotTo = 0;
@@ -132,6 +157,12 @@ private:
uint16 _shootOutCnt = 0;
uint16 _totalDies = 0;
+ Common::String _lastScene;
+ Common::String _retScene;
+ Common::String _subScene;
+
+ uint32 _thisGameTimer = 0;
+
// base functions
void newGame();
void resetParams();
@@ -161,16 +192,25 @@ private:
void genericNext();
void playerWon();
+ // Timer
+ void setupCursorTimer();
+ void removeCursorTimer();
+
// Script functions: Zone
void zoneBullethole(Common::Point *point);
void zoneSkullhole(Common::Point *point);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotmenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
+ void rectEasy(Rect *rect);
+ void rectAverage(Rect *rect);
+ void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectSkull(Rect *rect);
void rectKillInnocentMan(Rect *rect);
void rectKillInnocentWoman(Rect *rect);
@@ -248,6 +288,9 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
+
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerMaddog2 : public GUI::Debugger {
diff --git a/engines/alg/logic/game_spacepirates.cpp b/engines/alg/logic/game_spacepirates.cpp
index 7cc8e4b71e3..b29425c39f1 100644
--- a/engines/alg/logic/game_spacepirates.cpp
+++ b/engines/alg/logic/game_spacepirates.cpp
@@ -64,6 +64,12 @@ GameSpacePirates::~GameSpacePirates() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ delete _saveSound;
+ delete _loadSound;
+ delete _difficultySound;
+ delete _skullSound;
+ delete _shotSound;
+ delete _emptySound;
}
void GameSpacePirates::init() {
@@ -90,27 +96,25 @@ void GameSpacePirates::init() {
registerScriptFunctions();
verifyScriptFunctions();
- _menuzone = new Zone("MainMenu", "GLOBALHIT");
- _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone = new Zone("MainMenu", "GLOBALHIT");
+ _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
- _submenzone = new Zone("SubMenu", "GLOBALHIT");
- _submenzone->addRect(0x24, 0x16, 0x64, 0x26, nullptr, 0, "STARTMENU", "0");
- _submenzone->addRect(0x24, 0x36, 0x64, 0x46, nullptr, 0, "RECTLOAD", "0");
- _submenzone->addRect(0x24, 0x56, 0x64, 0x66, nullptr, 0, "RECTSAVE", "0");
- _submenzone->addRect(0x24, 0x76, 0x64, 0x86, nullptr, 0, "CONTMENU", "0");
- _submenzone->addRect(0x24, 0x96, 0x64, 0xA6, nullptr, 0, "EXITMENU", "0");
- _submenzone->addRect(0xD5, 0x3B, 0x0115, 0x4B, nullptr, 0, "RECTEASY", "0");
- _submenzone->addRect(0xD5, 0x63, 0x0115, 0x73, nullptr, 0, "RECTAVG", "0");
- _submenzone->addRect(0xD5, 0x90, 0x0115, 0xA0, nullptr, 0, "RECTHARD", "0");
+ _subMenuZone = new Zone("SubMenu", "GLOBALHIT");
+ _subMenuZone->addRect(0x24, 0x16, 0x64, 0x26, nullptr, 0, "STARTMENU", "0");
+ _subMenuZone->addRect(0x24, 0x36, 0x64, 0x46, nullptr, 0, "RECTLOAD", "0");
+ _subMenuZone->addRect(0x24, 0x56, 0x64, 0x66, nullptr, 0, "RECTSAVE", "0");
+ _subMenuZone->addRect(0x24, 0x76, 0x64, 0x86, nullptr, 0, "CONTMENU", "0");
+ _subMenuZone->addRect(0x24, 0x96, 0x64, 0xA6, nullptr, 0, "EXITMENU", "0");
+ _subMenuZone->addRect(0xD5, 0x3B, 0x0115, 0x4B, nullptr, 0, "RECTEASY", "0");
+ _subMenuZone->addRect(0xD5, 0x63, 0x0115, 0x73, nullptr, 0, "RECTAVG", "0");
+ _subMenuZone->addRect(0xD5, 0x90, 0x0115, 0xA0, nullptr, 0, "RECTHARD", "0");
_shotSound = loadSoundFile("phaser.8b");
_emptySound = loadSoundFile("emptygun.8b");
_saveSound = loadSoundFile("saved.8b");
_loadSound = loadSoundFile("loaded.8b");
_skullSound = loadSoundFile("error.8b");
- _easySound = loadSoundFile("difflev.8b");
- _avgSound = loadSoundFile("difflev.8b");
- _hardSound = loadSoundFile("difflev.8b");
+ _difficultySound = loadSoundFile("difflev.8b");
_gun = AlgGraphics::loadScreenCoordAniImage("gun.ani", _palette);
_difficultyIcon = (*_gun)[1];
@@ -356,7 +360,7 @@ Common::Error GameSpacePirates::run() {
Common::Point firedCoords;
if (fired(&firedCoords)) {
if (!_holster) {
- Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords);
+ Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else if (_shots > 0) {
@@ -364,9 +368,9 @@ Common::Error GameSpacePirates::run() {
_shots--;
}
displayShotFiredImage(&firedCoords);
- doShot();
+ playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -473,7 +477,7 @@ void GameSpacePirates::doMenu() {
while (_inMenu && !_vm->shouldQuit()) {
Common::Point firedCoords;
if (fired(&firedCoords)) {
- Rect *hitMenuRect = checkZone(_submenzone, &firedCoords);
+ Rect *hitMenuRect = checkZone(_subMenuZone, &firedCoords);
if (hitMenuRect != nullptr) {
callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect);
}
@@ -868,19 +872,26 @@ uint16 GameSpacePirates::pickCrystalScene(uint16 scene1, uint16 scene2, uint16 s
}
// Script functions: RectHit
+void GameSpacePirates::rectNewScene(Rect *rect) {
+ _score += rect->_score;
+ if (!rect->_scene.empty()) {
+ _curScene = rect->_scene;
+ }
+}
+
void GameSpacePirates::rectShotMenu(Rect *rect) {
doMenu();
}
void GameSpacePirates::rectSave(Rect *rect) {
if (saveState()) {
- doSaveSound();
+ playSound(_saveSound);
}
}
void GameSpacePirates::rectLoad(Rect *rect) {
if (loadState()) {
- doLoadSound();
+ playSound(_loadSound);
}
}
@@ -901,23 +912,27 @@ void GameSpacePirates::rectStart(Rect *rect) {
}
void GameSpacePirates::rectEasy(Rect *rect) {
- doDiffSound(1);
+ playSound(_difficultySound);
_difficulty = 0;
}
void GameSpacePirates::rectAverage(Rect *rect) {
- doDiffSound(2);
+ playSound(_difficultySound);
_difficulty = 1;
}
void GameSpacePirates::rectHard(Rect *rect) {
- doDiffSound(3);
+ playSound(_difficultySound);
_difficulty = 2;
}
+void GameSpacePirates::rectExit(Rect *rect) {
+ shutdown();
+}
+
void GameSpacePirates::rectDefault(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_score += rect->_score;
if (_score - _lastExtraLifeScore >= 1500 && _lives < 3) {
_lives++;
@@ -931,7 +946,7 @@ void GameSpacePirates::rectDefault(Rect *rect) {
void GameSpacePirates::rectKillInnocentPerson(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
if (!_debug_godMode) {
_lives--;
}
@@ -951,7 +966,7 @@ void GameSpacePirates::rectKillInnocentPerson(Rect *rect) {
void GameSpacePirates::rectContinueJunkRings(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_randomCount++;
uint16 picked = 0;
if (_randomCount >= 10) {
@@ -969,7 +984,7 @@ void GameSpacePirates::rectContinueJunkRings(Rect *rect) {
void GameSpacePirates::rectShotGrinReaper(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotGrinReaperCount++;
uint16 picked = 0;
if (_clue - 223 <= _shotGrinReaperCount) {
@@ -989,14 +1004,14 @@ void GameSpacePirates::rectShotGrinReaper(Rect *rect) {
void GameSpacePirates::rectShowMadDog(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_nextSceneFound = true;
_curScene = "scene354";
}
void GameSpacePirates::rectPottWorldShowCrystal(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
uint16 picked = 0;
if (_crystalState == 7) {
picked = 0xA6;
@@ -1009,21 +1024,21 @@ void GameSpacePirates::rectPottWorldShowCrystal(Rect *rect) {
void GameSpacePirates::rectShotLeft(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotDirection = 1;
_nextSceneFound = true;
}
void GameSpacePirates::rectShotRight(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotDirection = 2;
_nextSceneFound = true;
}
void GameSpacePirates::rectShotGold(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotColor = 3;
_nextSceneFound = true;
_curScene = rect->_scene;
@@ -1031,7 +1046,7 @@ void GameSpacePirates::rectShotGold(Rect *rect) {
void GameSpacePirates::rectShotSilver(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotColor = 4;
_nextSceneFound = true;
_curScene = rect->_scene;
@@ -1039,7 +1054,7 @@ void GameSpacePirates::rectShotSilver(Rect *rect) {
void GameSpacePirates::rectSelectedDuneWorld(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
if (!_worldDone[0]) {
_selectedAWorld = true;
_currentWorld = 0;
@@ -1053,7 +1068,7 @@ void GameSpacePirates::rectSelectedDuneWorld(Rect *rect) {
void GameSpacePirates::rectSelectedJunkWorld(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
if (!_worldDone[1]) {
_selectedAWorld = true;
_currentWorld = 1;
@@ -1067,7 +1082,7 @@ void GameSpacePirates::rectSelectedJunkWorld(Rect *rect) {
void GameSpacePirates::rectSelectedDragonsTeethWorld(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
if (!_worldDone[2]) {
_selectedAWorld = true;
_currentWorld = 2;
@@ -1081,7 +1096,7 @@ void GameSpacePirates::rectSelectedDragonsTeethWorld(Rect *rect) {
void GameSpacePirates::rectSelectedVolcanoWorld(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
if (!_worldDone[3]) {
_selectedAWorld = true;
_currentWorld = 3;
@@ -1098,7 +1113,7 @@ void GameSpacePirates::rectShotRedDeathGrip(Rect *rect) {
_nextSceneFound = true;
if (_clue == 0x36) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
picked = 0x5A;
} else {
rectKillInnocentPerson(rect);
@@ -1112,7 +1127,7 @@ void GameSpacePirates::rectShotBlueDeathGrip(Rect *rect) {
_nextSceneFound = true;
if (_clue == 0x38) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
picked = 0x5C;
} else {
rectKillInnocentPerson(rect);
@@ -1126,7 +1141,7 @@ void GameSpacePirates::rectShotGreenDeathGrip(Rect *rect) {
_nextSceneFound = true;
if (_clue == 0x37) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
picked = 0x5B;
} else {
rectKillInnocentPerson(rect);
@@ -1137,14 +1152,14 @@ void GameSpacePirates::rectShotGreenDeathGrip(Rect *rect) {
void GameSpacePirates::rectShotYellow(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotColor = 0x0F;
_nextSceneFound = true;
}
void GameSpacePirates::rectShotBlue(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_shotColor = 0x0E;
_nextSceneFound = true;
}
@@ -1152,7 +1167,7 @@ void GameSpacePirates::rectShotBlue(Rect *rect) {
void GameSpacePirates::rectShotRedCrystal(Rect *rect) {
uint16 picked = 0;
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
Scene *scene = _sceneInfo->findScene(_curScene);
if (_crystalsShot == 1) {
if (_pickedStartSplitter == 0x6A) {
@@ -1185,7 +1200,7 @@ void GameSpacePirates::rectShotRedCrystal(Rect *rect) {
void GameSpacePirates::rectShotBlueCrystal(Rect *rect) {
uint16 picked = 0;
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
Scene *scene = _sceneInfo->findScene(_curScene);
if (_crystalsShot == 1) {
if (_pickedStartSplitter == 0x6C) {
@@ -1218,7 +1233,7 @@ void GameSpacePirates::rectShotBlueCrystal(Rect *rect) {
void GameSpacePirates::rectShotGreenCrystal(Rect *rect) {
uint16 picked = 0;
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
Scene *scene = _sceneInfo->findScene(_curScene);
if (_crystalsShot == 1) {
if (_pickedStartSplitter == 0x6B) {
@@ -1250,7 +1265,7 @@ void GameSpacePirates::rectShotGreenCrystal(Rect *rect) {
void GameSpacePirates::rectShotBlackDragon1(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_score += rect->_score;
_nextSceneFound = true;
_curScene = "scene203";
@@ -1258,7 +1273,7 @@ void GameSpacePirates::rectShotBlackDragon1(Rect *rect) {
void GameSpacePirates::rectShotBlackDragon2(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_score += rect->_score;
_nextSceneFound = true;
_curScene = "scene204";
@@ -1266,7 +1281,7 @@ void GameSpacePirates::rectShotBlackDragon2(Rect *rect) {
void GameSpacePirates::rectShotBlackDragon3(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_score += rect->_score;
_nextSceneFound = true;
_curScene = "scene335";
@@ -1274,7 +1289,7 @@ void GameSpacePirates::rectShotBlackDragon3(Rect *rect) {
void GameSpacePirates::rectDoFlyingSkull(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_nextSceneFound = true;
Scene *scene = _sceneInfo->findScene(rect->_scene);
_sceneBeforeFlyingSkulls = sceneToNumber(scene);
@@ -1284,7 +1299,7 @@ void GameSpacePirates::rectDoFlyingSkull(Rect *rect) {
void GameSpacePirates::rectSkipScene(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
_nextSceneFound = true;
Scene *scene = _sceneInfo->findScene(_curScene);
_curScene = scene->_next;
@@ -1292,7 +1307,7 @@ void GameSpacePirates::rectSkipScene(Rect *rect) {
void GameSpacePirates::rectHitPirateShip(Rect *rect) {
displayShotFiredImage();
- doShot();
+ playSound(_shotSound);
displayMultipleShotLines();
_score += rect->_score;
_nextSceneFound = true;
@@ -1931,6 +1946,13 @@ void GameSpacePirates::sceneDefaultWepdwn(Scene *scene) {
_shots = 10;
}
+// Script functions: ScnScr
+void GameSpacePirates::sceneDefaultScore(Scene *scene) {
+ if (scene->_scnscrParam > 0) {
+ _score += scene->_scnscrParam;
+ }
+}
+
// Debug methods
void GameSpacePirates::debugWarpTo(int val) {
// TODO implement
diff --git a/engines/alg/logic/game_spacepirates.h b/engines/alg/logic/game_spacepirates.h
index 99fb188b433..dee1589a1e3 100644
--- a/engines/alg/logic/game_spacepirates.h
+++ b/engines/alg/logic/game_spacepirates.h
@@ -85,9 +85,29 @@ private:
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ // sounds
+ Audio::SeekableAudioStream *_saveSound = nullptr;
+ Audio::SeekableAudioStream *_loadSound = nullptr;
+ Audio::SeekableAudioStream *_difficultySound = nullptr;
+ Audio::SeekableAudioStream *_skullSound = nullptr;
+ Audio::SeekableAudioStream *_shotSound = nullptr;
+ Audio::SeekableAudioStream *_emptySound = nullptr;
+
// constants
// gamestate
+ uint8 _difficulty = 1;
+ uint8 _oldDifficulty = 1;
+ bool _holster = false;
+ int8 _lives = 0;
+ int8 _oldLives = 0;
+ int32 _score = 0;
+ int32 _oldScore = -1;
+ uint16 _shots = 0;
+ uint8 _oldShots = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+
bool _gameLoaded = false;
int8 _livesLoaded = 0;
uint16 _shotsLoaded = 0;
@@ -150,6 +170,7 @@ private:
uint16 pickCrystalScene(uint16 scene1, uint16 scene2, uint16 scene3);
// Script functions: RectHit
+ void rectNewScene(Rect *rect);
void rectShotMenu(Rect *rect);
void rectSave(Rect *rect);
void rectLoad(Rect *rect);
@@ -158,6 +179,7 @@ private:
void rectEasy(Rect *rect);
void rectAverage(Rect *rect);
void rectHard(Rect *rect);
+ void rectExit(Rect *rect);
void rectDefault(Rect *rect);
void rectKillInnocentPerson(Rect *rect);
void rectContinueJunkRings(Rect *rect);
@@ -249,8 +271,8 @@ private:
// Script functions: Scene WepDwn
void sceneDefaultWepdwn(Scene *scene);
- // Script functions: Scene ScnScr
- void sceneDefaultScnscr(Scene *scene);
+ // Script functions: ScnScr
+ void sceneDefaultScore(Scene *scene);
};
class DebuggerSpacePirates : public GUI::Debugger {
Commit: 7444a45dd9ad2dd02e3ca7ae694b2d4e64742ab9
https://github.com/scummvm/scummvm/commit/7444a45dd9ad2dd02e3ca7ae694b2d4e64742ab9
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: Bugfixes for Graphics, script bugfix for SP
Changed paths:
engines/alg/graphics.cpp
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_crimepatrol.h
engines/alg/logic/game_drugwars.cpp
engines/alg/logic/game_drugwars.h
engines/alg/logic/game_johnnyrock.cpp
engines/alg/logic/game_maddog.cpp
engines/alg/logic/game_maddog2.cpp
engines/alg/logic/game_spacepirates.cpp
engines/alg/logic/game_spacepirates.h
diff --git a/engines/alg/graphics.cpp b/engines/alg/graphics.cpp
index 2d98b10ff33..c6e0d6675c4 100644
--- a/engines/alg/graphics.cpp
+++ b/engines/alg/graphics.cpp
@@ -167,7 +167,7 @@ void AlgGraphics::drawImage(Graphics::Surface *dst, Graphics::Surface *src, int3
if (dstY + src->h > dst->h) {
subRect.bottom -= dstY + src->h - dst->h;
}
- dst->copyRectToSurfaceWithKey(src->getBasePtr(subRect.left, subRect.top), src->pitch, dstX, dstY, subRect.width(), subRect.height(), 0x00);
+ dst->copyRectToSurfaceWithKey(*src, dstX, dstY, subRect, 0x00);
}
void AlgGraphics::drawImageCentered(Graphics::Surface *dst, Graphics::Surface *src, int32 x, int32 y) {
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index e57f584523b..acf312d202f 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -679,9 +679,11 @@ void GameBountyHunter::setNextScene(uint16 sceneId) {
void GameBountyHunter::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
}
}
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index 800d1b90f36..e03e5a974a3 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -639,9 +639,11 @@ bool GameCrimePatrol::loadState() {
// misc game functions
void GameCrimePatrol::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
}
}
@@ -649,8 +651,8 @@ void GameCrimePatrol::enableVideoFadeIn() {
// TODO implement
}
-uint16 GameCrimePatrol::sceneToNumber(Scene *scene) {
- return atoi(scene->_name.substr(5).c_str());
+uint16 GameCrimePatrol::sceneToNumber(Common::String sceneName) {
+ return atoi(sceneName.substr(5).c_str());
}
uint16 GameCrimePatrol::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
@@ -822,7 +824,7 @@ void GameCrimePatrol::rectExit(Rect *rect) {
void GameCrimePatrol::rectTargetPractice(Rect *rect) {
uint16 nextScene = 0;
Scene *scene = _sceneInfo->findScene(_curScene);
- if (_levelScenes[0][0] == sceneToNumber(scene)) {
+ if (_levelScenes[0][0] == sceneToNumber(_curScene)) {
_practiceMask = 0x1F;
}
if (_practiceMask == 0) {
@@ -912,13 +914,13 @@ void GameCrimePatrol::rectKillInnocentMan(Rect *rect) {
// Script functions: Scene PreOps
void GameCrimePatrol::scenePsoWarehouseGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(2, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoGangFightGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(1, sceneId);
enableVideoFadeIn();
}
@@ -929,55 +931,55 @@ void GameCrimePatrol::scenePsoWestcoastSoundGotTo(Scene *scene) {
}
void GameCrimePatrol::scenePsoDrugDealGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(4, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoCarRingGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(5, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoBankGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(7, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoCrackHouseGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(9, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoMethLabGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(8, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoAirplaneGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(10, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoAirportGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(12, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoNukeTransportGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(11, sceneId);
enableVideoFadeIn();
}
void GameCrimePatrol::scenePsoPowerPlantGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
sceneIsoGotToGeneric(13, sceneId);
_finalStageScene = sceneId;
enableVideoFadeIn();
diff --git a/engines/alg/logic/game_crimepatrol.h b/engines/alg/logic/game_crimepatrol.h
index bdf1aaadae7..169d4b25866 100644
--- a/engines/alg/logic/game_crimepatrol.h
+++ b/engines/alg/logic/game_crimepatrol.h
@@ -184,7 +184,7 @@ private:
// misc game functions
void displayShotFiredImage(Common::Point *point);
void enableVideoFadeIn();
- uint16 sceneToNumber(Scene *scene);
+ uint16 sceneToNumber(Common::String sceneName);
uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint8 index, uint8 max);
uint16 pickDeathScene();
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index eccc18345f6..203eb5c7022 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -591,9 +591,11 @@ bool GameDrugWars::loadState() {
// misc game functions
void GameDrugWars::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
}
}
@@ -601,8 +603,8 @@ void GameDrugWars::enableVideoFadeIn() {
// TODO implement
}
-uint16 GameDrugWars::sceneToNumber(Scene *scene) {
- return atoi(scene->_name.substr(5).c_str());
+uint16 GameDrugWars::sceneToNumber(Common::String sceneName) {
+ return atoi(sceneName.substr(5).c_str());
}
uint16 GameDrugWars::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
@@ -830,10 +832,10 @@ void GameDrugWars::rectSelectVillage(Rect *rect) {
// Script functions: Scene PreOps
void GameDrugWars::scenePsoGotTo(Scene *scene) {
- uint16 sceneId = sceneToNumber(scene);
+ uint16 sceneId = sceneToNumber(scene->_name);
_gotTo[_gotToIndex] = sceneId;
if (_gotToIndex == 13) {
- _finalStageScene = sceneToNumber(scene);
+ _finalStageScene = sceneToNumber(scene->_name);
}
enableVideoFadeIn();
}
diff --git a/engines/alg/logic/game_drugwars.h b/engines/alg/logic/game_drugwars.h
index 74c821644b5..c7096f35c4d 100644
--- a/engines/alg/logic/game_drugwars.h
+++ b/engines/alg/logic/game_drugwars.h
@@ -163,7 +163,7 @@ private:
// misc game functions
void displayShotFiredImage(Common::Point *point);
void enableVideoFadeIn();
- uint16 sceneToNumber(Scene *scene);
+ uint16 sceneToNumber(Common::String sceneName);
uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint8 index, uint8 max);
uint16 pickDeathScene();
diff --git a/engines/alg/logic/game_johnnyrock.cpp b/engines/alg/logic/game_johnnyrock.cpp
index ae50f81853b..c3855c5a88e 100644
--- a/engines/alg/logic/game_johnnyrock.cpp
+++ b/engines/alg/logic/game_johnnyrock.cpp
@@ -844,9 +844,11 @@ uint16 GameJohnnyRock::sceneToNum(Common::String sceneName) {
void GameJohnnyRock::defaultBullethole(Common::Point *point) {
if (point->x >= 14 && point->x <= 306 && point->y >= 5 && point->y <= 169) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
updateCursor();
_shotFired = true;
playSound(_shotSound);
diff --git a/engines/alg/logic/game_maddog.cpp b/engines/alg/logic/game_maddog.cpp
index db17bf58b4c..218d4709e2e 100644
--- a/engines/alg/logic/game_maddog.cpp
+++ b/engines/alg/logic/game_maddog.cpp
@@ -690,9 +690,11 @@ bool GameMaddog::loadState() {
// misc game functions
void GameMaddog::defaultBullethole(Common::Point *point) {
if (point->x >= 59 && point->y <= 166) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
updateCursor();
_shotFired = true;
playSound(_shotSound);
@@ -901,9 +903,11 @@ void GameMaddog::zoneBullethole(Common::Point *point) {
void GameMaddog::zoneSkullhole(Common::Point *point) {
if (point->x >= 59 && point->y <= 166) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
updateCursor();
_shotFired = true;
diff --git a/engines/alg/logic/game_maddog2.cpp b/engines/alg/logic/game_maddog2.cpp
index 85738b8ad48..e41cc04dcf2 100644
--- a/engines/alg/logic/game_maddog2.cpp
+++ b/engines/alg/logic/game_maddog2.cpp
@@ -756,9 +756,11 @@ uint16 GameMaddog2::sceneToNum(Common::String sceneName) {
void GameMaddog2::defaultBullethole(Common::Point *point) {
if (point->x >= 14 && point->x <= 306 && point->y >= 5 && point->y <= 169) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
updateCursor();
_shotFired = true;
playSound(_shotSound);
@@ -1028,9 +1030,11 @@ void GameMaddog2::zoneBullethole(Common::Point *point) {
void GameMaddog2::zoneSkullhole(Common::Point *point) {
if (point->x >= 14 && point->x <= 306 && point->y >= 5 && point->y <= 169) {
- uint16 targetX = point->x - _videoPosX;
- uint16 targetY = point->y - _videoPosY;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX;
+ int32 targetY = point->y - _videoPosY;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
updateCursor();
_shotFired = true;
diff --git a/engines/alg/logic/game_spacepirates.cpp b/engines/alg/logic/game_spacepirates.cpp
index b29425c39f1..a66ea47ee18 100644
--- a/engines/alg/logic/game_spacepirates.cpp
+++ b/engines/alg/logic/game_spacepirates.cpp
@@ -95,6 +95,7 @@ void GameSpacePirates::init() {
registerScriptFunctions();
verifyScriptFunctions();
+ fixScriptBugs();
_menuZone = new Zone("MainMenu", "GLOBALHIT");
_menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
@@ -273,6 +274,19 @@ void GameSpacePirates::verifyScriptFunctions() {
}
}
+void GameSpacePirates::fixScriptBugs() {
+ auto scenes = _sceneInfo->getScenes();
+ for (auto scene : *scenes) {
+ for (auto zone : scene->_zones) {
+ for (auto rect : zone->_rects) {
+ if (rect->_scene == "scene363") {
+ rect->_scene = "scene11";
+ }
+ }
+ }
+ }
+}
+
SPScriptFunctionRect GameSpacePirates::getScriptFunctionRectHit(Common::String name) {
auto it = _rectHitFuncs.find(name);
if (it != _rectHitFuncs.end()) {
@@ -640,8 +654,7 @@ bool GameSpacePirates::weaponDown() {
}
bool GameSpacePirates::saveState() {
- Scene *scene = _sceneInfo->findScene(_curScene);
- uint16 sceneNum = sceneToNumber(scene);
+ uint16 sceneNum = sceneToNumber(_curScene);
if ((sceneNum < 0xAC || sceneNum > 0xB9) && sceneNum != 0x6F) {
Common::OutSaveFile *outSaveFile;
Common::String saveFileName = _vm->getSaveStateName(0);
@@ -761,9 +774,11 @@ void GameSpacePirates::displayShotFiredImage() {
void GameSpacePirates::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
- uint16 targetX = point->x - _videoPosX - 4;
- uint16 targetY = point->y - _videoPosY - 4;
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ int32 targetX = point->x - _videoPosX - 4;
+ int32 targetY = point->y - _videoPosY - 4;
+ if (targetX > 0 && targetY > 0) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ }
}
}
@@ -817,8 +832,8 @@ void GameSpacePirates::enableVideoFadeIn() {
// TODO implement
}
-uint16 GameSpacePirates::sceneToNumber(Scene *scene) {
- return atoi(scene->_name.substr(5).c_str());
+uint16 GameSpacePirates::sceneToNumber(Common::String sceneName) {
+ return atoi(sceneName.substr(5).c_str());
}
uint16 GameSpacePirates::randomUnusedScene(uint8 max) {
@@ -956,8 +971,7 @@ void GameSpacePirates::rectKillInnocentPerson(Rect *rect) {
_curScene = "scene185";
return;
}
- Scene *scene = _sceneInfo->findScene(rect->_scene);
- uint16 picked = sceneToNumber(scene);
+ uint16 picked = sceneToNumber(rect->_scene);
if (picked == 0) {
picked = randomNumberInRange(0xB7, 0xB9);
}
@@ -1291,8 +1305,7 @@ void GameSpacePirates::rectDoFlyingSkull(Rect *rect) {
displayShotFiredImage();
playSound(_shotSound);
_nextSceneFound = true;
- Scene *scene = _sceneInfo->findScene(rect->_scene);
- _sceneBeforeFlyingSkulls = sceneToNumber(scene);
+ _sceneBeforeFlyingSkulls = sceneToNumber(rect->_scene);
uint16 picked = randomNumberInRange(0x014A, 0x014D);
_curScene = Common::String::format("scene%d", picked);
}
@@ -1320,16 +1333,16 @@ void GameSpacePirates::scenePsoFadeInVideo(Scene *scene) {
void GameSpacePirates::scenePsoSetGotTo(Scene *scene) {
enableVideoFadeIn();
- _gotTo = sceneToNumber(scene);
+ _gotTo = sceneToNumber(scene->_name);
}
void GameSpacePirates::scenePsoSetGotToNoFadeIn(Scene *scene) {
- _gotTo = sceneToNumber(scene);
+ _gotTo = sceneToNumber(scene->_name);
}
void GameSpacePirates::scenePsoSetWorldGotTo(Scene *scene) {
enableVideoFadeIn();
- uint16 sceneNum = sceneToNumber(scene);
+ uint16 sceneNum = sceneToNumber(scene->_name);
_worldGotTo[_currentWorld] = sceneNum;
}
@@ -1339,8 +1352,8 @@ void GameSpacePirates::sceneIsoPickAWorld(Scene *scene) {
uint8 world = 3;
for (auto &rect : zone->_rects) {
if (_worldDone[world]) {
- uint16 centerX = rect->left + (rect->width() / 2);
- uint16 centerY = rect->top + (rect->height() / 2);
+ int32 centerX = rect->left + (rect->width() / 2);
+ int32 centerY = rect->top + (rect->height() / 2);
AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), (*_gun)[2], centerX - 16, centerY - 24);
}
world--;
@@ -1358,7 +1371,7 @@ void GameSpacePirates::sceneIsoPickAWorld(Scene *scene) {
}
void GameSpacePirates::sceneIsoSetWorldGotTo(Scene *scene) {
- uint16 sceneNum = sceneToNumber(scene);
+ uint16 sceneNum = sceneToNumber(scene->_name);
_worldGotTo[_currentWorld] = sceneNum;
}
@@ -1515,7 +1528,7 @@ void GameSpacePirates::sceneNxtscnAsteroidsDone(Scene *scene) {
}
void GameSpacePirates::sceneNxtscnDoFlyingSkulls(Scene *scene) {
- _sceneBeforeFlyingSkulls = sceneToNumber(scene);
+ _sceneBeforeFlyingSkulls = sceneToNumber(scene->_name);
uint16 picked = randomNumberInRange(0x014A, 0x014D);
_curScene = Common::String::format("scene%d", picked);
}
@@ -1761,7 +1774,7 @@ void GameSpacePirates::sceneNxtscnStartDragonsTeethPopup(Scene *scene) {
}
void GameSpacePirates::sceneNxtscnContinueDragonsTeethPopup(Scene *scene) {
- if (sceneToNumber(scene) != 0x14F) {
+ if (sceneToNumber(scene->_name) != 0x14F) {
_randomCount++;
}
if (((_difficulty * 9) + 9) > _randomCount) {
diff --git a/engines/alg/logic/game_spacepirates.h b/engines/alg/logic/game_spacepirates.h
index dee1589a1e3..9162ade7bfe 100644
--- a/engines/alg/logic/game_spacepirates.h
+++ b/engines/alg/logic/game_spacepirates.h
@@ -60,6 +60,7 @@ private:
void init() override;
void registerScriptFunctions();
void verifyScriptFunctions();
+ void fixScriptBugs();
SPScriptFunctionRect getScriptFunctionRectHit(Common::String name);
SPScriptFunctionScene getScriptFunctionScene(SceneFuncType type, Common::String name);
void callScriptFunctionRectHit(Common::String name, Rect *rect);
@@ -164,7 +165,7 @@ private:
void displayShotLine(uint16 startX, uint16 startY, uint16 endX, uint16 endY);
void displayMultipleShotLines();
void enableVideoFadeIn();
- uint16 sceneToNumber(Scene *scene);
+ uint16 sceneToNumber(Common::String sceneName);
uint16 randomUnusedScene(uint8 max);
uint16 randomNumberInRange(uint16 min, uint16 max);
uint16 pickCrystalScene(uint16 scene1, uint16 scene2, uint16 scene3);
Commit: 51a5e63af7f1e733ae15de637ed0e67688bae4b0
https://github.com/scummvm/scummvm/commit/51a5e63af7f1e733ae15de637ed0e67688bae4b0
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: Refactoring, improve support for LBH
Changed paths:
engines/alg/game.cpp
engines/alg/game.h
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_bountyhunter.h
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_crimepatrol.h
engines/alg/logic/game_drugwars.cpp
engines/alg/logic/game_drugwars.h
engines/alg/logic/game_johnnyrock.cpp
engines/alg/logic/game_johnnyrock.h
engines/alg/logic/game_maddog.cpp
engines/alg/logic/game_maddog.h
engines/alg/logic/game_maddog2.cpp
engines/alg/logic/game_maddog2.h
engines/alg/logic/game_spacepirates.cpp
engines/alg/logic/game_spacepirates.h
engines/alg/scene.cpp
engines/alg/scene.h
diff --git a/engines/alg/game.cpp b/engines/alg/game.cpp
index 8b9c0e4bbd4..0c3914d3f15 100644
--- a/engines/alg/game.cpp
+++ b/engines/alg/game.cpp
@@ -199,59 +199,6 @@ Rect *Game::checkZone(Zone *zone, Common::Point *point) {
return nullptr;
}
-// This is used by earlier games
-Zone *Game::checkZonesV1(Scene *scene, Rect *&hitRect, Common::Point *point) {
- for (auto &zone : scene->_zones) {
- uint32 startFrame = zone->_startFrame - _videoFrameSkip + 1;
- uint32 endFrame = zone->_endFrame + _videoFrameSkip - 1;
- if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
- hitRect = checkZone(zone, point);
- if (hitRect != nullptr) {
- return zone;
- }
- }
- }
- return nullptr;
-}
-
-// This is used by later games
-Zone *Game::checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point, uint8 difficulty) {
- for (auto &zone : scene->_zones) {
- uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((difficulty - 1) * _videoFrameSkip);
- uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((difficulty - 1) * _videoFrameSkip);
- if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
- hitRect = checkZone(zone, point);
- if (hitRect != nullptr) {
- return zone;
- }
- }
- }
- return nullptr;
-}
-
-// only used by earlier games
-void Game::adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty) {
- Common::Array<Scene *> *scenes = _sceneInfo->getScenes();
- for (const auto &scene : *scenes) {
- if (!(scene->_diff & 0x01)) {
- if (scene->_preop == "PAUSE" || scene->_preop == "PAUSFI" || scene->_preop == "PAUSPR") {
- scene->_dataParam1 = (scene->_dataParam1 * _pauseDiffScale[newDifficulty - 1]) / _pauseDiffScale[oldDifficulty - 1];
- }
- }
- for (const auto &zone : scene->_zones) {
- for (const auto &rect : zone->_rects) {
- if (!(scene->_diff & 0x02)) {
- int16 cx = (rect->left + rect->right) / 2;
- int16 cy = (rect->top + rect->bottom) / 2;
- int32 w = (rect->width() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
- int32 h = (rect->height() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
- rect->center(cx, cy, w, h);
- }
- }
- }
- }
-}
-
uint32 Game::getFrame(Scene *scene) {
if (_videoDecoder->getCurrentFrame() == 0) {
return scene->_startFrame;
@@ -411,10 +358,14 @@ void Game::debug_drawZoneRects() {
Scene *targetScene = _sceneInfo->findScene(_curScene);
for (auto &zone : targetScene->_zones) {
for (auto rect : zone->_rects) {
- _screen->drawLine(rect->left, rect->top, rect->right, rect->top, 1);
- _screen->drawLine(rect->left, rect->top, rect->left, rect->bottom, 1);
- _screen->drawLine(rect->right, rect->bottom, rect->right, rect->top, 1);
- _screen->drawLine(rect->right, rect->bottom, rect->left, rect->bottom, 1);
+ // only draw frames that appear soon or are current
+ if (_currentFrame + 30 >= zone->_startFrame && _currentFrame <= zone->_endFrame) {
+ Common::Rect interpolated = rect->getInterpolatedRect(zone->_startFrame, zone->_endFrame, _currentFrame);
+ _screen->drawLine(interpolated.left, interpolated.top, interpolated.right, interpolated.top, 1);
+ _screen->drawLine(interpolated.left, interpolated.top, interpolated.left, interpolated.bottom, 1);
+ _screen->drawLine(interpolated.right, interpolated.bottom, interpolated.right, interpolated.top, 1);
+ _screen->drawLine(interpolated.right, interpolated.bottom, interpolated.left, interpolated.bottom, 1);
+ }
}
}
}
diff --git a/engines/alg/game.h b/engines/alg/game.h
index 25667054121..b18346b8a6b 100644
--- a/engines/alg/game.h
+++ b/engines/alg/game.h
@@ -84,10 +84,7 @@ protected:
uint32 getMsTime();
bool fired(Common::Point *point);
Rect *checkZone(Zone *zone, Common::Point *point);
- Zone *checkZonesV1(Scene *scene, Rect *&hitRect, Common::Point *point);
- Zone *checkZonesV2(Scene *scene, Rect *&hitRect, Common::Point *point, uint8 difficulty);
uint32 getFrame(Scene *scene);
- void adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty);
int8 skipToNewScene(Scene *scene);
void debug_drawZoneRects();
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index acf312d202f..ecd56e19fa6 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -52,10 +52,6 @@ GameBountyHunter::~GameBountyHunter() {
_deadIcon->free();
delete _deadIcon;
}
- if (_diffIcon) {
- _diffIcon->free();
- delete _diffIcon;
- }
if (_bulletholeIcon) {
_bulletholeIcon->free();
delete _bulletholeIcon;
@@ -370,6 +366,7 @@ void GameBountyHunter::callScriptFunctionScene(SceneFuncType type, Common::Strin
Common::Error GameBountyHunter::run() {
init();
newGame();
+ _numPlayers = 1;
_curScene = _startScene;
Common::String oldscene;
while (!_vm->shouldQuit()) {
@@ -377,24 +374,21 @@ Common::Error GameBountyHunter::run() {
_fired = false;
Scene *scene = _sceneInfo->findScene(_curScene);
if (!loadScene(scene)) {
- error("GameBountyHunter::run(): Cannot find scene %s in libfile", scene->_name.c_str());
+ _curScene = scene->_next;
+ continue;
}
_sceneSkipped = false;
_paletteDirty = true;
_nextFrameTime = getMsTime() + 100;
+ _lastShotTime = getMsTime();
callScriptFunctionScene(PREOP, scene->_preop, scene);
_currentFrame = getFrame(scene);
while (_currentFrame <= scene->_endFrame && _curScene == oldscene && !_vm->shouldQuit()) {
updateMouse();
- callScriptFunctionScene(SHOWMSG, scene->_scnmsg, scene);
callScriptFunctionScene(INSOP, scene->_insop, scene);
- _holster = weaponDown();
- if (_holster) {
- callScriptFunctionScene(WEPDWN, scene->_wepdwn, scene);
- }
Common::Point firedCoords;
if (fired(&firedCoords)) {
- if (!_holster) {
+ if (_lastShotTime == 0) {
Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
@@ -402,24 +396,17 @@ Common::Error GameBountyHunter::run() {
if (_playerShots[_player] > 0) {
if (!_debug_unlimitedAmmo) {
_playerShots[_player]--;
+ _lastShotTime = getMsTime();
}
displayShotFiredImage(&firedCoords);
- playSound(_shotSound);
+ playSound(_shotSound); // TODO different sound for shotgun
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
- } else {
- int8 skip = skipToNewScene(scene);
- if (skip == -1) {
+ if (_curScene == oldscene) {
+ // skip to new scene
callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene);
- } else if (skip == 1) {
- if (scene->_dataParam4 > 0) {
- uint32 framesToSkip = (scene->_dataParam4 - _currentFrame) / _videoFrameSkip;
- _videoDecoder->skipNumberOfFrames(framesToSkip);
- } else {
- callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene);
- }
}
}
} else {
@@ -431,9 +418,20 @@ Common::Error GameBountyHunter::run() {
if (_curScene == oldscene) {
callScriptFunctionScene(NXTFRM, scene->_nxtfrm, scene);
}
- displayLivesLeft(0);
- displayScores(0);
- displayShotsLeft(0);
+ for (int i = 0; i < _numPlayers; i++) {
+ if (weaponDown()) {
+ sceneDefaultWepdwn(scene);
+ }
+ displayScores(i);
+ displayLivesLeft(i);
+ displayShotsLeft(i);
+ }
+ if (_lastShotTime != 0) {
+ if (getMsTime() - _lastShotTime > 185) {
+ _lastShotTime = 0;
+ }
+ }
+
moveMouse();
if (_pauseTime > 0) {
_videoDecoder->pauseAudio(true);
@@ -466,6 +464,9 @@ Common::Error GameBountyHunter::run() {
if (_curScene == oldscene) {
callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene);
}
+ if (_curScene == oldscene) {
+ _curScene = scene->_next;
+ }
if (_curScene == "") {
shutdown();
}
@@ -479,7 +480,6 @@ void GameBountyHunter::newGame() {
_playerGun[0] = _playerGun[1] = 1;
_playerScore[0] = _playerScore[1] = 0;
_currentSubLevelSceneId = 0x017B;
- _holster = false;
}
void GameBountyHunter::doMenu() {
@@ -562,51 +562,52 @@ void GameBountyHunter::moveMouse() {
}
void GameBountyHunter::displayLivesLeft(uint8 player) {
- if (_lives == _oldLives) {
+ if (_lives[player] == _oldLives[player]) {
return;
}
- int posY = 0x67;
+ int posX = player == 0 ? 0xD7 : 0x50;
for (int i = 0; i < 3; i++) {
- AlgGraphics::drawImage(_screen, _deadIcon, 0x12F, posY);
- posY += 0xE;
+ AlgGraphics::drawImage(_screen, _deadIcon, posX, 0xBE);
+ posX += 10;
}
- posY = 0x67;
- for (int i = 0; i < _lives; i++) {
- AlgGraphics::drawImage(_screen, _liveIcon, 0x12F, posY);
- posY += 0xE;
+ posX = player == 0 ? 0xD7 : 0x50;
+ for (int i = 0; i < _lives[player]; i++) {
+ AlgGraphics::drawImage(_screen, _liveIcon, posX, 0xBE);
+ posX += 10;
}
- _oldLives = _lives;
+ _oldLives[player] = _lives[player];
}
void GameBountyHunter::displayScores(uint8 player) {
- if (_score == _oldScore) {
+ if (_score[player] == _oldScore[player]) {
return;
}
- Common::String scoreString = Common::String::format("%05d", _score);
- int posX = 0x9B;
+ Common::String scoreString = Common::String::format("%05d", _score[player]);
+ int posX = player == 0 ? 0xA5 : 0x78;
for (int i = 0; i < 5; i++) {
uint8 digit = scoreString[i] - '0';
- AlgGraphics::drawImage(_screen, (*_numbers)[digit], posX, 0xBF);
- posX += 7;
+ uint8 digitOffset = player == 1 ? digit : digit + 10;
+ AlgGraphics::drawImage(_screen, (*_numbers)[digitOffset], posX, 0xBF);
+ posX += 5;
}
- _oldScore = _score;
+ _oldScore[player] = _score[player];
}
void GameBountyHunter::displayShotsLeft(uint8 player) {
- if (_shots == _oldShots) {
+ if (_shots[player] == _oldShots[player]) {
return;
}
- uint16 posX = 0xEE;
+ uint16 posX = player == 0 ? 0xF8 : 0x0C;
for (int i = 0; i < 10; i++) {
- AlgGraphics::drawImage(_screen, _emptyIcon, posX, 0xBE);
+ AlgGraphics::drawImage(_screen, _emptyIcon, posX, 0xBF);
posX += 5;
}
- posX = 0xEE;
- for (int i = 0; i < _shots; i++) {
- AlgGraphics::drawImage(_screen, _shotIcon, posX, 0xBE);
+ posX = player == 0 ? 0xF8 : 0x0C;
+ for (int i = 0; i < _shots[player]; i++) {
+ AlgGraphics::drawImage(_screen, _shotIcon, posX, 0xBF);
posX += 5;
}
- _oldShots = _shots;
+ _oldShots[player] = _shots[player];
}
bool GameBountyHunter::weaponDown() {
@@ -635,7 +636,7 @@ bool GameBountyHunter::saveState() {
outSaveFile->writeByte(_playerShots[i]);
outSaveFile->writeUint32LE(_playerScore[i]);
}
- outSaveFile->writeByte(_unk_2ADA6);
+ outSaveFile->writeByte(_difficulty);
outSaveFile->writeByte(_numPlayers);
outSaveFile->finalize();
delete outSaveFile;
@@ -664,7 +665,7 @@ bool GameBountyHunter::loadState() {
_playerShots[i] = inSaveFile->readByte();
_playerScore[i] = inSaveFile->readUint32LE();
}
- _unk_2ADA6 = inSaveFile->readByte();
+ _difficulty = inSaveFile->readByte();
_numPlayers = inSaveFile->readByte();
assert(_numPlayers <= 2);
delete inSaveFile;
@@ -672,6 +673,35 @@ bool GameBountyHunter::loadState() {
return true;
}
+Zone *GameBountyHunter::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ if (zone->_difficulty == _difficulty) {
+ uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1);
+ uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1);
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+Rect *GameBountyHunter::checkZone(Zone *zone, Common::Point *point) {
+ for (auto &rect : zone->_rects) {
+ Common::Rect interpolated = rect->getInterpolatedRect(zone->_startFrame, zone->_endFrame, _currentFrame);
+ if (point->x >= interpolated.left &&
+ point->x <= interpolated.right &&
+ point->y >= interpolated.top &&
+ point->y <= interpolated.bottom) {
+ return rect;
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
void GameBountyHunter::setNextScene(uint16 sceneId) {
_curScene = Common::String::format("%d", sceneId);
@@ -735,16 +765,15 @@ uint16 GameBountyHunter::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude
}
uint16 GameBountyHunter::pickRandomScene(uint16 *sceneList, uint8 max) {
- if (max == 0) {
- return 0;
- }
- _randomSceneList = sceneList;
- _randomMax = max;
- _randomMask = 0;
- _randomPicked = -1;
- _randomSceneCount = 0;
- while (_randomSceneList[_randomSceneCount] != 0) {
- _randomSceneCount++;
+ if (max != 0) {
+ _randomSceneList = sceneList;
+ _randomMax = max;
+ _randomMask = 0;
+ _randomPicked = -1;
+ _randomSceneCount = 0;
+ while (_randomSceneList[_randomSceneCount] != 0) {
+ _randomSceneCount++;
+ }
}
uint16 count = _randomMax--;
if (count > 0) {
@@ -799,7 +828,7 @@ uint16 GameBountyHunter::pickDeathScene() {
uint16 GameBountyHunter::timeForGunfight() {
uint16 picked = 0;
if (--_gunfightCount <= 0) {
- int index = (_unk_2ADA6 * 5) + (_numLevelsDone);
+ int index = (_difficulty * 5) + (_numLevelsDone);
_gunfightCount = _gunfightCountDown[index];
picked = pickGunfightScene();
}
@@ -834,7 +863,13 @@ void GameBountyHunter::doShotgunSound() {
// Script functions: RectHit
void GameBountyHunter::rectNewScene(Rect *rect) {
- _score += rect->_score;
+ uint32 _weightedScore = rect->_score + (_difficulty * 10);
+ _score[_player] += _weightedScore;
+ _pointsSinceLastBonus[_player] += _weightedScore;
+ if (_pointsSinceLastBonus[_player] > 5000) {
+ _pointsSinceLastBonus[_player] = 0;
+ _lives[_player]++;
+ }
if (!rect->_scene.empty()) {
_curScene = rect->_scene;
}
@@ -890,18 +925,6 @@ void GameBountyHunter::rectStart(Rect *rect) {
newGame();
}
-void GameBountyHunter::rectEasy(Rect *rect) {
- _difficulty = 1;
-}
-
-void GameBountyHunter::rectAverage(Rect *rect) {
- _difficulty = 2;
-}
-
-void GameBountyHunter::rectHard(Rect *rect) {
- _difficulty = 3;
-}
-
void GameBountyHunter::rectExit(Rect *rect) {
shutdown();
}
@@ -909,17 +932,17 @@ void GameBountyHunter::rectExit(Rect *rect) {
void GameBountyHunter::rectTogglePlayers(Rect *rect) {
if (_numPlayers == 1) {
_numPlayers = 2;
- AlgGraphics::drawImage(_screen, _playersIcon2, 0xCE, 0x95);
- AlgGraphics::drawImage(_screen, _textBlackBarIcon, 0x78, 0xBF);
- AlgGraphics::drawImage(_screen, _textBlackBarIcon, 0x0C, 0xBF);
+ AlgGraphics::drawImage(_background, _playersIcon2, 0xCE, 0x95);
+ AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x78, 0xBF);
+ AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x0C, 0xBF);
displayShotsLeft(1);
displayLivesLeft(1);
} else {
_numPlayers = 1;
- AlgGraphics::drawImage(_screen, _playersIcon1, 0xCE, 0x95);
- AlgGraphics::drawImage(_screen, _textScoreIcon, 0x78, 0xBF);
- AlgGraphics::drawImage(_screen, _textMenuIcon, 0x0C, 0xBF);
- AlgGraphics::drawImage(_screen, _textBlackBarIcon, 0x50, 0xBE);
+ AlgGraphics::drawImage(_background, _playersIcon1, 0xCE, 0x95);
+ AlgGraphics::drawImage(_background, _textScoreIcon, 0x78, 0xBF);
+ AlgGraphics::drawImage(_background, _textMenuIcon, 0x0C, 0xBF);
+ AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x50, 0xBE);
}
playSound(_skullSound);
_screen->copyRectToSurface(_background->getBasePtr(_videoPosX, _videoPosY), _background->pitch, _videoPosX, _videoPosY, _videoDecoder->getWidth(), _videoDecoder->getHeight());
@@ -1037,8 +1060,8 @@ void GameBountyHunter::scenePsoSetCurrentScene(Scene *scene) {
if (sceneId == 0) {
uint8 index = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
uint8 subLevel = _subLevelOrder[index];
- uint16 picked = (_currentLevel * 20) + (subLevel * 4);
- _currentSubLevelSceneId = 0x0D32 + picked;
+ uint16 picked = (_currentLevel * 10) + subLevel;
+ _currentSubLevelSceneId = _subLevelSceneIds[picked];
}
}
@@ -1152,16 +1175,12 @@ void GameBountyHunter::sceneNxtscnGotoLevelSelect(Scene *scene) {
}
void GameBountyHunter::sceneNxtscnContinueRandom(Scene *scene) {
- // TODO verify
- sceneNxtscnNextSubLevel(scene);
- /*
- uint16 picked = _PickRandomScene(0, 0);
+ uint16 picked = pickRandomScene(0, 0);
if (picked == 0) {
- _scene_nxtscn_next_sub_level(scene);
- return;
+ sceneNxtscnNextSubLevel(scene);
+ } else {
+ setNextScene(picked);
}
- _SetNextScene(picked);
- */
}
void GameBountyHunter::sceneNxtscnInitRandomHarry1(Scene *scene) {
@@ -1282,8 +1301,8 @@ void GameBountyHunter::sceneNxtscnWoundedMain(Scene *scene) {
void GameBountyHunter::sceneNxtscnEndLevel(Scene *scene) {
_levelDoneMask |= (2 << _currentLevel);
_numLevelsDone++;
- if (_numLevelsDone > 1 && _unk_2ADA6 < 2) {
- _unk_2ADA6++;
+ if (_numLevelsDone > 1 && _difficulty < 2) {
+ _difficulty++;
}
_numSubLevelsDone = 0;
_currentSubLevelSceneId = 0;
@@ -1370,11 +1389,39 @@ void GameBountyHunter::sceneDefaultWepdwn(Scene *scene) {
// Script functions: ScnScr
void GameBountyHunter::sceneDefaultScore(Scene *scene) {
if (scene->_scnscrParam > 0) {
- _score += scene->_scnscrParam;
+ _score[0] += scene->_scnscrParam;
}
+ // TODO verify, nothing for player2?
}
// Debug methods
+void GameBountyHunter::debug_drawZoneRects() {
+ if (_debug_drawRects || debugChannelSet(1, Alg::kAlgDebugGraphics)) {
+ if (_inMenu) {
+ for (auto rect : _subMenuZone->_rects) {
+ _screen->drawLine(rect->left, rect->top, rect->right, rect->top, 1);
+ _screen->drawLine(rect->left, rect->top, rect->left, rect->bottom, 1);
+ _screen->drawLine(rect->right, rect->bottom, rect->right, rect->top, 1);
+ _screen->drawLine(rect->right, rect->bottom, rect->left, rect->bottom, 1);
+ }
+ } else if (_curScene != "") {
+ Scene *targetScene = _sceneInfo->findScene(_curScene);
+ for (auto &zone : targetScene->_zones) {
+ for (auto rect : zone->_rects) {
+ // only draw frames that appear soon or are current and match current difficulty level
+ if (_currentFrame + 30 >= zone->_startFrame && _currentFrame <= zone->_endFrame && zone->_difficulty == _difficulty) {
+ Common::Rect interpolated = rect->getInterpolatedRect(zone->_startFrame, zone->_endFrame, _currentFrame);
+ _screen->drawLine(interpolated.left, interpolated.top, interpolated.right, interpolated.top, 1);
+ _screen->drawLine(interpolated.left, interpolated.top, interpolated.left, interpolated.bottom, 1);
+ _screen->drawLine(interpolated.right, interpolated.bottom, interpolated.right, interpolated.top, 1);
+ _screen->drawLine(interpolated.right, interpolated.bottom, interpolated.left, interpolated.bottom, 1);
+ }
+ }
+ }
+ }
+ }
+}
+
void GameBountyHunter::debugWarpTo(int val) {
// TODO implement
}
diff --git a/engines/alg/logic/game_bountyhunter.h b/engines/alg/logic/game_bountyhunter.h
index 55d1ac769f1..fe9f7680f44 100644
--- a/engines/alg/logic/game_bountyhunter.h
+++ b/engines/alg/logic/game_bountyhunter.h
@@ -80,7 +80,6 @@ private:
Graphics::Surface *_emptyIcon;
Graphics::Surface *_liveIcon;
Graphics::Surface *_deadIcon;
- Graphics::Surface *_diffIcon;
Graphics::Surface *_bulletholeIcon;
Graphics::Surface *_playersIcon1;
Graphics::Surface *_playersIcon2;
@@ -123,7 +122,7 @@ private:
const uint8 _mainLevelMasks[5] = {2, 4, 8, 0x10, 0x80};
const uint8 _gunfightCountDown[15] = {5, 4, 3, 3, 3, 4, 3, 3, 2, 1, 3, 2, 2, 2, 1};
- // const uint16 _firstSceneInScenario[4] = {4, 0x36, 0x36, 0x66};
+ // const uint16 _firstSceneInScenario[4] = {0x04, 0x36, 0x36, 0x66};
const uint16 _moneyScenes[4] = {0x017D, 0x013C, 0xC3, 0x69};
const uint16 _gunfightScenarios[18] = {0x0116, 0x0118, 0x011B, 0x011D, 0x011F, 0x0121, 0x0123, 0x0125, 0x0127,
0x0129, 0x012B, 0x012D, 0x012F, 0x0131, 0x0133, 0x0135, 0x0137, 0x0139};
@@ -133,17 +132,19 @@ private:
const uint16 _allPlayersDead = 0x108;
// gamestate
- uint8 _difficulty = 1;
+ uint8 _difficulty = 0;
uint8 _oldDifficulty = 1;
- bool _holster = false;
- int8 _lives = 0;
- int8 _oldLives = 0;
- int32 _score = 0;
- int32 _oldScore = -1;
- uint16 _shots = 0;
- uint8 _oldShots = 0;
+ uint32 _lastShotTime = 0;
+ int8 _lives[2] = {0, 0};
+ int8 _oldLives[2] = {0, 0};
+ int32 _score[2] = {0, 0};
+ int32 _oldScore[2] = {-1, -1};
+ uint32 _pointsSinceLastBonus[2] = {0, 0};
+ uint16 _shots[2] = {0, 0};
+ uint8 _oldShots[2] = {0, 0};
uint8 _whichGun = 0;
uint8 _oldWhichGun = 0xFF;
+ // TODO verify, whichGun for player2?
uint16 _restartScene = 0;
uint8 _numPlayers = 1;
@@ -191,8 +192,6 @@ private:
uint32 _firstDrawFrame = 0;
uint8 _count = 0;
- uint8 _unk_2ADA6 = 0;
-
Common::String _subScene;
// base functions
@@ -207,6 +206,8 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
+ Rect *checkZone(Zone *zone, Common::Point *point);
// misc game functions
void setNextScene(uint16 sceneId);
@@ -231,9 +232,6 @@ private:
void rectLoad(Rect *rect);
void rectContinue(Rect *rect);
void rectStart(Rect *rect);
- void rectEasy(Rect *rect);
- void rectAverage(Rect *rect);
- void rectHard(Rect *rect);
void rectExit(Rect *rect);
void rectTogglePlayers(Rect *rect);
void rectHitIconJug(Rect *rect);
@@ -299,6 +297,9 @@ private:
// Script functions: ScnScr
void sceneDefaultScore(Scene *scene);
+
+ // debug methods
+ void debug_drawZoneRects();
};
class DebuggerBountyHunter : public GUI::Debugger {
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index e03e5a974a3..514260b63e3 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -354,7 +354,7 @@ Common::Error GameCrimePatrol::run() {
displayShotFiredImage(&firedCoords);
playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -636,6 +636,20 @@ bool GameCrimePatrol::loadState() {
return true;
}
+Zone *GameCrimePatrol::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((_difficulty - 1) * _videoFrameSkip);
+ uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((_difficulty - 1) * _videoFrameSkip);
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
void GameCrimePatrol::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
diff --git a/engines/alg/logic/game_crimepatrol.h b/engines/alg/logic/game_crimepatrol.h
index 169d4b25866..ac4d587ecec 100644
--- a/engines/alg/logic/game_crimepatrol.h
+++ b/engines/alg/logic/game_crimepatrol.h
@@ -180,6 +180,7 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
void displayShotFiredImage(Common::Point *point);
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index 203eb5c7022..b60e3a8a861 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -298,7 +298,7 @@ Common::Error GameDrugWars::run() {
displayShotFiredImage(&firedCoords);
playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -588,6 +588,20 @@ bool GameDrugWars::loadState() {
return true;
}
+Zone *GameDrugWars::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((_difficulty - 1) * _videoFrameSkip);
+ uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((_difficulty - 1) * _videoFrameSkip);
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
void GameDrugWars::displayShotFiredImage(Common::Point *point) {
if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) {
diff --git a/engines/alg/logic/game_drugwars.h b/engines/alg/logic/game_drugwars.h
index c7096f35c4d..998bbc86238 100644
--- a/engines/alg/logic/game_drugwars.h
+++ b/engines/alg/logic/game_drugwars.h
@@ -159,6 +159,7 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
void displayShotFiredImage(Common::Point *point);
diff --git a/engines/alg/logic/game_johnnyrock.cpp b/engines/alg/logic/game_johnnyrock.cpp
index c3855c5a88e..6acdc8041d5 100644
--- a/engines/alg/logic/game_johnnyrock.cpp
+++ b/engines/alg/logic/game_johnnyrock.cpp
@@ -349,7 +349,7 @@ Common::Error GameJohnnyRock::run() {
}
updateStat();
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV1(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionZonePtrFb(hitSceneZone->_ptrfb, &firedCoords);
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
@@ -587,11 +587,36 @@ void GameJohnnyRock::changeDifficulty(uint8 newDifficulty) {
return;
}
showDifficulty(newDifficulty, true);
- Game::adjustDifficulty(newDifficulty, _oldDifficulty);
+ adjustDifficulty(newDifficulty, _oldDifficulty);
_oldDifficulty = newDifficulty;
_difficulty = newDifficulty;
}
+void GameJohnnyRock::adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty) {
+ Common::Array<Scene *> *scenes = _sceneInfo->getScenes();
+ for (size_t i = 0; i < scenes->size(); i++) {
+ Scene *scene = (*scenes)[i];
+ if (!(scene->_diff & 0x01)) {
+ if (scene->_preop == "PAUSE" || scene->_preop == "PAUSFI" || scene->_preop == "PAUSPR") {
+ scene->_dataParam1 = (scene->_dataParam1 * _pauseDiffScale[newDifficulty - 1]) / _pauseDiffScale[oldDifficulty - 1];
+ }
+ }
+ for (size_t j = 0; j < scene->_zones.size(); j++) {
+ Zone *zone = scene->_zones[j];
+ for (size_t k = 0; k < zone->_rects.size(); k++) {
+ Rect *rect = zone->_rects[k];
+ if (!(scene->_diff & 0x02)) {
+ int16 cx = (rect->left + rect->right) / 2;
+ int16 cy = (rect->top + rect->bottom) / 2;
+ int32 w = (rect->width() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ int32 h = (rect->height() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ rect->center(cx, cy, w, h);
+ }
+ }
+ }
+ }
+}
+
void GameJohnnyRock::updateCursor() {
_oldWhichGun = _whichGun;
}
@@ -800,6 +825,20 @@ void GameJohnnyRock::doMoneySound() {
playSound(_moneySound);
}
+Zone *GameJohnnyRock::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - _videoFrameSkip + 1;
+ uint32 endFrame = zone->_endFrame + _videoFrameSkip - 1;
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// Misc game functions
Common::String GameJohnnyRock::numToScene(int n) {
switch (n) {
diff --git a/engines/alg/logic/game_johnnyrock.h b/engines/alg/logic/game_johnnyrock.h
index d426e00d941..614af5a2af3 100644
--- a/engines/alg/logic/game_johnnyrock.h
+++ b/engines/alg/logic/game_johnnyrock.h
@@ -191,6 +191,7 @@ private:
void displayScore();
void showDifficulty(uint8 newDifficulty, bool updateCursor);
void changeDifficulty(uint8 newDifficulty);
+ void adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty);
void updateCursor();
void updateMouse();
void moveMouse();
@@ -198,6 +199,7 @@ private:
bool saveState();
bool loadState();
void doMoneySound();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
Common::String numToScene(int n);
diff --git a/engines/alg/logic/game_maddog.cpp b/engines/alg/logic/game_maddog.cpp
index 218d4709e2e..09121246305 100644
--- a/engines/alg/logic/game_maddog.cpp
+++ b/engines/alg/logic/game_maddog.cpp
@@ -370,7 +370,7 @@ Common::Error GameMaddog::run() {
}
updateStat();
hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV1(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionZonePtrFb(hitSceneZone->_ptrfb, &firedCoords);
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
@@ -533,7 +533,7 @@ void GameMaddog::changeDifficulty(uint8 newDifficulty) {
return;
}
showDifficulty(newDifficulty, true);
- Game::adjustDifficulty(newDifficulty, _oldDifficulty);
+ adjustDifficulty(newDifficulty, _oldDifficulty);
_oldDifficulty = newDifficulty;
_difficulty = newDifficulty;
}
@@ -547,6 +547,31 @@ void GameMaddog::showDifficulty(uint8 newDifficulty, bool cursor) {
}
}
+void GameMaddog::adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty) {
+ Common::Array<Scene *> *scenes = _sceneInfo->getScenes();
+ for (size_t i = 0; i < scenes->size(); i++) {
+ Scene *scene = (*scenes)[i];
+ if (!(scene->_diff & 0x01)) {
+ if (scene->_preop == "PAUSE" || scene->_preop == "PAUSFI" || scene->_preop == "PAUSPR") {
+ scene->_dataParam1 = (scene->_dataParam1 * _pauseDiffScale[newDifficulty - 1]) / _pauseDiffScale[oldDifficulty - 1];
+ }
+ }
+ for (size_t j = 0; j < scene->_zones.size(); j++) {
+ Zone *zone = scene->_zones[j];
+ for (size_t k = 0; k < zone->_rects.size(); k++) {
+ Rect *rect = zone->_rects[k];
+ if (!(scene->_diff & 0x02)) {
+ int16 cx = (rect->left + rect->right) / 2;
+ int16 cy = (rect->top + rect->bottom) / 2;
+ int32 w = (rect->width() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ int32 h = (rect->height() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ rect->center(cx, cy, w, h);
+ }
+ }
+ }
+ }
+}
+
void GameMaddog::updateCursor() {
updateMouse();
}
@@ -687,6 +712,20 @@ bool GameMaddog::loadState() {
return true;
}
+Zone *GameMaddog::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - _videoFrameSkip + 1;
+ uint32 endFrame = zone->_endFrame + _videoFrameSkip - 1;
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
void GameMaddog::defaultBullethole(Common::Point *point) {
if (point->x >= 59 && point->y <= 166) {
diff --git a/engines/alg/logic/game_maddog.h b/engines/alg/logic/game_maddog.h
index 85a5e5fbb84..6f9a1fe38e8 100644
--- a/engines/alg/logic/game_maddog.h
+++ b/engines/alg/logic/game_maddog.h
@@ -162,6 +162,7 @@ private:
void updateStat();
void changeDifficulty(uint8 newDifficulty);
void showDifficulty(uint8 newDifficulty, bool updateCursor);
+ void adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty);
void updateCursor();
void updateMouse();
void moveMouse();
@@ -169,6 +170,7 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
void defaultBullethole(Common::Point *point);
diff --git a/engines/alg/logic/game_maddog2.cpp b/engines/alg/logic/game_maddog2.cpp
index e41cc04dcf2..78c0cbf46fa 100644
--- a/engines/alg/logic/game_maddog2.cpp
+++ b/engines/alg/logic/game_maddog2.cpp
@@ -378,7 +378,7 @@ Common::Error GameMaddog2::run() {
}
updateStat();
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV1(scene, hitRect, &firedCoords);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionZonePtrFb(hitSceneZone->_ptrfb, &firedCoords);
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
@@ -542,7 +542,7 @@ void GameMaddog2::changeDifficulty(uint8 newDifficulty) {
return;
}
showDifficulty(newDifficulty, true);
- Game::adjustDifficulty(newDifficulty, _oldDifficulty);
+ adjustDifficulty(newDifficulty, _oldDifficulty);
_oldDifficulty = newDifficulty;
_difficulty = newDifficulty;
}
@@ -556,6 +556,31 @@ void GameMaddog2::showDifficulty(uint8 newDifficulty, bool cursor) {
}
}
+void GameMaddog2::adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty) {
+ Common::Array<Scene *> *scenes = _sceneInfo->getScenes();
+ for (size_t i = 0; i < scenes->size(); i++) {
+ Scene *scene = (*scenes)[i];
+ if (!(scene->_diff & 0x01)) {
+ if (scene->_preop == "PAUSE" || scene->_preop == "PAUSFI" || scene->_preop == "PAUSPR") {
+ scene->_dataParam1 = (scene->_dataParam1 * _pauseDiffScale[newDifficulty - 1]) / _pauseDiffScale[oldDifficulty - 1];
+ }
+ }
+ for (size_t j = 0; j < scene->_zones.size(); j++) {
+ Zone *zone = scene->_zones[j];
+ for (size_t k = 0; k < zone->_rects.size(); k++) {
+ Rect *rect = zone->_rects[k];
+ if (!(scene->_diff & 0x02)) {
+ int16 cx = (rect->left + rect->right) / 2;
+ int16 cy = (rect->top + rect->bottom) / 2;
+ int32 w = (rect->width() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ int32 h = (rect->height() * _rectDiffScale[newDifficulty - 1]) / _rectDiffScale[oldDifficulty - 1];
+ rect->center(cx, cy, w, h);
+ }
+ }
+ }
+ }
+}
+
void GameMaddog2::updateCursor() {
updateMouse();
}
@@ -705,6 +730,20 @@ bool GameMaddog2::loadState() {
return true;
}
+Zone *GameMaddog2::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - _videoFrameSkip + 1;
+ uint32 endFrame = zone->_endFrame + _videoFrameSkip - 1;
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
Common::String GameMaddog2::numToScene(int n) {
switch (n) {
diff --git a/engines/alg/logic/game_maddog2.h b/engines/alg/logic/game_maddog2.h
index 2e05e5ea65e..b099f5735c9 100644
--- a/engines/alg/logic/game_maddog2.h
+++ b/engines/alg/logic/game_maddog2.h
@@ -170,6 +170,7 @@ private:
void updateStat();
void changeDifficulty(uint8 newDifficulty);
void showDifficulty(uint8 newDifficulty, bool updateCursor);
+ void adjustDifficulty(uint8 newDifficulty, uint8 oldDifficulty);
void updateCursor();
void updateMouse();
void moveMouse();
@@ -177,6 +178,7 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
Common::String numToScene(int n);
diff --git a/engines/alg/logic/game_spacepirates.cpp b/engines/alg/logic/game_spacepirates.cpp
index a66ea47ee18..1e99f82c0d1 100644
--- a/engines/alg/logic/game_spacepirates.cpp
+++ b/engines/alg/logic/game_spacepirates.cpp
@@ -384,7 +384,7 @@ Common::Error GameSpacePirates::run() {
displayShotFiredImage(&firedCoords);
playSound(_shotSound);
Rect *hitRect = nullptr;
- Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords, _difficulty);
+ Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
} else {
@@ -763,6 +763,20 @@ bool GameSpacePirates::loadState() {
return true;
}
+Zone *GameSpacePirates::checkZones(Scene *scene, Rect *&hitRect, Common::Point *point) {
+ for (auto &zone : scene->_zones) {
+ uint32 startFrame = zone->_startFrame - (_videoFrameSkip + 1) + ((_difficulty - 1) * _videoFrameSkip);
+ uint32 endFrame = zone->_endFrame + (_videoFrameSkip - 1) - ((_difficulty - 1) * _videoFrameSkip);
+ if (_currentFrame >= startFrame && _currentFrame <= endFrame) {
+ hitRect = checkZone(zone, point);
+ if (hitRect != nullptr) {
+ return zone;
+ }
+ }
+ }
+ return nullptr;
+}
+
// misc game functions
void GameSpacePirates::playErrorSound() {
playSound(_skullSound);
diff --git a/engines/alg/logic/game_spacepirates.h b/engines/alg/logic/game_spacepirates.h
index 9162ade7bfe..bdd2a0625e1 100644
--- a/engines/alg/logic/game_spacepirates.h
+++ b/engines/alg/logic/game_spacepirates.h
@@ -157,6 +157,7 @@ private:
bool weaponDown();
bool saveState();
bool loadState();
+ Zone *checkZones(Scene *scene, Rect *&hitRect, Common::Point *point);
// misc game functions
void playErrorSound();
diff --git a/engines/alg/scene.cpp b/engines/alg/scene.cpp
index 562ef4f44fe..1bb677a4d25 100644
--- a/engines/alg/scene.cpp
+++ b/engines/alg/scene.cpp
@@ -248,37 +248,37 @@ void SceneInfo::parseZone(const Common::String &zoneName, uint32 startFrame, uin
void SceneInfo::addZonesToScenes() {
for (auto &scene : _scenes) {
if (!scene->_zonesStart.empty()) {
- Zone *zone = findZone(scene->_zonesStart);
- scene->_zones.push_back(zone);
- while (!zone->_next.empty()) {
- zone = findZone(zone->_next);
- if (zone == nullptr) {
- break;
+ Zone *zone = nullptr;
+ do {
+ Zone *found = findZone(scene->_zonesStart);
+ if (zone) {
+ zone = found->clone();
+ zone->_difficulty = 0;
+ scene->_zones.push_back(zone);
}
- scene->_zones.push_back(zone);
- }
+ } while (zone && !zone->_next.empty());
}
if (!scene->_zonesStart2.empty() && scene->_zonesStart2 != scene->_zonesStart) {
- Zone *zone = findZone(scene->_zonesStart2);
- scene->_zones.push_back(zone);
- while (!zone->_next.empty()) {
- zone = findZone(zone->_next);
- if (zone == nullptr) {
- break;
+ Zone *zone = nullptr;
+ do {
+ Zone *found = findZone(scene->_zonesStart);
+ if (zone) {
+ zone = found->clone();
+ zone->_difficulty = 1;
+ scene->_zones.push_back(zone);
}
- scene->_zones.push_back(zone);
- }
+ } while (zone && !zone->_next.empty());
}
if (!scene->_zonesStart3.empty() && scene->_zonesStart3 != scene->_zonesStart2) {
- Zone *zone = findZone(scene->_zonesStart3);
- scene->_zones.push_back(zone);
- while (!zone->_next.empty()) {
- zone = findZone(zone->_next);
- if (zone == nullptr) {
- break;
+ Zone *zone = nullptr;
+ do {
+ Zone *found = findZone(scene->_zonesStart);
+ if (zone) {
+ zone = found->clone();
+ zone->_difficulty = 2;
+ scene->_zones.push_back(zone);
}
- scene->_zones.push_back(zone);
- }
+ } while (zone && !zone->_next.empty());
}
}
}
@@ -355,6 +355,12 @@ Scene::Scene(const Common::String &name, uint32 startFrame, uint32 endFrame) {
_difficultyMod = 0;
}
+Scene::~Scene() {
+ for (auto zone : _zones) {
+ delete zone;
+ }
+}
+
Zone::Zone(const Common::String &name, const Common::String &ptrfb) {
_name = name;
_ptrfb = ptrfb;
@@ -372,7 +378,7 @@ Zone::~Zone() {
}
}
-void Zone::addRect(int16 left, int16 top, int16 right, int16 bottom, const Common::String &scene, uint32 score, const Common::String &rectHit, const Common::String &unknown) {
+void Zone::addRect(int16 left, int16 top, int16 right, int16 bottom, const Common::String scene, uint32 score, const Common::String rectHit, const Common::String unknown) {
Rect *rect = new Rect();
rect->left = left;
rect->top = top;
@@ -385,4 +391,47 @@ void Zone::addRect(int16 left, int16 top, int16 right, int16 bottom, const Commo
_rects.push_back(rect);
}
+Zone *Zone::clone() {
+ Zone *clone = new Zone(_name, _startFrame, _endFrame);
+ clone->_ptrfb = _ptrfb;
+ clone->_next = _next;
+ clone->_rects = _rects;
+ return clone;
+}
+
+void Rect::center(int16 cx, int16 cy, int16 w, int16 h) {
+ right = cx + (w / 2);
+ left = cx - (w / 2);
+ top = cy - (h / 2);
+ bottom = cy + (h / 2);
+}
+
+Common::Rect Rect::getInterpolatedRect(uint32 startFrame, uint32 endFrame, uint32 currentFrame) {
+ if (_isMoving && currentFrame >= startFrame && currentFrame < endFrame) {
+ Rect interpolated;
+ uint32 totalFrames = endFrame - startFrame;
+ uint32 relativeFrame = currentFrame - startFrame;
+ double percentage = relativeFrame * 100.0f / totalFrames;
+ interpolated.top = top + ((_dest.top - top) / 100.0f * percentage);
+ interpolated.left = left + ((_dest.left - left) / 100.0f * percentage);
+ interpolated.bottom = bottom + ((_dest.bottom - bottom) / 100.0f * percentage);
+ interpolated.right = right + ((_dest.right - right) / 100.0f * percentage);
+ return interpolated;
+ } else if (_isMoving && currentFrame >= endFrame) {
+ Rect finished;
+ finished.top = _dest.top;
+ finished.left = _dest.left;
+ finished.bottom = _dest.bottom;
+ finished.right = _dest.right;
+ return finished;
+ } else {
+ Rect normal;
+ normal.top = top;
+ normal.left = left;
+ normal.bottom = bottom;
+ normal.right = right;
+ return normal;
+ }
+}
+
} // End of namespace Alg
diff --git a/engines/alg/scene.h b/engines/alg/scene.h
index 270a1ed0b66..5ecc8a71cb7 100644
--- a/engines/alg/scene.h
+++ b/engines/alg/scene.h
@@ -77,12 +77,8 @@ public:
Common::String _unknown;
bool _isMoving = false;
Common::Rect _dest;
- void center(int16 cx, int16 cy, int16 w, int16 h) {
- right = cx + (w / 2);
- left = cx - (w / 2);
- top = cy - (h / 2);
- bottom = cy + (h / 2);
- }
+ void center(int16 cx, int16 cy, int16 w, int16 h);
+ Common::Rect getInterpolatedRect(uint32 startFrame, uint32 endFrame, uint32 currentFrame);
};
class Zone {
@@ -96,13 +92,15 @@ public:
Common::String _ptrfb;
Common::Array<Rect *> _rects;
Common::String _next;
- void addRect(int16 left, int16 top, int16 right, int16 bottom, const Common::String &scene, uint32 score, const Common::String &rectHit, const Common::String &unknown);
+ uint8 _difficulty;
+ void addRect(int16 left, int16 top, int16 right, int16 bottom, const Common::String scene, uint32 score, const Common::String rectHit, const Common::String unknown);
+ Zone *clone();
};
class Scene {
public:
Scene(const Common::String &name, uint32 startFrame, uint32 endFrame);
- ~Scene() = default;
+ ~Scene();
Common::String _name;
uint32 _startFrame;
uint32 _endFrame;
Commit: 3d5a98788bb165e6af0423469532bef9704152df
https://github.com/scummvm/scummvm/commit/3d5a98788bb165e6af0423469532bef9704152df
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: Refactoring, further implementations for LBH
Changed paths:
engines/alg/detection_tables.h
engines/alg/game.cpp
engines/alg/game.h
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_bountyhunter.h
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_crimepatrol.h
engines/alg/logic/game_drugwars.cpp
engines/alg/logic/game_drugwars.h
engines/alg/logic/game_johnnyrock.cpp
engines/alg/logic/game_johnnyrock.h
engines/alg/logic/game_maddog.cpp
engines/alg/logic/game_maddog.h
engines/alg/logic/game_maddog2.cpp
engines/alg/logic/game_maddog2.h
engines/alg/logic/game_spacepirates.cpp
engines/alg/logic/game_spacepirates.h
engines/alg/scene.cpp
engines/alg/scene.h
diff --git a/engines/alg/detection_tables.h b/engines/alg/detection_tables.h
index c2caad8ecd2..3b87c5b8c9d 100644
--- a/engines/alg/detection_tables.h
+++ b/engines/alg/detection_tables.h
@@ -95,7 +95,7 @@ static const AlgGameDescription gameDescriptions[] = {
AD_ENTRY1s("BHDS.LIB", "6fad52a6a72830ab3373cbe3e0a3a779", 281473503),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO0()
},
GType_LAST_BOUNTY_HUNTER,
@@ -108,7 +108,7 @@ static const AlgGameDescription gameDescriptions[] = {
AD_ENTRY1s("BHDEMO.LIB", "af5fbbd5e18d96225077eb6bf2cac680", 28368775),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE | ADGF_DEMO,
+ ADGF_DEMO,
GUIO1(GAMEOPTION_SINGLE_SPEED_VERSION)
},
GType_LAST_BOUNTY_HUNTER,
diff --git a/engines/alg/game.cpp b/engines/alg/game.cpp
index 0c3914d3f15..ac972311079 100644
--- a/engines/alg/game.cpp
+++ b/engines/alg/game.cpp
@@ -52,18 +52,6 @@ Game::~Game() {
_screen->free();
delete _screen;
}
- for (auto item : *_gun) {
- if (item) {
- item->free();
- delete item;
- }
- }
- for (auto item : *_numbers) {
- if (item) {
- item->free();
- delete item;
- }
- }
}
void Game::init() {
@@ -189,10 +177,7 @@ bool Game::fired(Common::Point *point) {
Rect *Game::checkZone(Zone *zone, Common::Point *point) {
for (auto &rect : zone->_rects) {
- if (point->x >= rect->left &&
- point->x <= rect->right &&
- point->y >= rect->top &&
- point->y <= rect->bottom) {
+ if (rect->contains(*point)) {
return rect;
}
}
diff --git a/engines/alg/game.h b/engines/alg/game.h
index b18346b8a6b..1069d314445 100644
--- a/engines/alg/game.h
+++ b/engines/alg/game.h
@@ -59,8 +59,6 @@ protected:
Graphics::Surface *_background;
Graphics::Surface *_screen;
- Common::Array<Graphics::Surface *> *_gun;
- Common::Array<Graphics::Surface *> *_numbers;
Audio::SoundHandle _sfxAudioHandle;
@@ -80,13 +78,13 @@ protected:
Audio::SeekableAudioStream *loadSoundFile(const Common::Path &path);
void playSound(Audio::SeekableAudioStream *stream);
bool loadScene(Scene *scene);
- void updateScreen();
+ virtual void updateScreen();
uint32 getMsTime();
bool fired(Common::Point *point);
Rect *checkZone(Zone *zone, Common::Point *point);
uint32 getFrame(Scene *scene);
int8 skipToNewScene(Scene *scene);
- void debug_drawZoneRects();
+ virtual void debug_drawZoneRects();
// Script functions: Zone
void zoneGlobalHit(Common::Point *point);
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index ecd56e19fa6..27238dcd268 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -24,6 +24,7 @@
#include "common/savefile.h"
#include "common/system.h"
+#include "graphics/paletteman.h"
#include "graphics/cursorman.h"
#include "alg/graphics.h"
@@ -44,6 +45,10 @@ GameBountyHunter::~GameBountyHunter() {
_emptyIcon->free();
delete _emptyIcon;
}
+ if (_shellIcon) {
+ _shellIcon->free();
+ delete _shellIcon;
+ }
if (_liveIcon) {
_liveIcon->free();
delete _liveIcon;
@@ -52,10 +57,6 @@ GameBountyHunter::~GameBountyHunter() {
_deadIcon->free();
delete _deadIcon;
}
- if (_bulletholeIcon) {
- _bulletholeIcon->free();
- delete _bulletholeIcon;
- }
if (_playersIcon1) {
_playersIcon1->free();
delete _playersIcon1;
@@ -76,11 +77,23 @@ GameBountyHunter::~GameBountyHunter() {
_textBlackBarIcon->free();
delete _textBlackBarIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
for (auto item : *_bagsIcons) {
item->free();
delete item;
}
- for (auto item : *_shotgun) {
+ for (auto item : *_bulletHoleIcon) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_shotgunHoleIcon) {
item->free();
delete item;
}
@@ -111,7 +124,7 @@ void GameBountyHunter::init() {
verifyScriptFunctions();
_menuZone = new Zone("MainMenu", "GLOBALHIT");
- _menuZone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0");
+ _menuZone->addRect(0x0A, 0xAE, 0x3C, 0xC7, nullptr, 0, "SHOTMENU", "0");
_subMenuZone = new Zone("SubMenu", "GLOBALHIT");
_subMenuZone->addRect(0, 0, 0x78, 0x3C, nullptr, 0, "STARTMENU", "0");
@@ -129,16 +142,16 @@ void GameBountyHunter::init() {
_skullSound = loadSoundFile("skull.8b");
_gun = AlgGraphics::loadScreenCoordAniImage("bh_gun.ani", _palette);
- _shotgun = AlgGraphics::loadScreenCoordAniImage("bh_buck.ani", _palette);
+ _bulletHoleIcon = AlgGraphics::loadScreenCoordAniImage("bh_hole.ani", _palette);
+ _shotgunHoleIcon = AlgGraphics::loadScreenCoordAniImage("bh_buck.ani", _palette);
_numbers = AlgGraphics::loadAniImage("bh_num.ani", _palette);
auto bullets = AlgGraphics::loadAniImage("bh_ammo.ani", _palette);
_shotIcon = (*bullets)[0];
_emptyIcon = (*bullets)[1];
+ _shellIcon = (*bullets)[2];
auto lives = AlgGraphics::loadAniImage("bh_life.ani", _palette);
_liveIcon = (*lives)[0];
_deadIcon = (*lives)[1];
- auto hole = AlgGraphics::loadScreenCoordAniImage("bh_hole.ani", _palette);
- _bulletholeIcon = (*hole)[0];
auto players = AlgGraphics::loadAniImage("bh_plyr.ani", _palette);
_playersIcon1 = (*players)[0];
_playersIcon2 = (*players)[1];
@@ -149,6 +162,9 @@ void GameBountyHunter::init() {
_bagsIcons = AlgGraphics::loadScreenCoordAniImage("bh_bags.ani", _palette);
_background = AlgGraphics::loadVgaBackground("bh_menu.vga", _palette);
+ AlgGraphics::drawImage(_background, _textScoreIcon, 0x78, 0xBF);
+ AlgGraphics::drawImage(_background, _textMenuIcon, 0x0C, 0xBF);
+ displayScores(0);
_screen->copyRectToSurface(_background->getPixels(), _background->pitch, 0, 0, _background->w, _background->h);
moveMouse();
@@ -365,7 +381,7 @@ void GameBountyHunter::callScriptFunctionScene(SceneFuncType type, Common::Strin
Common::Error GameBountyHunter::run() {
init();
- newGame();
+ startMyGame();
_numPlayers = 1;
_curScene = _startScene;
Common::String oldscene;
@@ -390,6 +406,11 @@ Common::Error GameBountyHunter::run() {
if (fired(&firedCoords)) {
if (_lastShotTime == 0) {
Rect *hitGlobalRect = checkZone(_menuZone, &firedCoords);
+ if (_bagActive && _bagRect.contains(firedCoords)) {
+ if (_iconCounter < 3) {
+ _iconCounter++;
+ }
+ }
if (hitGlobalRect != nullptr) {
callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect);
} else {
@@ -399,15 +420,15 @@ Common::Error GameBountyHunter::run() {
_lastShotTime = getMsTime();
}
displayShotFiredImage(&firedCoords);
- playSound(_shotSound); // TODO different sound for shotgun
+ if (_playerGun[_player] == 2) {
+ playSound(_shotgunSound);
+ } else {
+ playSound(_shotSound);
+ }
Rect *hitRect = nullptr;
Zone *hitSceneZone = checkZones(scene, hitRect, &firedCoords);
if (hitSceneZone != nullptr) {
callScriptFunctionRectHit(hitRect->_rectHit, hitRect);
- if (_curScene == oldscene) {
- // skip to new scene
- callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene);
- }
}
} else {
playSound(_emptySound);
@@ -446,6 +467,7 @@ Common::Error GameBountyHunter::run() {
if (remainingMillis < 10) {
if (_videoDecoder->getCurrentFrame() > 0) {
_videoDecoder->getNextFrame();
+ moveCurrentBag();
}
remainingMillis = _nextFrameTime - getMsTime();
_nextFrameTime = getMsTime() + (remainingMillis > 0 ? remainingMillis : 0) + 100;
@@ -474,12 +496,54 @@ Common::Error GameBountyHunter::run() {
return Common::kNoError;
}
-void GameBountyHunter::newGame() {
- _playerLives[0] = _playerLives[1] = 3;
- _playerShots[0] = _playerShots[1] = 6;
- _playerGun[0] = _playerGun[1] = 1;
- _playerScore[0] = _playerScore[1] = 0;
+void GameBountyHunter::updateScreen() {
+ _screen->copyRectToSurface(_background->getPixels(), _background->pitch, 0, 0, _background->w, _background->h);
+ if (!_inMenu) {
+ Graphics::Surface *frame = _videoDecoder->getVideoFrame();
+ _screen->copyRectToSurface(frame->getPixels(), frame->pitch, _videoPosX, _videoPosY, frame->w, frame->h);
+ }
+ debug_drawZoneRects();
+ displayCurrentBag();
+ if (_paletteDirty || _videoDecoder->isPaletteDirty()) {
+ g_system->getPaletteManager()->setPalette(_palette, 0, 256);
+ _paletteDirty = false;
+ }
+ g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h);
+ g_system->updateScreen();
+}
+
+uint16 GameBountyHunter::startMyGame() {
+ uint16 startScene = 0;
+ if (_restartScene == 0) {
+ _playerGun[0] = _playerGun[1] = 1;
+ _playerShots[0] = _playerShots[1] = 6;
+ _playerLives[0] = _playerLives[1] = 3;
+ _playerScore[0] = _playerScore[1] = 0;
+ initGameStatus();
+ if (_vm->isDemo()) {
+ startScene = 69; // TODO fix
+ } else {
+ startScene = 69;
+ }
+ } else {
+ startScene = _restartScene;
+ _restartScene = 0;
+ }
+ return startScene;
+}
+
+void GameBountyHunter::initGameStatus() {
+ _currentLevel = 0;
+ _continuesUsed = 0;
+ _restartScene = 0;
+ _levelDoneMask = 0;
+ _numLevelsDone = 0;
+ _numSubLevelsDone = 0;
+ _difficulty = 0;
+
_currentSubLevelSceneId = 0x017B;
+ iconSetup();
+ iconReset(); // not in original!
}
void GameBountyHunter::doMenu() {
@@ -517,11 +581,8 @@ void GameBountyHunter::updateCursor() {
void GameBountyHunter::updateMouse() {
if (_oldWhichGun != _whichGun) {
Graphics::Surface *cursor = (*_gun)[_whichGun];
- if (_playerGun[0] == 2 && _whichGun < 2) {
- cursor = (*_shotgun)[_whichGun];
- }
- uint16 hotspotX = (cursor->w / 2) + 8;
- uint16 hotspotY = (cursor->h / 2) + 8;
+ uint16 hotspotX = (cursor->w / 2) + 7;
+ uint16 hotspotY = (cursor->h / 2) + 6;
if (debugChannelSet(1, Alg::kAlgDebugGraphics)) {
cursor->drawLine(0, hotspotY, cursor->w, hotspotY, 1);
cursor->drawLine(hotspotX, 0, hotspotX, cursor->h, 1);
@@ -550,68 +611,75 @@ void GameBountyHunter::moveMouse() {
g_system->warpMouse(x, y);
}
*/
- if (_mousePos.y >= 0xA3 && _mousePos.x >= 0xF0) {
- _whichGun = 1; // holster
- } else if (_mousePos.y >= 0xA3 && _mousePos.x <= 0x43) {
+ if (_mousePos.y >= 0xAE && _mousePos.x >= 0xF0) {
+ _whichGun = 4; // holster
+ } else if (_mousePos.y >= 0xAE && _mousePos.x <= 0x3C) {
_whichGun = 2; // menu button cursor
} else {
- _whichGun = 0; // regular gun
+ _whichGun = 0; // player 1 gun cursor is 0, player 2 is 1
}
}
updateMouse();
}
void GameBountyHunter::displayLivesLeft(uint8 player) {
- if (_lives[player] == _oldLives[player]) {
+ if (_playerLives[player] == _oldLives[player]) {
return;
}
+ if (_playerLives[player] < 0) {
+ _playerLives[player] = 0;
+ }
int posX = player == 0 ? 0xD7 : 0x50;
for (int i = 0; i < 3; i++) {
- AlgGraphics::drawImage(_screen, _deadIcon, posX, 0xBE);
+ AlgGraphics::drawImage(_background, _deadIcon, posX, 0xBE);
posX += 10;
}
posX = player == 0 ? 0xD7 : 0x50;
- for (int i = 0; i < _lives[player]; i++) {
- AlgGraphics::drawImage(_screen, _liveIcon, posX, 0xBE);
+ for (int i = 0; i < _playerLives[player]; i++) {
+ AlgGraphics::drawImage(_background, _liveIcon, posX, 0xBE);
posX += 10;
}
- _oldLives[player] = _lives[player];
+ _oldLives[player] = _playerLives[player];
}
void GameBountyHunter::displayScores(uint8 player) {
- if (_score[player] == _oldScore[player]) {
+ if (_playerScore[player] == _oldScore[player]) {
return;
}
- Common::String scoreString = Common::String::format("%05d", _score[player]);
+ Common::String scoreString = Common::String::format("%05d", _playerScore[player]);
int posX = player == 0 ? 0xA5 : 0x78;
for (int i = 0; i < 5; i++) {
uint8 digit = scoreString[i] - '0';
- uint8 digitOffset = player == 1 ? digit : digit + 10;
- AlgGraphics::drawImage(_screen, (*_numbers)[digitOffset], posX, 0xBF);
+ uint8 digitOffset = player == 0 ? digit : digit + 10;
+ AlgGraphics::drawImage(_background, (*_numbers)[digitOffset], posX, 0xBF);
posX += 5;
}
- _oldScore[player] = _score[player];
+ _oldScore[player] = _playerScore[player];
}
void GameBountyHunter::displayShotsLeft(uint8 player) {
- if (_shots[player] == _oldShots[player]) {
+ if (_playerShots[player] == _oldShots[player]) {
return;
}
uint16 posX = player == 0 ? 0xF8 : 0x0C;
for (int i = 0; i < 10; i++) {
- AlgGraphics::drawImage(_screen, _emptyIcon, posX, 0xBF);
+ AlgGraphics::drawImage(_background, _emptyIcon, posX, 0xBF);
posX += 5;
}
posX = player == 0 ? 0xF8 : 0x0C;
- for (int i = 0; i < _shots[player]; i++) {
- AlgGraphics::drawImage(_screen, _shotIcon, posX, 0xBF);
+ for (int i = 0; i < _playerShots[player]; i++) {
+ if (_playerGun[_player] == 2) {
+ AlgGraphics::drawImage(_background, _shellIcon, posX, 0xBF);
+ } else {
+ AlgGraphics::drawImage(_background, _shotIcon, posX, 0xBF);
+ }
posX += 5;
}
- _oldShots[player] = _shots[player];
+ _oldShots[player] = _playerShots[player];
}
bool GameBountyHunter::weaponDown() {
- if (_rightDown && _mousePos.y >= 0xAA && _mousePos.x >= 0x113) {
+ if (_rightDown && _mousePos.y >= 0xAE && _mousePos.x >= 0xF0) {
return true;
}
return false;
@@ -692,10 +760,11 @@ Zone *GameBountyHunter::checkZones(Scene *scene, Rect *&hitRect, Common::Point *
Rect *GameBountyHunter::checkZone(Zone *zone, Common::Point *point) {
for (auto &rect : zone->_rects) {
Common::Rect interpolated = rect->getInterpolatedRect(zone->_startFrame, zone->_endFrame, _currentFrame);
- if (point->x >= interpolated.left &&
- point->x <= interpolated.right &&
- point->y >= interpolated.top &&
- point->y <= interpolated.bottom) {
+ if (_playerGun[_player] == 2) {
+ // shotgun, hit area is enlarged
+ interpolated.grow(15);
+ }
+ if (interpolated.contains(*point)) {
return rect;
}
}
@@ -712,7 +781,11 @@ void GameBountyHunter::displayShotFiredImage(Common::Point *point) {
int32 targetX = point->x - _videoPosX;
int32 targetY = point->y - _videoPosY;
if (targetX > 0 && targetY > 0) {
- AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY);
+ if (_playerGun[_player] == 2) {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), (*_shotgunHoleIcon)[_player], targetX - 8, targetY - 10);
+ } else {
+ AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), (*_bulletHoleIcon)[_player], targetX - 4, targetY - 4);
+ }
}
}
}
@@ -721,12 +794,115 @@ void GameBountyHunter::enableVideoFadeIn() {
// TODO implement
}
+void GameBountyHunter::iconBags() {
+ if (!_bagDropped) {
+ _bagActive = true;
+ _bagRect.top = _mousePos.y;
+ _bagRect.left = _mousePos.x;
+ _bagRect.bottom = _mousePos.y + 0x26;
+ _bagRect.right = _mousePos.x + 0x11;
+ _playerWhoHitBag = _player;
+ _bagDropped = true;
+ }
+}
+
+void GameBountyHunter::iconBullets() {
+ if (!_bulletsGiven) {
+ if (_playerGun[_player] == 1) {
+ _playerShots[_player] = 12;
+ } else {
+ _playerShots[_player] = 5;
+ }
+ _bulletsGiven = true;
+ displayShotsLeft(_player);
+ }
+}
+
+void GameBountyHunter::iconMoney() {
+ if (!_moneyGiven) {
+ _playerScore[_player] += 50;
+ _moneyGiven = 1;
+ }
+}
+
void GameBountyHunter::iconShotgun() {
- // TODO implement
+ if (!_shotgunGiven) {
+ _shotgunGiven = 1;
+ _playerShots[_player] = 5;
+ _playerGun[_player] = 2;
+ displayShotsLeft(_player);
+ }
}
void GameBountyHunter::iconReset() {
- // TODO implement
+ _bulletsGiven = 0;
+ _moneyGiven = false;
+ _shotgunGiven = false;
+ _bagDropped = false;
+ _iconOffset = 0;
+ _iconCounter = 0;
+
+}
+
+void GameBountyHunter::iconSetup() {
+ uint16 usedFlags = 0;
+ _iconOrder[0] = randomUnusedInt(4, &usedFlags, -1);
+ _iconOrder[1] = randomUnusedInt(4, &usedFlags, -1);
+ _iconOrder[2] = randomUnusedInt(4, &usedFlags, -1);
+ _iconOrder[3] = randomUnusedInt(4, &usedFlags, -1);
+ _iconOffset = 0;
+ _iconCounter = 0;
+}
+
+void GameBountyHunter::iconHitGeneric(uint8 type) {
+ uint8 selected = 0;
+ for (uint8 i = 0; i < 4; i++) {
+ if(_iconOrder[i] == type) {
+ selected = i;
+ break;
+ }
+ }
+ switch (selected)
+ {
+ case 0:
+ iconBullets();
+ break;
+ case 1:
+ iconMoney();
+ break;
+ case 2:
+ iconBags();
+ break;
+ case 3:
+ iconShotgun();
+ break;
+ }
+}
+
+void GameBountyHunter::displayCurrentBag() {
+ if (_bagActive) {
+ AlgGraphics::drawImageCentered(_screen, (*_bagsIcons)[_iconOffset], _bagRect.left, _bagRect.top);
+ }
+}
+
+void GameBountyHunter::moveCurrentBag() {
+ if (_bagActive) {
+ uint8 animState = _bagAnimToggle ? 1 : 0;
+ _iconOffset = (_iconCounter * 2) + animState;
+ _bagAnimToggle = !_bagAnimToggle;
+
+ uint16 offsetY = _difficulty + 4;
+ _bagRect.top += offsetY;
+ _bagRect.bottom += offsetY;
+
+ if (_bagRect.top > 0x99) {
+ _bagActive = false;
+ _playerScore[_playerWhoHitBag] += 2 << _iconCounter;
+ displayScores(_playerWhoHitBag);
+ _iconOffset = 0;
+ _iconCounter = 0;
+ }
+ }
}
uint16 GameBountyHunter::beginLevel(uint8 levelNumber) {
@@ -771,14 +947,18 @@ uint16 GameBountyHunter::pickRandomScene(uint16 *sceneList, uint8 max) {
_randomMask = 0;
_randomPicked = -1;
_randomSceneCount = 0;
- while (_randomSceneList[_randomSceneCount] != 0) {
- _randomSceneCount++;
+ if (_randomSceneList != nullptr) {
+ while (_randomSceneList[_randomSceneCount] != 0) {
+ _randomSceneCount++;
+ }
}
}
- uint16 count = _randomMax--;
+ int16 count = _randomMax--;
if (count > 0) {
_randomPicked = randomUnusedInt(_randomSceneCount, &_randomMask, _randomPicked);
- return _randomSceneList[_randomPicked];
+ if (_randomSceneList != nullptr) {
+ return _randomSceneList[_randomPicked];
+ }
}
return 0;
}
@@ -826,13 +1006,12 @@ uint16 GameBountyHunter::pickDeathScene() {
}
uint16 GameBountyHunter::timeForGunfight() {
- uint16 picked = 0;
if (--_gunfightCount <= 0) {
int index = (_difficulty * 5) + (_numLevelsDone);
_gunfightCount = _gunfightCountDown[index];
- picked = pickGunfightScene();
+ return pickGunfightScene();
}
- return picked;
+ return 0;
}
void GameBountyHunter::waitingForShootout(uint32 drawFrame) {
@@ -844,31 +1023,20 @@ void GameBountyHunter::waitingForShootout(uint32 drawFrame) {
displayShotsLeft(i);
}
}
- // TODO investigate & fix
if (_currentFrame > _firstDrawFrame) {
- // player1 = 1;
- // player2 = 1;
- }
- /*
- if (shotsPlayer1 <= 0 && shotsPlayer2 <= 0) {
- return false;
+ _playerGun[0] = 1;
+ _playerGun[1] = 1;
}
- return true;
- */
-}
-
-void GameBountyHunter::doShotgunSound() {
- playSound(_shotgunSound);
}
// Script functions: RectHit
void GameBountyHunter::rectNewScene(Rect *rect) {
uint32 _weightedScore = rect->_score + (_difficulty * 10);
- _score[_player] += _weightedScore;
+ _playerScore[_player] += _weightedScore;
_pointsSinceLastBonus[_player] += _weightedScore;
if (_pointsSinceLastBonus[_player] > 5000) {
_pointsSinceLastBonus[_player] = 0;
- _lives[_player]++;
+ _playerLives[_player]++;
}
if (!rect->_scene.empty()) {
_curScene = rect->_scene;
@@ -915,14 +1083,8 @@ void GameBountyHunter::rectStart(Rect *rect) {
_inMenu = false;
_fired = false;
_gameInProgress = true;
- _restartScene = 0;
- if (_vm->isDemo()) {
- debug(5, "FIXME: Demo Next Scene is 0x45?");
- setNextScene(0x45); // TODO fix
- } else {
- setNextScene(0x45);
- }
- newGame();
+ uint16 startScene = startMyGame();
+ setNextScene(startScene);
}
void GameBountyHunter::rectExit(Rect *rect) {
@@ -935,45 +1097,39 @@ void GameBountyHunter::rectTogglePlayers(Rect *rect) {
AlgGraphics::drawImage(_background, _playersIcon2, 0xCE, 0x95);
AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x78, 0xBF);
AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x0C, 0xBF);
+ // force rendering
+ _oldShots[1] = 0;
+ _oldLives[1] = 0;
displayShotsLeft(1);
displayLivesLeft(1);
} else {
_numPlayers = 1;
AlgGraphics::drawImage(_background, _playersIcon1, 0xCE, 0x95);
+ AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x50, 0xBE);
AlgGraphics::drawImage(_background, _textScoreIcon, 0x78, 0xBF);
AlgGraphics::drawImage(_background, _textMenuIcon, 0x0C, 0xBF);
- AlgGraphics::drawImage(_background, _textBlackBarIcon, 0x50, 0xBE);
}
playSound(_skullSound);
- _screen->copyRectToSurface(_background->getBasePtr(_videoPosX, _videoPosY), _background->pitch, _videoPosX, _videoPosY, _videoDecoder->getWidth(), _videoDecoder->getHeight());
}
void GameBountyHunter::rectHitIconJug(Rect *rect) {
- // TODO fix
- // Icon.funcs[1](param);
- // PlaySound(4);
- // Icon.hitCount++;
+ iconHitGeneric(1);
+ playSound(_skullSound);
}
void GameBountyHunter::rectHitIconLantern(Rect *rect) {
- // TODO fix
- // Icon.funcs[3](param);
- // PlaySound(4);
- // Icon.hitCount++;
+ iconHitGeneric(3);
+ playSound(_skullSound);
}
void GameBountyHunter::rectHitIconSkull(Rect *rect) {
- // TODO fix
- // Icon.funcs[0](param);
- // PlaySound(4);
- // Icon.hitCount++;
+ iconHitGeneric(0);
+ playSound(_skullSound);
}
void GameBountyHunter::rectHitIconWheel(Rect *rect) {
- // TODO fix
- // Icon.funcs[2](param);
- // PlaySound(4);
- // Icon.hitCount++;
+ iconHitGeneric(2);
+ playSound(_skullSound);
}
void GameBountyHunter::rectHitSelectHarry(Rect *rect) {
@@ -1013,12 +1169,10 @@ void GameBountyHunter::rectHitGiveShotgun(Rect *rect) {
}
void GameBountyHunter::rectHitKill3(Rect *rect) {
- _count++;
- if (_count == 3) {
- _count = 0;
+ _kill3Count++;
+ if (_kill3Count == 3) {
+ _kill3Count = 0;
rectNewScene(rect);
- // TODO verify
- // _RHONewScene(param1, param2);
}
}
@@ -1072,12 +1226,11 @@ void GameBountyHunter::sceneIsoShootout(Scene *scene) {
void GameBountyHunter::sceneIsoGivemoney(Scene *scene) {
const int moneyFrames[] = {0x1E8F, 0x3BB4, 0x7814, 0xA287};
- const int woundBits[] = {2, 4, 8, 0x10};
+ const int woundBits[] = {2, 4, 8, 16};
for (int i = 0; i < _numPlayers; i++) {
if (_currentLevel <= 3) {
uint32 moneyFrame = moneyFrames[_currentLevel];
- // TODO investigate
- if (moneyFrame == _currentFrame && !_given) {
+ if (moneyFrame == _currentFrame && !_moneyGiven) {
if (_wounded) {
_mainWounds |= woundBits[_currentLevel];
int bonus = (2 ^ _numLevelsDone) * 200;
@@ -1087,9 +1240,9 @@ void GameBountyHunter::sceneIsoGivemoney(Scene *scene) {
_playerScore[i] += bonus;
}
_wounded = false;
- _given = true;
+ _moneyGiven = true;
} else if (moneyFrame != _currentFrame) {
- _given = false;
+ _moneyGiven = false;
}
}
displayScores(i);
@@ -1099,19 +1252,21 @@ void GameBountyHunter::sceneIsoGivemoney(Scene *scene) {
// Script functions: Scene NxtScn
void GameBountyHunter::sceneNxtscnLoseALife(Scene *scene) {
uint16 picked = 0;
- int deadPlayerCount = 0;
+ uint8 deadCount = 0;
(void)scene;
- for (uint i = 0; i < _numPlayers; i++) {
- _playerLives[i]--;
+ for (int i = 0; i < _numPlayers; i++) {
+ if (!_debug_godMode) {
+ _playerLives[i]--;
+ }
displayLivesLeft(i);
if (_playerLives[i] <= 0) {
_playerScore[i] = (_playerScore[i] * 6) / 10;
- deadPlayerCount++;
+ deadCount++;
}
}
- if (deadPlayerCount == 1 && _numPlayers == 2) {
+ if (deadCount == 1 && _numPlayers == 2) {
picked = _onePlayerOfTwoDead[_numSubLevelsDone & 1];
- } else if (deadPlayerCount > 0) {
+ } else if (deadCount > 0) {
picked = _allPlayersDead;
} else {
picked = pickDeathScene();
@@ -1175,7 +1330,7 @@ void GameBountyHunter::sceneNxtscnGotoLevelSelect(Scene *scene) {
}
void GameBountyHunter::sceneNxtscnContinueRandom(Scene *scene) {
- uint16 picked = pickRandomScene(0, 0);
+ uint16 picked = pickRandomScene(nullptr, 0);
if (picked == 0) {
sceneNxtscnNextSubLevel(scene);
} else {
@@ -1235,21 +1390,19 @@ void GameBountyHunter::sceneNxtscnInitRandomKid2(Scene *scene) {
void GameBountyHunter::sceneNxtscnNextSubLevel(Scene *scene) {
iconReset();
_numSubLevelsDone++;
- int index = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
- uint8 subLevel = _subLevelOrder[index];
+ int subLevelIndex = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
+ uint8 subLevel = _subLevelOrder[subLevelIndex];
uint16 sceneIndex = (_currentLevel * 5) + subLevel;
uint16 picked = _subLevelSceneIds[sceneIndex];
_currentSubLevelSceneId = picked;
uint16 gunfightScene = timeForGunfight();
if (gunfightScene != 0) {
- setNextScene(gunfightScene);
+ picked = gunfightScene;
}
- if (subLevel == 2) {
+ else if (subLevel != 2) {
if (_currentLevel == 0) {
- setNextScene(picked);
- return;
+ picked = _clueLevels[_currentLevel];
}
- picked = _clueLevels[_currentLevel];
}
setNextScene(picked);
}
@@ -1343,7 +1496,9 @@ void GameBountyHunter::sceneNxtscnDiedRefed(Scene *scene) {
uint8 deadCount = 0;
(void)scene;
for (uint i = 0; i < _numPlayers; i++) {
- _playerLives[i]--;
+ if (!_debug_godMode) {
+ _playerLives[i]--;
+ }
displayLivesLeft(i);
if (_playerLives[i] <= 0) {
deadCount++;
@@ -1388,10 +1543,12 @@ void GameBountyHunter::sceneDefaultWepdwn(Scene *scene) {
// Script functions: ScnScr
void GameBountyHunter::sceneDefaultScore(Scene *scene) {
- if (scene->_scnscrParam > 0) {
- _score[0] += scene->_scnscrParam;
+ uint16 score = scene->_scnscrParam + (_difficulty * 4);
+ if (score > 0) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
+ _playerScore[i] += score;
+ }
}
- // TODO verify, nothing for player2?
}
// Debug methods
diff --git a/engines/alg/logic/game_bountyhunter.h b/engines/alg/logic/game_bountyhunter.h
index fe9f7680f44..cbd1c79a2de 100644
--- a/engines/alg/logic/game_bountyhunter.h
+++ b/engines/alg/logic/game_bountyhunter.h
@@ -78,16 +78,19 @@ private:
// images
Graphics::Surface *_shotIcon;
Graphics::Surface *_emptyIcon;
+ Graphics::Surface *_shellIcon;
Graphics::Surface *_liveIcon;
Graphics::Surface *_deadIcon;
- Graphics::Surface *_bulletholeIcon;
Graphics::Surface *_playersIcon1;
Graphics::Surface *_playersIcon2;
Graphics::Surface *_textScoreIcon;
Graphics::Surface *_textMenuIcon;
Graphics::Surface *_textBlackBarIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
Common::Array<Graphics::Surface *> *_bagsIcons;
- Common::Array<Graphics::Surface *> *_shotgun;
+ Common::Array<Graphics::Surface *> *_bulletHoleIcon;
+ Common::Array<Graphics::Surface *> *_shotgunHoleIcon;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
@@ -124,49 +127,43 @@ private:
// const uint16 _firstSceneInScenario[4] = {0x04, 0x36, 0x36, 0x66};
const uint16 _moneyScenes[4] = {0x017D, 0x013C, 0xC3, 0x69};
- const uint16 _gunfightScenarios[18] = {0x0116, 0x0118, 0x011B, 0x011D, 0x011F, 0x0121, 0x0123, 0x0125, 0x0127,
- 0x0129, 0x012B, 0x012D, 0x012F, 0x0131, 0x0133, 0x0135, 0x0137, 0x0139};
+ const uint16 _gunfightScenarios[19] = {0x0116, 0x0118, 0x011B, 0x011D, 0x011F, 0x0121, 0x0123, 0x0125, 0x0127,
+ 0x0129, 0x012B, 0x012D, 0x012F, 0x0131, 0x0133, 0x0135, 0x0137, 0x0139, 0};
const uint16 _innocentScenarios[5] = {0x0110, 0x010F, 0x010C, 0x010B, 0};
const uint16 _deathScenarios[9] = {0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0};
const uint16 _onePlayerOfTwoDead[2] = {0x0109, 0x010A};
const uint16 _allPlayersDead = 0x108;
// gamestate
+ uint8 _continuesUsed = 0;
+ uint8 _currentLevel = 0;
+ uint16 _currentSubLevelSceneId = 0;
uint8 _difficulty = 0;
uint8 _oldDifficulty = 1;
+ uint32 _firstDrawFrame = 0;
+ int8 _gunfightCount = 0;
+ uint8 _kill3Count = 0;
uint32 _lastShotTime = 0;
- int8 _lives[2] = {0, 0};
- int8 _oldLives[2] = {0, 0};
- int32 _score[2] = {0, 0};
- int32 _oldScore[2] = {-1, -1};
- uint32 _pointsSinceLastBonus[2] = {0, 0};
- uint16 _shots[2] = {0, 0};
- uint8 _oldShots[2] = {0, 0};
- uint8 _whichGun = 0;
- uint8 _oldWhichGun = 0xFF;
- // TODO verify, whichGun for player2?
-
- uint16 _restartScene = 0;
+ uint8 _levelDoneMask = 0;
+ uint16 _mainWounds = 0;
+ uint8 _numLevelsDone = 0;
+ uint8 _numSubLevelsDone = 0;
uint8 _numPlayers = 1;
uint8 _player = 0;
- uint8 _playerLives[2] = {0, 0};
+ int8 _playerLives[2] = {3, 3};
+ int8 _oldLives[2] = {0, 0};
uint8 _playerGun[2] = {1, 1};
- uint8 _playerShots[2] = {0, 0};
+ uint8 _playerShots[2] = {6, 6};
+ uint8 _oldShots[2] = {0, 0};
uint32 _playerScore[2] = {0, 0};
+ uint32 _oldScore[2] = {1, 1};
+ uint32 _pointsSinceLastBonus[2] = {0, 0};
+ uint16 _restartScene = 0;
+ uint8 _whichGun = 0;
+ uint8 _oldWhichGun = 0xFF;
+ bool _wounded = false;
- uint8 _currentLevel = 0;
- uint16 _currentSubLevelSceneId = 0;
- uint8 _numLevelsDone = 0;
- uint8 _levelDoneMask = 0;
- uint8 _numSubLevelsDone = 0;
-
- // TODO remove?
- // uint16 _usedScenes = 0;
- // int16 _lastPick = -1;
- // int16 _initted = 0;
- // int16 _sceneCount = 0;
-
- uint16 *_randomSceneList;
+ uint16 *_randomSceneList = nullptr;
uint8 _randomMax = 0;
uint16 _randomMask = 0;
int16 _randomPicked = 0;
@@ -184,18 +181,25 @@ private:
int16 _deathPicked = 0;
uint8 _deathSceneCount = 0;
- uint8 _continuesUsed = 0;
- bool _wounded = false;
- uint16 _mainWounds = 0;
- int8 _gunfightCount = 0;
- bool _given = false;
- uint32 _firstDrawFrame = 0;
- uint8 _count = 0;
+ uint8 _iconOrder[4] = {0, 0, 0, 0};
+ uint32 _iconOffset = 0;
+ uint32 _iconCounter = 0;
+ bool _bagAnimToggle = false;
+ Rect _bagRect;
+ bool _bagActive = false;
+ uint8 _playerWhoHitBag = 0;
+
+ bool _bulletsGiven = false;
+ bool _moneyGiven = false;
+ bool _shotgunGiven = false;
+ bool _bagDropped = false;
Common::String _subScene;
// base functions
- void newGame();
+ void updateScreen() override;
+ uint16 startMyGame();
+ void initGameStatus();
void doMenu();
void updateCursor();
void updateMouse();
@@ -213,8 +217,15 @@ private:
void setNextScene(uint16 sceneId);
void displayShotFiredImage(Common::Point *point);
void enableVideoFadeIn();
+ void iconBags();
+ void iconBullets();
+ void iconMoney();
void iconShotgun();
void iconReset();
+ void iconSetup();
+ void iconHitGeneric(uint8 type);
+ void displayCurrentBag();
+ void moveCurrentBag();
uint16 beginLevel(uint8 levelNumber);
uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint16 *sceneList, uint8 max);
@@ -223,7 +234,6 @@ private:
uint16 pickDeathScene();
uint16 timeForGunfight();
void waitingForShootout(uint32 drawFrame);
- void doShotgunSound();
// Script functions: RectHit
void rectNewScene(Rect *rect);
@@ -299,7 +309,7 @@ private:
void sceneDefaultScore(Scene *scene);
// debug methods
- void debug_drawZoneRects();
+ void debug_drawZoneRects() override;
};
class DebuggerBountyHunter : public GUI::Debugger {
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index 514260b63e3..20c106832d3 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -60,6 +60,14 @@ GameCrimePatrol::~GameCrimePatrol() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _skullSound;
diff --git a/engines/alg/logic/game_crimepatrol.h b/engines/alg/logic/game_crimepatrol.h
index ac4d587ecec..628a181fd60 100644
--- a/engines/alg/logic/game_crimepatrol.h
+++ b/engines/alg/logic/game_crimepatrol.h
@@ -80,6 +80,8 @@ private:
Graphics::Surface *_deadIcon;
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index b60e3a8a861..87595d136ae 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -60,6 +60,14 @@ GameDrugWars::~GameDrugWars() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _skullSound;
diff --git a/engines/alg/logic/game_drugwars.h b/engines/alg/logic/game_drugwars.h
index 998bbc86238..da67b8760b9 100644
--- a/engines/alg/logic/game_drugwars.h
+++ b/engines/alg/logic/game_drugwars.h
@@ -80,6 +80,8 @@ private:
Graphics::Surface *_deadIcon;
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/logic/game_johnnyrock.cpp b/engines/alg/logic/game_johnnyrock.cpp
index 6acdc8041d5..0cf0903543c 100644
--- a/engines/alg/logic/game_johnnyrock.cpp
+++ b/engines/alg/logic/game_johnnyrock.cpp
@@ -49,6 +49,14 @@ GameJohnnyRock::~GameJohnnyRock() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _moneySound;
diff --git a/engines/alg/logic/game_johnnyrock.h b/engines/alg/logic/game_johnnyrock.h
index 614af5a2af3..3a92ece666f 100644
--- a/engines/alg/logic/game_johnnyrock.h
+++ b/engines/alg/logic/game_johnnyrock.h
@@ -83,6 +83,8 @@ private:
Common::Array<Graphics::Surface *> *_difficultyIcon;
Graphics::Surface *_levelIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/logic/game_maddog.cpp b/engines/alg/logic/game_maddog.cpp
index 09121246305..ef0723c7b44 100644
--- a/engines/alg/logic/game_maddog.cpp
+++ b/engines/alg/logic/game_maddog.cpp
@@ -69,6 +69,14 @@ GameMaddog::~GameMaddog() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _easySound;
diff --git a/engines/alg/logic/game_maddog.h b/engines/alg/logic/game_maddog.h
index 6f9a1fe38e8..5a1c87435c7 100644
--- a/engines/alg/logic/game_maddog.h
+++ b/engines/alg/logic/game_maddog.h
@@ -88,6 +88,8 @@ private:
Graphics::Surface *_drawIcon;
Graphics::Surface *_knifeIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/logic/game_maddog2.cpp b/engines/alg/logic/game_maddog2.cpp
index 78c0cbf46fa..5d3eed11aed 100644
--- a/engines/alg/logic/game_maddog2.cpp
+++ b/engines/alg/logic/game_maddog2.cpp
@@ -69,6 +69,14 @@ GameMaddog2::~GameMaddog2() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _skullSound;
diff --git a/engines/alg/logic/game_maddog2.h b/engines/alg/logic/game_maddog2.h
index b099f5735c9..4113347cb7c 100644
--- a/engines/alg/logic/game_maddog2.h
+++ b/engines/alg/logic/game_maddog2.h
@@ -88,6 +88,8 @@ private:
Graphics::Surface *_drawIcon;
Graphics::Surface *_knifeIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/logic/game_spacepirates.cpp b/engines/alg/logic/game_spacepirates.cpp
index 1e99f82c0d1..6c50e2a7b12 100644
--- a/engines/alg/logic/game_spacepirates.cpp
+++ b/engines/alg/logic/game_spacepirates.cpp
@@ -64,6 +64,14 @@ GameSpacePirates::~GameSpacePirates() {
_bulletholeIcon->free();
delete _bulletholeIcon;
}
+ for (auto item : *_gun) {
+ item->free();
+ delete item;
+ }
+ for (auto item : *_numbers) {
+ item->free();
+ delete item;
+ }
delete _saveSound;
delete _loadSound;
delete _difficultySound;
diff --git a/engines/alg/logic/game_spacepirates.h b/engines/alg/logic/game_spacepirates.h
index bdd2a0625e1..054cb9759e9 100644
--- a/engines/alg/logic/game_spacepirates.h
+++ b/engines/alg/logic/game_spacepirates.h
@@ -85,6 +85,8 @@ private:
Graphics::Surface *_liveIcon3;
Graphics::Surface *_difficultyIcon;
Graphics::Surface *_bulletholeIcon;
+ Common::Array<Graphics::Surface *> *_gun;
+ Common::Array<Graphics::Surface *> *_numbers;
// sounds
Audio::SeekableAudioStream *_saveSound = nullptr;
diff --git a/engines/alg/scene.cpp b/engines/alg/scene.cpp
index 1bb677a4d25..3e447c7180b 100644
--- a/engines/alg/scene.cpp
+++ b/engines/alg/scene.cpp
@@ -248,37 +248,49 @@ void SceneInfo::parseZone(const Common::String &zoneName, uint32 startFrame, uin
void SceneInfo::addZonesToScenes() {
for (auto &scene : _scenes) {
if (!scene->_zonesStart.empty()) {
- Zone *zone = nullptr;
- do {
- Zone *found = findZone(scene->_zonesStart);
+ Zone *zone = findZone(scene->_zonesStart);
+ while (true) {
if (zone) {
- zone = found->clone();
+ zone = zone->clone();
zone->_difficulty = 0;
scene->_zones.push_back(zone);
}
- } while (zone && !zone->_next.empty());
+ if (zone->_next.empty()) {
+ break;
+ } else {
+ zone = findZone(zone->_next);
+ }
+ }
}
- if (!scene->_zonesStart2.empty() && scene->_zonesStart2 != scene->_zonesStart) {
- Zone *zone = nullptr;
- do {
- Zone *found = findZone(scene->_zonesStart);
+ if (!scene->_zonesStart2.empty()) {
+ Zone *zone = findZone(scene->_zonesStart);
+ while (true) {
if (zone) {
- zone = found->clone();
+ zone = zone->clone();
zone->_difficulty = 1;
scene->_zones.push_back(zone);
}
- } while (zone && !zone->_next.empty());
+ if (zone->_next.empty()) {
+ break;
+ } else {
+ zone = findZone(zone->_next);
+ }
+ }
}
- if (!scene->_zonesStart3.empty() && scene->_zonesStart3 != scene->_zonesStart2) {
- Zone *zone = nullptr;
- do {
- Zone *found = findZone(scene->_zonesStart);
+ if (!scene->_zonesStart3.empty()) {
+ Zone *zone = findZone(scene->_zonesStart);
+ while (true) {
if (zone) {
- zone = found->clone();
+ zone = zone->clone();
zone->_difficulty = 2;
scene->_zones.push_back(zone);
}
- } while (zone && !zone->_next.empty());
+ if (zone->_next.empty()) {
+ break;
+ } else {
+ zone = findZone(zone->_next);
+ }
+ }
}
}
}
@@ -359,6 +371,7 @@ Scene::~Scene() {
for (auto zone : _zones) {
delete zone;
}
+ _zones.clear();
}
Zone::Zone(const Common::String &name, const Common::String &ptrfb) {
@@ -376,6 +389,7 @@ Zone::~Zone() {
for (auto rect : _rects) {
delete rect;
}
+ _rects.clear();
}
void Zone::addRect(int16 left, int16 top, int16 right, int16 bottom, const Common::String scene, uint32 score, const Common::String rectHit, const Common::String unknown) {
@@ -395,7 +409,10 @@ Zone *Zone::clone() {
Zone *clone = new Zone(_name, _startFrame, _endFrame);
clone->_ptrfb = _ptrfb;
clone->_next = _next;
- clone->_rects = _rects;
+ for (auto rect : _rects) {
+ Rect *cloneRect = rect->clone();
+ clone->_rects.push_back(cloneRect);
+ }
return clone;
}
@@ -434,4 +451,19 @@ Common::Rect Rect::getInterpolatedRect(uint32 startFrame, uint32 endFrame, uint3
}
}
+Rect *Rect::clone() {
+ Rect *clone = new Rect();
+ clone->top = top;
+ clone->left = left;
+ clone->bottom = bottom;
+ clone->right = right;
+ clone->_scene = _scene;
+ clone->_score = _score;
+ clone->_rectHit = _rectHit;
+ clone->_unknown = _unknown;
+ clone->_isMoving = _isMoving;
+ clone->_dest = _dest;
+ return clone;
+}
+
} // End of namespace Alg
diff --git a/engines/alg/scene.h b/engines/alg/scene.h
index 5ecc8a71cb7..85a7320a7e9 100644
--- a/engines/alg/scene.h
+++ b/engines/alg/scene.h
@@ -79,6 +79,7 @@ public:
Common::Rect _dest;
void center(int16 cx, int16 cy, int16 w, int16 h);
Common::Rect getInterpolatedRect(uint32 startFrame, uint32 endFrame, uint32 currentFrame);
+ Rect *clone();
};
class Zone {
Commit: 8ef78e5e6d787df0f1911314a8cfaec4ac778255
https://github.com/scummvm/scummvm/commit/8ef78e5e6d787df0f1911314a8cfaec4ac778255
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: Bugfixes for LBH and SP, refactoring
Changed paths:
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_bountyhunter.h
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_crimepatrol.h
engines/alg/logic/game_drugwars.cpp
engines/alg/logic/game_drugwars.h
engines/alg/logic/game_johnnyrock.cpp
engines/alg/logic/game_johnnyrock.h
engines/alg/logic/game_maddog.cpp
engines/alg/logic/game_maddog.h
engines/alg/logic/game_maddog2.cpp
engines/alg/logic/game_maddog2.h
engines/alg/logic/game_spacepirates.cpp
engines/alg/logic/game_spacepirates.h
engines/alg/scene.cpp
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index 27238dcd268..81e8f643a44 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -117,7 +117,7 @@ void GameBountyHunter::init() {
loadLibArchive("bhds.lib");
}
- _sceneInfo->loadScnFile("bh.scn");
+ _sceneInfo->loadScnFile(_vm->isDemo() ? "bhdemo.scn" : "bh.scn");
_startScene = _sceneInfo->getStartScene();
registerScriptFunctions();
@@ -218,8 +218,9 @@ void GameBountyHunter::registerScriptFunctions() {
PRE_OPS_FUNCTION("L1DSETUP", scenePsoDrawRct);
PRE_OPS_FUNCTION("L2ASETUP", scenePsoSetupNdRandom1);
PRE_OPS_FUNCTION("L2BSETUP", scenePsoDrawRct);
- PRE_OPS_FUNCTION("L4A1SETUP", scenePsoDrawRct);
- PRE_OPS_FUNCTION("L4A2SETUP", scenePsoDrawRct);
+ // i have no clue how the original calls these 2, but apparently not via NXSTSCN
+ PRE_OPS_FUNCTION("L4A1SETUP", sceneNxtscnInitRandomKid1);
+ PRE_OPS_FUNCTION("L4A2SETUP", sceneNxtscnInitRandomKid2);
PRE_OPS_FUNCTION("SETUPL3A", scenePsoDrawRct);
PRE_OPS_FUNCTION("SET3SHOT", scenePsoDrawRct);
PRE_OPS_FUNCTION("L3BSETUP", scenePsoDrawRct);
@@ -439,7 +440,7 @@ Common::Error GameBountyHunter::run() {
if (_curScene == oldscene) {
callScriptFunctionScene(NXTFRM, scene->_nxtfrm, scene);
}
- for (int i = 0; i < _numPlayers; i++) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
if (weaponDown()) {
sceneDefaultWepdwn(scene);
}
@@ -466,6 +467,9 @@ Common::Error GameBountyHunter::run() {
int32 remainingMillis = _nextFrameTime - getMsTime();
if (remainingMillis < 10) {
if (_videoDecoder->getCurrentFrame() > 0) {
+ if (_videoDecoder->isFinished()) {
+ break;
+ }
_videoDecoder->getNextFrame();
moveCurrentBag();
}
@@ -489,6 +493,9 @@ Common::Error GameBountyHunter::run() {
if (_curScene == oldscene) {
_curScene = scene->_next;
}
+ if (_curScene == "" && _vm->isDemo()) {
+ setNextScene(387);
+ }
if (_curScene == "") {
shutdown();
}
@@ -521,7 +528,7 @@ uint16 GameBountyHunter::startMyGame() {
_playerScore[0] = _playerScore[1] = 0;
initGameStatus();
if (_vm->isDemo()) {
- startScene = 69; // TODO fix
+ startScene = 387;
} else {
startScene = 69;
}
@@ -541,7 +548,7 @@ void GameBountyHunter::initGameStatus() {
_numSubLevelsDone = 0;
_difficulty = 0;
- _currentSubLevelSceneId = 0x017B;
+ _currentSubLevelSceneId = _selectOpponentScreen;
iconSetup();
iconReset(); // not in original!
}
@@ -662,7 +669,7 @@ void GameBountyHunter::displayShotsLeft(uint8 player) {
return;
}
uint16 posX = player == 0 ? 0xF8 : 0x0C;
- for (int i = 0; i < 10; i++) {
+ for (int i = 0; i < 12; i++) {
AlgGraphics::drawImage(_background, _emptyIcon, posX, 0xBF);
posX += 5;
}
@@ -692,13 +699,12 @@ bool GameBountyHunter::saveState() {
warning("GameBountyHunter::saveState(): Can't create file '%s', game not saved", saveFileName.c_str());
return false;
}
- uint16 currentSceneNum = atoi(_curScene.c_str());
outSaveFile->writeUint32BE(MKTAG('A', 'L', 'G', 'S')); // header
outSaveFile->writeByte(0); // version, unused for now
outSaveFile->writeByte(_currentLevel);
outSaveFile->writeUint16LE(_currentSubLevelSceneId);
outSaveFile->writeByte(_continuesUsed);
- outSaveFile->writeUint16LE(currentSceneNum);
+ outSaveFile->writeUint16LE(_restartScene);
for (int i = 0; i < 2; i++) {
outSaveFile->writeByte(_playerLives[i]);
outSaveFile->writeByte(_playerShots[i]);
@@ -707,6 +713,7 @@ bool GameBountyHunter::saveState() {
outSaveFile->writeByte(_difficulty);
outSaveFile->writeByte(_numPlayers);
outSaveFile->finalize();
+ _restartScene = 0;
delete outSaveFile;
return true;
}
@@ -737,7 +744,6 @@ bool GameBountyHunter::loadState() {
_numPlayers = inSaveFile->readByte();
assert(_numPlayers <= 2);
delete inSaveFile;
- _gameInProgress = true;
return true;
}
@@ -908,8 +914,8 @@ void GameBountyHunter::moveCurrentBag() {
uint16 GameBountyHunter::beginLevel(uint8 levelNumber) {
_currentLevel = levelNumber;
_numSubLevelsDone = 0;
- int index = (levelNumber * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
- uint8 subLevel = _subLevelOrder[index];
+ uint8 subLevelIndex = (levelNumber * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
+ uint8 subLevel = _subLevelOrder[subLevelIndex];
uint16 sceneIndex = (_currentLevel * 5) + subLevel;
uint16 sceneNum = _subLevelSceneIds[sceneIndex];
_currentSubLevelSceneId = sceneNum;
@@ -1007,7 +1013,7 @@ uint16 GameBountyHunter::pickDeathScene() {
uint16 GameBountyHunter::timeForGunfight() {
if (--_gunfightCount <= 0) {
- int index = (_difficulty * 5) + (_numLevelsDone);
+ int index = (_difficulty * 5) + (_numLevelsDone * 2);
_gunfightCount = _gunfightCountDown[index];
return pickGunfightScene();
}
@@ -1016,7 +1022,7 @@ uint16 GameBountyHunter::timeForGunfight() {
void GameBountyHunter::waitingForShootout(uint32 drawFrame) {
if (drawFrame != 0) {
- for (uint i = 0; i < _numPlayers; i++) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
_firstDrawFrame = drawFrame;
_playerShots[i] = 0;
_playerGun[i] = 0;
@@ -1056,9 +1062,8 @@ void GameBountyHunter::rectSave(Rect *rect) {
void GameBountyHunter::rectLoad(Rect *rect) {
if (loadState()) {
playSound(_loadSound);
+ _restartScene = 0;
}
- setNextScene(_restartScene);
- _restartScene = 0;
}
void GameBountyHunter::rectContinue(Rect *rect) {
@@ -1214,7 +1219,7 @@ void GameBountyHunter::scenePsoSetCurrentScene(Scene *scene) {
if (sceneId == 0) {
uint8 index = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
uint8 subLevel = _subLevelOrder[index];
- uint16 picked = (_currentLevel * 10) + subLevel;
+ uint16 picked = (_currentLevel * 5) + subLevel;
_currentSubLevelSceneId = _subLevelSceneIds[picked];
}
}
@@ -1227,7 +1232,7 @@ void GameBountyHunter::sceneIsoShootout(Scene *scene) {
void GameBountyHunter::sceneIsoGivemoney(Scene *scene) {
const int moneyFrames[] = {0x1E8F, 0x3BB4, 0x7814, 0xA287};
const int woundBits[] = {2, 4, 8, 16};
- for (int i = 0; i < _numPlayers; i++) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
if (_currentLevel <= 3) {
uint32 moneyFrame = moneyFrames[_currentLevel];
if (moneyFrame == _currentFrame && !_moneyGiven) {
@@ -1254,8 +1259,8 @@ void GameBountyHunter::sceneNxtscnLoseALife(Scene *scene) {
uint16 picked = 0;
uint8 deadCount = 0;
(void)scene;
- for (int i = 0; i < _numPlayers; i++) {
- if (!_debug_godMode) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
+ if (!_debug_godMode && !_vm->isDemo()) {
_playerLives[i]--;
}
displayLivesLeft(i);
@@ -1289,7 +1294,9 @@ void GameBountyHunter::sceneNxtscnDidNotContinue(Scene *scene) {
void GameBountyHunter::sceneNxtscnKillInnocentMan(Scene *scene) {
uint16 picked = 0;
- _playerLives[_player]--;
+ if (!_debug_godMode) {
+ _playerLives[_player]--;
+ }
if (_playerLives[_player]) {
picked = pickInnocentScene();
} else {
@@ -1307,7 +1314,7 @@ void GameBountyHunter::sceneNxtscnKillInnocentWoman(Scene *scene) {
}
void GameBountyHunter::sceneNxtscnAfterDie(Scene *scene) {
- for (int i = 0; i < _numPlayers; i++) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
if (_playerLives[i] <= 0) {
_playerLives[i] = 3;
displayLivesLeft(i);
@@ -1320,7 +1327,7 @@ void GameBountyHunter::sceneNxtscnGotoLevelSelect(Scene *scene) {
iconReset();
uint16 picked = 0;
if ((_levelDoneMask & 0x1E) != 0x1E) {
- picked = 0x17B;
+ picked = _selectOpponentScreen;
} else if (!(_levelDoneMask & 0x80)) {
picked = 0x66;
} else {
@@ -1351,11 +1358,10 @@ void GameBountyHunter::sceneNxtscnInitRandomHarry2(Scene *scene) {
void GameBountyHunter::sceneNxtscnInitRandomDan1(Scene *scene) {
uint16 picked = 0;
- uint8 picks = _randomScenesPicks[2] + _numPlayers;
if (_numPlayers == 2) {
- picked = pickRandomScene(_randomDan1TwoPlayer, picks);
+ picked = pickRandomScene(_randomDan1TwoPlayer, 5);
} else {
- picked = pickRandomScene(_randomScenes[2], picks);
+ picked = pickRandomScene(_randomScenes[2], _randomScenesPicks[2]);
}
_currentSubLevelSceneId = 0x0174;
setNextScene(picked);
@@ -1390,7 +1396,7 @@ void GameBountyHunter::sceneNxtscnInitRandomKid2(Scene *scene) {
void GameBountyHunter::sceneNxtscnNextSubLevel(Scene *scene) {
iconReset();
_numSubLevelsDone++;
- int subLevelIndex = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
+ uint8 subLevelIndex = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
uint8 subLevel = _subLevelOrder[subLevelIndex];
uint16 sceneIndex = (_currentLevel * 5) + subLevel;
uint16 picked = _subLevelSceneIds[sceneIndex];
@@ -1399,8 +1405,8 @@ void GameBountyHunter::sceneNxtscnNextSubLevel(Scene *scene) {
if (gunfightScene != 0) {
picked = gunfightScene;
}
- else if (subLevel != 2) {
- if (_currentLevel == 0) {
+ else if (subLevel == 2) {
+ if (_currentLevel != 0) {
picked = _clueLevels[_currentLevel];
}
}
@@ -1409,8 +1415,8 @@ void GameBountyHunter::sceneNxtscnNextSubLevel(Scene *scene) {
void GameBountyHunter::sceneNxtscnGotoBadGuy(Scene *scene) {
iconReset();
- uint8 index = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
- uint8 subLevel = _subLevelOrder[index];
+ uint8 subLevelIndex = (_currentLevel * 24) + (_numLevelsDone * 6) + _numSubLevelsDone;
+ uint8 subLevel = _subLevelOrder[subLevelIndex];
uint16 sceneIndex = (_currentLevel * 5) + subLevel;
uint16 picked = _subLevelSceneIds[sceneIndex];
setNextScene(picked);
@@ -1429,7 +1435,7 @@ void GameBountyHunter::sceneNxtscnAutoSelectLevel(Scene *scene) {
}
void GameBountyHunter::sceneNxtscnSelectScenario(Scene *scene) {
- setNextScene(_currentLevel);
+ // do nothing
}
void GameBountyHunter::sceneNxtscnFinishScenario(Scene *scene) {
@@ -1443,12 +1449,12 @@ void GameBountyHunter::sceneNxtscnGameWon(Scene *scene) {
void GameBountyHunter::sceneNxtscnKilledMain(Scene *scene) {
_wounded = false;
- _subScene = "scene379";
+ _currentSubLevelSceneId = _selectOpponentScreen;
}
void GameBountyHunter::sceneNxtscnWoundedMain(Scene *scene) {
_wounded = true;
- _subScene = "scene379";
+ _currentSubLevelSceneId = _selectOpponentScreen;
}
void GameBountyHunter::sceneNxtscnEndLevel(Scene *scene) {
@@ -1463,7 +1469,7 @@ void GameBountyHunter::sceneNxtscnEndLevel(Scene *scene) {
setNextScene(0x66);
return;
}
- setNextScene(0x017B);
+ setNextScene(_selectOpponentScreen);
}
void GameBountyHunter::sceneNxtscnEndGame(Scene *scene) {
@@ -1495,8 +1501,8 @@ void GameBountyHunter::sceneNxtscnDiedRefed(Scene *scene) {
uint16 picked = 0;
uint8 deadCount = 0;
(void)scene;
- for (uint i = 0; i < _numPlayers; i++) {
- if (!_debug_godMode) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
+ if (!_debug_godMode && !_vm->isDemo()) {
_playerLives[i]--;
}
displayLivesLeft(i);
@@ -1516,7 +1522,7 @@ void GameBountyHunter::sceneNxtscnDiedRefed(Scene *scene) {
void GameBountyHunter::sceneNxtscnGiveShotgun(Scene *scene) {
(void)scene;
- for (uint i = 0; i < _numPlayers; i++) {
+ for (uint8 i = 0; i < _numPlayers; i++) {
_playerShots[i] = 5;
_playerGun[i] = 2;
displayShotsLeft(i);
@@ -1579,8 +1585,41 @@ void GameBountyHunter::debug_drawZoneRects() {
}
}
-void GameBountyHunter::debugWarpTo(int val) {
- // TODO implement
+void GameBountyHunter::debug_warpTo(int val) {
+ if (_vm->isDemo()) {
+ return;
+ }
+ startMyGame();
+ switch (val) {
+ case 0:
+ setNextScene(69);
+ break;
+ case 1:
+ setNextScene(_selectOpponentScreen);
+ break;
+ case 2:
+ _levelDoneMask = 2;
+ _numLevelsDone = 1;
+ setNextScene(_selectOpponentScreen);
+ break;
+ case 3:
+ _levelDoneMask = 2 | 4;
+ _numLevelsDone = 2;
+ setNextScene(_selectOpponentScreen);
+ break;
+ case 4:
+ _levelDoneMask = 2 | 4 | 8;
+ _numLevelsDone = 3;
+ setNextScene(_selectOpponentScreen);
+ break;
+ case 5:
+ _levelDoneMask = 2 | 4 | 8 | 0x10;
+ _numLevelsDone = 4;
+ setNextScene(0x66);
+ break;
+ default:
+ break;
+ }
}
// Debugger methods
@@ -1595,11 +1634,11 @@ DebuggerBountyHunter::DebuggerBountyHunter(GameBountyHunter *game) {
bool DebuggerBountyHunter::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
return false;
}
}
diff --git a/engines/alg/logic/game_bountyhunter.h b/engines/alg/logic/game_bountyhunter.h
index cbd1c79a2de..72d16bfb1ea 100644
--- a/engines/alg/logic/game_bountyhunter.h
+++ b/engines/alg/logic/game_bountyhunter.h
@@ -55,7 +55,7 @@ public:
GameBountyHunter(AlgEngine *vm, const AlgGameDescription *gd);
~GameBountyHunter() override;
Common::Error run() override;
- void debugWarpTo(int val);
+ void debug_warpTo(int val);
private:
void init() override;
@@ -133,7 +133,7 @@ private:
const uint16 _deathScenarios[9] = {0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0};
const uint16 _onePlayerOfTwoDead[2] = {0x0109, 0x010A};
const uint16 _allPlayersDead = 0x108;
-
+ const uint16 _selectOpponentScreen = 0x017B;
// gamestate
uint8 _continuesUsed = 0;
uint8 _currentLevel = 0;
@@ -194,8 +194,6 @@ private:
bool _shotgunGiven = false;
bool _bagDropped = false;
- Common::String _subScene;
-
// base functions
void updateScreen() override;
uint16 startMyGame();
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index 20c106832d3..9003fcdcfea 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -1365,8 +1365,18 @@ void GameCrimePatrol::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameCrimePatrol::debugWarpTo(int val) {
- // TODO implement
+void GameCrimePatrol::debug_warpTo(int val) {
+ if (_vm->isDemo()) {
+ return;
+ }
+ resetParams();
+ if (val > 0 && val <= 14) {
+ for (uint8 i = 0; i < val; i++) {
+ sceneNxtscnGeneric(i);
+ }
+ } else if (val == 0) {
+ _curScene = Common::String::format("scene%d", _stageStartScenes[0]);
+ }
}
void GameCrimePatrol::debugDrawPracticeRects() {
@@ -1401,11 +1411,11 @@ DebuggerCrimePatrol::DebuggerCrimePatrol(GameCrimePatrol *game) {
bool DebuggerCrimePatrol::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
return false;
}
}
diff --git a/engines/alg/logic/game_crimepatrol.h b/engines/alg/logic/game_crimepatrol.h
index 628a181fd60..619aa2c6280 100644
--- a/engines/alg/logic/game_crimepatrol.h
+++ b/engines/alg/logic/game_crimepatrol.h
@@ -53,7 +53,7 @@ public:
GameCrimePatrol(AlgEngine *vm, const AlgGameDescription *gd);
~GameCrimePatrol() override;
void init() override;
- void debugWarpTo(int val);
+ void debug_warpTo(int val);
private:
Common::Error run() override;
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index 87595d136ae..8700c0ccbca 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -688,41 +688,6 @@ uint16 GameDrugWars::pickDeathScene() {
return _diedScenesByStage[_stage][_deathPicked];
}
-void GameDrugWars::sceneNxtscnGeneric(uint8 index) {
- uint16 nextSceneId = 0;
- _gotTo[index] = 0;
- if (_gotTo[0] || _gotTo[1] || _gotTo[3] || _gotTo[2]) {
- nextSceneId = 0x26;
- } else if (_gotTo[4] || _gotTo[5] || _gotTo[6]) {
- if (_stage == 1) {
- nextSceneId = 0x52;
- } else {
- _stage = 1;
- nextSceneId = 0x50;
- }
- } else if (_gotTo[7] || _gotTo[8] || _gotTo[9]) {
- if (_stage == 2) {
- nextSceneId = 0x9A;
- } else {
- _stage = 2;
- nextSceneId = 0x81;
- }
- } else if (_gotTo[10] || _gotTo[11] || _gotTo[12]) {
- if (_stage == 3) {
- nextSceneId = 0xDF;
- } else {
- _stage = 3;
- nextSceneId = 0x14B;
- }
- } else if (_gotTo[13]) {
- _stage = 4;
- nextSceneId = 0x18F;
- } else {
- nextSceneId = 0x21;
- }
- _curScene = Common::String::format("scene%d", nextSceneId);
-}
-
void GameDrugWars::rectSelectGeneric(uint8 index) {
if (_gotTo[index] > 0) {
_curScene = Common::String::format("scene%d", _gotTo[index]);
@@ -1062,8 +1027,19 @@ void GameDrugWars::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameDrugWars::debugWarpTo(int val) {
- // TODO implement
+void GameDrugWars::debug_warpTo(int val) {
+ if (_vm->isDemo()) {
+ return;
+ }
+ resetParams();
+ if (val > 0 && val <= 14) {
+ for (uint8 i = 0; i < val; i++) {
+ _gotTo[i] = 0;
+ sceneNxtscnFinishScenario(nullptr);
+ }
+ } else if (val == 0) {
+ _curScene = Common::String::format("scene%d", _stageStartScenes[0]);
+ }
}
// Debugger methods
@@ -1078,11 +1054,11 @@ DebuggerDrugWars::DebuggerDrugWars(GameDrugWars *game) {
bool DebuggerDrugWars::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
return false;
}
}
diff --git a/engines/alg/logic/game_drugwars.h b/engines/alg/logic/game_drugwars.h
index da67b8760b9..43a077a2244 100644
--- a/engines/alg/logic/game_drugwars.h
+++ b/engines/alg/logic/game_drugwars.h
@@ -53,7 +53,7 @@ public:
GameDrugWars(AlgEngine *vm, const AlgGameDescription *gd);
~GameDrugWars() override;
Common::Error run() override;
- void debugWarpTo(int val);
+ void debug_warpTo(int val);
private:
void init() override;
@@ -170,7 +170,6 @@ private:
uint16 randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude);
uint16 pickRandomScene(uint8 index, uint8 max);
uint16 pickDeathScene();
- void sceneNxtscnGeneric(uint8 index);
void rectSelectGeneric(uint8 index);
// Script functions: RectHit
diff --git a/engines/alg/logic/game_johnnyrock.cpp b/engines/alg/logic/game_johnnyrock.cpp
index 0cf0903543c..cc20fcd65ab 100644
--- a/engines/alg/logic/game_johnnyrock.cpp
+++ b/engines/alg/logic/game_johnnyrock.cpp
@@ -339,7 +339,7 @@ Common::Error GameJohnnyRock::run() {
_currentFrame = getFrame(scene);
while (_currentFrame <= scene->_endFrame && _curScene == oldscene && !_vm->shouldQuit()) {
updateMouse();
- // TODO: call scene->messageFunc
+ callScriptFunctionScene(SHOWMSG, scene->_scnmsg, scene);
callScriptFunctionScene(INSOP, scene->_insop, scene);
_holster = weaponDown();
if (_holster) {
@@ -1852,8 +1852,18 @@ void GameJohnnyRock::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameJohnnyRock::debugWarpTo(int val) {
- // TODO implement
+void GameJohnnyRock::debug_warpTo(int val) {
+ resetParams();
+ switch (val) {
+ case 0:
+ _curScene = _startScene;
+ break;
+ case 1:
+ _curScene = "scene175";
+ break;
+ default:
+ break;
+ }
}
// Debugger methods
@@ -1868,11 +1878,11 @@ DebuggerJohnnyRock::DebuggerJohnnyRock(GameJohnnyRock *game) {
bool DebuggerJohnnyRock::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
return false;
}
}
diff --git a/engines/alg/logic/game_johnnyrock.h b/engines/alg/logic/game_johnnyrock.h
index 3a92ece666f..ba27a2f4717 100644
--- a/engines/alg/logic/game_johnnyrock.h
+++ b/engines/alg/logic/game_johnnyrock.h
@@ -55,8 +55,8 @@ public:
GameJohnnyRock(AlgEngine *vm, const AlgGameDescription *gd);
~GameJohnnyRock() override;
Common::Error run() override;
- void debugWarpTo(int val);
void runCursorTimer();
+ void debug_warpTo(int val);
private:
void init() override;
diff --git a/engines/alg/logic/game_maddog.cpp b/engines/alg/logic/game_maddog.cpp
index ef0723c7b44..98e3cbedecc 100644
--- a/engines/alg/logic/game_maddog.cpp
+++ b/engines/alg/logic/game_maddog.cpp
@@ -360,7 +360,7 @@ Common::Error GameMaddog::run() {
_currentFrame = getFrame(scene);
while (_currentFrame <= scene->_endFrame && _curScene == oldscene && !_vm->shouldQuit()) {
updateMouse();
- // TODO: call scene->messageFunc
+ callScriptFunctionScene(SHOWMSG, scene->_scnmsg, scene);
callScriptFunctionScene(INSOP, scene->_insop, scene);
_holster = weaponDown();
if (_holster) {
@@ -1616,21 +1616,26 @@ void GameMaddog::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameMaddog::debugWarpTo(int val) {
+void GameMaddog::debug_warpTo(int val) {
+ resetParams();
switch (val) {
case 0:
_beenTo = 0;
- _curScene = "scene28";
+ _curScene = _startScene;
break;
case 1:
+ _beenTo = 0;
+ _curScene = "scene28";
+ break;
+ case 2:
_beenTo = 1;
_curScene = pickTown();
break;
- case 2:
+ case 3:
_beenTo = 15;
_curScene = pickTown();
break;
- case 3:
+ case 4:
_beenTo = 575;
// always go right
_map0 = -1;
@@ -1638,16 +1643,16 @@ void GameMaddog::debugWarpTo(int val) {
_map2 = -1;
_curScene = pickTown();
break;
- case 4:
+ case 5:
_beenTo = 575;
_hideOutFront = true; // go to front
_curScene = "scene210";
break;
- case 5:
+ case 6:
_beenTo = 639;
_curScene = "scene227";
break;
- case 6:
+ case 7:
_beenTo = 1023;
_curScene = "scene250";
break;
@@ -1668,11 +1673,19 @@ DebuggerMaddog::DebuggerMaddog(GameMaddog *game) {
bool DebuggerMaddog::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
+ if (val == 4) {
+ debugPrintf("Hint: Always go right\n");
+ return true;
+ }
+ if (val == 5) {
+ debugPrintf("Hint: Go to front of hideout\n");
+ return true;
+ }
return false;
}
}
diff --git a/engines/alg/logic/game_maddog.h b/engines/alg/logic/game_maddog.h
index 5a1c87435c7..7d0751726b9 100644
--- a/engines/alg/logic/game_maddog.h
+++ b/engines/alg/logic/game_maddog.h
@@ -55,8 +55,8 @@ public:
GameMaddog(AlgEngine *vm, const AlgGameDescription *gd);
~GameMaddog() override;
Common::Error run() override;
- void debugWarpTo(int val);
void runCursorTimer();
+ void debug_warpTo(int val);
private:
void init() override;
diff --git a/engines/alg/logic/game_maddog2.cpp b/engines/alg/logic/game_maddog2.cpp
index 5d3eed11aed..f6868f9b351 100644
--- a/engines/alg/logic/game_maddog2.cpp
+++ b/engines/alg/logic/game_maddog2.cpp
@@ -368,7 +368,7 @@ Common::Error GameMaddog2::run() {
_currentFrame = getFrame(scene);
while (_currentFrame <= scene->_endFrame && _curScene == oldscene && !_vm->shouldQuit()) {
updateMouse();
- // TODO: call scene->messageFunc
+ callScriptFunctionScene(SHOWMSG, scene->_scnmsg, scene);
callScriptFunctionScene(INSOP, scene->_insop, scene);
_holster = weaponDown();
if (_holster) {
@@ -1806,8 +1806,30 @@ void GameMaddog2::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameMaddog2::debugWarpTo(int val) {
- // TODO implement
+void GameMaddog2::debug_warpTo(int val) {
+ resetParams();
+ switch (val) {
+ case 0:
+ _curScene = _startScene;
+ break;
+ case 1:
+ _curScene = "scene50";
+ break;
+ case 2:
+ _doneGuide = 1;
+ _curScene = "scene50";
+ break;
+ case 3:
+ _doneGuide = 1 | 2;
+ _curScene = "scene50";
+ break;
+ case 4:
+ _doneGuide = 1 | 2 | 4;
+ _curScene = "scene290";
+ break;
+ default:
+ break;
+ }
}
// Debugger methods
@@ -1822,11 +1844,11 @@ DebuggerMaddog2::DebuggerMaddog2(GameMaddog2 *game) {
bool DebuggerMaddog2::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
return false;
}
}
diff --git a/engines/alg/logic/game_maddog2.h b/engines/alg/logic/game_maddog2.h
index 4113347cb7c..b0f575b55fd 100644
--- a/engines/alg/logic/game_maddog2.h
+++ b/engines/alg/logic/game_maddog2.h
@@ -55,8 +55,8 @@ public:
GameMaddog2(AlgEngine *vm, const AlgGameDescription *gd);
~GameMaddog2() override;
Common::Error run() override;
- void debugWarpTo(int val);
void runCursorTimer();
+ void debug_warpTo(int val);
private:
void init() override;
diff --git a/engines/alg/logic/game_spacepirates.cpp b/engines/alg/logic/game_spacepirates.cpp
index 6c50e2a7b12..329c4c7885e 100644
--- a/engines/alg/logic/game_spacepirates.cpp
+++ b/engines/alg/logic/game_spacepirates.cpp
@@ -425,6 +425,9 @@ Common::Error GameSpacePirates::run() {
int32 remainingMillis = _nextFrameTime - getMsTime();
if (remainingMillis < 10) {
if (_videoDecoder->getCurrentFrame() > 0) {
+ if (_videoDecoder->isFinished()) {
+ break;
+ }
_videoDecoder->getNextFrame();
}
remainingMillis = _nextFrameTime - getMsTime();
@@ -1267,6 +1270,7 @@ void GameSpacePirates::rectShotBlueCrystal(Rect *rect) {
}
void GameSpacePirates::rectShotGreenCrystal(Rect *rect) {
+ debug("rectShotGreenCrystal");
uint16 picked = 0;
displayShotFiredImage();
playSound(_shotSound);
@@ -1296,6 +1300,7 @@ void GameSpacePirates::rectShotGreenCrystal(Rect *rect) {
}
}
_nextSceneFound = true;
+ debug("rectShotGreenCrystal picked: %d", picked);
_curScene = Common::String::format("scene%d", picked);
}
@@ -1336,8 +1341,6 @@ void GameSpacePirates::rectSkipScene(Rect *rect) {
displayShotFiredImage();
playSound(_shotSound);
_nextSceneFound = true;
- Scene *scene = _sceneInfo->findScene(_curScene);
- _curScene = scene->_next;
}
void GameSpacePirates::rectHitPirateShip(Rect *rect) {
@@ -1989,8 +1992,56 @@ void GameSpacePirates::sceneDefaultScore(Scene *scene) {
}
// Debug methods
-void GameSpacePirates::debugWarpTo(int val) {
- // TODO implement
+void GameSpacePirates::debug_warpTo(int val) {
+ if (_vm->isDemo()) {
+ return;
+ }
+ resetParams();
+ switch (val) {
+ case 0:
+ _curScene = "scene187";
+ break;
+ case 1:
+ _curScene = "scene110";
+ _pickedStartSplitter = 0x6A;
+ break;
+ case 2:
+ _worldDone[0] = true;
+ _pickedStartSplitter = 0x6A;
+ _curScene = "scene110";
+ break;
+ case 3:
+ _worldDone[0] = true;
+ _worldDone[1] = true;
+ _pickedStartSplitter = 0x6A;
+ _curScene = "scene110";
+ break;
+ case 4:
+ _worldDone[0] = true;
+ _worldDone[1] = true;
+ _worldDone[2] = true;
+ _pickedStartSplitter = 0x6A;
+ _curScene = "scene110";
+ break;
+ case 5:
+ _worldDone[0] = true;
+ _worldDone[1] = true;
+ _worldDone[2] = true;
+ _worldDone[3] = true;
+ _pickedStartSplitter = 0x6A;
+ _curScene = "scene192";
+ break;
+ case 6:
+ _worldDone[0] = true;
+ _worldDone[1] = true;
+ _worldDone[2] = true;
+ _worldDone[3] = true;
+ _pickedStartSplitter = 0x6A;
+ _curScene = "scene334";
+ break;
+ default:
+ break;
+ }
}
// Debugger methods
@@ -2005,11 +2056,15 @@ DebuggerSpacePirates::DebuggerSpacePirates(GameSpacePirates *game) {
bool DebuggerSpacePirates::cmdWarpTo(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Usage: warp <int>");
+ debugPrintf("Usage: warp <int>\n");
return true;
} else {
int val = atoi(argv[1]);
- _game->debugWarpTo(val);
+ _game->debug_warpTo(val);
+ if (val >= 1 && val <= 5) {
+ debugPrintf("Hint: Crystal shoot order: red, green, blue\n");
+ return true;
+ }
return false;
}
}
diff --git a/engines/alg/logic/game_spacepirates.h b/engines/alg/logic/game_spacepirates.h
index 054cb9759e9..3faed264848 100644
--- a/engines/alg/logic/game_spacepirates.h
+++ b/engines/alg/logic/game_spacepirates.h
@@ -54,7 +54,7 @@ public:
GameSpacePirates(AlgEngine *vm, const AlgGameDescription *gd);
~GameSpacePirates() override;
Common::Error run() override;
- void debugWarpTo(int val);
+ void debug_warpTo(int val);
private:
void init() override;
diff --git a/engines/alg/scene.cpp b/engines/alg/scene.cpp
index 3e447c7180b..0e82b38ab94 100644
--- a/engines/alg/scene.cpp
+++ b/engines/alg/scene.cpp
@@ -250,7 +250,7 @@ void SceneInfo::addZonesToScenes() {
if (!scene->_zonesStart.empty()) {
Zone *zone = findZone(scene->_zonesStart);
while (true) {
- if (zone) {
+ if (zone != nullptr) {
zone = zone->clone();
zone->_difficulty = 0;
scene->_zones.push_back(zone);
@@ -259,13 +259,16 @@ void SceneInfo::addZonesToScenes() {
break;
} else {
zone = findZone(zone->_next);
+ if (zone == nullptr) {
+ break;
+ }
}
}
}
if (!scene->_zonesStart2.empty()) {
Zone *zone = findZone(scene->_zonesStart);
while (true) {
- if (zone) {
+ if (zone != nullptr) {
zone = zone->clone();
zone->_difficulty = 1;
scene->_zones.push_back(zone);
@@ -274,13 +277,16 @@ void SceneInfo::addZonesToScenes() {
break;
} else {
zone = findZone(zone->_next);
+ if (zone == nullptr) {
+ break;
+ }
}
}
}
if (!scene->_zonesStart3.empty()) {
Zone *zone = findZone(scene->_zonesStart);
while (true) {
- if (zone) {
+ if (zone != nullptr) {
zone = zone->clone();
zone->_difficulty = 2;
scene->_zones.push_back(zone);
@@ -289,6 +295,9 @@ void SceneInfo::addZonesToScenes() {
break;
} else {
zone = findZone(zone->_next);
+ if (zone == nullptr) {
+ break;
+ }
}
}
}
Commit: 90a83d7322208c5b2782d1dffd7cdaa63bcce255
https://github.com/scummvm/scummvm/commit/90a83d7322208c5b2782d1dffd7cdaa63bcce255
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: minor style cleanup
Changed paths:
engines/alg/logic/game_bountyhunter.cpp
engines/alg/logic/game_crimepatrol.cpp
engines/alg/logic/game_drugwars.cpp
diff --git a/engines/alg/logic/game_bountyhunter.cpp b/engines/alg/logic/game_bountyhunter.cpp
index 81e8f643a44..65a01d01f49 100644
--- a/engines/alg/logic/game_bountyhunter.cpp
+++ b/engines/alg/logic/game_bountyhunter.cpp
@@ -933,7 +933,7 @@ uint16 GameBountyHunter::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude
}
uint16 randomNum = 0;
// find an unused random number
- while (1) {
+ while (true) {
randomNum = _rnd->getRandomNumber(max - 1);
// check if bit is already used
uint16 bit = 1 << randomNum;
diff --git a/engines/alg/logic/game_crimepatrol.cpp b/engines/alg/logic/game_crimepatrol.cpp
index 9003fcdcfea..e773eaaa2f7 100644
--- a/engines/alg/logic/game_crimepatrol.cpp
+++ b/engines/alg/logic/game_crimepatrol.cpp
@@ -688,7 +688,7 @@ uint16 GameCrimePatrol::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude)
}
uint16 randomNum = 0;
// find an unused random number
- while (1) {
+ while (true) {
randomNum = _rnd->getRandomNumber(max - 1);
// check if bit is already used
uint16 bit = 1 << randomNum;
diff --git a/engines/alg/logic/game_drugwars.cpp b/engines/alg/logic/game_drugwars.cpp
index 8700c0ccbca..664f593a886 100644
--- a/engines/alg/logic/game_drugwars.cpp
+++ b/engines/alg/logic/game_drugwars.cpp
@@ -640,7 +640,7 @@ uint16 GameDrugWars::randomUnusedInt(uint8 max, uint16 *mask, uint16 exclude) {
}
uint16 randomNum = 0;
// find an unused random number
- while (1) {
+ while (true) {
randomNum = _rnd->getRandomNumber(max - 1);
// check if bit is already used
uint16 bit = 1 << randomNum;
Commit: 597d22e7f05b8e358849167f50e4a9e944c7ceb6
https://github.com/scummvm/scummvm/commit/597d22e7f05b8e358849167f50e4a9e944c7ceb6
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: fix clang warnings of unused fields
Changed paths:
engines/alg/logic/game_bountyhunter.h
engines/alg/logic/game_johnnyrock.h
diff --git a/engines/alg/logic/game_bountyhunter.h b/engines/alg/logic/game_bountyhunter.h
index 72d16bfb1ea..eb962a1e376 100644
--- a/engines/alg/logic/game_bountyhunter.h
+++ b/engines/alg/logic/game_bountyhunter.h
@@ -139,7 +139,6 @@ private:
uint8 _currentLevel = 0;
uint16 _currentSubLevelSceneId = 0;
uint8 _difficulty = 0;
- uint8 _oldDifficulty = 1;
uint32 _firstDrawFrame = 0;
int8 _gunfightCount = 0;
uint8 _kill3Count = 0;
diff --git a/engines/alg/logic/game_johnnyrock.h b/engines/alg/logic/game_johnnyrock.h
index ba27a2f4717..c9e66b7c336 100644
--- a/engines/alg/logic/game_johnnyrock.h
+++ b/engines/alg/logic/game_johnnyrock.h
@@ -119,8 +119,6 @@ private:
bool _holster = false;
uint8 _oldDifficulty = 1;
uint8 _inHolster = 0;
- int8 _lives = 0;
- int8 _oldLives = 0;
int32 _score = 0;
int32 _oldScore = -1;
bool _shotFired = false;
Commit: 854c9aa33b267765d2c4f07265a1ac69e714e04e
https://github.com/scummvm/scummvm/commit/854c9aa33b267765d2c4f07265a1ac69e714e04e
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: bugfix, do not assign int to string
Changed paths:
engines/alg/scene.cpp
diff --git a/engines/alg/scene.cpp b/engines/alg/scene.cpp
index 0e82b38ab94..ce7f44b9f19 100644
--- a/engines/alg/scene.cpp
+++ b/engines/alg/scene.cpp
@@ -147,8 +147,8 @@ void SceneInfo::parseScene(const Common::String &sceneName, uint32 startFrame, u
scene->_dataParam2 = atoi(tokenizer.nextToken().c_str());
scene->_dataParam3 = atoi(tokenizer.nextToken().c_str());
scene->_dataParam4 = atoi(tokenizer.nextToken().c_str());
- scene->_dataParam5 = atoi(tokenizer.nextToken().c_str());
- scene->_dataParam6 = atoi(tokenizer.nextToken().c_str());
+ scene->_dataParam5 = tokenizer.nextToken().c_str();
+ scene->_dataParam6 = tokenizer.nextToken().c_str();
break;
case 11: // DIFF
scene->_diff = atoi(tokenizer.nextToken().c_str());
Commit: 8e49de7a26555f34fb6fcabe9e913d8f6c67c315
https://github.com/scummvm/scummvm/commit/8e49de7a26555f34fb6fcabe9e913d8f6c67c315
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: add GUIO docs
Changed paths:
doc/docportal/settings/game.rst
diff --git a/doc/docportal/settings/game.rst b/doc/docportal/settings/game.rst
index d40311c520d..7ecdda0d6a4 100644
--- a/doc/docportal/settings/game.rst
+++ b/doc/docportal/settings/game.rst
@@ -204,6 +204,22 @@ High Quality
,,,,,,
+.. _ALG:
+
+ALG
+******************
+
+.. _single_speed_videos:
+
+Use lower quality single speed CD-ROM video
+ Some games come with videos in single and double CD-ROM speed.
+ The double CD-ROM speed videos are of slightly higher quality and bandwith.
+ By default the double speed videos are used, this toggle changes to single speed videos.
+
+ *single_speed_videos*
+
+,,,,,,
+
.. _BLADERUNNER:
Bladerunner
Commit: d3b5625ea2c22e260585df53e55a19bd766e96b4
https://github.com/scummvm/scummvm/commit/d3b5625ea2c22e260585df53e55a19bd766e96b4
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
ALG: enable build-by-default
Changed paths:
engines/alg/configure.engine
diff --git a/engines/alg/configure.engine b/engines/alg/configure.engine
index a9e02e7404c..eba92b7709f 100644
--- a/engines/alg/configure.engine
+++ b/engines/alg/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
-add_engine alg "American Laser Games" no
+add_engine alg "American Laser Games" yes
Commit: 7a5326ad82f3a5991d4435d1f2003641481132e5
https://github.com/scummvm/scummvm/commit/7a5326ad82f3a5991d4435d1f2003641481132e5
Author: loki (loki at localhost)
Date: 2026-03-01T13:20:13+01:00
Commit Message:
NEWS: add ALG games
Changed paths:
NEWS.md
diff --git a/NEWS.md b/NEWS.md
index d1d5f076656..dc48febd1fb 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,6 +3,12 @@ For a more comprehensive changelog of the latest experimental code, see:
#### 2026.1.1 (2026-XX-XX)
+ New games:
+ - Added ALG engine for DOS versions of American Laser Games:
+ Crime Patrol, Crime Patrol 2: Drug Wars, The Last Bounty Hunter,
+ Mad Dog McCree, Mad Dog II: The Lost Gold, Space Pirates
+ and Who Shot Johnny Rock?.
+
General:
- Improved PC-Speaker emulation.
- Implemented multiselect in the GUI launcher games list.
More information about the Scummvm-git-logs
mailing list