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

goblin_v1.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-2006 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-9-1/engines/gob/goblin_v1.cpp $
 * $Id: goblin_v1.cpp 23065 2006-06-12 21:33:30Z drmccoy $
 *
 */

#include "common/stdafx.h"
#include "common/endian.h"

#include "gob/gob.h"
#include "gob/goblin.h"
#include "gob/scenery.h"
#include "gob/map.h"

namespace Gob {

Goblin_v1::Goblin_v1(GobEngine *vm) : Goblin(vm) {
      _rotStates[0][0] = 0; _rotStates[0][1] = 22; _rotStates[0][2] = 23; _rotStates[0][3] = 24;
      _rotStates[1][0] = 13; _rotStates[1][1] = 2; _rotStates[1][2] = 12; _rotStates[1][3] = 14;
      _rotStates[2][0] = 16; _rotStates[2][1] = 15; _rotStates[2][2] = 4; _rotStates[2][3] = 17;
      _rotStates[3][0] = 27; _rotStates[3][1] = 25; _rotStates[3][2] = 26; _rotStates[3][3] = 6;
}

void Goblin_v1::freeObjects(void) {
      int16 i;
      int16 state;
      int16 col;

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

            _vm->_snd->freeSoundDesc(_soundData[i]);
            _soundData[i] = 0;
      }

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

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

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

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

            delete[] _goblins[i]->stateMach;
            delete _goblins[i];
            _goblins[i] = 0;
      }

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

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

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

            delete[] _objects[i]->stateMach;
            delete _objects[i];
            _objects[i] = 0;
      }
}

void Goblin_v1::placeObject(Gob_Object *objDesc, char animated,
            int16 index, int16 x, int16 y, int16 state) {
      int16 layer;

      if (objDesc->stateMach[objDesc->state][0] != 0) {
            objDesc->animation =
                objDesc->stateMach[objDesc->state][0]->animation;

            objDesc->noTick = 0;
            objDesc->toRedraw = 1;
            objDesc->doAnim = animated;

            objDesc->maxTick = 1;
            objDesc->tick = 1;
            objDesc->curFrame = 0;
            objDesc->type = 0;
            objDesc->actionStartState = 0;
            objDesc->nextState = -1;
            objDesc->multState = -1;
            objDesc->stateColumn = 0;
            objDesc->curLookDir = 0;
            objDesc->visible = 1;
            objDesc->pickable = 0;
            objDesc->unk14 = 0;

            objDesc->relaxTime = _vm->_util->getRandom(30);

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

            objDesc->order = _vm->_scenery->_toRedrawBottom / 24 + 3;

            objDesc->left = objDesc->xPos;
            objDesc->right = objDesc->xPos;
            objDesc->dirtyLeft = objDesc->xPos;
            objDesc->dirtyRight = objDesc->xPos;

            objDesc->top = objDesc->yPos;
            objDesc->bottom = objDesc->yPos;
            objDesc->dirtyTop = objDesc->yPos;
            objDesc->dirtyBottom = objDesc->yPos;

            _vm->_util->listInsertBack(_objList, objDesc);
      }
}

void Goblin_v1::initiateMove(Mult::Mult_Object *obj) {
      _vm->_map->findNearestToDest(0);
      _vm->_map->findNearestToGob(0);
      _vm->_map->optimizePoints(0, 0, 0);

      _pathExistence = _vm->_map->checkDirectPath(0, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
          _pressedMapX, _pressedMapY);

      if (_pathExistence == 3) {
            if (_vm->_map->checkLongPath(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
                  _pressedMapX, _pressedMapY,
                  _vm->_map->_nearestWayPoint, _vm->_map->_nearestDest) == 0) {
                  _pathExistence = 0;
            } else {
                  _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x;
                  _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y;
            }
      }
}

