Initial commit
This commit is contained in:
1
engines/hdb/POTFILES
Normal file
1
engines/hdb/POTFILES
Normal file
@@ -0,0 +1 @@
|
||||
engines/hdb/metaengine.cpp
|
||||
3410
engines/hdb/ai-bots.cpp
Normal file
3410
engines/hdb/ai-bots.cpp
Normal file
File diff suppressed because it is too large
Load Diff
896
engines/hdb/ai-cinematic.cpp
Normal file
896
engines/hdb/ai-cinematic.cpp
Normal file
@@ -0,0 +1,896 @@
|
||||
/* 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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/gfx.h"
|
||||
#include "hdb/lua-script.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
static const char *cineTypeStr[] = {
|
||||
"C_NO_COMMAND",
|
||||
"C_STOPCINE",
|
||||
"C_LOCKPLAYER",
|
||||
"C_UNLOCKPLAYER",
|
||||
"C_SETCAMERA",
|
||||
"C_MOVECAMERA",
|
||||
"C_WAIT",
|
||||
"C_WAITUNTILDONE",
|
||||
"C_MOVEENTITY",
|
||||
"C_DIALOG",
|
||||
"C_ANIMENTITY",
|
||||
"C_RESETCAMERA",
|
||||
"C_SETENTITY",
|
||||
"C_STARTMAP",
|
||||
"C_MOVEPIC",
|
||||
"C_MOVEMASKEDPIC",
|
||||
"C_DRAWPIC",
|
||||
"C_DRAWMASKEDPIC",
|
||||
"C_FADEIN",
|
||||
"C_FADEOUT",
|
||||
"C_SPAWNENTITY",
|
||||
"C_PLAYSOUND",
|
||||
"C_CLEAR_FG",
|
||||
"C_SET_FG",
|
||||
"C_SET_BG",
|
||||
"C_FUNCTION",
|
||||
"C_ENTITYFACE",
|
||||
"C_USEENTITY",
|
||||
"C_REMOVEENTITY",
|
||||
"C_SETANIMFRAME",
|
||||
"C_TEXTOUT",
|
||||
"C_CENTERTEXTOUT",
|
||||
"C_PLAYVOICE",
|
||||
|
||||
"C_ENDLIST"
|
||||
};
|
||||
|
||||
void AI::processCines() {
|
||||
if (!_cineActive)
|
||||
return;
|
||||
|
||||
// Make sure Dialogs are timing out
|
||||
g_hdb->_window->checkDialogClose(0, 0);
|
||||
|
||||
// Make sure Cine Pics are drawing
|
||||
for (int i = 0; i < _numCineBlitList; i++) {
|
||||
if (_cineBlitList[i]->masked == false)
|
||||
_cineBlitList[i]->pic->draw(_cineBlitList[i]->x, _cineBlitList[i]->y);
|
||||
else
|
||||
_cineBlitList[i]->pic->drawMasked(_cineBlitList[i]->x, _cineBlitList[i]->y);
|
||||
}
|
||||
|
||||
// Check for Game Pause
|
||||
if (g_hdb->getPause())
|
||||
return;
|
||||
|
||||
bool bailOut = false;
|
||||
bool complete = false;
|
||||
|
||||
for (uint i = 0; i < _cine.size(); i++) {
|
||||
debug(3, "processCines: [%d] %s now: %d start: %d delay: %d", i, cineTypeStr[_cine[i]->cmdType],
|
||||
g_system->getMillis(), _cine[i]->start, _cine[i]->delay);
|
||||
|
||||
switch (_cine[i]->cmdType) {
|
||||
case C_STOPCINE:
|
||||
{
|
||||
char func[64];
|
||||
memset(func, 0, 64);
|
||||
|
||||
if (_cine[i]->title)
|
||||
Common::strlcpy(func, _cine[i]->title, 64);
|
||||
|
||||
cineCleanup();
|
||||
if (func[0])
|
||||
g_hdb->_lua->callFunction(func, 0);
|
||||
}
|
||||
break;
|
||||
case C_STARTMAP:
|
||||
{
|
||||
const char *title = _cine[i]->title;
|
||||
// free all gfx alloc'ed during cine
|
||||
cineFreeGfx();
|
||||
_cineActive = false;
|
||||
_playerLock = false;
|
||||
_cameraLock = false;
|
||||
g_hdb->_window->setInfobarDark(0);
|
||||
g_hdb->_gfx->setPointerState(1);
|
||||
_cine.resize(0);
|
||||
_numCineFreeList = 0;
|
||||
_numCineBlitList = 0;
|
||||
// if cine is aborted and an abort function was specified, call it
|
||||
if (_cineAborted && _cineAbortFunc)
|
||||
g_hdb->_lua->callFunction(_cineAbortFunc, 0);
|
||||
g_hdb->changeMap(title);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case C_LOCKPLAYER:
|
||||
_playerLock = true;
|
||||
complete = true;
|
||||
if (_player)
|
||||
stopEntity(_player);
|
||||
clearWaypoints();
|
||||
break;
|
||||
case C_UNLOCKPLAYER:
|
||||
_playerLock = false;
|
||||
complete = true;
|
||||
break;
|
||||
case C_SETCAMERA:
|
||||
_cameraX = _cine[i]->x;
|
||||
_cameraY = _cine[i]->y;
|
||||
g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
|
||||
_cameraLock = true;
|
||||
complete = true;
|
||||
break;
|
||||
case C_RESETCAMERA:
|
||||
{
|
||||
_cameraLock = false;
|
||||
int px, py;
|
||||
g_hdb->_ai->getPlayerXY(&px, &py);
|
||||
g_hdb->_map->centerMapXY(px + 16, py + 16);
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
case C_MOVECAMERA:
|
||||
_cameraLock = true;
|
||||
if (!(_cine[i]->start)) {
|
||||
debug(3, "C_MOVECAMERA: [%d] now: x: %f, y: %f, speed: %d", i, _cine[i]->x, _cine[i]->y, _cine[i]->speed);
|
||||
_cine[i]->xv = (((double)_cine[i]->x) - _cameraX) / (double)_cine[i]->speed;
|
||||
_cine[i]->yv = (((double)_cine[i]->y) - _cameraY) / (double)_cine[i]->speed;
|
||||
_cine[i]->start = 1;
|
||||
}
|
||||
_cameraX += _cine[i]->xv;
|
||||
_cameraY += _cine[i]->yv;
|
||||
debug(3, "C_MOVECAMERA: _cine[%d]->xv: %f, _cine[%d]->yv: %f", i, _cine[i]->xv, i, _cine[i]->yv);
|
||||
debug(3, "C_MOVECAMERA: abs(_cameraX - _cine[i]->x): %f, abs(_cameraY - _cine[i]->y): %f", fabs(_cameraX - _cine[i]->x), fabs(_cameraY - _cine[i]->y));
|
||||
if (fabs(_cameraX - _cine[i]->x) <= 1 && fabs(_cameraY - _cine[i]->y) <= 1) {
|
||||
_cameraX = _cine[i]->x;
|
||||
_cameraY = _cine[i]->y;
|
||||
complete = true;
|
||||
}
|
||||
g_hdb->_map->centerMapXY((int)_cameraX + 16, (int)_cameraY + 16);
|
||||
break;
|
||||
case C_WAIT:
|
||||
if (!(_cine[i]->start)) {
|
||||
_cine[i]->start = 1;
|
||||
_cine[i]->delay = g_system->getMillis() + _cine[i]->delay * 1000;
|
||||
} else if (_cine[i]->delay < g_system->getMillis())
|
||||
complete = true;
|
||||
else
|
||||
bailOut = true;
|
||||
break;
|
||||
case C_WAITUNTILDONE:
|
||||
if (!i)
|
||||
complete = true;
|
||||
else
|
||||
bailOut = true;
|
||||
|
||||
break;
|
||||
case C_SETENTITY:
|
||||
_cine[i]->e = locateEntity(_cine[i]->string);
|
||||
if (_cine[i]->e) {
|
||||
_cine[i]->e->tileX = (int)_cine[i]->x / kTileWidth;
|
||||
_cine[i]->e->x = (int)_cine[i]->x;
|
||||
_cine[i]->e->tileY = (int)_cine[i]->y / kTileHeight;
|
||||
_cine[i]->e->y = (int)_cine[i]->y;
|
||||
_cine[i]->e->level = (int)_cine[i]->x2;
|
||||
debug(2, "Found '%s' in setEntity", _cine[i]->string);
|
||||
} else
|
||||
warning("Can't locate '%s' in setEntity", _cine[i]->string);
|
||||
|
||||
complete = true;
|
||||
break;
|
||||
case C_MOVEENTITY:
|
||||
if (!_cine[i]->start) {
|
||||
AIEntity *e = locateEntity(_cine[i]->title);
|
||||
if (e) {
|
||||
_cine[i]->e = e;
|
||||
_cine[i]->e->moveSpeed = _cine[i]->speed;
|
||||
_cine[i]->e->level = (int)_cine[i]->x2;
|
||||
setEntityGoal(_cine[i]->e, (int)_cine[i]->x, (int)_cine[i]->y);
|
||||
_cine[i]->start = 1;
|
||||
} else {
|
||||
warning("Can't locate '%s' in moveEntity", _cine[i]->title);
|
||||
// If the entity can't be found, we consider this cinematic command completed
|
||||
complete = true;
|
||||
}
|
||||
} else {
|
||||
// Fix for bug #16421
|
||||
// Ensure that the entity _cine[i]->e still exists,
|
||||
// because it could have been removed, eg. if Guy shoots the chicken in Map 10
|
||||
AIEntity *e = locateEntity(_cine[i]->title);
|
||||
if (e) {
|
||||
_cine[i]->e = e;
|
||||
debug(3, "C_MOVEENTITY: %d, %s tileX: %d, goalX: %d tileY %d, goalY: %d", i, AIType2Str(_cine[i]->e->type), _cine[i]->e->tileX, _cine[i]->e->goalX, _cine[i]->e->tileY, _cine[i]->e->goalY);
|
||||
if (!_cine[i]->e->goalX)
|
||||
complete = true;
|
||||
} else {
|
||||
warning("Can't locate '%s' in moveEntity (_cine[%d]->start=%d)", _cine[i]->title, i, _cine[i]->start);
|
||||
// If the entity can't be found, we consider this cinematic command completed
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case C_ANIMENTITY:
|
||||
if (!_cine[i]->start) {
|
||||
AIEntity *e = locateEntity(_cine[i]->title);
|
||||
if (e) {
|
||||
_cine[i]->e = e;
|
||||
e->state = (AIState)_cine[i]->speed;
|
||||
_cine[i]->start = 1;
|
||||
if (_cine[i]->end) // Loop ?
|
||||
complete = true;
|
||||
e->animFrame = 0;
|
||||
e->animDelay = e->animCycle;
|
||||
animEntFrames(e);
|
||||
} else {
|
||||
warning("Can't locate '%s' in animEntity", _cine[i]->title);
|
||||
complete = true;
|
||||
}
|
||||
} else {
|
||||
AIEntity *e = _cine[i]->e;
|
||||
if (!e->animFrame && e->animDelay == e->animCycle) {
|
||||
e->state = STATE_STANDDOWN;
|
||||
e->animFrame = 0;
|
||||
e->animDelay = e->animCycle;
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case C_SETANIMFRAME:
|
||||
{
|
||||
AIEntity *e = locateEntity(_cine[i]->title);
|
||||
if (e) {
|
||||
e->state = (AIState)_cine[i]->start;
|
||||
e->animFrame = _cine[i]->end;
|
||||
e->animDelay = e->animCycle;
|
||||
animEntFrames(e);
|
||||
e->state = STATE_NONE;
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case C_ENTITYFACE:
|
||||
{
|
||||
AIEntity *e = locateEntity(_cine[i]->title);
|
||||
|
||||
if (e) {
|
||||
int d = (int)_cine[i]->x;
|
||||
e->dir = (AIDir)d;
|
||||
switch (e->dir) {
|
||||
case DIR_UP:
|
||||
e->state = STATE_STANDUP;
|
||||
break;
|
||||
case DIR_DOWN:
|
||||
e->state = STATE_STANDDOWN;
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
e->state = STATE_STANDLEFT;
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
e->state = STATE_STANDRIGHT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else
|
||||
warning("Can't find %s to ENTITYFACE", _cine[i]->title);
|
||||
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
case C_DIALOG:
|
||||
if (_cine[i]->start) {
|
||||
g_hdb->_window->openDialog(_cine[i]->title, -1, _cine[i]->string, 0, nullptr);
|
||||
g_hdb->_window->setDialogDelay(_cine[i]->delay);
|
||||
_cine[i]->start = 0;
|
||||
} else if (g_hdb->_window->getDialogDelay() < g_hdb->getTimeSlice())
|
||||
complete = true;
|
||||
break;
|
||||
case C_TEXTOUT:
|
||||
if (!_cine[i]->start) {
|
||||
g_hdb->_window->textOut(_cine[i]->title, _cine[i]->x, _cine[i]->y, _cine[i]->end);
|
||||
_cine[i]->start = 1;
|
||||
} else if (!g_hdb->_window->textOutActive())
|
||||
complete = true;
|
||||
break;
|
||||
case C_CENTERTEXTOUT:
|
||||
if (!_cine[i]->start) {
|
||||
g_hdb->_window->centerTextOut(_cine[i]->title, _cine[i]->y, _cine[i]->end);
|
||||
_cine[i]->start = 1;
|
||||
} else if (!g_hdb->_window->textOutActive())
|
||||
complete = true;
|
||||
break;
|
||||
case C_DRAWPIC:
|
||||
{
|
||||
Picture *p = cineFindInBlitList(_cine[i]->id);
|
||||
if (p == nullptr) {
|
||||
p = g_hdb->_gfx->loadPic(_cine[i]->string);
|
||||
cineAddToFreeList(p);
|
||||
cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, false);
|
||||
}
|
||||
_cine[i]->pic = p;
|
||||
_cine[i]->pic->draw((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
case C_DRAWMASKEDPIC:
|
||||
{
|
||||
Picture *p = cineFindInBlitList(_cine[i]->id);
|
||||
if (p == nullptr) {
|
||||
p = g_hdb->_gfx->loadPic(_cine[i]->string);
|
||||
cineAddToFreeList(p);
|
||||
cineAddToBlitList(_cine[i]->id, p, (int)_cine[i]->x, (int)_cine[i]->y, true);
|
||||
}
|
||||
_cine[i]->pic = p;
|
||||
_cine[i]->pic->drawMasked((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_MOVEPIC:
|
||||
if (!_cine[i]->start) {
|
||||
Picture *pic = cineFindInBlitList(_cine[i]->id);
|
||||
if (!pic) {
|
||||
pic = g_hdb->_gfx->loadPic(_cine[i]->string);
|
||||
cineAddToFreeList(pic);
|
||||
} else
|
||||
cineRemoveFromBlitList(_cine[i]->id);
|
||||
_cine[i]->pic = pic;
|
||||
_cine[i]->start = 1;
|
||||
}
|
||||
|
||||
cineRemoveFromBlitList(_cine[i]->id);
|
||||
_cine[i]->x += _cine[i]->xv;
|
||||
_cine[i]->y += _cine[i]->yv;
|
||||
cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, false);
|
||||
if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
|
||||
complete = true;
|
||||
break;
|
||||
|
||||
case C_MOVEMASKEDPIC:
|
||||
if (!_cine[i]->start) {
|
||||
Picture *pic = cineFindInBlitList(_cine[i]->id);
|
||||
if (!pic) {
|
||||
pic = g_hdb->_gfx->loadPic(_cine[i]->string);
|
||||
cineAddToFreeList(pic);
|
||||
} else
|
||||
cineRemoveFromBlitList(_cine[i]->id);
|
||||
_cine[i]->pic = pic;
|
||||
_cine[i]->start = 1;
|
||||
}
|
||||
|
||||
cineRemoveFromBlitList(_cine[i]->id);
|
||||
_cine[i]->x += _cine[i]->xv;
|
||||
_cine[i]->y += _cine[i]->yv;
|
||||
cineAddToBlitList(_cine[i]->id, _cine[i]->pic, (int)_cine[i]->x, (int)_cine[i]->y, true);
|
||||
if (abs((int)(_cine[i]->x - _cine[i]->x2)) <= 1 && abs((int)(_cine[i]->y - _cine[i]->y2)) <= 1)
|
||||
complete = true;
|
||||
break;
|
||||
|
||||
case C_USEENTITY:
|
||||
for (Common::Array<AIEntity *>::iterator it = _ents->begin(); it != _ents->end(); ++it) {
|
||||
if (Common::matchString((*it)->entityName, _cine[i]->string, true))
|
||||
g_hdb->useEntity((*it));
|
||||
}
|
||||
for (int k = 0; k < kMaxActions; k++) {
|
||||
if (Common::matchString(_actions[k].entityName, _cine[i]->string, true)) {
|
||||
checkActionList(&_dummyPlayer, _actions[k].x1, _actions[k].y1, false);
|
||||
checkActionList(&_dummyPlayer, _actions[k].x2, _actions[k].y2, false);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < kMaxAutoActions; j++) {
|
||||
if (Common::matchString(_autoActions[j].entityName, _cine[i]->string, true) && !_autoActions[j].activated)
|
||||
checkAutoList(&_dummyPlayer, _autoActions[j].x, _autoActions[j].y);
|
||||
}
|
||||
complete = true;
|
||||
break;
|
||||
case C_PLAYSOUND:
|
||||
g_hdb->_sound->playSound((int)_cine[i]->start);
|
||||
complete = true;
|
||||
break;
|
||||
case C_PLAYVOICE:
|
||||
g_hdb->_sound->playVoice((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
break;
|
||||
case C_FADEIN:
|
||||
if (!_cine[i]->start) {
|
||||
g_hdb->_gfx->setFade(true, (bool)_cine[i]->end, _cine[i]->speed);
|
||||
_cine[i]->start = 1;
|
||||
} else if (!g_hdb->_gfx->isFadeActive())
|
||||
complete = true;
|
||||
break;
|
||||
case C_FADEOUT:
|
||||
if (!_cine[i]->start) {
|
||||
g_hdb->_gfx->setFade(false, (bool)_cine[i]->end, _cine[i]->speed);
|
||||
_cine[i]->start = 1;
|
||||
} else if (!g_hdb->_gfx->isFadeActive())
|
||||
complete = true;
|
||||
break;
|
||||
case C_SPAWNENTITY:
|
||||
{
|
||||
int x2 = (int)_cine[i]->x2;
|
||||
int y2 = (int)_cine[i]->y2;
|
||||
spawn((AIType)x2, (AIDir)y2, (int)_cine[i]->x, (int)_cine[i]->y, _cine[i]->title, _cine[i]->string,
|
||||
_cine[i]->id, (AIDir)_cine[i]->start, (int)_cine[i]->end, (int)_cine[i]->delay, (int)_cine[i]->speed, 1);
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
case C_REMOVEENTITY:
|
||||
{
|
||||
AIEntity *e = locateEntity(_cine[i]->string);
|
||||
if (e)
|
||||
removeEntity(e);
|
||||
complete = true;
|
||||
}
|
||||
break;
|
||||
case C_CLEAR_FG:
|
||||
g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, -1);
|
||||
g_hdb->_map->removeFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
break;
|
||||
case C_SET_BG:
|
||||
g_hdb->_map->setMapBGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
|
||||
g_hdb->_map->addBGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
break;
|
||||
case C_SET_FG:
|
||||
g_hdb->_map->setMapFGTileIndex((int)_cine[i]->x, (int)_cine[i]->y, (int)_cine[i]->start);
|
||||
g_hdb->_map->addFGTileAnimation((int)_cine[i]->x, (int)_cine[i]->y);
|
||||
complete = true;
|
||||
break;
|
||||
case C_FUNCTION:
|
||||
g_hdb->_lua->callFunction(_cine[i]->title, 0);
|
||||
complete = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bailOut)
|
||||
return;
|
||||
|
||||
if (complete && _cine.size()) {
|
||||
delete _cine[i];
|
||||
_cine.remove_at(i);
|
||||
i--;
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AI::cineCleanup() {
|
||||
cineFreeGfx();
|
||||
_cineActive = false;
|
||||
// If aborted and abort function specified, call it
|
||||
if (_cineAborted && _cineAbortFunc)
|
||||
g_hdb->_lua->callFunction(_cineAbortFunc, 0);
|
||||
|
||||
_cameraLock = false;
|
||||
_playerLock = false;
|
||||
g_hdb->_window->setInfobarDark(0);
|
||||
g_hdb->_gfx->setPointerState(1);
|
||||
|
||||
int px, py;
|
||||
getPlayerXY(&px, &py);
|
||||
g_hdb->_map->centerMapXY(px + 16, py + 16);
|
||||
}
|
||||
|
||||
void AI::cineAbort() {
|
||||
for (uint i = 0; i < _cine.size(); i++) {
|
||||
if (_cine[i]->cmdType == C_STARTMAP || _cine[i]->cmdType == C_STOPCINE)
|
||||
_cine[0] = _cine[i];
|
||||
}
|
||||
|
||||
_cine.resize(1);
|
||||
|
||||
g_hdb->_window->closeAll();
|
||||
|
||||
if (_player)
|
||||
stopEntity(_player);
|
||||
_cineAborted = true;
|
||||
}
|
||||
|
||||
void AI::cineAddToBlitList(const char *id, Picture *pic, int x, int y, bool masked) {
|
||||
_cineBlitList[_numCineBlitList] = new CineBlit;
|
||||
_cineBlitList[_numCineBlitList]->id = id;
|
||||
_cineBlitList[_numCineBlitList]->pic = pic;
|
||||
_cineBlitList[_numCineBlitList]->x = x;
|
||||
_cineBlitList[_numCineBlitList]->y = y;
|
||||
_cineBlitList[_numCineBlitList]->masked = masked;
|
||||
_numCineBlitList++;
|
||||
}
|
||||
|
||||
Picture *AI::cineFindInBlitList(const char *name) {
|
||||
for (int i = 0; i < _numCineBlitList; i++) {
|
||||
if (Common::matchString(_cineBlitList[i]->id, name, true))
|
||||
return _cineBlitList[i]->pic;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AI::cineRemoveFromBlitList(const char *name) {
|
||||
for (int i = 0; i < _numCineBlitList; i++) {
|
||||
if (Common::matchString(_cineBlitList[i]->id, name, true)) {
|
||||
delete _cineBlitList[i];
|
||||
for (; i < _numCineBlitList - 1; i++)
|
||||
_cineBlitList[i] = _cineBlitList[i + 1];
|
||||
_numCineBlitList--;
|
||||
_cineBlitList[_numCineBlitList] = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AI::cineAddToFreeList(Picture *pic) {
|
||||
if (_numCineFreeList >= kMaxCineGfx) {
|
||||
warning("cineAddToFreeList: Too many gfx in Cinematic!");
|
||||
return;
|
||||
}
|
||||
_cineFreeList[_numCineFreeList] = pic;
|
||||
_numCineFreeList++;
|
||||
}
|
||||
|
||||
void AI::cineFreeGfx() {
|
||||
for (int i = 0; i < _numCineFreeList; i++)
|
||||
delete _cineFreeList[i];
|
||||
|
||||
_numCineFreeList = 0;
|
||||
}
|
||||
|
||||
void AI::cineStart(bool abortable, const char *abortFunc) {
|
||||
_cineAbortable = abortable;
|
||||
_cineAborted = false;
|
||||
_cineAbortFunc = abortFunc;
|
||||
_numCineBlitList = 0;
|
||||
_numCineFreeList = 0;
|
||||
_cineActive = true;
|
||||
_playerLock = false;
|
||||
_cameraLock = false;
|
||||
|
||||
_cine.clear();
|
||||
}
|
||||
|
||||
void AI::cineStop(const char *funcNext) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_STOPCINE;
|
||||
cmd->title = funcNext;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineStartMap(const char *mapName) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_STARTMAP;
|
||||
cmd->title = mapName;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineLockPlayer() {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_LOCKPLAYER;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineUnlockPlayer() {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_UNLOCKPLAYER;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSetCamera(int x, int y) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x * kTileWidth;
|
||||
cmd->y = y * kTileHeight;
|
||||
cmd->cmdType = C_SETCAMERA;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineResetCamera() {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_RESETCAMERA;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineMoveCamera(int x, int y, int speed) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->start = 0;
|
||||
cmd->x = x * kTileWidth;
|
||||
cmd->y = y * kTileHeight;
|
||||
cmd->speed = speed;
|
||||
debug(2, "Setting up C_MOVECAMERA: x: %f, y: %f", cmd->x, cmd->y);
|
||||
cmd->cmdType = C_MOVECAMERA;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineWait(int seconds) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->start = 0;
|
||||
cmd->cmdType = C_WAIT;
|
||||
cmd->delay = seconds;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineWaitUntilDone() {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_WAITUNTILDONE;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSetEntity(const char *entName, int x, int y, int level) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->string = entName;
|
||||
cmd->x = x * kTileWidth;
|
||||
cmd->y = y * kTileHeight;
|
||||
cmd->x2 = level;
|
||||
cmd->cmdType = C_SETENTITY;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineMoveEntity(const char *entName, int x, int y, int level, int speed) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->x2 = level;
|
||||
cmd->start = 0;
|
||||
cmd->speed = speed;
|
||||
cmd->title = entName;
|
||||
cmd->cmdType = C_MOVEENTITY;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineAnimEntity(const char *entName, AIState state, int loop) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->start = 0;
|
||||
cmd->title = entName;
|
||||
cmd->speed = state;
|
||||
cmd->end = loop;
|
||||
cmd->cmdType = C_ANIMENTITY;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSetAnimFrame(const char *entName, AIState state, int frame) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->start = state;
|
||||
cmd->title = entName;
|
||||
cmd->end = frame;
|
||||
cmd->cmdType = C_SETANIMFRAME;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineEntityFace(const char *luaName, double dir) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->title = luaName;
|
||||
cmd->x = dir;
|
||||
cmd->cmdType = C_ENTITYFACE;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSpawnEntity(AIType t, AIDir d, int x, int y, const char *func_init, const char *func_action,
|
||||
const char *func_use, AIDir d2, int level, int value1, int value2) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->cmdType = C_SPAWNENTITY;
|
||||
cmd->x2 = (double)t;
|
||||
cmd->y2 = (double)d;
|
||||
cmd->x = (double)x;
|
||||
cmd->y = (double)y;
|
||||
cmd->title = func_init;
|
||||
cmd->string = func_action;
|
||||
cmd->id = func_use;
|
||||
cmd->start = (int)d2;
|
||||
cmd->end = level;
|
||||
cmd->delay = value1;
|
||||
cmd->speed = value2;
|
||||
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineRemoveEntity(const char *entName) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->string = entName;
|
||||
cmd->cmdType = C_REMOVEENTITY;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineDialog(const char *title, const char *string, int seconds) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->title = title;
|
||||
cmd->string = string;
|
||||
cmd->delay = seconds;
|
||||
cmd->start = 1;
|
||||
if (!title || !string)
|
||||
warning("cineDialog: Missing Title or Text");
|
||||
cmd->cmdType = C_DIALOG;
|
||||
debug(6, "In cineDialog: C_DIALOG created. cmd->start: %d, cmd->title: %s", cmd->start, cmd->title);
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineTextOut(const char *text, int x, int y, int timer) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->title = text;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->end = timer;
|
||||
cmd->start = 0;
|
||||
cmd->cmdType = C_TEXTOUT;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineCenterTextOut(const char *text, int y, int timer) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->title = text;
|
||||
cmd->y = y;
|
||||
cmd->end = timer;
|
||||
cmd->start = 0;
|
||||
cmd->cmdType = C_CENTERTEXTOUT;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineDrawPic(const char *id, const char *pic, int x, int y) {
|
||||
if (!pic || !id) {
|
||||
warning("cineDrawPic: Missing ID or PIC");
|
||||
return;
|
||||
}
|
||||
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->string = pic;
|
||||
cmd->id = id;
|
||||
cmd->cmdType = C_DRAWPIC;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineDrawMaskedPic(const char *id, const char *pic, int x, int y) {
|
||||
if (!pic || !id) {
|
||||
warning("cineDrawMaskedPic: Missing ID or PIC");
|
||||
return;
|
||||
}
|
||||
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->string = pic;
|
||||
cmd->id = id;
|
||||
cmd->cmdType = C_DRAWMASKEDPIC;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineMovePic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
|
||||
if (!pic || !id) {
|
||||
warning("cineMovePic: Missing ID or PIC");
|
||||
return;
|
||||
}
|
||||
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x1;
|
||||
cmd->y = y1;
|
||||
cmd->x2 = x2;
|
||||
cmd->y2 = y2;
|
||||
cmd->speed = speed;
|
||||
cmd->xv = ((double)(x2-x1)) / (double)speed;
|
||||
cmd->yv = ((double)(y2-y1)) / (double)speed;
|
||||
cmd->start = 0;
|
||||
cmd->string = pic;
|
||||
cmd->id = id;
|
||||
cmd->cmdType = C_MOVEPIC;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineMoveMaskedPic(const char *id, const char *pic, int x1, int y1, int x2, int y2, int speed) {
|
||||
if (!pic || !id) {
|
||||
warning("cineMoveMaskedPic: Missing ID or PIC");
|
||||
return;
|
||||
}
|
||||
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x1;
|
||||
cmd->y = y1;
|
||||
cmd->x2 = x2;
|
||||
cmd->y2 = y2;
|
||||
cmd->speed = speed;
|
||||
cmd->xv = ((double)(x2-x1)) / (double)speed;
|
||||
cmd->yv = ((double)(y2-y1)) / (double)speed;
|
||||
cmd->start = 0;
|
||||
cmd->string = pic;
|
||||
cmd->id = id;
|
||||
cmd->cmdType = C_MOVEMASKEDPIC;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineUse(const char *entName) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->string = entName;
|
||||
cmd->cmdType = C_USEENTITY;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cinePlaySound(int index) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->start = index;
|
||||
cmd->cmdType = C_PLAYSOUND;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cinePlayVoice(int index, int actor) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = index;
|
||||
cmd->y = actor;
|
||||
cmd->cmdType = C_PLAYVOICE;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineFadeIn(bool isBlack, int steps) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->speed = steps;
|
||||
cmd->end = (int)isBlack;
|
||||
cmd->start = 0;
|
||||
cmd->cmdType = C_FADEIN;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineFadeOut(bool isBlack, int steps) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->speed = steps;
|
||||
cmd->end = (int)isBlack;
|
||||
cmd->start = 0;
|
||||
cmd->cmdType = C_FADEOUT;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineClearForeground(int x, int y) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->cmdType = C_CLEAR_FG;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSetBackground(int x, int y, int index) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->start = index;
|
||||
cmd->cmdType = C_SET_BG;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineSetForeground(int x, int y, int index) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->x = x;
|
||||
cmd->y = y;
|
||||
cmd->start = index;
|
||||
cmd->cmdType = C_SET_FG;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
void AI::cineFunction(const char *func) {
|
||||
CineCommand *cmd = new CineCommand;
|
||||
cmd->title = func;
|
||||
cmd->cmdType = C_FUNCTION;
|
||||
_cine.push_back(cmd);
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
2614
engines/hdb/ai-funcs.cpp
Normal file
2614
engines/hdb/ai-funcs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2285
engines/hdb/ai-init.cpp
Normal file
2285
engines/hdb/ai-init.cpp
Normal file
File diff suppressed because it is too large
Load Diff
317
engines/hdb/ai-inventory.cpp
Normal file
317
engines/hdb/ai-inventory.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/* 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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
// Add entity to Player's Inventory
|
||||
bool AI::addToInventory(AIEntity *e) {
|
||||
switch (e->type) {
|
||||
case ITEM_GEM_WHITE:
|
||||
_numGems++;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
case ITEM_GEM_BLUE:
|
||||
_numGems += 5;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
case ITEM_GEM_RED:
|
||||
_numGems += 10;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
case ITEM_GEM_GREEN:
|
||||
_numGems += 100;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
case ITEM_GOO_CUP:
|
||||
_numGooCups++;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
case ITEM_MONKEYSTONE:
|
||||
_numMonkeystones++;
|
||||
removeEntity(e);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (_numInventory >= kMaxInventory) {
|
||||
g_hdb->_window->openMessageBar("Your inventory is full.", 5);
|
||||
return false;
|
||||
}
|
||||
|
||||
_inventory[_numInventory].ent = *e;
|
||||
_numInventory++;
|
||||
|
||||
// If weapon, ready it
|
||||
switch (e->type) {
|
||||
case ITEM_CLUB:
|
||||
case ITEM_ROBOSTUNNER:
|
||||
case ITEM_SLUGSLINGER:
|
||||
g_hdb->_window->chooseWeapon(e->type);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printYouGotMsg(e->printedName);
|
||||
removeEntity(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AI::purgeInventory() {
|
||||
memset(&_inventory, 0, sizeof(InvEnt) * kMaxInventory);
|
||||
_numInventory = 0;
|
||||
}
|
||||
|
||||
// Clear out the Player inventory except Gems,
|
||||
// Monkeystones and Goo Cups unless its marked
|
||||
void AI::clearInventory() {
|
||||
int keepslot = 0;
|
||||
for (int i = 0; i < _numInventory; i++) {
|
||||
if (!_inventory[i].keep) {
|
||||
_inventory[i].reset();
|
||||
} else {
|
||||
if (i != keepslot) {
|
||||
_inventory[keepslot] = _inventory[i];
|
||||
_inventory[i].reset();
|
||||
}
|
||||
keepslot++;
|
||||
}
|
||||
}
|
||||
_numInventory = keepslot;
|
||||
}
|
||||
|
||||
AIEntity *AI::getInvItem(int which) {
|
||||
if (which >= _numInventory)
|
||||
return nullptr;
|
||||
return &_inventory[which].ent;
|
||||
}
|
||||
|
||||
int AI::queryInventory(const char *string) {
|
||||
if (!scumm_stricmp(string, "monkeystone"))
|
||||
return getMonkeystoneAmount();
|
||||
if (!scumm_stricmp(string, "goo"))
|
||||
return getGooCupAmount();
|
||||
if (!scumm_stricmp(string, "gem"))
|
||||
return getGemAmount();
|
||||
|
||||
if (!_numInventory)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
for (int i = _numInventory - 1; i >= 0; i--)
|
||||
if (strstr(_inventory[i].ent.entityName, string))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool AI::removeInvItem(const char *string, int amount) {
|
||||
// Check specially for Gems, Monkeystones and Goo Cups
|
||||
if (!scumm_stricmp(string, "gem")) {
|
||||
_numGems -= amount;
|
||||
return true;
|
||||
} else if (!scumm_stricmp(string, "monkeystone")) {
|
||||
_numMonkeystones -= amount;
|
||||
return true;
|
||||
} else if (!scumm_stricmp(string, "goo")) {
|
||||
_numGooCups -= amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_numInventory)
|
||||
return false;
|
||||
|
||||
bool found;
|
||||
do {
|
||||
found = false;
|
||||
|
||||
for (int i = _numInventory - 1; i >= 0; i--)
|
||||
if (strstr(_inventory[i].ent.entityName, string)) {
|
||||
int j = i;
|
||||
_inventory[j].reset();
|
||||
while (j < _numInventory - 1) {
|
||||
_inventory[j] = _inventory[j + 1];
|
||||
_inventory[j + 1].reset();
|
||||
j++;
|
||||
}
|
||||
_numInventory--;
|
||||
amount--;
|
||||
found = true;
|
||||
if (!amount)
|
||||
break;
|
||||
}
|
||||
} while (found && amount);
|
||||
|
||||
// if we haven't removed them all, return false
|
||||
if (amount)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int AI::queryInventoryType(AIType which) {
|
||||
if (which == ITEM_MONKEYSTONE)
|
||||
return getMonkeystoneAmount();
|
||||
if (which == ITEM_GOO_CUP)
|
||||
return getGooCupAmount();
|
||||
if (which == ITEM_GEM_WHITE)
|
||||
return getGemAmount();
|
||||
|
||||
if (!_numInventory)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < _numInventory; i++) {
|
||||
if (_inventory[i].ent.type == which)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int AI::queryInventoryTypeSlot(AIType which) {
|
||||
if (!_numInventory)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < _numInventory; i++) {
|
||||
if (_inventory[i].ent.type == which)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AI::removeInvItemType(AIType which, int amount) {
|
||||
// Check specially for Gems, Monkeystones and Goo Cups
|
||||
if (which == ITEM_GEM_WHITE) {
|
||||
_numGems -= amount;
|
||||
return true;
|
||||
} else if (which == ITEM_MONKEYSTONE) {
|
||||
_numMonkeystones -= amount;
|
||||
return true;
|
||||
} else if (which == ITEM_GOO_CUP) {
|
||||
_numGooCups -= amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_numInventory)
|
||||
return false;
|
||||
|
||||
bool found;
|
||||
do {
|
||||
found = false;
|
||||
|
||||
for (int i = 0; i < _numInventory; i++) {
|
||||
if (_inventory[i].ent.type == which) {
|
||||
int j = i;
|
||||
_inventory[j].reset();
|
||||
while (j < _numInventory - 1) {
|
||||
_inventory[j] = _inventory[j + 1];
|
||||
_inventory[j + 1].reset();
|
||||
j++;
|
||||
}
|
||||
_numInventory--;
|
||||
amount--;
|
||||
found = true;
|
||||
if (!amount)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (found && amount);
|
||||
|
||||
// if we haven't removed them all, return false
|
||||
if (amount)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AI::addItemToInventory(AIType type, int amount, const char *funcInit, const char *funcAction, const char *funcUse) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
spawn(type, DIR_UP, 0, 0, funcInit, funcAction, funcUse, DIR_UP, 1, 0, 0, 1);
|
||||
AIEntity *e = findEntity(0, 0);
|
||||
if (!e)
|
||||
return false;
|
||||
if (!addToInventory(e))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AI::keepInvItem(AIType type) {
|
||||
for (int i = 0; i < _numInventory; i++) {
|
||||
if (_inventory[i].ent.type == type)
|
||||
_inventory[i].keep = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void AI::printYouGotMsg(const char *name) {
|
||||
if (!name || !name[0])
|
||||
return;
|
||||
|
||||
Common::String youGotString = Common::String::format("Got %s", name);
|
||||
g_hdb->_window->textOut(youGotString.c_str(), kYouGotX, g_hdb->_ai->_youGotY, 120);
|
||||
}
|
||||
|
||||
void AI::newDelivery(const char *itemTextName, const char *itemGfxName, const char *destTextName, const char *destGfxName, const char *id) {
|
||||
int i = _numDeliveries;
|
||||
|
||||
if (i == kMaxDeliveries) {
|
||||
g_hdb->_window->openMessageBar("You have too many deliveries already!", 3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemTextName)
|
||||
Common::strlcpy(_deliveries[i].itemTextName, itemTextName, sizeof(_deliveries[0].itemTextName));
|
||||
if (itemGfxName)
|
||||
Common::strlcpy(_deliveries[i].itemGfxName, itemGfxName, sizeof(_deliveries[0].itemGfxName));
|
||||
if (destTextName)
|
||||
Common::strlcpy(_deliveries[i].destTextName, destTextName, sizeof(_deliveries[0].destTextName));
|
||||
if (destGfxName)
|
||||
Common::strlcpy(_deliveries[i].destGfxName, destGfxName, sizeof(_deliveries[0].destGfxName));
|
||||
|
||||
Common::strlcpy(_deliveries[i].id, id, sizeof(_deliveries[0].id));
|
||||
|
||||
_numDeliveries++;
|
||||
|
||||
g_hdb->_window->openDeliveries(true);
|
||||
}
|
||||
|
||||
bool AI::completeDelivery(const char *id) {
|
||||
for (int i = 0; i < _numDeliveries; i++) {
|
||||
if (!scumm_stricmp(_deliveries[i].id, id)) {
|
||||
for (; i < _numDeliveries; i++)
|
||||
_deliveries[i] = _deliveries[i + 1];
|
||||
_numDeliveries--;
|
||||
if (g_hdb->isPPC())
|
||||
g_hdb->_sound->playSound(SND_QUEST_COMPLETE);
|
||||
else
|
||||
g_hdb->_sound->playVoice(GUY_COMPLETED, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
864
engines/hdb/ai-lists.cpp
Normal file
864
engines/hdb/ai-lists.cpp
Normal file
@@ -0,0 +1,864 @@
|
||||
/* 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
|
||||
* 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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/ai-player.h"
|
||||
#include "hdb/file-manager.h"
|
||||
#include "hdb/gfx.h"
|
||||
#include "hdb/lua-script.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
/*
|
||||
Adds a tile to an animation list
|
||||
*/
|
||||
void AI::addAnimateTarget(int x, int y, int start, int end, AnimSpeed speed, bool killAuto, bool inMap, const char *tileName) {
|
||||
AnimTarget *at = new AnimTarget;
|
||||
|
||||
at->x = x;
|
||||
at->y = y;
|
||||
at->start = start;
|
||||
at->end = end;
|
||||
at->killAuto = killAuto; // Doesn't actually kill it, deactivates it
|
||||
|
||||
// Set animCycle and animFrame as per speed
|
||||
switch (speed) {
|
||||
case ANIM_SLOW:
|
||||
at->animCycle = 10;
|
||||
at->animFrame = 10;
|
||||
break;
|
||||
case ANIM_NORMAL:
|
||||
default:
|
||||
at->animCycle = 6;
|
||||
at->animFrame = 6;
|
||||
break;
|
||||
case ANIM_FAST:
|
||||
at->animCycle = 2;
|
||||
at->animFrame = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set +1/-1 for tile anim direction
|
||||
if ((end - start) > 0)
|
||||
at->vel = 1;
|
||||
else
|
||||
at->vel = -1;
|
||||
|
||||
// Set Info if this is not an inMap animation
|
||||
at->inMap = inMap;
|
||||
if (!inMap) {
|
||||
char name[32];
|
||||
for (int i = start; i <= end; i++) {
|
||||
if (i < 10)
|
||||
snprintf(name, 32, "%s0%d", tileName, i + 1);
|
||||
else
|
||||
snprintf(name, 32, "%s%d", tileName, i + 1);
|
||||
uint32 size = g_hdb->_fileMan->getLength(name, TYPE_TILE32);
|
||||
at->gfxList[i] = g_hdb->_gfx->getTileGfx(name, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert in the beginning
|
||||
_animTargets.insert_at(0, at);
|
||||
}
|
||||
|
||||
/*
|
||||
Animate _animTargets
|
||||
Called every frame
|
||||
*/
|
||||
void AI::animateTargets() {
|
||||
int mx, my;
|
||||
g_hdb->_map->getMapXY(&mx, &my);
|
||||
|
||||
for (uint i = 0; i < _animTargets.size(); i++) {
|
||||
AnimTarget *at = _animTargets[i];
|
||||
debug(9, "AnimTarget #%i: at: at->x: %d, at->y: %d, at->start: %d, at->end: %d, at->vel: %d", i, at->x, at->y, at->start, at->end, at->vel);
|
||||
|
||||
// Draw Non-map stuff every frame
|
||||
if (!at->inMap)
|
||||
// FIXME: Out of bounds reference to gfxList
|
||||
at->gfxList[at->start]->drawMasked(at->x - mx, at->y - my);
|
||||
|
||||
// Frame Timer
|
||||
if (at->animFrame-- < 1) {
|
||||
at->animFrame = at->animCycle;
|
||||
|
||||
if (at->inMap) {
|
||||
// Animate Map Tiles
|
||||
int layer = 0; // BG layer
|
||||
if (!(at->start == g_hdb->_map->getMapBGTileIndex(at->x, at->y)))
|
||||
layer = 1;
|
||||
|
||||
// Change Tile Anim
|
||||
at->start += at->vel;
|
||||
|
||||
// Set it back in map
|
||||
if (!layer)
|
||||
g_hdb->_map->setMapBGTileIndex(at->x, at->y, at->start);
|
||||
else
|
||||
g_hdb->_map->setMapFGTileIndex(at->x, at->y, at->start);
|
||||
} else {
|
||||
// Animate non-map tiles
|
||||
at->start++;
|
||||
}
|
||||
|
||||
// Animation Finished ?
|
||||
if (at->start == at->end) {
|
||||
|
||||
if (at->killAuto)
|
||||
autoDeactivate(at->x, at->y);
|
||||
|
||||
delete _animTargets[i];
|
||||
_animTargets.remove_at(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AI::addBridgeExtend(int x, int y, int bridgeType) {
|
||||
if (_numBridges >= kMaxBridges)
|
||||
return;
|
||||
|
||||
if (bridgeType == _targetBridgeU)
|
||||
_bridges[_numBridges].dir = DIR_UP;
|
||||
else if (bridgeType == _targetBridgeD)
|
||||
_bridges[_numBridges].dir = DIR_DOWN;
|
||||
else if (bridgeType == _targetBridgeL)
|
||||
_bridges[_numBridges].dir = DIR_LEFT;
|
||||
else if (bridgeType == _targetBridgeR)
|
||||
_bridges[_numBridges].dir = DIR_RIGHT;
|
||||
|
||||
_bridges[_numBridges].delay = 5;
|
||||
_bridges[_numBridges].x = x;
|
||||
_bridges[_numBridges].y = y;
|
||||
_bridges[_numBridges].anim = 0;
|
||||
|
||||
if (g_hdb->_map->onScreen(_bridges[_numBridges].x, _bridges[_numBridges].y))
|
||||
g_hdb->_sound->playSound(SND_BRIDGE_START);
|
||||
|
||||
_numBridges++;
|
||||
}
|
||||
|
||||
void AI::animateBridges() {
|
||||
// out quick!
|
||||
if (!_numBridges)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < _numBridges; i++) {
|
||||
if (_bridges[i].delay-- > 0)
|
||||
continue;
|
||||
|
||||
_bridges[i].delay = 5;
|
||||
bool done = false;
|
||||
int xv = 0;
|
||||
int yv = 0;
|
||||
|
||||
switch (_bridges[i].dir) {
|
||||
case DIR_UP:
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeU + _bridges[i].anim);
|
||||
_bridges[i].anim++;
|
||||
if (_bridges[i].anim > 2) {
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeMidUD);
|
||||
yv = -1;
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
case DIR_DOWN:
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeD + _bridges[i].anim);
|
||||
_bridges[i].anim++;
|
||||
if (_bridges[i].anim > 2) {
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeMidUD);
|
||||
yv = 1;
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeL + _bridges[i].anim);
|
||||
_bridges[i].anim++;
|
||||
if (_bridges[i].anim > 2) {
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeMidLR);
|
||||
xv = -1;
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeR + _bridges[i].anim);
|
||||
_bridges[i].anim++;
|
||||
if (_bridges[i].anim > 2) {
|
||||
g_hdb->_map->setMapFGTileIndex(_bridges[i].x, _bridges[i].y, _targetBridgeMidLR);
|
||||
xv = 1;
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
case DIR_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// is this bridge done extending one chunk?
|
||||
if (done) {
|
||||
if (g_hdb->_map->onScreen(_bridges[i].x, _bridges[i].y))
|
||||
g_hdb->_sound->playSound(SND_BRIDGE_EXTEND);
|
||||
_bridges[i].anim = 0;
|
||||
_bridges[i].x += xv;
|
||||
_bridges[i].y += yv;
|
||||
int tileIndex = g_hdb->_map->getMapFGTileIndex(_bridges[i].x, _bridges[i].y);
|
||||
uint32 flags = g_hdb->_map->getMapBGTileFlags(_bridges[i].x, _bridges[i].y);
|
||||
if (!flags || (flags & kFlagMetal) || tileIndex >= 0 || (flags & kFlagSolid)) {
|
||||
if (g_hdb->_map->onScreen(_bridges[i].x, _bridges[i].y))
|
||||
g_hdb->_sound->playSound(SND_BRIDGE_END);
|
||||
// TODO: CHECKME - Using i as an index looks very wrong as the for statement uses j.
|
||||
// This results in copying multiple times the same data
|
||||
for (int j = 0; j < _numBridges - 1; j++)
|
||||
memcpy(&_bridges[i], &_bridges[i + 1], sizeof(Bridge));
|
||||
_numBridges--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AI::addToFairystones(int index, int tileX, int tileY, int sourceOrDest) {
|
||||
if (!sourceOrDest) {
|
||||
_fairystones[index].srcX = tileX;
|
||||
_fairystones[index].srcY = tileY;
|
||||
} else {
|
||||
_fairystones[index].destX = tileX;
|
||||
_fairystones[index].destY = tileY;
|
||||
}
|
||||
}
|
||||
|
||||
int AI::checkFairystones(int tileX, int tileY) {
|
||||
for (int i = 0; i < kMaxFairystones; i++) {
|
||||
if (_fairystones[i].destX == tileX && _fairystones[i].destY == tileY)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add an action location to the list of possible actions
|
||||
// Each action must be paired with another of the same number
|
||||
void AI::addToActionList(int actionIndex, int x, int y, char *luaFuncInit, char *luaFuncUse) {
|
||||
if (!_actions[actionIndex].x1) {
|
||||
_actions[actionIndex].x1 = x;
|
||||
_actions[actionIndex].y1 = y;
|
||||
if (luaFuncInit[0] != '*')
|
||||
Common::strlcpy(_actions[actionIndex].luaFuncInit, luaFuncInit, 32);
|
||||
if (luaFuncUse[0] != '*')
|
||||
Common::strlcpy(_actions[actionIndex].luaFuncUse, luaFuncUse, 32);
|
||||
|
||||
if (_actions[actionIndex].luaFuncInit[0]) {
|
||||
g_hdb->_lua->callFunction(_actions[actionIndex].luaFuncInit, 2);
|
||||
Common::strlcpy(_actions[actionIndex].entityName, g_hdb->_lua->getStringOffStack(), 32);
|
||||
Common::strlcpy(_actions[actionIndex].entityName, g_hdb->_lua->getStringOffStack(), 32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_actions[actionIndex].x2) {
|
||||
_actions[actionIndex].x2 = x;
|
||||
_actions[actionIndex].y2 = y;
|
||||
if (luaFuncInit[0] != '*')
|
||||
Common::strlcpy(_actions[actionIndex].luaFuncInit, luaFuncInit, 32);
|
||||
if (luaFuncUse[0] != '*')
|
||||
Common::strlcpy(_actions[actionIndex].luaFuncUse, luaFuncUse, 32);
|
||||
|
||||
if (_actions[actionIndex].luaFuncInit[0]) {
|
||||
g_hdb->_lua->callFunction(_actions[actionIndex].luaFuncInit, 2);
|
||||
Common::strlcpy(_actions[actionIndex].entityName, g_hdb->_lua->getStringOffStack(), 32);
|
||||
Common::strlcpy(_actions[actionIndex].entityName, g_hdb->_lua->getStringOffStack(), 32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
warning("Adding a 3rd action to ACTION-%d is illegal", actionIndex);
|
||||
}
|
||||
|
||||
// Checks if the location passed-in matches an action pair.
|
||||
// If so, activate it if possible. Returns TRUE for finding pair.
|
||||
bool AI::checkActionList(AIEntity *e, int x, int y, bool lookAndGrab) {
|
||||
for (int i = 0; i < kMaxActions; i++) {
|
||||
if ((_actions[i].x1 == x && _actions[i].y1 == y) || (_actions[i].x2 == x && _actions[i].y2 == y)) {
|
||||
int targetX = _actions[i].x2;
|
||||
int targetY = _actions[i].y2;
|
||||
bool success;
|
||||
|
||||
// Choose target co-ordinates
|
||||
if (x == targetX && y == targetY) {
|
||||
targetX = _actions[i].x1;
|
||||
targetY = _actions[i].y1;
|
||||
}
|
||||
|
||||
// Is this an actual switch?
|
||||
uint32 flags = g_hdb->_map->getMapFGTileFlags(x, y);
|
||||
if (!flags)
|
||||
flags = g_hdb->_map->getMapBGTileFlags(x, y);
|
||||
if (!(flags & kFlagSolid) && (_player->tileX != x && _player->tileY != y))
|
||||
return false;
|
||||
// Closing on something?
|
||||
if (findEntity(targetX, targetY))
|
||||
return false;
|
||||
|
||||
success = activateAction(e, x, y, targetX, targetY);
|
||||
|
||||
// If successful, remove action from list
|
||||
if (success) {
|
||||
_actions[i].x1 = _actions[i].y1 = _actions[i].x2 = _actions[i].y2 = 0;
|
||||
|
||||
// Call Lua Use function if it exists
|
||||
if (_actions[i].luaFuncUse[0]) {
|
||||
g_hdb->_lua->callFunction(_actions[i].luaFuncUse, 0);
|
||||
}
|
||||
|
||||
} else if (e == _player && !checkForTouchplate(x, y))
|
||||
addWaypoint(e->tileX, e->tileY, x, y, e->level);
|
||||
|
||||
if (lookAndGrab && e == _player) {
|
||||
lookAtXY(x, y);
|
||||
animGrabbing();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AI::addToHereList(const char *entName, int x, int y) {
|
||||
HereT *h = new HereT;
|
||||
Common::strlcpy(h->entName, entName, 32);
|
||||
h->x = x;
|
||||
h->y = y;
|
||||
_hereList->push_back(h);
|
||||
}
|
||||
|
||||
HereT *AI::findHere(int x, int y) {
|
||||
for (Common::Array<HereT *>::iterator it = _hereList->begin(); it != _hereList->end(); ++it) {
|
||||
if ((*it)->x == x && (*it)->y == y)
|
||||
return *it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AI::addToAutoList(int x, int y, const char *luaFuncInit, const char *luaFuncUse) {
|
||||
for (int i = 0; i < kMaxAutoActions; i++) {
|
||||
if (!_autoActions[i].x) {
|
||||
_autoActions[i].x = x;
|
||||
_autoActions[i].y = y;
|
||||
_autoActions[i].activated = false;
|
||||
if (luaFuncInit[0] != '*')
|
||||
Common::strlcpy(&_autoActions[i].luaFuncInit[0], luaFuncInit, 32);
|
||||
if (luaFuncUse[0] != '*')
|
||||
Common::strlcpy(&_autoActions[i].luaFuncUse[0], luaFuncUse, 32);
|
||||
|
||||
if (_autoActions[i].luaFuncInit[0]) {
|
||||
g_hdb->_lua->callFunction(_autoActions[i].luaFuncInit, 2);
|
||||
const char *get = g_hdb->_lua->getStringOffStack();
|
||||
if (!get)
|
||||
return;
|
||||
Common::strlcpy(&_autoActions[i].entityName[0], get, 32);
|
||||
get = g_hdb->_lua->getStringOffStack();
|
||||
if (!get)
|
||||
return;
|
||||
Common::strlcpy(&_autoActions[i].entityName[0], get, 32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AI::autoDeactivate(int x, int y) {
|
||||
for (int i = 0; i < kMaxAutoActions; i++) {
|
||||
if (_autoActions[i].x == x && _autoActions[i].y == y) {
|
||||
_autoActions[i].activated = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AI::activateAction(AIEntity *e, int x, int y, int targetX, int targetY) {
|
||||
bool success = false;
|
||||
int tileIndex = g_hdb->_map->getMapFGTileIndex(x, y);
|
||||
|
||||
// If FG tile invisivle or grating, ignore if
|
||||
int fgFlags = g_hdb->_map->getMapFGTileFlags(x, y);
|
||||
if (fgFlags & (kFlagInvisible | kFlagGrating))
|
||||
tileIndex = -1;
|
||||
|
||||
if (tileIndex < 0)
|
||||
tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
// Check which tile is going to activate
|
||||
if (tileIndex == _useSwitchOff || tileIndex == _useSwitchOff + 1)
|
||||
success = useSwitch(e, x, y, targetX, targetY, _useSwitchOn);
|
||||
else if (tileIndex == _useSwitchOn)
|
||||
success = useSwitchOn(e, x, y, targetX, targetY, _useSwitchOff);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _useHandswitchOff || tileIndex == _useHandswitchOff + 1)
|
||||
success = useSwitch(e, x, y, targetX, targetY, _useHandswitchOn);
|
||||
else if (tileIndex == _useHandswitchOn)
|
||||
success = useSwitchOn(e, x, y, targetX, targetY, _useHandswitchOff);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _kcHolderWhiteOff || tileIndex == _kcHolderWhiteOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderWhiteOn, ITEM_KEYCARD_WHITE, "I need a White Keycard.");
|
||||
else if (tileIndex == _kcHolderWhiteOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderWhiteOff, ITEM_KEYCARD_WHITE);
|
||||
else if (tileIndex == _kcHolderBlueOff || tileIndex == _kcHolderBlueOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderBlueOn, ITEM_KEYCARD_BLUE, "I need a Blue Keycard.");
|
||||
else if (tileIndex == _kcHolderBlueOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderBlueOff, ITEM_KEYCARD_BLUE);
|
||||
else if (tileIndex == _kcHolderRedOff || tileIndex == _kcHolderRedOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderRedOn, ITEM_KEYCARD_RED, "I need a Red Keycard.");
|
||||
else if (tileIndex == _kcHolderRedOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderRedOff, ITEM_KEYCARD_RED);
|
||||
else if (tileIndex == _kcHolderGreenOff || tileIndex == _kcHolderGreenOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderGreenOn, ITEM_KEYCARD_GREEN, "I need a Green Keycard.");
|
||||
else if (tileIndex == _kcHolderGreenOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderGreenOff, ITEM_KEYCARD_GREEN);
|
||||
else if (tileIndex == _kcHolderPurpleOff || tileIndex == _kcHolderPurpleOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderPurpleOn, ITEM_KEYCARD_PURPLE, "I need a Purple Keycard.");
|
||||
else if (tileIndex == _kcHolderPurpleOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderPurpleOff, ITEM_KEYCARD_PURPLE);
|
||||
else if (tileIndex == _kcHolderBlackOff || tileIndex == _kcHolderBlackOff + 1)
|
||||
success = useLockedSwitch(e, x, y, targetX, targetY, _kcHolderBlackOn, ITEM_KEYCARD_BLACK, "I need a Black Keycard.");
|
||||
else if (tileIndex == _kcHolderBlackOn)
|
||||
success = useLockedSwitchOn(e, x, y, targetX, targetY, _kcHolderBlackOff, ITEM_KEYCARD_BLACK);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _useSwitch2Off || tileIndex == _useSwitch2Off + 1)
|
||||
success = useSwitch2(e, x, y, targetX, targetY);
|
||||
else if (tileIndex == _useHolderEmpty || tileIndex == _useHolderEmpty + 1)
|
||||
success = useCellHolder(e, x, y, targetX, targetY);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _targetDoorN || tileIndex == _targetDoorN + 3)
|
||||
success = useAutoDoorOpenClose(e, x, y);
|
||||
else if (tileIndex == _targetDoorP || tileIndex == _targetDoorP + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorS || tileIndex == _targetDoorS + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorNv || tileIndex == _targetDoorNv + 3)
|
||||
success = useAutoDoorOpenClose(e, x, y);
|
||||
else if (tileIndex == _targetDoorPv || tileIndex == _targetDoorPv + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorSv || tileIndex == _targetDoorSv + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _targetDoorN || tileIndex == _targetDoor2N + 3)
|
||||
success = useAutoDoorOpenClose(e, x, y);
|
||||
else if (tileIndex == _targetDoorP || tileIndex == _targetDoor2P + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorS || tileIndex == _targetDoor2S + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorNv || tileIndex == _targetDoor2Nv + 3)
|
||||
success = useAutoDoorOpenClose(e, x, y);
|
||||
else if (tileIndex == _targetDoorPv || tileIndex == _targetDoor2Pv + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
else if (tileIndex == _targetDoorSv || tileIndex == _targetDoor2Sv + 3)
|
||||
success = useDoorOpenCloseBot(e, x, y);
|
||||
//-------------------------------------------------------------------
|
||||
else if (tileIndex == _touchplateOff)
|
||||
success = useTouchplate(e, x, y, targetX, targetY, _touchplateOn);
|
||||
else if (tileIndex == _touchplateOn)
|
||||
success = useTouchplateOn(e, x, y, targetX, targetY, _touchplateOff);
|
||||
else if (tileIndex == _templeTouchpOff)
|
||||
success = useTouchplate(e, x, y, targetX, targetY, _templeTouchpOn);
|
||||
else if (tileIndex == _templeTouchpOn)
|
||||
success = useTouchplateOn(e, x, y, targetX, targetY, _templeTouchpOff);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool AI::checkAutoList(AIEntity *e, int x, int y) {
|
||||
for (int i = 0; i < kMaxAutoActions; i++) {
|
||||
if (_autoActions[i].x == x && _autoActions[i].y == y && !_autoActions[i].activated) {
|
||||
debug(1, "Activating action for Entity: %s, x: %d, y: %d", e->entityName, x, y);
|
||||
bool success = activateAction(e, x, y, 0, 0);
|
||||
_autoActions[i].activated = true;
|
||||
|
||||
if (success && _autoActions[i].luaFuncUse[0])
|
||||
g_hdb->_lua->callFunction(_autoActions[i].luaFuncUse, 0);
|
||||
|
||||
if (e == _player) {
|
||||
lookAtXY(x, y);
|
||||
animGrabbing();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::autoActive(int x, int y) {
|
||||
for (int i = 0; i < kMaxAutoActions; i++) {
|
||||
if (_autoActions[i].x == x && _autoActions[i].y == y) {
|
||||
if (!_autoActions[i].activated)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CallbackDef allCallbacks[] = {
|
||||
{NO_FUNCTION, nullptr},
|
||||
{AI_BARREL_EXPLOSION_END, callbackAiBarrelExplosionEnd},
|
||||
{CALLBACK_DOOR_OPEN_CLOSE, callbackDoorOpenClose},
|
||||
{CALLBACK_AUTODOOR_OPEN_CLOSE, callbackAutoDoorOpenClose},
|
||||
{CALLBACK_END, nullptr}
|
||||
};
|
||||
|
||||
void AI::addCallback(CallbackType type, int x, int y, int delay) {
|
||||
for (int i = kMaxCallbacks - 1; i >= 0; i--)
|
||||
if (_callbacks[i].type == NO_FUNCTION) {
|
||||
_callbacks[i].type = type;
|
||||
_callbacks[i].x = x;
|
||||
_callbacks[i].y = y;
|
||||
_callbacks[i].delay = delay;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AI::processCallbackList() {
|
||||
for (int i = 0; i < kMaxCallbacks; i++)
|
||||
if (_callbacks[i].type != NO_FUNCTION) {
|
||||
if (_callbacks[i].delay) {
|
||||
_callbacks[i].delay--;
|
||||
return;
|
||||
}
|
||||
allCallbacks[_callbacks[i].type].function(_callbacks[i].x, _callbacks[i].y);
|
||||
_callbacks[i].type = NO_FUNCTION;
|
||||
_callbacks[i].x = _callbacks[i].y = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AI::addToLuaList(int x, int y, int value1, int value2, char *luaFuncInit, char *luaFuncAction, char *luaFuncUse) {
|
||||
for (int i = 0; i < kMaxLuaEnts; i++) {
|
||||
if (!_luaList[i].luaFuncInit[0] && !_luaList[i].luaFuncAction[0] && !_luaList[i].luaFuncUse[0]) {
|
||||
_luaList[i].x = x;
|
||||
_luaList[i].y = y;
|
||||
_luaList[i].value1 = value1;
|
||||
_luaList[i].value2 = value2;
|
||||
|
||||
Common::strlcpy(_luaList[i].luaFuncInit, luaFuncInit, 32);
|
||||
if (luaFuncInit[0] == '*')
|
||||
_luaList[i].luaFuncInit[0] = 0;
|
||||
Common::strlcpy(_luaList[i].luaFuncAction, luaFuncAction, 32);
|
||||
if (luaFuncAction[0] == '*')
|
||||
_luaList[i].luaFuncAction[0] = 0;
|
||||
Common::strlcpy(_luaList[i].luaFuncUse, luaFuncUse, 32);
|
||||
if (luaFuncUse[0] == '*')
|
||||
_luaList[i].luaFuncUse[0] = 0;
|
||||
|
||||
_numLuaList++;
|
||||
if (_luaList[i].luaFuncInit[0])
|
||||
g_hdb->_lua->invokeLuaFunction(luaFuncInit, x, y, value1, value2);
|
||||
|
||||
spawnBlocking(x, y, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AI::checkLuaList(AIEntity *e, int x, int y) {
|
||||
for (int i = 0; i < _numLuaList; i++) {
|
||||
if (_luaList[i].x == x && _luaList[i].y == y && _luaList[i].luaFuncUse[0]) {
|
||||
if (e == _player) {
|
||||
lookAtXY(x, y);
|
||||
animGrabbing();
|
||||
}
|
||||
|
||||
g_hdb->_lua->invokeLuaFunction(_luaList[i].luaFuncUse, _luaList[i].x, _luaList[i].y, _luaList[i].value1, _luaList[i].value2);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::luaExistAtXY(int x, int y) {
|
||||
for (int i = 0; i < _numLuaList; i++) {
|
||||
if (_luaList[i].x == x && _luaList[i].y == y && _luaList[i].luaFuncUse[0]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AI::addToTeleportList(int teleIndex, int x, int y, int dir, int level, int anim, int usable, const char *luaFuncUse) {
|
||||
if (!level)
|
||||
level = 1;
|
||||
|
||||
if (!_teleporters[teleIndex].x1) {
|
||||
_teleporters[teleIndex].x1 = x;
|
||||
_teleporters[teleIndex].y1 = y;
|
||||
_teleporters[teleIndex].dir1 = (AIDir)dir;
|
||||
_teleporters[teleIndex].level1 = level;
|
||||
_teleporters[teleIndex].anim1 = anim;
|
||||
_teleporters[teleIndex].usable1 = usable;
|
||||
Common::strlcpy(_teleporters[teleIndex].luaFuncUse1, luaFuncUse, 32);
|
||||
if (_teleporters[teleIndex].luaFuncUse1[0] == '*')
|
||||
_teleporters[teleIndex].luaFuncUse1[0] = 0;
|
||||
_numTeleporters++;
|
||||
return;
|
||||
}
|
||||
if (!_teleporters[teleIndex].x2) {
|
||||
_teleporters[teleIndex].x2 = x;
|
||||
_teleporters[teleIndex].y2 = y;
|
||||
_teleporters[teleIndex].dir2 = (AIDir)dir;
|
||||
_teleporters[teleIndex].level2 = level;
|
||||
_teleporters[teleIndex].anim2 = anim;
|
||||
_teleporters[teleIndex].usable2 = usable;
|
||||
Common::strlcpy(_teleporters[teleIndex].luaFuncUse2, luaFuncUse, 32);
|
||||
if (_teleporters[teleIndex].luaFuncUse2[0] == '*')
|
||||
_teleporters[teleIndex].luaFuncUse2[0] = 0;
|
||||
_numTeleporters++;
|
||||
return;
|
||||
}
|
||||
|
||||
warning("addToTeleporterList: Adding a 3rd teleporter is illegal");
|
||||
}
|
||||
|
||||
bool AI::findTeleporterDest(int tileX, int tileY, SingleTele *info) {
|
||||
for (int i = 0; i < _numTeleporters; i++) {
|
||||
if ((_teleporters[i].x1 == tileX) && (_teleporters[i].y1 == tileY)) {
|
||||
info->anim = _teleporters[i].anim2;
|
||||
info->x = _teleporters[i].x2;
|
||||
info->y = _teleporters[i].y2;
|
||||
info->dir = _teleporters[i].dir2;
|
||||
info->level = _teleporters[i].level2;
|
||||
info->usable = _teleporters[i].usable2;
|
||||
return true;
|
||||
}
|
||||
if ((_teleporters[i].x2 == tileX) && (_teleporters[i].y2 == tileY)) {
|
||||
info->anim = _teleporters[i].anim1;
|
||||
info->x = _teleporters[i].x1;
|
||||
info->y = _teleporters[i].y1;
|
||||
info->dir = _teleporters[i].dir1;
|
||||
info->level = _teleporters[i].level1;
|
||||
info->usable = _teleporters[i].usable1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::checkTeleportList(AIEntity *e, int x, int y) {
|
||||
for (int i = 0; i < kMaxTeleporters; i++) {
|
||||
if ((_teleporters[i].x1 == x && _teleporters[i].y1 == y) || (_teleporters[i].x2 == x && _teleporters[i].y2 == y)) {
|
||||
int targetX = _teleporters[i].x1;
|
||||
int targetY = _teleporters[i].y1;
|
||||
int targetX2 = _teleporters[i].x2;
|
||||
int targetY2 = _teleporters[i].y2;
|
||||
//AIDir dir1 = _teleporters[i].dir1;
|
||||
AIDir dir2 = _teleporters[i].dir2;
|
||||
//int level1 = _teleporters[i].level1;
|
||||
int level2 = _teleporters[i].level2;
|
||||
int usable1 = _teleporters[i].usable1;
|
||||
//int usable2 = _teleporters[i].usable2;
|
||||
int anim1 = _teleporters[i].anim1;
|
||||
int anim2 = _teleporters[i].anim2;
|
||||
//const char *luaFuncUse1 = _teleporters[i].luaFuncUse1;
|
||||
const char *luaFuncUse2 = _teleporters[i].luaFuncUse2;
|
||||
|
||||
// Choose which set of co-ordinates is the target
|
||||
if (x != targetX || y != targetY) {
|
||||
targetX = _teleporters[i].x2;
|
||||
targetY = _teleporters[i].y2;
|
||||
targetX2 = _teleporters[i].x1;
|
||||
targetY2 = _teleporters[i].y1;
|
||||
//dir1 = _teleporters[i].dir2;
|
||||
dir2 = _teleporters[i].dir1;
|
||||
//level1 = _teleporters[i].level2;
|
||||
level2 = _teleporters[i].level1;
|
||||
usable1 = _teleporters[i].usable2;
|
||||
//usable2 = _teleporters[i].usable1;
|
||||
anim1 = _teleporters[i].anim2;
|
||||
anim2 = _teleporters[i].anim1;
|
||||
//luaFuncUse1 = _teleporters[i].luaFuncUse2;
|
||||
luaFuncUse2 = _teleporters[i].luaFuncUse1;
|
||||
}
|
||||
|
||||
// We must be exactly on the teleporter
|
||||
if (abs(targetX*kTileWidth - e->x) > 2 || abs(targetY*kTileHeight - e->y) > 2)
|
||||
return false;
|
||||
|
||||
// Can this teleporter be used?
|
||||
if (usable1)
|
||||
return false;
|
||||
|
||||
// Move Entity to new Spot, then walk forward one tile
|
||||
e->tileX = targetX2;
|
||||
e->tileY = targetY2;
|
||||
e->x = targetX2 * kTileWidth;
|
||||
e->y = targetY2 * kTileHeight;
|
||||
e->xVel = e->yVel = 0;
|
||||
e->goalX = e->goalY = 0;
|
||||
e->animFrame = 0;
|
||||
e->drawXOff = e->drawYOff = 0;
|
||||
e->dir = dir2;
|
||||
e->level = level2;
|
||||
|
||||
if (luaFuncUse2[0])
|
||||
g_hdb->_lua->callFunction(luaFuncUse2, 0);
|
||||
|
||||
e->draw = e->standdownGfx[0];
|
||||
if (e == _player) {
|
||||
clearWaypoints();
|
||||
}
|
||||
|
||||
switch (e->dir) {
|
||||
case DIR_UP:
|
||||
setEntityGoal(e, e->tileX, e->tileY - 1);
|
||||
break;
|
||||
case DIR_DOWN:
|
||||
setEntityGoal(e, e->tileX, e->tileY + 1);
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
setEntityGoal(e, e->tileX - 1, e->tileY);
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
setEntityGoal(e, e->tileX + 1, e->tileY);
|
||||
break;
|
||||
case DIR_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hdb->_map->centerMapXY(e->x + 16, e->y + 16);
|
||||
|
||||
// Start up Teleport flash animation only if value1 is set to 1
|
||||
if (anim1 == 1 || anim2 == 2) {
|
||||
addAnimateTarget(e->x, e->y, 0, 7, ANIM_NORMAL, false, false, "teleporter_flash_sit");
|
||||
g_hdb->_sound->playSound(SND_TELEPORT);
|
||||
}
|
||||
|
||||
// PANIC ZONE Teleports?
|
||||
if (anim2 >= 2)
|
||||
g_hdb->_window->startPanicZone();
|
||||
else
|
||||
g_hdb->_window->stopPanicZone();
|
||||
|
||||
// Is there an attack gem still floating around?
|
||||
for (Common::Array<AIEntity *>::iterator it = _ents->begin(); it != _ents->end(); ++it) {
|
||||
if ((*it)->type == AI_GEM_ATTACK) {
|
||||
int amt = getGemAmount();
|
||||
setGemAmount(amt + 1);
|
||||
removeEntity(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_playerEmerging = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AI::addToPathList(int x, int y, int type, AIDir dir) {
|
||||
ArrowPath *arrowPath = new ArrowPath;
|
||||
|
||||
arrowPath->type = type;
|
||||
arrowPath->tileX = x;
|
||||
arrowPath->tileY = y;
|
||||
arrowPath->dir = dir;
|
||||
|
||||
_arrowPaths->push_back(arrowPath);
|
||||
}
|
||||
|
||||
ArrowPath *AI::findArrowPath(int x, int y) {
|
||||
for (Common::Array<ArrowPath *>::iterator it = _arrowPaths->begin(); it != _arrowPaths->end(); ++it) {
|
||||
if ((*it)->tileX == x && (*it)->tileY == y)
|
||||
return *it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AI::addToTriggerList(char *luaFuncInit, char *luaFuncUse, int x, int y, int value1, int value2, char *id) {
|
||||
Trigger *t = new Trigger;
|
||||
|
||||
_triggerList->push_back(t);
|
||||
|
||||
Common::strlcpy(t->id, id, 32);
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
t->value1 = value1;
|
||||
t->value2 = value2;
|
||||
if (luaFuncInit[0] != '*')
|
||||
Common::strlcpy(t->luaFuncInit, luaFuncInit, 32);
|
||||
if (luaFuncUse[0] != '*')
|
||||
Common::strlcpy(t->luaFuncUse, luaFuncUse, 32);
|
||||
|
||||
if (!t->luaFuncUse[0])
|
||||
g_hdb->_window->openMessageBar("Trigger without USE!", 10);
|
||||
|
||||
if (t->luaFuncInit[0]) {
|
||||
g_hdb->_lua->pushFunction(t->luaFuncInit);
|
||||
g_hdb->_lua->pushInt(x);
|
||||
g_hdb->_lua->pushInt(y);
|
||||
g_hdb->_lua->pushInt(value1);
|
||||
g_hdb->_lua->pushInt(value2);
|
||||
g_hdb->_lua->call(4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool AI::checkTriggerList(char *entName, int x, int y) {
|
||||
for (Common::Array<Trigger *>::iterator it = _triggerList->begin(); it != _triggerList->end(); ++it) {
|
||||
Trigger *t = *it;
|
||||
if (t->x == x && t->y == y) {
|
||||
if (!t->luaFuncUse[0])
|
||||
return false;
|
||||
|
||||
g_hdb->_lua->pushFunction(t->luaFuncUse);
|
||||
g_hdb->_lua->pushString(entName);
|
||||
g_hdb->_lua->pushInt(t->x);
|
||||
g_hdb->_lua->pushInt(t->y);
|
||||
g_hdb->_lua->pushInt(t->value1);
|
||||
g_hdb->_lua->pushInt(t->value2);
|
||||
g_hdb->_lua->call(5, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AI::killTrigger(const char *id) {
|
||||
for (uint i = 0; i < _triggerList->size(); i++) {
|
||||
if (!scumm_stricmp(id, _triggerList->operator[](i)->id)) {
|
||||
_triggerList->remove_at(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
1771
engines/hdb/ai-player.cpp
Normal file
1771
engines/hdb/ai-player.cpp
Normal file
File diff suppressed because it is too large
Load Diff
277
engines/hdb/ai-player.h
Normal file
277
engines/hdb/ai-player.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/* 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 HDB_AI_PLAYER_H
|
||||
#define HDB_AI_PLAYER_H
|
||||
|
||||
namespace HDB {
|
||||
|
||||
void aiPlayerInit(AIEntity *e, int mx, int my);
|
||||
void aiPlayerInit2(AIEntity *e, int mx, int my);
|
||||
void aiPlayerAction(AIEntity *e, int mx, int my);
|
||||
void aiPlayerDraw(AIEntity *e, int mx, int my);
|
||||
void aiGemAttackInit(AIEntity *e, int mx, int my);
|
||||
void aiGemAttackInit2(AIEntity *e, int mx, int my);
|
||||
void aiGemAttackAction(AIEntity *e, int mx, int my);
|
||||
void aiChickenAction(AIEntity *e, int mx, int my);
|
||||
void aiChickenUse(AIEntity *e, int mx, int my);
|
||||
void aiChickenInit(AIEntity *e, int mx, int my);
|
||||
void aiChickenInit2(AIEntity *e, int mx, int my);
|
||||
void aiDollyInit(AIEntity *e, int mx, int my);
|
||||
void aiDollyInit2(AIEntity *e, int mx, int my);
|
||||
void aiSergeantInit(AIEntity *e, int mx, int my);
|
||||
void aiSergeantInit2(AIEntity *e, int mx, int my);
|
||||
void aiSergeantAction(AIEntity *e, int mx, int my);
|
||||
void aiSpacedudeInit(AIEntity *e, int mx, int my);
|
||||
void aiSpacedudeInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiCrateAction(AIEntity *e, int mx, int my);
|
||||
void aiCrateInit2(AIEntity *e, int mx, int my);
|
||||
void aiCrateInit(AIEntity *e, int mx, int my);
|
||||
void aiBarrelLightAction(AIEntity *e, int mx, int my);
|
||||
void aiBarrelLightInit2(AIEntity *e, int mx, int my);
|
||||
void aiBarrelLightInit(AIEntity *e, int mx, int my);
|
||||
void aiBarrelHeavyAction(AIEntity *e, int mx, int my);
|
||||
void aiBarrelHeavyInit(AIEntity *e, int mx, int my);
|
||||
void aiBarrelHeavyInit2(AIEntity *e, int mx, int my);
|
||||
void aiBarrelExplode(AIEntity *e, int mx, int my);
|
||||
void aiBarrelExplodeInit(AIEntity *e, int mx, int my);
|
||||
void aiBarrelExplodeInit2(AIEntity *e, int mx, int my);
|
||||
void aiBarrelExplodeAction(AIEntity *e, int mx, int my);
|
||||
void aiBarrelExplodeSpread(AIEntity *e, int mx, int my);
|
||||
void aiBarrelBlowup(AIEntity *e, int x, int y);
|
||||
|
||||
void aiMaintBotInit(AIEntity *e, int mx, int my);
|
||||
void aiMaintBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiMaintBotAction(AIEntity *e, int mx, int my);
|
||||
void aiShockBotAction(AIEntity *e, int mx, int my);
|
||||
void aiShockBotShock(AIEntity *e, int mx, int my);
|
||||
void aiShockBotInit(AIEntity *e, int mx, int my);
|
||||
void aiShockBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiScientistInit(AIEntity *e, int mx, int my);
|
||||
void aiScientistInit2(AIEntity *e, int mx, int my);
|
||||
void aiFourFirerInit(AIEntity *e, int mx, int my);
|
||||
void aiFourFirerInit2(AIEntity *e, int mx, int my);
|
||||
void aiFourFirerAction(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderInit(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderInit2(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderAction(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderUse(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderOnUse(AIEntity *e, int mx, int my);
|
||||
void aiRailRiderOnAction(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotMissileAction(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotMissileInit(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotMissileInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiSlugAttackAction(AIEntity *e, int mx, int my);
|
||||
void aiSlugAttackDraw(AIEntity *e, int mx, int my);
|
||||
void aiSlugAttackInit(AIEntity *e, int mx, int my);
|
||||
void aiSlugAttackInit2(AIEntity *e, int mx, int my);
|
||||
void aiDeadWorkerInit(AIEntity *e, int mx, int my);
|
||||
void aiDeadWorkerInit2(AIEntity *e, int mx, int my);
|
||||
void aiWorkerInit(AIEntity *e, int mx, int my);
|
||||
void aiWorkerInit2(AIEntity *e, int mx, int my);
|
||||
void aiAccountantInit(AIEntity *e, int mx, int my);
|
||||
void aiAccountantInit2(AIEntity *e, int mx, int my);
|
||||
void aiFrogStatueInit(AIEntity *e, int mx, int my);
|
||||
void aiFrogStatueInit2(AIEntity *e, int mx, int my);
|
||||
void aiFrogStatueAction(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiRoboStunnerAction(AIEntity *e, int mx, int my);
|
||||
void aiRoboStunnerInit(AIEntity *e, int mx, int my);
|
||||
void aiRoboStunnerInit2(AIEntity *e, int mx, int my);
|
||||
void aiClubInit(AIEntity *e, int mx, int my);
|
||||
void aiClubInit2(AIEntity *e, int mx, int my);
|
||||
void aiSlugSlingerInit(AIEntity *e, int mx, int my);
|
||||
void aiSlugSlingerInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiTurnBotAction(AIEntity *e, int mx, int my);
|
||||
void aiPushBotAction(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotAction(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotMove(AIEntity *e, int mx, int my);
|
||||
void aiLaserAction(AIEntity *e, int mx, int my);
|
||||
void aiLaserDraw(AIEntity *e, int mx, int my);
|
||||
void aiDiverterAction(AIEntity *e, int mx, int my);
|
||||
void aiDiverterDraw(AIEntity *e, int mx, int my);
|
||||
void aiRightBotAction(AIEntity *e, int mx, int my);
|
||||
void aiDeadEyeAction(AIEntity *e, int mx, int my);
|
||||
void aiMeerkatDraw(AIEntity *e, int mx, int my);
|
||||
void aiMeerkatAction(AIEntity *e, int mx, int my);
|
||||
void aiMeerkatLookAround(AIEntity *e, int mx, int my);
|
||||
void aiDeadEyeWalkInPlace(AIEntity *e, int mx, int my);
|
||||
void aiFatFrogAction(AIEntity *e, int mx, int my);
|
||||
void aiFatFrogTongueDraw(AIEntity *e, int mx, int my);
|
||||
void aiGoodFairyAction(AIEntity *e, int mx, int my);
|
||||
void aiBadFairyAction(AIEntity *e, int mx, int my);
|
||||
void aiGatePuddleAction(AIEntity *e, int mx, int my);
|
||||
void aiIcePuffSnowballAction(AIEntity *e, int mx, int my);
|
||||
void aiIcePuffSnowballDraw(AIEntity *e, int mx, int my);
|
||||
void aiIcePuffAction(AIEntity *e, int mx, int my);
|
||||
void aiBuzzflyAction(AIEntity *e, int mx, int my);
|
||||
void aiDragonAction(AIEntity *e, int mx, int my);
|
||||
void aiDragonDraw(AIEntity *e, int mx, int my);
|
||||
void aiTurnBotInit(AIEntity *e, int mx, int my);
|
||||
void aiTurnBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotInit(AIEntity *e, int mx, int my);
|
||||
void aiOmniBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiLaserInit(AIEntity *e, int mx, int my);
|
||||
void aiLaserInit2(AIEntity *e, int mx, int my);
|
||||
void aiDiverterInit(AIEntity *e, int mx, int my);
|
||||
void aiDiverterInit2(AIEntity *e, int mx, int my);
|
||||
void aiRightBotInit(AIEntity *e, int mx, int my);
|
||||
void aiRightBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiPushBotInit(AIEntity *e, int mx, int my);
|
||||
void aiPushBotInit2(AIEntity *e, int mx, int my);
|
||||
void aiDeadEyeInit(AIEntity *e, int mx, int my);
|
||||
void aiDeadEyeInit2(AIEntity *e, int mx, int my);
|
||||
void aiMeerkatInit(AIEntity *e, int mx, int my);
|
||||
void aiMeerkatInit2(AIEntity *e, int mx, int my);
|
||||
void aiFatFrogInit(AIEntity *e, int mx, int my);
|
||||
void aiFatFrogInit2(AIEntity *e, int mx, int my);
|
||||
void aiGoodFairyInit(AIEntity *e, int mx, int my);
|
||||
void aiGoodFairyInit2(AIEntity *e, int mx, int my);
|
||||
void aiBadFairyInit(AIEntity *e, int mx, int my);
|
||||
void aiBadFairyInit2(AIEntity *e, int mx, int my);
|
||||
void aiGatePuddleInit(AIEntity *e, int mx, int my);
|
||||
void aiGatePuddleInit2(AIEntity *e, int mx, int my);
|
||||
void aiIcePuffInit(AIEntity *e, int mx, int my);
|
||||
void aiIcePuffInit2(AIEntity *e, int mx, int my);
|
||||
void aiBuzzflyInit(AIEntity *e, int mx, int my);
|
||||
void aiBuzzflyInit2(AIEntity *e, int mx, int my);
|
||||
void aiDragonInit(AIEntity *e, int mx, int my);
|
||||
void aiDragonInit2(AIEntity *e, int mx, int my);
|
||||
void aiDragonWake(AIEntity *e, int mx, int my);
|
||||
void aiDragonUse(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiEnvelopeGreenInit(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeGreenInit2(AIEntity *e, int mx, int my);
|
||||
void aiGemBlueInit(AIEntity *e, int mx, int my);
|
||||
void aiGemBlueInit2(AIEntity *e, int mx, int my);
|
||||
void aiGemRedInit(AIEntity *e, int mx, int my);
|
||||
void aiGemRedInit2(AIEntity *e, int mx, int my);
|
||||
void aiGemGreenInit(AIEntity *e, int mx, int my);
|
||||
void aiGemGreenInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiTeaCupInit(AIEntity *e, int mx, int my);
|
||||
void aiTeaCupInit2(AIEntity *e, int mx, int my);
|
||||
void aiCookieInit(AIEntity *e, int mx, int my);
|
||||
void aiCookieInit2(AIEntity *e, int mx, int my);
|
||||
void aiBurgerInit(AIEntity *e, int mx, int my);
|
||||
void aiBurgerInit2(AIEntity *e, int mx, int my);
|
||||
void aiBookInit(AIEntity *e, int mx, int my);
|
||||
void aiBookInit2(AIEntity *e, int mx, int my);
|
||||
void aiClipboardInit(AIEntity *e, int mx, int my);
|
||||
void aiClipboardInit2(AIEntity *e, int mx, int my);
|
||||
void aiNoteInit(AIEntity *e, int mx, int my);
|
||||
void aiNoteInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardWhiteInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardWhiteInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardBlueInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardBlueInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardRedInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardRedInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardGreenInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardGreenInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardPurpleInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardPurpleInit2(AIEntity *e, int mx, int my);
|
||||
void aiKeycardBlackInit(AIEntity *e, int mx, int my);
|
||||
void aiKeycardBlackInit2(AIEntity *e, int mx, int my);
|
||||
void aiSeedInit(AIEntity *e, int mx, int my);
|
||||
void aiSeedInit2(AIEntity *e, int mx, int my);
|
||||
void aiSodaInit(AIEntity *e, int mx, int my);
|
||||
void aiSodaInit2(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool1Init(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool1Init2(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool2Init(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool2Init2(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool3Init(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool3Init2(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool4Init(AIEntity *e, int mx, int my);
|
||||
void aiDollyTool4Init2(AIEntity *e, int mx, int my);
|
||||
void aiRouterInit(AIEntity *e, int mx, int my);
|
||||
void aiRouterInit2(AIEntity *e, int mx, int my);
|
||||
void aiSlicerInit(AIEntity *e, int mx, int my);
|
||||
void aiSlicerInit2(AIEntity *e, int mx, int my);
|
||||
void aiPackageInit(AIEntity *e, int mx, int my);
|
||||
void aiPackageInit2(AIEntity *e, int mx, int my);
|
||||
void aiMagicEggAction(AIEntity *e, int mx, int my);
|
||||
void aiMagicEggInit(AIEntity *e, int mx, int my);
|
||||
void aiMagicEggInit2(AIEntity *e, int mx, int my);
|
||||
void aiMagicEggUse(AIEntity *e, int mx, int my);
|
||||
void aiIceBlockAction(AIEntity *e, int mx, int my);
|
||||
void aiIceBlockInit(AIEntity *e, int mx, int my);
|
||||
void aiIceBlockInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiCabKeyInit(AIEntity *e, int mx, int my);
|
||||
void aiCabKeyInit2(AIEntity *e, int mx, int my);
|
||||
void aiItemChickenInit(AIEntity *e, int mx, int my);
|
||||
void aiItemChickenInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiPdaInit(AIEntity *e, int mx, int my);
|
||||
void aiPdaInit2(AIEntity *e, int mx, int my);
|
||||
#if 0
|
||||
void aiCellUse(AIEntity *e, int mx, int my);
|
||||
#endif
|
||||
void aiCellInit2(AIEntity *e, int mx, int my);
|
||||
void aiCellInit(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeWhiteInit(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeWhiteInit2(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeBlueInit(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeBlueInit2(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeRedInit(AIEntity *e, int mx, int my);
|
||||
void aiEnvelopeRedInit2(AIEntity *e, int mx, int my);
|
||||
void aiTransceiverInit(AIEntity *e, int mx, int my);
|
||||
void aiTransceiverInit2(AIEntity *e, int mx, int my);
|
||||
void aiTransceiverAction(AIEntity *e, int mx, int my);
|
||||
#if 0
|
||||
void aiTransceiverUse(AIEntity *e, int mx, int my);
|
||||
#endif
|
||||
void aiMonkeystoneInit(AIEntity *e, int mx, int my);
|
||||
void aiMonkeystoneAction(AIEntity *e, int mx, int my);
|
||||
void aiMonkeystoneInit2(AIEntity *e, int mx, int my);
|
||||
void aiMonkeystoneUse(AIEntity *e, int mx, int my);
|
||||
void aiGemAction(AIEntity *e, int mx, int my);
|
||||
void aiGemWhiteInit(AIEntity *e, int mx, int my);
|
||||
void aiGemWhiteInit2(AIEntity *e, int mx, int my);
|
||||
void aiGooCupUse(AIEntity *e, int mx, int my);
|
||||
void aiGooCupInit(AIEntity *e, int mx, int my);
|
||||
void aiGooCupInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiVortexianAction(AIEntity *e, int mx, int my);
|
||||
void aiVortexianUse(AIEntity *e, int mx, int my);
|
||||
void aiVortexianInit(AIEntity *e, int mx, int my);
|
||||
void aiVortexianInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void aiNoneInit(AIEntity *e, int mx, int my);
|
||||
void aiNoneInit2(AIEntity *e, int mx, int my);
|
||||
|
||||
void callbackDoorOpenClose(int x, int y);
|
||||
void callbackAutoDoorOpenClose(int x, int y);
|
||||
void callbackAiBarrelExplosionEnd(int x, int y);
|
||||
|
||||
// Utility Functions
|
||||
void aiAnimateStanddown(AIEntity *e, int speed);
|
||||
void aiGenericAction(AIEntity *e, int mx, int my);
|
||||
void aiGetItemAction(AIEntity *e, int mx, int my);
|
||||
|
||||
} // End of Namespace
|
||||
|
||||
#endif // !HDB_AI_PLAYER_H
|
||||
307
engines/hdb/ai-use.cpp
Normal file
307
engines/hdb/ai-use.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
/* 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 AI::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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
bool AI::isClosedDoor(int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
if ((tileIndex == _targetDoorN + 3) || // locked SILVER door?
|
||||
(tileIndex == _targetDoorNv + 3) ||
|
||||
(tileIndex == _targetDoorP + 3) || // locked BLUE door?
|
||||
(tileIndex == _targetDoorPv + 3) ||
|
||||
(tileIndex == _targetDoorS + 3) || // locked RED door?
|
||||
(tileIndex == _targetDoorSv + 3) ||
|
||||
(tileIndex == _targetDoor2N + 3) || // locked SILVER door?
|
||||
(tileIndex == _targetDoor2Nv + 3) ||
|
||||
(tileIndex == _targetDoor2P + 3) || // locked BLUE door?
|
||||
(tileIndex == _targetDoor2Pv + 3) ||
|
||||
(tileIndex == _targetDoor2S + 3) || // locked RED door?
|
||||
(tileIndex == _targetDoor2Sv + 3) ||
|
||||
(tileIndex == _target2DoorN + 3) || // locked SILVER door?
|
||||
(tileIndex == _target2DoorNv + 3) ||
|
||||
(tileIndex == _target2DoorP + 3) || // locked BLUE door?
|
||||
(tileIndex == _target2DoorPv + 3) ||
|
||||
(tileIndex == _target2DoorS + 3) || // locked RED door?
|
||||
(tileIndex == _target2DoorSv + 3) ||
|
||||
(tileIndex == _target3DoorN + 3) || // locked SILVER door?
|
||||
(tileIndex == _target3DoorNv + 3) ||
|
||||
(tileIndex == _target3DoorP + 3) || // locked BLUE door?
|
||||
(tileIndex == _target3DoorPv + 3) ||
|
||||
(tileIndex == _target3DoorS + 3) || // locked RED door?
|
||||
(tileIndex == _target3DoorSv + 3) ||
|
||||
(tileIndex == _blockpole + 3)) // blockpole UP?
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::isOpenDoor(int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
if ((tileIndex == _targetDoorN) || // open SILVER door?
|
||||
(tileIndex == _targetDoorNv) ||
|
||||
(tileIndex == _targetDoorP) || // open BLUE door?
|
||||
(tileIndex == _targetDoorPv) ||
|
||||
(tileIndex == _targetDoorS) || // open RED door?
|
||||
(tileIndex == _targetDoorSv) ||
|
||||
(tileIndex == _targetDoor2N) || // open SILVER door?
|
||||
(tileIndex == _targetDoor2Nv) ||
|
||||
(tileIndex == _targetDoor2P) || // open BLUE door?
|
||||
(tileIndex == _targetDoor2Pv) ||
|
||||
(tileIndex == _targetDoor2S) || // open RED door?
|
||||
(tileIndex == _targetDoor2Sv) ||
|
||||
(tileIndex == _target2DoorN) || // open SILVER door?
|
||||
(tileIndex == _target2DoorNv) ||
|
||||
(tileIndex == _target2DoorP) || // open BLUE door?
|
||||
(tileIndex == _target2DoorPv) ||
|
||||
(tileIndex == _target2DoorS) || // open RED door?
|
||||
(tileIndex == _target2DoorSv) ||
|
||||
(tileIndex == _target3DoorN) || // open SILVER door?
|
||||
(tileIndex == _target3DoorNv) ||
|
||||
(tileIndex == _target3DoorP) || // open BLUE door?
|
||||
(tileIndex == _target3DoorPv) ||
|
||||
(tileIndex == _target3DoorS) || // open RED door?
|
||||
(tileIndex == _target3DoorSv) ||
|
||||
(tileIndex == _blockpole)) // blockpole DOWN?
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::useTarget(int x, int y, int targetX, int targetY, int newTile, int *worked) {
|
||||
// open a locked door?
|
||||
if (isClosedDoor(targetX, targetY)) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(targetX, targetY);
|
||||
|
||||
addAnimateTarget(targetX, targetY, tileIndex, tileIndex - 3, ANIM_SLOW, false, true, nullptr);
|
||||
g_hdb->_map->setMapBGTileIndex(x, y, newTile);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
*worked = 1;
|
||||
return false; // return FALSE because we need to be able to do it some more
|
||||
}
|
||||
|
||||
// close an open door?
|
||||
if (isOpenDoor(targetX, targetY)) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(targetX, targetY);
|
||||
|
||||
addAnimateTarget(targetX, targetY, tileIndex, tileIndex + 3, ANIM_SLOW, false, true, nullptr);
|
||||
g_hdb->_map->setMapBGTileIndex(x, y, newTile);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
*worked = 1;
|
||||
return false; // return FALSE because we need to be able to do it some more
|
||||
}
|
||||
|
||||
// open up a bridge?
|
||||
int tileIndex = g_hdb->_map->getMapFGTileIndex(targetX, targetY);
|
||||
if (tileIndex == _targetBridgeU ||
|
||||
tileIndex == _targetBridgeD ||
|
||||
tileIndex == _targetBridgeL ||
|
||||
tileIndex == _targetBridgeR) {
|
||||
addBridgeExtend(targetX, targetY, tileIndex);
|
||||
g_hdb->_map->setMapBGTileIndex(x, y, newTile);
|
||||
*worked = 1;
|
||||
return true; // return TRUE because we can't open it again
|
||||
}
|
||||
|
||||
*worked = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Black Door Switch
|
||||
bool AI::useSwitch(AIEntity *e, int x, int y, int targetX, int targetY, int onTile) {
|
||||
int worked;
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
return useTarget(x, y, targetX, targetY, onTile, &worked);
|
||||
}
|
||||
|
||||
bool AI::useSwitchOn(AIEntity *e, int x, int y, int targetX, int targetY, int offTile) {
|
||||
int worked;
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
return useTarget(x, y, targetX, targetY, offTile, &worked);
|
||||
}
|
||||
|
||||
bool AI::useSwitch2(AIEntity *e, int x, int y, int targetX, int targetY) {
|
||||
// int i = 10; // unused
|
||||
return true;
|
||||
}
|
||||
|
||||
// Colored Keycard Switch
|
||||
bool AI::useLockedSwitch(AIEntity *e, int x, int y, int targetX, int targetY, int onTile, AIType item, const char *keyerror) {
|
||||
// is the PLAYER next to this thing? No other entities are allowed to unlock anything!
|
||||
if (abs(x - _player->tileX) > 1 || abs(y - _player->tileY) > 1)
|
||||
return false;
|
||||
|
||||
int amount = queryInventoryType(item);
|
||||
if (amount) {
|
||||
int worked;
|
||||
bool rtn = useTarget(x, y, targetX, targetY, onTile, &worked);
|
||||
if (worked) {
|
||||
removeInvItemType(item, 1);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
}
|
||||
return rtn;
|
||||
} else {
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_CELLHOLDER_USE_REJECT);
|
||||
g_hdb->_window->openMessageBar(keyerror, 3);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AI::useLockedSwitchOn(AIEntity *e, int x, int y, int targetX, int targetY, int offTile, AIType item) {
|
||||
// is the PLAYER next to this thing? No other entities are allowed to unlock anything!
|
||||
if (abs(x - _player->tileX) > 1 || abs(y - _player->tileY) > 1)
|
||||
return false;
|
||||
|
||||
if (getInvAmount() == 10)
|
||||
return false;
|
||||
|
||||
int worked;
|
||||
bool rtn = useTarget(x, y, targetX, targetY, offTile, &worked);
|
||||
if (worked) {
|
||||
addItemToInventory(item, 1, nullptr, nullptr, nullptr);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
// Purple Cell Holder Switch
|
||||
bool AI::useCellHolder(AIEntity *e, int x, int y, int targetX, int targetY) {
|
||||
// is the PLAYER next to this thing? No other entities are allowed to unlock anything!
|
||||
if (abs(x - _player->tileX) > 1 || abs(y - _player->tileY) > 1)
|
||||
return false;
|
||||
|
||||
int amount = queryInventoryType(ITEM_CELL);
|
||||
|
||||
if (amount) {
|
||||
int worked;
|
||||
bool rtn = useTarget(x, y, targetX, targetY, _useHolderFull, &worked);
|
||||
if (worked) {
|
||||
removeInvItemType(ITEM_CELL, 1);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
}
|
||||
return rtn;
|
||||
} else {
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_CELLHOLDER_USE_REJECT);
|
||||
}
|
||||
|
||||
g_hdb->_window->openDialog("Locked!", -1, "I can't use that unless I have an Energy Cell.", 0, nullptr);
|
||||
g_hdb->_sound->playVoice(GUY_ENERGY_CELL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Touchplate
|
||||
bool AI::useTouchplate(AIEntity *e, int x, int y, int targetX, int targetY, int type) {
|
||||
int worked;
|
||||
g_hdb->_sound->playSound(SND_TOUCHPLATE_CLICK);
|
||||
return useTarget(x, y, targetX, targetY, type, &worked);
|
||||
}
|
||||
bool AI::useTouchplateOn(AIEntity *e, int x, int y, int targetX, int targetY, int type) {
|
||||
int worked;
|
||||
g_hdb->_sound->playSound(SND_TOUCHPLATE_CLICK);
|
||||
return useTarget(x, y, targetX, targetY, type, &worked);
|
||||
}
|
||||
|
||||
void callbackDoorOpenClose(int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
// is the door gonna close on something? if so, wait again
|
||||
if (!g_hdb->_ai->findEntity(x, y)) {
|
||||
g_hdb->_ai->addCallback(CALLBACK_DOOR_OPEN_CLOSE, x, y, kDelay5Seconds);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hdb->_ai->addAnimateTarget(x, y, tileIndex, tileIndex + 3, ANIM_SLOW, false, true, nullptr);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal Door
|
||||
bool AI::useDoorOpenClose(AIEntity *e, int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
addAnimateTarget(x, y, tileIndex, tileIndex - 3, ANIM_SLOW, false, true, nullptr);
|
||||
addCallback(CALLBACK_DOOR_OPEN_CLOSE, x, y, kDelay5Seconds);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void callbackAutoDoorOpenClose(int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
// Is the door going to close on something?
|
||||
if (g_hdb->_ai->findEntity(x, y)) {
|
||||
g_hdb->_ai->addCallback(CALLBACK_AUTODOOR_OPEN_CLOSE, x, y, kDelay5Seconds);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hdb->_ai->addAnimateTarget(x, y, tileIndex, tileIndex + 3, ANIM_SLOW, true, true, nullptr);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
return;
|
||||
}
|
||||
|
||||
bool AI::useAutoDoorOpenClose(AIEntity *e, int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
if (autoActive(x, y))
|
||||
return false;
|
||||
|
||||
addAnimateTarget(x, y, tileIndex, tileIndex - 3, ANIM_SLOW, false, true, nullptr);
|
||||
addCallback(CALLBACK_AUTODOOR_OPEN_CLOSE, x, y, kDelay5Seconds);
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Any Type Door
|
||||
bool AI::useDoorOpenCloseBot(AIEntity *e, int x, int y) {
|
||||
int tileIndex = g_hdb->_map->getMapBGTileIndex(x, y);
|
||||
|
||||
if (e == _player || e->type == AI_SLUG_ATTACK || e->type == AI_GEM_ATTACK) {
|
||||
if (isClosedDoor(x, y))
|
||||
g_hdb->_sound->playSound(SND_GUY_UHUH);
|
||||
return false;
|
||||
}
|
||||
|
||||
addAnimateTarget(x, y, tileIndex, tileIndex - 3, ANIM_SLOW, false, true, nullptr);
|
||||
// AddCallback( CALLBACK_DOOR_OPEN_CLOSE, x, y, DELAY_5SECONDS / fs );
|
||||
if (g_hdb->_map->onScreen(x, y))
|
||||
g_hdb->_sound->playSound(SND_DOOR_OPEN_CLOSE);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
463
engines/hdb/ai-waypoint.cpp
Normal file
463
engines/hdb/ai-waypoint.cpp
Normal file
@@ -0,0 +1,463 @@
|
||||
/* 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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/gfx.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
void AI::addWaypoint(int px, int py, int x, int y, int level) {
|
||||
// at the max yet?
|
||||
if (_numWaypoints >= kMaxWaypoints || (playerOnIce() && _player->goalX))
|
||||
return;
|
||||
|
||||
// first, let's see if this is a duplicate waypoint
|
||||
int i;
|
||||
for (i = 0; i < _numWaypoints; i++)
|
||||
if (_waypoints[i].x == x && _waypoints[i].y == y)
|
||||
return;
|
||||
|
||||
// check to make sure the path is clear...
|
||||
// if it's not, don't add to waypoint list!
|
||||
// The destination x,y might be modified, so
|
||||
// we'll pass in the address to them...
|
||||
int nx = x;
|
||||
int ny = y;
|
||||
if (!_numWaypoints) {
|
||||
// if player is already moving and this is the first waypoint, forget it.
|
||||
// player is using the keyboard and must be fully stopped before laying
|
||||
// the first waypoint
|
||||
if (_player->goalX)
|
||||
return;
|
||||
|
||||
// trace from player to new spot
|
||||
// return value of 0 only means a diagonal was selected!
|
||||
if (!traceStraightPath(px, py, &nx, &ny, &level)) {
|
||||
int tx, ty, tx2, ty2;
|
||||
|
||||
// it didn't work, so player is probably trying some diagonal movement.
|
||||
// let's break it down into two waypoints: one horz, one vert
|
||||
tx = nx;
|
||||
ty = py;
|
||||
tx2 = nx;
|
||||
ty2 = ny;
|
||||
int lvl1, lvl2;
|
||||
|
||||
lvl1 = lvl2 = level;
|
||||
|
||||
if (traceStraightPath(px, py, &tx, &ty, &lvl1)) {
|
||||
if (tx != nx || ty != py)
|
||||
goto newpath;
|
||||
|
||||
traceStraightPath(tx, ty, &tx2, &ty2, &lvl2);
|
||||
|
||||
if (tx2 != nx || ty2 != ny)
|
||||
goto newpath;
|
||||
|
||||
_waypoints[_numWaypoints].x = tx;
|
||||
_waypoints[_numWaypoints].y = ty;
|
||||
_waypoints[_numWaypoints].level = lvl1;
|
||||
_numWaypoints++;
|
||||
_waypoints[_numWaypoints].x = nx;
|
||||
_waypoints[_numWaypoints].y = ny;
|
||||
_waypoints[_numWaypoints].level = lvl2;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
|
||||
if (onEvenTile(_player->x, _player->y))
|
||||
setEntityGoal(_player, tx, ty);
|
||||
} else {
|
||||
newpath:
|
||||
tx = px;
|
||||
ty = ny;
|
||||
tx2 = nx;
|
||||
ty2 = ny;
|
||||
|
||||
lvl1 = lvl2 = level;
|
||||
|
||||
if (traceStraightPath(px, py, &tx, &ty, &lvl1)) {
|
||||
if (tx != px || ty != ny)
|
||||
return;
|
||||
|
||||
traceStraightPath(tx, ty, &nx, &ny, &lvl2);
|
||||
|
||||
if (tx2 != nx || ty2 != ny)
|
||||
return;
|
||||
|
||||
_waypoints[_numWaypoints].x = tx;
|
||||
_waypoints[_numWaypoints].y = ty;
|
||||
_waypoints[_numWaypoints].level = lvl1;
|
||||
_numWaypoints++;
|
||||
_waypoints[_numWaypoints].x = nx;
|
||||
_waypoints[_numWaypoints].y = ny;
|
||||
_waypoints[_numWaypoints].level = lvl2;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
|
||||
if (onEvenTile(_player->x, _player->y))
|
||||
setEntityGoal(_player, tx, ty);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// create a waypoint @ the player x,y? NO!
|
||||
if ((nx != px || ny != py) && onEvenTile(_player->x, _player->y))
|
||||
setEntityGoal(_player, nx, ny);
|
||||
else
|
||||
return;
|
||||
} else {
|
||||
// trace from last waypoint to new spot
|
||||
level = _waypoints[_numWaypoints - 1].level;
|
||||
|
||||
if (!traceStraightPath(_waypoints[_numWaypoints - 1].x, _waypoints[_numWaypoints - 1].y, &nx, &ny, &level)) {
|
||||
int tx, ty, tx2, ty2;
|
||||
|
||||
// it didn't work, so player is probably trying some diagonal movement.
|
||||
// let's break it down into two waypoints: one horz, one vert
|
||||
px = _waypoints[_numWaypoints - 1].x;
|
||||
py = _waypoints[_numWaypoints - 1].y;
|
||||
level = _waypoints[_numWaypoints - 1].level;
|
||||
|
||||
tx = nx;
|
||||
ty = py;
|
||||
tx2 = nx;
|
||||
ty2 = ny;
|
||||
int lvl1, lvl2;
|
||||
|
||||
lvl1 = lvl2 = level;
|
||||
|
||||
if (traceStraightPath(px, py, &tx, &ty, &lvl1)) {
|
||||
if (tx != nx || ty != py)
|
||||
goto newpath2;
|
||||
|
||||
traceStraightPath(tx, ty, &tx2, &ty2, &lvl2);
|
||||
|
||||
if (tx2 != nx || ty2 != ny)
|
||||
goto newpath2;
|
||||
|
||||
if (_numWaypoints < kMaxWaypoints) {
|
||||
_waypoints[_numWaypoints].x = tx;
|
||||
_waypoints[_numWaypoints].y = ty;
|
||||
_waypoints[_numWaypoints].level = lvl1;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
}
|
||||
|
||||
if (_numWaypoints < kMaxWaypoints) {
|
||||
_waypoints[_numWaypoints].x = nx;
|
||||
_waypoints[_numWaypoints].y = ny;
|
||||
_waypoints[_numWaypoints].level = lvl2;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
}
|
||||
} else {
|
||||
newpath2:
|
||||
tx = px;
|
||||
ty = ny;
|
||||
tx2 = nx;
|
||||
ty2 = ny;
|
||||
|
||||
lvl1 = lvl2 = level;
|
||||
|
||||
if (traceStraightPath(px, py, &tx, &ty, &lvl1)) {
|
||||
if (tx != px || ty != ny)
|
||||
return;
|
||||
|
||||
traceStraightPath(tx, ty, &nx, &ny, &lvl2);
|
||||
|
||||
if (tx2 != nx || ty2 != ny)
|
||||
return;
|
||||
|
||||
if (_numWaypoints < kMaxWaypoints) {
|
||||
_waypoints[_numWaypoints].x = tx;
|
||||
_waypoints[_numWaypoints].y = ty;
|
||||
_waypoints[_numWaypoints].level = lvl1;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
}
|
||||
|
||||
if (_numWaypoints < kMaxWaypoints) {
|
||||
_waypoints[_numWaypoints].x = nx;
|
||||
_waypoints[_numWaypoints].y = ny;
|
||||
_waypoints[_numWaypoints].level = lvl2;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// create a waypoint @ the player x,y? NO!
|
||||
if (nx == px && ny == py)
|
||||
return;
|
||||
|
||||
// make sure potential waypoint isn't on other waypoints!
|
||||
for (i = 0; i < _numWaypoints; i++)
|
||||
if (_waypoints[i].x == nx && _waypoints[i].y == ny)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_numWaypoints < kMaxWaypoints) {
|
||||
_waypoints[_numWaypoints].x = nx;
|
||||
_waypoints[_numWaypoints].y = ny;
|
||||
_waypoints[_numWaypoints].level = level;
|
||||
_numWaypoints++;
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
}
|
||||
}
|
||||
|
||||
void AI::removeFirstWaypoint() {
|
||||
if (!_numWaypoints)
|
||||
return;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < _numWaypoints; i++) {
|
||||
_waypoints[i] = _waypoints[i + 1];
|
||||
}
|
||||
|
||||
_waypoints[i].x = 0;
|
||||
_waypoints[i].y = 0;
|
||||
_waypoints[i].level = 0;
|
||||
_numWaypoints--;
|
||||
}
|
||||
|
||||
void AI::clearWaypoints() {
|
||||
for (uint8 i = 0; i < ARRAYSIZE(_waypoints); i++) {
|
||||
_waypoints[i].reset();
|
||||
}
|
||||
_numWaypoints = 0;
|
||||
}
|
||||
|
||||
bool AI::traceStraightPath(int x1, int y1, int *x2, int *y2, int *level) {
|
||||
// this checks to make sure we're only going vert or horz
|
||||
if (x1 != *x2 && y1 != *y2)
|
||||
return false;
|
||||
|
||||
// this sets a -1, 0, or 1 step value
|
||||
int xVel = *x2 - x1;
|
||||
if (xVel < 0)
|
||||
xVel = -1;
|
||||
if (xVel > 0)
|
||||
xVel = 1;
|
||||
|
||||
int yVel = *y2 - y1;
|
||||
if (yVel < 0)
|
||||
yVel = -1;
|
||||
if (yVel > 0)
|
||||
yVel = 1;
|
||||
|
||||
AIEntity *e;
|
||||
while (1) {
|
||||
// clear tile ahead?
|
||||
bool entOK = false;
|
||||
bool ok = false;
|
||||
|
||||
uint32 flags = g_hdb->_map->getMapBGTileFlags(x1, y1);
|
||||
if (flags & kFlagStairTop)
|
||||
*level = 2;
|
||||
else if (flags & kFlagStairBot)
|
||||
*level = 1;
|
||||
|
||||
// Floor level 1
|
||||
if (*level < 2) {
|
||||
ok = !(flags & (kFlagPlayerBlock | kFlagMonsterBlock));
|
||||
// if it's blocking, is it rad or plasma? (might be melted stuff on it)
|
||||
if (!ok) {
|
||||
ok = ((flags & kFlagPlasmaFloor) == kFlagPlasmaFloor) +
|
||||
((flags & kFlagRadFloor) == kFlagRadFloor);
|
||||
e = findEntity(x1, y1);
|
||||
if (e && g_hdb->_ai->walkThroughEnt(e->type))
|
||||
entOK = true;
|
||||
else if (ok && e && (e->state == STATE_FLOATING || e->state == STATE_MELTED || e == _player))
|
||||
entOK = ok = true;
|
||||
else
|
||||
ok = false;
|
||||
} else if (ok &&
|
||||
((flags & kFlagWater) == kFlagWater ||
|
||||
(flags & kFlagSlime) == kFlagSlime)) {
|
||||
// if it's non-blocking, is there water or slime?
|
||||
e = findEntity(x1, y1);
|
||||
if (e && g_hdb->_ai->walkThroughEnt(e->type))
|
||||
entOK = true;
|
||||
else
|
||||
if (e && (e->state == STATE_FLOATING || e->state == STATE_MELTED || e == _player))
|
||||
entOK = ok = true;
|
||||
else
|
||||
ok = false;
|
||||
}
|
||||
} else {
|
||||
// Floor level 2
|
||||
if (g_hdb->_map->getMapFGTileIndex(x1, y1) >= 0) // is there a foregnd tile? its flags take precedence on Level 2
|
||||
ok = !(g_hdb->_map->getMapFGTileFlags(x1, y1) & (kFlagPlayerBlock | kFlagMonsterBlock));
|
||||
else {
|
||||
flags = g_hdb->_map->getMapBGTileFlags(x1, y1);
|
||||
ok = !(flags & (kFlagPlayerBlock | kFlagMonsterBlock));
|
||||
// if it's blocking, is it rad or plasma? (might be melted stuff on it)
|
||||
if (!ok) {
|
||||
ok = ((flags & kFlagPlasmaFloor) == kFlagPlasmaFloor) +
|
||||
((flags & kFlagRadFloor) == kFlagRadFloor);
|
||||
e = findEntity(x1, y1);
|
||||
if (e && g_hdb->_ai->walkThroughEnt(e->type))
|
||||
entOK = true;
|
||||
else if (ok && e && (e->state == STATE_FLOATING || e->state == STATE_MELTED || e == _player))
|
||||
entOK = ok = true;
|
||||
else
|
||||
ok = false;
|
||||
} else if (ok &&
|
||||
((flags & kFlagWater) == kFlagWater ||
|
||||
(flags & kFlagSlime) == kFlagSlime)) {
|
||||
// if it's non-blocking, is there water or slime?
|
||||
e = findEntity(x1, y1);
|
||||
if (e && g_hdb->_ai->walkThroughEnt(e->type))
|
||||
entOK = true;
|
||||
else
|
||||
if (e && (e->state == STATE_FLOATING || e->state == STATE_MELTED || e == _player))
|
||||
entOK = ok = true;
|
||||
else
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
e = findEntity(x1, y1);
|
||||
if (e == _player)
|
||||
e = nullptr;
|
||||
else if (g_hdb->_map->laserBeamExist(x1, y1)) {
|
||||
*x2 = x1 - xVel;
|
||||
*y2 = y1 - yVel;
|
||||
return true;
|
||||
} else if (e && (e->level != _player->level) && (g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY) & kFlagGrating)) {
|
||||
// on the same level????
|
||||
entOK = 1;
|
||||
}
|
||||
|
||||
if (e && !entOK) {
|
||||
if (g_hdb->_ai->walkThroughEnt(e->type)) {
|
||||
// yes! are we at desired location?
|
||||
if (x1 == *x2 && y1 == *y2)
|
||||
return true;
|
||||
} else {
|
||||
// solid tile! back up one and return!
|
||||
*x2 = x1 - xVel;
|
||||
*y2 = y1 - yVel;
|
||||
return true;
|
||||
}
|
||||
} else if (x1 == *x2 && y1 == *y2) {
|
||||
// yes! are we at desired location?
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// solid tile! back up one and return!
|
||||
*x2 = x1 - xVel;
|
||||
*y2 = y1 - yVel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
x1 += xVel;
|
||||
y1 += yVel;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Tile *AI::getStandFrameDir(AIEntity *e) {
|
||||
switch (e->dir) {
|
||||
case DIR_DOWN:
|
||||
if (e->standdownFrames)
|
||||
return e->standdownGfx[0];
|
||||
else if (e->movedownFrames)
|
||||
return e->movedownGfx[0];
|
||||
break;
|
||||
case DIR_UP:
|
||||
if (e->standupFrames)
|
||||
return e->standupGfx[0];
|
||||
else if (e->moveupFrames)
|
||||
return e->moveupGfx[0];
|
||||
break;
|
||||
case DIR_LEFT:
|
||||
if (e->standleftFrames)
|
||||
return e->standleftGfx[0];
|
||||
else if (e->moveleftFrames)
|
||||
return e->moveleftGfx[0];
|
||||
break;
|
||||
case DIR_RIGHT:
|
||||
if (e->standrightFrames)
|
||||
return e->standrightGfx[0];
|
||||
else if (e->moverightFrames)
|
||||
return e->moverightGfx[0];
|
||||
break;
|
||||
case DIR_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return e->standdownGfx[0];
|
||||
}
|
||||
|
||||
void AI::drawWayPoints() {
|
||||
static int anim = 0;
|
||||
static uint32 delay = g_hdb->getTimeSlice();
|
||||
static int alpha = 255;
|
||||
static int aVel = -4;
|
||||
|
||||
int mapX, mapY;
|
||||
g_hdb->_map->getMapXY(&mapX, &mapY);
|
||||
|
||||
for (int i = 0; i < _numWaypoints; i++) {
|
||||
int x = _waypoints[i].x * kTileWidth;
|
||||
int y = _waypoints[i].y * kTileHeight;
|
||||
|
||||
if (x > mapX - 32 && (x < (mapX + g_hdb->_screenWidth)) &&
|
||||
y > mapY - 32 && (y < (mapY + g_hdb->_screenHeight)))
|
||||
_waypointGfx[anim]->drawMasked(x - mapX, y - mapY, alpha);
|
||||
}
|
||||
|
||||
// vary the alpha blending
|
||||
alpha = (alpha + aVel);
|
||||
if (alpha < 64) {
|
||||
alpha = 64;
|
||||
aVel = -aVel;
|
||||
}
|
||||
|
||||
if (alpha > 200) {
|
||||
alpha = 200;
|
||||
aVel = -aVel;
|
||||
}
|
||||
|
||||
// don't animate every single game frame...
|
||||
if (delay > g_hdb->getTimeSlice())
|
||||
return;
|
||||
|
||||
delay = g_hdb->getTimeSlice() + 100;
|
||||
|
||||
// cycle the waypoint gfx animation
|
||||
anim++;
|
||||
if (anim == 4)
|
||||
anim = 0;
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
1448
engines/hdb/ai.h
Normal file
1448
engines/hdb/ai.h
Normal file
File diff suppressed because it is too large
Load Diff
3
engines/hdb/configure.engine
Normal file
3
engines/hdb/configure.engine
Normal file
@@ -0,0 +1,3 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine hdb "Hyperspace Delivery Boy!" yes "" "" "16bit highres lua" ""
|
||||
4
engines/hdb/credits.pl
Normal file
4
engines/hdb/credits.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
begin_section("HDB");
|
||||
add_person("Eugene Sandulenko", "sev", "");
|
||||
add_person("Nipun Garg", "nipung", "GSoC student");
|
||||
end_section();
|
||||
134
engines/hdb/detection.cpp
Normal file
134
engines/hdb/detection.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* 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 "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "hdb/detection.h"
|
||||
|
||||
static const PlainGameDescriptor hdbGames[] = {
|
||||
{"hdb", "Hyperspace Delivery Boy!"},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
namespace HDB {
|
||||
|
||||
static const ADGameDescription gameDescriptions[] = {
|
||||
{
|
||||
"hdb",
|
||||
"",
|
||||
AD_ENTRY1s("hyperspace.mpc", "ff8e51d0872736bc6afe87cfcb846b70", 50339161),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
{
|
||||
"hdb",
|
||||
"",
|
||||
AD_ENTRY1s("hyperspace.mpc", "39d3c9dbc9614f370ad9430307c043f9", 45645305),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformLinux,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
// PocketPC Arm
|
||||
{
|
||||
"hdb",
|
||||
"",
|
||||
AD_ENTRY1s("hyperspace.msd", "a62468904beb3efe16d4d64f3955a32e", 6825555),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformPocketPC,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
|
||||
// Demos
|
||||
{
|
||||
"hdb",
|
||||
"Demo",
|
||||
AD_ENTRY1s("hyperdemo.mpc", "d8743b3b8be56486bcfb1398b2f2aad4", 13816461),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformLinux,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
{
|
||||
"hdb",
|
||||
"Demo",
|
||||
AD_ENTRY1s("hyperdemo.mpc", "f3bc878e179f00b8666a9846f3d9f9f5", 5236568),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
// provided by sev
|
||||
{
|
||||
"hdb",
|
||||
"Demo",
|
||||
AD_ENTRY1s("hyperdemo.mpc", "7bc533e8f1866931c884f1bc09353744", 13906865),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
{
|
||||
"hdb",
|
||||
"Demo",
|
||||
AD_ENTRY1s("hyperdemo.msd", "312525298ca9f5ac904883d1ce19dc0f", 3088651),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformPocketPC,
|
||||
ADGF_DEMO,
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
{
|
||||
"hdb",
|
||||
"Handango Demo",
|
||||
AD_ENTRY1s("hyperdemo.msd", "2d4457b284a940b7058b36e5706b9951", 3094241),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformPocketPC,
|
||||
(ADGF_DEMO | GF_HANDANGO),
|
||||
GUIO2(GUIO_NOMIDI,GAMEOPTION_CHEATMODE)
|
||||
},
|
||||
AD_TABLE_END_MARKER
|
||||
};
|
||||
|
||||
} // End of namespace HDB
|
||||
|
||||
class HDBMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
|
||||
public:
|
||||
HDBMetaEngineDetection() : AdvancedMetaEngineDetection(HDB::gameDescriptions, hdbGames) {
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "hdb";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Hyperspace Delivery Boy!";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Hyperspace Delivery Boy! (C) 2001 Monkeystone Games";
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(HDB_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, HDBMetaEngineDetection);
|
||||
35
engines/hdb/detection.h
Normal file
35
engines/hdb/detection.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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 HDB_DETECTION_H
|
||||
#define HDB_DETECTION_H
|
||||
|
||||
namespace HDB {
|
||||
|
||||
enum HDBGameFeatures {
|
||||
GF_HANDANGO = (1 << 0)
|
||||
};
|
||||
|
||||
#define GAMEOPTION_CHEATMODE GUIO_GAMEOPTIONS1
|
||||
|
||||
} // End of namespace HDB
|
||||
|
||||
#endif // HDB_DETECTION_H
|
||||
210
engines/hdb/file-manager.cpp
Normal file
210
engines/hdb/file-manager.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/* 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/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/compression/deflate.h"
|
||||
|
||||
#include "hdb/hdb.h"
|
||||
#include "hdb/file-manager.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
FileMan::FileMan() {
|
||||
_mpcFile = new Common::File;
|
||||
_dataHeader.id = 0;
|
||||
_dataHeader.dirSize = 0;
|
||||
}
|
||||
|
||||
FileMan::~FileMan() {
|
||||
delete _mpcFile;
|
||||
for (uint i = 0; i < _dir.size(); i++)
|
||||
delete _dir[i];
|
||||
}
|
||||
|
||||
void FileMan::openMPC(const Common::Path &filename) {
|
||||
if (!_mpcFile->open(filename))
|
||||
error("FileMan::openMPC(): Error reading the MSD/MPC file %s", filename.toString().c_str());
|
||||
|
||||
_dataHeader.id = _mpcFile->readUint32BE();
|
||||
|
||||
if (_dataHeader.id == MKTAG('M', 'P', 'C', 'C'))
|
||||
error("FileMan::openMPC: Compressed MPC File");
|
||||
else if (_dataHeader.id == MKTAG('M', 'S', 'D', 'U'))
|
||||
error("FileMan::openMPC: Uncompressed MSD File");
|
||||
else if (_dataHeader.id != MKTAG('M', 'P', 'C', 'U') && _dataHeader.id != MKTAG('M', 'S', 'D', 'C'))
|
||||
error("FileMan::openMPC: Invalid MPC/MSD File.");
|
||||
|
||||
// read the directory
|
||||
uint32 offset = _mpcFile->readUint32LE();
|
||||
_mpcFile->seek((int32)offset);
|
||||
|
||||
// Note: The MPC archive format assumes the offset to be uint32,
|
||||
// but Common::File::seek() takes the offset as int32.
|
||||
|
||||
_dataHeader.dirSize = _mpcFile->readUint32LE();
|
||||
|
||||
debug(8, "MPCU: Read %d entries", _dataHeader.dirSize);
|
||||
|
||||
for (uint32 fileIndex = 0; fileIndex < _dataHeader.dirSize; fileIndex++) {
|
||||
MPCEntry *dirEntry = new MPCEntry();
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
dirEntry->filename[i] = tolower(_mpcFile->readByte());
|
||||
|
||||
dirEntry->offset = _mpcFile->readUint32LE();
|
||||
dirEntry->length = _mpcFile->readUint32LE();
|
||||
dirEntry->ulength = _mpcFile->readUint32LE();
|
||||
dirEntry->type = (DataType)_mpcFile->readUint32LE();
|
||||
|
||||
debug(9, "%d: %s off:%d len:%d ulen: %d type: %d", fileIndex, dirEntry->filename, dirEntry->offset, dirEntry->length, dirEntry->ulength, dirEntry->type);
|
||||
|
||||
_dir.push_back(dirEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void FileMan::closeMPC() {
|
||||
_dir.clear();
|
||||
_mpcFile->close();
|
||||
}
|
||||
|
||||
void FileMan::seek(int32 offset, int flag) {
|
||||
_mpcFile->seek(offset, flag);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *FileMan::findFirstData(const char *string, DataType type, int *length) {
|
||||
Common::String fileString;
|
||||
MPCEntry *file = nullptr;
|
||||
|
||||
char fname[128];
|
||||
Common::strlcpy(fname, string, 128);
|
||||
char *pDest = strrchr(fname, '.');
|
||||
if (pDest)
|
||||
*pDest = '_';
|
||||
|
||||
debug(8, "Looking for Data: '%s' <- '%s'", fname, string);
|
||||
|
||||
Common::String fnameS(fname);
|
||||
fnameS.toLowercase();
|
||||
|
||||
// Find MPC Entry
|
||||
for (MPCIterator it = _dir.begin(); it != _dir.end(); it++) {
|
||||
fileString = (*it)->filename;
|
||||
if (fileString.equals(fnameS)) {
|
||||
if ((*it)->type == type) {
|
||||
file = *it;
|
||||
break;
|
||||
} else {
|
||||
debug(4, "Found Data but type mismatch: '%s', target: %d, found: %d", fnameS.c_str(), type, (*it)->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file == nullptr) {
|
||||
debug(4, "Couldn't find Data: '%s'", fnameS.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Load corresponding file into a buffer
|
||||
_mpcFile->seek(file->offset);
|
||||
byte *buffer = (byte *)malloc(file->length);
|
||||
|
||||
_mpcFile->read(buffer, file->length);
|
||||
|
||||
if (length)
|
||||
*length = file->ulength;
|
||||
|
||||
// Return buffer wrapped in a MemoryReadStream, automatically
|
||||
// uncompressed if it is zlib-compressed
|
||||
return Common::wrapCompressedReadStream(new Common::MemoryReadStream(buffer, file->length, DisposeAfterUse::YES), DisposeAfterUse::YES, file->length);
|
||||
}
|
||||
|
||||
int32 FileMan::getLength(const char *string, DataType type) {
|
||||
Common::String fileString;
|
||||
MPCEntry *file = nullptr;
|
||||
|
||||
char fname[128];
|
||||
Common::strlcpy(fname, string, 128);
|
||||
char *pDest = strrchr(fname, '.');
|
||||
if (pDest)
|
||||
*pDest = '_';
|
||||
|
||||
Common::String fnameS(fname);
|
||||
fnameS.toLowercase();
|
||||
|
||||
// Find MPC Entry
|
||||
for (MPCIterator it = _dir.begin(); it != _dir.end(); it++) {
|
||||
fileString = (*it)->filename;
|
||||
if (fileString.contains(fnameS)) {
|
||||
if ((*it)->type == type) {
|
||||
file = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file->ulength;
|
||||
}
|
||||
|
||||
int FileMan::getCount(const char *subString, DataType type) {
|
||||
int count = 0;
|
||||
Common::String fileString;
|
||||
|
||||
Common::String fnameS(subString);
|
||||
fnameS.toLowercase();
|
||||
|
||||
for (MPCIterator it = _dir.begin(); it != _dir.end(); it++) {
|
||||
fileString = (*it)->filename;
|
||||
if (fileString.contains(fnameS)) {
|
||||
if ((*it)->type == type) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Common::Array<const char *> *FileMan::findFiles(const char *string, DataType type) {
|
||||
Common::Array<const char *> *result = new Common::Array<const char *>;
|
||||
Common::String fileString;
|
||||
|
||||
Common::String fnameS(string);
|
||||
fnameS.toLowercase();
|
||||
|
||||
// Find MPC Entry
|
||||
for (MPCIterator it = _dir.begin(); it != _dir.end(); it++) {
|
||||
fileString = (*it)->filename;
|
||||
if (fileString.contains(fnameS)) {
|
||||
if ((*it)->type == type) {
|
||||
result->push_back((*it)->filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of Namespace HDB
|
||||
83
engines/hdb/file-manager.h
Normal file
83
engines/hdb/file-manager.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 HDB_FILE_MANAGER_H
|
||||
#define HDB_FILE_MANAGER_H
|
||||
|
||||
namespace Common {
|
||||
class File;
|
||||
}
|
||||
|
||||
#define MPCIterator Common::Array<MPCEntry *>::iterator
|
||||
|
||||
namespace HDB {
|
||||
|
||||
// Each entry in a MSD file is of the following types
|
||||
|
||||
enum DataType {
|
||||
TYPE_ERROR,
|
||||
TYPE_BINARY,
|
||||
TYPE_TILE32,
|
||||
TYPE_FONT,
|
||||
TYPE_ICON32,
|
||||
TYPE_PIC,
|
||||
|
||||
ENDOFTYPES
|
||||
};
|
||||
|
||||
struct MPCEntry {
|
||||
char filename[64]; // filename
|
||||
int32 offset; // offset in MSD file of data
|
||||
int32 length; // compressed length of data
|
||||
int32 ulength; // uncompressed length
|
||||
DataType type; // type of data
|
||||
};
|
||||
|
||||
class FileMan {
|
||||
private:
|
||||
|
||||
Common::File *_mpcFile;
|
||||
Common::Array<MPCEntry *> _dir;
|
||||
|
||||
public:
|
||||
|
||||
FileMan();
|
||||
~FileMan();
|
||||
|
||||
struct {
|
||||
uint32 id;
|
||||
uint32 dirSize;
|
||||
} _dataHeader;
|
||||
|
||||
void openMPC(const Common::Path &filename);
|
||||
void closeMPC();
|
||||
void seek(int32 offset, int flag);
|
||||
|
||||
Common::SeekableReadStream *findFirstData(const char *string, DataType type, int *length = nullptr);
|
||||
int32 getLength(const char *string, DataType type);
|
||||
int getCount(const char *subString, DataType type);
|
||||
Common::Array<const char *> *findFiles(const char *string, DataType type);
|
||||
|
||||
};
|
||||
|
||||
} // End of Namespace HDB
|
||||
|
||||
#endif // !HDB_FILE_MANAGER_H
|
||||
1462
engines/hdb/gfx.cpp
Normal file
1462
engines/hdb/gfx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
277
engines/hdb/gfx.h
Normal file
277
engines/hdb/gfx.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/* 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 HDB_GFX_H
|
||||
#define HDB_GFX_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Math {
|
||||
class SineTable;
|
||||
class CosineTable;
|
||||
}
|
||||
|
||||
namespace HDB {
|
||||
|
||||
#define HDB_FONT "normalprop"
|
||||
|
||||
struct TileLookup {
|
||||
const char *filename;
|
||||
Tile *tData;
|
||||
uint16 skyIndex;
|
||||
uint16 animIndex;
|
||||
|
||||
TileLookup() : filename(nullptr), tData(nullptr), skyIndex(0), animIndex(0) {}
|
||||
};
|
||||
|
||||
struct GfxCache {
|
||||
char name[32];
|
||||
bool status; // false = tileGfx, true = picGfx
|
||||
union {
|
||||
Tile *tileGfx;
|
||||
Picture *picGfx;
|
||||
};
|
||||
uint32 size;
|
||||
int16 loaded;
|
||||
|
||||
GfxCache() : status(false), tileGfx(nullptr), size(0), loaded(0) { name[0] = 0; }
|
||||
};
|
||||
|
||||
struct FontInfo {
|
||||
int type; // 0 = mono, 1 = proportional
|
||||
int numChars; // how many characters in font
|
||||
int height; // height of entire font
|
||||
int kerning; // space between chars
|
||||
int leading; // space between lines
|
||||
};
|
||||
|
||||
struct CharInfo {
|
||||
int16 width; // Character width in pixels
|
||||
int32 offset; // From the start of the font charInfo chunk
|
||||
};
|
||||
|
||||
class Gfx {
|
||||
public:
|
||||
|
||||
Gfx();
|
||||
~Gfx();
|
||||
|
||||
Graphics::ManagedSurface _globalSurface;
|
||||
|
||||
void init();
|
||||
void save(Common::OutSaveFile *out);
|
||||
void loadSaveFile(Common::InSaveFile *in);
|
||||
void fillScreen(uint32 color);
|
||||
void updateVideo();
|
||||
void setPointerState(int value);
|
||||
void drawPointer();
|
||||
void showPointer(bool status) {
|
||||
_showCursor = status;
|
||||
}
|
||||
bool getPointer() {
|
||||
return _showCursor;
|
||||
}
|
||||
|
||||
void setFade(bool fadeIn, bool black, int steps);
|
||||
void updateFade();
|
||||
bool isFadeActive() { return _fadeInfo.active; }
|
||||
bool isFadeStaying() { return _fadeInfo.stayFaded; }
|
||||
void turnOffFade() { _fadeInfo.active = _fadeInfo.stayFaded = false; }
|
||||
void turnOnSnow();
|
||||
void turnOffSnow() { _snowInfo.active = false; }
|
||||
|
||||
Picture *loadPic(const char *picName);
|
||||
Tile *loadTile(const char *tileName);
|
||||
Tile *loadIcon(const char *tileName);
|
||||
void setPixel(int x, int y, uint16 color);
|
||||
|
||||
Tile *getTile(int index);
|
||||
void cacheTileSequence(int index, int count);
|
||||
int getTileIndex(const char *name);
|
||||
Picture *getPicture(const char *name);
|
||||
|
||||
void emptyGfxCaches();
|
||||
void markTileCacheFreeable();
|
||||
void markGfxCacheFreeable();
|
||||
|
||||
// Returns: true->Tile, false->Pic
|
||||
bool selectGfxType(const char *name);
|
||||
Tile *getTileGfx(const char *name, int32 size);
|
||||
Picture *getPicGfx(const char *name, int32 size);
|
||||
|
||||
int isSky(int skyIndex);
|
||||
void setSky(int skyIndex);
|
||||
void setup3DStars();
|
||||
void setup3DStarsLeft();
|
||||
void draw3DStars();
|
||||
void draw3DStarsLeft();
|
||||
void drawSky();
|
||||
void drawSnow();
|
||||
|
||||
int animateTile(int tileIndex);
|
||||
|
||||
// Font Functions
|
||||
|
||||
bool loadFont(const char *string);
|
||||
void drawText(const char *string);
|
||||
void getDimensions(const char *string, int *pixelsWide, int *lines);
|
||||
int stringLength(const char *string);
|
||||
void centerPrint(const char *string);
|
||||
void setTextEdges(int left, int right, int top, int bottom);
|
||||
void getTextEdges(int *left, int *right, int *top, int *bottom);
|
||||
void setKernLead(int kern, int lead);
|
||||
void getKernLead(int *kern, int *lead);
|
||||
void setCursor(int x, int y);
|
||||
void getCursor(int *x, int *y);
|
||||
|
||||
// Trig Functions
|
||||
|
||||
double getSin(int index);
|
||||
double getCos(int index);
|
||||
|
||||
// Bonus star functions
|
||||
|
||||
void turnOnBonusStars(int which);
|
||||
void drawBonusStars();
|
||||
|
||||
void drawDebugInfo(Tile *_debugLogo, int fps);
|
||||
|
||||
private:
|
||||
int _numTiles;
|
||||
TileLookup *_tLookupArray;
|
||||
uint16 _skyTiles[kMaxSkies];
|
||||
|
||||
Graphics::ManagedSurface _fadeBuffer1, _fadeBuffer2;
|
||||
|
||||
Common::Array<GfxCache *> *_gfxCache;
|
||||
|
||||
int _currentSky; // 0 if no Sky, 1+ for which Sky to use
|
||||
struct {
|
||||
bool active;
|
||||
bool stayFaded;
|
||||
bool isBlack;
|
||||
int speed;
|
||||
bool isFadeIn;
|
||||
|
||||
int curStep;
|
||||
} _fadeInfo;
|
||||
|
||||
#define MAX_SNOW 50 // how many snowflakes onscreen
|
||||
#define MAX_SNOW_XV 12
|
||||
struct {
|
||||
bool active;
|
||||
double x[MAX_SNOW];
|
||||
double y[MAX_SNOW];
|
||||
double yv[MAX_SNOW];
|
||||
int xvindex[MAX_SNOW];
|
||||
} _snowInfo;
|
||||
|
||||
struct {
|
||||
int x, y, speed;
|
||||
uint16 color;
|
||||
} _stars3D[kNum3DStars];
|
||||
|
||||
struct {
|
||||
double x, y, speed;
|
||||
uint16 color;
|
||||
} _stars3DSlow[kNum3DStars];
|
||||
|
||||
int _tileSkyStars; // Index of sky_stars tile
|
||||
int _tileSkyStarsLeft; // Left-scrolling stars, slow
|
||||
int _tileSkyClouds; // Index of sky_stars tile
|
||||
Picture *_starField[4];
|
||||
Picture *_snowflake;
|
||||
Picture *_skyClouds;
|
||||
|
||||
struct {
|
||||
bool active;
|
||||
int starAngle[10];
|
||||
Picture *gfx[2];
|
||||
uint32 timer;
|
||||
int anim, radius;
|
||||
double angleSpeed;
|
||||
uint32 totalTime;
|
||||
} _starsInfo;
|
||||
|
||||
// Cursor
|
||||
int _cursorX, _cursorY;
|
||||
Picture *_mousePointer[8]; // Gfx for screen pointer (4 Animations)
|
||||
int _pointerDisplayable;
|
||||
bool _showCursor;
|
||||
|
||||
// Font Data
|
||||
|
||||
FontInfo _fontHeader;
|
||||
Common::Array<CharInfo *> _charInfoBlocks;
|
||||
Graphics::Surface _fontSurfaces[256];
|
||||
uint16 _fontGfx;
|
||||
int _eLeft, _eRight, _eTop, _eBottom;
|
||||
|
||||
bool _systemInit;
|
||||
|
||||
Math::SineTable *_sines;
|
||||
Math::CosineTable *_cosines;
|
||||
};
|
||||
|
||||
class Picture {
|
||||
public:
|
||||
|
||||
Picture();
|
||||
~Picture();
|
||||
|
||||
Graphics::Surface load(Common::SeekableReadStream *stream);
|
||||
int draw(int x, int y);
|
||||
int drawMasked(int x, int y, int alpha = 0xff);
|
||||
|
||||
int _width, _height;
|
||||
|
||||
char *getName() { return _name; }
|
||||
|
||||
Graphics::ManagedSurface *getSurface() { return &_surface; }
|
||||
|
||||
private:
|
||||
char _name[64];
|
||||
|
||||
Graphics::ManagedSurface _surface;
|
||||
};
|
||||
|
||||
class Tile {
|
||||
public:
|
||||
|
||||
Tile();
|
||||
~Tile();
|
||||
|
||||
Graphics::Surface load(Common::SeekableReadStream *stream);
|
||||
int draw(int x, int y);
|
||||
int drawMasked(int x, int y, int alpha = 0xff);
|
||||
|
||||
uint32 _flags;
|
||||
|
||||
char *getName() { return _name; }
|
||||
private:
|
||||
char _name[64];
|
||||
|
||||
Graphics::ManagedSurface _surface;
|
||||
};
|
||||
|
||||
} // End of Namespace HDB
|
||||
|
||||
#endif // !HDB_GFX_H
|
||||
1135
engines/hdb/hdb.cpp
Normal file
1135
engines/hdb/hdb.cpp
Normal file
File diff suppressed because it is too large
Load Diff
384
engines/hdb/hdb.h
Normal file
384
engines/hdb/hdb.h
Normal file
@@ -0,0 +1,384 @@
|
||||
/* 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 HDB_HDB_H
|
||||
#define HDB_HDB_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/fs.h"
|
||||
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Common {
|
||||
class RandomSource;
|
||||
}
|
||||
|
||||
namespace HDB {
|
||||
class AI;
|
||||
struct AIEntity;
|
||||
class FileMan;
|
||||
class Gfx;
|
||||
class Input;
|
||||
class LuaScript;
|
||||
class Map;
|
||||
class Menu;
|
||||
class Tile;
|
||||
class Picture;
|
||||
class Sound;
|
||||
class Window;
|
||||
|
||||
#define CONFIG_MUSICVOL "music_volume"
|
||||
#define CONFIG_SFXVOL "sfx_volume"
|
||||
#define CONFIG_SPEECHVOL "speech_volume"
|
||||
#define CONFIG_MSTONE7 "hdb_memory_heap"
|
||||
#define CONFIG_MSTONE14 "lua_stack_offset"
|
||||
#define CONFIG_MSTONE21 "fmod_mix_timer"
|
||||
#define CONFIG_SOUNDCACHE "sound_cache_max" // Unused
|
||||
#define CONFIG_GFXCACHE "gfx_cache_max" // Unused
|
||||
#define CONFIG_CHEAT "hypercheat"
|
||||
#define CONFIG_NOSPEECH "speech_mute"
|
||||
#define CONFIG_MUTEALL "mute"
|
||||
|
||||
enum {
|
||||
kTileWidth = 32,
|
||||
kTileHeight = 32,
|
||||
kMaxSkies = 10,
|
||||
kNum3DStars = 300,
|
||||
kFontSpace = 5,
|
||||
kFontIncrement = 1,
|
||||
kGameFPS = 60,
|
||||
kAnimFrameDelay = kGameFPS / 30,
|
||||
kAnimSlowFrames = kAnimFrameDelay * 10,
|
||||
kAnimMediumFrames = kAnimFrameDelay * 6,
|
||||
kAnimFastFrames = kAnimFrameDelay * 2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct ADGameDescription;
|
||||
|
||||
namespace HDB {
|
||||
|
||||
enum GameState {
|
||||
GAME_TITLE,
|
||||
GAME_MENU,
|
||||
GAME_PLAY,
|
||||
GAME_LOADING
|
||||
};
|
||||
|
||||
enum Flag {
|
||||
kFlagOK = 0x0,
|
||||
kFlagPlayerBlock = 0x1,
|
||||
kFlagMonsterBlock = 0x2,
|
||||
kFlagSolid = 0x3,
|
||||
kFlagItemDie = 0x4,
|
||||
kFlagPlayerDie = 0x8,
|
||||
kFlagMonsterDie = 0x10,
|
||||
kFlagInvisible = 0x20,
|
||||
kFlagMetal = 0x40,
|
||||
kFlagForeground = 0x80,
|
||||
kFlagMonsterHurt = 0x100,
|
||||
kFlagPushUp = 0x200,
|
||||
kFlagPushRight = 0x400,
|
||||
kFlagPushDown = 0x800,
|
||||
kFlagPushLeft = 0x1000,
|
||||
kFlagLightSink = 0x2000,
|
||||
kFlagSlime = 0x201C,
|
||||
kFlagHeavySink = 0x4000,
|
||||
kFlagWater = 0x401C,
|
||||
kFlagLightMelt = 0x8000,
|
||||
kFlagHeavyMelt = 0x10000,
|
||||
kFlagSlide = 0x20000,
|
||||
kFlagEnergyFloor = 0x40000,
|
||||
kFlagPlasmaFloor = 0x6000D,
|
||||
kFlagRadFloor = 0x6800D,
|
||||
kFlagTeleport = 0x80000,
|
||||
kFlagSpecial = 0x100000,
|
||||
kFlagIce = 0x120000,
|
||||
kFlagStairBot = 0x200000,
|
||||
kFlagStairTop = 0x400000,
|
||||
kFlagAnimSlow = 0x800000,
|
||||
kFlagAnimMedium = 0x1000000,
|
||||
kFlagAnimFast = 0x1800000,
|
||||
kFlagMasked = 0x2000000,
|
||||
kFlagGrating = 0x4000000,
|
||||
kFlagPlummet = 0x8000000
|
||||
};
|
||||
|
||||
struct Save {
|
||||
char saveID[12];
|
||||
int fileSlot;
|
||||
char mapName[32];
|
||||
uint32 seconds;
|
||||
|
||||
Save() : fileSlot(0), seconds(0) {
|
||||
saveID[0] = 0;
|
||||
mapName[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class HDBGame : public Engine {
|
||||
public:
|
||||
HDBGame(OSystem *syst, const ADGameDescription *gameDesc);
|
||||
~HDBGame() override;
|
||||
|
||||
bool hasFeature(Engine::EngineFeature f) const override;
|
||||
void initializePath(const Common::FSNode &gamePath) override;
|
||||
|
||||
Common::Error run() override;
|
||||
void syncSoundSettings() override;
|
||||
|
||||
// Detection related members;
|
||||
const ADGameDescription *_gameDescription;
|
||||
const char *getGameId() const;
|
||||
const char *getGameFile() const;
|
||||
uint32 getGameFlags() const;
|
||||
Common::Platform getPlatform() const;
|
||||
bool isDemo() const;
|
||||
bool isPPC() const;
|
||||
bool isHandango() const;
|
||||
|
||||
// Platform-Specific Constants
|
||||
|
||||
int _screenWidth;
|
||||
int _screenHeight;
|
||||
int _screenDrawWidth; // visible pixels wide
|
||||
int _screenDrawHeight;
|
||||
int _progressY;
|
||||
|
||||
/*
|
||||
Game System Pointers
|
||||
*/
|
||||
|
||||
FileMan *_fileMan;
|
||||
Gfx *_gfx;
|
||||
LuaScript *_lua;
|
||||
Map *_map;
|
||||
AI *_ai;
|
||||
Input *_input;
|
||||
Menu *_menu;
|
||||
Sound *_sound;
|
||||
Window *_window;
|
||||
|
||||
// Random Source
|
||||
Common::RandomSource *_rnd;
|
||||
|
||||
// Game related members;
|
||||
|
||||
bool init();
|
||||
void save(Common::OutSaveFile *out);
|
||||
void loadSaveFile(Common::InSaveFile *in);
|
||||
|
||||
void start();
|
||||
bool restartMap();
|
||||
bool startMap(const char *name);
|
||||
|
||||
void changeMap(const char *name) {
|
||||
Common::strlcpy(_changeMapname, name, 64);
|
||||
_changeLevel = true;
|
||||
}
|
||||
|
||||
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
|
||||
Common::Error loadGameState(int slot) override;
|
||||
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
|
||||
void saveGame(Common::OutSaveFile *out);
|
||||
void loadGame(Common::InSaveFile *in);
|
||||
|
||||
Common::String genSaveFileName(uint slot, bool lua);
|
||||
|
||||
void saveWhenReady(int slot) {
|
||||
_saveInfo.active = true;
|
||||
_saveInfo.slot = slot;
|
||||
}
|
||||
|
||||
void loadWhenReady(int slot) {
|
||||
_loadInfo.active = true;
|
||||
_loadInfo.slot = slot;
|
||||
}
|
||||
|
||||
void setGameState(GameState gs) {
|
||||
_gameState = gs;
|
||||
}
|
||||
GameState getGameState() {
|
||||
return _gameState;
|
||||
}
|
||||
void changeGameState();
|
||||
void paint();
|
||||
void moveMap(int x, int y); // Get Stylus Coords and Scroll
|
||||
void startMoveMap(int x, int y); // Start Dragging Map
|
||||
|
||||
void setTargetXY(int x, int y);
|
||||
void useEntity(AIEntity *e);
|
||||
|
||||
void setupProgressBar(int maxCount);
|
||||
void drawProgressBar();
|
||||
void makeProgress() {
|
||||
_progressCurrent++;
|
||||
drawProgressBar();
|
||||
}
|
||||
void checkProgress();
|
||||
void stopProgress() {
|
||||
_progressActive = false;
|
||||
}
|
||||
void drawLoadingScreen();
|
||||
|
||||
int getActionMode() {
|
||||
return _actionMode;
|
||||
}
|
||||
void setActionMode(int status) {
|
||||
_actionMode = status;
|
||||
}
|
||||
|
||||
void togglePause() {
|
||||
_pauseFlag ^= true;
|
||||
}
|
||||
|
||||
bool getPause() {
|
||||
return _pauseFlag;
|
||||
}
|
||||
|
||||
void resetTimer() {
|
||||
_timePlayed = _timeSeconds = 0;
|
||||
}
|
||||
|
||||
uint32 getTime() {
|
||||
return _timePlayed / 1000;
|
||||
}
|
||||
|
||||
uint32 getTimeSlice() {
|
||||
return _timeSlice;
|
||||
}
|
||||
|
||||
uint32 getTimeSliceDelta() {
|
||||
return _timeSlice - _prevTimeSlice;
|
||||
}
|
||||
|
||||
const Common::String *getTargetName() {
|
||||
return &_targetName;
|
||||
}
|
||||
|
||||
int getDebug() { return _debugFlag; }
|
||||
void setDebug(int flag) { _debugFlag = flag; }
|
||||
|
||||
bool isVoiceless() {
|
||||
/*
|
||||
FIXME: Add hyperspace-nv.mpc to gameDescriptions[]
|
||||
in detection.cpp, and add a flag check for it.
|
||||
Until then, the voiceless version is unsupported.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
char *lastMapName() { return _lastMapname; }
|
||||
char *currentMapName() { return _currentMapname; }
|
||||
char *getInMapName() { return _inMapName; }
|
||||
void setInMapName(const char *name);
|
||||
|
||||
void changeLevel(const char *name) {
|
||||
Common::strlcpy(_changeMapname, name, 64);
|
||||
_changeLevel = true;
|
||||
}
|
||||
|
||||
//
|
||||
// monkeystone secret stars
|
||||
//
|
||||
int32 getStarsMonkeystone7() { return _monkeystone7; }
|
||||
int32 getStarsMonkeystone14() { return _monkeystone14; }
|
||||
int32 getStarsMonkeystone21() { return _monkeystone21; }
|
||||
|
||||
void setStarsMonkeystone7(int32 value) { _monkeystone7 = value; }
|
||||
void setStarsMonkeystone14(int32 value) { _monkeystone14 = value; }
|
||||
void setStarsMonkeystone21(int32 value) { _monkeystone21 = value; }
|
||||
|
||||
void setCheatingOn() {
|
||||
_cheating = true;
|
||||
}
|
||||
bool getCheatingOn() {
|
||||
return _cheating;
|
||||
}
|
||||
|
||||
Save _saveHeader;
|
||||
bool _gameShutdown;
|
||||
Graphics::PixelFormat _format;
|
||||
|
||||
Picture *_progressGfx, *_progressMarkGfx;
|
||||
Picture *_loadingScreenGfx, *_logoGfx;
|
||||
bool _progressActive;
|
||||
int _progressCurrent, _progressXOffset, _progressMax;
|
||||
|
||||
// FPS Variables
|
||||
Common::Array<uint32> _frames;
|
||||
|
||||
Common::OutSaveFile *_currentOutSaveFile;
|
||||
Common::InSaveFile *_currentInSaveFile;
|
||||
|
||||
private:
|
||||
|
||||
uint32 _timePlayed;
|
||||
uint32 _timeSlice, _prevTimeSlice;
|
||||
uint32 _timeSeconds;
|
||||
|
||||
uint32 _tiempo;
|
||||
|
||||
// Game Variables
|
||||
|
||||
bool _systemInit;
|
||||
GameState _gameState;
|
||||
int _actionMode; // 0 or 1
|
||||
|
||||
// Misc Variables
|
||||
bool _pauseFlag;
|
||||
bool _cheating;
|
||||
int _debugFlag;
|
||||
Tile *_debugLogo;
|
||||
int _dx, _dy; // DEBUG : for dragging map
|
||||
|
||||
char _currentMapname[64];
|
||||
char _lastMapname[64];
|
||||
|
||||
char _currentLuaName[64];
|
||||
char _lastLuaName[64];
|
||||
|
||||
char _inMapName[32]; // Name Inside Map file
|
||||
|
||||
int32 _monkeystone7;
|
||||
int32 _monkeystone14;
|
||||
int32 _monkeystone21;
|
||||
|
||||
bool _changeLevel;
|
||||
char _changeMapname[64];
|
||||
|
||||
struct {
|
||||
bool active;
|
||||
int slot;
|
||||
} _saveInfo, _loadInfo;
|
||||
|
||||
bool _noMusicDriver; // If "Music Device" is set to "No Music" from Audio tab
|
||||
};
|
||||
|
||||
extern HDBGame *g_hdb;
|
||||
|
||||
}// End of namespace HDB
|
||||
|
||||
#endif
|
||||
550
engines/hdb/input.cpp
Normal file
550
engines/hdb/input.cpp
Normal file
@@ -0,0 +1,550 @@
|
||||
/* 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 "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/gfx.h"
|
||||
#include "hdb/input.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/menu.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
void Input::init() {
|
||||
_stylusDown = false;
|
||||
_buttons = 0;
|
||||
|
||||
_mouseX = g_hdb->_screenWidth / 2;
|
||||
_mouseY = g_hdb->_screenHeight / 2;
|
||||
}
|
||||
|
||||
void Input::setButtons(uint16 b) {
|
||||
_buttons = b;
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
// Change Game State
|
||||
if ((_buttons & kButtonA) && (g_hdb->getGameState() != GAME_MENU)) {
|
||||
if (g_hdb->_ai->cinematicsActive() && g_hdb->_ai->cineAbortable()) {
|
||||
g_hdb->_ai->cineAbort();
|
||||
g_hdb->_sound->playSound(SND_POP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hdb->getGameState() == GAME_TITLE)
|
||||
g_hdb->_menu->changeToMenu();
|
||||
g_hdb->_sound->playSound(SND_MENU_BACKOUT);
|
||||
g_hdb->changeGameState();
|
||||
}
|
||||
|
||||
if (g_hdb->isPPC()) {
|
||||
if (_buttons & kButtonD) {
|
||||
if (g_hdb->_window->inventoryActive()) {
|
||||
g_hdb->_window->closeInv();
|
||||
g_hdb->_window->openDeliveries(false);
|
||||
} else if (g_hdb->_window->deliveriesActive()) {
|
||||
g_hdb->_window->closeDlvs();
|
||||
} else {
|
||||
g_hdb->_window->openInventory();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug Mode Cycling
|
||||
if ((_buttons & kButtonExit) && g_hdb->getCheatingOn()) {
|
||||
int debugFlag = g_hdb->getDebug();
|
||||
debugFlag++;
|
||||
if (debugFlag > 2)
|
||||
debugFlag = 0;
|
||||
g_hdb->setDebug(debugFlag);
|
||||
|
||||
if (debugFlag == 2)
|
||||
g_hdb->_ai->clearWaypoints();
|
||||
|
||||
if (!debugFlag && g_hdb->getGameState() == GAME_PLAY) {
|
||||
int x, y;
|
||||
g_hdb->_ai->getPlayerXY(&x, &y);
|
||||
g_hdb->_map->centerMapXY(x + 16, y + 16); // point to center of player
|
||||
}
|
||||
}
|
||||
|
||||
if (g_hdb->getGameState() == GAME_PLAY) {
|
||||
// Is Player Dead? Click on TRY AGAIN
|
||||
if (g_hdb->_ai->playerDead()) {
|
||||
// TRY AGAIN is onscreen...
|
||||
if (_buttons & kButtonB) {
|
||||
if (g_hdb->loadGameState(kAutoSaveSlot).getCode() == Common::kNoError) {
|
||||
g_hdb->_window->clearTryAgain();
|
||||
g_hdb->setGameState(GAME_PLAY);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hdb->isPPC()) {
|
||||
// Deliveries screen?
|
||||
if (g_hdb->_window->deliveriesActive() && !g_hdb->_window->animatingDelivery()) {
|
||||
if (_buttons & kButtonLeft) {
|
||||
int amount = g_hdb->_ai->getDeliveriesAmount();
|
||||
int current = g_hdb->_window->getSelectedDelivery();
|
||||
|
||||
if (!current)
|
||||
current = amount - 1;
|
||||
else
|
||||
current--;
|
||||
|
||||
g_hdb->_window->setSelectedDelivery(current);
|
||||
} else if (_buttons & kButtonRight) {
|
||||
int amount = g_hdb->_ai->getDeliveriesAmount();
|
||||
int current = g_hdb->_window->getSelectedDelivery();
|
||||
|
||||
current++;
|
||||
if (current == amount)
|
||||
current = 0;
|
||||
|
||||
g_hdb->_window->setSelectedDelivery(current);
|
||||
} else if (_buttons & kButtonB)
|
||||
g_hdb->_window->closeDlvs();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Resources screen? Move select cursor around
|
||||
//
|
||||
if (g_hdb->_window->inventoryActive()) {
|
||||
// select weapon?
|
||||
if (_buttons & kButtonB) {
|
||||
static AIType lastWeaponSelected = AI_NONE;
|
||||
|
||||
if (!g_hdb->getActionMode()) {
|
||||
g_hdb->_window->closeInv();
|
||||
return;
|
||||
}
|
||||
|
||||
AIType t = g_hdb->_ai->getInvItemType(g_hdb->_window->getInvSelect());
|
||||
Tile *gfx = g_hdb->_ai->getInvItemGfx(g_hdb->_window->getInvSelect());
|
||||
|
||||
switch (t) {
|
||||
case ITEM_CLUB:
|
||||
case ITEM_ROBOSTUNNER:
|
||||
case ITEM_SLUGSLINGER:
|
||||
g_hdb->_ai->setPlayerWeapon(t, gfx);
|
||||
if (t == lastWeaponSelected) {
|
||||
g_hdb->_window->closeInv();
|
||||
return;
|
||||
}
|
||||
lastWeaponSelected = t;
|
||||
g_hdb->_sound->playSound(SND_MENU_ACCEPT);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_hdb->_sound->playSound(SND_CELLHOLDER_USE_REJECT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_buttons & kButtonLeft) {
|
||||
int amount = g_hdb->_ai->getInvMax();
|
||||
int current = g_hdb->_window->getInvSelect();
|
||||
|
||||
if (!amount)
|
||||
return;
|
||||
|
||||
if (current == 5)
|
||||
current = amount - 1;
|
||||
else if (!current && amount > 5)
|
||||
current = 4;
|
||||
else if (!current)
|
||||
current = amount - 1;
|
||||
else
|
||||
current--;
|
||||
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
g_hdb->_window->setInvSelect(current);
|
||||
} else if (_buttons & kButtonRight) {
|
||||
int amount = g_hdb->_ai->getInvMax();
|
||||
int current = g_hdb->_window->getInvSelect();
|
||||
|
||||
if (!amount)
|
||||
return;
|
||||
|
||||
if (amount > 5) {
|
||||
if (current == amount - 1)
|
||||
current = 5;
|
||||
else if (current == 4)
|
||||
current = 0;
|
||||
else
|
||||
current++;
|
||||
} else if (current == amount - 1)
|
||||
current = 0;
|
||||
else
|
||||
current++;
|
||||
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
g_hdb->_window->setInvSelect(current);
|
||||
} else if (_buttons & kButtonUp) {
|
||||
int amount = g_hdb->_ai->getInvMax();
|
||||
int current = g_hdb->_window->getInvSelect();
|
||||
|
||||
if (amount < 6)
|
||||
return;
|
||||
|
||||
if (current - 5 >= 0)
|
||||
current -= 5;
|
||||
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
g_hdb->_window->setInvSelect(current);
|
||||
} else if (_buttons & kButtonDown) {
|
||||
int amount = g_hdb->_ai->getInvMax();
|
||||
int current = g_hdb->_window->getInvSelect();
|
||||
|
||||
if (amount < 6)
|
||||
return;
|
||||
|
||||
if (current + 5 < amount)
|
||||
current += 5;
|
||||
else if (current < 5)
|
||||
current = amount - 1;
|
||||
|
||||
g_hdb->_sound->playSound(SND_MENU_SLIDER);
|
||||
g_hdb->_window->setInvSelect(current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose from DialogChoice
|
||||
if (g_hdb->_window->dialogChoiceActive()) {
|
||||
if (_buttons & kButtonUp)
|
||||
g_hdb->_window->dialogChoiceMoveup();
|
||||
else if (_buttons & kButtonDown)
|
||||
g_hdb->_window->dialogChoiceMovedown();
|
||||
else if (_buttons & kButtonB)
|
||||
g_hdb->_window->closeDialogChoice();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to move the player
|
||||
if (!g_hdb->_ai->playerDead())
|
||||
g_hdb->_ai->movePlayer(_buttons);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Input::getButtons() {
|
||||
return _buttons;
|
||||
}
|
||||
|
||||
void Input::stylusDown(int x, int y) {
|
||||
static uint32 delay = 0, time;
|
||||
|
||||
// Don't let the screen get clicked too fast
|
||||
time = g_system->getMillis();
|
||||
if (time - delay < 100)
|
||||
return;
|
||||
time = delay;
|
||||
|
||||
GameState gs = g_hdb->getGameState();
|
||||
|
||||
switch (gs) {
|
||||
case GAME_TITLE:
|
||||
g_hdb->_menu->changeToMenu();
|
||||
g_hdb->changeGameState();
|
||||
break;
|
||||
case GAME_MENU:
|
||||
g_hdb->_menu->processInput(x, y);
|
||||
break;
|
||||
case GAME_PLAY:
|
||||
{
|
||||
// Is Player Dead? Click on TRY AGAIN
|
||||
if (g_hdb->_ai->playerDead()) {
|
||||
if (y >= g_hdb->_window->_tryRestartY && y <= g_hdb->_window->_tryRestartY + 24) {
|
||||
if (g_hdb->loadGameState(kAutoSaveSlot).getCode() == Common::kNoError) {
|
||||
g_hdb->_window->clearTryAgain();
|
||||
g_hdb->setGameState(GAME_PLAY);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hdb->isPPC()) {
|
||||
// is Deliveries active?
|
||||
if (g_hdb->_window->deliveriesActive()) {
|
||||
if (!g_hdb->_window->checkDlvsClose(x, y))
|
||||
return;
|
||||
if (!g_hdb->_ai->cinematicsActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// is Inventory active?
|
||||
if (g_hdb->_window->inventoryActive()) {
|
||||
if (!g_hdb->_window->checkInvClose(x, y))
|
||||
return;
|
||||
if (!g_hdb->_ai->cinematicsActive())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Is Dialog Active?
|
||||
if (g_hdb->_window->dialogActive()) {
|
||||
g_hdb->_window->closeDialog();
|
||||
if (!g_hdb->_ai->cinematicsActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// Is a Choice Dialog Active?
|
||||
if (g_hdb->_window->dialogChoiceActive()) {
|
||||
if (!g_hdb->_window->checkDialogChoiceClose(x, y))
|
||||
return;
|
||||
if (!g_hdb->_ai->cinematicsActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// Is MessageBar active?
|
||||
if (g_hdb->_window->msgBarActive()) {
|
||||
if (g_hdb->_window->checkMsgClose(x, y))
|
||||
return;
|
||||
}
|
||||
|
||||
// In a cinematic?
|
||||
if (g_hdb->_ai->playerLocked())
|
||||
return;
|
||||
|
||||
// Check for map dragging in debug Mode and place player there
|
||||
if ((GAME_PLAY == g_hdb->getGameState()) && g_hdb->getDebug() == 2) {
|
||||
int mx, my;
|
||||
g_hdb->_map->getMapXY(&mx, &my);
|
||||
|
||||
mx = ((mx + x) / kTileWidth) * kTileWidth;
|
||||
my = ((my + y) / kTileHeight) * kTileHeight;
|
||||
g_hdb->_ai->setPlayerXY(mx, my);
|
||||
|
||||
g_hdb->startMoveMap(x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clicked in the world
|
||||
int worldX, worldY;
|
||||
g_hdb->_map->getMapXY(&worldX, &worldY);
|
||||
worldX = ((worldX + x) / kTileWidth) * kTileWidth;
|
||||
worldY = ((worldY + y) / kTileHeight) * kTileHeight;
|
||||
|
||||
if (!g_hdb->isPPC()) {
|
||||
// Don't allow a click into INV/DELIVERIES area to go into the world
|
||||
if (x >= (g_hdb->_screenWidth - 32 * 5))
|
||||
return;
|
||||
}
|
||||
|
||||
// Double-Clicking on the player to open inventory?
|
||||
int nx, ny;
|
||||
g_hdb->_ai->getPlayerXY(&nx, &ny);
|
||||
if (g_hdb->isPPC()) {
|
||||
if (nx == worldX && ny == worldY) {
|
||||
static uint32 dblClickTimer = 0;
|
||||
|
||||
if (dblClickTimer && ((int)(g_system->getMillis() - dblClickTimer) < (int)(kGameFPS * 1000 / 60))) {
|
||||
g_hdb->_window->openInventory();
|
||||
dblClickTimer = 0;
|
||||
g_hdb->_ai->togglePlayerRunning();
|
||||
if (g_hdb->_ai->playerRunning())
|
||||
g_hdb->_window->centerTextOut("Running Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
|
||||
else
|
||||
g_hdb->_window->centerTextOut("Walking Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
return;
|
||||
} else
|
||||
dblClickTimer = g_system->getMillis();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle Walk Speed if we clicked Player
|
||||
static uint32 lastRunning = g_system->getMillis();
|
||||
if (nx == worldX && ny == worldY) {
|
||||
if (lastRunning > g_system->getMillis())
|
||||
return;
|
||||
lastRunning = g_system->getMillis() + 1000 * kRunToggleDelay;
|
||||
g_hdb->_ai->togglePlayerRunning();
|
||||
if (g_hdb->_ai->playerRunning())
|
||||
g_hdb->_window->centerTextOut("Running Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
|
||||
else
|
||||
g_hdb->_window->centerTextOut("Walking Speed", g_hdb->_screenHeight - 32, kRunToggleDelay * kGameFPS);
|
||||
g_hdb->_sound->playSound(SND_SWITCH_USE);
|
||||
}
|
||||
|
||||
g_hdb->setTargetXY(worldX, worldY);
|
||||
break;
|
||||
}
|
||||
case GAME_LOADING:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::stylusMove(int x, int y) {
|
||||
// In a cinematic?
|
||||
if (g_hdb->_ai->playerLocked() || g_hdb->_ai->playerDead())
|
||||
return;
|
||||
|
||||
switch (g_hdb->getGameState()) {
|
||||
case GAME_PLAY:
|
||||
if (g_hdb->getDebug() == 2)
|
||||
g_hdb->moveMap(x, y);
|
||||
break;
|
||||
case GAME_MENU:
|
||||
g_hdb->_menu->processInput(x, y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::updateMouse(int newX, int newY) {
|
||||
_mouseX = CLIP(newX, 0, g_hdb->_screenWidth - 1);
|
||||
_mouseY = CLIP(newY, 0, g_hdb->_screenHeight - 1);
|
||||
|
||||
// Turn Cursor back on?
|
||||
if (!g_hdb->_gfx->getPointer())
|
||||
g_hdb->_gfx->showPointer(true);
|
||||
|
||||
// Check if LButton is being dragged
|
||||
if (_stylusDown)
|
||||
stylusMove(_mouseX, _mouseY);
|
||||
}
|
||||
|
||||
void Input::updateMouseButtons(bool isDown) {
|
||||
_stylusDown = isDown;
|
||||
|
||||
// Check if LButton has been pressed
|
||||
// Check if LButton has been lifted
|
||||
if (isDown) {
|
||||
if (g_hdb->isPPC()) {
|
||||
stylusDown(_mouseX, _mouseY);
|
||||
return;
|
||||
}
|
||||
if (_mouseX > (g_hdb->_screenWidth - 32 * 5) && _mouseY < 240) {
|
||||
g_hdb->_window->checkInvSelect(_mouseX, _mouseY);
|
||||
} else if (_mouseX > (g_hdb->_screenWidth - 32 * 5) && _mouseY >= 240) {
|
||||
g_hdb->_window->checkDlvSelect(_mouseX, _mouseY);
|
||||
} else {
|
||||
if (g_hdb->getPause() && g_hdb->getGameState() == GAME_PLAY) {
|
||||
g_hdb->_window->checkPause(_mouseX, _mouseY);
|
||||
return;
|
||||
}
|
||||
stylusDown(_mouseX, _mouseY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Input::updateActions(Common::Event event, bool keyDown, bool fromMouse) {
|
||||
static bool current = false, last = false;
|
||||
|
||||
if (keyDown && event.customType == kHDBActionQuit) {
|
||||
g_hdb->quitGame();
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 buttons = getButtons();
|
||||
|
||||
// PAUSE key pressed?
|
||||
last = current;
|
||||
if (keyDown && event.customType == kHDBActionPause && g_hdb->getGameState() == GAME_PLAY) {
|
||||
current = true;
|
||||
if (!last) {
|
||||
g_hdb->togglePause();
|
||||
g_hdb->_sound->playSound(SND_POP);
|
||||
}
|
||||
} else
|
||||
current = false;
|
||||
|
||||
if (!g_hdb->getPause()) {
|
||||
if (event.customType == kHDBActionUp) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonUp;
|
||||
if (g_hdb->_gfx->getPointer() && !fromMouse)
|
||||
g_hdb->_gfx->showPointer(false);
|
||||
} else {
|
||||
buttons &= ~kButtonUp;
|
||||
}
|
||||
} else if (event.customType == kHDBActionDown) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonDown;
|
||||
if (g_hdb->_gfx->getPointer() && !fromMouse)
|
||||
g_hdb->_gfx->showPointer(false);
|
||||
} else {
|
||||
buttons &= ~kButtonDown;
|
||||
}
|
||||
} else if (event.customType == kHDBActionLeft) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonLeft;
|
||||
if (g_hdb->_gfx->getPointer() && !fromMouse)
|
||||
g_hdb->_gfx->showPointer(false);
|
||||
} else {
|
||||
buttons &= ~kButtonLeft;
|
||||
}
|
||||
} else if (event.customType == kHDBActionRight) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonRight;
|
||||
if (g_hdb->_gfx->getPointer() && !fromMouse)
|
||||
g_hdb->_gfx->showPointer(false);
|
||||
} else {
|
||||
buttons &= ~kButtonRight;
|
||||
}
|
||||
} else if (event.customType == kHDBActionUse) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonB;
|
||||
if (g_hdb->_gfx->getPointer() && !fromMouse)
|
||||
g_hdb->_gfx->showPointer(false);
|
||||
} else {
|
||||
buttons &= ~kButtonB;
|
||||
}
|
||||
} else if (event.customType == kHDBActionClearWaypoints) {
|
||||
if (keyDown) {
|
||||
g_hdb->_ai->clearWaypoints();
|
||||
g_hdb->_sound->playSound(SND_POP);
|
||||
}
|
||||
}
|
||||
// TODO: Inventory key
|
||||
}
|
||||
|
||||
if (event.customType == kHDBActionMenu) {
|
||||
if (keyDown) {
|
||||
buttons |= kButtonA;
|
||||
g_hdb->_gfx->showPointer(true);
|
||||
g_hdb->_menu->setMenuKey(1);
|
||||
} else {
|
||||
buttons &= ~kButtonA;
|
||||
g_hdb->_menu->setMenuKey(0);
|
||||
}
|
||||
} else if (event.customType == kHDBActionDebug) {
|
||||
if (keyDown)
|
||||
buttons |= kButtonExit;
|
||||
else
|
||||
buttons &= ~kButtonExit;
|
||||
}
|
||||
|
||||
setButtons(buttons);
|
||||
}
|
||||
|
||||
} // End of Namespace
|
||||
87
engines/hdb/input.h
Normal file
87
engines/hdb/input.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 HDB_INPUT_H
|
||||
#define HDB_INPUT_H
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
enum Button {
|
||||
kButtonUp = 2 << 0,
|
||||
kButtonDown = 2 << 1,
|
||||
kButtonLeft = 2 << 2,
|
||||
kButtonRight = 2 << 3,
|
||||
kButtonA = 2 << 4,
|
||||
kButtonB = 2 << 5,
|
||||
kButtonC = 2 << 6,
|
||||
kButtonD = 2 << 7,
|
||||
kButtonExit = 2 << 8
|
||||
};
|
||||
|
||||
enum HDBAction {
|
||||
kHDBActionNone,
|
||||
kHDBActionUp,
|
||||
kHDBActionDown,
|
||||
kHDBActionLeft,
|
||||
kHDBActionRight,
|
||||
kHDBActionUse,
|
||||
kHDBActionClearWaypoints,
|
||||
kHDBActionInventory,
|
||||
kHDBActionMenu,
|
||||
kHDBActionPause,
|
||||
kHDBActionDebug,
|
||||
kHDBActionQuit
|
||||
};
|
||||
|
||||
class Input {
|
||||
public:
|
||||
|
||||
void init();
|
||||
|
||||
void setButtons(uint16 b);
|
||||
uint16 getButtons();
|
||||
void stylusDown(int x, int y);
|
||||
void stylusUp(int x, int y);
|
||||
void stylusMove(int x, int y);
|
||||
|
||||
void updateMouse(int newX, int newY);
|
||||
void updateMouseButtons(bool isDown);
|
||||
void updateActions(Common::Event event, bool keyDown, bool fromMouse);
|
||||
|
||||
int getMouseX() {
|
||||
return _mouseX;
|
||||
}
|
||||
int getMouseY() {
|
||||
return _mouseY;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint16 _buttons; // Flags for buttons
|
||||
bool _stylusDown;
|
||||
int _mouseX, _mouseY;
|
||||
};
|
||||
|
||||
} // End of Namespace
|
||||
|
||||
#endif // !HDB_INPUT_H
|
||||
2118
engines/hdb/lua-script.cpp
Normal file
2118
engines/hdb/lua-script.cpp
Normal file
File diff suppressed because it is too large
Load Diff
99
engines/hdb/lua-script.h
Normal file
99
engines/hdb/lua-script.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* 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 HDB_LUA_SCRIPT_H
|
||||
#define HDB_LUA_SCRIPT_H
|
||||
|
||||
struct lua_State;
|
||||
|
||||
namespace HDB {
|
||||
|
||||
struct Global {
|
||||
char global[32]; // name of global variable
|
||||
int valueOrString; // value = 0, string = 1
|
||||
double value; // value
|
||||
char string[32]; // string
|
||||
|
||||
Global() : valueOrString(0), value(0) {
|
||||
global[0] = 0;
|
||||
string[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class LuaScript {
|
||||
public:
|
||||
LuaScript();
|
||||
~LuaScript();
|
||||
|
||||
bool loadLua(const char *name);
|
||||
void saveGlobalNumber(const char *global, double value);
|
||||
void saveGlobalString(const char *global, const char *string);
|
||||
void loadGlobal(const char *global);
|
||||
void purgeGlobals();
|
||||
void save(Common::OutSaveFile *out);
|
||||
void loadSaveFile(Common::InSaveFile *in);
|
||||
|
||||
void init();
|
||||
bool initScript(Common::SeekableReadStream *stream, const char *scriptName, int32 length);
|
||||
|
||||
void pushInt(int value);
|
||||
void pushString(char *string);
|
||||
void pushFunction(char *func);
|
||||
void call(int args, int returns);
|
||||
bool callFunction(const char *name, int returns);
|
||||
void invokeLuaFunction(char *luaFunc, int x, int y, int value1, int value2);
|
||||
|
||||
bool executeMPC(Common::SeekableReadStream *stream, const char *name, const char *scriptName, int32 length);
|
||||
bool executeFile(const Common::String &filename);
|
||||
bool executeChunk(Common::String &chunk, const Common::String &chunkName) const;
|
||||
void checkParameters(const char *func, int params);
|
||||
|
||||
const char *getStringOffStack();
|
||||
|
||||
void setLuaGlobalValue(const char *name, int value);
|
||||
bool isValid() {
|
||||
return _systemInit;
|
||||
}
|
||||
|
||||
// Platform-specific Constants
|
||||
int _cameraXOff;
|
||||
int _cameraYOff;
|
||||
|
||||
private:
|
||||
lua_State *_state;
|
||||
int _pcallErrorhandlerRegistryIndex;
|
||||
|
||||
Common::SeekableReadStream* _globalLuaStream;
|
||||
int32 _globalLuaLength;
|
||||
bool _systemInit;
|
||||
|
||||
bool registerExtensions();
|
||||
void stripComments(char *chunk);
|
||||
void addPatches(Common::String &chunk, const char *scriptName);
|
||||
|
||||
Common::Array<Global *> _globals;
|
||||
};
|
||||
|
||||
void lua_printstack(lua_State *L);
|
||||
|
||||
}
|
||||
|
||||
#endif // !HDB_LUA_SCRIPT_H
|
||||
1235
engines/hdb/map.cpp
Normal file
1235
engines/hdb/map.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
engines/hdb/map.h
Normal file
184
engines/hdb/map.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/* 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 HDB_MAP_H
|
||||
#define HDB_MAP_H
|
||||
|
||||
namespace HDB {
|
||||
|
||||
enum {
|
||||
kMaxGratings = 250,
|
||||
kMaxForegrounds = 250
|
||||
};
|
||||
|
||||
struct MSMIcon {
|
||||
uint16 icon; // index into icon list
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
|
||||
char funcInit[32]; // Lua init function for this entity
|
||||
char funcAction[32];
|
||||
char funcUse[32];
|
||||
uint16 dir; // direction entity is facing
|
||||
uint16 level; // which floor level entity is on
|
||||
uint16 value1, value2;
|
||||
|
||||
MSMIcon(): icon(0), x(0), y(0), dir(0), level(0), value1(0), value2(0) {
|
||||
funcInit[0] = 0;
|
||||
funcAction[0] = 0;
|
||||
funcUse[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Foreground {
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 tile;
|
||||
|
||||
Foreground() : x(0), y(0), tile(0) {}
|
||||
};
|
||||
|
||||
struct SeeThroughTile {
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 tile;
|
||||
|
||||
SeeThroughTile() : x(0), y(0), tile(0) {}
|
||||
};
|
||||
|
||||
class Map {
|
||||
public:
|
||||
Map();
|
||||
~Map();
|
||||
|
||||
void save(Common::OutSaveFile *out);
|
||||
void loadSaveFile(Common::InSaveFile *in);
|
||||
void restartSystem();
|
||||
|
||||
int loadTiles();
|
||||
bool load(Common::SeekableReadStream *stream);
|
||||
bool loadMap(char *name);
|
||||
void draw();
|
||||
void drawEnts();
|
||||
void drawGratings();
|
||||
void drawForegrounds();
|
||||
|
||||
bool isLoaded() {
|
||||
return _mapLoaded;
|
||||
}
|
||||
|
||||
bool onScreen(int x, int y);
|
||||
int mapPixelWidth() {
|
||||
return _width * kTileWidth;
|
||||
}
|
||||
int mapPixelHeight() {
|
||||
return _height * kTileHeight;
|
||||
}
|
||||
|
||||
uint32 getMapBGTileFlags(int x, int y);
|
||||
uint32 getMapFGTileFlags(int x, int y);
|
||||
int16 getMapBGTileIndex(int x, int y);
|
||||
int16 getMapFGTileIndex(int x, int y);
|
||||
void setMapBGTileIndex(int x, int y, int index);
|
||||
void setMapFGTileIndex(int x, int y, int index);
|
||||
void addBGTileAnimation(int x, int y);
|
||||
void addFGTileAnimation(int x, int y);
|
||||
void removeBGTileAnimation(int x, int y);
|
||||
void removeFGTileAnimation(int x, int y);
|
||||
|
||||
void getMapXY(int *x, int *y);
|
||||
void setMapXY(int x, int y);
|
||||
void centerMapXY(int x, int y);
|
||||
bool checkEntOnScreen(AIEntity *);
|
||||
bool checkXYOnScreen(int x, int y);
|
||||
|
||||
// Check if one of the tiles in a range exists in the map on either layer
|
||||
bool checkOneTileExistInRange(int tileIndex, int count);
|
||||
|
||||
bool explosionExist(int x, int y) {
|
||||
return _mapExplosions[y * _width + x];
|
||||
}
|
||||
void setExplosion(int x, int y, int value) {
|
||||
_mapExplosions[y * _width + x] = value;
|
||||
}
|
||||
|
||||
bool boomBarrelExist(int x, int y) {
|
||||
return _mapExpBarrels[y * _width + x];
|
||||
}
|
||||
void setBoomBarrel(int x, int y, int value) {
|
||||
_mapExpBarrels[y * _width + x] = value;
|
||||
}
|
||||
|
||||
bool laserBeamExist(int x, int y) {
|
||||
return _mapLaserBeams[y * _width + x];
|
||||
}
|
||||
void setLaserBeam(int x, int y, int value) {
|
||||
_mapLaserBeams[y * _width + x] = value;
|
||||
}
|
||||
void clearLaserBeams() {
|
||||
uint size = _width * _height;
|
||||
memset(_mapLaserBeams, 0, size);
|
||||
}
|
||||
|
||||
// Platform-specific Constants;
|
||||
int _screenXTiles;
|
||||
int _screenYTiles;
|
||||
int _screenTileWidth;
|
||||
int _screenTileHeight;
|
||||
|
||||
uint16 _width, _height;
|
||||
int _mapX, _mapY; // Coordinates of Map
|
||||
int _mapTileX, _mapTileY; // Tile Coordinates of Map
|
||||
int _mapTileXOff, _mapTileYOff; // Tile Coordinates Offset (0-31)
|
||||
|
||||
Foreground _gratings[kMaxGratings], _foregrounds[kMaxForegrounds];
|
||||
int _numGratings, _numForegrounds;
|
||||
|
||||
int _animCycle; // Tile Animation Counter
|
||||
Common::Array<uint32> _listBGAnimSlow;
|
||||
Common::Array<uint32> _listBGAnimMedium;
|
||||
Common::Array<uint32> _listBGAnimFast;
|
||||
Common::Array<uint32> _listFGAnimSlow;
|
||||
Common::Array<uint32> _listFGAnimMedium;
|
||||
Common::Array<uint32> _listFGAnimFast;
|
||||
|
||||
private:
|
||||
char _name[32];
|
||||
uint32 _backgroundOffset;
|
||||
uint32 _foregroundOffset;
|
||||
uint16 _iconNum;
|
||||
uint32 _iconListOffset;
|
||||
uint16 _infoNum;
|
||||
uint32 _infoListOffset;
|
||||
|
||||
int16 *_background;
|
||||
int16 *_foreground;
|
||||
MSMIcon *_iconList;
|
||||
|
||||
byte *_mapExplosions;
|
||||
byte *_mapExpBarrels;
|
||||
byte *_mapLaserBeams;
|
||||
|
||||
bool _mapLoaded;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !HDB_MAP_H
|
||||
1774
engines/hdb/menu.cpp
Normal file
1774
engines/hdb/menu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
220
engines/hdb/menu.h
Normal file
220
engines/hdb/menu.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/* 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 HDB_MENU_H
|
||||
#define HDB_MENU_H
|
||||
|
||||
#include "common/events.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/sound.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
#define TITLE_DELAY1 2 // time to wait before OOH OOH
|
||||
#define TITLE_DELAY2 0.5 // time to spend doing OOH OOH
|
||||
#define TITLE_DELAY3 1 // time to wait before ending title
|
||||
|
||||
#define centerPic(x) (g_hdb->_screenWidth / 2 - x->_width / 2)
|
||||
|
||||
enum {
|
||||
kStarRedX = 70,
|
||||
kStarRedY = 20,
|
||||
kStarGreenX = 70,
|
||||
kStarGreenY = 100,
|
||||
kStarBlueX = 70,
|
||||
kStarBlueY = 180,
|
||||
|
||||
kOptionSPC = 16,
|
||||
kOptionLineSPC = 32,
|
||||
|
||||
kScreenFade = 512,
|
||||
kNebulaCount = 7,
|
||||
kMaxStars = 10
|
||||
};
|
||||
|
||||
enum OptionsScreens {
|
||||
kOptionsScreenMain = 1, // The main Options screen; Sound Settings and Modify Controls button
|
||||
kOptionsScreenModifyControls = 2 // The controls screen, for viewing and remapping controls (currently not implemented)
|
||||
};
|
||||
|
||||
enum MenuScreens {
|
||||
kMenuOptions = 0,
|
||||
kMenuLoadGame = 1,
|
||||
kMenuNewGame = 2
|
||||
};
|
||||
|
||||
struct Star {
|
||||
int x, y, speed, anim, delay;
|
||||
|
||||
Star() : x(0), y(0), speed(0), anim(0), delay(0) {}
|
||||
};
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
|
||||
Menu();
|
||||
~Menu();
|
||||
|
||||
bool init();
|
||||
|
||||
void readConfig();
|
||||
void writeConfig();
|
||||
|
||||
bool startTitle();
|
||||
void drawTitle();
|
||||
void startMenu();
|
||||
void changeToMenu(); // Changing from Intro to Menu
|
||||
void drawMenu();
|
||||
void freeMenu();
|
||||
|
||||
void processInput(int x, int y); // this is where the items are clicked!
|
||||
void controlsInput(int x, int y, int xit); // take mouse input and pass through to menu
|
||||
void controlsDraw();
|
||||
void drawNebula();
|
||||
void drawRocketAndSelections(); // draw the background stuff
|
||||
void drawSlider(int x, int y, int offset);
|
||||
void drawToggle(int x, int y, bool flag);
|
||||
void drawWarpScreen();
|
||||
void saveSong(SoundType song) {
|
||||
_resumeSong = song;
|
||||
}
|
||||
|
||||
void fillSavegameSlots();
|
||||
|
||||
void setMenuKey(int status) {
|
||||
_menuKey = status;
|
||||
}
|
||||
int getMenuKey() {
|
||||
return _menuKey;
|
||||
}
|
||||
|
||||
// Platform-specific Constants
|
||||
int _menuX, _menuY;
|
||||
int _menuItemWidth;
|
||||
int _menuItemHeight;
|
||||
int _mResumeY;
|
||||
int _mQuitY;
|
||||
int _mOptionsY;
|
||||
int _mLoadY;
|
||||
int _mControlsY;
|
||||
int _menuExitXLeft;
|
||||
int _menuExitY;
|
||||
int _menuExitYTop;
|
||||
int _menuVortSaveY;
|
||||
int _menuVortSaveX;
|
||||
int _mRocketX;
|
||||
int _mRocketY;
|
||||
int _mRocketYBottom;
|
||||
int _mRocketEXHX;
|
||||
int _mRocketEXHX2;
|
||||
int _mTitleY;
|
||||
int _oohOhhX;
|
||||
int _oohOhhY;
|
||||
int _newGameX;
|
||||
int _newGameX2;
|
||||
int _modePuzzleY;
|
||||
int _modeActionY;
|
||||
int _optionsX;
|
||||
int _optionsY;
|
||||
int _vortSaveX;
|
||||
int _vortSaveTextX;
|
||||
int _vortSaveY;
|
||||
int _saveSlotX;
|
||||
int _saveSlotY;
|
||||
int _quitX;
|
||||
int _quitY;
|
||||
int _quitYesX1;
|
||||
int _quitYesX2;
|
||||
int _quitYesY1;
|
||||
int _quitYesY2;
|
||||
int _quitNoX1;
|
||||
int _quitNoX2;
|
||||
int _quitNoY1;
|
||||
int _quitNoY2;
|
||||
int _controlX;
|
||||
int _controlY;
|
||||
int _controlUpX;
|
||||
int _controlUpY;
|
||||
int _controlDownX;
|
||||
int _controlDownY;
|
||||
int _controlLeftX;
|
||||
int _controlLeftY;
|
||||
int _controlRightX;
|
||||
int _controlRightY;
|
||||
int _controlUseX;
|
||||
int _controlUseY;
|
||||
int _controlWidth;
|
||||
int _controlHeight;
|
||||
int _assignX;
|
||||
int _assignY;
|
||||
int _backoutX;
|
||||
int _backoutY;
|
||||
int _warpBackoutX;
|
||||
int _warpBackoutY;
|
||||
int _warpX;
|
||||
int _warpY;
|
||||
|
||||
Save _saveGames[kNumSaveSlots + 1];
|
||||
|
||||
int _starWarp;
|
||||
int _titleCycle;
|
||||
uint32 _titleDelay;
|
||||
bool _titleActive;
|
||||
SoundType _resumeSong; // the song that was playing before entering the Options screen
|
||||
|
||||
Picture *_oohOohGfx;
|
||||
Picture *_titleScreen, *_titleLogo, *_hdbLogoScreen, *_menuBackoutGfx, *_controlButtonGfx, *_controlsGfx, *_menuBackspaceGfx;
|
||||
|
||||
int _rocketY, _rocketYVel, _rocketEx; // Rocket Vars
|
||||
Picture *_rocketEx1, *_rocketEx2, *_rocketMain, *_rocketSecond;
|
||||
int _rocketX;
|
||||
|
||||
int _nebulaX, _nebulaY, _nebulaYVel, _nebulaWhich;
|
||||
Picture *_nebulaGfx[kNebulaCount];
|
||||
|
||||
Picture *_newGfx, *_loadGfx, *_optionsGfx, *_quitGfx, *_resumeGfx, *_slotGfx;
|
||||
Picture *_modePuzzleGfx, *_modeActionGfx, *_modeLoadGfx, *_modeSaveGfx, *_quitScreen;
|
||||
Tile *_vortexian[3];
|
||||
Picture *_star[3], *_warpGfx;
|
||||
uint32 _quitTimer;
|
||||
Picture *_starRedGfx[2], *_starGreenGfx[2], *_starBlueGfx[2], *_versionGfx;
|
||||
Picture *_screenshots1gfx, *_screenshots1agfx, *_screenshots2gfx, *_demoPlaqueGfx, *_handangoGfx;
|
||||
|
||||
bool _menuActive, _optionsScrolling, _newgameActive, _sayHDB, _warpActive, _gamefilesActive, _optionsActive, _quitActive;
|
||||
int _clickDelay, _saveSlot, _optionsScreenId, _quitCounter, _warpMapId;
|
||||
int _optionsScrollX, _optionsXV, _oBannerY;
|
||||
int _nextScreen;
|
||||
|
||||
Picture *_contArrowUp, *_contArrowDown, *_contArrowLeft, *_contArrowRight, *_contAssign, *_warpPlaque;
|
||||
|
||||
Picture *_sliderLeft, *_sliderMid, *_sliderRight, *_sliderKnob;
|
||||
Picture *_gCheckEmpty, *_gCheckOn, *_gCheckOff, *_gCheckLeft, *_gCheckRight;
|
||||
|
||||
SoundType _introSong, _titleSong;
|
||||
|
||||
Star _fStars[kMaxStars];
|
||||
|
||||
int _menuKey;
|
||||
};
|
||||
|
||||
} // End of Namespace
|
||||
|
||||
#endif // !HDB_SOUND_H
|
||||
292
engines/hdb/metaengine.cpp
Normal file
292
engines/hdb/metaengine.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/* 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 "base/plugins.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymapper.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "hdb/hdb.h"
|
||||
#include "hdb/input.h"
|
||||
#include "hdb/detection.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_CHEATMODE,
|
||||
{
|
||||
_s("Enable cheat mode"),
|
||||
_s("Debug info and level selection becomes available"),
|
||||
"hypercheat",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
const char *HDBGame::getGameId() const { return _gameDescription->gameId; }
|
||||
Common::Platform HDBGame::getPlatform() const { return _gameDescription->platform; }
|
||||
|
||||
const char *HDBGame::getGameFile() const {
|
||||
return _gameDescription->filesDescriptions[0].fileName;
|
||||
}
|
||||
|
||||
uint32 HDBGame::getGameFlags() const {
|
||||
return _gameDescription->flags;
|
||||
}
|
||||
|
||||
bool HDBGame::isDemo() const {
|
||||
return (getGameFlags() & ADGF_DEMO);
|
||||
}
|
||||
|
||||
bool HDBGame::isPPC() const {
|
||||
return (getPlatform() == Common::kPlatformPocketPC);
|
||||
}
|
||||
|
||||
bool HDBGame::isHandango() const {
|
||||
return (getGameFlags() & GF_HANDANGO);
|
||||
}
|
||||
|
||||
} // End of namespace HDB
|
||||
|
||||
class HDBMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "hdb";
|
||||
}
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return HDB::optionsList;
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
int getMaximumSaveSlot() const override;
|
||||
|
||||
bool removeSaveState(const char *target, int slot) const override;
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
|
||||
};
|
||||
|
||||
bool HDBMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSimpleSavesNames) ||
|
||||
(f == kSavesSupportPlayTime);
|
||||
}
|
||||
|
||||
bool HDB::HDBGame::hasFeature(Engine::EngineFeature f) const {
|
||||
return (f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
bool HDBMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
return g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
int HDBMetaEngine::getMaximumSaveSlot() const { return 99; }
|
||||
|
||||
SaveStateList HDBMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".###";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
SaveStateList saveList;
|
||||
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||
// Obtain the last 2 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(file->c_str() + file->size() - 2);
|
||||
|
||||
if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
|
||||
Common::ScopedPtr<Common::InSaveFile> in(saveFileMan->openForLoading(*file));
|
||||
if (in) {
|
||||
SaveStateDescriptor desc;
|
||||
char mapName[32];
|
||||
Graphics::Surface *thumbnail;
|
||||
|
||||
if (!Graphics::loadThumbnail(*in, thumbnail)) {
|
||||
warning("Error loading thumbnail for %s", file->c_str());
|
||||
}
|
||||
desc.setThumbnail(thumbnail);
|
||||
|
||||
uint32 timeSeconds = in->readUint32LE();
|
||||
in->read(mapName, 32);
|
||||
|
||||
debug(1, "mapName: %s playtime: %d", mapName, timeSeconds);
|
||||
|
||||
desc.setSaveSlot(slotNum);
|
||||
desc.setPlayTime(timeSeconds * 1000);
|
||||
|
||||
if (slotNum < 8)
|
||||
desc.setDescription(Common::String::format("Auto: %s", mapName));
|
||||
else
|
||||
desc.setDescription(mapName);
|
||||
|
||||
saveList.push_back(desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort saves based on slot number.
|
||||
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
|
||||
return saveList;
|
||||
}
|
||||
|
||||
SaveStateDescriptor HDBMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::ScopedPtr<Common::InSaveFile> in(g_system->getSavefileManager()->openForLoading(Common::String::format("%s.%03d", target, slot)));
|
||||
|
||||
if (in) {
|
||||
SaveStateDescriptor desc;
|
||||
char mapName[32];
|
||||
Graphics::Surface *thumbnail;
|
||||
|
||||
if (!Graphics::loadThumbnail(*in, thumbnail)) {
|
||||
warning("Error loading thumbnail");
|
||||
}
|
||||
desc.setThumbnail(thumbnail);
|
||||
|
||||
uint32 timeSeconds = in->readUint32LE();
|
||||
in->read(mapName, 32);
|
||||
|
||||
desc.setSaveSlot(slot);
|
||||
desc.setPlayTime(timeSeconds * 1000);
|
||||
desc.setDescription(mapName);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
Common::KeymapArray HDBMetaEngine::initKeymaps(const char *target) const {
|
||||
using namespace Common;
|
||||
using namespace HDB;
|
||||
|
||||
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "hdb", "Hyperspace Delivery Boy!");
|
||||
|
||||
Action *act;
|
||||
|
||||
act = new Action(kStandardActionLeftClick, _("Left click"));
|
||||
act->setLeftClickEvent();
|
||||
act->addDefaultInputMapping("MOUSE_LEFT");
|
||||
act->addDefaultInputMapping("JOY_A");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionMoveUp, _("Move up"));
|
||||
act->setCustomEngineActionEvent(kHDBActionUp);
|
||||
act->addDefaultInputMapping("UP");
|
||||
act->addDefaultInputMapping("JOY_UP");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionMoveDown, _("Move down"));
|
||||
act->setCustomEngineActionEvent(kHDBActionDown);
|
||||
act->addDefaultInputMapping("DOWN");
|
||||
act->addDefaultInputMapping("JOY_DOWN");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionMoveLeft, _("Move left"));
|
||||
act->setCustomEngineActionEvent(kHDBActionLeft);
|
||||
act->addDefaultInputMapping("LEFT");
|
||||
act->addDefaultInputMapping("JOY_LEFT");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionMoveRight, _("Move right"));
|
||||
act->setCustomEngineActionEvent(kHDBActionRight);
|
||||
act->addDefaultInputMapping("RIGHT");
|
||||
act->addDefaultInputMapping("JOY_RIGHT");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("USE", _("Use"));
|
||||
act->setCustomEngineActionEvent(kHDBActionUse);
|
||||
act->addDefaultInputMapping("RETURN");
|
||||
act->addDefaultInputMapping("MOUSE_RIGHT");
|
||||
act->addDefaultInputMapping("JOY_B");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("CLEAR", _("Clear waypoints"));
|
||||
act->setCustomEngineActionEvent(kHDBActionClearWaypoints);
|
||||
act->addDefaultInputMapping("MOUSE_MIDDLE");
|
||||
act->addDefaultInputMapping("JOY_X");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
#if 0
|
||||
act = new Action("INV", _("Inventory"));
|
||||
act->setCustomEngineActionEvent(kHDBActionInventory);
|
||||
act->addDefaultInputMapping("SPACE");
|
||||
act->addDefaultInputMapping("JOY_Y");
|
||||
engineKeyMap->addAction(act);
|
||||
#endif
|
||||
|
||||
act = new Action(kStandardActionPause, _("Pause"));
|
||||
act->setCustomEngineActionEvent(kHDBActionPause);
|
||||
act->addDefaultInputMapping("p");
|
||||
act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action(kStandardActionOpenMainMenu, _("Menu"));
|
||||
act->setCustomEngineActionEvent(kHDBActionMenu);
|
||||
act->addDefaultInputMapping("ESCAPE");
|
||||
act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("DEBUG", _("Debug"));
|
||||
act->setCustomEngineActionEvent(kHDBActionDebug);
|
||||
act->addDefaultInputMapping("F1");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
act = new Action("QUIT", _("Quit"));
|
||||
act->setCustomEngineActionEvent(kHDBActionQuit);
|
||||
act->addDefaultInputMapping("F10");
|
||||
engineKeyMap->addAction(act);
|
||||
|
||||
return Keymap::arrayOf(engineKeyMap);
|
||||
}
|
||||
|
||||
Common::Error HDBMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
|
||||
*engine = new HDB::HDBGame(syst, desc);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(HDB)
|
||||
REGISTER_PLUGIN_DYNAMIC(HDB, PLUGIN_TYPE_ENGINE, HDBMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(HDB, PLUGIN_TYPE_ENGINE, HDBMetaEngine);
|
||||
#endif
|
||||
37
engines/hdb/module.mk
Normal file
37
engines/hdb/module.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
MODULE := engines/hdb
|
||||
|
||||
MODULE_OBJS := \
|
||||
ai-bots.o \
|
||||
ai-cinematic.o \
|
||||
ai-funcs.o \
|
||||
ai-init.o \
|
||||
ai-inventory.o \
|
||||
ai-lists.o \
|
||||
ai-player.o \
|
||||
ai-use.o \
|
||||
ai-waypoint.o \
|
||||
file-manager.o \
|
||||
gfx.o \
|
||||
hdb.o \
|
||||
input.o \
|
||||
lua-script.o \
|
||||
map.o \
|
||||
menu.o \
|
||||
metaengine.o \
|
||||
sound.o \
|
||||
saveload.o \
|
||||
window.o
|
||||
|
||||
MODULE_DIRS += \
|
||||
engines/hdb
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_HDB), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
# Detection objects
|
||||
DETECT_OBJS += $(MODULE)/detection.o
|
||||
2241
engines/hdb/mpc.h
Normal file
2241
engines/hdb/mpc.h
Normal file
File diff suppressed because it is too large
Load Diff
389
engines/hdb/saveload.cpp
Normal file
389
engines/hdb/saveload.cpp
Normal file
@@ -0,0 +1,389 @@
|
||||
/* 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 "graphics/thumbnail.h"
|
||||
|
||||
#include "hdb/hdb.h"
|
||||
#include "hdb/ai.h"
|
||||
#include "hdb/gfx.h"
|
||||
#include "hdb/lua-script.h"
|
||||
#include "hdb/map.h"
|
||||
#include "hdb/sound.h"
|
||||
#include "hdb/window.h"
|
||||
|
||||
namespace HDB {
|
||||
|
||||
bool HDBGame::canSaveGameStateCurrently(Common::U32String *msg) {
|
||||
return (_gameState == GAME_PLAY && !_ai->cinematicsActive());
|
||||
}
|
||||
|
||||
Common::Error HDBGame::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
||||
|
||||
// If no map is loaded, don't try to save
|
||||
if (!g_hdb->_map->isLoaded())
|
||||
return Common::kCreatingFileFailed;
|
||||
|
||||
// If it is autosave, push down all saves
|
||||
if (slot == 0) {
|
||||
Common::String nameFrom;
|
||||
Common::String nameTo;
|
||||
for (int i = kNumSaveSlots - 2; i >= 0; i--) {
|
||||
nameFrom = genSaveFileName(i, false);
|
||||
nameTo = genSaveFileName(i + 1, false);
|
||||
_saveFileMan->renameSavefile(nameFrom, nameTo);
|
||||
|
||||
nameFrom = genSaveFileName(i, true);
|
||||
nameTo = genSaveFileName(i + 1, true);
|
||||
_saveFileMan->renameSavefile(nameFrom, nameTo);
|
||||
}
|
||||
}
|
||||
|
||||
Common::OutSaveFile *out;
|
||||
|
||||
Common::String saveFileName = genSaveFileName(slot, false);
|
||||
if (!(out = _saveFileMan->openForSaving(saveFileName)))
|
||||
error("Unable to open save file");
|
||||
|
||||
Graphics::saveThumbnail(*out);
|
||||
|
||||
_saveHeader.fileSlot = 0;
|
||||
Common::strlcpy(_saveHeader.saveID, saveFileName.c_str(), sizeof(_saveHeader.saveID));
|
||||
_saveHeader.seconds = _timeSeconds + (_timePlayed / 1000);
|
||||
Common::strlcpy(_saveHeader.mapName, _inMapName, sizeof(_saveHeader.mapName));
|
||||
|
||||
// Actual Save Data
|
||||
saveGame(out);
|
||||
_lua->save(out);
|
||||
|
||||
out->finalize();
|
||||
if (out->err())
|
||||
warning("Can't write file '%s'. (Disk full?)", saveFileName.c_str());
|
||||
|
||||
delete out;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool HDBGame::canLoadGameStateCurrently(Common::U32String *msg) {
|
||||
return _gameState == GAME_PLAY;
|
||||
}
|
||||
|
||||
Common::Error HDBGame::loadGameState(int slot) {
|
||||
Common::InSaveFile *in;
|
||||
|
||||
Common::String saveFileName = genSaveFileName(slot, false);
|
||||
if (!(in = _saveFileMan->openForLoading(saveFileName))) {
|
||||
warning("missing savegame file %s", saveFileName.c_str());
|
||||
if (g_hdb->_map->isLoaded())
|
||||
g_hdb->setGameState(GAME_PLAY);
|
||||
return Common::kReadingFailed;
|
||||
}
|
||||
|
||||
_window->closeAll();
|
||||
|
||||
Graphics::skipThumbnail(*in);
|
||||
|
||||
// Actual Save Data
|
||||
loadGame(in);
|
||||
|
||||
_lua->loadLua(_currentLuaName); // load the Lua code FIRST! (if no file, it's ok)
|
||||
|
||||
_lua->loadSaveFile(in);
|
||||
|
||||
delete in;
|
||||
|
||||
// center the player on the screen
|
||||
int x, y;
|
||||
_ai->getPlayerXY(&x, &y);
|
||||
_map->centerMapXY(x + 16, y + 16);
|
||||
|
||||
if (!_ai->cinematicsActive())
|
||||
_gfx->turnOffFade();
|
||||
|
||||
debug(7, "Action List Info:");
|
||||
for (int k = 0; k < 20; k++) {
|
||||
debug(7, "Action %d: entityName: %s", k, _ai->_actions[k].entityName);
|
||||
debug(7, "Action %d: x1: %d, y1: %d", k, _ai->_actions[k].x1, _ai->_actions[k].y1);
|
||||
debug(7, "Action %d: x2: %d, y2: %d", k, _ai->_actions[k].x2, _ai->_actions[k].y2);
|
||||
debug(7, "Action %d: luaFuncInit: %s, luaFuncUse: %s", k, _ai->_actions[k].luaFuncInit, _ai->_actions[k].luaFuncUse);
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void HDBGame::saveGame(Common::OutSaveFile *out) {
|
||||
debug(1, "HDBGame::saveGame: start at %u", (uint32)out->pos());
|
||||
|
||||
// Save Map Name and Time
|
||||
out->writeUint32LE(_saveHeader.seconds);
|
||||
out->write(_inMapName, 32);
|
||||
|
||||
debug(1, "HDBGame::saveGame: map at %u", (uint32)out->pos());
|
||||
// Save Map Object Data
|
||||
_map->save(out);
|
||||
|
||||
// Save Window Object Data
|
||||
debug(1, "HDBGame::saveGame: window at %u", (uint32)out->pos());
|
||||
_window->save(out);
|
||||
|
||||
// Save Gfx Object Data
|
||||
debug(1, "HDBGame::saveGame: gfx at %u", (uint32)out->pos());
|
||||
_gfx->save(out);
|
||||
|
||||
// Save Sound Object Data
|
||||
debug(1, "HDBGame::saveGame: sound at %u", (uint32)out->pos());
|
||||
_sound->save(out);
|
||||
|
||||
// Save Game Object Data
|
||||
debug(1, "HDBGame::saveGame: game object at %u", (uint32)out->pos());
|
||||
save(out);
|
||||
|
||||
// Save AI Object Data
|
||||
debug(1, "HDBGame::saveGame: ai at %u", (uint32)out->pos());
|
||||
_ai->save(out);
|
||||
|
||||
debug(1, "HDBGame::saveGame: end at %u", (uint32)out->pos());
|
||||
}
|
||||
|
||||
void HDBGame::loadGame(Common::InSaveFile *in) {
|
||||
debug(1, "HDBGame::loadGame: start at %u", (uint32)in->pos());
|
||||
|
||||
// Load Map Name and Time
|
||||
_timeSeconds = in->readUint32LE();
|
||||
_timePlayed = 0;
|
||||
in->read(_inMapName, 32);
|
||||
|
||||
g_hdb->_sound->stopMusic();
|
||||
_saveHeader.seconds = _timeSeconds;
|
||||
Common::strlcpy(_saveHeader.mapName, _inMapName, sizeof(_saveHeader.mapName));
|
||||
|
||||
// Load Map Object Data
|
||||
debug(1, "HDBGame::loadGame: map at %u", (uint32)in->pos());
|
||||
_map->loadSaveFile(in);
|
||||
|
||||
// Load Window Object Data
|
||||
debug(1, "HDBGame::loadGame: window at %u", (uint32)in->pos());
|
||||
_window->loadSaveFile(in);
|
||||
|
||||
// Load Gfx Object Data
|
||||
debug(1, "HDBGame::loadGame: gfx at %u", (uint32)in->pos());
|
||||
_gfx->loadSaveFile(in);
|
||||
|
||||
// Load Sound Object Data
|
||||
debug(1, "HDBGame::loadGame: sound at %u", (uint32)in->pos());
|
||||
_sound->loadSaveFile(in);
|
||||
|
||||
// Load Game Object Data
|
||||
debug(1, "HDBGame::loadGame: game object at %u", (uint32)in->pos());
|
||||
loadSaveFile(in);
|
||||
|
||||
// Load AI Object Data
|
||||
debug(1, "HDBGame::loadGame: ai at %u", (uint32)in->pos());
|
||||
_ai->loadSaveFile(in);
|
||||
|
||||
debug(1, "HDBGame::loadGame: end at %u", (uint32)in->pos());
|
||||
|
||||
_gfx->turnOffFade();
|
||||
}
|
||||
|
||||
void HDBGame::save(Common::OutSaveFile *out) {
|
||||
out->write(_currentMapname, 64);
|
||||
out->write(_lastMapname, 64);
|
||||
out->write(_currentLuaName, 64);
|
||||
out->writeSint32LE(_actionMode);
|
||||
out->writeByte(_changeLevel);
|
||||
out->write(_changeMapname, 64);
|
||||
out->write(_inMapName, 32);
|
||||
}
|
||||
|
||||
void HDBGame::loadSaveFile(Common::InSaveFile *in) {
|
||||
in->read(_currentMapname, 64);
|
||||
|
||||
debug(0, "Loading map %s", _currentMapname);
|
||||
|
||||
in->read(_lastMapname, 64);
|
||||
in->read(_currentLuaName, 64);
|
||||
_actionMode = in->readSint32LE();
|
||||
_changeLevel = in->readByte();
|
||||
in->read(_changeMapname, 64);
|
||||
in->read(_inMapName, 32);
|
||||
}
|
||||
|
||||
void AIEntity::save(Common::OutSaveFile *out) {
|
||||
char funcString[32];
|
||||
const char *lookUp;
|
||||
|
||||
|
||||
// Write out 32-char names for the function ptrs we have in the entity struct
|
||||
lookUp = g_hdb->_ai->funcLookUp(aiAction);
|
||||
memset(&funcString, 0, 32);
|
||||
if (!lookUp && aiAction)
|
||||
error("AIEntity::save: No matching ACTION function for func-string for %s entity", AIType2Str(type));
|
||||
if (lookUp)
|
||||
strncpy(funcString, lookUp, 31);
|
||||
out->write(funcString, 32);
|
||||
|
||||
lookUp = g_hdb->_ai->funcLookUp(aiUse);
|
||||
memset(&funcString, 0, 32);
|
||||
if (!lookUp && aiUse)
|
||||
error("AIEntity::save: No matching USE function for func-string for %s entity", AIType2Str(type));
|
||||
if (lookUp)
|
||||
strncpy(funcString, lookUp, 31);
|
||||
out->write(funcString, 32);
|
||||
|
||||
lookUp = g_hdb->_ai->funcLookUp(aiInit);
|
||||
memset(&funcString, 0, 32);
|
||||
if (!lookUp && aiInit)
|
||||
error("AIEntity::save: No matching INIT function for func-string for %s entity", AIType2Str(type));
|
||||
if (lookUp)
|
||||
strncpy(funcString, lookUp, 31);
|
||||
out->write(funcString, 32);
|
||||
|
||||
lookUp = g_hdb->_ai->funcLookUp(aiInit2);
|
||||
memset(&funcString, 0, 32);
|
||||
if (!lookUp && aiInit2)
|
||||
error("AIEntity::save: No matching INIT2 function for func-string for %s entity", AIType2Str(type));
|
||||
if (lookUp)
|
||||
strncpy(funcString, lookUp, 31);
|
||||
out->write(funcString, 32);
|
||||
|
||||
lookUp = g_hdb->_ai->funcLookUp(aiDraw);
|
||||
memset(&funcString, 0, 32);
|
||||
if (!lookUp && aiDraw)
|
||||
error("AIEntity::save: No matching DRAW function for func-string for %s entity", AIType2Str(type));
|
||||
if (lookUp)
|
||||
strncpy(funcString, lookUp, 31);
|
||||
out->write(funcString, 32);
|
||||
|
||||
// Save AIEntity
|
||||
out->writeSint32LE((int)type);
|
||||
out->writeSint32LE((int)state);
|
||||
out->writeSint32LE((int)dir);
|
||||
out->write(luaFuncInit, 32);
|
||||
out->write(luaFuncAction, 32);
|
||||
out->write(luaFuncUse, 32);
|
||||
out->writeUint16LE(level);
|
||||
out->writeUint16LE(value1);
|
||||
out->writeUint16LE(value2);
|
||||
out->writeSint32LE((int)dir2);
|
||||
out->writeUint16LE(x);
|
||||
out->writeUint16LE(y);
|
||||
out->writeSint16LE(drawXOff);
|
||||
out->writeSint16LE(drawYOff);
|
||||
out->writeUint16LE(onScreen);
|
||||
out->writeUint16LE(moveSpeed);
|
||||
out->writeSint16LE(xVel);
|
||||
out->writeSint16LE(yVel);
|
||||
out->writeUint16LE(tileX);
|
||||
out->writeUint16LE(tileY);
|
||||
out->writeUint16LE(goalX);
|
||||
out->writeUint16LE(goalY);
|
||||
out->writeUint16LE(touchpX);
|
||||
out->writeUint16LE(touchpY);
|
||||
out->writeUint16LE(touchpTile);
|
||||
out->writeUint16LE(touchpWait);
|
||||
out->writeUint16LE(stunnedWait);
|
||||
out->writeSint16LE(sequence);
|
||||
out->write(entityName, 32);
|
||||
out->write(printedName, 32);
|
||||
out->writeUint16LE(animFrame);
|
||||
out->writeUint16LE(animDelay);
|
||||
out->writeUint16LE(animCycle);
|
||||
}
|
||||
|
||||
void AIEntity::load(Common::InSaveFile *in) {
|
||||
char funcString[32];
|
||||
FuncPtr init, init2, use, action, drawf;
|
||||
|
||||
action = init = init2 = use = drawf = nullptr;
|
||||
|
||||
// Read 32-char names for the function ptrs we have in entity struct
|
||||
in->read(funcString, 32);
|
||||
if (funcString[0])
|
||||
action = g_hdb->_ai->funcLookUp(funcString);
|
||||
|
||||
in->read(funcString, 32);
|
||||
if (funcString[0])
|
||||
use = g_hdb->_ai->funcLookUp(funcString);
|
||||
|
||||
in->read(funcString, 32);
|
||||
if (funcString[0])
|
||||
init = g_hdb->_ai->funcLookUp(funcString);
|
||||
|
||||
in->read(funcString, 32);
|
||||
if (funcString[0])
|
||||
init2 = g_hdb->_ai->funcLookUp(funcString);
|
||||
|
||||
in->read(funcString, 32);
|
||||
if (funcString[0])
|
||||
drawf = g_hdb->_ai->funcLookUp(funcString);
|
||||
|
||||
// Load AIEntity
|
||||
type = (AIType)in->readSint32LE();
|
||||
state = (AIState)in->readSint32LE();
|
||||
dir = (AIDir)in->readSint32LE();
|
||||
in->read(luaFuncInit, 32);
|
||||
in->read(luaFuncAction, 32);
|
||||
in->read(luaFuncUse, 32);
|
||||
level = in->readUint16LE();
|
||||
value1 = in->readUint16LE();
|
||||
value2 = in->readUint16LE();
|
||||
dir2 = (AIDir)in->readSint32LE();
|
||||
x = in->readUint16LE();
|
||||
y = in->readUint16LE();
|
||||
drawXOff = in->readSint16LE();
|
||||
drawYOff = in->readSint16LE();
|
||||
onScreen = in->readUint16LE();
|
||||
moveSpeed = in->readUint16LE();
|
||||
xVel = in->readSint16LE();
|
||||
yVel = in->readSint16LE();
|
||||
tileX = in->readUint16LE();
|
||||
tileY = in->readUint16LE();
|
||||
goalX = in->readUint16LE();
|
||||
goalY = in->readUint16LE();
|
||||
touchpX = in->readUint16LE();
|
||||
touchpY = in->readUint16LE();
|
||||
touchpTile = in->readUint16LE();
|
||||
touchpWait = in->readUint16LE();
|
||||
stunnedWait = in->readUint16LE();
|
||||
sequence = in->readSint16LE();
|
||||
in->read(entityName, 32);
|
||||
in->read(printedName, 32);
|
||||
animFrame = in->readUint16LE();
|
||||
animDelay = in->readUint16LE();
|
||||
animCycle = in->readUint16LE();
|
||||
|
||||
aiAction = action;
|
||||
aiInit = init;
|
||||
aiInit2 = init2;
|
||||
aiUse = use;
|
||||
aiDraw = drawf;
|
||||
}
|
||||
|
||||
Common::String HDBGame::genSaveFileName(uint slot, bool lua) {
|
||||
if (!lua)
|
||||
return Common::String::format("%s.%03d", _targetName.c_str(), slot);
|
||||
|
||||
return Common::String::format("%s.l.%03d", _targetName.c_str(), slot);
|
||||
}
|
||||
|
||||
|
||||
} // End of Namespace
|
||||
1929
engines/hdb/sound.cpp
Normal file
1929
engines/hdb/sound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1576
engines/hdb/sound.h
Normal file
1576
engines/hdb/sound.h
Normal file
File diff suppressed because it is too large
Load Diff
1939
engines/hdb/window.cpp
Normal file
1939
engines/hdb/window.cpp
Normal file
File diff suppressed because it is too large
Load Diff
351
engines/hdb/window.h
Normal file
351
engines/hdb/window.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/* 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 HDB_WINDOW_H
|
||||
#define HDB_WINDOW_H
|
||||
|
||||
namespace HDB {
|
||||
|
||||
enum {
|
||||
kMaxMsgQueue = 10,
|
||||
kPanicZoneFaceY = 5,
|
||||
kNumCrazy = 37
|
||||
};
|
||||
|
||||
enum PZValue {
|
||||
PANICZONE_TIMER,
|
||||
PANICZONE_START,
|
||||
PANICZONE_TITLESTOP,
|
||||
PANICZONE_BLASTOFF,
|
||||
PANICZONE_COUNTDOWN,
|
||||
|
||||
PANICZONE_END
|
||||
};
|
||||
|
||||
struct DialogInfo {
|
||||
char title[64]; // TITLE string
|
||||
int tileIndex; // this is for a character picture
|
||||
char string[160]; // actual text in the dialog
|
||||
|
||||
bool active; // is it drawing or not?
|
||||
int x, y; // where to draw dialog
|
||||
int width, height; // size of the dialog itself
|
||||
int titleWidth;
|
||||
Picture *gfx; // character tile (picture)
|
||||
int more; // whether we want to draw the MORE icon or not
|
||||
int el, er, et, eb; // saves the text edges
|
||||
char luaMore[64]; // the name of the function to call after clicking the MORE button
|
||||
|
||||
DialogInfo() : tileIndex(0), active(false), x(0), y(0),
|
||||
width(0), height(0), titleWidth(0), gfx(nullptr), more(0), el(0), er(0), et(0),
|
||||
eb(0) {
|
||||
title[0] = 0;
|
||||
string[0] = 0;
|
||||
luaMore[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct DialogChoiceInfo {
|
||||
char title[64]; // TITLE string
|
||||
char text[160]; // actual text in the dialog
|
||||
char func[64]; // function to call with result
|
||||
|
||||
bool active; // is it drawing or not?
|
||||
int x, y; // where to draw dialog
|
||||
int width, height; // size of the dialog itself
|
||||
int textHeight; // height of everything above choices
|
||||
int titleWidth;
|
||||
int el, er, et, eb; // saves the text edges
|
||||
uint32 timeout; // timeout value!
|
||||
|
||||
int selection; // which choice we've made
|
||||
int numChoices; // how many choices possible
|
||||
char choices[10][64]; // ptrs to choice text
|
||||
|
||||
DialogChoiceInfo() : active(false), x(0), y(0),
|
||||
width(0), height(0), textHeight(0), titleWidth(0), el(0), er(0), et(0),
|
||||
eb(0), timeout(0), selection(0), numChoices(0) {
|
||||
title[0] = 0;
|
||||
text[0] = 0;
|
||||
func[0] = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
choices[i][0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct MessageInfo {
|
||||
bool active;
|
||||
char title[128];
|
||||
int timer;
|
||||
int x, y;
|
||||
int width, height;
|
||||
|
||||
MessageInfo() : active(false), timer(0), x(0), y(0), width(0), height(0) {
|
||||
title[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct InvWinInfo {
|
||||
int x, y;
|
||||
int width, height;
|
||||
int selection;
|
||||
bool active;
|
||||
|
||||
InvWinInfo() : x(0), y(0), width(0), height(0), selection(0), active(false) {}
|
||||
};
|
||||
|
||||
struct DlvsInfo {
|
||||
int x, y;
|
||||
int width, height;
|
||||
bool active;
|
||||
int selected;
|
||||
bool animate;
|
||||
uint32 delay1, delay2, delay3;
|
||||
bool go1, go2, go3;
|
||||
|
||||
DlvsInfo() : x(0), y(0), width(0), height(0), active(false), selected(0),
|
||||
animate(false), delay1(0), delay2(0), delay3(0), go1(false), go2(false), go3(false) {}
|
||||
};
|
||||
|
||||
struct PanicZone {
|
||||
bool active;
|
||||
int sequence;
|
||||
int timer;
|
||||
int x1, y1;
|
||||
int x2, y2;
|
||||
int xv, yv; // for both
|
||||
int numberTime;
|
||||
int numberTimeMaster;
|
||||
int numberValue;
|
||||
Picture *gfxPanic, *gfxZone;
|
||||
Picture *gfxFace[2];
|
||||
Picture *gfxNumber[10];
|
||||
|
||||
PanicZone() : active(false), sequence(0), timer(0), x1(0), y1(0), x2(0), y2(0), xv(0), yv(0),
|
||||
numberTime(0), numberTimeMaster(0), numberValue(0), gfxPanic(nullptr), gfxZone(nullptr) {
|
||||
memset(&gfxFace, 0, sizeof(gfxFace));
|
||||
memset(&gfxNumber, 0, sizeof(gfxNumber));
|
||||
}
|
||||
};
|
||||
|
||||
struct TryAgainInfo {
|
||||
double y1, y2;
|
||||
double yv1, yv2;
|
||||
double yv1v, yv2v;
|
||||
double x1, x2;
|
||||
|
||||
TryAgainInfo() : y1(0), y2(0), yv1(0), yv2(0), yv1v(0), yv2v(0), x1(0), x2(0) {}
|
||||
};
|
||||
|
||||
struct TOut {
|
||||
char text[128];
|
||||
int x, y;
|
||||
uint32 timer;
|
||||
|
||||
TOut() : x(0), y(0), timer(0) {
|
||||
text[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
void init();
|
||||
void save(Common::OutSaveFile *out);
|
||||
void loadSaveFile(Common::InSaveFile *in);
|
||||
void restartSystem();
|
||||
void setInfobarDark(int value);
|
||||
|
||||
void closeAll();
|
||||
|
||||
// Pause Functions
|
||||
void drawPause();
|
||||
void checkPause(int x, int y);
|
||||
|
||||
// Weapon Functions
|
||||
void drawWeapon();
|
||||
void chooseWeapon(AIType wType);
|
||||
|
||||
// Dialog Functions
|
||||
|
||||
void openDialog(const char *title, int tileIndex, const char *string, int more, const char *luaMore);
|
||||
void drawDialog();
|
||||
void closeDialog();
|
||||
bool checkDialogClose(int x, int y);
|
||||
void drawBorder(int x, int y, int width, int height, bool guyTalking);
|
||||
void setDialogDelay(int delay);
|
||||
uint32 getDialogDelay() {
|
||||
return _dialogDelay;
|
||||
}
|
||||
bool dialogActive() {
|
||||
return _dialogInfo.active;
|
||||
}
|
||||
|
||||
// Dialog Choice Functions
|
||||
|
||||
void openDialogChoice(const char *title, const char *text, const char *func, int numChoices, const char *choices[10]);
|
||||
void drawDialogChoice();
|
||||
void closeDialogChoice();
|
||||
bool checkDialogChoiceClose(int x, int y);
|
||||
void dialogChoiceMoveup();
|
||||
void dialogChoiceMovedown();
|
||||
bool dialogChoiceActive() {
|
||||
return _dialogChoiceInfo.active;
|
||||
}
|
||||
|
||||
// MessageBar Functions
|
||||
void openMessageBar(const char *title, int time);
|
||||
void drawMessageBar();
|
||||
bool checkMsgClose(int x, int y);
|
||||
void nextMsgQueued();
|
||||
void closeMsg();
|
||||
bool msgBarActive() {
|
||||
return _msgInfo.active;
|
||||
}
|
||||
|
||||
// Inventory Functions
|
||||
void drawInventory();
|
||||
void setInvSelect(int status) {
|
||||
_invWinInfo.selection = status;
|
||||
}
|
||||
int getInvSelect() {
|
||||
return _invWinInfo.selection;
|
||||
}
|
||||
void checkInvSelect(int x, int y);
|
||||
bool inventoryActive() {
|
||||
return _invWinInfo.active;
|
||||
}
|
||||
// PPC Inventory
|
||||
void openInventory();
|
||||
bool checkInvClose(int x, int y);
|
||||
void closeInv();
|
||||
|
||||
// Deliveries Functions
|
||||
void openDeliveries(bool animate);
|
||||
void drawDeliveries();
|
||||
void setSelectedDelivery(int which);
|
||||
int getSelectedDelivery() {
|
||||
return _dlvsInfo.selected;
|
||||
}
|
||||
bool animatingDelivery() {
|
||||
return _dlvsInfo.animate;
|
||||
}
|
||||
void checkDlvSelect(int x, int y);
|
||||
// PPC Deliveries
|
||||
bool checkDlvsClose(int x, int y);
|
||||
void closeDlvs();
|
||||
bool deliveriesActive() {
|
||||
return _dlvsInfo.active;
|
||||
}
|
||||
|
||||
// Try Again Functions
|
||||
void drawTryAgain();
|
||||
void clearTryAgain();
|
||||
|
||||
// Panic Zone Functions
|
||||
void loadPanicZoneGfx();
|
||||
void drawPanicZone();
|
||||
void startPanicZone();
|
||||
void stopPanicZone();
|
||||
bool inPanicZone() {
|
||||
return _pzInfo.active;
|
||||
}
|
||||
|
||||
// TextOut functions
|
||||
void textOut(const char *text, int x, int y, int timer);
|
||||
void centerTextOut(const char *text, int y, int timer);
|
||||
void drawTextOut();
|
||||
int textOutActive() {
|
||||
return (_textOutList.size());
|
||||
}
|
||||
void closeTextOut();
|
||||
|
||||
// Platform-specific Constants
|
||||
int _weaponX, _weaponY;
|
||||
int _invItemSpace, _invItemSpaceX, _invItemSpaceY;
|
||||
int _invItemPerLine;
|
||||
int _dlvItemSpaceX;
|
||||
int _dlvItemSpaceY;
|
||||
int _dlvItemPerLine;
|
||||
int _dlvItemTextY;
|
||||
int _dialogTextLeft;
|
||||
int _dialogTextRight;
|
||||
int _openDialogTextLeft;
|
||||
int _openDialogTextRight;
|
||||
int _textOutCenterX;
|
||||
int _pauseY;
|
||||
int _tryY1; // TRY
|
||||
int _tryY2; // AGAIN
|
||||
int _tryRestartY; // (ok)
|
||||
int _panicXStop;
|
||||
int _panicZoneFaceX;
|
||||
|
||||
Tile *getGemGfx() {
|
||||
return _gemGfx;
|
||||
}
|
||||
|
||||
PanicZone _pzInfo, _tempPzInfo;
|
||||
|
||||
private:
|
||||
|
||||
DialogInfo _dialogInfo;
|
||||
uint32 _dialogDelay; // Used for Cinematics
|
||||
|
||||
DialogChoiceInfo _dialogChoiceInfo;
|
||||
|
||||
MessageInfo _msgInfo;
|
||||
|
||||
InvWinInfo _invWinInfo;
|
||||
Common::Array<TOut *> _textOutList;
|
||||
DlvsInfo _dlvsInfo;
|
||||
|
||||
TryAgainInfo _tryAgainInfo;
|
||||
|
||||
char _msgQueueStr[kMaxMsgQueue][128];
|
||||
int _msgQueueWait[kMaxMsgQueue];
|
||||
int _numMsgQueue;
|
||||
|
||||
// Windows GFX
|
||||
Picture *_gfxTL, *_gfxTM, *_gfxTR;
|
||||
Picture *_gfxL, *_gfxM, *_gfxR;
|
||||
Picture *_gfxBL, *_gfxBM, *_gfxBR;
|
||||
Picture *_gfxTitleL, *_gfxTitleM, *_gfxTitleR;
|
||||
Picture *_gGfxTL, *_gGfxTM, *_gGfxTR;
|
||||
Picture *_gGfxL, *_gGfxM, *_gGfxR;
|
||||
Picture *_gGfxBL, *_gGfxBM, *_gGfxBR;
|
||||
Picture *_gGfxTitleL, *_gGfxTitleM, *_gGfxTitleR;
|
||||
Picture *_gfxIndent, *_gfxArrowTo, *_gfxHandright;
|
||||
Picture *_gfxTry, *_gfxAgain, *_gfxInvSelect;
|
||||
Picture *_gfxLevelRestart, *_gfxPausePlaque;
|
||||
Tile *_gemGfx;
|
||||
Picture *_mstoneGfx;
|
||||
|
||||
// Info Bar
|
||||
Picture *_gfxResources, *_gfxDeliveries;
|
||||
Picture *_gfxInfobar, *_gfxDarken;
|
||||
int _infobarDimmed;
|
||||
};
|
||||
|
||||
} // End of Namespace
|
||||
|
||||
#endif // !HDB_WINDOW_H
|
||||
Reference in New Issue
Block a user