diff options
Diffstat (limited to 'engines/gob/goblin.cpp')
-rw-r--r-- | engines/gob/goblin.cpp | 2381 |
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 |