/* 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 . * */ #include "common/debug.h" #include "common/rect.h" #include "common/savefile.h" #include "common/system.h" #include "graphics/cursorman.h" #include "alg/graphics.h" #include "alg/logic/game_crimepatrol.h" #include "alg/scene.h" namespace Alg { GameCrimePatrol::GameCrimePatrol(AlgEngine *vm, const AlgGameDescription *gd) : Game(vm) { } GameCrimePatrol::~GameCrimePatrol() { if (_shotIcon) { _shotIcon->free(); delete _shotIcon; } if (_emptyIcon) { _emptyIcon->free(); delete _emptyIcon; } if (_liveIcon) { _liveIcon->free(); delete _liveIcon; } if (_deadIcon) { _deadIcon->free(); delete _deadIcon; } if (_difficultyIcon) { _difficultyIcon->free(); delete _difficultyIcon; } if (_bulletholeIcon) { _bulletholeIcon->free(); delete _bulletholeIcon; } } void GameCrimePatrol::init() { Game::init(); _videoPosX = 11; _videoPosY = 2; if (_vm->isDemo()) { loadLibArchive("cp.lib"); } else if(_vm->useSingleSpeedVideos()) { loadLibArchive("cpss.lib"); } else { loadLibArchive("cpds.lib"); } _sceneInfo->loadScnFile("cp.scn"); _startScene = _sceneInfo->getStartScene(); registerScriptFunctions(); verifyScriptFunctions(); _menuzone = new Zone("MainMenu", "GLOBALHIT"); _menuzone->addRect(0x0C, 0xAA, 0x38, 0xC7, nullptr, 0, "SHOTMENU", "0"); _submenzone = new Zone("SubMenu", "GLOBALHIT"); _submenzone->addRect(0x1C, 0x11, 0x5D, 0x20, nullptr, 0, "STARTMENU", "0"); _submenzone->addRect(0x1C, 0x31, 0x5D, 0x40, nullptr, 0, "RECTLOAD", "0"); _submenzone->addRect(0x1C, 0x51, 0x5D, 0x60, nullptr, 0, "RECTSAVE", "0"); _submenzone->addRect(0x1C, 0x71, 0x5D, 0x80, nullptr, 0, "CONTMENU", "0"); _submenzone->addRect(0x1C, 0x91, 0x5D, 0xA0, nullptr, 0, "EXITMENU", "0"); _submenzone->addRect(0xDD, 0x3C, 0x010A, 0x4B, nullptr, 0, "RECTEASY", "0"); _submenzone->addRect(0xDD, 0x5C, 0x010A, 0x6B, nullptr, 0, "RECTAVG", "0"); _submenzone->addRect(0xDD, 0x7C, 0x010A, 0x8B, nullptr, 0, "RECTHARD", "0"); _shotSound = loadSoundFile("blow.8b"); _emptySound = loadSoundFile("empty.8b"); _saveSound = loadSoundFile("saved.8b"); _loadSound = loadSoundFile("loaded.8b"); _skullSound = loadSoundFile("skull.8b"); _gun = AlgGraphics::loadScreenCoordAniImage("gun.ani", _palette); _numbers = AlgGraphics::loadAniImage("numbers.ani", _palette); auto bullets = AlgGraphics::loadAniImage("bullets.ani", _palette); _shotIcon = (*bullets)[0]; _emptyIcon = (*bullets)[1]; auto lives = AlgGraphics::loadAniImage("lives.ani", _palette); _liveIcon = (*lives)[0]; _deadIcon = (*lives)[1]; auto difficlt = AlgGraphics::loadScreenCoordAniImage("difficlt.ani", _palette); _difficultyIcon = (*difficlt)[0]; auto hole = AlgGraphics::loadScreenCoordAniImage("hole.ani", _palette); _bulletholeIcon = (*hole)[0]; _background = AlgGraphics::loadVgaBackground("cp_menu.vga", _palette); _screen->copyRectToSurface(_background->getPixels(), _background->pitch, 0, 0, _background->w, _background->h); moveMouse(); } void GameCrimePatrol::registerScriptFunctions() { #define RECT_HIT_FUNCTION(name, func) _rectHitFuncs[name] = new CPScriptFunctionRect(this, &GameCrimePatrol::func); RECT_HIT_FUNCTION("DEFAULT", rectNewScene); RECT_HIT_FUNCTION("NEWSCENE", rectNewScene); RECT_HIT_FUNCTION("EXITMENU", rectExit); RECT_HIT_FUNCTION("CONTMENU", rectContinue); RECT_HIT_FUNCTION("STARTMENU", rectStart); RECT_HIT_FUNCTION("SHOTMENU", rectShotMenu); RECT_HIT_FUNCTION("RECTSAVE", rectSave); RECT_HIT_FUNCTION("RECTLOAD", rectLoad); RECT_HIT_FUNCTION("RECTEASY", rectEasy); RECT_HIT_FUNCTION("RECTAVG", rectAverage); RECT_HIT_FUNCTION("RECTHARD", rectHard); RECT_HIT_FUNCTION("TARGET_PRACTICE", rectTargetPractice); RECT_HIT_FUNCTION("SELECT_TARGET_PRACTICE", rectSelectTargetPractice); RECT_HIT_FUNCTION("SELECT_GANG_FIGHT", rectSelectGangFight); RECT_HIT_FUNCTION("SELECT_WAREHOUSE", rectSelectWarehouse); RECT_HIT_FUNCTION("SELECT_WESTCOAST_SOUND", rectSelectWestcoastSound); RECT_HIT_FUNCTION("SELECT_DRUG_DEAL", rectSelectDrugDeal); RECT_HIT_FUNCTION("SELECT_CAR_RING", rectSelectCarRing); RECT_HIT_FUNCTION("SELECT_BAR", rectSelectBar); RECT_HIT_FUNCTION("SELECT_BANK", rectSelectBank); RECT_HIT_FUNCTION("SELECT_CRACK_HOUSE", rectSelectCrackHouse); RECT_HIT_FUNCTION("SELECT_METH_LAB", rectSelectMethLab); RECT_HIT_FUNCTION("SELECT_AIRPLANE", rectSelectAirplane); RECT_HIT_FUNCTION("SELECT_NUKE_TRANSPORT", rectSelectNukeTransport); RECT_HIT_FUNCTION("SELECT_AIRPORT", rectSelectAirport); RECT_HIT_FUNCTION("KILL_INNOCENT_MAN", rectKillInnocentMan); #undef RECT_HIT_FUNCTION #define PRE_OPS_FUNCTION(name, func) _scenePreOps[name] = new CPScriptFunctionScene(this, &GameCrimePatrol::func); PRE_OPS_FUNCTION("DEFAULT", scenePsoDrawRct); PRE_OPS_FUNCTION("PAUSE", scenePsoPause); PRE_OPS_FUNCTION("FADEIN", scenePsoFadeIn); PRE_OPS_FUNCTION("PAUSE_FADEIN", scenePsoPauseFadeIn); PRE_OPS_FUNCTION("WAREHOUSE_GOT_TO", scenePsoWarehouseGotTo); PRE_OPS_FUNCTION("GANG_FIGHT_GOT_TO", scenePsoGangFightGotTo); PRE_OPS_FUNCTION("WESTCOAST_SOUND_GOT_TO", scenePsoWestcoastSoundGotTo); PRE_OPS_FUNCTION("DRUG_DEAL_GOT_TO", scenePsoDrugDealGotTo); PRE_OPS_FUNCTION("CAR_RING_GOT_TO", scenePsoCarRingGotTo); PRE_OPS_FUNCTION("BANK_GOT_TO", scenePsoBankGotTo); PRE_OPS_FUNCTION("CRACK_HOUSE_GOT_TO", scenePsoCrackHouseGotTo); PRE_OPS_FUNCTION("METH_LAB_GOT_TO", scenePsoMethLabGotTo); PRE_OPS_FUNCTION("AIRPLANE_GOT_TO", scenePsoAirplaneGotTo); PRE_OPS_FUNCTION("AIRPORT_GOT_TO", scenePsoAirportGotTo); PRE_OPS_FUNCTION("NUKE_TRANSPORT_GOT_TO", scenePsoNukeTransportGotTo); PRE_OPS_FUNCTION("POWER_PLANT_GOT_TO", scenePsoPowerPlantGotTo); #undef PRE_OPS_FUNCTION #define INS_OPS_FUNCTION(name, func) _sceneInsOps[name] = new CPScriptFunctionScene(this, &GameCrimePatrol::func); INS_OPS_FUNCTION("DEFAULT", sceneIsoDoNothing); INS_OPS_FUNCTION("PAUSE", sceneIsoPause); #undef INS_OPS_FUNCTION #define NXT_SCN_FUNCTION(name, func) _sceneNxtScn[name] = new CPScriptFunctionScene(this, &GameCrimePatrol::func); NXT_SCN_FUNCTION("DEFAULT", sceneDefaultNxtscn); NXT_SCN_FUNCTION("GAME_WON", sceneNxtscnGameWon); NXT_SCN_FUNCTION("LOSE_A_LIFE", sceneNxtscnLoseALife); NXT_SCN_FUNCTION("DID_NOT_CONTINUE", sceneNxtscnDidNotContinue); NXT_SCN_FUNCTION("KILL_INNOCENT_MAN", sceneNxtscnKillInnocentMan); NXT_SCN_FUNCTION("KILL_INNOCENT_WOMAN", sceneNxtscnKillInnocentWoman); NXT_SCN_FUNCTION("AFTER_DIE", sceneNxtscnAfterDie); NXT_SCN_FUNCTION("SELECT_LANGUAGE_1", sceneNxtscnSelectLanguage1); NXT_SCN_FUNCTION("SELECT_LANGUAGE_2", sceneNxtscnSelectLanguage2); NXT_SCN_FUNCTION("INIT_RANDOM_TARGET_PRACTICE", sceneNxtscnInitRandomTargetPractice); NXT_SCN_FUNCTION("CONTINUE_TARGET_PRACTICE", sceneNxtscnContinueTargetPractice); NXT_SCN_FUNCTION("SELECT_ROOKIE_SCENARIO", sceneNxtscnSelectRookieScenario); NXT_SCN_FUNCTION("FINISH_GANG_FIGHT", sceneNxtscnFinishGangFight); NXT_SCN_FUNCTION("FINISH_WESTCOAST_SOUND", sceneNxtscnFinishWestcoastSound); NXT_SCN_FUNCTION("FINISH_WAREHOUSE", sceneNxtscnFinishWarehouse); NXT_SCN_FUNCTION("INIT_RANDOM_WAREHOUSE", sceneNxtscnInitRandomWarehouse); NXT_SCN_FUNCTION("CONTINUE_WAREHOUSE", sceneNxtscnContinueWarehouse); NXT_SCN_FUNCTION("SELECT_UNDERCOVER_SCENARIO", sceneNxtscnSelectUndercoverScenario); NXT_SCN_FUNCTION("FINISH_DRUG_DEAL", sceneNxtscnFinishDrugDeal); NXT_SCN_FUNCTION("INIT_RANDOM_CAR_RING_LEADER", sceneNxtscnInitRandomCarRingLeader); NXT_SCN_FUNCTION("CONTINUE_CAR_RING_LEADER_1", sceneNxtscnContinueCarRingLeader1); NXT_SCN_FUNCTION("CONTINUE_CAR_RING_LEADER_2", sceneNxtscnContinueCarRingLeader2); NXT_SCN_FUNCTION("INIT_RANDOM_CAR_RING", sceneNxtscnInitRandomCarRing); NXT_SCN_FUNCTION("CONTINUE_CAR_RING", sceneNxtscnContinueCarRing); NXT_SCN_FUNCTION("FINISH_CAR_RING", sceneNxtscnFinishCarRing); NXT_SCN_FUNCTION("FINISH_BAR", sceneNxtscnFinishBar); NXT_SCN_FUNCTION("FINISH_BANK", sceneNxtscnFinishBank); NXT_SCN_FUNCTION("FINISH_CRACK_HOUSE", sceneNxtscnFinishCrackHouse); NXT_SCN_FUNCTION("FINISH_METH_LAB", sceneNxtscnFinishMethLab); NXT_SCN_FUNCTION("FINISH_AIRPLANE", sceneNxtscnFinishAirplane); NXT_SCN_FUNCTION("FINISH_AIRPORT", sceneNxtscnFinishAirport); NXT_SCN_FUNCTION("FINISH_NUKE_TRANSPORT", sceneNxtscnFinishNukeTransport); NXT_SCN_FUNCTION("INIT_RANDOM_BAR", sceneNxtscnInitRandomBar); NXT_SCN_FUNCTION("CONTINUE_BAR", sceneNxtscnContinueBar); NXT_SCN_FUNCTION("SELECT_SWAT_SCENARIO", sceneNxtscnSelectSwatScenario); NXT_SCN_FUNCTION("INIT_RANDOM_BANK", sceneNxtscnInitRandomBank); NXT_SCN_FUNCTION("CONTINUE_BANK", sceneNxtscnContinueBank); NXT_SCN_FUNCTION("INIT_RANDOM_METH_LAB", sceneNxtscnInitRandomMethLab); NXT_SCN_FUNCTION("CONTINUE_METH_LAB", sceneNxtscnContinueMethLab); NXT_SCN_FUNCTION("SELECT_DELTA_SCENARIO", sceneNxtscnSelectDeltaScenario); NXT_SCN_FUNCTION("PICK_RANDOM_RAPPELLER", sceneNxtscnPickRandomRapeller); NXT_SCN_FUNCTION("INIT_RANDOM_AIRPLANE", sceneNxtscnInitRandomAirplane); NXT_SCN_FUNCTION("CONTINUE_AIRPLANE", sceneNxtscnContinueAirplane); NXT_SCN_FUNCTION("PICK_RANDOM_AIRPLANE_FRONT", sceneNxtscnPickRandomAirplaneFront); NXT_SCN_FUNCTION("INIT_RANDOM_AIRPORT", sceneNxtscnInitRandomAirport); NXT_SCN_FUNCTION("CONTINUE_AIRPORT", sceneNxtscnContinueAirport); NXT_SCN_FUNCTION("INIT_RANDOM_NUKE_TRANSPORT", sceneNxtscnInitRandomNukeTransport); NXT_SCN_FUNCTION("CONTINUE_NUKE_TRANSPORT", sceneNxtscnContinueNukeTransport); NXT_SCN_FUNCTION("INIT_RANDOM_POWERPLANT", sceneNxtscnInitRandomPowerplant); NXT_SCN_FUNCTION("CONTINUE_POWERPLANT", sceneNxtscnContinuePowerplant); #undef NXT_SCN_FUNCTION _sceneShowMsg["DEFAULT"] = new CPScriptFunctionScene(this, &GameCrimePatrol::sceneSmDonothing); _sceneWepDwn["DEFAULT"] = new CPScriptFunctionScene(this, &GameCrimePatrol::sceneDefaultWepdwn); _sceneScnScr["DEFAULT"] = new CPScriptFunctionScene(this, &GameCrimePatrol::sceneDefaultScore); _sceneNxtFrm["DEFAULT"] = new CPScriptFunctionScene(this, &GameCrimePatrol::sceneNxtfrm); } void GameCrimePatrol::verifyScriptFunctions() { auto scenes = _sceneInfo->getScenes(); for (auto scene : *scenes) { getScriptFunctionScene(PREOP, scene->_preop); getScriptFunctionScene(SHOWMSG, scene->_scnmsg); getScriptFunctionScene(INSOP, scene->_insop); getScriptFunctionScene(WEPDWN, scene->_wepdwn); getScriptFunctionScene(SCNSCR, scene->_scnscr); getScriptFunctionScene(NXTFRM, scene->_nxtfrm); getScriptFunctionScene(NXTSCN, scene->_nxtscn); for (auto zone : scene->_zones) { for (auto rect : zone->_rects) { getScriptFunctionRectHit(rect->_rectHit); } } } } CPScriptFunctionRect GameCrimePatrol::getScriptFunctionRectHit(Common::String name) { auto it = _rectHitFuncs.find(name); if (it != _rectHitFuncs.end()) { return *it->_value; } else { error("GameCrimePatrol::getScriptFunctionRectHit(): Could not find rectHit function: %s", name.c_str()); } } CPScriptFunctionScene GameCrimePatrol::getScriptFunctionScene(SceneFuncType type, Common::String name) { CPScriptFunctionSceneMap *functionMap; switch (type) { case PREOP: functionMap = &_scenePreOps; break; case SHOWMSG: functionMap = &_sceneShowMsg; break; case INSOP: functionMap = &_sceneInsOps; break; case WEPDWN: functionMap = &_sceneWepDwn; break; case SCNSCR: functionMap = &_sceneScnScr; break; case NXTFRM: functionMap = &_sceneNxtFrm; break; case NXTSCN: functionMap = &_sceneNxtScn; break; default: error("GameCrimePatrol::getScriptFunctionScene(): Unkown scene script type: %u", type); break; } CPScriptFunctionSceneMap::iterator it; it = functionMap->find(name); if (it != functionMap->end()) { return *it->_value; } else { error("GameCrimePatrol::getScriptFunctionScene(): Could not find scene type %u function: %s", type, name.c_str()); } } void GameCrimePatrol::callScriptFunctionRectHit(Common::String name, Rect *rect) { CPScriptFunctionRect function = getScriptFunctionRectHit(name); function(rect); } void GameCrimePatrol::callScriptFunctionScene(SceneFuncType type, Common::String name, Scene *scene) { CPScriptFunctionScene function = getScriptFunctionScene(type, name); function(scene); } Common::Error GameCrimePatrol::run() { init(); newGame(); _curScene = _startScene; Common::String oldscene; while (!_vm->shouldQuit()) { oldscene = _curScene; _fired = false; Scene *scene = _sceneInfo->findScene(_curScene); if (!loadScene(scene)) { if (scene->_nxtscn == "CONTINUE_TARGET_PRACTICE") { callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene); } else { error("GameCrimePatrol::run(): Cannot find scene %s in libfile", scene->_name.c_str()); } } _sceneSkipped = false; _paletteDirty = true; _nextFrameTime = getMsTime() + 100; callScriptFunctionScene(PREOP, scene->_preop, scene); _currentFrame = getFrame(scene); while (_currentFrame <= scene->_endFrame && _curScene == oldscene && !_vm->shouldQuit()) { updateMouse(); callScriptFunctionScene(SHOWMSG, scene->_scnmsg, scene); callScriptFunctionScene(INSOP, scene->_insop, scene); _holster = weaponDown(); if (_holster) { callScriptFunctionScene(WEPDWN, scene->_wepdwn, scene); } Common::Point firedCoords; if (fired(&firedCoords)) { if (!_holster) { Rect *hitGlobalRect = checkZone(_menuzone, &firedCoords); if (hitGlobalRect != nullptr) { callScriptFunctionRectHit(hitGlobalRect->_rectHit, hitGlobalRect); } else if (_shots > 0) { if (!_debug_unlimitedAmmo) { _shots--; } displayShotFiredImage(&firedCoords); doShot(); Rect *hitRect = nullptr; Zone *hitSceneZone = checkZonesV2(scene, hitRect, &firedCoords); if (hitSceneZone != nullptr) { callScriptFunctionRectHit(hitRect->_rectHit, hitRect); } else { int8 skip = skipToNewScene(scene); if (skip == -1) { callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene); } else if (skip == 1) { if (scene->_dataParam4 > 0) { uint32 framesToSkip = (scene->_dataParam4 - _currentFrame) / _videoFrameSkip; _videoDecoder->skipNumberOfFrames(framesToSkip); } else { callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene); } } } } else { playSound(_emptySound); } } } if (_curScene == oldscene) { callScriptFunctionScene(NXTFRM, scene->_nxtfrm, scene); } displayLivesLeft(); displayScores(); displayShotsLeft(); moveMouse(); if (_pauseTime > 0) { _videoDecoder->pauseAudio(true); } else { _videoDecoder->pauseAudio(false); } if (_videoDecoder->getCurrentFrame() == 0) { _videoDecoder->getNextFrame(); } updateScreen(); int32 remainingMillis = _nextFrameTime - getMsTime(); if (remainingMillis < 10) { if (_videoDecoder->getCurrentFrame() > 0) { _videoDecoder->getNextFrame(); } remainingMillis = _nextFrameTime - getMsTime(); _nextFrameTime = getMsTime() + (remainingMillis > 0 ? remainingMillis : 0) + 100; } if (remainingMillis > 0) { if (remainingMillis > 15) { remainingMillis = 15; } g_system->delayMillis(remainingMillis); } _currentFrame = getFrame(scene); debugDrawPracticeRects(); } // frame limit reached or scene changed, prepare for next scene _hadPause = false; _pauseTime = 0; if (_curScene == oldscene) { callScriptFunctionScene(NXTSCN, scene->_nxtscn, scene); } if (_curScene == "") { shutdown(); } } return Common::kNoError; } void GameCrimePatrol::newGame() { _shots = 10; _lives = 3; _holster = false; } void GameCrimePatrol::resetParams() { // fill _gotTo with start scenes // 0 in _gotTo array means the level is finished for (int i = 0; i < 15; i++) { _gotTo[i] = _levelScenes[i][0]; } } void GameCrimePatrol::doMenu() { uint32 startTime = getMsTime(); updateCursor(); _inMenu = true; moveMouse(); _videoDecoder->pauseAudio(true); _screen->copyRectToSurface(_background->getBasePtr(_videoPosX, _videoPosY), _background->pitch, _videoPosX, _videoPosY, _videoDecoder->getWidth(), _videoDecoder->getHeight()); showDifficulty(_difficulty, false); while (_inMenu && !_vm->shouldQuit()) { Common::Point firedCoords; if (fired(&firedCoords)) { Rect *hitMenuRect = checkZone(_submenzone, &firedCoords); if (hitMenuRect != nullptr) { callScriptFunctionRectHit(hitMenuRect->_rectHit, hitMenuRect); } } if (_difficulty != _oldDifficulty) { changeDifficulty(_difficulty); } updateScreen(); g_system->delayMillis(15); } updateCursor(); _videoDecoder->pauseAudio(false); if (_hadPause) { uint32 endTime = getMsTime(); uint32 timeDiff = endTime - startTime; _pauseTime += timeDiff; _nextFrameTime += timeDiff; } } void GameCrimePatrol::changeDifficulty(uint8 newDifficulty) { if (newDifficulty == _oldDifficulty) { return; } showDifficulty(newDifficulty, true); _oldDifficulty = newDifficulty; _difficulty = newDifficulty; } void GameCrimePatrol::showDifficulty(uint8 newDifficulty, bool cursor) { // reset menu screen _screen->copyRectToSurface(_background->getBasePtr(_videoPosX, _videoPosY), _background->pitch, _videoPosX, _videoPosY, _videoDecoder->getWidth(), _videoDecoder->getHeight()); uint16 posY = 0x45 + ((newDifficulty - 1) * 0x21); AlgGraphics::drawImageCentered(_screen, _difficultyIcon, 0x0115, posY); if (cursor) { updateCursor(); } } void GameCrimePatrol::updateCursor() { updateMouse(); } void GameCrimePatrol::updateMouse() { if (_oldWhichGun != _whichGun) { Graphics::Surface *cursor = (*_gun)[_whichGun]; uint16 hotspotX = (cursor->w / 2) + 3; uint16 hotspotY = (cursor->h / 2) + 3; if (debugChannelSet(1, Alg::kAlgDebugGraphics)) { cursor->drawLine(0, hotspotY, cursor->w, hotspotY, 1); cursor->drawLine(hotspotX, 0, hotspotX, cursor->h, 1); } CursorMan.replaceCursor(cursor->getPixels(), cursor->w, cursor->h, hotspotX, hotspotY, 0); CursorMan.showMouse(true); _oldWhichGun = _whichGun; } } void GameCrimePatrol::moveMouse() { if (_inMenu) { _whichGun = 3; // in menu cursor } else { // TODO: disabled for now, because glitchy /* uint16 x = _mousePos.x; uint16 y = _mousePos.y; if (x < 13) {x = 13;} if (x > 286) {x = 286;} if (y < 3) {y = 3;} if (y > 166) {y = 166;} if (_mousePos.x != x || _mousePos.y != y) { _mousePos.x = x; _mousePos.y = y; g_system->warpMouse(x, y); } */ if (_mousePos.y >= 0xA3 && _mousePos.x >= 0xF0) { _whichGun = 1; // holster } else if (_mousePos.y >= 0xA3 && _mousePos.x <= 0x43) { _whichGun = 2; // menu button cursor } else { _whichGun = 0; // regular gun } } updateMouse(); } void GameCrimePatrol::displayLivesLeft() { if (_lives == _oldLives) { return; } int posY = 0x67; for (int i = 0; i < 3; i++) { AlgGraphics::drawImage(_screen, _deadIcon, 0x12F, posY); posY += 0xE; } posY = 0x67; for (int i = 0; i < _lives; i++) { AlgGraphics::drawImage(_screen, _liveIcon, 0x12F, posY); posY += 0xE; } _oldLives = _lives; } void GameCrimePatrol::displayScores() { if (_score == _oldScore) { return; } Common::String scoreString = Common::String::format("%05d", _score); int posX = 0x9B; for (int i = 0; i < 5; i++) { uint8 digit = scoreString[i] - '0'; AlgGraphics::drawImage(_screen, (*_numbers)[digit], posX, 0xBF); posX += 7; } _oldScore = _score; } void GameCrimePatrol::displayShotsLeft() { if (_shots == _oldShots) { return; } uint16 posX = 0xEE; for (int i = 0; i < 10; i++) { AlgGraphics::drawImage(_screen, _emptyIcon, posX, 0xBE); posX += 5; } posX = 0xEE; for (int i = 0; i < _shots; i++) { AlgGraphics::drawImage(_screen, _shotIcon, posX, 0xBE); posX += 5; } _oldShots = _shots; } bool GameCrimePatrol::weaponDown() { if (_rightDown && _mousePos.y >= 0xAA && _mousePos.x >= 0x113) { return true; } return false; } bool GameCrimePatrol::saveState() { Common::OutSaveFile *outSaveFile; Common::String saveFileName = _vm->getSaveStateName(0); if (!(outSaveFile = g_system->getSavefileManager()->openForSaving(saveFileName))) { warning("GameCrimePatrol::saveState(): Can't create file '%s', game not saved", saveFileName.c_str()); return false; } outSaveFile->writeUint32BE(MKTAG('A', 'L', 'G', 'S')); // header outSaveFile->writeByte(0); // version, unused for now outSaveFile->writeSByte(_stage); for (int i = 0; i < 15; i++) { outSaveFile->writeUint16LE(_gotTo[i]); } outSaveFile->writeSint32LE(_score); outSaveFile->writeUint16LE(_shots); outSaveFile->writeSByte(_lives); outSaveFile->finalize(); delete outSaveFile; return true; } bool GameCrimePatrol::loadState() { Common::InSaveFile *inSaveFile; Common::String saveFileName = _vm->getSaveStateName(0); if (!(inSaveFile = g_system->getSavefileManager()->openForLoading(saveFileName))) { debug("GameCrimePatrol::loadState(): Can't load file '%s', game not loaded", saveFileName.c_str()); return false; } uint32 header = inSaveFile->readUint32BE(); if (header != MKTAG('A', 'L', 'G', 'S')) { warning("GameCrimePatrol::loadState(): Unkown save file, header: %s", tag2str(header)); return false; } inSaveFile->skip(1); // version, unused for now _stage = inSaveFile->readSByte(); for (int i = 0; i < 15; i++) { _gotTo[i] = inSaveFile->readUint16LE(); } _score = inSaveFile->readSint32LE(); _shots = inSaveFile->readUint16LE(); _lives = inSaveFile->readSByte(); delete inSaveFile; _gameInProgress = true; sceneNxtscnGeneric(_stage); return true; } // misc game functions void GameCrimePatrol::displayShotFiredImage(Common::Point *point) { if (point->x >= _videoPosX && point->x <= (_videoPosX + _videoDecoder->getWidth()) && point->y >= _videoPosY && point->y <= (_videoPosY + _videoDecoder->getHeight())) { uint16 targetX = point->x - _videoPosX; uint16 targetY = point->y - _videoPosY; AlgGraphics::drawImageCentered(_videoDecoder->getVideoFrame(), _bulletholeIcon, targetX, targetY); } } void GameCrimePatrol::enableVideoFadeIn() { // TODO implement } uint16 GameCrimePatrol::sceneToNumber(Scene *scene) { return atoi(scene->_name.substr(5).c_str()); } uint16 GameCrimePatrol::pickRandomScene(uint8 index, uint8 max) { if (max != 0) { _randomMax = max; _randomMask = 0; _randomPicked = 0; _randomSceneCount = 0; while (_levelScenes[index][_randomSceneCount] != 0) { _randomSceneCount++; } } uint16 count = _randomMax--; if (count > 0) { _randomPicked = randomUnusedInt(_randomSceneCount, &_randomMask, _randomPicked); return _levelScenes[index][_randomPicked]; } return 0; } uint16 GameCrimePatrol::pickDeathScene() { if (_stage != _oldStage) { _oldStage = _stage; _deathMask = 0; _deathPicked = -1; _deathSceneCount = 0; while (_diedScenesByStage[_stage][_deathSceneCount] != 0) { _deathSceneCount++; } } _deathPicked = randomUnusedInt(_deathSceneCount, &_deathMask, _deathPicked); return _diedScenesByStage[_stage][_deathPicked]; } void GameCrimePatrol::sceneNxtscnGeneric(uint8 index) { uint16 nextSceneId = 0; _gotTo[index] = 0; if (_gotTo[0] || _gotTo[1] || _gotTo[3] || _gotTo[2]) { nextSceneId = _stageStartScenes[0]; } else if (_gotTo[4] || _gotTo[5] || _gotTo[6]) { if (_stage == 1) { nextSceneId = _stageStartScenes[1]; } else { _stage = 1; nextSceneId = 0x50; } } else if (_gotTo[7] || _gotTo[8] || _gotTo[9]) { if (_stage == 2) { nextSceneId = _stageStartScenes[2]; } else { _stage = 2; nextSceneId = 0x81; } } else if (_gotTo[10] || _gotTo[11] || _gotTo[12]) { if (_stage == 3) { nextSceneId = _stageStartScenes[3]; } else { _stage = 3; nextSceneId = 0x014B; } } else if (_gotTo[13]) { _stage = 4; nextSceneId = 0x018F; } else { nextSceneId = 0x21; } _curScene = Common::String::format("scene%d", nextSceneId); } void GameCrimePatrol::rectSelectGeneric(uint8 index) { if (_gotTo[index] > 0) { _curScene = Common::String::format("scene%d", _gotTo[index]); } } void GameCrimePatrol::sceneIsoGotToGeneric(uint8 index, uint16 sceneId) { _gotTo[index] = sceneId; } // Script functions: RectHit void GameCrimePatrol::rectShotMenu(Rect *rect) { doMenu(); } void GameCrimePatrol::rectSave(Rect *rect) { if (saveState()) { doSaveSound(); } } void GameCrimePatrol::rectLoad(Rect *rect) { if (loadState()) { doLoadSound(); } } void GameCrimePatrol::rectContinue(Rect *rect) { _inMenu = false; _fired = false; if (_lives <= 0) { _score = (int32)(_score * 0.7f); uint16 returnScene = _stageStartScenes[_stage]; _curScene = Common::String::format("scene%d", returnScene); newGame(); } } void GameCrimePatrol::rectStart(Rect *rect) { _inMenu = false; _fired = false; _gameInProgress = true; if (_vm->isDemo()) { _curScene = "scene39"; _gotTo[1] = 39; } else { _curScene = Common::String::format("scene%d", _stageStartScenes[0]); } resetParams(); newGame(); } void GameCrimePatrol::rectTargetPractice(Rect *rect) { uint16 nextScene = 0; Scene *scene = _sceneInfo->findScene(_curScene); if (_levelScenes[0][0] == sceneToNumber(scene)) { _practiceMask = 0x1F; } if (_practiceMask == 0) { _practiceMask = 0x1F; } for (int i = 0; i < 5; i++) { if (_mousePos.x <= _practiceTargetLeft[i] || _mousePos.x >= _practiceTargetRight[i] || _mousePos.y <= _practiceTargetTop[i] || _mousePos.y >= _practiceTargetBottom[i]) { // did not hit target continue; } uint8 mask = 1 << i; if (!(_practiceMask & mask)) { // target was already hit before continue; } // did hit target _score += scene->_scnscrParam == 0 ? 50 : scene->_scnscrParam; _practiceMask ^= mask; uint8 inverted = _practiceMask ^ 0x1F; if (_practiceMask == 0) { nextScene = 432; } else { nextScene = 401 + inverted; } break; } if (nextScene != 0) { _curScene = Common::String::format("scene%d", nextScene); } } void GameCrimePatrol::rectSelectTargetPractice(Rect *rect) { rectSelectGeneric(0); _gotTo[0] = 0; } void GameCrimePatrol::rectSelectGangFight(Rect *rect) { _gotTo[0] = 0; rectSelectGeneric(1); } void GameCrimePatrol::rectSelectWarehouse(Rect *rect) { _gotTo[0] = 0; rectSelectGeneric(2); } void GameCrimePatrol::rectSelectWestcoastSound(Rect *rect) { _gotTo[0] = 0; rectSelectGeneric(3); } void GameCrimePatrol::rectSelectDrugDeal(Rect *rect) { rectSelectGeneric(4); } void GameCrimePatrol::rectSelectCarRing(Rect *rect) { rectSelectGeneric(5); } void GameCrimePatrol::rectSelectBar(Rect *rect) { rectSelectGeneric(6); } void GameCrimePatrol::rectSelectBank(Rect *rect) { rectSelectGeneric(7); } void GameCrimePatrol::rectSelectCrackHouse(Rect *rect) { rectSelectGeneric(9); } void GameCrimePatrol::rectSelectMethLab(Rect *rect) { rectSelectGeneric(8); } void GameCrimePatrol::rectSelectAirplane(Rect *rect) { rectSelectGeneric(10); } void GameCrimePatrol::rectSelectNukeTransport(Rect *rect) { rectSelectGeneric(11); } void GameCrimePatrol::rectSelectAirport(Rect *rect) { rectSelectGeneric(12); } void GameCrimePatrol::rectKillInnocentMan(Rect *rect) { } // Script functions: Scene PreOps void GameCrimePatrol::scenePsoWarehouseGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(2, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoGangFightGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(1, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoWestcoastSoundGotTo(Scene *scene) { sceneIsoGotToGeneric(3, 456); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoDrugDealGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(4, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoCarRingGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(5, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoBankGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(7, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoCrackHouseGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(9, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoMethLabGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(8, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoAirplaneGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(10, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoAirportGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(12, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoNukeTransportGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(11, sceneId); enableVideoFadeIn(); } void GameCrimePatrol::scenePsoPowerPlantGotTo(Scene *scene) { uint16 sceneId = sceneToNumber(scene); sceneIsoGotToGeneric(13, sceneId); _finalStageScene = sceneId; enableVideoFadeIn(); } // Script functions: Scene NxtScn void GameCrimePatrol::sceneNxtscnLoseALife(Scene *scene) { uint16 picked = 0; if (!_debug_godMode) { _lives--; } if (_vm->isDemo()) { _curScene = "scene39"; return; } else if (_lives > 0) { displayLivesLeft(); picked = pickDeathScene(); } else { picked = _deadScenes[_stage]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnGameWon(Scene *scene) { _gameInProgress = false; _curScene = _startScene; } void GameCrimePatrol::sceneNxtscnDidNotContinue(Scene *scene) { _gameInProgress = false; _curScene = _startScene; } void GameCrimePatrol::sceneNxtscnKillInnocentMan(Scene *scene) { uint16 picked = 0; if (!_debug_godMode) { _lives--; } if (_lives > 0) { picked = _stageStartScenes[_stage]; } else { picked = _deadScenes[_stage]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnKillInnocentWoman(Scene *scene) { uint16 picked = 0; if (!_debug_godMode) { _lives--; } if (_lives > 0) { picked = _stageStartScenes[_stage]; } else { picked = _deadScenes[_stage]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnAfterDie(Scene *scene) { uint16 picked = _stageStartScenes[_stage]; _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnSelectLanguage1(Scene *scene) { // do nothing } void GameCrimePatrol::sceneNxtscnSelectLanguage2(Scene *scene) { // do nothing } void GameCrimePatrol::sceneNxtscnInitRandomTargetPractice(Scene *scene) { uint16 picked = pickRandomScene(14, 6); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueTargetPractice(Scene *scene) { uint16 picked = pickRandomScene(14, 0); if (picked == 0) { sceneIsoGotToGeneric(0, 1); sceneNxtscnGeneric(0); } else { _curScene = Common::String::format("scene%d", picked); } } void GameCrimePatrol::sceneNxtscnSelectRookieScenario(Scene *scene) { uint16 picked = 0; if (_gotTo[0] > 0) { picked = _gotTo[0]; _gotTo[0] = 0; } else if (_gotTo[3] > 0) { picked = _gotTo[3]; } else if (_gotTo[1] > 0) { picked = _gotTo[1]; } else if (_gotTo[2] > 0) { picked = _gotTo[2]; } else { picked = _stageStartScenes[1]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnSelectUndercoverScenario(Scene *scene) { uint16 picked = 0; if (_gotTo[4] > 0) { picked = _gotTo[4]; } else if (_gotTo[5] > 0) { picked = _gotTo[5]; } else if (_gotTo[6] > 0) { picked = _gotTo[6]; } else { picked = _stageStartScenes[2]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnSelectSwatScenario(Scene *scene) { uint16 picked = 0; if (_gotTo[8] > 0) { picked = _gotTo[8]; } else if (_gotTo[7] > 0) { picked = _gotTo[7]; } else if (_gotTo[9] > 0) { picked = _gotTo[9]; } else { picked = _stageStartScenes[3]; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnSelectDeltaScenario(Scene *scene) { uint16 picked = 0; if (_gotTo[10] > 0) { picked = _gotTo[10]; } else if (_gotTo[11] > 0) { picked = _gotTo[11]; } else if (_gotTo[12] > 0) { picked = _gotTo[12]; } else { picked = _finalStageScene; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnFinishGangFight(Scene *scene) { if (_vm->isDemo()) { _curScene = _startScene; return; } sceneNxtscnGeneric(1); } void GameCrimePatrol::sceneNxtscnFinishWestcoastSound(Scene *scene) { sceneNxtscnGeneric(3); } void GameCrimePatrol::sceneNxtscnFinishWarehouse(Scene *scene) { sceneNxtscnGeneric(2); } void GameCrimePatrol::sceneNxtscnInitRandomWarehouse(Scene *scene) { uint16 picked = pickRandomScene(15, (_difficulty * 2) + 5); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueWarehouse(Scene *scene) { uint16 picked = pickRandomScene(15, 0); if (picked == 0) { picked = 0x43; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnFinishDrugDeal(Scene *scene) { sceneNxtscnGeneric(4); } void GameCrimePatrol::sceneNxtscnInitRandomCarRingLeader(Scene *scene) { uint16 picked = pickRandomScene(16, 2); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueCarRingLeader1(Scene *scene) { uint16 picked = pickRandomScene(16, 0); if (picked == 0) { picked = 0x67; } else { picked = 0x63; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueCarRingLeader2(Scene *scene) { uint16 picked = pickRandomScene(16, 0); if (picked == 0) { picked = 0x67; } else { picked = 0x66; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomCarRing(Scene *scene) { uint16 picked = pickRandomScene(17, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueCarRing(Scene *scene) { uint16 picked = pickRandomScene(17, 0); if (picked == 0) { picked = 0x74; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnFinishCarRing(Scene *scene) { sceneNxtscnGeneric(5); } void GameCrimePatrol::sceneNxtscnFinishBar(Scene *scene) { sceneNxtscnGeneric(6); } void GameCrimePatrol::sceneNxtscnFinishBank(Scene *scene) { sceneNxtscnGeneric(7); } void GameCrimePatrol::sceneNxtscnFinishCrackHouse(Scene *scene) { sceneNxtscnGeneric(9); } void GameCrimePatrol::sceneNxtscnFinishMethLab(Scene *scene) { sceneNxtscnGeneric(8); } void GameCrimePatrol::sceneNxtscnFinishAirplane(Scene *scene) { sceneNxtscnGeneric(10); } void GameCrimePatrol::sceneNxtscnFinishAirport(Scene *scene) { sceneNxtscnGeneric(12); } void GameCrimePatrol::sceneNxtscnFinishNukeTransport(Scene *scene) { sceneNxtscnGeneric(11); } void GameCrimePatrol::sceneNxtscnInitRandomBar(Scene *scene) { uint16 picked = pickRandomScene(18, (_difficulty * 2) + 9); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueBar(Scene *scene) { uint16 picked = pickRandomScene(18, 0); if (picked == 0) { picked = 0x92; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomBank(Scene *scene) { uint16 picked = pickRandomScene(19, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueBank(Scene *scene) { uint16 picked = pickRandomScene(19, 0); if (picked == 0) { picked = 0xA8; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomMethLab(Scene *scene) { uint16 picked = pickRandomScene(20, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueMethLab(Scene *scene) { uint16 picked = pickRandomScene(20, 0); if (picked == 0) { picked = 0xD0; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnPickRandomRapeller(Scene *scene) { uint16 picked = pickRandomScene(21, 1); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomAirplane(Scene *scene) { uint16 picked = pickRandomScene(22, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueAirplane(Scene *scene) { uint16 picked = pickRandomScene(22, 0); if (picked == 0) { picked = 0x108; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnPickRandomAirplaneFront(Scene *scene) { uint16 picked = pickRandomScene(23, 1); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomAirport(Scene *scene) { uint16 picked = pickRandomScene(24, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueAirport(Scene *scene) { uint16 picked = pickRandomScene(24, 0); if (picked == 0) { picked = 0x12D; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomNukeTransport(Scene *scene) { uint16 picked = pickRandomScene(25, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinueNukeTransport(Scene *scene) { uint16 picked = pickRandomScene(25, 0); if (picked == 0) { picked = 0x147; } _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnInitRandomPowerplant(Scene *scene) { uint16 picked = pickRandomScene(26, (_difficulty * 2) + 8); _curScene = Common::String::format("scene%d", picked); } void GameCrimePatrol::sceneNxtscnContinuePowerplant(Scene *scene) { uint16 picked = pickRandomScene(26, 0); if (picked == 0) { picked = 0x169; } _curScene = Common::String::format("scene%d", picked); } // Script functions: WepDwn void GameCrimePatrol::sceneDefaultWepdwn(Scene *scene) { _shots = 10; } // Debug methods void GameCrimePatrol::debugWarpTo(int val) { // TODO implement } void GameCrimePatrol::debugDrawPracticeRects() { if (_debug_drawRects || debugChannelSet(1, Alg::kAlgDebugGraphics)) { Scene *scene = _sceneInfo->findScene(_curScene); if (scene->_zones.size() > 0) { if (scene->_zones[0]->_name == "zone283") { for (int i = 0; i < 5; i++) { uint16 left = _practiceTargetLeft[i] - _videoPosX; uint16 right = _practiceTargetRight[i] - _videoPosX; uint16 top = _practiceTargetTop[i] - _videoPosY; uint16 bottom = _practiceTargetBottom[i] - _videoPosY; _videoDecoder->getVideoFrame()->drawLine(left, top, right, top, 1); _videoDecoder->getVideoFrame()->drawLine(left, top, left, bottom, 1); _videoDecoder->getVideoFrame()->drawLine(right, bottom, right, top, 1); _videoDecoder->getVideoFrame()->drawLine(right, bottom, left, bottom, 1); } } } } } // Debugger methods DebuggerCrimePatrol::DebuggerCrimePatrol(GameCrimePatrol *game) { _game = game; registerVar("drawRects", &game->_debug_drawRects); registerVar("godMode", &game->_debug_godMode); registerVar("unlimitedAmmo", &game->_debug_unlimitedAmmo); registerCmd("warpTo", WRAP_METHOD(DebuggerCrimePatrol, cmdWarpTo)); registerCmd("dumpLib", WRAP_METHOD(DebuggerCrimePatrol, cmdDumpLib)); } bool DebuggerCrimePatrol::cmdWarpTo(int argc, const char **argv) { if (argc != 2) { debugPrintf("Usage: warp "); return true; } else { int val = atoi(argv[1]); _game->debugWarpTo(val); return false; } } bool DebuggerCrimePatrol::cmdDumpLib(int argc, const char **argv) { return _game->debug_dumpLibFile(); } } // End of namespace Alg