Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

goblin.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-2005 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.
 *
 * $Header: /cvsroot/scummvm/scummvm/gob/goblin.cpp,v 1.21.2.1 2005/10/18 02:11:18 sev Exp $
 *
 */
#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"

namespace Gob {

Util_List *gob_objList;
Gob_Object *gob_goblins[4];
int16 gob_currentGoblin;
Snd_SoundDesc *gob_soundData[16];
int16 gob_gobStateLayer;
char gob_goesAtTarget = 0;
char gob_readyToAct = 0;
int16 gob_gobAction = 0;
Gob_Pos gob_gobPositions[3];
int16 gob_gobDestX;
int16 gob_gobDestY;
int16 gob_pressedMapX;
int16 gob_pressedMapY;
char gob_pathExistence;

int16 gob_itemIndInPocket = 5;
int16 gob_itemIdInPocket = 2;
char gob_itemByteFlag = 0;
int16 gob_destItemId = -1;
int16 gob_destActionItem = 0;
Gob_Object *gob_actDestItemDesc = 0;
int16 gob_forceNextState[10] = {
      -1, -1, -1, -1, -1, -1, -1, 0, 0, 0
};

char gob_rotStates[4][4] = {
      {0, 22, 23, 24},
      {13, 2, 12, 14},
      {16, 15, 4, 17},
      {27, 25, 26, 6}
};

int16 gob_destItemType;
int16 gob_destItemState;
// Pointers to interpreter variables
int32 *gob_some0ValPtr;

int32 *gob_gobRetVarPtr;
int32 *gob_curGobVarPtr;
int32 *gob_curGobXPosVarPtr;
int32 *gob_curGobYPosVarPtr;
int32 *gob_itemInPocketVarPtr;
int32 *gob_curGobStateVarPtr;
int32 *gob_curGobFrameVarPtr;
int32 *gob_curGobMultStateVarPtr;
int32 *gob_curGobNextStateVarPtr;
int32 *gob_curGobScrXVarPtr;
int32 *gob_curGobScrYVarPtr;
int32 *gob_curGobLeftVarPtr;
int32 *gob_curGobTopVarPtr;
int32 *gob_curGobRightVarPtr;
int32 *gob_curGobBottomVarPtr;
int32 *gob_curGobDoAnimVarPtr;
int32 *gob_curGobOrderVarPtr;
int32 *gob_curGobNoTickVarPtr;
int32 *gob_curGobTypeVarPtr;
int32 *gob_curGobMaxTickVarPtr;
int32 *gob_curGobTickVarPtr;
int32 *gob_curGobActStartStateVarPtr;
int32 *gob_curGobLookDirVarPtr;
int32 *gob_curGobPickableVarPtr;
int32 *gob_curGobRelaxVarPtr;
int32 *gob_curGobMaxFrameVarPtr;

int32 *gob_destItemStateVarPtr;
int32 *gob_destItemFrameVarPtr;
int32 *gob_destItemMultStateVarPtr;
int32 *gob_destItemNextStateVarPtr;
int32 *gob_destItemScrXVarPtr;
int32 *gob_destItemScrYVarPtr;
int32 *gob_destItemLeftVarPtr;
int32 *gob_destItemTopVarPtr;
int32 *gob_destItemRightVarPtr;
int32 *gob_destItemBottomVarPtr;
int32 *gob_destItemDoAnimVarPtr;
int32 *gob_destItemOrderVarPtr;
int32 *gob_destItemNoTickVarPtr;
int32 *gob_destItemTypeVarPtr;
int32 *gob_destItemMaxTickVarPtr;
int32 *gob_destItemTickVarPtr;
int32 *gob_destItemActStartStVarPtr;
int32 *gob_destItemLookDirVarPtr;
int32 *gob_destItemPickableVarPtr;
int32 *gob_destItemRelaxVarPtr;
int32 *gob_destItemMaxFrameVarPtr;

//
int16 gob_itemToObject[20];
Gob_Object *gob_objects[20];
int16 gob_objCount;
int16 gob_gobsCount;
char gob_boreCounter = 0;
int16 gob_positionedGob = 5;

char gob_noPick = 0;

char gob_rotateState(int16 from, int16 to) {
      return gob_rotStates[from / 2][to / 2];
}

int16 gob_peekGoblin(Gob_Object *curGob) {
      Util_ListNode *ptr;
      Gob_Object *desc;
      int16 index;
      int16 i;

      ptr = gob_objList->pHead;
      index = 0;
      while (ptr != 0) {
            desc = (Gob_Object *) ptr->pData;
            if (desc != curGob) {
                  for (i = 0; i < 3; i++) {
                        if (desc != gob_goblins[i])
                              continue;

                        if (inter_mouseX < desc->right &&
                            inter_mouseX > desc->left &&
                            inter_mouseY < desc->bottom &&
                            inter_mouseY > desc->top) {
                              index = i + 1;
                        }
                  }
            }
            ptr = ptr->pNext;
      }
      return index;
}

void gob_initList(void) {
      gob_objList = (Util_List *) malloc(sizeof(Util_List));
      gob_objList->pHead = 0;
      gob_objList->pTail = 0;
}

void gob_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 != gob_goblins[gob_currentGoblin])
                                    continue;
                        }
                  }

                  SWAP(ptr->pData, ptr2->pData);
            }
            ptr = ptr->pNext;
      }
}

void gob_playSound(Snd_SoundDesc *snd, int16 repCount, int16 freq) {
      if (snd != 0) {
            snd_stopSound(0);
            snd_playSample(snd, repCount, freq);
      }
}

void gob_drawObjects(void) {
      Util_ListNode *ptr;
      Util_ListNode *ptr2;

      Gob_Object *objDesc;
      Gob_Object *gobDesc2;
      int16 layer;

      ptr = gob_objList->pHead;
      for (ptr = gob_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 = gob_objList->pHead; ptr != 0; ptr = ptr->pNext) {
            objDesc = (Gob_Object *) ptr->pData;
            if (objDesc->toRedraw == 0)
                  continue;

            vid_drawSprite(anim_underAnimSurf, draw_backSurface,
                objDesc->left, objDesc->top, objDesc->right,
                objDesc->bottom, objDesc->left, objDesc->top, 0);

            draw_invalidateRect(objDesc->left, objDesc->top,
                objDesc->right, objDesc->bottom);

            if (objDesc->type != 0)
                  continue;

            layer =
                objDesc->stateMach[objDesc->state][objDesc->stateColumn]->
                layer;
            scen_updateAnim(layer, objDesc->curFrame, objDesc->animation,
                0, objDesc->xPos, objDesc->yPos, 0);

            if (scen_toRedrawLeft == -12345) {
                  objDesc->dirtyLeft = objDesc->left;
                  objDesc->dirtyRight = objDesc->right;
                  objDesc->dirtyTop = objDesc->top;
                  objDesc->dirtyBottom = objDesc->bottom;
            } else {
                  objDesc->dirtyLeft =
                      MIN(objDesc->left, scen_toRedrawLeft);
                  objDesc->dirtyRight =
                      MAX(objDesc->right, scen_toRedrawRight);
                  objDesc->dirtyTop =
                      MIN(objDesc->top, scen_toRedrawTop);
                  objDesc->dirtyBottom =
                      MAX(objDesc->bottom, scen_toRedrawBottom);
            }

            objDesc->dirtyLeft = 0;
            objDesc->dirtyRight = 319;
            objDesc->dirtyTop = 0;
            objDesc->dirtyBottom = 199;
      }

      gob_sortByOrder(gob_objList);
      for (ptr = gob_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) {
                              scen_updateAnim(layer,
                                  objDesc->curFrame,
                                  objDesc->animation, 0,
                                  objDesc->xPos, objDesc->yPos, 0);

                        } else {
                              scen_updateAnim(layer,
                                  objDesc->curFrame,
                                  objDesc->animation, 2,
                                  objDesc->xPos, objDesc->yPos, 1);
                        }
                        if (scen_toRedrawLeft == -12345) {
                              objDesc->left = 0;
                              objDesc->top = 0;
                              objDesc->right = 0;
                              objDesc->bottom = 0;
                        } else {
                              draw_invalidateRect(scen_toRedrawLeft,
                                  scen_toRedrawTop,
                                  scen_toRedrawRight,
                                  scen_toRedrawBottom);

                              objDesc->left = scen_toRedrawLeft;
                              objDesc->top = scen_toRedrawTop;
                              objDesc->right = scen_toRedrawRight;
                              objDesc->bottom = scen_toRedrawBottom;
                              scen_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 = gob_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;

                        scen_toRedrawLeft = gobDesc2->dirtyLeft;
                        scen_toRedrawRight = gobDesc2->dirtyRight;
                        scen_toRedrawTop = gobDesc2->dirtyTop;
                        scen_toRedrawBottom = gobDesc2->dirtyBottom;

                        layer =
                            objDesc->stateMach[objDesc->
                            state][objDesc->stateColumn]->layer;

                        scen_updateAnim(layer, objDesc->curFrame,
                            objDesc->animation, 4, objDesc->xPos,
                            objDesc->yPos, 1);

                        scen_updateStatic(objDesc->order);
                  }
            }
      }

      for (ptr = gob_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) {
                              gob_playSound(gob_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) {
                              gob_playSound(gob_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) {
                              gob_playSound(gob_soundData[sndItem],
                                  repCount, freq);
                        }
                  }
            }
      }

//      scen_updateAnim(27, 0, 9, 2, 10, 10, 1);
}

void gob_animateObjects(void) {
      Util_ListNode *node;
      Gob_Object *objDesc;
      Scen_AnimLayer *pLayer;
      int16 layer;

      for (node = gob_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 =
                      scen_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 = gob_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 gob_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 = util_getRandom(30);

            layer = objDesc->stateMach[objDesc->state][0]->layer;
            scen_updateAnim(layer, 0, objDesc->animation, 0,
                objDesc->xPos, objDesc->yPos, 0);

            objDesc->order = scen_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;

            util_listInsertBack(gob_objList, objDesc);
      }
}

int16 gob_getObjMaxFrame(Gob_Object * objDesc) {
      int16 layer;

      layer = objDesc->stateMach[objDesc->state][0]->layer;
      return scen_animations[objDesc->animation].layers[layer]->framesCount -
          1;
}

int16 gob_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 gob_setMultStates(Gob_Object * gobDesc) {
      gobDesc->stateMach = gob_goblins[(int)gobDesc->multObjIndex]->stateMach;
}

