2008-05-02 14:48:19 +00:00
|
|
|
/* 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 2
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kyra/kyra_v2.h"
|
|
|
|
#include "kyra/screen_v2.h"
|
2008-05-04 15:56:28 +00:00
|
|
|
#include "kyra/debugger.h"
|
2008-05-02 14:48:19 +00:00
|
|
|
|
|
|
|
namespace Kyra {
|
|
|
|
|
2008-05-11 23:16:50 +00:00
|
|
|
KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const EngineDesc &desc) : KyraEngine_v1(system, flags), _desc(desc) {
|
2008-05-02 14:48:19 +00:00
|
|
|
memset(&_sceneAnims, 0, sizeof(_sceneAnims));
|
|
|
|
memset(&_sceneAnimMovie, 0, sizeof(_sceneAnimMovie));
|
|
|
|
|
|
|
|
_lastProcessedSceneScript = 0;
|
|
|
|
_specialSceneScriptRunFlag = false;
|
2008-05-02 15:08:45 +00:00
|
|
|
|
|
|
|
_itemList = 0;
|
|
|
|
_itemListSize = 0;
|
2008-05-02 15:21:51 +00:00
|
|
|
|
|
|
|
_characterShapeFile = -1;
|
2008-05-02 15:39:51 +00:00
|
|
|
|
|
|
|
_updateCharPosNextUpdate = 0;
|
2008-05-02 15:48:30 +00:00
|
|
|
|
|
|
|
memset(&_sceneScriptState, 0, sizeof(_sceneScriptState));
|
|
|
|
memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
|
2008-05-02 17:14:59 +00:00
|
|
|
|
|
|
|
_animObjects = 0;
|
2008-05-03 19:23:45 +00:00
|
|
|
|
|
|
|
_runFlag = true;
|
|
|
|
_showOutro = false;
|
|
|
|
_deathHandler = -1;
|
|
|
|
_animNeedUpdate = false;
|
|
|
|
|
|
|
|
_animShapeCount = 0;
|
|
|
|
_animShapeFiledata = 0;
|
|
|
|
|
|
|
|
_vocHigh = -1;
|
|
|
|
_chatVocHigh = -1;
|
|
|
|
_chatVocLow = -1;
|
|
|
|
_chatText = 0;
|
|
|
|
_chatObject = -1;
|
2008-05-04 13:25:03 +00:00
|
|
|
|
|
|
|
memset(_hiddenItems, -1, sizeof(_hiddenItems));
|
2008-05-04 15:56:28 +00:00
|
|
|
|
2008-05-05 16:05:56 +00:00
|
|
|
_screenBuffer = 0;
|
2008-05-06 17:44:00 +00:00
|
|
|
|
|
|
|
memset(&_mainCharacter, 0, sizeof(_mainCharacter));
|
|
|
|
memset(&_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory));
|
2008-05-23 13:37:56 +00:00
|
|
|
|
|
|
|
_pauseStart = 0;
|
2008-05-02 14:48:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
KyraEngine_v2::~KyraEngine_v2() {
|
2008-05-13 21:39:18 +00:00
|
|
|
if (!(_flags.isDemo && !_flags.isTalkie)) {
|
|
|
|
for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) {
|
|
|
|
delete[] i->_value;
|
|
|
|
i->_value = 0;
|
|
|
|
}
|
|
|
|
_gameShapes.clear();
|
2008-05-02 14:48:19 +00:00
|
|
|
}
|
2008-05-02 15:08:45 +00:00
|
|
|
|
2008-05-05 16:05:56 +00:00
|
|
|
delete[] _itemList;
|
2008-05-06 16:57:07 +00:00
|
|
|
delete[] _sceneList;
|
2008-05-02 15:48:30 +00:00
|
|
|
|
|
|
|
_emc->unload(&_sceneScriptData);
|
2008-05-02 17:14:59 +00:00
|
|
|
|
2008-05-05 16:05:56 +00:00
|
|
|
delete[] _animObjects;
|
2008-05-03 19:23:45 +00:00
|
|
|
|
|
|
|
for (Common::Array<const Opcode*>::iterator i = _opcodesAnimation.begin(); i != _opcodesAnimation.end(); ++i)
|
|
|
|
delete *i;
|
|
|
|
_opcodesAnimation.clear();
|
|
|
|
|
2008-05-05 16:05:56 +00:00
|
|
|
delete[] _screenBuffer;
|
2008-05-04 15:56:28 +00:00
|
|
|
}
|
|
|
|
|
2008-05-23 13:37:56 +00:00
|
|
|
void KyraEngine_v2::pauseEngineIntern(bool pause) {
|
|
|
|
KyraEngine_v1::pauseEngineIntern(pause);
|
|
|
|
|
|
|
|
if (!pause) {
|
|
|
|
for (int i = 0; i < ARRAYSIZE(_sceneSpecialScriptsTimer); ++i) {
|
|
|
|
if (_sceneSpecialScriptsTimer[i])
|
|
|
|
_sceneSpecialScriptsTimer[i] += _pauseStart;
|
|
|
|
}
|
|
|
|
|
|
|
|
_pauseStart = 0;
|
|
|
|
} else {
|
|
|
|
_pauseStart = _system->getMillis();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-10 19:41:26 +00:00
|
|
|
void KyraEngine_v2::delay(uint32 amount, bool updateGame, bool isMainLoop) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::delay(%u, %d, %d)", amount, updateGame, isMainLoop);
|
|
|
|
|
|
|
|
uint32 start = _system->getMillis();
|
|
|
|
do {
|
|
|
|
if (updateGame) {
|
|
|
|
if (_chatText)
|
|
|
|
updateWithText();
|
|
|
|
else
|
|
|
|
update();
|
|
|
|
} else {
|
|
|
|
updateInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amount > 0)
|
|
|
|
_system->delayMillis(amount > 10 ? 10 : amount);
|
|
|
|
} while (!skipFlag() && _system->getMillis() < start + amount && !_quitFlag);
|
|
|
|
}
|
|
|
|
|
2008-05-04 15:56:28 +00:00
|
|
|
int KyraEngine_v2::checkInput(Button *buttonList, bool mainLoop) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::checkInput(%p, %d)", (const void*)buttonList, mainLoop);
|
|
|
|
updateInput();
|
|
|
|
|
|
|
|
int keys = 0;
|
2008-05-11 11:35:12 +00:00
|
|
|
int8 mouseWheel = 0;
|
2008-05-04 15:56:28 +00:00
|
|
|
|
|
|
|
while (_eventList.size()) {
|
|
|
|
Common::Event event = *_eventList.begin();
|
|
|
|
bool breakLoop = false;
|
|
|
|
|
|
|
|
switch (event.type) {
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' &&
|
|
|
|
(event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && mainLoop) {
|
|
|
|
const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990);
|
|
|
|
|
|
|
|
if (event.kbd.flags == Common::KBD_CTRL) {
|
|
|
|
loadGame(saveLoadSlot);
|
|
|
|
_eventList.clear();
|
|
|
|
breakLoop = true;
|
|
|
|
} else {
|
|
|
|
char savegameName[14];
|
|
|
|
sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0');
|
|
|
|
saveGame(saveLoadSlot, savegameName);
|
|
|
|
}
|
|
|
|
} else if (event.kbd.flags == Common::KBD_CTRL) {
|
|
|
|
if (event.kbd.keycode == 'd')
|
|
|
|
_debugger->attach();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Common::EVENT_MOUSEMOVE: {
|
|
|
|
Common::Point pos = getMousePos();
|
|
|
|
_mouseX = pos.x;
|
|
|
|
_mouseY = pos.y;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
|
|
case Common::EVENT_LBUTTONUP: {
|
|
|
|
Common::Point pos = getMousePos();
|
|
|
|
_mouseX = pos.x;
|
|
|
|
_mouseY = pos.y;
|
2008-05-05 18:50:42 +00:00
|
|
|
keys = (event.type == Common::EVENT_LBUTTONDOWN ? 199 : (200 | 0x800));
|
2008-05-04 15:56:28 +00:00
|
|
|
breakLoop = true;
|
|
|
|
} break;
|
|
|
|
|
2008-05-11 11:35:12 +00:00
|
|
|
case Common::EVENT_WHEELUP:
|
|
|
|
mouseWheel = -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Common::EVENT_WHEELDOWN:
|
|
|
|
mouseWheel = 1;
|
|
|
|
break;
|
|
|
|
|
2008-05-04 15:56:28 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_debugger->isAttached())
|
|
|
|
_debugger->onFrame();
|
|
|
|
|
|
|
|
if (breakLoop)
|
|
|
|
break;
|
|
|
|
|
|
|
|
_eventList.erase(_eventList.begin());
|
|
|
|
}
|
|
|
|
|
2008-05-11 11:35:12 +00:00
|
|
|
return gui_v2()->processButtonList(buttonList, keys | 0x8000, mouseWheel);
|
2008-05-02 14:48:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::updateInput() {
|
|
|
|
Common::Event event;
|
|
|
|
|
|
|
|
while (_eventMan->pollEvent(event)) {
|
|
|
|
switch (event.type) {
|
|
|
|
case Common::EVENT_QUIT:
|
|
|
|
_quitFlag = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE)
|
|
|
|
_eventList.push_back(Event(event, true));
|
|
|
|
else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL)
|
|
|
|
_quitFlag = true;
|
|
|
|
else
|
|
|
|
_eventList.push_back(event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
|
|
_eventList.push_back(Event(event, true));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Common::EVENT_MOUSEMOVE:
|
2008-05-05 18:50:42 +00:00
|
|
|
screen_v2()->updateScreen();
|
|
|
|
// fall through
|
|
|
|
|
|
|
|
case Common::EVENT_LBUTTONUP:
|
2008-05-11 11:35:12 +00:00
|
|
|
case Common::EVENT_WHEELUP:
|
|
|
|
case Common::EVENT_WHEELDOWN:
|
2008-05-02 14:48:19 +00:00
|
|
|
_eventList.push_back(event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::removeInputTop() {
|
|
|
|
if (!_eventList.empty())
|
|
|
|
_eventList.erase(_eventList.begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KyraEngine_v2::skipFlag() const {
|
|
|
|
for (Common::List<Event>::const_iterator i = _eventList.begin(); i != _eventList.end(); ++i) {
|
|
|
|
if (i->causedSkip)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::resetSkipFlag(bool removeEvent) {
|
|
|
|
for (Common::List<Event>::iterator i = _eventList.begin(); i != _eventList.end(); ++i) {
|
|
|
|
if (i->causedSkip) {
|
|
|
|
if (removeEvent)
|
|
|
|
_eventList.erase(i);
|
|
|
|
else
|
|
|
|
i->causedSkip = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KyraEngine_v2::checkSpecialSceneExit(int num, int x, int y) {
|
|
|
|
if (_specialExitTable[0+num] > x || _specialExitTable[5+num] > y ||
|
|
|
|
_specialExitTable[10+num] < x || _specialExitTable[15+num] < y)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::addShapeToPool(const uint8 *data, int realIndex, int shape) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d, %d)", data, realIndex, shape);
|
|
|
|
remShapeFromPool(realIndex);
|
|
|
|
_gameShapes[realIndex] = screen_v2()->makeShapeCopy(data, shape);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::addShapeToPool(uint8 *shpData, int index) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d)", shpData, index);
|
|
|
|
remShapeFromPool(index);
|
|
|
|
_gameShapes[index] = shpData;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::remShapeFromPool(int idx) {
|
|
|
|
ShapeMap::iterator iter = _gameShapes.find(idx);
|
|
|
|
if (iter != _gameShapes.end()) {
|
2008-05-07 14:20:37 +00:00
|
|
|
delete[] iter->_value;
|
2008-05-02 14:48:19 +00:00
|
|
|
iter->_value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 *KyraEngine_v2::getShapePtr(int shape) const {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::getShapePtr(%d)", shape);
|
|
|
|
ShapeMap::iterator iter = _gameShapes.find(shape);
|
|
|
|
if (iter == _gameShapes.end())
|
|
|
|
return 0;
|
|
|
|
return iter->_value;
|
|
|
|
}
|
|
|
|
|
2008-05-02 15:39:51 +00:00
|
|
|
void KyraEngine_v2::moveCharacter(int facing, int x, int y) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::moveCharacter(%d, %d, %d)", facing, x, y);
|
|
|
|
x &= ~3;
|
|
|
|
y &= ~1;
|
|
|
|
_mainCharacter.facing = facing;
|
|
|
|
|
|
|
|
Screen *scr = screen();
|
|
|
|
scr->hideMouse();
|
|
|
|
switch (facing) {
|
|
|
|
case 0:
|
|
|
|
while (_mainCharacter.y1 > y)
|
|
|
|
updateCharPosWithUpdate();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
while (_mainCharacter.x1 < x)
|
|
|
|
updateCharPosWithUpdate();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
while (_mainCharacter.y1 < y)
|
|
|
|
updateCharPosWithUpdate();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
while (_mainCharacter.x1 > x)
|
|
|
|
updateCharPosWithUpdate();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
scr->showMouse();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KyraEngine_v2::updateCharPosWithUpdate() {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::updateCharPosWithUpdate()");
|
|
|
|
updateCharPos(0, 0);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
int KyraEngine_v2::updateCharPos(int *table, int force) {
|
|
|
|
debugC(9, kDebugLevelMain, "KyraEngine_v2::updateCharPos(%p, %d)", (const void*)table, force);
|
|
|
|
if (_updateCharPosNextUpdate > _system->getMillis() && !force)
|
|
|
|
return 0;
|
2008-05-18 21:11:19 +00:00
|
|
|
_mainCharacter.x1 += _charAddXPosTable[_mainCharacter.facing];
|
|
|
|
_mainCharacter.y1 += _charAddYPosTable[_mainCharacter.facing];
|
2008-05-02 15:39:51 +00:00
|
|
|
updateCharAnimFrame(0, table);
|
|
|
|
_updateCharPosNextUpdate = _system->getMillis() + getCharacterWalkspeed() * _tickLength;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-05-02 14:48:19 +00:00
|
|
|
} // end of namespace Kyra
|
|
|
|
|