aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/goblin.cpp
diff options
context:
space:
mode:
authorMax Horn2006-02-11 22:45:04 +0000
committerMax Horn2006-02-11 22:45:04 +0000
commit26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch)
tree26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /engines/gob/goblin.cpp
parent2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff)
downloadscummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.gz
scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.bz2
scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.zip
Moved engines to the new engines/ directory
svn-id: r20582
Diffstat (limited to 'engines/gob/goblin.cpp')
-rw-r--r--engines/gob/goblin.cpp2381
1 files changed, 2381 insertions, 0 deletions
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
new file mode 100644
index 0000000000..f434c65a70
--- /dev/null
+++ b/engines/gob/goblin.cpp
@@ -0,0 +1,2381 @@
+/* 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"
+
+namespace Gob {
+
+Goblin::Goblin(GobEngine *vm) : _vm(vm) {
+ _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;
+
+ _rotStates[0][0] = 0; _rotStates[0][1] = 22; _rotStates[0][2] = 23; _rotStates[0][3] = 24;
+ _rotStates[1][0] = 13; _rotStates[1][1] = 2; _rotStates[1][2] = 12; _rotStates[1][3] = 14;
+ _rotStates[2][0] = 16; _rotStates[2][1] = 15; _rotStates[2][2] = 4; _rotStates[2][3] = 17;
+ _rotStates[3][0] = 27; _rotStates[3][1] = 25; _rotStates[3][2] = 26; _rotStates[3][3] = 6;
+
+ _boreCounter = 0;
+ _positionedGob = 5;
+
+ _noPick = 0;
+ _objList = 0;
+ int i;
+ 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;
+}
+
+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;
+ }
+ }
+}
+
+void Goblin::placeObject(Gob_Object *objDesc, char animated) {
+ int16 layer;
+
+ if (objDesc->stateMach[objDesc->state][0] != 0) {
+ objDesc->animation =
+ objDesc->stateMach[objDesc->state][0]->animation;
+
+ objDesc->noTick = 0;
+ objDesc->toRedraw = 1;
+ objDesc->doAnim = animated;
+
+ objDesc->maxTick = 1;
+ objDesc->tick = 1;
+ objDesc->curFrame = 0;
+ objDesc->type = 0;
+ objDesc->actionStartState = 0;
+ objDesc->nextState = -1;
+ objDesc->multState = -1;
+ objDesc->stateColumn = 0;
+ objDesc->curLookDir = 0;
+ objDesc->visible = 1;
+ objDesc->pickable = 0;
+ objDesc->unk14 = 0;
+
+ objDesc->relaxTime = _vm->_util->getRandom(30);
+
+ layer = objDesc->stateMach[objDesc->state][0]->layer;
+ _vm->_scenery->updateAnim(layer, 0, objDesc->animation, 0,
+ objDesc->xPos, objDesc->yPos, 0);
+
+ objDesc->order = _vm->_scenery->_toRedrawBottom / 24 + 3;
+
+ objDesc->left = objDesc->xPos;
+ objDesc->right = objDesc->xPos;
+ objDesc->dirtyLeft = objDesc->xPos;
+ objDesc->dirtyRight = objDesc->xPos;
+
+ objDesc->top = objDesc->yPos;
+ objDesc->bottom = objDesc->yPos;
+ objDesc->dirtyTop = objDesc->yPos;
+ objDesc->dirtyBottom = objDesc->yPos;
+
+ _vm->_util->listInsertBack(_objList, objDesc);
+ }
+}
+
+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;
+
+ debug(4, "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->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3 ||
+ _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 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->_passMap[_pressedMapY][_pressedMapX] == 0 &&
+ (_gobAction == 0
+ || _vm->_map->_itemsMap[_pressedMapY][_pressedMapX] == 0)) {
+
+ resDelta = -1;
+ resDeltaDir = 0;
+ resDeltaPix = 0;
+
+ for (i = 1;
+ i <= _pressedMapX
+ && _vm->_map->_passMap[_pressedMapY][_pressedMapX - i] == 0;
+ i++);
+
+ if (i <= _pressedMapX) {
+ resDeltaPix = (i - 1) * 12 + (posX % 12) + 1;
+ resDelta = i;
+ }
+
+ for (i = 1;
+ (i + _pressedMapX) < Map::kMapWidth
+ && _vm->_map->_passMap[_pressedMapY][_pressedMapX + i] == 0;
+ i++);
+
+ if (_pressedMapX + i < Map::kMapWidth) {
+ deltaPix = (i * 12) - (posX % 12);
+ if (resDelta == -1 || deltaPix < resDeltaPix) {
+ resDeltaPix = deltaPix;
+ resDelta = i;
+ resDeltaDir = 1;
+ }
+ }
+
+ for (i = 1;
+ (i + _pressedMapY) < Map::kMapHeight
+ && _vm->_map->_passMap[_pressedMapY + i][_pressedMapX] == 0;
+ i++);
+
+ if (_pressedMapY + i < Map::kMapHeight) {
+ deltaPix = (i * 6) - (posY % 6);
+ if (resDelta == -1 || deltaPix < resDeltaPix) {
+ resDeltaPix = deltaPix;
+ resDelta = i;
+ resDeltaDir = 2;
+ }
+ }
+
+ for (i = 1;
+ i <= _pressedMapY
+ && _vm->_map->_passMap[_pressedMapY - i][_pressedMapX] == 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 < Map::kMapWidth - 1
+ && _vm->_map->_itemsMap[_pressedMapY][_pressedMapX + 1] !=
+ 0) {
+ _pressedMapX++;
+ } else if (_pressedMapX < Map::kMapWidth - 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->_passMap[_pressedMapY][_pressedMapX] == 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 ((_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->_passMap[tmpPosY][tmpPosX] == 1) {
+ _pressedMapX = tmpPosX;
+ _vm->_map->_destX = tmpPosX;
+ _gobDestX = tmpPosX;
+
+ _pressedMapY = tmpPosY;
+ _vm->_map->_destY = tmpPosY;
+ _gobDestY = tmpPosY;
+ }
+ }
+ }
+}
+
+void Goblin::initiateMove(void) {
+ _vm->_map->findNearestToDest();
+ _vm->_map->findNearestToGob();
+ _vm->_map->optimizePoints();
+
+ _pathExistence = _vm->_map->checkDirectPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
+ _pressedMapX, _pressedMapY);
+
+ if (_pathExistence == 3) {
+ if (_vm->_map->checkLongPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
+ _pressedMapX, _pressedMapY,
+ _vm->_map->_nearestWayPoint, _vm->_map->_nearestDest) == 0) {
+ _pathExistence = 0;
+ } else {
+ _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x;
+ _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y;
+ }
+ }
+}
+
+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 = posX / 12;
+ _pressedMapY = posY / 6;
+
+ 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();
+
+ 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->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6) {
+ _forceNextState[0] = 28;
+ _forceNextState[1] = -1;
+ }
+
+ if (gobDesc->nextState == 29
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6) {
+ _forceNextState[0] = 29;
+ _forceNextState[1] = -1;
+ }
+
+ if ((gobDesc->nextState == 28 || gobDesc->nextState == 29
+ || gobDesc->nextState == 20)
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6) {
+ if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
+ || gobDesc->curLookDir == 2)
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6) {
+ _forceNextState[0] = 28;
+ _forceNextState[1] = -1;
+ } else if ((gobDesc->curLookDir == 0
+ || gobDesc->curLookDir == 4
+ || gobDesc->curLookDir == 6)
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6) {
+ _forceNextState[0] = 29;
+ _forceNextState[1] = -1;
+ }
+ }
+
+ if (gobDesc->nextState == 8
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 3) {
+ _forceNextState[0] = 8;
+ _forceNextState[1] = -1;
+ }
+
+ if (gobDesc->nextState == 9
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 3) {
+ _forceNextState[0] = 9;
+ _forceNextState[1] = -1;
+ }
+
+ if (gobDesc->nextState == 20
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) {
+ if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
+ || gobDesc->curLookDir == 2)
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 3) {
+ _forceNextState[0] = 8;
+ _forceNextState[1] = -1;
+ } else if ((gobDesc->curLookDir == 0
+ || gobDesc->curLookDir == 4
+ || gobDesc->curLookDir == 6)
+ && _vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 3) {
+ _forceNextState[0] = 9;
+ _forceNextState[1] = -1;
+ }
+ }
+
+}
+
+void Goblin::movePathFind(Gob_Object *gobDesc, int16 nextAct) {
+ if (_pathExistence == 1) {
+ _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
+ _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;
+
+ if (_vm->_map->_curGoblinX == _pressedMapX &&
+ _vm->_map->_curGoblinY == _pressedMapY && _gobAction != 0) {
+ _readyToAct = 1;
+ _pathExistence = 0;
+ }
+
+ nextAct = _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
+ _vm->_map->_destX, _vm->_map->_destY);
+
+ if (nextAct == 0)
+ _pathExistence = 0;
+ } else if (_pathExistence == 3) {
+ _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
+ _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;
+
+ if (_vm->_map->_curGoblinX == _gobDestX && _vm->_map->_curGoblinY == _gobDestY) {
+ _pathExistence = 1;
+ _vm->_map->_destX = _pressedMapX;
+ _vm->_map->_destY = _pressedMapY;
+ } else {
+
+ if (_vm->_map->checkDirectPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
+ _gobDestX, _gobDestY) == 1) {
+ _vm->_map->_destX = _gobDestX;
+ _vm->_map->_destY = _gobDestY;
+ } else if (_vm->_map->_curGoblinX == _vm->_map->_destX && _vm->_map->_curGoblinY == _vm->_map->_destY) {
+
+ if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) {
+ _vm->_map->optimizePoints();
+
+ _vm->_map->_destX =
+ _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
+ x;
+ _vm->_map->_destY =
+ _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
+ y;
+
+ if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest)
+ _vm->_map->_nearestWayPoint--;
+ } else if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) {
+ _vm->_map->optimizePoints();
+
+ _vm->_map->_destX =
+ _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
+ x;
+ _vm->_map->_destY =
+ _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
+ y;
+
+ if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest)
+ _vm->_map->_nearestWayPoint++;
+ } else {
+ if (_vm->_map->checkDirectPath(_vm->_map->_curGoblinX,
+ _vm->_map->_curGoblinY, _gobDestX,
+ _gobDestY) == 3 && _vm->_map->_passMap[_pressedMapY][_pressedMapX] != 0) {
+ _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x;
+ _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y;
+ } else {
+ _pathExistence = 1;
+ _vm->_map->_destX = _pressedMapX;
+ _vm->_map->_destY = _pressedMapY;
+ }
+ }
+ }
+ nextAct =
+ _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
+ _vm->_map->_destX, _vm->_map->_destY);
+ }
+ }
+
+ if (_readyToAct != 0 && (_gobAction == 3 || _gobAction == 4))
+ nextAct = 0x4dc8;
+
+ switch (nextAct) {
+ case Map::kDirW:
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 0);
+ break;
+
+ case Map::kDirE:
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 4);
+ break;
+
+ case 16:
+ gobDesc->nextState = 16;
+ break;
+
+ case 23:
+ gobDesc->nextState = 23;
+ break;
+
+ case Map::kDirN:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) {
+ gobDesc->nextState = 8;
+ break;
+ }
+
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6 &&
+ _currentGoblin == 1) {
+ gobDesc->nextState = 28;
+ break;
+ }
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 2);
+ break;
+
+ case Map::kDirS:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3) {
+ gobDesc->nextState = 9;
+ break;
+ }
+
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6 &&
+ _currentGoblin == 1) {
+ gobDesc->nextState = 29;
+ break;
+ }
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 6);
+ break;
+
+ case Map::kDirSE:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX + 1] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ gobDesc->nextState = 5;
+ if (gobDesc->curLookDir == 4)
+ break;
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 4);
+ break;
+
+ case Map::kDirSW:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY + 1][_vm->_map->_curGoblinX - 1] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ gobDesc->nextState = 7;
+ if (gobDesc->curLookDir == 0)
+ break;
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 0);
+ break;
+
+ case Map::kDirNW:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX - 1] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ gobDesc->nextState = 1;
+ if (gobDesc->curLookDir == 0)
+ break;
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 0);
+ break;
+
+ case Map::kDirNE:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY - 1][_vm->_map->_curGoblinX + 1] == 6 &&
+ _currentGoblin != 1) {
+ _pathExistence = 0;
+ break;
+ }
+
+ gobDesc->nextState = 3;
+ if (gobDesc->curLookDir == 4)
+ break;
+
+ gobDesc->nextState = rotateState(gobDesc->curLookDir, 4);
+ break;
+
+ case 0x4dc8:
+
+ if (_currentGoblin == 0 && _gobAction == 3
+ && _itemIndInPocket == -1) {
+ _destItemId = -1;
+ _readyToAct = 0;
+ break;
+ }
+
+ if (_currentGoblin == 0 && _gobAction == 4 &&
+ _itemIndInPocket == -1 && _destActionItem == 0) {
+ gobDesc->multState = 104;
+ _destItemId = -1;
+ _readyToAct = 0;
+ break;
+ }
+
+ if (_currentGoblin == 0 && _gobAction == 4 &&
+ _itemIndInPocket == -1 && _destActionItem != 0 &&
+ _itemToObject[_destActionItem] != -1 &&
+ _objects[_itemToObject[_destActionItem]]->
+ pickable == 0) {
+ gobDesc->multState = 104;
+ _destItemId = -1;
+ _readyToAct = 0;
+ break;
+ }
+
+ switch (_vm->_map->_itemPoses[_destActionItem].orient) {
+ case 0:
+ case -4:
+ gobDesc->nextState = 10;
+ gobDesc->curLookDir = 0;
+ _destItemId = -1;
+ break;
+
+ case -1:
+ case 4:
+ gobDesc->nextState = 11;
+ gobDesc->curLookDir = 4;
+ _destItemId = -1;
+ break;
+ }
+ break;
+
+ default:
+ if (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 3 ||
+ (_vm->_map->_passMap[_vm->_map->_curGoblinY][_vm->_map->_curGoblinX] == 6
+ && _currentGoblin == 1)) {
+ gobDesc->nextState = 20;
+ break;
+ }
+
+ switch (gobDesc->curLookDir) {
+ case 2:
+ case 4:
+ gobDesc->nextState = 18;
+ break;
+
+ case 6:
+ case 0:
+ gobDesc->nextState = 19;
+ break;
+ }
+ break;
+ }
+ return;
+}
+
+void Goblin::moveAdvance(Gob_Object *gobDesc, int16 nextAct, int16 framesCount) {
+ int16 i;
+ int16 newX;
+ int16 newY;
+ int16 flag;
+
+ movePathFind(gobDesc, nextAct);
+
+ gobDesc->curFrame++;
+ if (gobDesc->curFrame == 1)
+ gobDesc->actionStartState = gobDesc->state;
+
+ if (_goesAtTarget == 0
+ && gobDesc->stateMach == gobDesc->realStateMach) {
+ switch (gobDesc->state) {
+ case 0:
+ case 1:
+ case 7:
+ case 13:
+ case 16:
+ case 27:
+ gobDesc->curLookDir = 0;
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ case 12:
+ case 23:
+ case 26:
+ gobDesc->curLookDir = 4;
+ break;
+
+ case 28:
+ if (_currentGoblin != 1)
+ break;
+ gobDesc->curLookDir = 2;
+ break;
+
+ case 2:
+ case 8:
+ case 15:
+ case 22:
+ case 25:
+ gobDesc->curLookDir = 2;
+ break;
+
+ case 29:
+ if (_currentGoblin != 1)
+ break;
+
+ gobDesc->curLookDir = 6;
+ break;
+
+ case 6:
+ case 9:
+ case 14:
+ case 17:
+ case 24:
+ gobDesc->curLookDir = 6;
+ break;
+ }
+ }
+
+ if (gobDesc->state >= 0 && gobDesc->state < 10 &&
+ gobDesc->stateMach == gobDesc->realStateMach &&
+ (gobDesc->curFrame == 3 || gobDesc->curFrame == 6)) {
+ _vm->_snd->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5);
+ }
+
+ if (_currentGoblin == 0
+ && gobDesc->stateMach == gobDesc->realStateMach
+ && (gobDesc->state == 10 || gobDesc->state == 11)
+ && gobDesc->curFrame == 9) {
+ _vm->_snd->stopSound(0);
+ if (_itemIndInPocket != -1) {
+ _vm->_snd->playSample(_soundData[14], 1, 9000);
+ }
+
+ if (_itemIndInPocket == -1) {
+ _vm->_snd->playSample(_soundData[14], 1, 5000);
+ }
+ }
+
+ if (_boreCounter++ == 120) {
+ _boreCounter = 0;
+ for (i = 0; i < 3; i++)
+ showBoredom(i);
+ }
+
+ if (gobDesc->multState != -1 && gobDesc->curFrame == framesCount &&
+ gobDesc->state != gobDesc->multState) {
+ gobDesc->nextState = gobDesc->multState;
+ gobDesc->multState = -1;
+
+ newX =
+ _vm->_scenery->_animations[gobDesc->animation].
+ layers[_gobStateLayer]->animDeltaX + gobDesc->xPos;
+
+ newY =
+ _vm->_scenery->_animations[gobDesc->animation].
+ layers[_gobStateLayer]->animDeltaY + gobDesc->yPos;
+
+ _gobStateLayer = nextLayer(gobDesc);
+
+ gobDesc->xPos = newX;
+ gobDesc->yPos = newY;
+ } else {
+ if (gobDesc->curFrame == 3 &&
+ gobDesc->stateMach == gobDesc->realStateMach &&
+ (gobDesc->state < 10 ||
+ (_currentGoblin == 1 && (gobDesc->state == 28
+ || gobDesc->state == 29))
+ )) {
+ flag = 0;
+ if (_forceNextState[0] != -1) {
+ gobDesc->nextState = _forceNextState[0];
+ for (i = 0; i < 9; i++)
+ _forceNextState[i] =
+ _forceNextState[i + 1];
+ }
+
+ _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
+ _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;
+
+ if (gobDesc->nextState != gobDesc->state) {
+ _gobStateLayer = nextLayer(gobDesc);
+ flag = 1;
+ }
+
+ switch (gobDesc->state) {
+ case 0:
+ _gobPositions[_currentGoblin].x--;
+ break;
+
+ case 2:
+ case 8:
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 4:
+ _gobPositions[_currentGoblin].x++;
+ break;
+
+ case 6:
+ case 9:
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 1:
+ _gobPositions[_currentGoblin].x--;
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 3:
+ _gobPositions[_currentGoblin].x++;
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 5:
+ _gobPositions[_currentGoblin].x++;
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 7:
+ _gobPositions[_currentGoblin].x--;
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 38:
+ _gobPositions[_currentGoblin].y++;
+ break;
+ }
+
+ if (_currentGoblin == 1) {
+ if (gobDesc->state == 28)
+ _gobPositions[1].y--;
+
+ if (gobDesc->state == 29)
+ _gobPositions[1].y++;
+ }
+
+ if (flag != 0) {
+ _vm->_scenery->updateAnim(_gobStateLayer, 0,
+ gobDesc->animation, 0, gobDesc->xPos,
+ gobDesc->yPos, 0);
+
+ gobDesc->yPos =
+ (_vm->_map->_curGoblinY + 1) * 6 -
+ (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
+ gobDesc->xPos =
+ _vm->_map->_curGoblinX * 12 - (_vm->_scenery->_toRedrawLeft -
+ _vm->_scenery->_animLeft);
+ }
+
+ if ((gobDesc->state == 10 || gobDesc->state == 11)
+ && _currentGoblin != 0)
+ _goesAtTarget = 1;
+ }
+
+ if (gobDesc->curFrame != framesCount)
+ return;
+
+ if (_forceNextState[0] != -1) {
+ gobDesc->nextState = _forceNextState[0];
+ for (i = 0; i < 10; i++)
+ _forceNextState[i] =
+ _forceNextState[i + 1];
+ }
+
+ _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
+ _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;
+
+ _gobStateLayer = nextLayer(gobDesc);
+ if (gobDesc->stateMach == gobDesc->realStateMach) {
+
+ switch (gobDesc->nextState) {
+ case 0:
+ _gobPositions[_currentGoblin].x--;
+ break;
+
+ case 2:
+ case 8:
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 4:
+ _gobPositions[_currentGoblin].x++;
+ break;
+
+ case 6:
+ case 9:
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 1:
+ _gobPositions[_currentGoblin].x--;
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 3:
+ _gobPositions[_currentGoblin].x++;
+ _gobPositions[_currentGoblin].y--;
+ break;
+
+ case 5:
+ _gobPositions[_currentGoblin].x++;
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 7:
+ _gobPositions[_currentGoblin].x--;
+ _gobPositions[_currentGoblin].y++;
+ break;
+
+ case 38:
+ _gobPositions[_currentGoblin].y++;
+ break;
+ }
+ if (_currentGoblin == 1) {
+ if (gobDesc->nextState == 28)
+ _gobPositions[1].y--;
+
+ if (gobDesc->nextState == 29)
+ _gobPositions[1].y++;
+ }
+ }
+
+ _vm->_scenery->updateAnim(_gobStateLayer, 0, gobDesc->animation, 0,
+ gobDesc->xPos, gobDesc->yPos, 0);
+
+ gobDesc->yPos =
+ (_vm->_map->_curGoblinY + 1) * 6 - (_vm->_scenery->_toRedrawBottom -
+ _vm->_scenery->_animTop);
+ gobDesc->xPos =
+ _vm->_map->_curGoblinX * 12 - (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
+
+ if ((gobDesc->state == 10 || gobDesc->state == 11)
+ && _currentGoblin != 0)
+ _goesAtTarget = 1;
+ }
+ return;
+}
+
+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(gobDesc, nextAct, framesCount);
+
+ return gobIndex;
+}
+
+void Goblin::freeObjects(void) {
+ int16 i;
+ int16 state;
+ int16 col;
+
+ for (i = 0; i < 16; i++) {
+ if (_soundData[i] == 0)
+ continue;
+
+ _vm->_snd->freeSoundData(_soundData[i]);
+ _soundData[i] = 0;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (_goblins[i] == 0)
+ continue;
+
+ _goblins[i]->stateMach = _goblins[i]->realStateMach;
+
+ for (state = 0; state < 40; state++) {
+ for (col = 0; col < 6; col++) {
+ delete _goblins[i]->stateMach[state][col];
+ _goblins[i]->stateMach[state][col] = 0;
+ }
+ }
+
+ if (i == 3) {
+ for (state = 40; state < 70; state++) {
+ delete _goblins[3]->stateMach[state][0];
+ _goblins[3]->stateMach[state][0] = 0;
+ }
+ }
+
+ delete[] _goblins[i]->stateMach;
+ delete _goblins[i];
+ _goblins[i] = 0;
+ }
+
+ for (i = 0; i < 20; i++) {
+ if (_objects[i] == 0)
+ continue;
+
+ _objects[i]->stateMach = _objects[i]->realStateMach;
+
+ for (state = 0; state < 40; state++) {
+ for (col = 0; col < 6; col++) {
+ delete _objects[i]->stateMach[state][col];
+ _objects[i]->stateMach[state][col] = 0;
+ }
+ }
+
+ delete[] _objects[i]->stateMach;
+ delete _objects[i];
+ _objects[i] = 0;
+ }
+}
+
+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);
+ 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);
+
+ for (i = 0; i < _objCount; i++) {
+ placeObject(_objects[i], 1);
+ }
+
+ 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 < Map::kMapHeight; y++) {
+ for (x = 0; x < Map::kMapWidth; 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 < Map::kMapWidth - 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->_passMap[(int)_vm->_map->_itemPoses[idInPocket].y][_vm->_map->_itemPoses[idInPocket].x + 1] == 1)
+ _vm->_map->_itemPoses[idInPocket].x++;
+ } else {
+ if (_vm->_map->_passMap[(int)_vm->_map->_itemPoses[idInPocket].y][_vm->_map->_itemPoses[idInPocket].x - 1] == 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 < Map::kMapHeight; y++) {
+ for (x = 0; x < Map::kMapWidth; 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 < Map::kMapHeight; y++) {
+ for (x = 0; x < Map::kMapWidth; 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;
+ }
+}
+
+} // End of namespace Gob