int16 gob_nextLayer(Gob_Object *gobDesc) {
      if (gobDesc->nextState == 10)
            gobDesc->curLookDir = 0;

      if (gobDesc->nextState == 11)
            gobDesc->curLookDir = 4;

      if (gobDesc->nextState > 39) {
            gob_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 gob_showBoredom(int16 gobIndex) {
      Gob_Object *gobDesc;
      int16 frame;
      int16 frameCount;
      int16 layer;
      int16 state;
      int16 boreFlag;

      gobDesc = gob_goblins[gobIndex];
      layer = gobDesc->stateMach[gobDesc->state][0]->layer;

      frameCount =
          scen_animations[gobDesc->animation].layers[layer]->framesCount;
      state = gobDesc->state;
      frame = gobDesc->curFrame;

      gobDesc->noTick = 0;
      gobDesc->toRedraw = 1;

      boreFlag = 1 << util_getRandom(7);

      if (gobIndex != gob_currentGoblin && 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 gob_switchGoblin(int16 index) {
      int16 next;
      int16 tmp;

      debug(4, "gob_switchGoblin");
      if (VAR(59) != 0)
            return;

      if (gob_goblins[gob_currentGoblin]->state <= 39 &&
          gob_goblins[gob_currentGoblin]->curFrame != 0)
            return;

      if (index != 0 && gob_goblins[index - 1]->type != 0)
            return;

      if (index == 0)
            next = (gob_currentGoblin + 1) % 3;
      else
            next = index - 1;

      if (map_passMap[map_curGoblinY][map_curGoblinX] == 3 ||
          map_passMap[map_curGoblinY][map_curGoblinX] == 6)
            return;

      if (gob_goblins[(gob_currentGoblin + 1) % 3]->type != 0 &&
          gob_goblins[(gob_currentGoblin + 2) % 3]->type != 0)
            return;

      gob_gobPositions[gob_currentGoblin].x = map_curGoblinX;
      gob_gobPositions[gob_currentGoblin].y = map_curGoblinY;

      gob_goblins[gob_currentGoblin]->doAnim = 1;
      gob_goblins[gob_currentGoblin]->nextState = 21;

      gob_nextLayer(gob_goblins[gob_currentGoblin]);

      gob_currentGoblin = next;
      if (gob_goblins[gob_currentGoblin]->type != 0)
            gob_currentGoblin = (gob_currentGoblin + 1) % 3;

      gob_goblins[gob_currentGoblin]->doAnim = 0;
      if (gob_goblins[gob_currentGoblin]->curLookDir == 4)
            gob_goblins[gob_currentGoblin]->nextState = 18;
      else
            gob_goblins[gob_currentGoblin]->nextState = 19;

      gob_goblins[gob_currentGoblin]->toRedraw = 1;
      gob_nextLayer(gob_goblins[gob_currentGoblin]);

      tmp = gob_gobPositions[gob_currentGoblin].x;
      gob_pressedMapX = tmp;
      map_destX = tmp;
      gob_gobDestX = tmp;
      map_curGoblinX = tmp;

      tmp = gob_gobPositions[gob_currentGoblin].y;
      gob_pressedMapY = tmp;
      map_destY = tmp;
      gob_gobDestY = tmp;
      map_curGoblinY = tmp;

      *gob_curGobVarPtr = gob_currentGoblin;
      gob_pathExistence = 0;
      gob_readyToAct = 0;
}

void gob_adjustDest(int16 posX, int16 posY) {
      int16 resDelta;
      int16 resDeltaDir;
      int16 resDeltaPix;
      int16 deltaPix;
      int16 i;

      if (map_passMap[gob_pressedMapY][gob_pressedMapX] == 0 &&
          (gob_gobAction == 0
            || map_itemsMap[gob_pressedMapY][gob_pressedMapX] == 0)) {

            resDelta = -1;
            resDeltaDir = 0;
            resDeltaPix = 0;

            for (i = 1;
                i <= gob_pressedMapX
                && map_passMap[gob_pressedMapY][gob_pressedMapX - i] == 0;
                i++);

            if (i <= gob_pressedMapX) {
                  resDeltaPix = (i - 1) * 12 + (posX % 12) + 1;
                  resDelta = i;
            }

            for (i = 1;
                (i + gob_pressedMapX) < 26
                && map_passMap[gob_pressedMapY][gob_pressedMapX + i] == 0;
                i++);

            if (gob_pressedMapX + i < 26) {
                  deltaPix = (i * 12) - (posX % 12);
                  if (resDelta == -1 || deltaPix < resDeltaPix) {
                        resDeltaPix = deltaPix;
                        resDelta = i;
                        resDeltaDir = 1;
                  }
            }

            for (i = 1;
                (i + gob_pressedMapY) < 28
                && map_passMap[gob_pressedMapY + i][gob_pressedMapX] == 0;
                i++);

            if (gob_pressedMapY + i < 28) {
                  deltaPix = (i * 6) - (posY % 6);
                  if (resDelta == -1 || deltaPix < resDeltaPix) {
                        resDeltaPix = deltaPix;
                        resDelta = i;
                        resDeltaDir = 2;
                  }
            }

            for (i = 1;
                i <= gob_pressedMapY
                && map_passMap[gob_pressedMapY - i][gob_pressedMapX] == 0;
                i++);

            if (i <= gob_pressedMapY) {
                  deltaPix = (i * 6) + (posY % 6);
                  if (resDelta == -1 || deltaPix < resDeltaPix) {
                        resDeltaPix = deltaPix;
                        resDelta = i;
                        resDeltaDir = 3;
                  }
            }

            switch (resDeltaDir) {
            case 0:
                  gob_pressedMapX -= resDelta;
                  break;

            case 1:
                  gob_pressedMapX += resDelta;
                  break;

            case 2:
                  gob_pressedMapY += resDelta;
                  break;

            case 3:
                  gob_pressedMapY -= resDelta;
                  break;
            }

      }
}

void gob_adjustTarget(void) {
      if (gob_gobAction == 4
          && map_itemsMap[gob_pressedMapY][gob_pressedMapX] == 0) {

            if (gob_pressedMapY > 0
                && map_itemsMap[gob_pressedMapY - 1][gob_pressedMapX] !=
                0) {
                  gob_pressedMapY--;
            } else if (gob_pressedMapX < 25
                && map_itemsMap[gob_pressedMapY][gob_pressedMapX + 1] !=
                0) {
                  gob_pressedMapX++;
            } else if (gob_pressedMapX < 25 && gob_pressedMapY > 0
                && map_itemsMap[gob_pressedMapY - 1][gob_pressedMapX +
                  1] != 0) {
                  gob_pressedMapY--;
                  gob_pressedMapX++;
            }
      }
}

void gob_targetDummyItem(Gob_Object *gobDesc) {
      if (map_itemsMap[gob_pressedMapY][gob_pressedMapX] == 0 &&
          map_passMap[gob_pressedMapY][gob_pressedMapX] == 1) {
            if (gobDesc->curLookDir == 0) {
                  map_itemPoses[0].x = gob_pressedMapX;
                  map_itemPoses[0].y = gob_pressedMapY;
                  map_itemPoses[0].orient = -4;
            } else {
                  map_itemPoses[0].x = gob_pressedMapX;
                  map_itemPoses[0].y = gob_pressedMapY;
                  map_itemPoses[0].orient = -1;
            }
      }
}

void gob_targetItem(void) {
      int16 tmpX;
      int16 tmpY;
      int16 items;
      int16 layer;
      int16 tmpPosX;
      int16 tmpPosY;
      Gob_Object *itemDesc;

      if (gob_gobAction == 3 || gob_gobAction == 4) {
            items = map_itemsMap[gob_pressedMapY][gob_pressedMapX];
            if (gob_gobAction == 4 && (items & 0xff00) != 0 &&
                gob_objects[gob_itemToObject[(items & 0xff00) >> 8]]->
                pickable == 1) {
                  gob_destItemId = (items & 0xff00) >> 8;
                  gob_destActionItem = (items & 0xff00) >> 8;
                  gob_itemByteFlag = 1;
            } else if ((items & 0xff) == 0) {
                  gob_destItemId = (items & 0xff00) >> 8;
                  gob_destActionItem = (items & 0xff00) >> 8;
                  gob_itemByteFlag = 1;
            } else if (gob_gobAction == 3 && gob_currentGoblin == 2 &&
                (items & 0xff00) != 0) {
                  gob_destItemId = (items & 0xff00) >> 8;
                  gob_destActionItem = (items & 0xff00) >> 8;
                  gob_itemByteFlag = 1;
            } else {
                  gob_destItemId = items & 0xff;
                  gob_destActionItem = items & 0xff;
                  gob_itemByteFlag = 0;
            }

            gob_pressedMapY = map_itemPoses[gob_destItemId].y;
            map_destY = map_itemPoses[gob_destItemId].y;
            gob_gobDestY = map_itemPoses[gob_destItemId].y;

            if (gob_gobAction == 3 || gob_destActionItem == 0) {
                  gob_pressedMapX = map_itemPoses[gob_destItemId].x;
                  map_destX = map_itemPoses[gob_destItemId].x;
                  gob_gobDestX = map_itemPoses[gob_destItemId].x;
            } else if ((items & 0xff00) != 0) {
                  if (map_itemPoses[gob_destItemId].orient == 4) {
                        if ((map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX - 1] & 0xff00) ==
                            (map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX] & 0xff00)) {
                              gob_pressedMapX--;
                              map_destX = gob_pressedMapX;
                              gob_gobDestX = gob_pressedMapX;
                        }
                  } else if (map_itemPoses[gob_destItemId].orient == 0) {

                        if ((map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX + 1] & 0xff00) ==
                            (map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX] & 0xff00)) {
                              gob_pressedMapX++;
                              map_destX = gob_pressedMapX;
                              gob_gobDestX = gob_pressedMapX;
                        }
                  }

                  if ((map_itemsMap[gob_pressedMapY +
                            1][gob_pressedMapX] & 0xff00) ==
                      (map_itemsMap[gob_pressedMapY][gob_pressedMapX] &
                        0xff00)) {
                        gob_pressedMapY++;
                        map_destY = gob_pressedMapY;
                        gob_gobDestY = gob_pressedMapY;
                  }
            } else {
                  if (map_itemPoses[gob_destItemId].orient == 4) {
                        if ((map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX - 1]) ==
                            (map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX])) {
                              gob_pressedMapX--;
                              map_destX = gob_pressedMapX;
                              gob_gobDestX = gob_pressedMapX;
                        }
                  } else if (map_itemPoses[gob_destItemId].orient == 0) {

                        if ((map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX + 1]) ==
                            (map_itemsMap[gob_pressedMapY]
                              [gob_pressedMapX])) {
                              gob_pressedMapX++;
                              map_destX = gob_pressedMapX;
                              gob_gobDestX = gob_pressedMapX;
                        }
                  }

                  if ((map_itemsMap[gob_pressedMapY +
                            1][gob_pressedMapX]) ==
                      (map_itemsMap[gob_pressedMapY][gob_pressedMapX])) {
                        gob_pressedMapY++;
                        map_destY = gob_pressedMapY;
                        gob_gobDestY = gob_pressedMapY;
                  }

            }

            if (gob_gobAction == 4 && gob_destActionItem != 0 &&
                  gob_itemToObject[gob_destActionItem] != -1 &&
                gob_objects[gob_itemToObject[gob_destActionItem]]->
                pickable == 1) {

                  itemDesc =
                      gob_objects[gob_itemToObject[gob_destActionItem]];

                  itemDesc->animation =
                      itemDesc->stateMach[itemDesc->state][0]->animation;
                  layer =
                      itemDesc->stateMach[itemDesc->state][itemDesc->
                      stateColumn]->layer;

                  scen_updateAnim(layer, 0, itemDesc->animation, 0,
                      itemDesc->xPos, itemDesc->yPos, 0);

                  tmpX = (scen_toRedrawRight + scen_toRedrawLeft) / 2;
                  tmpY = scen_toRedrawBottom;

                  tmpPosY = tmpY / 6;
                  if ((tmpY % 3) < 3 && tmpPosY > 0)
                        tmpPosY--;

                  tmpPosX = tmpX / 12;
                  if ((tmpX % 12) < 6 && tmpPosX > 0)
                        tmpPosX--;

                  if (map_itemPoses[gob_destActionItem].orient == 0 ||
                      map_itemPoses[gob_destActionItem].orient == -1) {
                        tmpPosX++;
                  }

                  if (map_passMap[tmpPosY][tmpPosX] == 1) {
                        gob_pressedMapX = tmpPosX;
                        map_destX = tmpPosX;
                        gob_gobDestX = tmpPosX;

                        gob_pressedMapY = tmpPosY;
                        map_destY = tmpPosY;
                        gob_gobDestY = tmpPosY;
                  }
            }
      }
}

