Initial commit
This commit is contained in:
43
engines/dgds/minigames/china_tank.cpp
Normal file
43
engines/dgds/minigames/china_tank.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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/system.h"
|
||||
|
||||
#include "dgds/dgds.h"
|
||||
#include "dgds/minigames/china_tank.h"
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
ChinaTank::ChinaTank() {
|
||||
}
|
||||
|
||||
void ChinaTank::init() {
|
||||
}
|
||||
|
||||
void ChinaTank::tick() {
|
||||
g_system->displayMessageOnOSD(Common::U32String("Tank minigame not implemented yet!"));
|
||||
DgdsEngine::getInstance()->setMenuToTrigger(kMenuSkipArcade);
|
||||
}
|
||||
|
||||
void ChinaTank::end() {
|
||||
}
|
||||
|
||||
} // end namespace Dgds
|
||||
43
engines/dgds/minigames/china_tank.h
Normal file
43
engines/dgds/minigames/china_tank.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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_MINIGAMES_CHINA_TANK_H
|
||||
#define DGDS_MINIGAMES_CHINA_TANK_H
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
/** Tank mini-game for Heart of China */
|
||||
class ChinaTank {
|
||||
public:
|
||||
ChinaTank();
|
||||
|
||||
void init();
|
||||
void tick();
|
||||
void end();
|
||||
|
||||
private:
|
||||
// TODO add private members
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Dgds
|
||||
|
||||
#endif // DGDS_MINIGAMES_CHINA_TANK_H
|
||||
1558
engines/dgds/minigames/china_train.cpp
Normal file
1558
engines/dgds/minigames/china_train.cpp
Normal file
File diff suppressed because it is too large
Load Diff
255
engines/dgds/minigames/china_train.h
Normal file
255
engines/dgds/minigames/china_train.h
Normal file
@@ -0,0 +1,255 @@
|
||||
/* 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_MINIGAMES_CHINA_TRAIN_H
|
||||
#define DGDS_MINIGAMES_CHINA_TRAIN_H
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
enum PlayerType {
|
||||
kPlayerLucky,
|
||||
kPlayerTong,
|
||||
};
|
||||
|
||||
enum PlayerAction {
|
||||
// The list of actions is not directly referenced in the game, but is in
|
||||
// the exe just after the "Heart of China Train Game" copyright
|
||||
kActionStandRight = 0,
|
||||
kActionWalkRight = 1,
|
||||
kActionWalkLeft = 2,
|
||||
kActionJumpRight = 3,
|
||||
kActionJumpLeft = 4,
|
||||
kActionDuckRight = 5,
|
||||
kActionFallRight = 6,
|
||||
kActionFallLeft = 7,
|
||||
kActionStagger = 8,
|
||||
kActionDeathScene = 9,
|
||||
kActionClub = 10,
|
||||
kActionClubHit = 11,
|
||||
kActionSwing = 12,
|
||||
kActionSwingHit = 13,
|
||||
kActionStab = 14,
|
||||
kActionStabHit = 15,
|
||||
kActionBlock = 16,
|
||||
kActionHeroicJump = 17,
|
||||
kActionBlockUp = 18,
|
||||
kActionFree6 = 19,
|
||||
kActionStandLeft = 20,
|
||||
kActionDuckLeft = 21,
|
||||
kActionFree7 = 22,
|
||||
kActionFree8 = 23,
|
||||
kActionERROR = 24,
|
||||
};
|
||||
|
||||
enum PlayerIntent {
|
||||
kIntentDuck = 0,
|
||||
kIntentRest = 1,
|
||||
kIntentPursue = 2,
|
||||
kIntentAttack = 3,
|
||||
kIntentRetreat = 4,
|
||||
kIntentQ = 5,
|
||||
kIntentInvalid = 255,
|
||||
};
|
||||
|
||||
class TrainPlayers;
|
||||
|
||||
struct PlayerData {
|
||||
int16 _frame; // field 0
|
||||
ImageFlipMode _flipMode; // field 1
|
||||
int16 _xstep; // field 2
|
||||
int16 _ystep; // field 3
|
||||
int16 _xoff; // field 4
|
||||
int16 _yoff; // field 5
|
||||
int16 _val6; // field 6
|
||||
};
|
||||
|
||||
struct TunnelData {
|
||||
TunnelData() : _start(0), _end(0) {}
|
||||
int32 _start;
|
||||
int32 _end;
|
||||
};
|
||||
|
||||
class TrainPlayer {
|
||||
public:
|
||||
friend class TrainPlayers;
|
||||
TrainPlayer(PlayerType type);
|
||||
|
||||
bool isBlocking() const { return _action == kActionBlock || _action == kActionBlockUp; }
|
||||
bool isDucking() const { return _action == kActionDuckRight || _action == kActionDuckLeft; }
|
||||
bool isFalling() const { return _action == kActionFallRight || _action == kActionFallLeft; }
|
||||
bool isJumping() const { return _action == kActionJumpRight || _action == kActionJumpLeft; }
|
||||
bool isStaggering() const { return _action == kActionStagger; }
|
||||
bool isStanding() const { return _action == kActionStandRight || _action == kActionStandLeft; }
|
||||
bool isWalking() const { return _action == kActionWalkLeft || _action == kActionWalkRight; }
|
||||
|
||||
bool isTong() const { return _type == kPlayerTong; }
|
||||
bool isLucky() const { return _type == kPlayerLucky; }
|
||||
|
||||
void checkLives();
|
||||
void doAttack(TrainPlayer &other);
|
||||
void doBlock();
|
||||
void doClub(int16 damage);
|
||||
void doPursue(const TrainPlayer &other);
|
||||
void doRun();
|
||||
void doJump();
|
||||
void setAction(PlayerAction state, bool flag);
|
||||
bool inRange(const TrainPlayer &other);
|
||||
void hit(int16 damage);
|
||||
void startStagger(const TrainPlayer &other);
|
||||
void readStuff(const Common::String &path);
|
||||
void computerDucks();
|
||||
void checkDuck(const TunnelData ¤tTunnel);
|
||||
void doProcess();
|
||||
|
||||
PlayerType _type;
|
||||
int16 _xpos;
|
||||
int16 _ypos;
|
||||
PlayerAction _action;
|
||||
int16 _fatigue;
|
||||
int16 _hitpoints;
|
||||
PlayerIntent _intent;
|
||||
int16 _ferocity;
|
||||
int16 _val7;
|
||||
Common::Array<Common::Array<PlayerData>> _allData;
|
||||
Common::Array<PlayerData> *_currentActionData;
|
||||
PlayerData *_data;
|
||||
|
||||
private:
|
||||
TrainPlayer &chooseEnemy();
|
||||
PlayerData *endOfCurrentAction();
|
||||
PlayerData *startOfCurrentAction();
|
||||
|
||||
static int16 _blockSoundFlag;
|
||||
};
|
||||
|
||||
class TrainPlayers {
|
||||
public:
|
||||
TrainPlayers();
|
||||
|
||||
void initPlayers();
|
||||
void checkLives();
|
||||
void readAnims();
|
||||
void freeAnims();
|
||||
void doScroll(int16 jumpOffset);
|
||||
|
||||
TrainPlayer _lucky;
|
||||
TrainPlayer _tong;
|
||||
};
|
||||
|
||||
|
||||
/** Train fight mini-game for Heart of China */
|
||||
class ChinaTrain {
|
||||
public:
|
||||
ChinaTrain();
|
||||
|
||||
void init(); // aka arcadeInit
|
||||
int16 tick(); // aka arcadeLoop
|
||||
void end(); // aka aracdeReset
|
||||
|
||||
//int16 currentCar() const { return _currentCar; }
|
||||
void checkTongFall(int16 xpos, int16 car);
|
||||
TrainPlayers &getPlayers() { return _players; }
|
||||
const TunnelData &getCurrentTunnel() const { return _currentTunnel; }
|
||||
void leaveArcade();
|
||||
bool checkGap(int16 xpos, int16 offset);
|
||||
|
||||
void onKeyDown(Common::KeyState kbd);
|
||||
void onKeyUp(Common::KeyState kbd);
|
||||
void setMenuResult(bool yes);
|
||||
|
||||
int16 _jumpOffset;
|
||||
|
||||
private:
|
||||
void arcadeFadeout();
|
||||
void getUserInput();
|
||||
void getNpcInput();
|
||||
void processInput();
|
||||
void handleVariables();
|
||||
void drawFrame();
|
||||
int16 trainArcade();
|
||||
void trainRestart();
|
||||
void lost();
|
||||
void makeNewTunnel();
|
||||
//void setupArcade(); // just sets fill=1 and _clipWin.
|
||||
void initScoreWindow();
|
||||
void drawBorder();
|
||||
void shadeLabel(int16 x, int16 y, int16 w, int16 h, const char *label);
|
||||
void shadeBox(Graphics::ManagedSurface &buf, byte backCol, byte foreCol, byte fill, int16 x, int16 y, int16 w, int16 h);
|
||||
|
||||
void fixBorder();
|
||||
void drawCommandButtons();
|
||||
void drawBmps();
|
||||
void drawTunnel();
|
||||
void drawMountains(int16 num);
|
||||
void drawBlock(int16 x1, int16 x2, int16 param_3, int16 y1, int16 y2, int16 param_6, int16 param_7, int16 param_8);
|
||||
void drawButtons(int16 *buttons);
|
||||
void shadePressButton(int16 x, int16 y);
|
||||
void shadeButton(int16 x, int16 y);
|
||||
void drawScoreWindow();
|
||||
void drawScore();
|
||||
void drawSnow();
|
||||
void drawTrain();
|
||||
void drawActors();
|
||||
void drawCar(int16 xoff, int16 frame, int16 yoff);
|
||||
void fixUpTunnel();
|
||||
bool calcBounce(int16 car);
|
||||
void checkRegions(TrainPlayer &player);
|
||||
void processOrders(TrainPlayer &player, TrainPlayer &enemy);
|
||||
int16 readButtons();
|
||||
void cabooseLost();
|
||||
|
||||
int16 _arcadeCount;
|
||||
int16 _arcadeFlag;
|
||||
bool _arcadeInitFlag;
|
||||
int16 _arcadeDrawFlag;
|
||||
|
||||
int16 _failCounter;
|
||||
int16 _lastMaskedArcadeFlag;
|
||||
int16 _int3036;
|
||||
int16 _tongAttackCounter;
|
||||
int16 _tongInjuredCounter;
|
||||
int16 _tongRestTarget;
|
||||
int16 _lastTongHP;
|
||||
int16 _lastTongFatigue;
|
||||
TrainPlayers _players;
|
||||
int16 _currentCar;
|
||||
int32 _trackPos;
|
||||
int32 _frameCnt;
|
||||
int16 _xOffset;
|
||||
int16 _tunnelNum;
|
||||
TunnelData _currentTunnel;
|
||||
int16 _cabooseTrail;
|
||||
int16 _lastBtn;
|
||||
const Common::Rect _clipWin;
|
||||
//Common::SharedPtr<Image> _simChars;
|
||||
Common::SharedPtr<Image> _rectShape;
|
||||
Common::SharedPtr<Image> _luckyMaps;
|
||||
Common::SharedPtr<Image> _test;
|
||||
int16 _pressedCommandButton;
|
||||
bool _leftButtonDown;
|
||||
bool _rightButtonDown;
|
||||
int16 _lastKeycode;
|
||||
bool _playedTunnelSFX;
|
||||
};
|
||||
|
||||
} // end namespace Dgds
|
||||
|
||||
#endif // DGDS_MINIGAMES_CHINA_TRAIN_H
|
||||
2552
engines/dgds/minigames/dragon_arcade.cpp
Normal file
2552
engines/dgds/minigames/dragon_arcade.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
engines/dgds/minigames/dragon_arcade.h
Normal file
228
engines/dgds/minigames/dragon_arcade.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/* 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_MINIGAMES_DRAGON_ARCADE_H
|
||||
#define DGDS_MINIGAMES_DRAGON_ARCADE_H
|
||||
|
||||
#include "common/types.h"
|
||||
#include "engines/dgds/minigames/dragon_arcade_ttm.h"
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
enum DragonBulletState {
|
||||
kBulletInactive = 0,
|
||||
kBulletFlying = 1,
|
||||
kBulletHittingBlade = 2,
|
||||
kBulletHittingEnemy = 3,
|
||||
};
|
||||
|
||||
enum DragonBladeMoveFlag {
|
||||
kBladeMoveNone = 0,
|
||||
kBladeMoveUp = 1,
|
||||
kBladeMoveDown = 2,
|
||||
kBladeMoveRight = 4,
|
||||
kBladeMoveLeft = 8,
|
||||
};
|
||||
|
||||
class ArcadeNPCState {
|
||||
public:
|
||||
ArcadeNPCState() : xx(0), yy(0), x(0), y(0), x_11(0), y_11(0), x_12(0), y_12(0),
|
||||
ttmPage(0), byte12(0), byte13(0), health(0), ttmNum(0), x_21(0), y_21(0),
|
||||
x_22(0), y_22(0) {}
|
||||
int16 xx;
|
||||
int16 yy;
|
||||
int16 x;
|
||||
int16 y;
|
||||
int16 x_11;
|
||||
int16 y_11;
|
||||
int16 x_12;
|
||||
int16 y_12;
|
||||
int16 ttmPage;
|
||||
int8 byte12;
|
||||
int8 byte13;
|
||||
int8 health;
|
||||
int8 ttmNum; /* Set to 0, 1 or 2 */
|
||||
int16 x_21;
|
||||
int16 y_21;
|
||||
int16 x_22;
|
||||
int16 y_22;
|
||||
};
|
||||
|
||||
class DragonArcadeBullet {
|
||||
public:
|
||||
DragonArcadeBullet() : _x(0), _y(0), _state(kBulletInactive),
|
||||
_flipMode(kImageFlipNone), _bulletType(0), _ySpeed(0) {}
|
||||
|
||||
int16 _x;
|
||||
int16 _y;
|
||||
DragonBulletState _state;
|
||||
ImageFlipMode _flipMode;
|
||||
int16 _bulletType;
|
||||
uint16 _ySpeed;
|
||||
// these fields are in the original but seem to not be used.
|
||||
// int16 _var2;
|
||||
// int16 _var3;
|
||||
};
|
||||
|
||||
class DragonArcade {
|
||||
public:
|
||||
DragonArcade();
|
||||
|
||||
void arcadeTick();
|
||||
void onKeyDown(Common::KeyState kbd);
|
||||
void onKeyUp(Common::KeyState kbd);
|
||||
|
||||
private:
|
||||
void initIfNeeded();
|
||||
void drawBackgroundAndWeapons();
|
||||
void checkToOpenMenu();
|
||||
void clearAllBulletStates();
|
||||
void clearAllNPCStates();
|
||||
void createBullet(int16 x, int16 y, ImageFlipMode flipMode, int16 bulletType);
|
||||
void bladeTakeHitAndCheck();
|
||||
void enemyTakeHit() { _npcState[1].health--; }
|
||||
void enemyTakeHitAndCheck();
|
||||
void playSfx(int16 num) const;
|
||||
void drawBulletHitCircles(uint16 x, uint16 y, bool colorFlag);
|
||||
void drawHealthBars();
|
||||
void runThenDrawBulletsInFlight();
|
||||
void redraw();
|
||||
void finish();
|
||||
void loadTTMScriptsForStage(uint16 stage);
|
||||
void fadeInAndClearScreen();
|
||||
bool doTickUpdate();
|
||||
void resetStageState();
|
||||
void initValuesForStage();
|
||||
void initValuesForStage0();
|
||||
void initValuesForStage2();
|
||||
void initValuesForStage3();
|
||||
void initValuesForStage4();
|
||||
void initValuesForStage6();
|
||||
void setFinishCountdownIfLessThan0(int16 val);
|
||||
void updateBladeWithInputs();
|
||||
void updateBlade();
|
||||
void updateBoss();
|
||||
void updateBoss2();
|
||||
void decBossHealth();
|
||||
void decBossHealthAndCheck();
|
||||
void bladeTakeHit();
|
||||
void arcade16bc();
|
||||
void arcade16de(int16 param);
|
||||
void arcade1e83();
|
||||
void arcade2445();
|
||||
void arcade2754(int16 findResult);
|
||||
void arcade34b4();
|
||||
void arcade3e96();
|
||||
void arcade4085();
|
||||
void updateXScrollOffset();
|
||||
bool isNpcInsideXRange(int16 num);
|
||||
void updateBullets();
|
||||
void checkBladeFireAllStages();
|
||||
void checkEnemyFireStage0124();
|
||||
void checkBossFireStage3();
|
||||
void checkBossFireStage6();
|
||||
void updateMouseAndJoystickStates();
|
||||
int16 findFloorUnderBlade();
|
||||
int16 checkBulletCollision(int16 num);
|
||||
void mouseUpdate();
|
||||
void keyboardUpdate();
|
||||
void limitToCenterOfScreenAndUpdateCursor();
|
||||
uint16 moveToNextStage();
|
||||
void findFloorMatch();
|
||||
void findFloorMinGT();
|
||||
void findFloorMinGE();
|
||||
void findFloorMatchOrMinOrMax();
|
||||
void findFloorMax();
|
||||
void updateFloorsUnderBlade();
|
||||
bool isFloorNotFound();
|
||||
void playSFX55AndStuff();
|
||||
void moveBladeX();
|
||||
void handleMouseStates();
|
||||
void drawScrollBmp();
|
||||
|
||||
int16 _lastDrawnBladeHealth;
|
||||
int16 _lastDrawnBossHealth;
|
||||
uint16 _nextRandomVal;
|
||||
int16 _loadedArcadeStage;
|
||||
int16 _nextStage;
|
||||
int16 _attemptCounter;
|
||||
int16 _shouldUpdateState;
|
||||
int16 _finishCountdown;
|
||||
int16 _bladeState1;
|
||||
int16 _bladePageOffset;
|
||||
uint16 _mouseButtonWentDown;
|
||||
int16 _scrollXOffset;
|
||||
int32 _nTickUpdates;
|
||||
int16 _startDifficultyMaybe;
|
||||
int16 _bossStateUpdateCounter;
|
||||
int16 _npcStateResetCounter;
|
||||
int16 _scrollVelocityX;
|
||||
uint16 _uint0a17;
|
||||
int16 _currentYOffset;
|
||||
int16 _int0b58;
|
||||
int16 _int0b5a;
|
||||
int16 _int0b60;
|
||||
int16 _ttmYAdjust;
|
||||
uint16 _uint0be6;
|
||||
bool _dontMoveBladeFlag;
|
||||
int16 _scrollXIncrement;
|
||||
bool _lMouseButtonState;
|
||||
bool _rMouseButtonState;
|
||||
bool _lastLMouseButtonState;
|
||||
bool _lastRMouseButtonState;
|
||||
int16 _bladeXMove;
|
||||
int16 _currentArrowNum;
|
||||
int16 _foundFloorY;
|
||||
bool _foundFloorFlag;
|
||||
int16 _lastFloorY;
|
||||
|
||||
bool _haveBigGun;
|
||||
bool _haveBomb;
|
||||
bool _enemyHasSmallGun;
|
||||
bool _dontRedrawBgndAndWeapons;
|
||||
// maybe don't need these
|
||||
//bool _arcadeNeedsBufferCopy;
|
||||
//bool _flagInventoryOpened;
|
||||
bool _initFinished;
|
||||
bool _stillLoadingScriptsMaybe;
|
||||
bool _flag40ee;
|
||||
bool _flag40ef;
|
||||
int16 _someMoveDirection;
|
||||
bool _bladeHasFired;
|
||||
bool _mouseIsAvailable;
|
||||
bool _isMovingStage;
|
||||
DragonBladeMoveFlag _bladeMoveFlag;
|
||||
DragonBladeMoveFlag _keyStateFlags;
|
||||
DragonBladeMoveFlag _bladeMoveFlagBeforeRButton;
|
||||
DragonBladeMoveFlag _bladeHorizMoveAttempt;
|
||||
DragonArcadeBullet _bullets[20];
|
||||
ArcadeNPCState _npcState[20];
|
||||
Common::SharedPtr<Image> _bulletImg;
|
||||
Common::SharedPtr<Image> _arrowImg;
|
||||
Common::SharedPtr<Image> _scrollImg;
|
||||
DragonArcadeTTM _arcadeTTM;
|
||||
Common::Array<int16> _floorY;
|
||||
Common::Array<bool> _floorFlag;
|
||||
};
|
||||
|
||||
} // end namespace Dgds
|
||||
|
||||
#endif // DGDS_MINIGAMES_DRAGON_ARCADE_H
|
||||
353
engines/dgds/minigames/dragon_arcade_ttm.cpp
Normal file
353
engines/dgds/minigames/dragon_arcade_ttm.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
/* 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 "dgds/minigames/dragon_arcade_ttm.h"
|
||||
#include "dgds/minigames/dragon_arcade.h"
|
||||
#include "dgds/ads.h"
|
||||
#include "dgds/drawing.h"
|
||||
#include "dgds/sound.h"
|
||||
#include "dgds/includes.h"
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
Common::String ArcadeFloor::dump() const {
|
||||
return Common::String::format("ArcadeFloor<x:%d-%d y:%d flg:%d>",
|
||||
x, x + width, yval, flag);
|
||||
}
|
||||
|
||||
|
||||
DragonArcadeTTM::DragonArcadeTTM(ArcadeNPCState *npcState) : _npcState(npcState),
|
||||
_currentTTMNum(0), _currentNPCRunningTTM(0), _drawXOffset(0), _drawYOffset(0),
|
||||
_startYOffset(0), _doingInit(false), _drawColBG(0), _drawColFG(0)
|
||||
{
|
||||
ARRAYCLEAR(_shapes3);
|
||||
}
|
||||
|
||||
void DragonArcadeTTM::clearDataPtrs() {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
_ttmEnvs[i] = TTMEnviro();
|
||||
}
|
||||
// TODO: Is this used anywhere?
|
||||
// INT_39e5_3cb8 = -1;
|
||||
}
|
||||
|
||||
int16 DragonArcadeTTM::load(const char *filename) {
|
||||
TTMEnviro *env = nullptr;
|
||||
int16 envNum;
|
||||
for (envNum = 0; envNum < ARRAYSIZE(_ttmEnvs); envNum++) {
|
||||
if (_ttmEnvs[envNum].scr == nullptr) {
|
||||
env = &_ttmEnvs[envNum];
|
||||
debug(1, "Arcade TTM load %s into env %d", filename, envNum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!env)
|
||||
error("Trying to load too many TTMs in Dragon arcade");
|
||||
|
||||
DgdsEngine *engine = DgdsEngine::getInstance();
|
||||
TTMParser dgds(engine->getResourceManager(), engine->getDecompressor());
|
||||
bool parseResult = dgds.parse(env, filename);
|
||||
if (!parseResult)
|
||||
error("Error loading dgds arcade script %s", filename);
|
||||
|
||||
env->scr->seek(0);
|
||||
|
||||
return envNum;
|
||||
}
|
||||
|
||||
void DragonArcadeTTM::finishTTMParse(int16 envNum) {
|
||||
TTMEnviro &env = _ttmEnvs[envNum];
|
||||
|
||||
if (!env.scr)
|
||||
error("DragonArcadeTTM::finishTTMParse: script env %d not loaded", envNum);
|
||||
|
||||
// Discover the frame offsets
|
||||
uint16 op = 0;
|
||||
for (uint frame = 0; frame < env._totalFrames; frame++) {
|
||||
env._frameOffsets[frame] = env.scr->pos();
|
||||
op = env.scr->readUint16LE();
|
||||
while (op != 0x0ff0 && env.scr->pos() < env.scr->size()) {
|
||||
switch (op & 0xf) {
|
||||
case 0:
|
||||
break;
|
||||
case 0xf: {
|
||||
TTMInterpreter::readTTMStringVal(env.scr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
env.scr->skip((op & 0xf) * 2);
|
||||
break;
|
||||
}
|
||||
op = env.scr->readUint16LE();
|
||||
}
|
||||
}
|
||||
env.scr->seek(0);
|
||||
}
|
||||
|
||||
int16 DragonArcadeTTM::runNextPage(int16 pageNum) {
|
||||
_shapes2[_currentTTMNum] = _shapes[_currentTTMNum];
|
||||
// TODO: what is this?
|
||||
//UINT_39e5_3ca2 = 0;
|
||||
|
||||
if (pageNum < _ttmEnvs[_currentTTMNum]._totalFrames && pageNum > -1 &&
|
||||
_ttmEnvs[_currentTTMNum]._frameOffsets[pageNum] > -1) {
|
||||
return runScriptPage(pageNum);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int16 DragonArcadeTTM::handleOperation(TTMEnviro &env, int16 page, uint16 op, byte count, const int16 *ivals, const Common::String &sval) {
|
||||
DgdsEngine *engine = DgdsEngine::getInstance();
|
||||
Graphics::ManagedSurface &compBuffer = engine->_compositionBuffer;
|
||||
switch (op) {
|
||||
case 0x0020:
|
||||
// This doesn't seem explicitly handled in the original, but appears in
|
||||
// arcade sequence 2 - just ignore it??
|
||||
break;
|
||||
case 0x0070:
|
||||
// Do nothing.
|
||||
break;
|
||||
case 0x0080: // FREE SHAPE
|
||||
_allShapes[_shapes3[_currentTTMNum] * 5 + _currentTTMNum].reset();
|
||||
_shapes[_currentTTMNum].reset();
|
||||
break;
|
||||
case 0x1021: // SET DELAY
|
||||
engine->adsInterpreter()->setScriptDelay((int)(ivals[0] * MS_PER_FRAME));
|
||||
break;
|
||||
case 0x1031: // SET BRUSH
|
||||
//debug(1, "Set brush %d for slot %d", ivals[0], _currentTTMNum);
|
||||
if (!_shapes2[_currentTTMNum]) {
|
||||
_brushes[_currentTTMNum].reset();
|
||||
} else {
|
||||
_brushes[_currentTTMNum] = Brush(_shapes2[_currentTTMNum], ivals[0]);
|
||||
}
|
||||
break;
|
||||
case 0x1051: // SET SHAPE
|
||||
_shapes3[_currentTTMNum] = ivals[0];
|
||||
//debug(1, "Set img %d into slot %d", ivals[0], _currentTTMNum);
|
||||
_shapes[_currentTTMNum] = _allShapes[ivals[0] * 5 + _currentTTMNum];
|
||||
_shapes2[_currentTTMNum] = _allShapes[ivals[0] * 5 + _currentTTMNum];
|
||||
break;
|
||||
case 0x1061:
|
||||
// Do nothing (ignore arg)
|
||||
break;
|
||||
case 0x1101:
|
||||
case 0x1111:
|
||||
// Do nothing (ignore arg)
|
||||
break;
|
||||
case 0x1201:
|
||||
// This doesn't seem explicitly handled in the original, but appears in
|
||||
// arcade sequence 1 - just ignore it??
|
||||
break;
|
||||
case 0x2002: // SET COLORS
|
||||
_drawColFG = (byte)ivals[0];
|
||||
_drawColBG = (byte)ivals[1];
|
||||
break;
|
||||
case 0x2012: { // PLAY SOUND
|
||||
int16 sound;
|
||||
if (ivals[0] == 0 || ivals[0] == 1) {
|
||||
sound = 0x26;
|
||||
} else if (ivals[0] == 2) {
|
||||
sound = 0x4f;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
engine->_soundPlayer->playSFX(sound);
|
||||
break;
|
||||
}
|
||||
case 0x4504: { // SET NPC POS 1
|
||||
int16 x = _drawXOffset + ivals[0];
|
||||
int16 y = _drawYOffset + ivals[1] + 2;
|
||||
_npcState[_currentNPCRunningTTM].x_11 = x;
|
||||
_npcState[_currentNPCRunningTTM].x_12 = x + ivals[2];
|
||||
_npcState[_currentNPCRunningTTM].y_11 = y;
|
||||
_npcState[_currentNPCRunningTTM].y_12 = y + ivals[3];
|
||||
break;
|
||||
}
|
||||
case 0x4514: {// SET NPC POS 2
|
||||
int16 x = _drawXOffset + ivals[0];
|
||||
int16 y = _drawYOffset + ivals[1] + 2;
|
||||
_npcState[_currentNPCRunningTTM].x_21 = x;
|
||||
_npcState[_currentNPCRunningTTM].x_22 = x + ivals[2];
|
||||
_npcState[_currentNPCRunningTTM].y_21 = y;
|
||||
_npcState[_currentNPCRunningTTM].y_22 = y + ivals[3];
|
||||
break;
|
||||
}
|
||||
case 0xA0A4: { // DRAW LINE
|
||||
compBuffer.drawLine(_drawXOffset + ivals[0], _drawYOffset + ivals[1] + 2, _drawXOffset + ivals[2], _drawYOffset + ivals[3] + 2, _drawColFG);
|
||||
break;
|
||||
}
|
||||
case 0xA104: // DRAW FILLED RECT
|
||||
if (_doingInit) {
|
||||
ArcadeFloor data;
|
||||
data.x = (page - 1) * SCREEN_WIDTH + ivals[0];
|
||||
data.width = ivals[2];
|
||||
data.yval = (byte)ivals[1];
|
||||
data.flag = false;
|
||||
debug(1, "Floor: %s", data.dump().c_str());
|
||||
_floorData.push_back(data);
|
||||
} else {
|
||||
const Common::Rect rect(Common::Point(ivals[0], ivals[1]), ivals[2], ivals[3]);
|
||||
compBuffer.fillRect(rect, _drawColFG);
|
||||
}
|
||||
break;
|
||||
case 0xA114: // DRAW EMPTY RECT
|
||||
if (_doingInit) {
|
||||
ArcadeFloor data;
|
||||
data.x = (page - 1) * SCREEN_WIDTH + ivals[0];
|
||||
data.width = ivals[2];
|
||||
data.yval = (byte)ivals[1];
|
||||
data.flag = true;
|
||||
debug(1, "Floor: %s", data.dump().c_str());
|
||||
_floorData.push_back(data);
|
||||
} else {
|
||||
const Common::Rect r(Common::Point(ivals[0], ivals[1]), ivals[2], ivals[3]);
|
||||
const Common::Rect drawWin(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
Drawing::rectClipped(r, drawWin, &compBuffer, _drawColFG);
|
||||
}
|
||||
break;
|
||||
case 0xA404: { // DRAW FILLED CIRCLE
|
||||
int16 r = ivals[3] / 2;
|
||||
Drawing::filledCircle(ivals[0], ivals[1], r, r, &compBuffer, _drawColFG, _drawColBG);
|
||||
break;
|
||||
}
|
||||
case 0xA424: { // DRAW EMPTY CIRCLE
|
||||
int16 r = ivals[3] / 2;
|
||||
Drawing::emptyCircle(ivals[0], ivals[1], r, r, &compBuffer, _drawColFG);
|
||||
break;
|
||||
}
|
||||
case 0xA502:
|
||||
case 0xA512:
|
||||
case 0xA522:
|
||||
case 0xA532: { // DRAW SHAPE
|
||||
if (_doingInit)
|
||||
break;
|
||||
|
||||
ImageFlipMode flipMode = kImageFlipNone;
|
||||
if (op == 0xa512)
|
||||
flipMode = kImageFlipV;
|
||||
else if (op == 0xa522)
|
||||
flipMode = kImageFlipH;
|
||||
else if (op == 0xa532)
|
||||
flipMode = kImageFlipHV;
|
||||
|
||||
// Only draw in the scroll area
|
||||
const Common::Rect drawWin(Common::Point(8, 8), SCREEN_WIDTH - 16, 117);
|
||||
if (_currentNPCRunningTTM == 0) {
|
||||
int16 x = ivals[0] + _npcState[0].x - 152;
|
||||
int16 y = ivals[1] + _startYOffset + 2;
|
||||
if (_brushes[_currentTTMNum].isValid())
|
||||
_brushes[_currentTTMNum].getShape()->drawBitmap(_brushes[_currentTTMNum].getFrame(), x, y, drawWin, compBuffer, flipMode);
|
||||
_npcState[0].y = y;
|
||||
} else {
|
||||
int16 x = ivals[0] + _drawXOffset;
|
||||
int16 y = ivals[1] + _drawYOffset + 2;
|
||||
if (_brushes[_currentTTMNum].isValid())
|
||||
_brushes[_currentTTMNum].getShape()->drawBitmap(_brushes[_currentTTMNum].getFrame(), x, y, drawWin, compBuffer, flipMode);
|
||||
_npcState[_currentNPCRunningTTM].x = x;
|
||||
_npcState[_currentNPCRunningTTM].y = y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xF02F: {
|
||||
_shapes[_currentTTMNum].reset(new Image(engine->getResourceManager(), engine->getDecompressor()));
|
||||
_shapes[_currentTTMNum]->loadBitmap(sval);
|
||||
debug(1, "Load img %s into slot %d", sval.c_str(), _currentTTMNum);
|
||||
_shapes2[_currentTTMNum] = _shapes[_currentTTMNum];
|
||||
_allShapes[_shapes3[_currentTTMNum] * 5 + _currentTTMNum] = _shapes[_currentTTMNum];
|
||||
break;
|
||||
}
|
||||
case 0x505F:
|
||||
// Do nothing (ignore arg)
|
||||
break;
|
||||
default:
|
||||
warning("Unsupported TTM opcode 0x%04x for Dragon arcade.", op);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 DragonArcadeTTM::runScriptPage(int16 pageNum) {
|
||||
Common::SeekableReadStream *scr = _ttmEnvs[_currentTTMNum].scr;
|
||||
scr->seek(_ttmEnvs[_currentTTMNum]._frameOffsets[pageNum]);
|
||||
|
||||
uint16 opcode = scr->readUint16LE();
|
||||
while (opcode != 0x0ff0 && opcode) {
|
||||
int16 ivals[4] { 0, 0, 0, 0 };
|
||||
Common::String sval;
|
||||
byte count = (byte)(opcode & 0xf);
|
||||
if (count <= 4) {
|
||||
for (int i = 0; i < count; i++)
|
||||
ivals[i] = scr->readUint16LE();
|
||||
} else if (count == 0xf) {
|
||||
sval = TTMInterpreter::readTTMStringVal(scr);
|
||||
} else {
|
||||
error("Unsupported TTM opcode 0x%04x with %d args for Dragon arcade.", opcode, count);
|
||||
}
|
||||
|
||||
handleOperation(_ttmEnvs[_currentTTMNum], pageNum, opcode, count, ivals, sval);
|
||||
opcode = scr->readUint16LE();
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
void DragonArcadeTTM::runPagesForEachNPC(int16 xScrollOffset) {
|
||||
for (_currentNPCRunningTTM = 19; _currentNPCRunningTTM > 0; _currentNPCRunningTTM--) {
|
||||
ArcadeNPCState &npcState = _npcState[_currentNPCRunningTTM];
|
||||
if (npcState.byte12) {
|
||||
npcState.x_21 = 0;
|
||||
npcState.x_11 = 0;
|
||||
npcState.x_22 = 0;
|
||||
npcState.x_12 = 0;
|
||||
npcState.y_21 = 0;
|
||||
npcState.y_11 = 0;
|
||||
npcState.y_22 = 0;
|
||||
npcState.y_12 = 0;
|
||||
_drawXOffset = npcState.xx - xScrollOffset * 8 - 152;
|
||||
_drawYOffset = npcState.yy;
|
||||
_currentTTMNum = npcState.ttmNum;
|
||||
|
||||
// The original does this comparison, but it seems like a bug (should be &&)
|
||||
// We could correct the check, but better to maintain bug compatibility.
|
||||
// if (_drawXOffset > -20 || _drawXOffset < 340)
|
||||
runNextPage(npcState.ttmPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DragonArcadeTTM::freePages(uint16 num) {
|
||||
delete _ttmEnvs[num].scr;
|
||||
_ttmEnvs[num] = TTMEnviro();
|
||||
}
|
||||
|
||||
void DragonArcadeTTM::freeShapes() {
|
||||
_shapes3[_currentTTMNum] = 0;
|
||||
_shapes[_currentTTMNum].reset();
|
||||
_shapes2[_currentTTMNum].reset();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_allShapes[i * 5 + _currentTTMNum].reset();
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Dgds
|
||||
118
engines/dgds/minigames/dragon_arcade_ttm.h
Normal file
118
engines/dgds/minigames/dragon_arcade_ttm.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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_MINIGAMES_DRAGON_ARCADE_TTM_H
|
||||
#define DGDS_MINIGAMES_DRAGON_ARCADE_TTM_H
|
||||
|
||||
#include "common/ptr.h"
|
||||
|
||||
#include "dgds/image.h"
|
||||
#include "dgds/ttm.h"
|
||||
|
||||
namespace Dgds {
|
||||
|
||||
/**
|
||||
* A segment of floor in the arcade section with a start x, width, height, and flag.
|
||||
*/
|
||||
class ArcadeFloor {
|
||||
public:
|
||||
ArcadeFloor() : x(0), width(0), yval(0), flag(false) {}
|
||||
int16 x;
|
||||
int16 width;
|
||||
byte yval;
|
||||
bool flag;
|
||||
|
||||
Common::String dump() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
The regular TTM interpreter always uses the environment's shape for the brushes,
|
||||
but the arcade one stores brushes as pointers to the exact frame within the shape.
|
||||
|
||||
In practice this may make no difference - maybe we can track use shapes2 and
|
||||
store the frame number?
|
||||
*/
|
||||
class Brush {
|
||||
public:
|
||||
Brush() : _frame(0) {}
|
||||
Brush(const Common::SharedPtr<Image> &shape, int16 frame) : _shape(shape), _frame(frame) {}
|
||||
|
||||
void reset() {
|
||||
_shape.reset();
|
||||
_frame = 0;
|
||||
}
|
||||
bool isValid() const { return _shape && _shape->loadedFrameCount() > _frame; }
|
||||
const Common::SharedPtr<Image> &getShape() const { return _shape; }
|
||||
int16 getFrame() const { return _frame; }
|
||||
private:
|
||||
Common::SharedPtr<Image> _shape;
|
||||
int16 _frame;
|
||||
};
|
||||
|
||||
class ArcadeNPCState;
|
||||
|
||||
/** A TTM interpreter which is simpler than the main one and
|
||||
specialized to the arcade sequences. */
|
||||
class DragonArcadeTTM {
|
||||
public:
|
||||
DragonArcadeTTM(ArcadeNPCState *npcState);
|
||||
void clearDataPtrs();
|
||||
int16 load(const char *filename);
|
||||
void finishTTMParse(int16 envNum);
|
||||
int16 runNextPage(int16 pageNum);
|
||||
void freePages(uint16 num);
|
||||
void freeShapes();
|
||||
void runPagesForEachNPC(int16 xScrollOffset);
|
||||
const Common::Array<ArcadeFloor> &getFloorData() { return _floorData; }
|
||||
|
||||
uint16 _currentTTMNum;
|
||||
int16 _currentNPCRunningTTM;
|
||||
int16 _drawXOffset;
|
||||
int16 _drawYOffset;
|
||||
int16 _startYOffset;
|
||||
bool _doingInit;
|
||||
|
||||
private:
|
||||
int16 runScriptPage(int16 pageNum);
|
||||
int16 handleOperation(TTMEnviro &env, int16 page, uint16 op, byte count, const int16 *ivals, const Common::String &sval);
|
||||
|
||||
int16 _shapes3[6];
|
||||
Common::SharedPtr<Image> _shapes[6];
|
||||
Common::SharedPtr<Image> _shapes2[6];
|
||||
Common::SharedPtr<Image> _allShapes[30];
|
||||
Brush _brushes[6];
|
||||
|
||||
byte _drawColFG;
|
||||
byte _drawColBG;
|
||||
ArcadeNPCState *_npcState;
|
||||
// int16 _numA1x4OpsInInit; // implicit by count of items in _floorData
|
||||
Common::Array<ArcadeFloor> _floorData;
|
||||
|
||||
// Note: only a subset of the enviro members get used, but
|
||||
// use the same structure for simplicity.
|
||||
TTMEnviro _ttmEnvs[5];
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Dgds
|
||||
|
||||
#endif // DGDS_MINIGAMES_DRAGON_ARCADE_TTM_H
|
||||
347
engines/dgds/minigames/shell_game.cpp
Normal file
347
engines/dgds/minigames/shell_game.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
/* 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/intrinsics.h"
|
||||
|
||||
#include "dgds/minigames/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 = static_cast<HocGlobals *>(engine->getGameGlobals());
|
||||
assert(globals);
|
||||
_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::k4x5Font);
|
||||
fnt->drawString(&engine->getStoredAreaBuffer(), countStr, x, y, 50, 13);
|
||||
}
|
||||
|
||||
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 = static_cast<HocGlobals *>(engine->getGameGlobals());
|
||||
assert(globals);
|
||||
|
||||
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
|
||||
67
engines/dgds/minigames/shell_game.h
Normal file
67
engines/dgds/minigames/shell_game.h
Normal file
@@ -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_MINIGAMES_SHELL_GAME_H
|
||||
#define DGDS_MINIGAMES_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_MINIGAMES_SHELL_GAME_H
|
||||
Reference in New Issue
Block a user