mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-23 02:11:38 +00:00
276d754443
svn-id: r22988
2054 lines
53 KiB
C++
2054 lines
53 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004 Ivan Dubrov
|
|
* Copyright (C) 2004-2006 The ScummVM project
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
#include "gob/gob.h"
|
|
#include "gob/goblin.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/global.h"
|
|
#include "gob/draw.h"
|
|
#include "gob/video.h"
|
|
#include "gob/anim.h"
|
|
#include "gob/scenery.h"
|
|
#include "gob/map.h"
|
|
#include "gob/sound.h"
|
|
#include "gob/game.h"
|
|
#include "gob/dataio.h"
|
|
#include "gob/cdrom.h"
|
|
#include "gob/music.h"
|
|
#include "gob/mult.h"
|
|
|
|
namespace Gob {
|
|
|
|
Goblin::Goblin(GobEngine *vm) : _vm(vm) {
|
|
int i;
|
|
|
|
_goesAtTarget = 0;
|
|
_readyToAct = 0;
|
|
_gobAction = 0;
|
|
_itemIndInPocket = 5;
|
|
_itemIdInPocket = 2;
|
|
_itemByteFlag = 0;
|
|
_destItemId = -1;
|
|
_destActionItem = 0;
|
|
_actDestItemDesc = 0;
|
|
_forceNextState[0] = -1;
|
|
_forceNextState[1] = -1;
|
|
_forceNextState[2] = -1;
|
|
_forceNextState[3] = -1;
|
|
_forceNextState[4] = -1;
|
|
_forceNextState[5] = -1;
|
|
_forceNextState[6] = -1;
|
|
_forceNextState[7] = 0;
|
|
_forceNextState[8] = 0;
|
|
_forceNextState[9] = 0;
|
|
|
|
_boreCounter = 0;
|
|
_positionedGob = 5;
|
|
|
|
_noPick = 0;
|
|
_objList = 0;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
_goblins[i] = 0;
|
|
_currentGoblin = 0;
|
|
for (i = 0; i < 16; i++)
|
|
_soundData[i] = 0;
|
|
for (i = 0; i < 3; i++) {
|
|
_gobPositions[i].x = 0;
|
|
_gobPositions[i].y = 0;
|
|
}
|
|
_gobDestX = 0;
|
|
_gobDestY = 0;
|
|
_pressedMapX = 0;
|
|
_pressedMapY = 0;
|
|
_pathExistence = 0;
|
|
|
|
_some0ValPtr = 0;
|
|
|
|
_gobRetVarPtr = 0;
|
|
_curGobVarPtr = 0;
|
|
_curGobXPosVarPtr = 0;
|
|
_curGobYPosVarPtr = 0;
|
|
_itemInPocketVarPtr = 0;
|
|
|
|
_curGobStateVarPtr = 0;
|
|
_curGobFrameVarPtr = 0;
|
|
_curGobMultStateVarPtr = 0;
|
|
_curGobNextStateVarPtr = 0;
|
|
_curGobScrXVarPtr = 0;
|
|
_curGobScrYVarPtr = 0;
|
|
_curGobLeftVarPtr = 0;
|
|
_curGobTopVarPtr = 0;
|
|
_curGobRightVarPtr = 0;
|
|
_curGobBottomVarPtr = 0;
|
|
_curGobDoAnimVarPtr = 0;
|
|
_curGobOrderVarPtr = 0;
|
|
_curGobNoTickVarPtr = 0;
|
|
_curGobTypeVarPtr = 0;
|
|
_curGobMaxTickVarPtr = 0;
|
|
_curGobTickVarPtr = 0;
|
|
_curGobActStartStateVarPtr = 0;
|
|
_curGobLookDirVarPtr = 0;
|
|
_curGobPickableVarPtr = 0;
|
|
_curGobRelaxVarPtr = 0;
|
|
_curGobMaxFrameVarPtr = 0;
|
|
|
|
_destItemStateVarPtr = 0;
|
|
_destItemFrameVarPtr = 0;
|
|
_destItemMultStateVarPtr = 0;
|
|
_destItemNextStateVarPtr = 0;
|
|
_destItemScrXVarPtr = 0;
|
|
_destItemScrYVarPtr = 0;
|
|
_destItemLeftVarPtr = 0;
|
|
_destItemTopVarPtr = 0;
|
|
_destItemRightVarPtr = 0;
|
|
_destItemBottomVarPtr = 0;
|
|
_destItemDoAnimVarPtr = 0;
|
|
_destItemOrderVarPtr = 0;
|
|
_destItemNoTickVarPtr = 0;
|
|
_destItemTypeVarPtr = 0;
|
|
_destItemMaxTickVarPtr = 0;
|
|
_destItemTickVarPtr = 0;
|
|
_destItemActStartStVarPtr = 0;
|
|
_destItemLookDirVarPtr = 0;
|
|
_destItemPickableVarPtr = 0;
|
|
_destItemRelaxVarPtr = 0;
|
|
_destItemMaxFrameVarPtr = 0;
|
|
|
|
_destItemType = 0;
|
|
_destItemState = 0;
|
|
for (i = 0; i < 20; i++) {
|
|
_itemToObject[i] = 0;
|
|
_objects[i] = 0;
|
|
}
|
|
_objCount = 0;
|
|
_gobsCount = 0;
|
|
|
|
_soundSlotsCount = 0;
|
|
for (i = 0; i < 60; i++)
|
|
_soundSlots[i] = -1;
|
|
|
|
warning("GOB2 Stub! _word_2F9C0, _word_2F9BE, _word_2F9BC, _word_2F9BA, _dword_2F9B6, _dword_2F9B2");
|
|
_word_2F9C0 = 0;
|
|
_word_2F9BE = 0;
|
|
_word_2F9BC = 0;
|
|
_word_2F9BA = 0;
|
|
_dword_2F9B6 = 0;
|
|
_dword_2F9B2 = 0;
|
|
}
|
|
|
|
Goblin::~Goblin() {
|
|
int i, state, col;
|
|
|
|
if (_objList)
|
|
_vm->_util->deleteList(_objList);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (_goblins[i]) {
|
|
if (_goblins[i]->stateMach) {
|
|
for (state = 0; state < (i == 3 ? 70 : 40); state++)
|
|
for (col = 0; col < 6; col++)
|
|
if (_goblins[i]->stateMach[state][col])
|
|
delete _goblins[i]->stateMach[state][col];
|
|
delete []_goblins[i]->stateMach;
|
|
}
|
|
delete _goblins[i];
|
|
}
|
|
}
|
|
for (i = 0; i < 20; i++) {
|
|
if (_objects[i]) {
|
|
if (_objects[i]->stateMach) {
|
|
for (state = 0; state < 40; state++)
|
|
for (col = 0; col < 6; col++)
|
|
if (_objects[i]->stateMach[state][col])
|
|
delete _objects[i]->stateMach[state][col];
|
|
delete []_objects[i]->stateMach;
|
|
}
|
|
delete _objects[i];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 16; i++)
|
|
if (_soundData[i]) {
|
|
if (_soundData[i]->data)
|
|
delete[] _soundData[i]->data;
|
|
delete _soundData[i];
|
|
}
|
|
}
|
|
|
|
char Goblin::rotateState(int16 from, int16 to) {
|
|
return _rotStates[from / 2][to / 2];
|
|
}
|
|
|
|
int16 Goblin::peekGoblin(Gob_Object *_curGob) {
|
|
Util::ListNode *ptr;
|
|
Gob_Object *desc;
|
|
int16 index;
|
|
int16 i;
|
|
|
|
ptr = _objList->pHead;
|
|
index = 0;
|
|
while (ptr != 0) {
|
|
desc = (Gob_Object *) ptr->pData;
|
|
if (desc != _curGob) {
|
|
for (i = 0; i < 3; i++) {
|
|
if (desc != _goblins[i])
|
|
continue;
|
|
|
|
if (_vm->_global->_inter_mouseX < desc->right &&
|
|
_vm->_global->_inter_mouseX > desc->left &&
|
|
_vm->_global->_inter_mouseY < desc->bottom &&
|
|
_vm->_global->_inter_mouseY > desc->top) {
|
|
index = i + 1;
|
|
}
|
|
}
|
|
}
|
|
ptr = ptr->pNext;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
void Goblin::initList(void) {
|
|
_objList = new Util::List;
|
|
_objList->pHead = 0;
|
|
_objList->pTail = 0;
|
|
}
|
|
|
|
void Goblin::sortByOrder(Util::List *list) {
|
|
Util::ListNode *ptr;
|
|
Util::ListNode *ptr2;
|
|
|
|
ptr = list->pHead;
|
|
while (ptr->pNext != 0) {
|
|
for (ptr2 = ptr->pNext; ptr2 != 0; ptr2 = ptr2->pNext) {
|
|
Gob_Object *objDesc = (Gob_Object *)ptr->pData;
|
|
Gob_Object *objDesc2 = (Gob_Object *)ptr2->pData;
|
|
|
|
if (objDesc->order <= objDesc2->order) {
|
|
if (objDesc->order != objDesc2->order)
|
|
continue;
|
|
|
|
if (objDesc->bottom <= objDesc2->bottom) {
|
|
if (objDesc->bottom != objDesc2->bottom)
|
|
continue;
|
|
|
|
if (objDesc != _goblins[_currentGoblin])
|
|
continue;
|
|
}
|
|
}
|
|
|
|
SWAP(ptr->pData, ptr2->pData);
|
|
}
|
|
ptr = ptr->pNext;
|
|
}
|
|
}
|
|
|
|
void Goblin::playSound(Snd::SoundDesc *snd, int16 repCount, int16 freq) {
|
|
if (snd != 0) {
|
|
_vm->_snd->stopSound(0);
|
|
_vm->_snd->playSample(snd, repCount, freq);
|
|
}
|
|
}
|
|
|
|
void Goblin::drawObjects(void) {
|
|
Util::ListNode *ptr;
|
|
Util::ListNode *ptr2;
|
|
|
|
Gob_Object *objDesc;
|
|
Gob_Object *gobDesc2;
|
|
int16 layer;
|
|
|
|
ptr = _objList->pHead;
|
|
for (ptr = _objList->pHead; ptr != 0; ptr = ptr->pNext) {
|
|
objDesc = (Gob_Object *) ptr->pData;
|
|
|
|
if (objDesc->type == 3)
|
|
objDesc->toRedraw = 1;
|
|
else if (objDesc->type == 1)
|
|
objDesc->toRedraw = 0;
|
|
}
|
|
|
|
for (ptr = _objList->pHead; ptr != 0; ptr = ptr->pNext) {
|
|
objDesc = (Gob_Object *) ptr->pData;
|
|
if (objDesc->toRedraw == 0)
|
|
continue;
|
|
|
|
_vm->_video->drawSprite(_vm->_anim->_animSurf, _vm->_draw->_backSurface,
|
|
objDesc->left, objDesc->top, objDesc->right,
|
|
objDesc->bottom, objDesc->left, objDesc->top, 0);
|
|
|
|
_vm->_draw->invalidateRect(objDesc->left, objDesc->top,
|
|
objDesc->right, objDesc->bottom);
|
|
|
|
if (objDesc->type != 0)
|
|
continue;
|
|
|
|
layer =
|
|
objDesc->stateMach[objDesc->state][objDesc->stateColumn]->
|
|
layer;
|
|
_vm->_scenery->updateAnim(layer, objDesc->curFrame, objDesc->animation,
|
|
0, objDesc->xPos, objDesc->yPos, 0);
|
|
|
|
if (_vm->_scenery->_toRedrawLeft == -12345) {
|
|
objDesc->dirtyLeft = objDesc->left;
|
|
objDesc->dirtyRight = objDesc->right;
|
|
objDesc->dirtyTop = objDesc->top;
|
|
objDesc->dirtyBottom = objDesc->bottom;
|
|
} else {
|
|
objDesc->dirtyLeft =
|
|
MIN(objDesc->left, _vm->_scenery->_toRedrawLeft);
|
|
objDesc->dirtyRight =
|
|
MAX(objDesc->right, _vm->_scenery->_toRedrawRight);
|
|
objDesc->dirtyTop =
|
|
MIN(objDesc->top, _vm->_scenery->_toRedrawTop);
|
|
objDesc->dirtyBottom =
|
|
MAX(objDesc->bottom, _vm->_scenery->_toRedrawBottom);
|
|
}
|
|
|
|
objDesc->dirtyLeft = 0;
|
|
objDesc->dirtyRight = 319;
|
|
objDesc->dirtyTop = 0;
|
|
objDesc->dirtyBottom = 199;
|
|
}
|
|
|
|
sortByOrder(_objList);
|
|
for (ptr = _objList->pHead; ptr != 0; ptr = ptr->pNext) {
|
|
objDesc = (Gob_Object *) ptr->pData;
|
|
if (objDesc->toRedraw) {
|
|
layer =
|
|
objDesc->stateMach[objDesc->state][objDesc->
|
|
stateColumn]->layer;
|
|
|
|
if (objDesc->type == 0) {
|
|
if (objDesc->visible == 0) {
|
|
_vm->_scenery->updateAnim(layer,
|
|
objDesc->curFrame,
|
|
objDesc->animation, 0,
|
|
objDesc->xPos, objDesc->yPos, 0);
|
|
|
|
} else {
|
|
_vm->_scenery->updateAnim(layer,
|
|
objDesc->curFrame,
|
|
objDesc->animation, 2,
|
|
objDesc->xPos, objDesc->yPos, 1);
|
|
}
|
|
if (_vm->_scenery->_toRedrawLeft == -12345) {
|
|
objDesc->left = 0;
|
|
objDesc->top = 0;
|
|
objDesc->right = 0;
|
|
objDesc->bottom = 0;
|
|
} else {
|
|
_vm->_draw->invalidateRect(_vm->_scenery->_toRedrawLeft,
|
|
_vm->_scenery->_toRedrawTop,
|
|
_vm->_scenery->_toRedrawRight,
|
|
_vm->_scenery->_toRedrawBottom);
|
|
|
|
objDesc->left = _vm->_scenery->_toRedrawLeft;
|
|
objDesc->top = _vm->_scenery->_toRedrawTop;
|
|
objDesc->right = _vm->_scenery->_toRedrawRight;
|
|
objDesc->bottom = _vm->_scenery->_toRedrawBottom;
|
|
_vm->_scenery->updateStatic(objDesc->order);
|
|
}
|
|
} else {
|
|
objDesc->left = 0;
|
|
objDesc->top = 0;
|
|
objDesc->right = 0;
|
|
objDesc->bottom = 0;
|
|
objDesc->type = 1;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (objDesc->type == 0 && objDesc->visible != 0) {
|
|
for (ptr2 = _objList->pHead; ptr2 != 0;
|
|
ptr2 = ptr2->pNext) {
|
|
gobDesc2 = (Gob_Object *) ptr2->pData;
|
|
|
|
if (gobDesc2->toRedraw == 0)
|
|
continue;
|
|
|
|
if (objDesc->right < gobDesc2->dirtyLeft)
|
|
continue;
|
|
|
|
if (gobDesc2->dirtyRight < objDesc->left)
|
|
continue;
|
|
|
|
if (objDesc->bottom < gobDesc2->dirtyTop)
|
|
continue;
|
|
|
|
if (gobDesc2->dirtyBottom < objDesc->top)
|
|
continue;
|
|
|
|
_vm->_scenery->_toRedrawLeft = gobDesc2->dirtyLeft;
|
|
_vm->_scenery->_toRedrawRight = gobDesc2->dirtyRight;
|
|
_vm->_scenery->_toRedrawTop = gobDesc2->dirtyTop;
|
|
_vm->_scenery->_toRedrawBottom = gobDesc2->dirtyBottom;
|
|
|
|
layer =
|
|
objDesc->stateMach[objDesc->
|
|
state][objDesc->stateColumn]->layer;
|
|
|
|
_vm->_scenery->updateAnim(layer, objDesc->curFrame,
|
|
objDesc->animation, 4, objDesc->xPos,
|
|
objDesc->yPos, 1);
|
|
|
|
_vm->_scenery->updateStatic(objDesc->order);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ptr = _objList->pHead; ptr != 0; ptr = ptr->pNext) {
|
|
objDesc = (Gob_Object *) ptr->pData;
|
|
if (objDesc->toRedraw == 0 || objDesc->type == 1)
|
|
continue;
|
|
|
|
Gob_State *state = objDesc->stateMach[objDesc->state][objDesc->stateColumn];
|
|
int16 sndFrame;
|
|
int16 sndItem;
|
|
int16 freq;
|
|
int16 repCount;
|
|
|
|
if (state->sndFrame & 0xff00) {
|
|
// There are two frames which trigger a sound effect,
|
|
// so everything has to be encoded in one byte each.
|
|
// Note that the frequency is multiplied by 100, not -
|
|
// as I would have thought, 0x100.
|
|
|
|
sndFrame = (state->sndFrame >> 8) & 0xff;
|
|
sndItem = (state->sndItem >> 8) & 0xff;
|
|
freq = 100 * ((state->freq >> 8) & 0xff);
|
|
repCount = (state->repCount >> 8) & 0xff;
|
|
|
|
if (objDesc->curFrame == sndFrame) {
|
|
if (sndItem != 0xff) {
|
|
playSound(_soundData[sndItem],
|
|
repCount, freq);
|
|
}
|
|
}
|
|
|
|
sndFrame = state->sndFrame & 0xff;
|
|
sndItem = state->sndItem & 0xff;
|
|
freq = 100 * (state->freq & 0xff);
|
|
repCount = state->repCount & 0xff;
|
|
|
|
if (objDesc->curFrame == sndFrame) {
|
|
if (sndItem != 0xff) {
|
|
playSound(_soundData[sndItem],
|
|
repCount, freq);
|
|
}
|
|
}
|
|
} else {
|
|
// There is only one, so frequency etc. are used as is.
|
|
sndFrame = state->sndFrame;
|
|
sndItem = state->sndItem;
|
|
freq = state->freq;
|
|
repCount = state->repCount;
|
|
|
|
if (objDesc->curFrame == sndFrame) {
|
|
if (sndItem != -1) {
|
|
playSound(_soundData[sndItem],
|
|
repCount, freq);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// _vm->_scenery->updateAnim(27, 0, 9, 2, 10, 10, 1);
|
|
}
|
|
|
|
void Goblin::animateObjects(void) {
|
|
Util::ListNode *node;
|
|
Gob_Object *objDesc;
|
|
Scenery::AnimLayer *pLayer;
|
|
int16 layer;
|
|
|
|
for (node = _objList->pHead; node != 0; node = node->pNext) {
|
|
objDesc = (Gob_Object *) node->pData;
|
|
if (objDesc->doAnim != 1 || objDesc->type != 0)
|
|
continue;
|
|
|
|
if (objDesc->noTick != 0)
|
|
continue;
|
|
|
|
if (objDesc->tick < objDesc->maxTick)
|
|
objDesc->tick++;
|
|
|
|
if (objDesc->tick >= objDesc->maxTick) {
|
|
objDesc->tick = 1;
|
|
objDesc->curFrame++;
|
|
|
|
layer = objDesc->stateMach[objDesc->state][0]->layer;
|
|
pLayer =
|
|
_vm->_scenery->_animations[objDesc->animation].layers[layer];
|
|
|
|
if (objDesc->curFrame < pLayer->framesCount)
|
|
continue;
|
|
|
|
objDesc->curFrame = 0;
|
|
|
|
objDesc->xPos += pLayer->animDeltaX;
|
|
objDesc->yPos += pLayer->animDeltaY;
|
|
|
|
if (objDesc->nextState == -1
|
|
&& objDesc->multState == -1
|
|
&& objDesc->unk14 == 0) {
|
|
objDesc->toRedraw = 0;
|
|
objDesc->curFrame = pLayer->framesCount - 1;
|
|
}
|
|
|
|
if (objDesc->multState != -1) {
|
|
if (objDesc->multState > 39) {
|
|
objDesc->stateMach = _goblins[(int)(objDesc->multObjIndex)]->stateMach;
|
|
objDesc->state = objDesc->multState - 40;
|
|
} else {
|
|
objDesc->stateMach = objDesc->realStateMach;
|
|
objDesc->state = objDesc->multState;
|
|
}
|
|
objDesc->animation =
|
|
objDesc->stateMach[objDesc->state][0]->
|
|
animation;
|
|
objDesc->multState = -1;
|
|
} else {
|
|
if (objDesc->nextState == -1)
|
|
continue;
|
|
|
|
objDesc->stateMach = objDesc->realStateMach;
|
|
objDesc->state = objDesc->nextState;
|
|
objDesc->animation =
|
|
objDesc->stateMach[objDesc->state][0]->
|
|
animation;
|
|
objDesc->nextState = -1;
|
|
}
|
|
objDesc->toRedraw = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
int16 Goblin::getObjMaxFrame(Gob_Object * objDesc) {
|
|
int16 layer;
|
|
|
|
layer = objDesc->stateMach[objDesc->state][0]->layer;
|
|
return _vm->_scenery->_animations[objDesc->animation].layers[layer]->framesCount -
|
|
1;
|
|
}
|
|
|
|
int16 Goblin::objIntersected(Gob_Object *obj1, Gob_Object *obj2) {
|
|
if (obj1->type == 1 || obj2->type == 1)
|
|
return 0;
|
|
|
|
if (obj1->right < obj2->left)
|
|
return 0;
|
|
|
|
if (obj1->left > obj2->right)
|
|
return 0;
|
|
|
|
if (obj1->bottom < obj2->top)
|
|
return 0;
|
|
|
|
if (obj1->top > obj2->bottom)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void Goblin::setMultStates(Gob_Object * gobDesc) {
|
|
gobDesc->stateMach = _goblins[(int)gobDesc->multObjIndex]->stateMach;
|
|
}
|
|
|
|
int16 Goblin::nextLayer(Gob_Object *gobDesc) {
|
|
if (gobDesc->nextState == 10)
|
|
gobDesc->curLookDir = 0;
|
|
|
|
if (gobDesc->nextState == 11)
|
|
gobDesc->curLookDir = 4;
|
|
|
|
if (gobDesc->nextState > 39) {
|
|
setMultStates(gobDesc);
|
|
} else {
|
|
gobDesc->stateMach = gobDesc->realStateMach;
|
|
}
|
|
|
|
gobDesc->curFrame = 0;
|
|
if (gobDesc->nextState > 39)
|
|
gobDesc->state = gobDesc->nextState - 40;
|
|
else
|
|
gobDesc->state = gobDesc->nextState;
|
|
|
|
gobDesc->animation = gobDesc->stateMach[gobDesc->state][0]->animation;
|
|
return gobDesc->stateMach[gobDesc->state][0]->layer;
|
|
}
|
|
|
|
void Goblin::showBoredom(int16 gobIndex) {
|
|
Gob_Object *gobDesc;
|
|
int16 frame;
|
|
int16 frameCount;
|
|
int16 layer;
|
|
int16 state;
|
|
int16 boreFlag;
|
|
|
|
gobDesc = _goblins[gobIndex];
|
|
layer = gobDesc->stateMach[gobDesc->state][0]->layer;
|
|
|
|
frameCount =
|
|
_vm->_scenery->_animations[gobDesc->animation].layers[layer]->framesCount;
|
|
state = gobDesc->state;
|
|
frame = gobDesc->curFrame;
|
|
|
|
gobDesc->noTick = 0;
|
|
gobDesc->toRedraw = 1;
|
|
|
|
boreFlag = 1 << _vm->_util->getRandom(7);
|
|
|
|
if (gobIndex != _currentGoblin && _vm->_util->getRandom(3) != 0) {
|
|
if (state == 21) {
|
|
if ((boreFlag & 16) || (boreFlag & 32)) {
|
|
gobDesc->multState = 92 + gobIndex;
|
|
} else if (boreFlag & 1) {
|
|
gobDesc->multState = 86 + gobIndex;
|
|
} else if (boreFlag & 2) {
|
|
gobDesc->multState = 80 + gobIndex;
|
|
} else if (boreFlag & 4) {
|
|
gobDesc->multState = 89 + gobIndex;
|
|
} else if (boreFlag & 8) {
|
|
gobDesc->multState = 104 + gobIndex;
|
|
}
|
|
}
|
|
gobDesc->nextState = 21;
|
|
} else if (state >= 18 && state <= 21 && VAR(59) == 0) {
|
|
if (state == 30 || state == 31) // ???
|
|
return;
|
|
|
|
if (frame != frameCount)
|
|
return;
|
|
|
|
gobDesc->multState = 104 + gobIndex;
|
|
}
|
|
}
|
|
|
|
// index - goblin to select+1
|
|
// index==0 - switch to next
|
|
void Goblin::switchGoblin(int16 index) {
|
|
int16 next;
|
|
int16 tmp;
|
|
|
|
debugC(4, DEBUG_GAMEFLOW, "switchGoblin");
|
|
if (VAR(59) != 0)
|
|
return;
|
|
|
|
if (_goblins[_currentGoblin]->state <= 39 &&
|
|
_goblins[_currentGoblin]->curFrame != 0)
|
|
return;
|
|
|
|
if (index != 0 && _goblins[index - 1]->type != 0)
|
|
return;
|
|
|
|
if (index == 0)
|
|
next = (_currentGoblin + 1) % 3;
|
|
else
|
|
next = index - 1;
|
|
|
|
if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3 ||
|
|
_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6)
|
|
return;
|
|
|
|
if (_goblins[(_currentGoblin + 1) % 3]->type != 0 &&
|
|
_goblins[(_currentGoblin + 2) % 3]->type != 0)
|
|
return;
|
|
|
|
_gobPositions[_currentGoblin].x = _vm->_map->_curGoblinX;
|
|
_gobPositions[_currentGoblin].y = _vm->_map->_curGoblinY;
|
|
|
|
_goblins[_currentGoblin]->doAnim = 1;
|
|
_goblins[_currentGoblin]->nextState = 21;
|
|
|
|
nextLayer(_goblins[_currentGoblin]);
|
|
|
|
_currentGoblin = next;
|
|
if (_goblins[_currentGoblin]->type != 0)
|
|
_currentGoblin = (_currentGoblin + 1) % 3;
|
|
|
|
_goblins[_currentGoblin]->doAnim = 0;
|
|
if (_goblins[_currentGoblin]->curLookDir == 4)
|
|
_goblins[_currentGoblin]->nextState = 18;
|
|
else
|
|
_goblins[_currentGoblin]->nextState = 19;
|
|
|
|
_goblins[_currentGoblin]->toRedraw = 1;
|
|
nextLayer(_goblins[_currentGoblin]);
|
|
|
|
tmp = _gobPositions[_currentGoblin].x;
|
|
_pressedMapX = tmp;
|
|
_vm->_map->_destX = tmp;
|
|
_gobDestX = tmp;
|
|
_vm->_map->_curGoblinX = tmp;
|
|
|
|
tmp = _gobPositions[_currentGoblin].y;
|
|
_pressedMapY = tmp;
|
|
_vm->_map->_destY = tmp;
|
|
_gobDestY = tmp;
|
|
_vm->_map->_curGoblinY = tmp;
|
|
|
|
*_curGobVarPtr = _currentGoblin;
|
|
_pathExistence = 0;
|
|
_readyToAct = 0;
|
|
}
|
|
|
|
void Goblin::adjustDest(int16 posX, int16 posY) {
|
|
int16 resDelta;
|
|
int16 resDeltaDir;
|
|
int16 resDeltaPix;
|
|
int16 deltaPix;
|
|
int16 i;
|
|
|
|
if (_vm->_map->getPass(_pressedMapX, _pressedMapY) == 0 &&
|
|
(_gobAction == 0
|
|
|| _vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0)) {
|
|
|
|
resDelta = -1;
|
|
resDeltaDir = 0;
|
|
resDeltaPix = 0;
|
|
|
|
for (i = 1;
|
|
i <= _pressedMapX
|
|
&& _vm->_map->getPass(_pressedMapX - i, _pressedMapY) == 0;
|
|
i++);
|
|
|
|
if (i <= _pressedMapX) {
|
|
resDeltaPix = (i - 1) * 12 + (posX % 12) + 1;
|
|
resDelta = i;
|
|
}
|
|
|
|
for (i = 1;
|
|
(i + _pressedMapX) < _vm->_map->_mapWidth
|
|
&& _vm->_map->getPass(_pressedMapX + i, _pressedMapY) == 0;
|
|
i++);
|
|
|
|
if (_pressedMapX + i < _vm->_map->_mapWidth) {
|
|
deltaPix = (i * 12) - (posX % 12);
|
|
if (resDelta == -1 || deltaPix < resDeltaPix) {
|
|
resDeltaPix = deltaPix;
|
|
resDelta = i;
|
|
resDeltaDir = 1;
|
|
}
|
|
}
|
|
|
|
for (i = 1;
|
|
(i + _pressedMapY) < _vm->_map->_mapHeight
|
|
&& _vm->_map->getPass(_pressedMapX, _pressedMapY + i) == 0;
|
|
i++);
|
|
|
|
if (_pressedMapY + i < _vm->_map->_mapHeight) {
|
|
deltaPix = (i * 6) - (posY % 6);
|
|
if (resDelta == -1 || deltaPix < resDeltaPix) {
|
|
resDeltaPix = deltaPix;
|
|
resDelta = i;
|
|
resDeltaDir = 2;
|
|
}
|
|
}
|
|
|
|
for (i = 1;
|
|
i <= _pressedMapY
|
|
&& _vm->_map->getPass(_pressedMapX, _pressedMapY - i) == 0;
|
|
i++);
|
|
|
|
if (i <= _pressedMapY) {
|
|
deltaPix = (i * 6) + (posY % 6);
|
|
if (resDelta == -1 || deltaPix < resDeltaPix) {
|
|
resDeltaPix = deltaPix;
|
|
resDelta = i;
|
|
resDeltaDir = 3;
|
|
}
|
|
}
|
|
|
|
switch (resDeltaDir) {
|
|
case 0:
|
|
_pressedMapX -= resDelta;
|
|
break;
|
|
|
|
case 1:
|
|
_pressedMapX += resDelta;
|
|
break;
|
|
|
|
case 2:
|
|
_pressedMapY += resDelta;
|
|
break;
|
|
|
|
case 3:
|
|
_pressedMapY -= resDelta;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void Goblin::adjustTarget(void) {
|
|
if (_gobAction == 4
|
|
&& _vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0) {
|
|
|
|
if (_pressedMapY > 0
|
|
&& _vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX] !=
|
|
0) {
|
|
_pressedMapY--;
|
|
} else if (_pressedMapX < _vm->_map->_mapWidth - 1
|
|
&& _vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] !=
|
|
0) {
|
|
_pressedMapX++;
|
|
} else if (_pressedMapX < _vm->_map->_mapWidth - 1 && _pressedMapY > 0
|
|
&& _vm->_map->_itemsMap[_pressedMapY - 1][_pressedMapX +
|
|
1] != 0) {
|
|
_pressedMapY--;
|
|
_pressedMapX++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::targetDummyItem(Gob_Object *gobDesc) {
|
|
if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0 &&
|
|
_vm->_map->getPass(_pressedMapX, _pressedMapY) == 1) {
|
|
if (gobDesc->curLookDir == 0) {
|
|
_vm->_map->_itemPoses[0].x = _pressedMapX;
|
|
_vm->_map->_itemPoses[0].y = _pressedMapY;
|
|
_vm->_map->_itemPoses[0].orient = -4;
|
|
} else {
|
|
_vm->_map->_itemPoses[0].x = _pressedMapX;
|
|
_vm->_map->_itemPoses[0].y = _pressedMapY;
|
|
_vm->_map->_itemPoses[0].orient = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::targetItem(void) {
|
|
int16 tmpX;
|
|
int16 tmpY;
|
|
int16 items;
|
|
int16 layer;
|
|
int16 tmpPosX;
|
|
int16 tmpPosY;
|
|
Gob_Object *itemDesc;
|
|
|
|
if (_gobAction == 3 || _gobAction == 4) {
|
|
items = _vm->_map->_itemsMap[_pressedMapY][_pressedMapX];
|
|
if (_gobAction == 4 && (items & 0xff00) != 0 &&
|
|
_objects[_itemToObject[(items & 0xff00) >> 8]]->
|
|
pickable == 1) {
|
|
_destItemId = (items & 0xff00) >> 8;
|
|
_destActionItem = (items & 0xff00) >> 8;
|
|
_itemByteFlag = 1;
|
|
} else if ((items & 0xff) == 0) {
|
|
_destItemId = (items & 0xff00) >> 8;
|
|
_destActionItem = (items & 0xff00) >> 8;
|
|
_itemByteFlag = 1;
|
|
} else if (_gobAction == 3 && _currentGoblin == 2 &&
|
|
(items & 0xff00) != 0) {
|
|
_destItemId = (items & 0xff00) >> 8;
|
|
_destActionItem = (items & 0xff00) >> 8;
|
|
_itemByteFlag = 1;
|
|
} else {
|
|
_destItemId = items & 0xff;
|
|
_destActionItem = items & 0xff;
|
|
_itemByteFlag = 0;
|
|
}
|
|
|
|
_pressedMapY = _vm->_map->_itemPoses[_destItemId].y;
|
|
_vm->_map->_destY = _vm->_map->_itemPoses[_destItemId].y;
|
|
_gobDestY = _vm->_map->_itemPoses[_destItemId].y;
|
|
|
|
if (_gobAction == 3 || _destActionItem == 0) {
|
|
_pressedMapX = _vm->_map->_itemPoses[_destItemId].x;
|
|
_vm->_map->_destX = _vm->_map->_itemPoses[_destItemId].x;
|
|
_gobDestX = _vm->_map->_itemPoses[_destItemId].x;
|
|
} else if ((items & 0xff00) != 0) {
|
|
if (_vm->_map->_itemPoses[_destItemId].orient == 4) {
|
|
if ((_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX - 1] & 0xff00) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX] & 0xff00)) {
|
|
_pressedMapX--;
|
|
_vm->_map->_destX = _pressedMapX;
|
|
_gobDestX = _pressedMapX;
|
|
}
|
|
} else if (_vm->_map->_itemPoses[_destItemId].orient == 0) {
|
|
|
|
if ((_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX + 1] & 0xff00) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX] & 0xff00)) {
|
|
_pressedMapX++;
|
|
_vm->_map->_destX = _pressedMapX;
|
|
_gobDestX = _pressedMapX;
|
|
}
|
|
}
|
|
|
|
if ((_vm->_map->_itemsMap[_pressedMapY +
|
|
1][_pressedMapX] & 0xff00) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] &
|
|
0xff00)) {
|
|
_pressedMapY++;
|
|
_vm->_map->_destY = _pressedMapY;
|
|
_gobDestY = _pressedMapY;
|
|
}
|
|
} else {
|
|
if (_vm->_map->_itemPoses[_destItemId].orient == 4) {
|
|
if ((_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX - 1]) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX])) {
|
|
_pressedMapX--;
|
|
_vm->_map->_destX = _pressedMapX;
|
|
_gobDestX = _pressedMapX;
|
|
}
|
|
} else if (_vm->_map->_itemPoses[_destItemId].orient == 0) {
|
|
|
|
if ((_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX + 1]) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY]
|
|
[_pressedMapX])) {
|
|
_pressedMapX++;
|
|
_vm->_map->_destX = _pressedMapX;
|
|
_gobDestX = _pressedMapX;
|
|
}
|
|
}
|
|
|
|
if (_pressedMapY < (_vm->_map->_mapHeight-1)) {
|
|
if ((_vm->_map->_itemsMap[_pressedMapY +
|
|
1][_pressedMapX]) ==
|
|
(_vm->_map->_itemsMap[_pressedMapY][_pressedMapX])) {
|
|
_pressedMapY++;
|
|
_vm->_map->_destY = _pressedMapY;
|
|
_gobDestY = _pressedMapY;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (_gobAction == 4 && _destActionItem != 0 &&
|
|
_itemToObject[_destActionItem] != -1 &&
|
|
_objects[_itemToObject[_destActionItem]]->
|
|
pickable == 1) {
|
|
|
|
itemDesc =
|
|
_objects[_itemToObject[_destActionItem]];
|
|
|
|
itemDesc->animation =
|
|
itemDesc->stateMach[itemDesc->state][0]->animation;
|
|
layer =
|
|
itemDesc->stateMach[itemDesc->state][itemDesc->
|
|
stateColumn]->layer;
|
|
|
|
_vm->_scenery->updateAnim(layer, 0, itemDesc->animation, 0,
|
|
itemDesc->xPos, itemDesc->yPos, 0);
|
|
|
|
tmpX = (_vm->_scenery->_toRedrawRight + _vm->_scenery->_toRedrawLeft) / 2;
|
|
tmpY = _vm->_scenery->_toRedrawBottom;
|
|
|
|
tmpPosY = tmpY / 6;
|
|
if ((tmpY % 3) < 3 && tmpPosY > 0)
|
|
tmpPosY--;
|
|
|
|
tmpPosX = tmpX / 12;
|
|
if ((tmpX % 12) < 6 && tmpPosX > 0)
|
|
tmpPosX--;
|
|
|
|
if (_vm->_map->_itemPoses[_destActionItem].orient == 0 ||
|
|
_vm->_map->_itemPoses[_destActionItem].orient == -1) {
|
|
tmpPosX++;
|
|
}
|
|
|
|
if (_vm->_map->getPass(tmpPosX, tmpPosY) == 1) {
|
|
_pressedMapX = tmpPosX;
|
|
_vm->_map->_destX = tmpPosX;
|
|
_gobDestX = tmpPosX;
|
|
|
|
_pressedMapY = tmpPosY;
|
|
_vm->_map->_destY = tmpPosY;
|
|
_gobDestY = tmpPosY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::moveFindItem(int16 posX, int16 posY) {
|
|
int16 i;
|
|
if (_gobAction == 3 || _gobAction == 4) {
|
|
for (i = 0; i < 20; i++) {
|
|
if (_objects[i] == 0)
|
|
continue;
|
|
|
|
if (_objects[i]->type != 0)
|
|
continue;
|
|
|
|
if (_objects[i]->left > posX)
|
|
continue;
|
|
|
|
if (_objects[i]->right < posX)
|
|
continue;
|
|
|
|
if (_objects[i]->top > posY)
|
|
continue;
|
|
|
|
if (_objects[i]->bottom < posY)
|
|
continue;
|
|
|
|
if (_objects[i]->right - _objects[i]->left < 40)
|
|
posX =
|
|
(_objects[i]->left +
|
|
_objects[i]->right) / 2;
|
|
|
|
if (_objects[i]->bottom - _objects[i]->top < 40)
|
|
posY =
|
|
(_objects[i]->top +
|
|
_objects[i]->bottom) / 2;
|
|
|
|
break;
|
|
}
|
|
|
|
_pressedMapX = MIN(posX / 12, _vm->_map->_mapWidth - 1);
|
|
_pressedMapY = MIN(posY / 6, _vm->_map->_mapHeight - 1);
|
|
|
|
if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0
|
|
&& i < 20) {
|
|
|
|
if (_vm->_map->_itemsMap[_pressedMapY +
|
|
1][_pressedMapX] != 0) {
|
|
_pressedMapY++;
|
|
} else if (_vm->_map->_itemsMap[_pressedMapY +
|
|
1][_pressedMapX + 1] != 0) {
|
|
_pressedMapX++;
|
|
_pressedMapY++;
|
|
} else
|
|
if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX +
|
|
1] != 0) {
|
|
_pressedMapX++;
|
|
} else if (_vm->_map->_itemsMap[_pressedMapY -
|
|
1][_pressedMapX + 1] != 0) {
|
|
_pressedMapX++;
|
|
_pressedMapY--;
|
|
} else if (_vm->_map->_itemsMap[_pressedMapY -
|
|
1][_pressedMapX] != 0) {
|
|
_pressedMapY--;
|
|
} else if (_vm->_map->_itemsMap[_pressedMapY -
|
|
1][_pressedMapX - 1] != 0) {
|
|
_pressedMapY--;
|
|
_pressedMapX--;
|
|
} else
|
|
if (_vm->_map->_itemsMap[_pressedMapY][_pressedMapX -
|
|
1] != 0) {
|
|
_pressedMapX--;
|
|
} else if (_vm->_map->_itemsMap[_pressedMapY +
|
|
1][_pressedMapX - 1] != 0) {
|
|
_pressedMapX--;
|
|
_pressedMapY++;
|
|
}
|
|
}
|
|
} else {
|
|
_pressedMapX = posX / 12;
|
|
_pressedMapY = posY / 6;
|
|
}
|
|
}
|
|
|
|
void Goblin::moveCheckSelect(int16 framesCount, Gob_Object * gobDesc, int16 *pGobIndex,
|
|
int16 *nextAct) {
|
|
if (gobDesc->right > _vm->_global->_inter_mouseX &&
|
|
gobDesc->left < _vm->_global->_inter_mouseX &&
|
|
gobDesc->bottom > _vm->_global->_inter_mouseY &&
|
|
gobDesc->bottom - 10 < _vm->_global->_inter_mouseY && _gobAction == 0) {
|
|
if (gobDesc->curLookDir & 4)
|
|
*nextAct = 16;
|
|
else
|
|
*nextAct = 23;
|
|
|
|
gobDesc->curFrame = framesCount - 1;
|
|
_pathExistence = 0;
|
|
} else {
|
|
*pGobIndex = peekGoblin(gobDesc);
|
|
|
|
if (*pGobIndex != 0) {
|
|
_pathExistence = 0;
|
|
} else if (_vm->_map->_curGoblinX == _pressedMapX &&
|
|
_vm->_map->_curGoblinY == _pressedMapY) {
|
|
|
|
if (_gobAction != 0)
|
|
_readyToAct = 1;
|
|
|
|
_pathExistence = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::moveInitStep(int16 framesCount, int16 action, int16 cont,
|
|
Gob_Object *gobDesc, int16 *pGobIndex, int16 *pNextAct) {
|
|
int16 posX;
|
|
int16 posY;
|
|
|
|
if (cont != 0 && _goesAtTarget == 0 &&
|
|
_readyToAct == 0 && VAR(59) == 0 &&
|
|
gobDesc->type != 1 &&
|
|
gobDesc->state != 10 && gobDesc->state != 11) {
|
|
if (gobDesc->state >= 40) {
|
|
gobDesc->curFrame = framesCount - 1;
|
|
}
|
|
|
|
_gobAction = action;
|
|
_forceNextState[0] = -1;
|
|
_forceNextState[1] = -1;
|
|
_forceNextState[2] = -1;
|
|
|
|
if (action == 3) {
|
|
posX = _vm->_global->_inter_mouseX + 6;
|
|
posY = _vm->_global->_inter_mouseY + 7;
|
|
} else if (action == 4) {
|
|
posX = _vm->_global->_inter_mouseX + 7;
|
|
posY = _vm->_global->_inter_mouseY + 12;
|
|
} else {
|
|
posX = _vm->_global->_inter_mouseX;
|
|
posY = _vm->_global->_inter_mouseY;
|
|
}
|
|
|
|
moveFindItem(posX, posY);
|
|
adjustDest(posX, posY);
|
|
adjustTarget();
|
|
|
|
_vm->_map->_destX = _pressedMapX;
|
|
_gobDestX = _pressedMapX;
|
|
|
|
_vm->_map->_destY = _pressedMapY;
|
|
_gobDestY = _pressedMapY;
|
|
|
|
targetDummyItem(gobDesc);
|
|
|
|
targetItem();
|
|
initiateMove(0);
|
|
|
|
moveCheckSelect(framesCount, gobDesc, pGobIndex, pNextAct);
|
|
} else {
|
|
|
|
if (_readyToAct != 0 &&
|
|
(_vm->_map->_curGoblinX != _pressedMapX ||
|
|
_vm->_map->_curGoblinY != _pressedMapY))
|
|
_readyToAct = 0;
|
|
|
|
if (gobDesc->type == 1) {
|
|
*pGobIndex = peekGoblin(gobDesc);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::moveTreatRopeStairs(Gob_Object *gobDesc) {
|
|
if (_currentGoblin != 1)
|
|
return;
|
|
|
|
if (gobDesc->nextState == 28
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6) {
|
|
_forceNextState[0] = 28;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
|
|
if (gobDesc->nextState == 29
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6) {
|
|
_forceNextState[0] = 29;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
|
|
if ((gobDesc->nextState == 28 || gobDesc->nextState == 29
|
|
|| gobDesc->nextState == 20)
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6) {
|
|
if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
|
|
|| gobDesc->curLookDir == 2)
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6) {
|
|
_forceNextState[0] = 28;
|
|
_forceNextState[1] = -1;
|
|
} else if ((gobDesc->curLookDir == 0
|
|
|| gobDesc->curLookDir == 4
|
|
|| gobDesc->curLookDir == 6)
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6) {
|
|
_forceNextState[0] = 29;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
}
|
|
|
|
if (gobDesc->nextState == 8
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 3) {
|
|
_forceNextState[0] = 8;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
|
|
if (gobDesc->nextState == 9
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 3) {
|
|
_forceNextState[0] = 9;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
|
|
if (gobDesc->nextState == 20
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) {
|
|
if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
|
|
|| gobDesc->curLookDir == 2)
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 3) {
|
|
_forceNextState[0] = 8;
|
|
_forceNextState[1] = -1;
|
|
} else if ((gobDesc->curLookDir == 0
|
|
|| gobDesc->curLookDir == 4
|
|
|| gobDesc->curLookDir == 6)
|
|
&& _vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 3) {
|
|
_forceNextState[0] = 9;
|
|
_forceNextState[1] = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int16 Goblin::doMove(Gob_Object *gobDesc, int16 cont, int16 action) {
|
|
int16 framesCount;
|
|
int16 nextAct;
|
|
int16 gobIndex;
|
|
int16 layer;
|
|
|
|
nextAct = 0;
|
|
gobIndex = 0;
|
|
|
|
layer = gobDesc->stateMach[gobDesc->state][0]->layer;
|
|
framesCount =
|
|
_vm->_scenery->_animations[gobDesc->animation].layers[layer]->framesCount;
|
|
|
|
if (VAR(59) == 0 &&
|
|
gobDesc->state != 30 && gobDesc->state != 31) {
|
|
gobDesc->order = (gobDesc->bottom) / 24 + 3;
|
|
}
|
|
|
|
if (_positionedGob != _currentGoblin) {
|
|
_vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
|
|
_vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;
|
|
}
|
|
|
|
_positionedGob = _currentGoblin;
|
|
|
|
gobDesc->animation =
|
|
gobDesc->stateMach[gobDesc->state][gobDesc->stateColumn]->
|
|
animation;
|
|
|
|
_gobStateLayer =
|
|
gobDesc->stateMach[gobDesc->state][gobDesc->stateColumn]->layer;
|
|
|
|
moveInitStep(framesCount, action, cont, gobDesc, &gobIndex,
|
|
&nextAct);
|
|
moveTreatRopeStairs(gobDesc);
|
|
moveAdvance(0, gobDesc, nextAct, framesCount);
|
|
|
|
return gobIndex;
|
|
}
|
|
|
|
void Goblin::zeroObjects(void) {
|
|
int16 i;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
_goblins[i] = 0;
|
|
|
|
for (i = 0; i < 20; i++)
|
|
_objects[i] = 0;
|
|
|
|
for (i = 0; i < 16; i++)
|
|
_soundData[i] = 0;
|
|
}
|
|
|
|
void Goblin::freeAllObjects(void) {
|
|
_vm->_util->deleteList(_objList);
|
|
_objList = 0;
|
|
freeObjects();
|
|
}
|
|
|
|
void Goblin::loadObjects(char *source) {
|
|
int16 i;
|
|
|
|
zeroObjects();
|
|
for (i = 0; i < 20; i++)
|
|
_itemToObject[i] = 100;
|
|
|
|
freeObjects();
|
|
initList();
|
|
strcpy(_vm->_map->_sourceFile, source);
|
|
|
|
_vm->_map->_sourceFile[strlen(_vm->_map->_sourceFile) - 4] = 0;
|
|
_vm->_map->loadMapObjects(source);
|
|
|
|
for (i = 0; i < _gobsCount; i++)
|
|
placeObject(_goblins[i], 0, 0, 0, 0, 0);
|
|
|
|
for (i = 0; i < _objCount; i++) {
|
|
placeObject(_objects[i], 1, 0, 0, 0, 0);
|
|
}
|
|
|
|
initVarPointers();
|
|
_actDestItemDesc = 0;
|
|
}
|
|
|
|
void Goblin::saveGobDataToVars(int16 xPos, int16 yPos, int16 someVal) {
|
|
Gob_Object *obj;
|
|
*_some0ValPtr = someVal;
|
|
*_curGobXPosVarPtr = xPos;
|
|
*_curGobYPosVarPtr = yPos;
|
|
*_itemInPocketVarPtr = _itemIndInPocket;
|
|
|
|
obj = _goblins[_currentGoblin];
|
|
|
|
*_curGobStateVarPtr = obj->state;
|
|
*_curGobFrameVarPtr = obj->curFrame;
|
|
*_curGobMultStateVarPtr = obj->multState;
|
|
*_curGobNextStateVarPtr = obj->nextState;
|
|
*_curGobScrXVarPtr = obj->xPos;
|
|
*_curGobScrYVarPtr = obj->yPos;
|
|
*_curGobLeftVarPtr = obj->left;
|
|
*_curGobTopVarPtr = obj->top;
|
|
*_curGobRightVarPtr = obj->right;
|
|
*_curGobBottomVarPtr = obj->bottom;
|
|
*_curGobDoAnimVarPtr = obj->doAnim;
|
|
*_curGobOrderVarPtr = obj->order;
|
|
*_curGobNoTickVarPtr = obj->noTick;
|
|
*_curGobTypeVarPtr = obj->type;
|
|
*_curGobMaxTickVarPtr = obj->maxTick;
|
|
*_curGobTickVarPtr = obj->tick;
|
|
*_curGobActStartStateVarPtr = obj->actionStartState;
|
|
*_curGobLookDirVarPtr = obj->curLookDir;
|
|
*_curGobPickableVarPtr = obj->pickable;
|
|
*_curGobRelaxVarPtr = obj->relaxTime;
|
|
*_curGobMaxFrameVarPtr = getObjMaxFrame(obj);
|
|
|
|
if (_actDestItemDesc == 0)
|
|
return;
|
|
|
|
obj = _actDestItemDesc;
|
|
*_destItemStateVarPtr = obj->state;
|
|
*_destItemFrameVarPtr = obj->curFrame;
|
|
*_destItemMultStateVarPtr = obj->multState;
|
|
*_destItemNextStateVarPtr = obj->nextState;
|
|
*_destItemScrXVarPtr = obj->xPos;
|
|
*_destItemScrYVarPtr = obj->yPos;
|
|
*_destItemLeftVarPtr = obj->left;
|
|
*_destItemTopVarPtr = obj->top;
|
|
*_destItemRightVarPtr = obj->right;
|
|
*_destItemBottomVarPtr = obj->bottom;
|
|
*_destItemDoAnimVarPtr = obj->doAnim;
|
|
*_destItemOrderVarPtr = obj->order;
|
|
*_destItemNoTickVarPtr = obj->noTick;
|
|
*_destItemTypeVarPtr = obj->type;
|
|
*_destItemMaxTickVarPtr = obj->maxTick;
|
|
*_destItemTickVarPtr = obj->tick;
|
|
*_destItemActStartStVarPtr = obj->actionStartState;
|
|
*_destItemLookDirVarPtr = obj->curLookDir;
|
|
*_destItemPickableVarPtr = obj->pickable;
|
|
*_destItemRelaxVarPtr = obj->relaxTime;
|
|
*_destItemMaxFrameVarPtr = getObjMaxFrame(obj);
|
|
|
|
_destItemState = obj->state;
|
|
_destItemType = obj->type;
|
|
}
|
|
|
|
void Goblin::initVarPointers(void) {
|
|
_gobRetVarPtr = (int32 *)VAR_ADDRESS(59);
|
|
_curGobStateVarPtr = (int32 *)VAR_ADDRESS(60);
|
|
_curGobFrameVarPtr = (int32 *)VAR_ADDRESS(61);
|
|
_curGobMultStateVarPtr = (int32 *)VAR_ADDRESS(62);
|
|
_curGobNextStateVarPtr = (int32 *)VAR_ADDRESS(63);
|
|
_curGobScrXVarPtr = (int32 *)VAR_ADDRESS(64);
|
|
_curGobScrYVarPtr = (int32 *)VAR_ADDRESS(65);
|
|
_curGobLeftVarPtr = (int32 *)VAR_ADDRESS(66);
|
|
_curGobTopVarPtr = (int32 *)VAR_ADDRESS(67);
|
|
_curGobRightVarPtr = (int32 *)VAR_ADDRESS(68);
|
|
_curGobBottomVarPtr = (int32 *)VAR_ADDRESS(69);
|
|
_curGobDoAnimVarPtr = (int32 *)VAR_ADDRESS(70);
|
|
_curGobOrderVarPtr = (int32 *)VAR_ADDRESS(71);
|
|
_curGobNoTickVarPtr = (int32 *)VAR_ADDRESS(72);
|
|
_curGobTypeVarPtr = (int32 *)VAR_ADDRESS(73);
|
|
_curGobMaxTickVarPtr = (int32 *)VAR_ADDRESS(74);
|
|
_curGobTickVarPtr = (int32 *)VAR_ADDRESS(75);
|
|
_curGobActStartStateVarPtr = (int32 *)VAR_ADDRESS(76);
|
|
_curGobLookDirVarPtr = (int32 *)VAR_ADDRESS(77);
|
|
_curGobPickableVarPtr = (int32 *)VAR_ADDRESS(80);
|
|
_curGobRelaxVarPtr = (int32 *)VAR_ADDRESS(81);
|
|
_destItemStateVarPtr = (int32 *)VAR_ADDRESS(82);
|
|
_destItemFrameVarPtr = (int32 *)VAR_ADDRESS(83);
|
|
_destItemMultStateVarPtr = (int32 *)VAR_ADDRESS(84);
|
|
_destItemNextStateVarPtr = (int32 *)VAR_ADDRESS(85);
|
|
_destItemScrXVarPtr = (int32 *)VAR_ADDRESS(86);
|
|
_destItemScrYVarPtr = (int32 *)VAR_ADDRESS(87);
|
|
_destItemLeftVarPtr = (int32 *)VAR_ADDRESS(88);
|
|
_destItemTopVarPtr = (int32 *)VAR_ADDRESS(89);
|
|
_destItemRightVarPtr = (int32 *)VAR_ADDRESS(90);
|
|
_destItemBottomVarPtr = (int32 *)VAR_ADDRESS(91);
|
|
_destItemDoAnimVarPtr = (int32 *)VAR_ADDRESS(92);
|
|
_destItemOrderVarPtr = (int32 *)VAR_ADDRESS(93);
|
|
_destItemNoTickVarPtr = (int32 *)VAR_ADDRESS(94);
|
|
_destItemTypeVarPtr = (int32 *)VAR_ADDRESS(95);
|
|
_destItemMaxTickVarPtr = (int32 *)VAR_ADDRESS(96);
|
|
_destItemTickVarPtr = (int32 *)VAR_ADDRESS(97);
|
|
_destItemActStartStVarPtr = (int32 *)VAR_ADDRESS(98);
|
|
_destItemLookDirVarPtr = (int32 *)VAR_ADDRESS(99);
|
|
_destItemPickableVarPtr = (int32 *)VAR_ADDRESS(102);
|
|
_destItemRelaxVarPtr = (int32 *)VAR_ADDRESS(103);
|
|
_destItemMaxFrameVarPtr = (int32 *)VAR_ADDRESS(105);
|
|
_curGobVarPtr = (int32 *)VAR_ADDRESS(106);
|
|
_some0ValPtr = (int32 *)VAR_ADDRESS(107);
|
|
_curGobXPosVarPtr = (int32 *)VAR_ADDRESS(108);
|
|
_curGobYPosVarPtr = (int32 *)VAR_ADDRESS(109);
|
|
_curGobMaxFrameVarPtr = (int32 *)VAR_ADDRESS(110);
|
|
|
|
_itemInPocketVarPtr = (int32 *)VAR_ADDRESS(114);
|
|
|
|
*_itemInPocketVarPtr = -2;
|
|
}
|
|
|
|
void Goblin::loadGobDataFromVars(void) {
|
|
Gob_Object *obj;
|
|
|
|
_itemIndInPocket = *_itemInPocketVarPtr;
|
|
|
|
obj = _goblins[_currentGoblin];
|
|
|
|
obj->state = *_curGobStateVarPtr;
|
|
obj->curFrame = *_curGobFrameVarPtr;
|
|
obj->multState = *_curGobMultStateVarPtr;
|
|
obj->nextState = *_curGobNextStateVarPtr;
|
|
obj->xPos = *_curGobScrXVarPtr;
|
|
obj->yPos = *_curGobScrYVarPtr;
|
|
obj->left = *_curGobLeftVarPtr;
|
|
obj->top = *_curGobTopVarPtr;
|
|
obj->right = *_curGobRightVarPtr;
|
|
obj->bottom = *_curGobBottomVarPtr;
|
|
obj->doAnim = *_curGobDoAnimVarPtr;
|
|
obj->order = *_curGobOrderVarPtr;
|
|
obj->noTick = *_curGobNoTickVarPtr;
|
|
obj->type = *_curGobTypeVarPtr;
|
|
obj->maxTick = *_curGobMaxTickVarPtr;
|
|
obj->tick = *_curGobTickVarPtr;
|
|
obj->actionStartState = *_curGobActStartStateVarPtr;
|
|
obj->curLookDir = *_curGobLookDirVarPtr;
|
|
obj->pickable = *_curGobPickableVarPtr;
|
|
obj->relaxTime = *_curGobRelaxVarPtr;
|
|
|
|
if (_actDestItemDesc == 0)
|
|
return;
|
|
|
|
obj = _actDestItemDesc;
|
|
|
|
obj->state = *_destItemStateVarPtr;
|
|
obj->curFrame = *_destItemFrameVarPtr;
|
|
obj->multState = *_destItemMultStateVarPtr;
|
|
obj->nextState = *_destItemNextStateVarPtr;
|
|
obj->xPos = *_destItemScrXVarPtr;
|
|
obj->yPos = *_destItemScrYVarPtr;
|
|
obj->left = *_destItemLeftVarPtr;
|
|
obj->top = *_destItemTopVarPtr;
|
|
obj->right = *_destItemRightVarPtr;
|
|
obj->bottom = *_destItemBottomVarPtr;
|
|
obj->doAnim = *_destItemDoAnimVarPtr;
|
|
obj->order = *_destItemOrderVarPtr;
|
|
obj->noTick = *_destItemNoTickVarPtr;
|
|
obj->type = *_destItemTypeVarPtr;
|
|
obj->maxTick = *_destItemMaxTickVarPtr;
|
|
obj->tick = *_destItemTickVarPtr;
|
|
obj->actionStartState = *_destItemActStartStVarPtr;
|
|
obj->curLookDir = *_destItemLookDirVarPtr;
|
|
obj->pickable = *_destItemPickableVarPtr;
|
|
obj->relaxTime = *_destItemRelaxVarPtr;
|
|
|
|
if (obj->type != _destItemType)
|
|
obj->toRedraw = 1;
|
|
|
|
if (obj->state != _destItemState && obj->type == 0)
|
|
obj->toRedraw = 1;
|
|
}
|
|
|
|
void Goblin::pickItem(int16 indexToPocket, int16 idToPocket) {
|
|
int16 x;
|
|
int16 y;
|
|
|
|
if (_objects[indexToPocket]->pickable != 1)
|
|
return;
|
|
|
|
_objects[indexToPocket]->type = 3;
|
|
|
|
_itemIndInPocket = indexToPocket;
|
|
_itemIdInPocket = idToPocket;
|
|
|
|
for (y = 0; y < _vm->_map->_mapHeight; y++) {
|
|
for (x = 0; x < _vm->_map->_mapWidth; x++) {
|
|
if (_itemByteFlag == 1) {
|
|
if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8) ==
|
|
idToPocket)
|
|
_vm->_map->_itemsMap[y][x] &= 0xff;
|
|
} else {
|
|
if ((_vm->_map->_itemsMap[y][x] & 0xff) == idToPocket)
|
|
_vm->_map->_itemsMap[y][x] &= 0xff00;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idToPocket >= 0 && idToPocket < 20) {
|
|
_vm->_map->_itemPoses[_itemIdInPocket].x = 0;
|
|
_vm->_map->_itemPoses[_itemIdInPocket].y = 0;
|
|
_vm->_map->_itemPoses[_itemIdInPocket].orient = 0;
|
|
}
|
|
}
|
|
|
|
void Goblin::placeItem(int16 indexInPocket, int16 idInPocket) {
|
|
Gob_Object *itemDesc;
|
|
int16 lookDir;
|
|
int16 xPos;
|
|
int16 yPos;
|
|
int16 layer;
|
|
|
|
itemDesc = _objects[indexInPocket];
|
|
lookDir = _goblins[0]->curLookDir & 4;
|
|
|
|
xPos = _gobPositions[0].x;
|
|
yPos = _gobPositions[0].y;
|
|
|
|
_itemIndInPocket = -1;
|
|
_itemIdInPocket = 0;
|
|
|
|
itemDesc->pickable = 1;
|
|
itemDesc->type = 0;
|
|
itemDesc->toRedraw = 1;
|
|
itemDesc->curFrame = 0;
|
|
itemDesc->order = _goblins[0]->order;
|
|
itemDesc->animation =
|
|
itemDesc->stateMach[itemDesc->state][0]->animation;
|
|
layer =
|
|
itemDesc->stateMach[itemDesc->state][itemDesc->stateColumn]->layer;
|
|
|
|
_vm->_scenery->updateAnim(layer, 0, itemDesc->animation, 0,
|
|
itemDesc->xPos, itemDesc->yPos, 0);
|
|
|
|
itemDesc->yPos +=
|
|
(_gobPositions[0].y * 6) + 5 - _vm->_scenery->_toRedrawBottom;
|
|
|
|
if (lookDir == 4) {
|
|
itemDesc->xPos += (_gobPositions[0].x * 12 + 14)
|
|
- (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
|
|
} else {
|
|
itemDesc->xPos += (_gobPositions[0].x * 12)
|
|
- (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
|
|
}
|
|
|
|
_vm->_map->placeItem(xPos, yPos, idInPocket);
|
|
|
|
if (yPos > 0) {
|
|
_vm->_map->placeItem(xPos, yPos - 1, idInPocket);
|
|
}
|
|
|
|
if (lookDir == 4) {
|
|
if (xPos < _vm->_map->_mapWidth - 1) {
|
|
_vm->_map->placeItem(xPos + 1, yPos, idInPocket);
|
|
|
|
if (yPos > 0) {
|
|
_vm->_map->placeItem(xPos + 1, yPos - 1, idInPocket);
|
|
}
|
|
}
|
|
} else {
|
|
if (xPos > 0) {
|
|
_vm->_map->placeItem(xPos - 1, yPos, idInPocket);
|
|
|
|
if (yPos > 0) {
|
|
_vm->_map->placeItem(xPos - 1, yPos - 1, idInPocket);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idInPocket >= 0 && idInPocket < 20) {
|
|
_vm->_map->_itemPoses[idInPocket].x = _gobPositions[0].x;
|
|
_vm->_map->_itemPoses[idInPocket].y = _gobPositions[0].y;
|
|
_vm->_map->_itemPoses[idInPocket].orient = lookDir;
|
|
if (_vm->_map->_itemPoses[idInPocket].orient == 0) {
|
|
// _vm->_map->_itemPoses[idInPocket].x++;
|
|
if (_vm->_map->getPass(_vm->_map->_itemPoses[idInPocket].x + 1, (int)_vm->_map->_itemPoses[idInPocket].y) == 1)
|
|
_vm->_map->_itemPoses[idInPocket].x++;
|
|
} else {
|
|
if (_vm->_map->getPass(_vm->_map->_itemPoses[idInPocket].x - 1, (int)_vm->_map->_itemPoses[idInPocket].y) == 1)
|
|
_vm->_map->_itemPoses[idInPocket].x--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::swapItems(int16 indexToPick, int16 idToPick) {
|
|
int16 layer;
|
|
Gob_Object *pickObj;
|
|
Gob_Object *placeObj;
|
|
int16 idToPlace;
|
|
int16 x;
|
|
int16 y;
|
|
|
|
pickObj = _objects[indexToPick];
|
|
placeObj = _objects[_itemIndInPocket];
|
|
|
|
idToPlace = _itemIdInPocket;
|
|
pickObj->type = 3;
|
|
_itemIndInPocket = indexToPick;
|
|
_itemIdInPocket = idToPick;
|
|
|
|
if (_itemByteFlag == 0) {
|
|
for (y = 0; y < _vm->_map->_mapHeight; y++) {
|
|
for (x = 0; x < _vm->_map->_mapWidth; x++) {
|
|
if ((_vm->_map->_itemsMap[y][x] & 0xff) == idToPick)
|
|
_vm->_map->_itemsMap[y][x] =
|
|
(_vm->_map->_itemsMap[y][x] & 0xff00) +
|
|
idToPlace;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
for (y = 0; y < _vm->_map->_mapHeight; y++) {
|
|
for (x = 0; x < _vm->_map->_mapWidth; x++) {
|
|
if (((_vm->_map->_itemsMap[y][x] & 0xff00) >> 8) ==
|
|
idToPick)
|
|
_vm->_map->_itemsMap[y][x] =
|
|
(_vm->_map->_itemsMap[y][x] & 0xff) +
|
|
(idToPlace << 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idToPick >= 0 && idToPick < 20) {
|
|
_vm->_map->_itemPoses[idToPlace].x =
|
|
_vm->_map->_itemPoses[_itemIdInPocket].x;
|
|
_vm->_map->_itemPoses[idToPlace].y =
|
|
_vm->_map->_itemPoses[_itemIdInPocket].y;
|
|
_vm->_map->_itemPoses[idToPlace].orient =
|
|
_vm->_map->_itemPoses[_itemIdInPocket].orient;
|
|
|
|
_vm->_map->_itemPoses[_itemIdInPocket].x = 0;
|
|
_vm->_map->_itemPoses[_itemIdInPocket].y = 0;
|
|
_vm->_map->_itemPoses[_itemIdInPocket].orient = 0;
|
|
}
|
|
|
|
_itemIndInPocket = -1;
|
|
_itemIdInPocket = 0;
|
|
|
|
placeObj->type = 0;
|
|
placeObj->nextState = -1;
|
|
placeObj->multState = -1;
|
|
placeObj->unk14 = 0;
|
|
placeObj->toRedraw = 1;
|
|
placeObj->curFrame = 0;
|
|
placeObj->order = _goblins[0]->order;
|
|
|
|
placeObj->animation =
|
|
placeObj->stateMach[placeObj->state][0]->animation;
|
|
|
|
layer =
|
|
placeObj->stateMach[placeObj->state][placeObj->stateColumn]->layer;
|
|
_vm->_scenery->updateAnim(layer, 0, placeObj->animation, 0, placeObj->xPos,
|
|
placeObj->yPos, 0);
|
|
|
|
placeObj->yPos +=
|
|
(_gobPositions[0].y * 6) + 5 - _vm->_scenery->_toRedrawBottom;
|
|
|
|
if (_vm->_map->_itemPoses[idToPlace].orient == 4) {
|
|
placeObj->xPos += (_gobPositions[0].x * 12 + 14)
|
|
- (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
|
|
} else {
|
|
placeObj->xPos += (_gobPositions[0].x * 12)
|
|
- (_vm->_scenery->_toRedrawLeft + _vm->_scenery->_toRedrawRight) / 2;
|
|
}
|
|
}
|
|
|
|
void Goblin::treatItemPick(int16 itemId) {
|
|
int16 itemIndex;
|
|
Gob_Object *gobDesc;
|
|
|
|
gobDesc = _goblins[_currentGoblin];
|
|
|
|
if (gobDesc->curFrame != 9)
|
|
return;
|
|
|
|
if (gobDesc->stateMach != gobDesc->realStateMach)
|
|
return;
|
|
|
|
_readyToAct = 0;
|
|
_goesAtTarget = 0;
|
|
|
|
itemIndex = _itemToObject[itemId];
|
|
if (itemId != 0 && itemIndex != -1
|
|
&& _objects[itemIndex]->pickable != 1)
|
|
itemIndex = -1;
|
|
|
|
if (_itemIndInPocket != -1 && _itemIndInPocket == itemIndex)
|
|
itemIndex = -1;
|
|
|
|
if (_itemIndInPocket != -1 && itemIndex != -1
|
|
&& _objects[itemIndex]->pickable == 1) {
|
|
swapItems(itemIndex, itemId);
|
|
_itemIndInPocket = itemIndex;
|
|
_itemIdInPocket = itemId;
|
|
return;
|
|
}
|
|
|
|
if (_itemIndInPocket != -1 && itemIndex == -1) {
|
|
placeItem(_itemIndInPocket, _itemIdInPocket);
|
|
return;
|
|
}
|
|
|
|
if (_itemIndInPocket == -1 && itemIndex != -1) {
|
|
pickItem(itemIndex, itemId);
|
|
return;
|
|
}
|
|
}
|
|
|
|
int16 Goblin::treatItem(int16 action) {
|
|
int16 state;
|
|
|
|
state = _goblins[_currentGoblin]->state;
|
|
if ((state == 10 || state == 11) &&
|
|
_goblins[_currentGoblin]->curFrame == 0) {
|
|
_readyToAct = 0;
|
|
}
|
|
|
|
if (action == 3 && _currentGoblin == 0 &&
|
|
(state == 10 || state == 11) && _goblins[0]->curFrame == 0) {
|
|
saveGobDataToVars(_gobPositions[_currentGoblin].x,
|
|
_gobPositions[_currentGoblin].y, 0);
|
|
_goesAtTarget = 1;
|
|
return -1;
|
|
}
|
|
|
|
if (_noPick == 0 && _currentGoblin == 0 &&
|
|
(state == 10 || state == 11)) {
|
|
treatItemPick(_destActionItem);
|
|
|
|
saveGobDataToVars(_gobPositions[_currentGoblin].x,
|
|
_gobPositions[_currentGoblin].y, 0);
|
|
return 0;
|
|
}
|
|
|
|
if (_goesAtTarget == 0) {
|
|
saveGobDataToVars(_gobPositions[_currentGoblin].x,
|
|
_gobPositions[_currentGoblin].y, 0);
|
|
return 0;
|
|
} else {
|
|
|
|
if (_itemToObject[_destActionItem] != 100 &&
|
|
_destActionItem != 0) {
|
|
|
|
if (_itemToObject[_destActionItem] == -1) {
|
|
_actDestItemDesc = 0;
|
|
} else {
|
|
_actDestItemDesc =
|
|
_objects[_itemToObject
|
|
[_destActionItem]];
|
|
}
|
|
}
|
|
|
|
_goesAtTarget = 0;
|
|
saveGobDataToVars(_gobPositions[_currentGoblin].x,
|
|
_gobPositions[_currentGoblin].y, 0);
|
|
return _destActionItem;
|
|
}
|
|
}
|
|
|
|
void Goblin::playSounds(Mult::Mult_Object *obj) {
|
|
int i;
|
|
Mult::Mult_AnimData *animData;
|
|
bool speaker;
|
|
int16 frequency;
|
|
int16 repCount;
|
|
int16 sndSlot;
|
|
int16 frame;
|
|
|
|
animData = obj->pAnimData;
|
|
|
|
for (i = 1; i <= obj->goblinStates[animData->state][0].dataCount; i++) {
|
|
speaker = obj->goblinStates[animData->state][i].speaker != 0;
|
|
if ((obj->goblinStates[animData->state][i].sndItem != -1) || (speaker == 1)) {
|
|
frame = obj->goblinStates[animData->state][i].sndFrame;
|
|
repCount = obj->goblinStates[animData->state][i].repCount;
|
|
frequency = obj->goblinStates[animData->state][i].freq;
|
|
if (animData->frame == frame) {
|
|
if (!speaker) {
|
|
sndSlot = obj->goblinStates[animData->state][i].sndItem;
|
|
_vm->_snd->stopSound(0);
|
|
if (sndSlot < _soundSlotsCount)
|
|
_vm->_snd->playSample(_vm->_game->_soundSamples[_soundSlots[sndSlot] & 0x7FFF],
|
|
repCount, frequency);
|
|
} else
|
|
_vm->_snd->speakerOn(frequency, repCount * 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void Goblin::sub_19BD3(void) {
|
|
Mult::Mult_Object *obj0;
|
|
Mult::Mult_Object *obj1;
|
|
Mult::Mult_AnimData *anim0;
|
|
Mult::Mult_AnimData *anim1;
|
|
int16 pass;
|
|
int16 gob1X;
|
|
int16 gob2X;
|
|
int16 gob1Y;
|
|
int16 gob2Y;
|
|
int16 var_A;
|
|
int16 var_C;
|
|
int16 di;
|
|
int16 si;
|
|
|
|
obj0 = &_vm->_mult->_objects[0];
|
|
obj1 = &_vm->_mult->_objects[1];
|
|
anim0 = obj0->pAnimData;
|
|
anim1 = obj1->pAnimData;
|
|
|
|
si = anim0->state;
|
|
di = anim1->state;
|
|
|
|
if (anim0->someFlag == 0) {
|
|
if ((_word_2F9BC == 0) && (anim0->isStatic == 0)) {
|
|
if ((VAR(_dword_2F9B6) == 0) && (si == 28)) {
|
|
si = _vm->_util->getRandom(3) + 24;
|
|
sub_195C7(0, si);
|
|
WRITE_VAR(_dword_2F9B6, 100);
|
|
} else
|
|
WRITE_VAR(_dword_2F9B6, VAR(_dword_2F9B6) - 1);
|
|
}
|
|
if ((si == 8) || (si == 9) || (si == 29))
|
|
anim0->curLookDir = 6;
|
|
}
|
|
if (anim1->someFlag == 0) {
|
|
if ((_word_2F9BA == 0) && (anim1->isStatic == 0)) {
|
|
if ((VAR(_dword_2F9B2) == 0) && (di == 28)) {
|
|
di = _vm->_util->getRandom(3) + 24;
|
|
sub_195C7(1, di);
|
|
WRITE_VAR(_dword_2F9B2, 100);
|
|
} else
|
|
WRITE_VAR(_dword_2F9B2, VAR(_dword_2F9B2) - 1);
|
|
}
|
|
if ((di == 8) || (di == 9) || (di == 29))
|
|
anim1->curLookDir = 6;
|
|
}
|
|
|
|
if ((anim0->someFlag == 1) && (anim0->isStatic == 0) &&
|
|
((anim0->state == 28) || (anim0->state == 29)))
|
|
anim0->curLookDir = 0;
|
|
if ((anim1->someFlag == 1) && (anim1->isStatic == 0) &&
|
|
((anim1->state == 28) || (anim1->state == 29)))
|
|
anim1->curLookDir = 0;
|
|
|
|
if (VAR(18) != ((uint32) -1)) {
|
|
if (anim0->layer == 44)
|
|
anim0->curLookDir = 4;
|
|
else if (anim0->layer == 45)
|
|
anim0->curLookDir = 0;
|
|
if (anim0->someFlag == 0)
|
|
anim0->curLookDir = 6;
|
|
}
|
|
if (VAR(19) != ((uint32) -1)) {
|
|
if (anim1->layer == 48)
|
|
anim1->curLookDir = 4;
|
|
else if (anim1->layer == 49)
|
|
anim1->curLookDir = 0;
|
|
if (anim1->someFlag == 0)
|
|
anim1->curLookDir = 6;
|
|
}
|
|
|
|
if ((anim0->layer == 45) && (anim0->curLookDir == 4) && (anim0->pathExistence == 5) &&
|
|
(VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
|
|
sub_195C7(0, 19);
|
|
}
|
|
if ((anim0->layer == 44) && (anim0->curLookDir == 0) && (anim0->pathExistence == 5) &&
|
|
(VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
|
|
sub_195C7(0, 16);
|
|
}
|
|
if ((anim1->layer == 49) && (anim1->curLookDir == 4) && (anim1->pathExistence == 5) &&
|
|
(VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
|
|
sub_195C7(1, 19);
|
|
}
|
|
if ((anim1->layer == 48) && (anim1->curLookDir == 0) && (anim1->pathExistence == 5) &&
|
|
(VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
|
|
sub_195C7(1, 16);
|
|
}
|
|
|
|
gob1X = obj0->goblinX;
|
|
gob2X = obj1->goblinX;
|
|
gob1Y = obj0->goblinY;
|
|
gob2Y = obj1->goblinY;
|
|
di = anim0->field_13;
|
|
si = anim0->field_14;
|
|
var_A = anim1->field_13;
|
|
var_C = anim1->field_14;
|
|
|
|
pass = _vm->_map->getPass(gob1X, gob1Y, 40);
|
|
if ((pass > 17) && (pass < 21))
|
|
warning("GOB2 Stub! sub_19AB7(anim0);");
|
|
pass = _vm->_map->getPass(gob2X, gob2Y, 40);
|
|
if ((pass > 17) && (pass < 21))
|
|
warning("GOB2 Stub! sub_19B45(anim1);");
|
|
|
|
if ((di < 0) || (di > 39) || (si < 0) || (si > 39))
|
|
return;
|
|
|
|
if (gob1Y > si) {
|
|
if (_vm->_map->getPass(di, si, 40) > 17) {
|
|
do {
|
|
si--;
|
|
} while (_vm->_map->getPass(di, si, 40) > 17);
|
|
si++;
|
|
if (_vm->_map->getPass(di - 1, si, 40) == 0) {
|
|
if (_vm->_map->getPass(di + 1, si, 40) != 0)
|
|
di++;
|
|
} else
|
|
di--;
|
|
warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di);
|
|
}
|
|
} else {
|
|
if (_vm->_map->getPass(di, si, 40) > 17) {
|
|
do {
|
|
si++;
|
|
} while (_vm->_map->getPass(di, si, 40) > 17);
|
|
si--;
|
|
if (_vm->_map->getPass(di - 1, si, 40) == 0) {
|
|
if (_vm->_map->getPass(di + 1, si, 40) != 0)
|
|
di++;
|
|
} else
|
|
di--;
|
|
warning("GOB2 Stub! sub_197A6(di (=%d), si (=%d), 0);", si, di);
|
|
}
|
|
}
|
|
if (gob2Y > var_C) {
|
|
if (_vm->_map->getPass(var_A, var_C, 40) > 17) {
|
|
do {
|
|
var_C--;
|
|
} while (_vm->_map->getPass(var_A, var_C, 40) > 17);
|
|
var_C++;
|
|
if (_vm->_map->getPass(var_A - 1, var_C, 40) == 0) {
|
|
if (_vm->_map->getPass(var_A + 1, var_C, 40) != 0)
|
|
var_A++;
|
|
} else
|
|
var_A--;
|
|
warning("GOB2 Stub! sub_197A6(var_A (=%d), var_C (=%d), 1);", var_A, var_C);
|
|
}
|
|
} else {
|
|
if (_vm->_map->getPass(var_A, var_C, 40) > 17) {
|
|
do {
|
|
var_C++;
|
|
} while (_vm->_map->getPass(var_A, var_C, 40) > 17);
|
|
var_C--;
|
|
if (_vm->_map->getPass(var_A - 1, var_C, 40) == 0) {
|
|
if (_vm->_map->getPass(var_A + 1, var_C, 40) != 0)
|
|
var_A++;
|
|
} else
|
|
var_A--;
|
|
warning("GOB2 Stub! sub_197A6(var_A (=%d), var_C (=%d), 1);", var_A, var_C);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Goblin::sub_195C7(int16 index, int16 state) {
|
|
Mult::Mult_Object *obj;
|
|
Mult::Mult_AnimData *animData;
|
|
int16 layer;
|
|
int16 animation;
|
|
|
|
obj = &_vm->_mult->_objects[index];
|
|
animData = obj->pAnimData;
|
|
|
|
if (obj->goblinStates[state] == 0)
|
|
return;
|
|
|
|
layer = obj->goblinStates[state][0].layer;
|
|
animation = obj->goblinStates[state][0].animation;
|
|
animData->layer = layer;
|
|
animData->animation = animation;
|
|
animData->state = state;
|
|
animData->frame = 0;
|
|
animData->isPaused = 0;
|
|
animData->isStatic = 0;
|
|
animData->newCycle = _vm->_scenery->_animations[animation].layers[layer]->framesCount;
|
|
_vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 1);
|
|
|
|
if (_vm->_map->_bigTiles) {
|
|
*obj->pPosY = ((obj->goblinY + 1) * _vm->_map->_tilesHeight) -
|
|
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop) -
|
|
(obj->goblinY + 1) / 2;
|
|
} else {
|
|
*obj->pPosY = (obj->goblinY + 1) * _vm->_map->_tilesHeight -
|
|
(_vm->_scenery->_animBottom - _vm->_scenery->_animTop);
|
|
}
|
|
*obj->pPosX = obj->goblinX * _vm->_map->_tilesWidth;
|
|
}
|
|
|
|
void Goblin::sub_11984(Mult::Mult_Object *obj) {
|
|
Mult::Mult_AnimData *animData;
|
|
int16 layer;
|
|
int16 animation;
|
|
int16 framesCount;
|
|
|
|
animData = obj->pAnimData;
|
|
|
|
if (animData->isStatic != 0)
|
|
return;
|
|
|
|
layer = obj->goblinStates[animData->state][0].layer;
|
|
animation = obj->goblinStates[animData->state][0].animation;
|
|
framesCount = _vm->_scenery->_animations[animation].layers[layer]->framesCount;
|
|
animData->newCycle = framesCount;
|
|
playSounds(obj);
|
|
|
|
if (animData->isPaused == 0)
|
|
animData->frame++;
|
|
|
|
switch (animData->field_16) {
|
|
case 0:
|
|
case 1:
|
|
animData->isPaused = 0;
|
|
break;
|
|
|
|
case 4:
|
|
if (animData->frame == 0)
|
|
animData->isPaused = 1;
|
|
break;
|
|
|
|
case 6:
|
|
if (animData->frame >= framesCount)
|
|
animData->isPaused = 1;
|
|
break;
|
|
}
|
|
|
|
if ((animData->field_F == -1) && (animData->frame >= framesCount)) {
|
|
if (animData->field_15 <= 0) {
|
|
animData->field_15 = animData->unknown;
|
|
animData->frame = 0;
|
|
} else
|
|
animData->field_15--;
|
|
}
|
|
|
|
if (animData->field_F != -1) {
|
|
animData->frame = 0;
|
|
animData->state = animData->field_F;
|
|
animData->field_F = -1;
|
|
animData->animation = obj->goblinStates[animData->state][0].animation;
|
|
animData->layer = obj->goblinStates[animData->state][0].layer;
|
|
*obj->pPosX += _vm->_scenery->_animations[animation].layers[layer]->animDeltaX;
|
|
*obj->pPosY += _vm->_scenery->_animations[animation].layers[layer]->animDeltaY;
|
|
animData->newCycle = _vm->_scenery->_animations[animation].layers[layer]->framesCount;
|
|
animData->isPaused = 0;
|
|
} else
|
|
animData->frame--;
|
|
}
|
|
|
|
} // End of namespace Gob
|