void gob_initiateMove(void) {
      map_findNearestToDest();
      map_findNearestToGob();

      map_nearestWayPoint =
          map_optimizePoints(map_curGoblinX, map_curGoblinY);

      gob_pathExistence = map_checkDirectPath(map_curGoblinX, map_curGoblinY,
          gob_pressedMapX, gob_pressedMapY);

      if (gob_pathExistence == 3) {
            if (map_checkLongPath(map_curGoblinX, map_curGoblinY,
                  gob_pressedMapX, gob_pressedMapY,
                  map_nearestWayPoint, map_nearestDest) == 0) {
                  gob_pathExistence = 0;
            } else {
                  map_destX = map_wayPoints[map_nearestWayPoint].x;
                  map_destY = map_wayPoints[map_nearestWayPoint].y;
            }
      }
}

void gob_moveFindItem(int16 posX, int16 posY) {
      int16 i;
      if (gob_gobAction == 3 || gob_gobAction == 4) {
            for (i = 0; i < 20; i++) {
                  if (gob_objects[i] == 0)
                        continue;

                  if (gob_objects[i]->type != 0)
                        continue;

                  if (gob_objects[i]->left > posX)
                        continue;

                  if (gob_objects[i]->right < posX)
                        continue;

                  if (gob_objects[i]->top > posY)
                        continue;

                  if (gob_objects[i]->bottom < posY)
                        continue;

                  if (gob_objects[i]->right - gob_objects[i]->left < 40)
                        posX =
                            (gob_objects[i]->left +
                            gob_objects[i]->right) / 2;

                  if (gob_objects[i]->bottom - gob_objects[i]->top < 40)
                        posY =
                            (gob_objects[i]->top +
                            gob_objects[i]->bottom) / 2;

                  break;
            }

            gob_pressedMapX = posX / 12;
            gob_pressedMapY = posY / 6;

            if (map_itemsMap[gob_pressedMapY][gob_pressedMapX] == 0
                && i < 20) {

                  if (map_itemsMap[gob_pressedMapY +
                        1][gob_pressedMapX] != 0) {
                        gob_pressedMapY++;
                  } else if (map_itemsMap[gob_pressedMapY +
                        1][gob_pressedMapX + 1] != 0) {
                        gob_pressedMapX++;
                        gob_pressedMapY++;
                  } else
                      if (map_itemsMap[gob_pressedMapY][gob_pressedMapX +
                        1] != 0) {
                        gob_pressedMapX++;
                  } else if (map_itemsMap[gob_pressedMapY -
                        1][gob_pressedMapX + 1] != 0) {
                        gob_pressedMapX++;
                        gob_pressedMapY--;
                  } else if (map_itemsMap[gob_pressedMapY -
                        1][gob_pressedMapX] != 0) {
                        gob_pressedMapY--;
                  } else if (map_itemsMap[gob_pressedMapY -
                        1][gob_pressedMapX - 1] != 0) {
                        gob_pressedMapY--;
                        gob_pressedMapX--;
                  } else
                      if (map_itemsMap[gob_pressedMapY][gob_pressedMapX -
                        1] != 0) {
                        gob_pressedMapX--;
                  } else if (map_itemsMap[gob_pressedMapY +
                        1][gob_pressedMapX - 1] != 0) {
                        gob_pressedMapX--;
                        gob_pressedMapY++;
                  }
            }
      } else {
            gob_pressedMapX = posX / 12;
            gob_pressedMapY = posY / 6;
      }
}

void gob_moveCheckSelect(int16 framesCount, Gob_Object * gobDesc, int16 *pGobIndex,
          int16 *nextAct) {
      if (gobDesc->right > inter_mouseX &&
          gobDesc->left < inter_mouseX &&
          gobDesc->bottom > inter_mouseY &&
          gobDesc->bottom - 10 < inter_mouseY && gob_gobAction == 0) {
            if (gobDesc->curLookDir & 4)
                  *nextAct = 16;
            else
                  *nextAct = 23;

            gobDesc->curFrame = framesCount - 1;
            gob_pathExistence = 0;
      } else {
            *pGobIndex = gob_peekGoblin(gobDesc);

            if (*pGobIndex != 0) {
                  gob_pathExistence = 0;
            } else if (map_curGoblinX == gob_pressedMapX &&
                map_curGoblinY == gob_pressedMapY) {

                  if (gob_gobAction != 0)
                        gob_readyToAct = 1;

                  gob_pathExistence = 0;
            }
      }
}

void gob_moveInitStep(int16 framesCount, int16 action, int16 cont,
          Gob_Object *gobDesc, int16 *pGobIndex, int16 *pNextAct) {
      int16 posX;
      int16 posY;

      if (cont != 0 && gob_goesAtTarget == 0 &&
          gob_readyToAct == 0 && VAR(59) == 0 &&
          gobDesc->type != 1 &&
          gobDesc->state != 10 && gobDesc->state != 11) {
            if (gobDesc->state >= 40) {
                  gobDesc->curFrame = framesCount - 1;
            }

            gob_gobAction = action;
            gob_forceNextState[0] = -1;
            gob_forceNextState[1] = -1;
            gob_forceNextState[2] = -1;

            if (action == 3) {
                  posX = inter_mouseX + 6;
                  posY = inter_mouseY + 7;
            } else if (action == 4) {
                  posX = inter_mouseX + 7;
                  posY = inter_mouseY + 12;
            } else {
                  posX = inter_mouseX;
                  posY = inter_mouseY;
            }

            gob_moveFindItem(posX, posY);
            gob_adjustDest(posX, posY);
            gob_adjustTarget();

            map_destX = gob_pressedMapX;
            gob_gobDestX = gob_pressedMapX;

            map_destY = gob_pressedMapY;
            gob_gobDestY = gob_pressedMapY;

            gob_targetDummyItem(gobDesc);

            gob_targetItem();
            gob_initiateMove();

            gob_moveCheckSelect(framesCount, gobDesc, pGobIndex, pNextAct);
      } else {

            if (gob_readyToAct != 0 &&
                (map_curGoblinX != gob_pressedMapX ||
                  map_curGoblinY != gob_pressedMapY))
                  gob_readyToAct = 0;

            if (gobDesc->type == 1) {
                  *pGobIndex = gob_peekGoblin(gobDesc);
            }
      }
}

void gob_moveTreatRopeStairs(Gob_Object *gobDesc) {
      if (gob_currentGoblin != 1)
            return;

      if (gobDesc->nextState == 28
          && map_passMap[map_curGoblinY - 1][map_curGoblinX] == 6) {
            gob_forceNextState[0] = 28;
            gob_forceNextState[1] = -1;
      }

      if (gobDesc->nextState == 29
          && map_passMap[map_curGoblinY + 1][map_curGoblinX] == 6) {
            gob_forceNextState[0] = 29;
            gob_forceNextState[1] = -1;
      }

      if ((gobDesc->nextState == 28 || gobDesc->nextState == 29
            || gobDesc->nextState == 20)
          && map_passMap[map_curGoblinY][map_curGoblinX] == 6) {
            if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
                  || gobDesc->curLookDir == 2)
                && map_passMap[map_curGoblinY - 1][map_curGoblinX] == 6) {
                  gob_forceNextState[0] = 28;
                  gob_forceNextState[1] = -1;
            } else if ((gobDesc->curLookDir == 0
                  || gobDesc->curLookDir == 4
                  || gobDesc->curLookDir == 6)
                && map_passMap[map_curGoblinY + 1][map_curGoblinX] == 6) {
                  gob_forceNextState[0] = 29;
                  gob_forceNextState[1] = -1;
            }
      }

      if (gobDesc->nextState == 8
          && map_passMap[map_curGoblinY - 1][map_curGoblinX] == 3) {
            gob_forceNextState[0] = 8;
            gob_forceNextState[1] = -1;
      }

      if (gobDesc->nextState == 9
          && map_passMap[map_curGoblinY + 1][map_curGoblinX] == 3) {
            gob_forceNextState[0] = 9;
            gob_forceNextState[1] = -1;
      }

      if (gobDesc->nextState == 20
          && map_passMap[map_curGoblinY][map_curGoblinX] == 3) {
            if ((gobDesc->curLookDir == 0 || gobDesc->curLookDir == 4
                  || gobDesc->curLookDir == 2)
                && map_passMap[map_curGoblinY - 1][map_curGoblinX] == 3) {
                  gob_forceNextState[0] = 8;
                  gob_forceNextState[1] = -1;
            } else if ((gobDesc->curLookDir == 0
                  || gobDesc->curLookDir == 4
                  || gobDesc->curLookDir == 6)
                && map_passMap[map_curGoblinY + 1][map_curGoblinX] == 3) {
                  gob_forceNextState[0] = 9;
                  gob_forceNextState[1] = -1;
            }
      }

}

