[Scummvm-git-logs] scummvm master -> e9f7121d7a764c19207b647a09f1d653bb827475
mduggan
noreply at scummvm.org
Fri Jul 26 11:14:25 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
e9f7121d7a DGDS: Implement HoC shell game
Commit: e9f7121d7a764c19207b647a09f1d653bb827475
https://github.com/scummvm/scummvm/commit/e9f7121d7a764c19207b647a09f1d653bb827475
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-07-26T21:12:08+10:00
Commit Message:
DGDS: Implement HoC shell game
Changed paths:
A engines/dgds/shell_game.cpp
A engines/dgds/shell_game.h
engines/dgds/ads.cpp
engines/dgds/clock.cpp
engines/dgds/dgds.cpp
engines/dgds/dgds.h
engines/dgds/dialog.cpp
engines/dgds/globals.cpp
engines/dgds/globals.h
engines/dgds/image.h
engines/dgds/inventory.cpp
engines/dgds/menu.cpp
engines/dgds/module.mk
engines/dgds/request.cpp
engines/dgds/scene.cpp
engines/dgds/scene.h
engines/dgds/ttm.cpp
diff --git a/engines/dgds/ads.cpp b/engines/dgds/ads.cpp
index 83ce852fcce..e8a8c817b03 100644
--- a/engines/dgds/ads.cpp
+++ b/engines/dgds/ads.cpp
@@ -379,11 +379,11 @@ bool ADSInterpreter::logicOpResult(uint16 code, const TTMEnviro *env, const TTMS
// FIXME: This should be right but we only have detail 0/1 and maybe HOC onward use
// different numbers? HOC intro checks for >= 4.
return false;
- //return ((int)static_cast<DgdsEngine *>(g_engine)->getDetailLevel() <= arg);
+ //return ((int)DgdsEngine::getInstance()->getDetailLevel() <= arg);
case 0x1390: // IF_DETAIL_GTE, 1 param
debugN(10, "ADS 0x%04x: if detail >= %d", code, arg);
return true;
- //return ((int)static_cast<DgdsEngine *>(g_engine)->getDetailLevel() >= arg);
+ //return ((int)DgdsEngine::getInstance()->getDetailLevel() >= arg);
default:
error("Not an ADS logic op: %04x, how did we get here?", code);
}
diff --git a/engines/dgds/clock.cpp b/engines/dgds/clock.cpp
index eba993dde72..714543b4ce3 100644
--- a/engines/dgds/clock.cpp
+++ b/engines/dgds/clock.cpp
@@ -123,7 +123,7 @@ void Clock::draw(Graphics::ManagedSurface &surf) {
const Common::String clockStr = getTimeStr();
- const FontManager *fontman = static_cast<DgdsEngine *>(g_engine)->getFontMan();
+ const FontManager *fontman = DgdsEngine::getInstance()->getFontMan();
const DgdsFont *font = fontman->getFont(FontManager::k4x5Font);
int width = font->getMaxCharWidth() * 12 + 3;
_drawPos.top = 0;
diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index 175faec057e..f931d9a751b 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -79,7 +79,7 @@ const byte DgdsEngine::HOC_CHAR_SWAP_ICONS[] = { 0, 20, 21, 22 };
DgdsEngine::DgdsEngine(OSystem *syst, const ADGameDescription *gameDesc)
: Engine(syst), _fontManager(nullptr), _console(nullptr), _inventory(nullptr),
- _soundPlayer(nullptr), _decompressor(nullptr), _scene(nullptr),
+ _soundPlayer(nullptr), _decompressor(nullptr), _scene(nullptr), _shellGame(nullptr),
_gdsScene(nullptr), _resource(nullptr), _gamePals(nullptr), _gameGlobals(nullptr),
_detailLevel(kDgdsDetailHigh), _textSpeed(1), _justChangedScene1(false), _justChangedScene2(false),
_random("dgds"), _currentCursor(-1), _menuToTrigger(kMenuNone), _isLoading(true),
@@ -123,6 +123,7 @@ DgdsEngine::~DgdsEngine() {
delete _fontManager;
delete _menu;
delete _inventory;
+ delete _shellGame;
_icons.reset();
_corners.reset();
@@ -325,6 +326,8 @@ void DgdsEngine::init(bool restarting) {
_menu = new Menu();
_adsInterp = new ADSInterpreter(this);
_inventory = new Inventory();
+ if (_gameId == GID_HOC)
+ _shellGame = new ShellGame();
_backgroundBuffer.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_storedAreaBuffer.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
diff --git a/engines/dgds/dgds.h b/engines/dgds/dgds.h
index 28928d23489..6a8409813ed 100644
--- a/engines/dgds/dgds.h
+++ b/engines/dgds/dgds.h
@@ -58,6 +58,7 @@ class Menu;
struct DgdsADS;
class ADSInterpreter;
class Globals;
+class ShellGame;
const float MS_PER_FRAME = 16.6667f;
@@ -116,6 +117,9 @@ private:
Globals *_gameGlobals;
Inventory *_inventory;
+ // HoC only
+ ShellGame *_shellGame;
+
FontManager *_fontManager;
Common::SharedPtr<Image> _corners;
Common::SharedPtr<Image> _icons;
@@ -212,6 +216,9 @@ public:
const Common::String &getBackgroundFile() const { return _backgroundFile; }
void setMenuToTrigger(MenuId menu) { _menuToTrigger = menu; }
bool isInvButtonVisible() const;
+ ShellGame *getShellGame() { return _shellGame; }
+
+ static DgdsEngine *getInstance() { return static_cast<DgdsEngine *>(g_engine); }
private:
Common::Error syncGame(Common::Serializer &s);
diff --git a/engines/dgds/dialog.cpp b/engines/dgds/dialog.cpp
index f85065039f5..d628ee7bb9a 100644
--- a/engines/dgds/dialog.cpp
+++ b/engines/dgds/dialog.cpp
@@ -85,7 +85,7 @@ static void _drawPixel(int x, int y, int color, void *data) {
const DgdsFont *Dialog::getDlgTextFont() const {
- const FontManager *fontman = static_cast<DgdsEngine *>(g_engine)->getFontMan();
+ const FontManager *fontman = DgdsEngine::getInstance()->getFontMan();
FontManager::FontType fontType = FontManager::kGameDlgFont;
if (_fontSize == 1)
fontType = FontManager::k8x8Font;
@@ -193,7 +193,7 @@ void Dialog::drawType2(Graphics::ManagedSurface *dst, DialogDrawStage stage) {
// Special case for HoC to update the Shekel count in their description.
// This is how the original game does it too.
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (_fileNum == 0x5d && _num == 0x32 && engine->getGameId() == GID_HOC) {
int16 shekels = engine->getGDSScene()->getGlobal(44);
const Common::String numstr = Common::String::format("%3d", shekels);
@@ -620,7 +620,7 @@ void Dialog::updateSelectedAction(int delta) {
}
struct DialogAction *Dialog::pickAction(bool isClosing, bool isForceClose) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (!isForceClose && isClosing) {
if (_action.empty())
return nullptr;
diff --git a/engines/dgds/globals.cpp b/engines/dgds/globals.cpp
index f67f32b8692..6b3d0164e46 100644
--- a/engines/dgds/globals.cpp
+++ b/engines/dgds/globals.cpp
@@ -37,7 +37,7 @@ public:
GameIsInteractiveGlobal(uint16 num, int16 *ptr) : Global(num), _ptr(ptr), _isSetOff(false) {}
int16 get() override {
- SDSScene *scene = static_cast<DgdsEngine *>(g_engine)->getScene();
+ SDSScene *scene = DgdsEngine::getInstance()->getScene();
bool nonInteractive = _isSetOff || scene->getDragItem() || scene->hasVisibleOrOpeningDialog();
*_ptr = !nonInteractive;
return *_ptr;
@@ -102,11 +102,12 @@ int16 Globals::getGlobal(uint16 num) {
error("getGlobal: requested non-existing global %d", num);
// Bug in HoC?
- warning("getGlobal: requested global 0");
+ //warning("getGlobal: requested global 0");
return 0;
}
int16 Globals::setGlobal(uint16 num, int16 val) {
+ debug("setGlobal %d -> %d", num, val);
for (auto &global : _globals) {
if (global->getNum() == num)
return global->set(val);
@@ -135,8 +136,8 @@ Common::Error Globals::syncState(Common::Serializer &s) {
class DetailLevelROGlobal : public Global {
public:
DetailLevelROGlobal(uint16 num) : Global(num) {}
- int16 get() override { return static_cast<DgdsEngine *>(g_engine)->getDetailLevel(); }
- int16 set(int16 val) override { return static_cast<DgdsEngine *>(g_engine)->getDetailLevel(); }
+ int16 get() override { return DgdsEngine::getInstance()->getDetailLevel(); }
+ int16 set(int16 val) override { return DgdsEngine::getInstance()->getDetailLevel(); }
void setRaw(int16 val) override { }
};
@@ -219,7 +220,7 @@ class HocCharacterGlobal : public RWI16Global {
public:
HocCharacterGlobal(uint16 num, int16 *val) : RWI16Global(num, val) {}
int16 set(int16 val) override {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
bool buttonVisible = engine->isInvButtonVisible();
if (buttonVisible)
engine->getScene()->removeInvButtonFromHotAreaList();
@@ -233,8 +234,8 @@ public:
HocGlobals::HocGlobals(Clock &clock) : Globals(clock), _unk82(1), _unk55(0),
_unkDlgFileNum(0), _unkDlgDlgNum(0), _currentCharacter2(0), _currentCharacter(0),
- _unk50(0), _unk49(0), _unk48(0), _unk47(0), _unk46(0), _unk45(0x3f), _sheckels(0),
- _unk43(0), _unk42(0), _unk41(0), _unk40(3), _unk39(0) {
+ _unk50(0), _nativeGameState(0), _unk48(0), _unk47(0), _unk46(0), _unk45(0x3f), _sheckels(0),
+ _shellBet(0), _shellPea(0), _unk41(0), _unk40(3), _unk39(0) {
_globals.push_back(new DetailLevelROGlobal(0x53));
_globals.push_back(new RWI16Global(0x52, &_unk82));
_globals.push_back(new RWI16Global(0x37, &_unk55)); // TODO: Special update function FUN_1407_080d, sound init related
@@ -243,14 +244,14 @@ HocGlobals::HocGlobals(Clock &clock) : Globals(clock), _unk82(1), _unk55(0),
_globals.push_back(new HocCharacterGlobal(0x34, &_currentCharacter));
_globals.push_back(new HocCharacterGlobal(0x33, &_currentCharacter2));
_globals.push_back(new RWI16Global(0x32, &_unk50));
- _globals.push_back(new RWI16Global(0x31, &_unk49));
+ _globals.push_back(new RWI16Global(0x31, &_nativeGameState));
_globals.push_back(new RWI16Global(0x30, &_unk48));
_globals.push_back(new RWI16Global(0x2F, &_unk47));
_globals.push_back(new RWI16Global(0x2E, &_unk46));
_globals.push_back(new RWI16Global(0x2D, &_unk45)); // TODO: Special update function FUN_1407_0784, palette related?
_globals.push_back(new RWI16Global(0x2C, &_sheckels)); // used as currency in Istanbul
- _globals.push_back(new RWI16Global(0x2B, &_unk43));
- _globals.push_back(new RWI16Global(0x2A, &_unk42));
+ _globals.push_back(new RWI16Global(0x2B, &_shellBet));
+ _globals.push_back(new RWI16Global(0x2A, &_shellPea));
_globals.push_back(new RWI16Global(0x29, &_unk41));
_globals.push_back(new RWI16Global(0x28, &_unk40));
_globals.push_back(new ROI16Global(0x27, &_unk39));
@@ -262,14 +263,14 @@ Common::Error HocGlobals::syncState(Common::Serializer &s) {
s.syncAsSint16LE(_unk39);
s.syncAsSint16LE(_unk40);
s.syncAsSint16LE(_unk41);
- s.syncAsSint16LE(_unk42);
- s.syncAsSint16LE(_unk43);
+ s.syncAsSint16LE(_shellPea);
+ s.syncAsSint16LE(_shellBet);
s.syncAsSint16LE(_sheckels);
s.syncAsSint16LE(_unk45);
s.syncAsSint16LE(_unk46);
s.syncAsSint16LE(_unk47);
s.syncAsSint16LE(_unk48);
- s.syncAsSint16LE(_unk49);
+ s.syncAsSint16LE(_nativeGameState);
s.syncAsSint16LE(_unk50);
s.syncAsSint16LE(_currentCharacter);
s.syncAsSint16LE(_currentCharacter2);
diff --git a/engines/dgds/globals.h b/engines/dgds/globals.h
index 7cc918d0e43..958aee29d35 100644
--- a/engines/dgds/globals.h
+++ b/engines/dgds/globals.h
@@ -149,19 +149,30 @@ class HocGlobals : public Globals {
public:
HocGlobals(Clock &clock);
+ int16 getSheckels() const { return _sheckels; }
+
+ int16 getShellBet() const { return _shellBet; }
+ void setShellBet(int16 bet) { _shellBet = bet; }
+
+ int16 getShellPea() const { return _shellPea; }
+ void setShellPea(int16 pea) { _shellPea = pea; }
+
+ int16 getNativeGameState() const { return _nativeGameState; }
+ void setNativeGameState(int16 state) { _nativeGameState = state; }
+
private:
// HoC-specific globals
int16 _unk39;
int16 _unk40;
int16 _unk41;
- int16 _unk42;
- int16 _unk43;
+ int16 _shellPea;
+ int16 _shellBet;
int16 _sheckels;
int16 _unk45;
int16 _unk46;
int16 _unk47;
int16 _unk48;
- int16 _unk49;
+ int16 _nativeGameState; // state for the shell game, tank game, etc.
int16 _unk50;
int16 _currentCharacter;
int16 _currentCharacter2;
diff --git a/engines/dgds/image.h b/engines/dgds/image.h
index 1ad92c80a57..f1913fc0f8e 100644
--- a/engines/dgds/image.h
+++ b/engines/dgds/image.h
@@ -23,6 +23,7 @@
#define DGDS_IMAGE_H
#include <common/ptr.h>
+#include <common/rect.h>
#include <graphics/palette.h>
namespace Common {
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index 1f2c8d09489..9254c418f15 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -46,7 +46,7 @@ void Inventory::open() {
// Allow double-open becuase that's how the inventory shows item
// descriptions.
_isOpen = true;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int curScene = engine->getScene()->getNum();
if (curScene != 2) {
_openedFromSceneNum = curScene;
@@ -61,7 +61,7 @@ void Inventory::close() {
return;
assert(_openedFromSceneNum != 0);
_isOpen = false;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
engine->changeScene(_openedFromSceneNum);
_showZoomBox = false;
_openedFromSceneNum = 0;
@@ -95,7 +95,7 @@ void Inventory::setRequestData(const REQFileData &data) {
_fullWidth = req._rect.width;
// TODO! Beamish doesn't have a zoom box, or it's a different ID?
- if (static_cast<DgdsEngine *>(g_engine)->getGameId() == GID_WILLY)
+ if (DgdsEngine::getInstance()->getGameId() == GID_WILLY)
_itemZoomBox = _itemBox;
if (!_prevPageBtn || !_nextPageBtn || !_itemZoomBox || !_exitButton || !_itemArea)
@@ -114,7 +114,7 @@ void Inventory::drawHeader(Graphics::ManagedSurface &surf) {
font->drawString(&surf, title, x1 + 4, y1 + 2, titleWidth, 0);
// Only draw the box around the title in DRAGON
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (engine->getGameId() == GID_DRAGON) {
int x2 = x1 + titleWidth + 6;
int y2 = y1 + font->getFontHeight();
@@ -127,7 +127,7 @@ void Inventory::drawHeader(Graphics::ManagedSurface &surf) {
void Inventory::draw(Graphics::ManagedSurface &surf, int itemCount) {
RequestData &boxreq = _reqData._requests[0];
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
DgdsGameId gameId = engine->getGameId();
if (_showZoomBox) {
@@ -182,7 +182,7 @@ void Inventory::draw(Graphics::ManagedSurface &surf, int itemCount) {
}
void Inventory::drawTime(Graphics::ManagedSurface &surf) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (engine->getGameId() != GID_DRAGON)
return;
@@ -196,7 +196,7 @@ void Inventory::drawTime(Graphics::ManagedSurface &surf) {
}
void Inventory::drawItems(Graphics::ManagedSurface &surf) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
const Common::SharedPtr<Image> &icons = engine->getIcons();
int x = 0;
int y = 0;
@@ -259,7 +259,7 @@ void Inventory::drawItems(Graphics::ManagedSurface &surf) {
}
void Inventory::mouseMoved(const Common::Point &pt) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
GameItem *dragItem = engine->getScene()->getDragItem();
if (dragItem) {
engine->setMouseCursor(dragItem->_iconNum);
@@ -278,7 +278,7 @@ GameItem *Inventory::itemUnderMouse(const Common::Point &pt) {
if (!_itemArea)
return nullptr;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
if (_itemArea->containsPoint(pt)) {
const int imgAreaX = _itemArea->_parentX + _itemArea->_x;
@@ -303,7 +303,7 @@ GameItem *Inventory::itemUnderMouse(const Common::Point &pt) {
}
bool Inventory::isItemInInventory(GameItem &item) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
DgdsGameId gameId = engine->getGameId();
bool result = item._inSceneNum == 2; // && (item._flags & 4)
if (gameId == GID_HOC) {
@@ -322,7 +322,7 @@ void Inventory::mouseLDown(const Common::Point &pt) {
if (!boxreq._rect.contains(pt))
return;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (engine->getScene()->hasVisibleDialog() || !_itemBox->containsPoint(pt)) {
return engine->getScene()->mouseLDown(pt);
@@ -339,7 +339,7 @@ void Inventory::mouseLDown(const Common::Point &pt) {
}
void Inventory::mouseLUp(const Common::Point &pt) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
GameItem *dragItem = engine->getScene()->getDragItem();
if (dragItem) {
@@ -394,7 +394,7 @@ void Inventory::mouseLUp(const Common::Point &pt) {
}
void Inventory::mouseRUp(const Common::Point &pt) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (_itemBox->containsPoint(pt)) {
GameItem *underMouse = itemUnderMouse(pt);
if (underMouse) {
diff --git a/engines/dgds/menu.cpp b/engines/dgds/menu.cpp
index 8ab80354c35..bd715394950 100644
--- a/engines/dgds/menu.cpp
+++ b/engines/dgds/menu.cpp
@@ -141,8 +141,7 @@ void Menu::setScreenBuffer() {
}
bool Menu::updateOptionsGadget(Gadget *gadget) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
- Audio::Mixer *mixer = engine->_mixer;
+ Audio::Mixer *mixer = DgdsEngine::getInstance()->_mixer;
switch (gadget->_gadgetNo) {
case kMenuOptionsJoystickOnOff:
@@ -167,7 +166,7 @@ bool Menu::updateOptionsGadget(Gadget *gadget) {
}
void Menu::configureGadget(MenuId menu, Gadget *gadget) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
// a bit of a hack - set up the gadget with the correct value before we draw it.
if (menu == kMenuControls) {
@@ -322,7 +321,7 @@ void Menu::onMouseMove(const Common::Point &mouse) {
}
void Menu::onMouseLUp(const Common::Point &mouse) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (_dragGadget && mouse != _dragStartPt) {
int16 setting = _dragGadget->onDragFinish(mouse);
switch (_dragGadget->_gadgetNo) {
@@ -369,7 +368,7 @@ void Menu::onMouseLUp(const Common::Point &mouse) {
}
void Menu::handleClick(const Common::Point &mouse) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int currentScene = engine->getScene()->getNum();
Gadget *gadget = getClickedMenuItem(mouse);
int16 clickedMenuItem = gadget->_gadgetNo;
@@ -517,7 +516,7 @@ void Menu::handleClick(const Common::Point &mouse) {
}
void Menu::handleClickOptionsMenu(const Common::Point &mouse) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
Audio::Mixer *mixer = engine->_mixer;
Gadget *gadget = getClickedMenuItem(mouse);
int16 clickedMenuItem = gadget->_gadgetNo;
@@ -556,7 +555,7 @@ void Menu::handleClickOptionsMenu(const Common::Point &mouse) {
}
void Menu::handleClickSkipPlayIntroMenu(const Common::Point &mouse) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
Gadget *gadget = getClickedMenuItem(mouse);
int16 clickedMenuItem = gadget->_gadgetNo;
diff --git a/engines/dgds/module.mk b/engines/dgds/module.mk
index 8d92c482150..707ac698040 100644
--- a/engines/dgds/module.mk
+++ b/engines/dgds/module.mk
@@ -20,6 +20,7 @@ MODULE_OBJS := \
request.o \
resource.o \
scripts.o \
+ shell_game.o \
ttm.o \
scene.o \
sound.o
diff --git a/engines/dgds/request.cpp b/engines/dgds/request.cpp
index 106e4d5ce07..e42a201d12a 100644
--- a/engines/dgds/request.cpp
+++ b/engines/dgds/request.cpp
@@ -427,7 +427,7 @@ byte ButtonGadget::drawWillyBg(Graphics::ManagedSurface *dst, bool enabled) cons
}
void ButtonGadget::draw(Graphics::ManagedSurface *dst) const {
- DgdsGameId gameId = static_cast<DgdsEngine *>(g_engine)->getGameId();
+ DgdsGameId gameId = DgdsEngine::getInstance()->getGameId();
bool enabled = !(_flags3 & 9);
byte textCol;
@@ -667,7 +667,7 @@ void ImageGadget::draw(Graphics::ManagedSurface *dst) const {
_drawFrame(dst, xoff, yoff, _width, _height, _sval1I, _sval1I);
// NOTE: This only done in inventory in originals
- if (static_cast<DgdsEngine *>(g_engine)->getGameId() == GID_DRAGON)
+ if (DgdsEngine::getInstance()->getGameId() == GID_DRAGON)
RequestData::drawCorners(dst, 19, xoff - 2, yoff - 2, _width + 4, _height + 4);
else
RequestData::drawCorners(dst, 19, xoff - 4, yoff - 4, _width + 8, _height + 8);
@@ -737,12 +737,12 @@ void RequestData::drawInvType(Graphics::ManagedSurface *dst) {
/*static*/
const DgdsFont *RequestData::getMenuFont() {
- return static_cast<DgdsEngine *>(g_engine)->getFontMan()->getFont(FontManager::kGameFont);
+ return DgdsEngine::getInstance()->getFontMan()->getFont(FontManager::kGameFont);
}
/*static*/
const Image *RequestData::getCorners() {
- return static_cast<DgdsEngine *>(g_engine)->getUICorners().get();
+ return DgdsEngine::getInstance()->getUICorners().get();
}
/*static*/
@@ -833,7 +833,7 @@ void RequestData::drawBackgroundWithSliderArea(Graphics::ManagedSurface *dst, in
dst->transBlitFrom(*corners[9], Common::Point(x, (y + sliderBgHeight) - corners[9]->h));
dst->transBlitFrom(*corners[10], Common::Point((x + width) - corners[10]->w, (y + sliderBgHeight) - corners[10]->h));
- if (static_cast<DgdsEngine *>(g_engine)->getGameId() == GID_DRAGON)
+ if (DgdsEngine::getInstance()->getGameId() == GID_DRAGON)
drawHeader(dst, x, y, width, 9, header, DragonHeaderTxtColor, true, DragonHeaderTopColor, DragonHeaderBottomColor);
else
drawHeader(dst, x, y + 4, width, 9, header, ChinaHeaderTxtColor, true, ChinaHeaderTopColor, ChinaHeaderBottomColor);
@@ -841,8 +841,7 @@ void RequestData::drawBackgroundWithSliderArea(Graphics::ManagedSurface *dst, in
void RequestData::drawBackgroundNoSliders(Graphics::ManagedSurface *dst, const Common::String &header) const {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
- DgdsGameId gameId = engine->getGameId();
+ DgdsGameId gameId = DgdsEngine::getInstance()->getGameId();
if (_rect.width == 0 || _rect.height == 0) {
warning("drawBackgroundNoSliders: empty rect");
@@ -863,7 +862,7 @@ void RequestData::drawBackgroundNoSliders(Graphics::ManagedSurface *dst, const C
/*static*/
void RequestData::fillBackground(Graphics::ManagedSurface *dst, uint16 x, uint16 y, uint16 width, uint16 height, int16 startoffset) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (engine->getGameId() == GID_DRAGON && engine->getDetailLevel() == kDgdsDetailHigh) {
Graphics::Surface area = dst->getSubArea(Common::Rect(Common::Point(x, y), width, height));
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index 300c590a0e0..208a4ecf653 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -502,7 +502,7 @@ void Scene::setItemAttrOp(const Common::Array<uint16> &args) {
if (args.size() < 3)
error("Expect 3 args for item attr opcode.");
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
for (auto &item : engine->getGDSScene()->getGameItems()) {
if (item._num != args[0])
continue;
@@ -520,7 +520,7 @@ void Scene::setItemAttrOp(const Common::Array<uint16> &args) {
}
void Scene::setDragItemOp(const Common::Array<uint16> &args) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
for (auto &item : engine->getGDSScene()->getGameItems()) {
if (item._num != args[0])
@@ -539,7 +539,7 @@ void Scene::setDragItemOp(const Common::Array<uint16> &args) {
}
void Scene::segmentStateOps(const Common::Array<uint16> &args) {
- ADSInterpreter *interp = static_cast<DgdsEngine *>(g_engine)->adsInterpreter();
+ ADSInterpreter *interp = DgdsEngine::getInstance()->adsInterpreter();
for (uint i = 0; i < args.size(); i += 2) {
uint16 subop = args[i];
@@ -582,7 +582,7 @@ void Scene::segmentStateOps(const Common::Array<uint16> &args) {
}
static void _drawDragonCountdown(FontManager::FontType fontType, int16 x, int16 y) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int16 countdownEnd = engine->getGameGlobals()->getGlobal(0x22);
int16 currentMins = engine->getClock().getMins();
const DgdsFont *fnt = engine->getFontMan()->getFont(fontType);
@@ -592,7 +592,7 @@ static void _drawDragonCountdown(FontManager::FontType fontType, int16 x, int16
bool Scene::runSceneOp(const SceneOp &op) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
switch (op._opCode) {
case kSceneOpChangeScene:
if (engine->changeScene(op._args[0]))
@@ -703,7 +703,7 @@ bool Scene::runSceneOp(const SceneOp &op) {
}
bool Scene::runDragonOp(const SceneOp &op) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
switch (op._opCode) {
case kSceneOpPasscode:
engine->getScene()->sceneOpUpdatePasscodeGlobal();
@@ -746,8 +746,9 @@ bool Scene::runDragonOp(const SceneOp &op) {
return true;
}
+
bool Scene::runChinaOp(const SceneOp &op) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
switch (op._opCode) {
case kSceneOpOpenChinaOpenGameOverMenu:
engine->setMenuToTrigger(kMenuGameOver);
@@ -759,14 +760,11 @@ bool Scene::runChinaOp(const SceneOp &op) {
case kSceneOpOpenChinaTrainMenu:
engine->setMenuToTrigger(kMenuSkipArcade);
break;
- case kSceneOpShellGame:
- // TODO: Shell game in scene 81 (accessible from scene 16)
- // We set a high number of sheckels for now
- engine->getGDSScene()->setGlobal(0x2C, 400);
- // We clear the gambler's talk data, as it's not cleared
- // by the game scripts
- engine->getScene()->freeTalkData(8);
- warning("TODO: Implement shell game");
+ case kSceneOpShellGameTick:
+ engine->getShellGame()->shellGameTick();
+ break;
+ case kSceneOpShellGameEnd:
+ engine->getShellGame()->shellGameEnd();
break;
case kSceneOpOpenChinaStartIntro:
// The game first jumps to scene 100, and then to 98
@@ -780,7 +778,7 @@ bool Scene::runChinaOp(const SceneOp &op) {
}
bool Scene::runBeamishOp(const SceneOp &op) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (op._opCode & 0x8000) {
uint16 opcode = op._opCode & 0x7fff;
for (const ConditionalSceneOp &cop : _conditionalOps) {
@@ -803,7 +801,7 @@ bool Scene::runBeamishOp(const SceneOp &op) {
}
bool Scene::runOps(const Common::Array<SceneOp> &ops, int16 addMinuites /* = 0 */) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
for (const SceneOp &op : ops) {
if (!checkConditions(op._conditionList))
continue;
@@ -838,7 +836,7 @@ bool Scene::runOps(const Common::Array<SceneOp> &ops, int16 addMinuites /* = 0 *
}
bool Scene::checkConditions(const Common::Array<SceneConditions> &conds) const {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
uint cnum = 0;
while (cnum < conds.size()) {
@@ -982,6 +980,7 @@ void SDSScene::unload() {
_objInteractions2.clear();
_dialogs.clear();
_triggers.clear();
+ _talkData.clear();
_sceneDialogFlags = kDlgFlagNone;
}
@@ -1061,7 +1060,7 @@ Dialog *SDSScene::loadDialogData(uint16 num) {
return &dlg;
const Common::String filename = Common::String::format("D%d.DDS", num);
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
ResourceManager *resourceManager = engine->getResourceManager();
Common::SeekableReadStream *dlgFile = resourceManager->getResource(filename);
if (!dlgFile)
@@ -1158,7 +1157,7 @@ bool SDSScene::loadTalkData(uint16 num) {
}
const Common::String filename = Common::String::format("T%d.TDS", num);
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
ResourceManager *resourceManager = engine->getResourceManager();
Common::SeekableReadStream *dlgFile = resourceManager->getResource(filename);
if (!dlgFile)
@@ -1369,8 +1368,8 @@ static uint16 passcodeVal3 = 0;
static uint16 passcodeVal4 = 0;
void SDSScene::sceneOpUpdatePasscodeGlobal() {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
- int16 globalval = engine->getGDSScene()->getGlobal(0x20);
+ GDSScene *gdsScene = DgdsEngine::getInstance()->getGDSScene();
+ int16 globalval = gdsScene->getGlobal(0x20);
if (globalval > 34)
return;
@@ -1430,7 +1429,7 @@ void SDSScene::sceneOpUpdatePasscodeGlobal() {
}
}
- engine->getGDSScene()->setGlobal(0x20, globalval);
+ gdsScene->setGlobal(0x20, globalval);
}
void SDSScene::showDialog(uint16 fileNum, uint16 dlgNum) {
@@ -1624,13 +1623,13 @@ bool SDSScene::drawAndUpdateDialogs(Graphics::ManagedSurface *dst) {
void SDSScene::globalOps(const Common::Array<uint16> &args) {
// The globals are held by the GDS scene
- static_cast<DgdsEngine *>(g_engine)->getGDSScene()->globalOps(args);
+ DgdsEngine::getInstance()->getGDSScene()->globalOps(args);
}
void SDSScene::mouseMoved(const Common::Point &pt) {
Dialog *dlg = getVisibleDialog();
const HotArea *area = findAreaUnderMouse(pt);
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int16 cursorNum = (!dlg && area) ? area->_cursorNum : 0;
if (_dragItem) {
@@ -1659,7 +1658,7 @@ void SDSScene::mouseLDown(const Common::Point &pt) {
debug(9, "Mouse LDown on area %d (%d,%d,%d,%d) cursor %d", area->_num, area->_rect.x, area->_rect.y,
area->_rect.width, area->_rect.height, area->_cursorNum);
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int16 addmins = engine->getGameGlobals()->getGameMinsToAddOnStartDrag();
runOps(area->onLDownOps, addmins);
GameItem *item = dynamic_cast<GameItem *>(area);
@@ -1703,7 +1702,7 @@ void SDSScene::mouseLUp(const Common::Point &pt) {
debug(9, "Mouse LUp on area %d (%d,%d,%d,%d) cursor %d", area->_num, area->_rect.x, area->_rect.y,
area->_rect.width, area->_rect.height, area->_cursorNum);
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (!_rbuttonDown)
engine->setMouseCursor(area->_cursorNum);
@@ -1762,7 +1761,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
GameItem *dragItem = _dragItem;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
const Globals *globals = engine->getGameGlobals();
GDSScene *gdsScene = engine->getGDSScene();
@@ -1852,7 +1851,7 @@ void SDSScene::mouseRUp(const Common::Point &pt) {
if (!area)
return;
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
if (area->_num == 0) {
debug("Mouse RUp on inventory.");
@@ -1894,9 +1893,7 @@ bool SDSScene::hasVisibleOrOpeningDialog() const {
}
HotArea *SDSScene::findAreaUnderMouse(const Common::Point &pt) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
-
- for (auto &item : engine->getGDSScene()->getGameItems()) {
+ for (auto &item : DgdsEngine::getInstance()->getGDSScene()->getGameItems()) {
if (item._inSceneNum == _num && checkConditions(item.enableConditions)
&& _isInRect(pt, item._rect)) {
return &item;
@@ -1912,7 +1909,7 @@ HotArea *SDSScene::findAreaUnderMouse(const Common::Point &pt) {
}
void SDSScene::addInvButtonToHotAreaList() {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
const Common::Array<MouseCursor> &cursors = engine->getGDSScene()->getCursorList();
const Common::SharedPtr<Image> &icons = engine->getIcons();
@@ -2110,7 +2107,7 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
/*uint32 unk = */ file->readUint32LE();
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
Common::Array<Global *> &globs = engine->getGameGlobals()->getAllGlobals();
if (globs.size() > 50)
@@ -2148,8 +2145,7 @@ bool GDSScene::loadRestart(const Common::String &filename, ResourceManager *reso
}
void GDSScene::initIconSizes() {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
- const Common::SharedPtr<Image> icons = engine->getIcons();
+ const Common::SharedPtr<Image> icons = DgdsEngine::getInstance()->getIcons();
uint16 nicons = icons ? icons->getFrames().size() : 0;
for (GameItem &item : _gameItems) {
if (item._iconNum < nicons) {
@@ -2269,7 +2265,7 @@ void GDSScene::globalOps(const Common::Array<uint16> &args) {
}
int16 GDSScene::getGlobal(uint16 num) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int curSceneNum = engine->getScene()->getNum();
DgdsGameId gameId = engine->getGameId();
@@ -2291,7 +2287,7 @@ int16 GDSScene::getGlobal(uint16 num) {
}
int16 GDSScene::setGlobal(uint16 num, int16 val) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
int curSceneNum = engine->getScene()->getNum();
for (auto &global : _perSceneGlobals) {
if (global.matches(num, curSceneNum)) {
@@ -2309,7 +2305,7 @@ int16 GDSScene::setGlobal(uint16 num, int16 val) {
}
void GDSScene::drawItems(Graphics::ManagedSurface &surf) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
const Common::SharedPtr<Image> &icons = engine->getIcons();
int currentScene = engine->getScene()->getNum();
if (!icons || icons->loadedFrameCount() < 3)
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index c63d1118a04..e1ca4e75a63 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -28,6 +28,7 @@
#include "dgds/dialog.h"
#include "dgds/dgds_rect.h"
+#include "dgds/shell_game.h"
namespace Dgds {
@@ -125,7 +126,8 @@ enum SceneOpCode {
// China-specific opcodes
kSceneOpOpenChinaTankMenu = 102,
- kSceneOpShellGame = 110,
+ kSceneOpShellGameEnd = 109,
+ kSceneOpShellGameTick = 110,
kSceneOpOpenChinaTrainMenu = 113,
kSceneOpOpenChinaOpenGameOverMenu = 114, // args: none.
kSceneOpOpenChinaOpenSkipCreditsMenu = 115, // args: none.
diff --git a/engines/dgds/shell_game.cpp b/engines/dgds/shell_game.cpp
new file mode 100644
index 00000000000..e138674f54e
--- /dev/null
+++ b/engines/dgds/shell_game.cpp
@@ -0,0 +1,345 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/math.h"
+
+#include "dgds/shell_game.h"
+#include "dgds/dgds.h"
+#include "dgds/globals.h"
+#include "dgds/font.h"
+#include "dgds/includes.h"
+#include "dgds/sound.h"
+
+namespace Dgds {
+
+ShellGame::ShellGame() : _swapStatus(0), _revealPeaStep(0),
+_currentPeaPosition(0), _lastPass(0), _distractStep(0),
+_distractDelay(0), _state13Counter(0), _swapPea1(0), _swapPea2(0),
+_lastSwapPea1(0), _swapMoveDist(0), _swapMoveStep(0), _swapCount(0),
+_reverseDirection(0), _clockwise(false)
+{
+}
+
+void ShellGame::init() {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ HocGlobals *globals = dynamic_cast<HocGlobals *>(engine->getGameGlobals());
+ _shellGameImg.reset(new Image(engine->getResourceManager(), engine->getDecompressor()));
+ _shellGameImg->loadBitmap("SHELLGM2.BMP");
+ globals->setShellPea(engine->getRandom().getRandomNumber(2));
+ _distractStep = 14;
+ _distractDelay = 0;
+ _state13Counter = 0;
+}
+
+static int16 _getState() {
+ HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
+ return globals->getNativeGameState();
+}
+
+static void _setState(int16 val) {
+ HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
+ globals->setNativeGameState(val);
+}
+
+static int16 _getPeaPosition() {
+ HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
+ return globals->getShellPea();
+}
+
+static void _setPeaPosition(int16 val) {
+ HocGlobals *globals = static_cast<HocGlobals *>(DgdsEngine::getInstance()->getGameGlobals());
+ globals->setShellPea(val);
+}
+
+
+void ShellGame::drawShellGameStr(int16 count, int16 x, int16 y) const {
+ const Common::String countStr = Common::String::format("%d", count);
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ const DgdsFont *fnt = engine->getFontMan()->getFont(FontManager::k6x6Font);
+ fnt->drawString(&engine->getStoredAreaBuffer(), countStr, x, y, 50, 0);
+}
+
+void ShellGame::drawShells() const {
+ const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
+ for (uint i = 0; i < 3; i++)
+ _shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, DgdsEngine::getInstance()->getStoredAreaBuffer());
+}
+
+void ShellGame::shellGameTick() {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ HocGlobals *globals = dynamic_cast<HocGlobals *>(engine->getGameGlobals());
+
+ if (!_shellGameImg)
+ init();
+
+ // copy the background to the saved buffer (hack.. but the original does it too)
+ engine->getStoredAreaBuffer().blitFrom(engine->getBackgroundBuffer());
+
+ // Draw the shekels.
+ drawShellGameStr(globals->getSheckels(), 131, 123);
+
+ // Draw the bet
+ drawShellGameStr(globals->getShellBet(), 201, 123);
+
+ update();
+
+ if (_revealPeaStep) {
+ revealPea(false);
+ } else {
+ if (_swapStatus)
+ swapShells(false);
+ else
+ drawShells();
+ }
+}
+
+
+void ShellGame::update() {
+ int16 state = _getState();
+ if (state == 1 || state == 7) {
+ _currentPeaPosition = _getPeaPosition();
+ if (state == 7)
+ _currentPeaPosition = _currentPeaPosition / 16;
+ _setPeaPosition(_getPeaPosition() & 0xf);
+ _revealPeaStep = 1;
+ state++;
+ } else if (state == 4 || state == 10) {
+ _swapStatus = 1;
+ _swapCount = 0;
+ state++;
+ } else if (state == 13) {
+ if (_state13Counter) {
+ _state13Counter--;
+ if (!_state13Counter)
+ state = 10;
+ } else {
+ _state13Counter = 20;
+ }
+ }
+ _setState(state);
+}
+
+
+void ShellGame::revealPea(bool flag) {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ if (_revealPeaStep == 1)
+ engine->_soundPlayer->playSFX(147);
+
+ uint16 x_offset = 55 * _currentPeaPosition;
+ uint16 y_offset;
+ if (_revealPeaStep > 40) {
+ y_offset = 60 - _revealPeaStep;
+ } else if (_revealPeaStep > 20) {
+ y_offset = 20;
+ } else {
+ y_offset = _revealPeaStep;
+ }
+
+ // Draw the pea
+ if (_currentPeaPosition == _getPeaPosition())
+ _shellGameImg->drawBitmap(1, 112 + x_offset, 166, screenRect, engine->getStoredAreaBuffer());
+
+ // Draw the shell revealing the pea
+ _shellGameImg->drawBitmap(0, 98 + x_offset, 153 - y_offset, screenRect, engine->getStoredAreaBuffer());
+
+ // Draw the other shells
+ for (int i = 0; i < 3; i++) {
+ if (i != _currentPeaPosition)
+ _shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, engine->getStoredAreaBuffer());
+ }
+
+ if (!flag) {
+ if (_lastPass) {
+ _lastPass = false;
+ _revealPeaStep = 0;
+ _setState(_getState() + 1);
+ } else {
+ if (y_offset == 0)
+ _lastPass = true;
+ else
+ _revealPeaStep++;
+ }
+ }
+}
+
+
+bool ShellGame::checkDistract() {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ HocGlobals *globals = static_cast<HocGlobals *>(engine->getGameGlobals());
+
+ int16 sheckels = globals->getSheckels();
+ int16 bet = globals->getShellBet();
+ if ((sheckels + bet >= 300)
+ || (sheckels + bet >= 150 && (engine->getRandom().getRandomNumber(256) & 0xc0))
+ || bet > 95
+ || (bet > 45 && (engine->getRandom().getRandomNumber(3)))) {
+ _distractStep++;
+ if (_distractStep > 21)
+ _distractStep = 14;
+ return true;
+ }
+
+ return false;
+}
+
+
+
+void ShellGame::setupSwap() {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ do {
+ _swapPea1 = engine->getRandom().getRandomNumber(2);
+ } while (_swapPea1 == _lastSwapPea1);
+
+ _lastSwapPea1 = _swapPea1;
+
+ if (_swapPea1 == 0) {
+ _swapPea2 = 1;
+ } else if (_swapPea1 == 1) {
+ _swapPea2 = 2;
+ } else {
+ _swapPea1 = 0;
+ _swapPea2 = 2;
+ }
+
+ if (_getPeaPosition() == _swapPea1) {
+ _setPeaPosition(_swapPea2);
+ } else if (_getPeaPosition() == _swapPea2) {
+ _setPeaPosition(_swapPea1);
+ }
+
+ _swapMoveDist = (_swapPea2 - _swapPea1) * 55;
+ _lastPass = false;
+ _swapMoveStep = 0;
+ _swapStatus = 2;
+}
+
+
+void ShellGame::swapShells(bool flag) {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+ const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ if (!flag) {
+ if (_swapStatus == 1) {
+ engine->_soundPlayer->playSFX(145);
+ setupSwap();
+ _clockwise = (bool)(engine->getRandom().getRandomNumber(255) & 0x40);
+ _reverseDirection = 0;
+ }
+
+ uint16 move_speed = (2 << engine->getDifficulty()) + 2;
+ if (_getState() >= 10 && _getState() <= 12)
+ move_speed++;
+ if (!_lastPass) {
+ _swapMoveStep += move_speed;
+ if (abs(_swapPea1 - _swapPea2) != 1)
+ _swapMoveStep += move_speed;
+ if (_swapMoveStep > _swapMoveDist)
+ _swapMoveStep = _swapMoveDist;
+ }
+ }
+
+ uint16 xbase1 = 98 + _swapPea1 * 55;
+ uint16 xbase2 = 98 + _swapPea2 * 55;
+
+ double move = ((double)_swapMoveStep / _swapMoveDist) * M_PI;
+ uint16 y_offset;
+ if (abs(_swapPea1 - _swapPea2) == 1)
+ y_offset = 26;
+ else
+ y_offset = 28;
+
+ y_offset = (int16)(y_offset * sin(move));
+
+ for (int i = 0; i < 3; i++) {
+ if (i != _swapPea1 && i != _swapPea2)
+ _shellGameImg->drawBitmap(0, 98 + i * 55, 153, screenRect, engine->getStoredAreaBuffer());
+ }
+
+ if (!flag) {
+ if ((_reverseDirection == 0) && (_swapMoveStep >= (_swapMoveDist / 2))) {
+ if (engine->getRandom().getRandomNumber(7)) {
+ _reverseDirection = -1;
+ } else {
+ _reverseDirection = 1;
+ if (_getPeaPosition() == _swapPea1)
+ _setPeaPosition(_swapPea2);
+ else if (_getPeaPosition() == _swapPea2)
+ _setPeaPosition(_swapPea1);
+ }
+ }
+ }
+
+ uint16 x1,x2,y1,y2;
+ if (_reverseDirection <= 0) {
+ x1 = xbase1 + _swapMoveStep;
+ x2 = xbase2 - _swapMoveStep;
+ } else {
+ x1 = xbase2 - _swapMoveStep;
+ x2 = xbase1 + _swapMoveStep;
+ }
+
+ if (_clockwise) {
+ y1 = 153 - y_offset;
+ y2 = 153 + y_offset;
+ } else {
+ y1 = 153 + y_offset;
+ y2 = 153 - y_offset;
+ }
+
+ _shellGameImg->drawBitmap(0, x1, y1, screenRect, engine->getStoredAreaBuffer());
+ _shellGameImg->drawBitmap(0, x2, y2, screenRect, engine->getStoredAreaBuffer());
+
+ if (!flag) {
+ int16 state = _getState();
+ if (_lastPass) {
+ _lastPass = false;
+ if (state == 11)
+ _setState(0);
+ else
+ _setState(6);
+ _swapStatus = 0;
+ } else if (_distractDelay) {
+ _distractDelay--;
+ } else if (_swapMoveStep == _swapMoveDist) {
+ _swapCount++;
+ if (state == 11) {
+ _lastPass = true;
+ } else if (_swapCount == 8 && checkDistract()) {
+ _setState(_distractStep);
+ _distractDelay = 20;
+ } else {
+ if (_swapCount < 12 || engine->getRandom().getRandomNumber(7) || state >= 14)
+ _swapStatus = 1;
+ else
+ _lastPass = true;
+ }
+ }
+ }
+}
+
+
+void ShellGame::shellGameEnd() {
+ _shellGameImg.reset();
+}
+
+} // end namespace Dgds
diff --git a/engines/dgds/shell_game.h b/engines/dgds/shell_game.h
new file mode 100644
index 00000000000..be2285d13a0
--- /dev/null
+++ b/engines/dgds/shell_game.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DGDS_SHELL_GAME_H
+#define DGDS_SHELL_GAME_H
+
+#include "dgds/image.h"
+
+namespace Dgds {
+
+/* Native code for the shell game from Heart of China. */
+class ShellGame {
+public:
+ ShellGame();
+
+ void shellGameTick();
+ void shellGameEnd();
+
+private:
+ void init();
+ void drawShellGameStr(int16 count, int16 x, int16 y) const;
+ void drawShells() const;
+ void swapShells(bool flag);
+ void revealPea(bool flag);
+ void update();
+ bool checkDistract();
+ void setupSwap();
+
+ Common::SharedPtr<Image> _shellGameImg;
+ uint16 _revealPeaStep;
+ uint16 _currentPeaPosition;
+ bool _lastPass;
+ uint16 _distractStep;
+ uint16 _distractDelay;
+ uint16 _state13Counter;
+ int16 _swapPea1;
+ int16 _swapPea2;
+ uint16 _lastSwapPea1;
+ uint16 _swapStatus;
+ int16 _swapMoveDist;
+ uint16 _swapMoveStep;
+ uint16 _swapCount;
+ int16 _reverseDirection;
+ bool _clockwise;
+};
+
+} // end namespace Dgds
+
+#endif // DGDS_SHELL_GAME_H
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index d54a00651a8..b2d2e43ba2d 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -43,7 +43,7 @@ void GetPutRegion::reset() {
}
Common::Error TTMEnviro::syncState(Common::Serializer &s) {
- DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
+ DgdsEngine *engine = DgdsEngine::getInstance();
for (auto &shape : _scriptShapes) {
bool hasShape = shape.get() != nullptr;
s.syncAsByte(hasShape);
More information about the Scummvm-git-logs
mailing list