void Goblin_v1::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 nextAct) {
      if (_pathExistence == 1) {
            _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
            _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;

            if (_vm->_map->_curGoblinX == _pressedMapX &&
                _vm->_map->_curGoblinY == _pressedMapY && _gobAction != 0) {
                  _readyToAct = 1;
                  _pathExistence = 0;
            }

            nextAct = _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
                _vm->_map->_destX, _vm->_map->_destY);

            if (nextAct == 0)
                  _pathExistence = 0;
      } else if (_pathExistence == 3) {
            _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
            _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;

            if (_vm->_map->_curGoblinX == _gobDestX && _vm->_map->_curGoblinY == _gobDestY) {
                  _pathExistence = 1;
                  _vm->_map->_destX = _pressedMapX;
                  _vm->_map->_destY = _pressedMapY;
            } else {

                  if (_vm->_map->checkDirectPath(0, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
                        _gobDestX, _gobDestY) == 1) {
                        _vm->_map->_destX = _gobDestX;
                        _vm->_map->_destY = _gobDestY;
                  } else if (_vm->_map->_curGoblinX == _vm->_map->_destX && _vm->_map->_curGoblinY == _vm->_map->_destY) {

                        if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) {
                              _vm->_map->optimizePoints(0, 0, 0);

                              _vm->_map->_destX =
                                  _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
                                  x;
                              _vm->_map->_destY =
                                  _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
                                  y;

                              if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest)
                                    _vm->_map->_nearestWayPoint--;
                        } else if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) {
                              _vm->_map->optimizePoints(0, 0, 0);

                              _vm->_map->_destX =
                                  _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
                                  x;
                              _vm->_map->_destY =
                                  _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].
                                  y;

                              if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest)
                                    _vm->_map->_nearestWayPoint++;
                        } else {
                              if (_vm->_map->checkDirectPath(0, _vm->_map->_curGoblinX,
                                    _vm->_map->_curGoblinY, _gobDestX,
                                    _gobDestY) == 3 && _vm->_map->getPass(_pressedMapX, _pressedMapY) != 0) {
                                    _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x;
                                    _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y;
                              } else {
                                    _pathExistence = 1;
                                    _vm->_map->_destX = _pressedMapX;
                                    _vm->_map->_destY = _pressedMapY;
                              }
                        }
                  }
                  nextAct =
                      _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY,
                      _vm->_map->_destX, _vm->_map->_destY);
            }
      }

      if (_readyToAct != 0 && (_gobAction == 3 || _gobAction == 4))
            nextAct = 0x4dc8;

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

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

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

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

      case Map::kDirN:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) {
                  gobDesc->nextState = 8;
                  break;
            }

            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6 &&
                _currentGoblin == 1) {
                  gobDesc->nextState = 28;
                  break;
            }

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

      case Map::kDirS:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3) {
                  gobDesc->nextState = 9;
                  break;
            }

            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6 &&
                _currentGoblin == 1) {
                  gobDesc->nextState = 29;
                  break;
            }

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

      case Map::kDirSE:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY + 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

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

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

      case Map::kDirSW:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY + 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

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

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

      case Map::kDirNW:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY - 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

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

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

      case Map::kDirNE:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY - 1) == 6 &&
                _currentGoblin != 1) {
                  _pathExistence = 0;
                  break;
            }

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

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

      case 0x4dc8:

            if (_currentGoblin == 0 && _gobAction == 3
                && _itemIndInPocket == -1) {
                  _destItemId = -1;
                  _readyToAct = 0;
                  break;
            }

            if (_currentGoblin == 0 && _gobAction == 4 &&
                _itemIndInPocket == -1 && _destActionItem == 0) {
                  gobDesc->multState = 104;
                  _destItemId = -1;
                  _readyToAct = 0;
                  break;
            }

            if (_currentGoblin == 0 && _gobAction == 4 &&
                _itemIndInPocket == -1 && _destActionItem != 0 &&
                _itemToObject[_destActionItem] != -1 &&
                _objects[_itemToObject[_destActionItem]]->
                pickable == 0) {
                  gobDesc->multState = 104;
                  _destItemId = -1;
                  _readyToAct = 0;
                  break;
            }

            switch (_vm->_map->_itemPoses[_destActionItem].orient) {
            case 0:
            case -4:
                  gobDesc->nextState = 10;
                  gobDesc->curLookDir = 0;
                  _destItemId = -1;
                  break;

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

      default:
            if (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 3 ||
                (_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY) == 6
                  && _currentGoblin == 1)) {
                  gobDesc->nextState = 20;
                  break;
            }

            switch (gobDesc->curLookDir) {
            case 2:
            case 4:
                  gobDesc->nextState = 18;
                  break;

            case 6:
            case 0:
                  gobDesc->nextState = 19;
                  break;
            }
            break;
      }
      return;
}