void gob_movePathFind(Gob_Object *gobDesc, int16 nextAct) {
      if (gob_pathExistence == 1) {
            map_curGoblinX = gob_gobPositions[gob_currentGoblin].x;
            map_curGoblinY = gob_gobPositions[gob_currentGoblin].y;

            if (map_curGoblinX == gob_pressedMapX &&
                map_curGoblinY == gob_pressedMapY && gob_gobAction != 0) {
                  gob_readyToAct = 1;
                  gob_pathExistence = 0;
            }

            nextAct = map_getDirection(map_curGoblinX, map_curGoblinY,
                map_destX, map_destY);

            if (nextAct == 0)
                  gob_pathExistence = 0;
      } else if (gob_pathExistence == 3) {
            map_curGoblinX = gob_gobPositions[gob_currentGoblin].x;
            map_curGoblinY = gob_gobPositions[gob_currentGoblin].y;

            if (map_curGoblinX == gob_gobDestX &&
                map_curGoblinY == gob_gobDestY) {
                  gob_pathExistence = 1;
                  map_destX = gob_pressedMapX;
                  map_destY = gob_pressedMapY;
            } else {

                  if (map_checkDirectPath(map_curGoblinX, map_curGoblinY,
                        gob_gobDestX, gob_gobDestY) == 1) {
                        map_destX = gob_gobDestX;
                        map_destY = gob_gobDestY;
                  } else if (map_curGoblinX == map_destX
                      && map_curGoblinY == map_destY) {

                        if (map_nearestWayPoint > map_nearestDest) {
                              map_nearestWayPoint =
                                  map_optimizePoints(map_curGoblinX,
                                  map_curGoblinY);

                              map_destX =
                                  map_wayPoints[map_nearestWayPoint].
                                  x;
                              map_destY =
                                  map_wayPoints[map_nearestWayPoint].
                                  y;

                              if (map_nearestWayPoint >
                                  map_nearestDest)
                                    map_nearestWayPoint--;
                        } else if (map_nearestWayPoint <
                            map_nearestDest) {
                              map_nearestWayPoint =
                                  map_optimizePoints(map_curGoblinX,
                                  map_curGoblinY);

                              map_destX =
                                  map_wayPoints[map_nearestWayPoint].
                                  x;
                              map_destY =
                                  map_wayPoints[map_nearestWayPoint].
                                  y;

                              if (map_nearestWayPoint < map_nearestDest)
                                    map_nearestWayPoint++;
                        } else {
                              if (map_checkDirectPath(map_curGoblinX,
                                    map_curGoblinY, gob_gobDestX,
                                    gob_gobDestY) == 3 && map_passMap[gob_pressedMapY][gob_pressedMapX] != 0) {
                                    map_destX = map_wayPoints[map_nearestWayPoint].x;
                                    map_destY = map_wayPoints[map_nearestWayPoint].y;
                              } else {
                                    gob_pathExistence = 1;
                                    map_destX = gob_pressedMapX;
                                    map_destY = gob_pressedMapY;
                              }
                        }
                  }
                  nextAct =
                      map_getDirection(map_curGoblinX, map_curGoblinY,
                      map_destX, map_destY);
            }
      }

      if (gob_readyToAct != 0 && (gob_gobAction == 3 || gob_gobAction == 4))
            nextAct = 0x4dc8;

      switch (nextAct) {
      case kDirW:
            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 0);
            break;

      case kDirE:
            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 4);
            break;

      case 16:
            gobDesc->nextState = 16;
            break;

      case 23:
            gobDesc->nextState = 23;
            break;

      case kDirN:
            if (map_passMap[map_curGoblinY - 1][map_curGoblinX] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            if (map_passMap[map_curGoblinY][map_curGoblinX] == 3) {
                  gobDesc->nextState = 8;
                  break;
            }

            if (map_passMap[map_curGoblinY][map_curGoblinX] == 6 &&
                gob_currentGoblin == 1) {
                  gobDesc->nextState = 28;
                  break;
            }

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 2);
            break;

      case kDirS:
            if (map_passMap[map_curGoblinY + 1][map_curGoblinX] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            if (map_passMap[map_curGoblinY][map_curGoblinX] == 3) {
                  gobDesc->nextState = 9;
                  break;
            }

            if (map_passMap[map_curGoblinY][map_curGoblinX] == 6 &&
                gob_currentGoblin == 1) {
                  gobDesc->nextState = 29;
                  break;
            }

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 6);
            break;

      case kDirSE:
            if (map_passMap[map_curGoblinY + 1][map_curGoblinX + 1] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            gobDesc->nextState = 5;
            if (gobDesc->curLookDir == 4)
                  break;

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 4);
            break;

      case kDirSW:
            if (map_passMap[map_curGoblinY + 1][map_curGoblinX - 1] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            gobDesc->nextState = 7;
            if (gobDesc->curLookDir == 0)
                  break;

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 0);
            break;

      case kDirNW:
            if (map_passMap[map_curGoblinY - 1][map_curGoblinX - 1] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            gobDesc->nextState = 1;
            if (gobDesc->curLookDir == 0)
                  break;

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 0);
            break;

      case kDirNE:
            if (map_passMap[map_curGoblinY - 1][map_curGoblinX + 1] == 6 &&
                gob_currentGoblin != 1) {
                  gob_pathExistence = 0;
                  break;
            }

            gobDesc->nextState = 3;
            if (gobDesc->curLookDir == 4)
                  break;

            gobDesc->nextState = gob_rotateState(gobDesc->curLookDir, 4);
            break;

      case 0x4dc8:

            if (gob_currentGoblin == 0 && gob_gobAction == 3
                && gob_itemIndInPocket == -1) {
                  gob_destItemId = -1;
                  gob_readyToAct = 0;
                  break;
            }

            if (gob_currentGoblin == 0 && gob_gobAction == 4 &&
                gob_itemIndInPocket == -1 && gob_destActionItem == 0) {
                  gobDesc->multState = 104;
                  gob_destItemId = -1;
                  gob_readyToAct = 0;
                  break;
            }

            if (gob_currentGoblin == 0 && gob_gobAction == 4 &&
                gob_itemIndInPocket == -1 && gob_destActionItem != 0 &&
                gob_itemToObject[gob_destActionItem] != -1 &&
                gob_objects[gob_itemToObject[gob_destActionItem]]->
                pickable == 0) {
                  gobDesc->multState = 104;
                  gob_destItemId = -1;
                  gob_readyToAct = 0;
                  break;
            }

            switch (map_itemPoses[gob_destActionItem].orient) {
            case 0:
            case -4:
                  gobDesc->nextState = 10;
                  gobDesc->curLookDir = 0;
                  gob_destItemId = -1;
                  break;

            case -1:
            case 4:
                  gobDesc->nextState = 11;
                  gobDesc->curLookDir = 4;
                  gob_destItemId = -1;
                  break;
            }
            break;

      default:
            if (map_passMap[map_curGoblinY][map_curGoblinX] == 3 ||
                (map_passMap[map_curGoblinY][map_curGoblinX] == 6
                  && gob_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 gob_moveAdvance(Gob_Object *gobDesc, int16 nextAct, int16 framesCount) {
      int16 i;
      int16 newX;
      int16 newY;
      int16 flag;

      gob_movePathFind(gobDesc, nextAct);

      gobDesc->curFrame++;
      if (gobDesc->curFrame == 1)
            gobDesc->actionStartState = gobDesc->state;

      if (gob_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 (gob_currentGoblin != 1)
                        break;
                  gobDesc->curLookDir = 2;
                  break;

            case 2:
            case 8:
            case 15:
            case 22:
            case 25:
                  gobDesc->curLookDir = 2;
                  break;

            case 29:
                  if (gob_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)) {
            snd_speakerOn(10 * util_getRandom(3) + 50, 5);
      }

      if (gob_currentGoblin == 0
          && gobDesc->stateMach == gobDesc->realStateMach
          && (gobDesc->state == 10 || gobDesc->state == 11)
          && gobDesc->curFrame == 9) {
            snd_stopSound(0);
            if (gob_itemIndInPocket != -1) {
                  snd_playSample(gob_soundData[14], 1, 9000);
            }

            if (gob_itemIndInPocket == -1) {
                  snd_playSample(gob_soundData[14], 1, 5000);
            }
      }

      if (gob_boreCounter++ == 120) {
            gob_boreCounter = 0;
            for (i = 0; i < 3; i++)
                  gob_showBoredom(i);
      }

      if (gobDesc->multState != -1 && gobDesc->curFrame == framesCount &&
          gobDesc->state != gobDesc->multState) {
            gobDesc->nextState = gobDesc->multState;
            gobDesc->multState = -1;

            newX =
                scen_animations[gobDesc->animation].
                layers[gob_gobStateLayer]->animDeltaX + gobDesc->xPos;

            newY =
                scen_animations[gobDesc->animation].
                layers[gob_gobStateLayer]->animDeltaY + gobDesc->yPos;

            gob_gobStateLayer = gob_nextLayer(gobDesc);

            gobDesc->xPos = newX;
            gobDesc->yPos = newY;
      } else {
            if (gobDesc->curFrame == 3 &&
                gobDesc->stateMach == gobDesc->realStateMach &&
                (gobDesc->state < 10 ||
                  (gob_currentGoblin == 1 && (gobDesc->state == 28
                        || gobDesc->state == 29))
                )) {
                  flag = 0;
                  if (gob_forceNextState[0] != -1) {
                        gobDesc->nextState = gob_forceNextState[0];
                        for (i = 0; i < 9; i++)
                              gob_forceNextState[i] =
                                  gob_forceNextState[i + 1];
                  }

                  map_curGoblinX = gob_gobPositions[gob_currentGoblin].x;
                  map_curGoblinY = gob_gobPositions[gob_currentGoblin].y;

                  if (gobDesc->nextState != gobDesc->state) {
                        gob_gobStateLayer = gob_nextLayer(gobDesc);
                        flag = 1;
                  }

                  switch (gobDesc->state) {
                  case 0:
                        gob_gobPositions[gob_currentGoblin].x--;
                        break;

                  case 2:
                  case 8:
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 4:
                        gob_gobPositions[gob_currentGoblin].x++;
                        break;

                  case 6:
                  case 9:
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 1:
                        gob_gobPositions[gob_currentGoblin].x--;
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 3:
                        gob_gobPositions[gob_currentGoblin].x++;
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 5:
                        gob_gobPositions[gob_currentGoblin].x++;
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 7:
                        gob_gobPositions[gob_currentGoblin].x--;
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 38:
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;
                  }

                  if (gob_currentGoblin == 1) {
                        if (gobDesc->state == 28)
                              gob_gobPositions[1].y--;

                        if (gobDesc->state == 29)
                              gob_gobPositions[1].y++;
                  }

                  if (flag != 0) {
                        scen_updateAnim(gob_gobStateLayer, 0,
                            gobDesc->animation, 0, gobDesc->xPos,
                            gobDesc->yPos, 0);

                        gobDesc->yPos =
                            (map_curGoblinY + 1) * 6 -
                            (scen_toRedrawBottom - scen_animTop);
                        gobDesc->xPos =
                            map_curGoblinX * 12 - (scen_toRedrawLeft -
                            scen_animLeft);
                  }

                  if ((gobDesc->state == 10 || gobDesc->state == 11)
                      && gob_currentGoblin != 0)
                        gob_goesAtTarget = 1;
            }

            if (gobDesc->curFrame != framesCount)
                  return;

            if (gob_forceNextState[0] != -1) {
                  gobDesc->nextState = gob_forceNextState[0];
                  for (i = 0; i < 10; i++)
                        gob_forceNextState[i] =
                            gob_forceNextState[i + 1];
            }

            map_curGoblinX = gob_gobPositions[gob_currentGoblin].x;
            map_curGoblinY = gob_gobPositions[gob_currentGoblin].y;

            gob_gobStateLayer = gob_nextLayer(gobDesc);
            if (gobDesc->stateMach == gobDesc->realStateMach) {

                  switch (gobDesc->nextState) {
                  case 0:
                        gob_gobPositions[gob_currentGoblin].x--;
                        break;

                  case 2:
                  case 8:
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 4:
                        gob_gobPositions[gob_currentGoblin].x++;
                        break;

                  case 6:
                  case 9:
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 1:
                        gob_gobPositions[gob_currentGoblin].x--;
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 3:
                        gob_gobPositions[gob_currentGoblin].x++;
                        gob_gobPositions[gob_currentGoblin].y--;
                        break;

                  case 5:
                        gob_gobPositions[gob_currentGoblin].x++;
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 7:
                        gob_gobPositions[gob_currentGoblin].x--;
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;

                  case 38:
                        gob_gobPositions[gob_currentGoblin].y++;
                        break;
                  }
                  if (gob_currentGoblin == 1) {
                        if (gobDesc->nextState == 28)
                              gob_gobPositions[1].y--;

                        if (gobDesc->nextState == 29)
                              gob_gobPositions[1].y++;
                  }
            }

            scen_updateAnim(gob_gobStateLayer, 0, gobDesc->animation, 0,
                gobDesc->xPos, gobDesc->yPos, 0);

            gobDesc->yPos =
                (map_curGoblinY + 1) * 6 - (scen_toRedrawBottom -
                scen_animTop);
            gobDesc->xPos =
                map_curGoblinX * 12 - (scen_toRedrawLeft - scen_animLeft);

            if ((gobDesc->state == 10 || gobDesc->state == 11)
                && gob_currentGoblin != 0)
                  gob_goesAtTarget = 1;
      }
      return;
}

int16 gob_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 =
          scen_animations[gobDesc->animation].layers[layer]->framesCount;

      if (VAR(59) == 0 &&
          gobDesc->state != 30 && gobDesc->state != 31) {
            gobDesc->order = (gobDesc->bottom) / 24 + 3;
      }

      if (gob_positionedGob != gob_currentGoblin) {
            map_curGoblinX = gob_gobPositions[gob_currentGoblin].x;
            map_curGoblinY = gob_gobPositions[gob_currentGoblin].y;
      }

      gob_positionedGob = gob_currentGoblin;

      gobDesc->animation =
          gobDesc->stateMach[gobDesc->state][gobDesc->stateColumn]->
          animation;

      gob_gobStateLayer =
          gobDesc->stateMach[gobDesc->state][gobDesc->stateColumn]->layer;

      gob_moveInitStep(framesCount, action, cont, gobDesc, &gobIndex,
          &nextAct);
      gob_moveTreatRopeStairs(gobDesc);
      gob_moveAdvance(gobDesc, nextAct, framesCount);

      return gobIndex;
}

void gob_freeObjects(void) {
      int16 i;
      int16 state;
      int16 col;

      for (i = 0; i < 16; i++) {
            if (gob_soundData[i] == 0)
                  continue;

            snd_freeSoundData(gob_soundData[i]);
            gob_soundData[i] = 0;
      }

      for (i = 0; i < 4; i++) {
            if (gob_goblins[i] == 0)
                  continue;

            gob_goblins[i]->stateMach = gob_goblins[i]->realStateMach;

            for (state = 0; state < 40; state++) {
                  for (col = 0; col < 6; col++) {
                        free(gob_goblins[i]->stateMach[state][col]);
                        gob_goblins[i]->stateMach[state][col] = 0;
                  }
            }

            if (i == 3) {
                  for (state = 40; state < 70; state++) {
                        free(gob_goblins[3]->stateMach[state][0]);
                        gob_goblins[3]->stateMach[state][0] = 0;
                  }
            }

            free(gob_goblins[i]->stateMach);
            free(gob_goblins[i]);
            gob_goblins[i] = 0;
      }

      for (i = 0; i < 20; i++) {
            if (gob_objects[i] == 0)
                  continue;

            gob_objects[i]->stateMach = gob_objects[i]->realStateMach;

            for (state = 0; state < 40; state++) {
                  for (col = 0; col < 6; col++) {
                        free(gob_objects[i]->stateMach[state][col]);
                        gob_objects[i]->stateMach[state][col] = 0;
                  }
            }

            free(gob_objects[i]->stateMach);
            free(gob_objects[i]);
            gob_objects[i] = 0;
      }
}

void gob_zeroObjects(void) {
      int16 i;

      for (i = 0; i < 4; i++)
            gob_goblins[i] = 0;

      for (i = 0; i < 20; i++)
            gob_objects[i] = 0;

      for (i = 0; i < 16; i++)
            gob_soundData[i] = 0;
}

void gob_freeAllObjects(void) {
      util_deleteList(gob_objList);
      gob_freeObjects();
}

void gob_loadObjects(char *source) {
      int16 i;

      gob_zeroObjects();
      for (i = 0; i < 20; i++)
            gob_itemToObject[i] = 100;

      gob_freeObjects();
      gob_initList();
      strcpy(map_sourceFile, source);

      map_sourceFile[strlen(map_sourceFile) - 4] = 0;
      map_loadMapObjects(source);

      for (i = 0; i < gob_gobsCount; i++)
            gob_placeObject(gob_goblins[i], 0);

      for (i = 0; i < gob_objCount; i++) {
            gob_placeObject(gob_objects[i], 1);
      }

      gob_initVarPointers();
      gob_actDestItemDesc = 0;
}

void gob_saveGobDataToVars(int16 xPos, int16 yPos, int16 someVal) {
      Gob_Object *obj;
      *gob_some0ValPtr = someVal;
      *gob_curGobXPosVarPtr = xPos;
      *gob_curGobYPosVarPtr = yPos;
      *gob_itemInPocketVarPtr = gob_itemIndInPocket;

      obj = gob_goblins[gob_currentGoblin];

      *gob_curGobStateVarPtr = obj->state;
      *gob_curGobFrameVarPtr = obj->curFrame;
      *gob_curGobMultStateVarPtr = obj->multState;
      *gob_curGobNextStateVarPtr = obj->nextState;
      *gob_curGobScrXVarPtr = obj->xPos;
      *gob_curGobScrYVarPtr = obj->yPos;
      *gob_curGobLeftVarPtr = obj->left;
      *gob_curGobTopVarPtr = obj->top;
      *gob_curGobRightVarPtr = obj->right;
      *gob_curGobBottomVarPtr = obj->bottom;
      *gob_curGobDoAnimVarPtr = obj->doAnim;
      *gob_curGobOrderVarPtr = obj->order;
      *gob_curGobNoTickVarPtr = obj->noTick;
      *gob_curGobTypeVarPtr = obj->type;
      *gob_curGobMaxTickVarPtr = obj->maxTick;
      *gob_curGobTickVarPtr = obj->tick;
      *gob_curGobActStartStateVarPtr = obj->actionStartState;
      *gob_curGobLookDirVarPtr = obj->curLookDir;
      *gob_curGobPickableVarPtr = obj->pickable;
      *gob_curGobRelaxVarPtr = obj->relaxTime;
      *gob_curGobMaxFrameVarPtr = gob_getObjMaxFrame(obj);

      if (gob_actDestItemDesc == 0)
            return;

      obj = gob_actDestItemDesc;
      *gob_destItemStateVarPtr = obj->state;
      *gob_destItemFrameVarPtr = obj->curFrame;
      *gob_destItemMultStateVarPtr = obj->multState;
      *gob_destItemNextStateVarPtr = obj->nextState;
      *gob_destItemScrXVarPtr = obj->xPos;
      *gob_destItemScrYVarPtr = obj->yPos;
      *gob_destItemLeftVarPtr = obj->left;
      *gob_destItemTopVarPtr = obj->top;
      *gob_destItemRightVarPtr = obj->right;
      *gob_destItemBottomVarPtr = obj->bottom;
      *gob_destItemDoAnimVarPtr = obj->doAnim;
      *gob_destItemOrderVarPtr = obj->order;
      *gob_destItemNoTickVarPtr = obj->noTick;
      *gob_destItemTypeVarPtr = obj->type;
      *gob_destItemMaxTickVarPtr = obj->maxTick;
      *gob_destItemTickVarPtr = obj->tick;
      *gob_destItemActStartStVarPtr = obj->actionStartState;
      *gob_destItemLookDirVarPtr = obj->curLookDir;
      *gob_destItemPickableVarPtr = obj->pickable;
      *gob_destItemRelaxVarPtr = obj->relaxTime;
      *gob_destItemMaxFrameVarPtr = gob_getObjMaxFrame(obj);

      gob_destItemState = obj->state;
      gob_destItemType = obj->type;
}

void gob_initVarPointers(void) {
      gob_gobRetVarPtr = (int32 *)VAR_ADDRESS(59);
      gob_curGobStateVarPtr = (int32 *)VAR_ADDRESS(60);
      gob_curGobFrameVarPtr = (int32 *)VAR_ADDRESS(61);
      gob_curGobMultStateVarPtr = (int32 *)VAR_ADDRESS(62);
      gob_curGobNextStateVarPtr = (int32 *)VAR_ADDRESS(63);
      gob_curGobScrXVarPtr = (int32 *)VAR_ADDRESS(64);
      gob_curGobScrYVarPtr = (int32 *)VAR_ADDRESS(65);
      gob_curGobLeftVarPtr = (int32 *)VAR_ADDRESS(66);
      gob_curGobTopVarPtr = (int32 *)VAR_ADDRESS(67);
      gob_curGobRightVarPtr = (int32 *)VAR_ADDRESS(68);
      gob_curGobBottomVarPtr = (int32 *)VAR_ADDRESS(69);
      gob_curGobDoAnimVarPtr = (int32 *)VAR_ADDRESS(70);
      gob_curGobOrderVarPtr = (int32 *)VAR_ADDRESS(71);
      gob_curGobNoTickVarPtr = (int32 *)VAR_ADDRESS(72);
      gob_curGobTypeVarPtr = (int32 *)VAR_ADDRESS(73);
      gob_curGobMaxTickVarPtr = (int32 *)VAR_ADDRESS(74);
      gob_curGobTickVarPtr = (int32 *)VAR_ADDRESS(75);
      gob_curGobActStartStateVarPtr = (int32 *)VAR_ADDRESS(76);
      gob_curGobLookDirVarPtr = (int32 *)VAR_ADDRESS(77);
      gob_curGobPickableVarPtr = (int32 *)VAR_ADDRESS(80);
      gob_curGobRelaxVarPtr = (int32 *)VAR_ADDRESS(81);
      gob_destItemStateVarPtr = (int32 *)VAR_ADDRESS(82);
      gob_destItemFrameVarPtr = (int32 *)VAR_ADDRESS(83);
      gob_destItemMultStateVarPtr = (int32 *)VAR_ADDRESS(84);
      gob_destItemNextStateVarPtr = (int32 *)VAR_ADDRESS(85);
      gob_destItemScrXVarPtr = (int32 *)VAR_ADDRESS(86);
      gob_destItemScrYVarPtr = (int32 *)VAR_ADDRESS(87);
      gob_destItemLeftVarPtr = (int32 *)VAR_ADDRESS(88);
      gob_destItemTopVarPtr = (int32 *)VAR_ADDRESS(89);
      gob_destItemRightVarPtr = (int32 *)VAR_ADDRESS(90);
      gob_destItemBottomVarPtr = (int32 *)VAR_ADDRESS(91);
      gob_destItemDoAnimVarPtr = (int32 *)VAR_ADDRESS(92);
      gob_destItemOrderVarPtr = (int32 *)VAR_ADDRESS(93);
      gob_destItemNoTickVarPtr = (int32 *)VAR_ADDRESS(94);
      gob_destItemTypeVarPtr = (int32 *)VAR_ADDRESS(95);
      gob_destItemMaxTickVarPtr = (int32 *)VAR_ADDRESS(96);
      gob_destItemTickVarPtr = (int32 *)VAR_ADDRESS(97);
      gob_destItemActStartStVarPtr = (int32 *)VAR_ADDRESS(98);
      gob_destItemLookDirVarPtr = (int32 *)VAR_ADDRESS(99);
      gob_destItemPickableVarPtr = (int32 *)VAR_ADDRESS(102);
      gob_destItemRelaxVarPtr = (int32 *)VAR_ADDRESS(103);
      gob_destItemMaxFrameVarPtr = (int32 *)VAR_ADDRESS(105);
      gob_curGobVarPtr = (int32 *)VAR_ADDRESS(106);
      gob_some0ValPtr = (int32 *)VAR_ADDRESS(107);
      gob_curGobXPosVarPtr = (int32 *)VAR_ADDRESS(108);
      gob_curGobYPosVarPtr = (int32 *)VAR_ADDRESS(109);
      gob_curGobMaxFrameVarPtr = (int32 *)VAR_ADDRESS(110);

      gob_itemInPocketVarPtr = (int32 *)VAR_ADDRESS(114);

      *gob_itemInPocketVarPtr = -2;
}

void gob_loadGobDataFromVars(void) {
      Gob_Object *obj;

      gob_itemIndInPocket = *gob_itemInPocketVarPtr;

      obj = gob_goblins[gob_currentGoblin];

      obj->state = *gob_curGobStateVarPtr;
      obj->curFrame = *gob_curGobFrameVarPtr;
      obj->multState = *gob_curGobMultStateVarPtr;
      obj->nextState = *gob_curGobNextStateVarPtr;
      obj->xPos = *gob_curGobScrXVarPtr;
      obj->yPos = *gob_curGobScrYVarPtr;
      obj->left = *gob_curGobLeftVarPtr;
      obj->top = *gob_curGobTopVarPtr;
      obj->right = *gob_curGobRightVarPtr;
      obj->bottom = *gob_curGobBottomVarPtr;
      obj->doAnim = *gob_curGobDoAnimVarPtr;
      obj->order = *gob_curGobOrderVarPtr;
      obj->noTick = *gob_curGobNoTickVarPtr;
      obj->type = *gob_curGobTypeVarPtr;
      obj->maxTick = *gob_curGobMaxTickVarPtr;
      obj->tick = *gob_curGobTickVarPtr;
      obj->actionStartState = *gob_curGobActStartStateVarPtr;
      obj->curLookDir = *gob_curGobLookDirVarPtr;
      obj->pickable = *gob_curGobPickableVarPtr;
      obj->relaxTime = *gob_curGobRelaxVarPtr;

      if (gob_actDestItemDesc == 0)
            return;

      obj = gob_actDestItemDesc;

      obj->state = *gob_destItemStateVarPtr;
      obj->curFrame = *gob_destItemFrameVarPtr;
      obj->multState = *gob_destItemMultStateVarPtr;
      obj->nextState = *gob_destItemNextStateVarPtr;
      obj->xPos = *gob_destItemScrXVarPtr;
      obj->yPos = *gob_destItemScrYVarPtr;
      obj->left = *gob_destItemLeftVarPtr;
      obj->top = *gob_destItemTopVarPtr;
      obj->right = *gob_destItemRightVarPtr;
      obj->bottom = *gob_destItemBottomVarPtr;
      obj->doAnim = *gob_destItemDoAnimVarPtr;
      obj->order = *gob_destItemOrderVarPtr;
      obj->noTick = *gob_destItemNoTickVarPtr;
      obj->type = *gob_destItemTypeVarPtr;
      obj->maxTick = *gob_destItemMaxTickVarPtr;
      obj->tick = *gob_destItemTickVarPtr;
      obj->actionStartState = *gob_destItemActStartStVarPtr;
      obj->curLookDir = *gob_destItemLookDirVarPtr;
      obj->pickable = *gob_destItemPickableVarPtr;
      obj->relaxTime = *gob_destItemRelaxVarPtr;

      if (obj->type != gob_destItemType)
            obj->toRedraw = 1;

      if (obj->state != gob_destItemState && obj->type == 0)
            obj->toRedraw = 1;
}

void gob_pickItem(int16 indexToPocket, int16 idToPocket) {
      int16 x;
      int16 y;

      if (gob_objects[indexToPocket]->pickable != 1)
            return;

      gob_objects[indexToPocket]->type = 3;

      gob_itemIndInPocket = indexToPocket;
      gob_itemIdInPocket = idToPocket;

      for (y = 0; y < 28; y++) {
            for (x = 0; x < 26; x++) {
                  if (gob_itemByteFlag == 1) {
                        if (((map_itemsMap[y][x] & 0xff00) >> 8) ==
                            idToPocket)
                              map_itemsMap[y][x] &= 0xff;
                  } else {
                        if ((map_itemsMap[y][x] & 0xff) == idToPocket)
                              map_itemsMap[y][x] &= 0xff00;
                  }
            }
      }

      if (idToPocket >= 0 && idToPocket < 20) {
            map_itemPoses[gob_itemIdInPocket].x = 0;
            map_itemPoses[gob_itemIdInPocket].y = 0;
            map_itemPoses[gob_itemIdInPocket].orient = 0;
      }
}

void gob_placeItem(int16 indexInPocket, int16 idInPocket) {
      Gob_Object *itemDesc;
      int16 lookDir;
      int16 xPos;
      int16 yPos;
      int16 layer;

      itemDesc = gob_objects[indexInPocket];
      lookDir = gob_goblins[0]->curLookDir & 4;

      xPos = gob_gobPositions[0].x;
      yPos = gob_gobPositions[0].y;

      gob_itemIndInPocket = -1;
      gob_itemIdInPocket = 0;

      itemDesc->pickable = 1;
      itemDesc->type = 0;
      itemDesc->toRedraw = 1;
      itemDesc->curFrame = 0;
      itemDesc->order = gob_goblins[0]->order;
      itemDesc->animation =
          itemDesc->stateMach[itemDesc->state][0]->animation;
      layer =
          itemDesc->stateMach[itemDesc->state][itemDesc->stateColumn]->layer;

      scen_updateAnim(layer, 0, itemDesc->animation, 0,
          itemDesc->xPos, itemDesc->yPos, 0);

      itemDesc->yPos +=
          (gob_gobPositions[0].y * 6) + 5 - scen_toRedrawBottom;

      if (lookDir == 4) {
            itemDesc->xPos += (gob_gobPositions[0].x * 12 + 14)
                - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
      } else {
            itemDesc->xPos += (gob_gobPositions[0].x * 12)
                - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
      }

      map_placeItem(xPos, yPos, idInPocket);

      if (yPos > 0) {
            map_placeItem(xPos, yPos - 1, idInPocket);
      }

      if (lookDir == 4) {
            if (xPos < 25) {
                  map_placeItem(xPos + 1, yPos, idInPocket);

                  if (yPos > 0) {
                        map_placeItem(xPos + 1, yPos - 1, idInPocket);
                  }
            }
      } else {
            if (xPos > 0) {
                  map_placeItem(xPos - 1, yPos, idInPocket);

                  if (yPos > 0) {
                        map_placeItem(xPos - 1, yPos - 1, idInPocket);
                  }
            }
      }

      if (idInPocket >= 0 && idInPocket < 20) {
            map_itemPoses[idInPocket].x = gob_gobPositions[0].x;
            map_itemPoses[idInPocket].y = gob_gobPositions[0].y;
            map_itemPoses[idInPocket].orient = lookDir;
            if (map_itemPoses[idInPocket].orient == 0) {
//                      map_itemPoses[idInPocket].x++;
                  if (map_passMap[(int)map_itemPoses[idInPocket].y][map_itemPoses[idInPocket].x + 1] == 1)
                        map_itemPoses[idInPocket].x++;
            } else {
                  if (map_passMap[(int)map_itemPoses[idInPocket].y][map_itemPoses[idInPocket].x - 1] == 1)
                        map_itemPoses[idInPocket].x--;
            }
      }
}

void gob_swapItems(int16 indexToPick, int16 idToPick) {
      int16 layer;
      Gob_Object *pickObj;
      Gob_Object *placeObj;
      int16 idToPlace;
      int16 x;
      int16 y;

      pickObj = gob_objects[indexToPick];
      placeObj = gob_objects[gob_itemIndInPocket];

      idToPlace = gob_itemIdInPocket;
      pickObj->type = 3;
      gob_itemIndInPocket = indexToPick;
      gob_itemIdInPocket = idToPick;

      if (gob_itemByteFlag == 0) {
            for (y = 0; y < 28; y++) {
                  for (x = 0; x < 26; x++) {
                        if ((map_itemsMap[y][x] & 0xff) == idToPick)
                              map_itemsMap[y][x] =
                                  (map_itemsMap[y][x] & 0xff00) +
                                  idToPlace;
                  }
            }
      } else {

            for (y = 0; y < 28; y++) {
                  for (x = 0; x < 26; x++) {
                        if (((map_itemsMap[y][x] & 0xff00) >> 8) ==
                            idToPick)
                              map_itemsMap[y][x] =
                                  (map_itemsMap[y][x] & 0xff) +
                                  (idToPlace << 8);
                  }
            }
      }

      if (idToPick >= 0 && idToPick < 20) {
            map_itemPoses[idToPlace].x =
                map_itemPoses[gob_itemIdInPocket].x;
            map_itemPoses[idToPlace].y =
                map_itemPoses[gob_itemIdInPocket].y;
            map_itemPoses[idToPlace].orient =
                map_itemPoses[gob_itemIdInPocket].orient;

            map_itemPoses[gob_itemIdInPocket].x = 0;
            map_itemPoses[gob_itemIdInPocket].y = 0;
            map_itemPoses[gob_itemIdInPocket].orient = 0;
      }

      gob_itemIndInPocket = -1;
      gob_itemIdInPocket = 0;

      placeObj->type = 0;
      placeObj->nextState = -1;
      placeObj->multState = -1;
      placeObj->unk14 = 0;
      placeObj->toRedraw = 1;
      placeObj->curFrame = 0;
      placeObj->order = gob_goblins[0]->order;

      placeObj->animation =
          placeObj->stateMach[placeObj->state][0]->animation;

      layer =
          placeObj->stateMach[placeObj->state][placeObj->stateColumn]->layer;
      scen_updateAnim(layer, 0, placeObj->animation, 0, placeObj->xPos,
          placeObj->yPos, 0);

      placeObj->yPos +=
          (gob_gobPositions[0].y * 6) + 5 - scen_toRedrawBottom;

      if (map_itemPoses[idToPlace].orient == 4) {
            placeObj->xPos += (gob_gobPositions[0].x * 12 + 14)
                - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
      } else {
            placeObj->xPos += (gob_gobPositions[0].x * 12)
                - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
      }
}

void gob_treatItemPick(int16 itemId) {
      int16 itemIndex;
      Gob_Object *gobDesc;

      gobDesc = gob_goblins[gob_currentGoblin];

      if (gobDesc->curFrame != 9)
            return;

      if (gobDesc->stateMach != gobDesc->realStateMach)
            return;

      gob_readyToAct = 0;
      gob_goesAtTarget = 0;

      itemIndex = gob_itemToObject[itemId];
      if (itemId != 0 && itemIndex != -1
          && gob_objects[itemIndex]->pickable != 1)
            itemIndex = -1;

      if (gob_itemIndInPocket != -1 && gob_itemIndInPocket == itemIndex)
            itemIndex = -1;

      if (gob_itemIndInPocket != -1 && itemIndex != -1
          && gob_objects[itemIndex]->pickable == 1) {
            gob_swapItems(itemIndex, itemId);
            gob_itemIndInPocket = itemIndex;
            gob_itemIdInPocket = itemId;
            return;
      }

      if (gob_itemIndInPocket != -1 && itemIndex == -1) {
            gob_placeItem(gob_itemIndInPocket, gob_itemIdInPocket);
            return;
      }

      if (gob_itemIndInPocket == -1 && itemIndex != -1) {
            gob_pickItem(itemIndex, itemId);
            return;
      }
}

int16 gob_treatItem(int16 action) {
      int16 state;

      state = gob_goblins[gob_currentGoblin]->state;
      if ((state == 10 || state == 11) &&
          gob_goblins[gob_currentGoblin]->curFrame == 0) {
            gob_readyToAct = 0;
      }

      if (action == 3 && gob_currentGoblin == 0 &&
          (state == 10 || state == 11) && gob_goblins[0]->curFrame == 0) {
            gob_saveGobDataToVars(gob_gobPositions[gob_currentGoblin].x,
                gob_gobPositions[gob_currentGoblin].y, 0);
            gob_goesAtTarget = 1;
            return -1;
      }

      if (gob_noPick == 0 && gob_currentGoblin == 0 &&
          (state == 10 || state == 11)) {
            gob_treatItemPick(gob_destActionItem);

            gob_saveGobDataToVars(gob_gobPositions[gob_currentGoblin].x,
                gob_gobPositions[gob_currentGoblin].y, 0);
            return 0;
      }

      if (gob_goesAtTarget == 0) {
            gob_saveGobDataToVars(gob_gobPositions[gob_currentGoblin].x,
                gob_gobPositions[gob_currentGoblin].y, 0);
            return 0;
      } else {

            if (gob_itemToObject[gob_destActionItem] != 100 &&
                gob_destActionItem != 0) {

                  if (gob_itemToObject[gob_destActionItem] == -1) {
                        gob_actDestItemDesc = 0;
                  } else {
                        gob_actDestItemDesc =
                            gob_objects[gob_itemToObject
                            [gob_destActionItem]];
                  }
            }

            gob_goesAtTarget = 0;
            gob_saveGobDataToVars(gob_gobPositions[gob_currentGoblin].x,
                gob_gobPositions[gob_currentGoblin].y, 0);
            return gob_destActionItem;
      }
}

void gob_interFunc(void) {
      int16 cmd;
      int16 extraData = 0;
      Gob_Object *objDesc = NULL;
      Gob_Object *gobDesc;
      int16 xPos;
      int16 yPos;
      int16 x;
      int16 y;
      int16 item;
      int16 val;
      int16 layer;
      int16 state;
      int32 *retVarPtr;
      bool objDescSet = false;

      retVarPtr = (int32 *)VAR_ADDRESS(59);

      cmd = inter_load16();
      inter_execPtr += 2;
      if (cmd > 0 && cmd < 17) {
            extraData = inter_load16();
            objDesc = gob_objects[extraData];
            objDescSet = true;
            extraData = inter_load16();
      }

      if (cmd > 90 && cmd < 107) {
            extraData = inter_load16();
            objDesc = gob_goblins[extraData];
            objDescSet = true;
            extraData = inter_load16();
            cmd -= 90;
      }

      if (cmd > 110 && cmd < 128) {
            extraData = inter_load16();
            objDesc = gob_goblins[extraData];
            objDescSet = true;
            cmd -= 90;
      } else if (cmd > 20 && cmd < 38) {
            extraData = inter_load16();
            objDesc = gob_objects[extraData];
            objDescSet = true;
      }

/*
      NB: The original gobliiins engine did not initialize the objDesc
      variable, so we manually check if objDesc is properly set before
      checking if it is zero. If it was not set, we do not return. This
      fixes a crash in the EGA version if the life bar is depleted, because
      gob_interFunc is called multiple times with cmd == 39.
      Bug #1324814
*/


      if (cmd < 40 && objDescSet && objDesc == 0)
            return;

      debug(5, "cmd = %d", cmd);
      switch (cmd) {
      case 1:
            objDesc->state = extraData;

            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemStateVarPtr = extraData;
            break;

      case 2:
            objDesc->curFrame = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemFrameVarPtr = extraData;
            break;

      case 3:
            objDesc->nextState = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemNextStateVarPtr = extraData;
            break;

      case 4:
            objDesc->multState = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemMultStateVarPtr = extraData;
            break;

      case 5:
            objDesc->order = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemOrderVarPtr = extraData;
            break;

      case 6:
            objDesc->actionStartState = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemActStartStVarPtr = extraData;
            break;

      case 7:
            objDesc->curLookDir = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemLookDirVarPtr = extraData;
            break;

      case 8:
            objDesc->type = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemTypeVarPtr = extraData;

            if (extraData == 0)
                  objDesc->toRedraw = 1;
            break;

      case 9:
            objDesc->noTick = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemNoTickVarPtr = extraData;
            break;

      case 10:
            objDesc->pickable = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemPickableVarPtr = extraData;
            break;

      case 12:
            objDesc->xPos = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemScrXVarPtr = extraData;
            break;

      case 13:
            objDesc->yPos = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemScrYVarPtr = extraData;
            break;

      case 14:
            objDesc->doAnim = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemDoAnimVarPtr = extraData;
            break;

      case 15:
            objDesc->relaxTime = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemRelaxVarPtr = extraData;
            break;

      case 16:
            objDesc->maxTick = extraData;
            if (objDesc == gob_actDestItemDesc)
                  *gob_destItemMaxTickVarPtr = extraData;
            break;

      case 21:
            *retVarPtr = objDesc->state;
            break;

      case 22:
            *retVarPtr = objDesc->curFrame;
            break;

      case 23:
            *retVarPtr = objDesc->nextState;
            break;

      case 24:
            *retVarPtr = objDesc->multState;
            break;

      case 25:
            *retVarPtr = objDesc->order;
            break;

      case 26:
            *retVarPtr = objDesc->actionStartState;
            break;

      case 27:
            *retVarPtr = objDesc->curLookDir;
            break;

      case 28:
            *retVarPtr = objDesc->type;
            break;

      case 29:
            *retVarPtr = objDesc->noTick;
            break;

      case 30:
            *retVarPtr = objDesc->pickable;
            break;

      case 32:
            *retVarPtr = gob_getObjMaxFrame(objDesc);
            break;

      case 33:
            *retVarPtr = objDesc->xPos;
            break;

      case 34:
            *retVarPtr = objDesc->yPos;
            break;

      case 35:
            *retVarPtr = objDesc->doAnim;
            break;

      case 36:
            *retVarPtr = objDesc->relaxTime;
            break;

      case 37:
            *retVarPtr = objDesc->maxTick;
            break;

      case 40:
      case 42:
            xPos = inter_load16();
            yPos = inter_load16();
            item = inter_load16();

            if (cmd == 42) {
                  xPos = VAR(xPos);
                  yPos = VAR(yPos);
                  item = VAR(item);
            }

            for (y = 0; y < 28; y++) {
                  for (x = 0; x < 26; x++) {
                        if ((map_itemsMap[y][x] & 0xff) == item) {
                              map_itemsMap[y][x] &= 0xff00;
                        } else if (((map_itemsMap[y][x] & 0xff00) >> 8)
                            == item) {
                              map_itemsMap[y][x] &= 0xff;
                        }
                  }
            }

            if (xPos < 25) {
                  if (yPos > 0) {
                        if ((map_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                            (map_itemsMap[yPos - 1][xPos] & 0xff00) !=
                            0
                            || (map_itemsMap[yPos][xPos +
                                  1] & 0xff00) != 0
                            || (map_itemsMap[yPos - 1][xPos +
                                  1] & 0xff00) != 0) {

                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff00)
                                  + item;

                              map_itemsMap[yPos - 1][xPos] =
                                  (map_itemsMap[yPos -
                                    1][xPos] & 0xff00) + item;

                              map_itemsMap[yPos][xPos + 1] =
                                  (map_itemsMap[yPos][xPos +
                                    1] & 0xff00) + item;

                              map_itemsMap[yPos - 1][xPos + 1] =
                                  (map_itemsMap[yPos - 1][xPos +
                                    1] & 0xff00) + item;
                        } else {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff) +
                                  (item << 8);

                              map_itemsMap[yPos - 1][xPos] =
                                  (map_itemsMap[yPos -
                                    1][xPos] & 0xff) + (item << 8);

                              map_itemsMap[yPos][xPos + 1] =
                                  (map_itemsMap[yPos][xPos +
                                    1] & 0xff) + (item << 8);

                              map_itemsMap[yPos - 1][xPos + 1] =
                                  (map_itemsMap[yPos - 1][xPos +
                                    1] & 0xff) + (item << 8);
                        }
                  } else {
                        if ((map_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                            (map_itemsMap[yPos][xPos + 1] & 0xff00) !=
                            0) {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff00)
                                  + item;

                              map_itemsMap[yPos][xPos + 1] =
                                  (map_itemsMap[yPos][xPos +
                                    1] & 0xff00) + item;
                        } else {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff) +
                                  (item << 8);

                              map_itemsMap[yPos][xPos + 1] =
                                  (map_itemsMap[yPos][xPos +
                                    1] & 0xff) + (item << 8);
                        }
                  }
            } else {
                  if (yPos > 0) {
                        if ((map_itemsMap[yPos][xPos] & 0xff00) != 0 ||
                            (map_itemsMap[yPos - 1][xPos] & 0xff00) !=
                            0) {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff00)
                                  + item;

                              map_itemsMap[yPos - 1][xPos] =
                                  (map_itemsMap[yPos -
                                    1][xPos] & 0xff00) + item;
                        } else {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff) +
                                  (item << 8);

                              map_itemsMap[yPos - 1][xPos] =
                                  (map_itemsMap[yPos -
                                    1][xPos] & 0xff) + (item << 8);
                        }
                  } else {
                        if ((map_itemsMap[yPos][xPos] & 0xff00) != 0) {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff00)
                                  + item;
                        } else {
                              map_itemsMap[yPos][xPos] =
                                  (map_itemsMap[yPos][xPos] & 0xff) +
                                  (item << 8);
                        }
                  }
            }

            if (item < 0 || item >= 20)
                  break;

            if (xPos > 1 && map_passMap[yPos][xPos - 2] == 1) {
                  map_itemPoses[item].x = xPos - 2;
                  map_itemPoses[item].y = yPos;
                  map_itemPoses[item].orient = 4;
                  break;
            }

            if (xPos < 24 && map_passMap[yPos][xPos + 2] == 1) {
                  map_itemPoses[item].x = xPos + 2;
                  map_itemPoses[item].y = yPos;
                  map_itemPoses[item].orient = 0;
                  break;
            }

            if (xPos < 25 && map_passMap[yPos][xPos + 1] == 1) {
                  map_itemPoses[item].x = xPos + 1;
                  map_itemPoses[item].y = yPos;
                  map_itemPoses[item].orient = 0;
                  break;
            }

            if (xPos > 0 && map_passMap[yPos][xPos - 1] == 1) {
                  map_itemPoses[item].x = xPos - 1;
                  map_itemPoses[item].y = yPos;
                  map_itemPoses[item].orient = 4;
                  break;
            }
            break;

      case 41:
      case 43:
            xPos = inter_load16();
            yPos = inter_load16();

            if (cmd == 43) {
                  xPos = VAR(xPos);
                  yPos = VAR(yPos);
            }

            if ((map_itemsMap[yPos][xPos] & 0xff00) != 0) {
                  *retVarPtr = (map_itemsMap[yPos][xPos] & 0xff00) >> 8;
            } else {
                  *retVarPtr = map_itemsMap[yPos][xPos];
            }
            break;

      case 44:
            xPos = inter_load16();
            yPos = inter_load16();
            val = inter_load16();
            map_passMap[yPos][xPos] = val;
            break;

      case 50:
            item = inter_load16();
            xPos = inter_load16();
            yPos = inter_load16();

            gob_gobPositions[item].x = xPos * 2;
            gob_gobPositions[item].y = yPos * 2;

            objDesc = gob_goblins[item];
            objDesc->nextState = 21;

            gob_nextLayer(objDesc);

            layer = objDesc->stateMach[objDesc->state][0]->layer;

            scen_updateAnim(layer, 0, objDesc->animation, 0,
                objDesc->xPos, objDesc->yPos, 0);

            objDesc->yPos =
                (gob_gobPositions[item].y * 6 + 6) - (scen_toRedrawBottom -
                scen_animTop);
            objDesc->xPos =
                gob_gobPositions[item].x * 12 - (scen_toRedrawLeft -
                scen_animLeft);

            objDesc->curFrame = 0;
            objDesc->state = 21;
            if (gob_currentGoblin == item) {
                  *gob_curGobScrXVarPtr = objDesc->xPos;
                  *gob_curGobScrYVarPtr = objDesc->yPos;

                  *gob_curGobFrameVarPtr = 0;
                  *gob_curGobStateVarPtr = 18;
                  gob_pressedMapX = gob_gobPositions[item].x;
                  gob_pressedMapY = gob_gobPositions[item].y;
            }
            break;

      case 52:
            item = inter_load16();
            *retVarPtr = gob_gobPositions[item].x >> 1;
            break;

      case 53:
            item = inter_load16();
            *retVarPtr = gob_gobPositions[item].y >> 1;
            break;

      case 150:
            item = inter_load16();
            xPos = inter_load16();
            yPos = inter_load16();

            objDesc = gob_goblins[item];
            if (yPos == 0) {
                  objDesc->multState = xPos;
                  objDesc->nextState = xPos;
                  gob_nextLayer(objDesc);

                  layer = objDesc->stateMach[objDesc->state][0]->layer;

                  objDesc->xPos =
                      scen_animations[objDesc->animation].layers[layer]->
                      posX;
                  objDesc->yPos =
                      scen_animations[objDesc->animation].layers[layer]->
                      posY;

                  *gob_curGobScrXVarPtr = objDesc->xPos;
                  *gob_curGobScrYVarPtr = objDesc->yPos;
                  *gob_curGobFrameVarPtr = 0;
                  *gob_curGobStateVarPtr = objDesc->state;
                  *gob_curGobNextStateVarPtr = objDesc->nextState;
                  *gob_curGobMultStateVarPtr = objDesc->multState;
                  *gob_curGobMaxFrameVarPtr =
                      gob_getObjMaxFrame(objDesc);
                  gob_noPick = 1;
                  break;
            }

            objDesc->multState = 21;
            objDesc->nextState = 21;
            objDesc->state = 21;
            gob_nextLayer(objDesc);
            layer = objDesc->stateMach[objDesc->state][0]->layer;

            scen_updateAnim(layer, 0, objDesc->animation, 0,
                objDesc->xPos, objDesc->yPos, 0);

            objDesc->yPos =
                (yPos * 6 + 6) - (scen_toRedrawBottom - scen_animTop);
            objDesc->xPos =
                xPos * 12 - (scen_toRedrawLeft - scen_animLeft);

            gob_gobPositions[item].x = xPos;
            gob_pressedMapX = xPos;
            map_curGoblinX = xPos;

            gob_gobPositions[item].y = yPos;
            gob_pressedMapY = yPos;
            map_curGoblinY = yPos;

            *gob_curGobScrXVarPtr = objDesc->xPos;
            *gob_curGobScrYVarPtr = objDesc->yPos;
            *gob_curGobFrameVarPtr = 0;
            *gob_curGobStateVarPtr = 21;
            *gob_curGobNextStateVarPtr = 21;
            *gob_curGobMultStateVarPtr = -1;
            gob_noPick = 0;
            break;

      case 250:
            item = inter_load16();
            xPos = inter_load16();
            yPos = inter_load16();

            gob_gobPositions[item].x = xPos;
            gob_gobPositions[item].y = yPos;

            objDesc = gob_goblins[item];
            objDesc->nextState = 21;
            gob_nextLayer(objDesc);

            layer = objDesc->stateMach[objDesc->state][0]->layer;

            scen_updateAnim(layer, 0, objDesc->animation, 0,
                objDesc->xPos, objDesc->yPos, 0);

            objDesc->yPos =
                (yPos * 6 + 6) - (scen_toRedrawBottom - scen_animTop);
            objDesc->xPos =
                xPos * 12 - (scen_toRedrawLeft - scen_animLeft);

            objDesc->curFrame = 0;
            objDesc->state = 21;

            if (gob_currentGoblin == item) {
                  *gob_curGobScrXVarPtr = objDesc->xPos;
                  *gob_curGobScrYVarPtr = objDesc->yPos;
                  *gob_curGobFrameVarPtr = 0;
                  *gob_curGobStateVarPtr = 18;

                  gob_pressedMapX = gob_gobPositions[item].x;
                  gob_pressedMapY = gob_gobPositions[item].y;
            }
            break;

      case 251:
            item = inter_load16();
            state = inter_load16();

            objDesc = gob_goblins[item];
            objDesc->nextState = state;

            gob_nextLayer(objDesc);
            layer = objDesc->stateMach[objDesc->state][0]->layer;

            objDesc->xPos =
                scen_animations[objDesc->animation].layers[layer]->posX;
            objDesc->yPos =
                scen_animations[objDesc->animation].layers[layer]->posY;

            if (item == gob_currentGoblin) {
                  *gob_curGobScrXVarPtr = objDesc->xPos;
                  *gob_curGobScrYVarPtr = objDesc->yPos;
                  *gob_curGobFrameVarPtr = 0;
                  *gob_curGobStateVarPtr = objDesc->state;
                  *gob_curGobMultStateVarPtr = objDesc->multState;
            }
            break;

      case 252:
            item = inter_load16();
            state = inter_load16();
            objDesc = gob_objects[item];

            objDesc->nextState = state;

            gob_nextLayer(objDesc);
            layer = objDesc->stateMach[objDesc->state][0]->layer;
            objDesc->xPos =
                scen_animations[objDesc->animation].layers[layer]->posX;
            objDesc->yPos =
                scen_animations[objDesc->animation].layers[layer]->posY;

            objDesc->toRedraw = 1;
            objDesc->type = 0;
            if (objDesc == gob_actDestItemDesc) {
                  *gob_destItemScrXVarPtr = objDesc->xPos;
                  *gob_destItemScrYVarPtr = objDesc->yPos;

                  *gob_destItemStateVarPtr = objDesc->state;
                  *gob_destItemNextStateVarPtr = -1;
                  *gob_destItemMultStateVarPtr = -1;
                  *gob_destItemFrameVarPtr = 0;
            }
            break;

      case 152:
            item = inter_load16();
            val = inter_load16();
            objDesc = gob_objects[item];
            objDesc->unk14 = val;
            break;

      case 200:
            gob_itemIdInPocket = inter_load16();
            break;

      case 201:
            gob_itemIndInPocket = inter_load16();
            break;

      case 202:
            *retVarPtr = gob_itemIdInPocket;
            break;

      case 203:
            *retVarPtr = gob_itemIndInPocket;
            break;

      case 204:
            item = inter_load16();
            xPos = inter_load16();
            yPos = inter_load16();
            val = inter_load16();

            map_itemPoses[item].x = xPos;
            map_itemPoses[item].y = yPos;
            map_itemPoses[item].orient = val;
            break;

      case 500:
            extraData = inter_load16();
            objDesc = gob_objects[extraData];

            objDesc->relaxTime--;
            if (objDesc->relaxTime < 0 &&
                gob_getObjMaxFrame(objDesc) == objDesc->curFrame) {
                  objDesc->relaxTime = util_getRandom(100) + 50;
                  objDesc->curFrame = 0;
                  objDesc->toRedraw = 1;
            }
            break;

      case 502:
            item = inter_load16();
            *retVarPtr = gob_gobPositions[item].x;
            break;

      case 503:
            item = inter_load16();
            *retVarPtr = gob_gobPositions[item].y;
            break;

      case 600:
            gob_pathExistence = 0;
            break;

      case 601:
            extraData = inter_load16();
            gob_goblins[extraData]->visible = 1;
            break;

      case 602:
            extraData = inter_load16();
            gob_goblins[extraData]->visible = 0;
            break;

      case 603:
            extraData = inter_load16();
            item = inter_load16();

            objDesc = gob_objects[extraData];
            if (gob_objIntersected(objDesc, gob_goblins[item]) != 0)
                  *retVarPtr = 1;
            else
                  *retVarPtr = 0;
            break;

      case 604:
            extraData = inter_load16();
            item = inter_load16();

            objDesc = gob_goblins[extraData];
            if (gob_objIntersected(objDesc, gob_goblins[item]) != 0)
                  *retVarPtr = 1;
            else
                  *retVarPtr = 0;
            break;

      case 605:
            item = inter_load16();
            xPos = inter_load16();
            yPos = inter_load16();
            val = inter_load16();

            map_itemPoses[item].x = xPos;
            map_itemPoses[item].y = yPos;
            map_itemPoses[item].orient = val;
            break;

      case 1000:
            extraData = inter_load16();
            if (game_extHandle >= 0)
                  data_closeData(game_extHandle);

            gob_loadObjects((char *)VAR_ADDRESS(extraData));
            game_extHandle = data_openData(game_curExtFile);
            break;

      case 1001:
            gob_freeAllObjects();
            break;

      case 1002:
            gob_animateObjects();
            break;

      case 1003:
            gob_drawObjects();

            if (cd_getTrackPos() == -1)
                  cd_playBgMusic();
            break;

      case 1004:
            map_loadMapsInitGobs();
            break;

      case 1005:
            extraData = inter_load16();
            xPos = inter_load16();

            if ((uint16)VAR(xPos) == 0) {
                  item =
                      gob_doMove(gob_goblins[gob_currentGoblin], 1,
                      (uint16)VAR(extraData));
            } else {
                  item =
                      gob_doMove(gob_goblins[gob_currentGoblin], 1, 3);
            }

            if (item != 0)
                  gob_switchGoblin(item);
            break;

      case 1006:
            gob_switchGoblin(0);
            break;

      case 1008:
            gob_loadGobDataFromVars();
            break;

      case 1009:
            extraData = inter_load16();
            cmd = inter_load16();
            xPos = inter_load16();

            if ((uint16)VAR(xPos) == 0) {
                  WRITE_VAR(cmd, gob_treatItem((uint16)VAR(extraData)));
                  break;
            }

            WRITE_VAR(cmd, gob_treatItem(3));
            break;

      case 1010:
            gob_doMove(gob_goblins[gob_currentGoblin], 0, 0);
            break;

      case 1011:
            extraData = inter_load16();
            if (VAR(extraData) != 0)
                  gob_goesAtTarget = 1;
            else
                  gob_goesAtTarget = 0;
            break;

      case 1015:
            extraData = inter_load16();
            extraData = VAR(extraData);
            gob_objects[10]->xPos = extraData;

            extraData = inter_load16();
            extraData = VAR(extraData);
            gob_objects[10]->yPos = extraData;
            break;

      case 2005:
            gobDesc = gob_goblins[0];
            if (gob_currentGoblin != 0) {
                  gob_goblins[gob_currentGoblin]->doAnim = 1;
                  gob_goblins[gob_currentGoblin]->nextState = 21;

                  gob_nextLayer(gob_goblins[gob_currentGoblin]);
                  gob_currentGoblin = 0;

                  gobDesc->doAnim = 0;
                  gobDesc->type = 0;
                  gobDesc->toRedraw = 1;

                  gob_pressedMapX = gob_gobPositions[0].x;
                  map_destX = gob_gobPositions[0].x;
                  gob_gobDestX = gob_gobPositions[0].x;

                  gob_pressedMapY = gob_gobPositions[0].y;
                  map_destY = gob_gobPositions[0].y;
                  gob_gobDestY = gob_gobPositions[0].y;

                  *gob_curGobVarPtr = 0;
                  gob_pathExistence = 0;
                  gob_readyToAct = 0;
            }

            if (gobDesc->state != 10 && gob_itemIndInPocket != -1 &&
                gob_getObjMaxFrame(gobDesc) == gobDesc->curFrame) {

                  gobDesc->stateMach = gobDesc->realStateMach;
                  xPos = gob_gobPositions[0].x;
                  yPos = gob_gobPositions[0].y;

                  gobDesc->nextState = 10;
                  layer = gob_nextLayer(gobDesc);

                  scen_updateAnim(layer, 0, gobDesc->animation, 0,
                      gobDesc->xPos, gobDesc->yPos, 0);

                  gobDesc->yPos =
                      (yPos * 6 + 6) - (scen_toRedrawBottom -
                      scen_animTop);
                  gobDesc->xPos =
                      xPos * 12 - (scen_toRedrawLeft - scen_animLeft);
            }

            if (gobDesc->state != 10)
                  break;

            if (gob_itemIndInPocket == -1)
                  break;

            if (gobDesc->curFrame != 10)
                  break;

            objDesc = gob_objects[gob_itemIndInPocket];
            objDesc->type = 0;
            objDesc->toRedraw = 1;
            objDesc->curFrame = 0;

            objDesc->order = gobDesc->order;
            objDesc->animation =
                objDesc->stateMach[objDesc->state][0]->animation;

            layer = objDesc->stateMach[objDesc->state][0]->layer;

            scen_updateAnim(layer, 0, objDesc->animation, 0,
                objDesc->xPos, objDesc->yPos, 0);

            objDesc->yPos +=
                (gob_gobPositions[0].y * 6 + 5) - scen_toRedrawBottom;

            if (gobDesc->curLookDir == 4) {
                  objDesc->xPos += gob_gobPositions[0].x * 12 + 14
                      - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
            } else {
                  objDesc->xPos += gob_gobPositions[0].x * 12
                      - (scen_toRedrawLeft + scen_toRedrawRight) / 2;
            }

            gob_itemIndInPocket = -1;
            gob_itemIdInPocket = -1;
            util_beep(50);
            break;

      default:
            warning("gob_interFunc: Unknown command %d!", cmd);
            inter_execPtr -= 2;
            cmd = inter_load16();
            inter_execPtr += cmd * 2;
            break;
      }
      return;
}

} // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index