void Goblin_v1::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
            int16 nextAct, int16 framesCount) {
      int16 i;
      int16 newX;
      int16 newY;
      int16 flag;

      movePathFind(0, gobDesc, nextAct);

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

      if (_goesAtTarget == 0
          && gobDesc->stateMach == gobDesc->realStateMach) {
            switch (gobDesc->state) {
            case 0:
            case 1:
            case 7:
            case 13:
            case 16:
            case 27:
                  gobDesc->curLookDir = 0;
                  break;

            case 3:
            case 4:
            case 5:
            case 12:
            case 23:
            case 26:
                  gobDesc->curLookDir = 4;
                  break;

            case 28:
                  if (_currentGoblin != 1)
                        break;
                  gobDesc->curLookDir = 2;
                  break;

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

            case 29:
                  if (_currentGoblin != 1)
                        break;

                  gobDesc->curLookDir = 6;
                  break;

            case 6:
            case 9:
            case 14:
            case 17:
            case 24:
                  gobDesc->curLookDir = 6;
                  break;
            }
      }

      if (gobDesc->state >= 0 && gobDesc->state < 10 &&
          gobDesc->stateMach == gobDesc->realStateMach &&
          (gobDesc->curFrame == 3 || gobDesc->curFrame == 6)) {
            _vm->_snd->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5);
      }

      if (_currentGoblin == 0
          && gobDesc->stateMach == gobDesc->realStateMach
          && (gobDesc->state == 10 || gobDesc->state == 11)
          && gobDesc->curFrame == 9) {
            _vm->_snd->stopSound(0);
            if (_itemIndInPocket != -1) {
                  _vm->_snd->playSample(_soundData[14], 1, 9000);
            }

            if (_itemIndInPocket == -1) {
                  _vm->_snd->playSample(_soundData[14], 1, 5000);
            }
      }

      if (_boreCounter++ == 120) {
            _boreCounter = 0;
            for (i = 0; i < 3; i++)
                  showBoredom(i);
      }

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

            newX =
                _vm->_scenery->_animations[gobDesc->animation].
                layers[_gobStateLayer].animDeltaX + gobDesc->xPos;

            newY =
                _vm->_scenery->_animations[gobDesc->animation].
                layers[_gobStateLayer].animDeltaY + gobDesc->yPos;

            _gobStateLayer = nextLayer(gobDesc);

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

                  _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
                  _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;

                  if (gobDesc->nextState != gobDesc->state) {
                        _gobStateLayer = nextLayer(gobDesc);
                        flag = 1;
                  }

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

                  case 2:
                  case 8:
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 4:
                        _gobPositions[_currentGoblin].x++;
                        break;

                  case 6:
                  case 9:
                        _gobPositions[_currentGoblin].y++;
                        break;

                  case 1:
                        _gobPositions[_currentGoblin].x--;
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 3:
                        _gobPositions[_currentGoblin].x++;
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 5:
                        _gobPositions[_currentGoblin].x++;
                        _gobPositions[_currentGoblin].y++;
                        break;

                  case 7:
                        _gobPositions[_currentGoblin].x--;
                        _gobPositions[_currentGoblin].y++;
                        break;

                  case 38:
                        _gobPositions[_currentGoblin].y++;
                        break;
                  }

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

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

                  if (flag != 0) {
                        _vm->_scenery->updateAnim(_gobStateLayer, 0,
                            gobDesc->animation, 0, gobDesc->xPos,
                            gobDesc->yPos, 0);

                        gobDesc->yPos =
                            (_vm->_map->_curGoblinY + 1) * 6 -
                            (_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
                        gobDesc->xPos =
                            _vm->_map->_curGoblinX * 12 - (_vm->_scenery->_toRedrawLeft -
                            _vm->_scenery->_animLeft);
                  }

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

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

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

            _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x;
            _vm->_map->_curGoblinY = _gobPositions[_currentGoblin].y;

            _gobStateLayer = nextLayer(gobDesc);
            if (gobDesc->stateMach == gobDesc->realStateMach) {

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

                  case 2:
                  case 8:
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 4:
                        _gobPositions[_currentGoblin].x++;
                        break;

                  case 6:
                  case 9:
                        _gobPositions[_currentGoblin].y++;
                        break;

                  case 1:
                        _gobPositions[_currentGoblin].x--;
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 3:
                        _gobPositions[_currentGoblin].x++;
                        _gobPositions[_currentGoblin].y--;
                        break;

                  case 5:
                        _gobPositions[_currentGoblin].x++;
                        _gobPositions[_currentGoblin].y++;
                        break;

                  case 7:
                        _gobPositions[_currentGoblin].x--;
                        _gobPositions[_currentGoblin].y++;
                        break;

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

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

            _vm->_scenery->updateAnim(_gobStateLayer, 0, gobDesc->animation, 0,
                gobDesc->xPos, gobDesc->yPos, 0);

            gobDesc->yPos =
                (_vm->_map->_curGoblinY + 1) * 6 - (_vm->_scenery->_toRedrawBottom -
                _vm->_scenery->_animTop);
            gobDesc->xPos =
                _vm->_map->_curGoblinX * 12 - (_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);

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

} // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index