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

actor_walk.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/saga/actor_walk.cpp $
 * $Id: actor_walk.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "saga/saga.h"

#include "saga/actor.h"
#include "saga/console.h"
#include "saga/events.h"
#include "saga/isomap.h"
#include "saga/objectmap.h"
#include "saga/sagaresnames.h"
#include "saga/script.h"
#include "saga/sound.h"
#include "saga/scene.h"

namespace Saga {

static const int angleLUT[16][2] = {
      {    0, -256 },
      {   98, -237 },
      {  181, -181 },
      {  237,  -98 },
      {  256,    0 },
      {  237,       98 },
      {  181,  181 },
      {   98,  237 },
      {    0,  256 },
      {  -98,  237 },
      { -181,  181 },
      { -237,   98 },
      { -256,    0 },
      { -237,  -98 },
      { -181, -181 },
      {  -98, -237 }
};

static const int directionLUT[8][2] = {
      {  0 * 2, -2 * 2 },
      {  2 * 2, -1 * 2 },
      {  3 * 2,  0 * 2 },
      {  2 * 2,  1 * 2 },
      {  0 * 2,  2 * 2 },
      { -2 * 2,  1 * 2 },
      { -4 * 2,  0 * 2 },
      { -2 * 2, -1 * 2 }
};

static const int tileDirectionLUT[8][2] = {
      {  1,  1 },
      {  2,  0 },
      {  1, -1 },
      {  0, -2 },
      { -1, -1 },
      { -2,  0 },
      { -1,  1 },
      {  0,  2 }
};

struct DragonMove {
      uint16 baseFrame;
      int16 offset[4][2];
};

static const DragonMove dragonMoveTable[12] = {
      {  0, { {  0,  0 }, {  0,  0 }, {   0,   0 }, {   0,   0 } } },
      {  0, { {  0,  0 }, {  0,  0 }, {   0,   0 }, {   0,   0 } } },
      {  0, { {  0,  0 }, {  0,  0 }, {   0,   0 }, {   0,   0 } } },
      {  0, { {  0,  0 }, {  0,  0 }, {   0,   0 }, {   0,   0 } } },
      { 28, { { -0,  0 }, { -1,  6 }, {  -5,  11 }, { -10,  15 } } },
      { 56, { {  0,  0 }, {  1,  6 }, {   5,  11 }, {  10,  15 } } },
      { 40, { {  0,  0 }, {  6,  1 }, {  11,   5 }, {  15,  10 } } },
      { 44, { {  0,  0 }, {  6, -1 }, {  11,  -5 }, {  15, -10 } } },
      { 32, { { -0, -0 }, { -6, -1 }, { -11,  -5 }, { -15, -10 } } },
      { 52, { { -0,  0 }, { -6,  1 }, { -11,   5 }, { -15,  10 } } },
      { 36, { {  0, -0 }, {  1, -6 }, {   5, -11 }, {  10, -15 } } },
      { 48, { { -0, -0 }, { -1, -6 }, {  -5, -11 }, { -10, -15 } } }
};

bool Actor::validFollowerLocation(const Location &location) {
      Point point;
      location.toScreenPointXY(point);

      if ((point.x < 5) || (point.x >= _vm->getDisplayWidth() - 5) ||
            (point.y < 0) || (point.y > _vm->_scene->getHeight())) {
            return false;
      }

      return (_vm->_scene->canWalk(point));
}

void Actor::realLocation(Location &location, uint16 objectId, uint16 walkFlags) {
      int angle;
      int distance;
      ActorData *actor;
      ObjectData *obj;
      debug (8, "Actor::realLocation objectId=%i", objectId);
      if (walkFlags & kWalkUseAngle) {
            if (_vm->_scene->getFlags() & kSceneFlagISO) {
                  angle = (location.x + 2) & 15;
                  distance = location.y;

                  location.u() = (angleLUT[angle][0] * distance) >> 8;
                  location.v() = -(angleLUT[angle][1] * distance) >> 8;
            } else {
                  angle = location.x & 15;
                  distance = location.y;

                  location.x = (angleLUT[angle][0] * distance) >> 6;
                  location.y = (angleLUT[angle][1] * distance) >> 6;
            }
      }

      if (objectId != ID_NOTHING) {
            if (validActorId(objectId)) {
                  actor = getActor(objectId);
                  location.addXY(actor->_location);
            } else if (validObjId(objectId)) {
                  obj = getObj(objectId);
                  location.addXY(obj->_location);
            }
      }
}

void Actor::actorFaceTowardsObject(uint16 actorId, uint16 objectId) {
      ActorData *actor;
      ObjectData *obj;

      if (validActorId(objectId)) {
            actor = getActor(objectId);
            actorFaceTowardsPoint(actorId, actor->_location);
      } else if (validObjId(objectId)) {
            obj = getObj(objectId);
            actorFaceTowardsPoint(actorId, obj->_location);
      }
}

void Actor::actorFaceTowardsPoint(uint16 actorId, const Location &toLocation) {
      ActorData *actor;
      Location delta;
      //debug (8, "Actor::actorFaceTowardsPoint actorId=%i", actorId);
      actor = getActor(actorId);

      toLocation.delta(actor->_location, delta);

      if (_vm->_scene->getFlags() & kSceneFlagISO) {
            if (delta.u() > 0) {
                  actor->_facingDirection = (delta.v() > 0) ? kDirUp : kDirRight;
            } else {
                  actor->_facingDirection = (delta.v() > 0) ? kDirLeft : kDirDown;
            }
      } else {
            if (ABS(delta.y) > ABS(delta.x * 2)) {
                  actor->_facingDirection = (delta.y > 0) ? kDirDown : kDirUp;
            } else {
                  actor->_facingDirection = (delta.x > 0) ? kDirRight : kDirLeft;
            }
      }
}

void Actor::updateActorsScene(int actorsEntrance) {
      int i, j;
      int followerDirection;
      ActorData *actor;
      Location tempLocation;
      Location possibleLocation;
      Point delta;
      const SceneEntry *sceneEntry;

      if (_vm->_scene->currentSceneNumber() == 0) {
            error("Actor::updateActorsScene _vm->_scene->currentSceneNumber() == 0");
      }

      _vm->_sound->stopVoice();
      _activeSpeech.stringsCount = 0;
      _activeSpeech.playing = false;
      _protagonist = NULL;

      for (i = 0; i < _actorsCount; i++) {
            actor = _actors[i];
            actor->_inScene = false;
            actor->_spriteList.freeMem();
            if (actor->_disabled) {
                  continue;
            }
            if ((actor->_flags & (kProtagonist | kFollower)) || (i == 0)) {
                  if (actor->_flags & kProtagonist) {
                        actor->_finalTarget = actor->_location;
                        _centerActor = _protagonist = actor;
                  } else if (_vm->getGameType() == GType_ITE && 
                                 _vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
                        continue;
                  }

                  actor->_sceneNumber = _vm->_scene->currentSceneNumber();
            }
            if (actor->_sceneNumber == _vm->_scene->currentSceneNumber()) {
                  actor->_inScene = true;
                  actor->_actionCycle = (_vm->_rnd.getRandomNumber(7) & 0x7) * 4; // 1/8th chance
            }
      }

      // _protagonist can be null while loading a game from the command line
      if (_protagonist == NULL)
            return;

      if ((actorsEntrance >= 0) && (_vm->_scene->_entryList.entryListCount > 0)) {
            if (_vm->_scene->_entryList.entryListCount <= actorsEntrance) {
                  actorsEntrance = 0; //OCEAN bug
            }

            sceneEntry = _vm->_scene->_entryList.getEntry(actorsEntrance);
            if (_vm->_scene->getFlags() & kSceneFlagISO) {
                  _protagonist->_location = sceneEntry->location;
            } else {
                  _protagonist->_location.x = sceneEntry->location.x * ACTOR_LMULT;
                  _protagonist->_location.y = sceneEntry->location.y * ACTOR_LMULT;
                  _protagonist->_location.z = sceneEntry->location.z * ACTOR_LMULT;
            }
            // Workaround for bug #1328045:
            // "When entering any of the houses at the start of the
            // game if you click on anything inside the building you
            // start walking through the door, turn around and leave."
            //
            // After stepping on an action zone, Rif is trying to exit.
            // Shift Rif's entry position to a non action zone area.
            if (_vm->getGameType() == GType_ITE) {
                  if ((_vm->_scene->currentSceneNumber() >= 53) && (_vm->_scene->currentSceneNumber() <= 66))
                        _protagonist->_location.y += 10;
            }

            _protagonist->_facingDirection = _protagonist->_actionDirection = sceneEntry->facing;
      }

      _protagonist->_currentAction = kActionWait;

      if (_vm->_scene->getFlags() & kSceneFlagISO) {
            //nothing?
      } else {
            _vm->_scene->initDoorsState(); //TODO: move to _scene
      }

      followerDirection = _protagonist->_facingDirection + 3;
      calcScreenPosition(_protagonist);

      for (i = 0; i < _actorsCount; i++) {
            actor = _actors[i];
            if (actor->_flags & (kFollower)) {
                  actor->_facingDirection = actor->_actionDirection = _protagonist->_facingDirection;
                  actor->_currentAction = kActionWait;
                  actor->_walkStepsCount = actor->_walkStepIndex = 0;
                  actor->_location.z = _protagonist->_location.z;


                  if (_vm->_scene->getFlags() & kSceneFlagISO) {
                        _vm->_isoMap->placeOnTileMap(_protagonist->_location, actor->_location, 3, followerDirection & 0x07);
                  } else {
                        followerDirection &= 0x07;

                        possibleLocation = _protagonist->_location;

                        delta.x = directionLUT[followerDirection][0];
                        delta.y = directionLUT[followerDirection][1];

                        for (j = 0; j < 30; j++) {
                              tempLocation = possibleLocation;
                              tempLocation.x += delta.x;
                              tempLocation.y += delta.y;

                              if (validFollowerLocation(tempLocation)) {
                                    possibleLocation = tempLocation;
                              } else {
                                    tempLocation = possibleLocation;
                                    tempLocation.x += delta.x;
                                    if (validFollowerLocation(tempLocation)) {
                                          possibleLocation = tempLocation;
                                    } else {
                                          tempLocation = possibleLocation;
                                          tempLocation.y += delta.y;
                                          if (validFollowerLocation(tempLocation)) {
                                                possibleLocation = tempLocation;
                                          } else {
                                                break;
                                          }
                                    }
                              }
                        }

                        actor->_location = possibleLocation;
                  }
                  followerDirection += 2;
            }

      }

      handleActions(0, true);
      if (_vm->_scene->getFlags() & kSceneFlagISO) {
            _vm->_isoMap->adjustScroll(true);
      }
}

void Actor::handleActions(int msec, bool setup) {
      int i;
      ActorData *actor;
      ActorFrameRange *frameRange;
      int state;
      int speed;
      int32 framesLeft;
      Location delta;
      Location addDelta;
      int hitZoneIndex;
      const HitZone *hitZone;
      Point hitPoint;
      Location pickLocation;

      for (i = 0; i < _actorsCount; i++) {
            actor = _actors[i];
            if (!actor->_inScene)
                  continue;

            if ((_vm->getGameType() == GType_ITE) && (i == ACTOR_DRAGON_INDEX)) {
                  moveDragon(actor);
                  continue;
            }

            switch (actor->_currentAction) {
            case kActionWait:
                  if (!setup && (actor->_flags & kFollower)) {
                        followProtagonist(actor);
                        if (actor->_currentAction != kActionWait)
                              break;
                  }

                  if (actor->_targetObject != ID_NOTHING) {
                        actorFaceTowardsObject(actor->_id, actor->_targetObject);
                  }

                  if (actor->_flags & kCycle) {
                        frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
                        if (frameRange->frameCount > 0) {
                              actor->_actionCycle++;
                              actor->_actionCycle = (actor->_actionCycle) % frameRange->frameCount;
                        } else {
                              actor->_actionCycle = 0;
                        }
                        actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
                        break;
                  }

                  if ((actor->_actionCycle & 3) == 0) {
                        actor->cycleWrap(100);

                        frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameWait));
                        if ((frameRange->frameCount < 1 || actor->_actionCycle > 33))
                              frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));

                        if (frameRange->frameCount) {
                              actor->_frameNumber = frameRange->frameIndex + (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
                        } else {
                              actor->_frameNumber = frameRange->frameIndex;
                        }
                  }
                  actor->_actionCycle++;
                  break;

            case kActionWalkToPoint:
            case kActionWalkToLink:
                  if (_vm->_scene->getFlags() & kSceneFlagISO) {
                        actor->_partialTarget.delta(actor->_location, delta);

                        while ((delta.u() == 0) && (delta.v() == 0)) {

                              if ((actor == _protagonist) && (_vm->mouseButtonPressed())) {
                                    _vm->_isoMap->screenPointToTileCoords(_vm->mousePos(), pickLocation);

                                    if (!actorWalkTo(_protagonist->_id, pickLocation)) {
                                          break;
                                    }
                              } else if (!_vm->_isoMap->nextTileTarget(actor) && !actorEndWalk(actor->_id, true)) {
                                    break;
                              }

                              actor->_partialTarget.delta(actor->_location, delta);
                              actor->_partialTarget.z = 0;
                        }

                        if (actor->_flags & kFastest) {
                              speed = 8;
                        } else if (actor->_flags & kFaster) {
                              speed = 6;
                        } else {
                              speed = 4;
                        }

                        if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
                              speed = 2;
                        }

                        if ((actor->_actionDirection == 2) || (actor->_actionDirection == 6)) {
                              speed = speed / 2;
                        }

                        if (ABS(delta.v()) > ABS(delta.u())) {
                              addDelta.v() = CLIP<int>(delta.v(), -speed, speed);
                              if (addDelta.v() == delta.v()) {
                                    addDelta.u() = delta.u();
                              } else {
                                    addDelta.u() = delta.u() * addDelta.v();
                                    addDelta.u() += (addDelta.u() > 0) ? (delta.v() / 2) : (-delta.v() / 2);
                                    addDelta.u() /= delta.v();
                              }
                        } else {
                              addDelta.u() = CLIP<int>(delta.u(), -speed, speed);
                              if (addDelta.u() == delta.u()) {
                                    addDelta.v() = delta.v();
                              } else {
                                    addDelta.v() = delta.v() * addDelta.u();
                                    addDelta.v() += (addDelta.v() > 0) ? (delta.u() / 2) : (-delta.u() / 2);
                                    addDelta.v() /= delta.u();
                              }
                        }

                        actor->_location.add(addDelta);
                  } else {
                        actor->_partialTarget.delta(actor->_location, delta);

                        while ((delta.x == 0) && (delta.y == 0)) {

                              if (actor->_walkStepIndex >= actor->_walkStepsCount) {
                                    actorEndWalk(actor->_id, true);
                                    return;           // break out of select case
                              }

                              actor->_partialTarget.fromScreenPoint(actor->_walkStepsPoints[actor->_walkStepIndex++]);
                              if (_vm->getGameType() == GType_ITE) {
                                    if (actor->_partialTarget.x > 224 * 2 * ACTOR_LMULT) {
                                          actor->_partialTarget.x -= 256 * 2 * ACTOR_LMULT;
                                    }
                              } else {
                                    if (actor->_partialTarget.x > 224 * 4 * ACTOR_LMULT) {
                                          actor->_partialTarget.x -= 256 * 4 * ACTOR_LMULT;
                                    }
                              }

                              actor->_partialTarget.delta(actor->_location, delta);

                              if (ABS(delta.y) > ABS(delta.x)) {
                                    actor->_actionDirection = delta.y > 0 ? kDirDown : kDirUp;
                              } else {
                                    actor->_actionDirection = delta.x > 0 ? kDirRight : kDirLeft;
                              }
                        }

                        if (_vm->getGameType() == GType_ITE)
                              speed = (ACTOR_LMULT * 2 * actor->_screenScale + 63) / 256;
                        else
                              speed = (ACTOR_SPEED * actor->_screenScale + 128) >> 8;

                        if (speed < 1)
                              speed = 1;

                        if (_vm->getGameType() == GType_IHNM)
                              speed = speed / 2;

                        if ((actor->_actionDirection == kDirUp) || (actor->_actionDirection == kDirDown)) {
                              addDelta.y = CLIP<int>(delta.y, -speed, speed);
                              if (addDelta.y == delta.y) {
                                    addDelta.x = delta.x;
                              } else {
                                    addDelta.x = delta.x * addDelta.y;
                                    addDelta.x += (addDelta.x > 0) ? (delta.y / 2) : (-delta.y / 2);
                                    addDelta.x /= delta.y;
                                    actor->_facingDirection = actor->_actionDirection;
                              }
                        } else {
                              addDelta.x = CLIP<int>(delta.x, -2 * speed, 2 * speed);
                              if (addDelta.x == delta.x) {
                                    addDelta.y = delta.y;
                              } else {
                                    addDelta.y = delta.y * addDelta.x;
                                    addDelta.y += (addDelta.y > 0) ? (delta.x / 2) : (-delta.x / 2);
                                    addDelta.y /= delta.x;
                                    actor->_facingDirection = actor->_actionDirection;
                              }
                        }

                        actor->_location.add(addDelta);
                  }

                  if (actor->_actorFlags & kActorBackwards) {
                        actor->_facingDirection = (actor->_actionDirection + 4) & 7;
                        actor->_actionCycle--;
                  } else {
                        actor->_actionCycle++;
                  }

                  frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);

                  if (actor->_actionCycle < 0) {
                        actor->_actionCycle = frameRange->frameCount - 1;
                  } else if (actor->_actionCycle >= frameRange->frameCount) {
                        actor->_actionCycle = 0;
                  }

                  actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
                  break;

            case kActionWalkDir:
                  if (_vm->_scene->getFlags() & kSceneFlagISO) {
                        actor->_location.u() += tileDirectionLUT[actor->_actionDirection][0];
                        actor->_location.v() += tileDirectionLUT[actor->_actionDirection][1];

                        frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);

                        actor->_actionCycle++;
                        actor->cycleWrap(frameRange->frameCount);
                        actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
                  } else {
                        if (_vm->getGameType() == GType_ITE) {
                              actor->_location.x += directionLUT[actor->_actionDirection][0] * 2;
                              actor->_location.y += directionLUT[actor->_actionDirection][1] * 2;
                        } else {
                              // FIXME: The original does not multiply by 8 here, but we do
                              actor->_location.x += (directionLUT[actor->_actionDirection][0] * 8 * actor->_screenScale + 128) >> 8;
                              actor->_location.y += (directionLUT[actor->_actionDirection][1] * 8 * actor->_screenScale + 128) >> 8;
                        }

                        frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
                        actor->_actionCycle++;
                        actor->cycleWrap(frameRange->frameCount);
                        actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
                  }
                  break;

            case kActionSpeak:
                  actor->_actionCycle++;
                  actor->cycleWrap(64);

                  frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameGesture));
                  if (actor->_actionCycle >= frameRange->frameCount) {
                        if (actor->_actionCycle & 1)
                              break;
                        frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameSpeak));

                        state = (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount);

                        if (state == 0) {
                              frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
                        } else {
                              state--;
                        }
                  } else {
                        state = actor->_actionCycle;
                  }

                  actor->_frameNumber = frameRange->frameIndex + state;
                  break;

            case kActionAccept:
            case kActionStoop:
                  break;

            case kActionCycleFrames:
            case kActionPongFrames:
                  if (actor->_cycleTimeCount > 0) {
                        actor->_cycleTimeCount--;
                        break;
                  }

                  actor->_cycleTimeCount = actor->_cycleDelay;
                  actor->_actionCycle++;

                  frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);

                  if (actor->_currentAction == kActionPongFrames) {
                        if (actor->_actionCycle >= frameRange->frameCount * 2 - 2) {
                              if (actor->_actorFlags & kActorContinuous) {
                                    actor->_actionCycle = 0;
                              } else {
                                    actor->_currentAction = kActionFreeze;
                                    break;
                              }
                        }

                        state = actor->_actionCycle;
                        if (state >= frameRange->frameCount) {
                              state = frameRange->frameCount * 2 - 2 - state;
                        }
                  } else {
                        if (actor->_actionCycle >= frameRange->frameCount) {
                              if (actor->_actorFlags & kActorContinuous) {
                                    actor->_actionCycle = 0;
                              } else {
                                    actor->_currentAction = kActionFreeze;
                                    break;
                              }
                        }
                        state = actor->_actionCycle;
                  }

                  if (frameRange->frameCount && (actor->_actorFlags & kActorRandom)) {
                        state = _vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
                  }

                  if (actor->_actorFlags & kActorBackwards) {
                        actor->_frameNumber = frameRange->frameIndex + frameRange->frameCount - 1 - state;
                  } else {
                        actor->_frameNumber = frameRange->frameIndex + state;
                  }
                  break;

            case kActionFall:
                  if (actor->_actionCycle > 0) {
                        framesLeft = actor->_actionCycle--;
                        actor->_finalTarget.delta(actor->_location, delta);
                        delta.x /= framesLeft;
                        delta.y /= framesLeft;
                        actor->_location.addXY(delta);
                        actor->_fallVelocity += actor->_fallAcceleration;
                        actor->_fallPosition += actor->_fallVelocity;
                        actor->_location.z = actor->_fallPosition >> 4;
                  } else {
                        actor->_location = actor->_finalTarget;
                        actor->_currentAction = kActionFreeze;
                        _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
                  }
                  break;

            case kActionClimb:
                  actor->_cycleDelay++;
                  if (actor->_cycleDelay & 3) {
                        break;
                  }

                  if (actor->_location.z >= actor->_finalTarget.z + ACTOR_CLIMB_SPEED) {
                        actor->_location.z -= ACTOR_CLIMB_SPEED;
                        actor->_actionCycle--;
                  } else if (actor->_location.z <= actor->_finalTarget.z - ACTOR_CLIMB_SPEED) {
                        actor->_location.z += ACTOR_CLIMB_SPEED;
                        actor->_actionCycle++;
                  } else {
                        actor->_location.z = actor->_finalTarget.z;
                        actor->_currentAction = kActionFreeze;
                        _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
                  }

                  frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);

                  if (actor->_actionCycle < 0) {
                        actor->_actionCycle = frameRange->frameCount - 1;
                  }
                  actor->cycleWrap(frameRange->frameCount);
                  actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
                  break;
            }

            if ((actor->_currentAction >= kActionWalkToPoint) && (actor->_currentAction <= kActionWalkDir)) {
                  hitZone = NULL;

                  if (_vm->_scene->getFlags() & kSceneFlagISO) {
                        actor->_location.toScreenPointUV(hitPoint);
                  } else {
                        actor->_location.toScreenPointXY(hitPoint);
                  }
                  hitZoneIndex = _vm->_scene->_actionMap->hitTest(hitPoint);
                  if (hitZoneIndex != -1) {
                        hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
                  }

                  // WORKAROUND for an incorrect hitzone which exists in IHNM
                  // In Gorrister's chapter, in the toilet screen, the hitzone of the exit is
                  // placed over the place where Gorrister sits to examine the graffiti on the wall
                  // to the left, which makes him exit the screen when the graffiti is examined.
                  // We effectively change the left side of the hitzone here so that it starts from
                  // pixel 301 onwards. The same workaround is applied in Script::whichObject
                  if (_vm->getGameType() == GType_IHNM) {
                        if (_vm->_scene->currentChapterNumber() == 1 && _vm->_scene->currentSceneNumber() == 22)
                              if (hitPoint.x <= 300)
                                    hitZone = NULL;
                  }

                  if (hitZone != actor->_lastZone) {
                        if (actor->_lastZone)
                              stepZoneAction(actor, actor->_lastZone, true, false);
                        actor->_lastZone = hitZone;
                        // WORKAROUND for graphics glitch in the rat caves. Don't do this step zone action in the rat caves
                        // (room 51) for hitzone 24577 (the door with the copy protection) to avoid the glitch. This glitch
                        // happens because the copy protection is supposed to kick in at this point, but it's bypassed
                        // (with permission from Wyrmkeep Entertainment)
                        if (hitZone && !(_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 51 && hitZone->getHitZoneId() == 24577)) {
                              stepZoneAction(actor, hitZone, false, false);
                        }
                  }
            }
      }
      // Update frameCount for sfWaitFrames in IHNM
      _vm->_frameCount++;
}

void Actor::direct(int msec) {

      if (_vm->_scene->_entryList.entryListCount == 0) {
            return;
      }

      if (_vm->_interface->_statusTextInput) {
            return;
      }

      // FIXME: HACK. This should be turned into cycle event.
      _lastTickMsec += msec;

      if (_lastTickMsec > 1000 / _handleActionDiv) {
            _lastTickMsec = 0;
            //process actions
            handleActions(msec, false);
      }

//process speech
      handleSpeech(msec);
}

bool Actor::followProtagonist(ActorData *actor) {
      Location protagonistLocation;
      Location newLocation;
      Location delta;
      int protagonistBGMaskType;
      Point prefer1;
      Point prefer2;
      Point prefer3;
      int16 prefU;
      int16 prefV;
      int16 newU;
      int16 newV;

      assert(_protagonist);

      actor->_flags &= ~(kFaster | kFastest);
      protagonistLocation = _protagonist->_location;
      calcScreenPosition(_protagonist);

      if (_vm->_scene->getFlags() & kSceneFlagISO) {
            prefU = 60;
            prefV = 60;


            actor->_location.delta(protagonistLocation, delta);

            if (actor->_id == actorIndexToId(2)) {
                  prefU = prefV = 48;
            }

            if ((delta.u() > prefU) || (delta.u() < -prefU) || (delta.v() > prefV) || (delta.v() < -prefV)) {

                  if ((delta.u() > prefU * 2) || (delta.u() < -prefU * 2) || (delta.v() > prefV * 2) || (delta.v() < -prefV * 2)) {
                        actor->_flags |= kFaster;

                        if ((delta.u() > prefU * 3) || (delta.u() < -prefU*3) || (delta.v() > prefV * 3) || (delta.v() < -prefV * 3)) {
                              actor->_flags |= kFastest;
                        }
                  }

                  prefU /= 2;
                  prefV /= 2;

                  newU = CLIP<int32>(delta.u(), -prefU, prefU) + protagonistLocation.u();
                  newV = CLIP<int32>(delta.v(), -prefV, prefV) + protagonistLocation.v();

                  newLocation.u() = newU + _vm->_rnd.getRandomNumber(prefU - 1) - prefU / 2;
                  newLocation.v() = newV + _vm->_rnd.getRandomNumber(prefV - 1) - prefV / 2;
                  newLocation.z = 0;

                  return actorWalkTo(actor->_id, newLocation);
            }

      } else {
            prefer1.x = (100 * _protagonist->_screenScale) >> 8;
            prefer1.y = (50 * _protagonist->_screenScale) >> 8;

            if (_protagonist->_currentAction == kActionWalkDir) {
                  prefer1.x /= 2;
            }

            if (prefer1.x < 8) {
                  prefer1.x = 8;
            }

            if (prefer1.y < 8) {
                  prefer1.y = 8;
            }

            prefer2.x = prefer1.x * 2;
            prefer2.y = prefer1.y * 2;
            prefer3.x = prefer1.x + prefer1.x / 2;
            prefer3.y = prefer1.y + prefer1.y / 2;

            actor->_location.delta(protagonistLocation, delta);

            protagonistBGMaskType = 0;
            if (_vm->_scene->isBGMaskPresent() && _vm->_scene->validBGMaskPoint(_protagonist->_screenPosition)) {
                  protagonistBGMaskType = _vm->_scene->getBGMaskType(_protagonist->_screenPosition);
            }

            if ((_vm->_rnd.getRandomNumber(7) & 0x7) == 0) // 1/8th chance
                  actor->_actorFlags &= ~kActorNoFollow;

            if (actor->_actorFlags & kActorNoFollow) {
                  return false;
            }

            if ((delta.x > prefer2.x) || (delta.x < -prefer2.x) ||
                  (delta.y > prefer2.y) || (delta.y < -prefer2.y) ||
                  ((_protagonist->_currentAction == kActionWait) &&
                  (delta.x * 2 < prefer1.x) && (delta.x * 2 > -prefer1.x) &&
                  (delta.y < prefer1.y) && (delta.y > -prefer1.y))) {

                        if (ABS(delta.x) > ABS(delta.y)) {

                              delta.x = (delta.x > 0) ? prefer3.x : -prefer3.x;

                              newLocation.x = delta.x + protagonistLocation.x;
                              newLocation.y = CLIP<int32>(delta.y, -prefer2.y, prefer2.y) + protagonistLocation.y;
                        } else {
                              delta.y = (delta.y > 0) ? prefer3.y : -prefer3.y;

                              newLocation.x = CLIP<int32>(delta.x, -prefer2.x, prefer2.x) + protagonistLocation.x;
                              newLocation.y = delta.y + protagonistLocation.y;
                        }
                        newLocation.z = 0;

                        if (protagonistBGMaskType != 3) {
                              newLocation.x += _vm->_rnd.getRandomNumber(prefer1.x - 1) - prefer1.x / 2;
                              newLocation.y += _vm->_rnd.getRandomNumber(prefer1.y - 1) - prefer1.y / 2;
                        }

                        newLocation.x = CLIP<int>(newLocation.x, -31 * 4, (_vm->getDisplayWidth() + 31) * 4);

                        return actorWalkTo(actor->_id, newLocation);
                  }
      }
      return false;
}

bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
      ActorData *actor;
      ActorData *anotherActor;
      int   i;

      Rect testBox;
      Rect testBox2;
      Point anotherActorScreenPosition;
      Point collision;
      Point pointFrom, pointTo, pointBest, pointAdd;
      Point delta, bestDelta;
      Point tempPoint;
      bool extraStartNode;
      bool extraEndNode;

      actor = getActor(actorId);

      if (actor == _protagonist) {
            _vm->_scene->setDoorState(2, 0xff);       // closed
            _vm->_scene->setDoorState(3, 0);          // open
      } else {
            _vm->_scene->setDoorState(2, 0);          // open
            _vm->_scene->setDoorState(3, 0xff);       // closed
      }

      if (_vm->_scene->getFlags() & kSceneFlagISO) {

            if ((_vm->getGameType() == GType_ITE) && (actor->_index == ACTOR_DRAGON_INDEX)) {
                  return false;
            }

            actor->_finalTarget = toLocation;
            actor->_walkStepsCount = 0;
            _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);


            if ((actor->_walkStepsCount == 0) && (actor->_flags & kProtagonist)) {
                  actor->_actorFlags |= kActorNoCollide;
                  _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);
            }

            actor->_walkStepIndex = 0;
            if (_vm->_isoMap->nextTileTarget(actor)) {
                  actor->_currentAction = kActionWalkToPoint;
                  actor->_walkFrameSequence = getFrameType(kFrameWalk);
            } else {
                  actorEndWalk(actorId, false);
                  return false;
            }
      } else {

            actor->_location.toScreenPointXY(pointFrom);
            // FIXME: why is the following line needed?
            pointFrom.x &= ~1;      // set last bit to 0

            extraStartNode = _vm->_scene->offscreenPath(pointFrom);

            toLocation.toScreenPointXY(pointTo);
            // FIXME: why is the following line needed?
            pointTo.x &= ~1;  // set last bit to 0

            // Are we already where we want to go?
            if (pointFrom.x == pointTo.x && pointFrom.y == pointTo.y) {
                  actor->_walkStepsCount = 0;
                  actorEndWalk(actorId, false);
                  return false;
            }

            extraEndNode = _vm->_scene->offscreenPath(pointTo);

            if (_vm->_scene->isBGMaskPresent()) {

                  if (
                        ((actor->_currentAction >= kActionWalkToPoint && actor->_currentAction <= kActionWalkDir) ||
                        (_vm->getGameType() == GType_ITE && actor == _protagonist)) &&
                        !_vm->_scene->canWalk(pointFrom)) {
                        
                        int max = _vm->getGameType() == GType_ITE ? 8 : 4;

                        for (i = 1; i < max; i++) {
                              pointAdd = pointFrom;
                              pointAdd.y += i;
                              if (_vm->_scene->canWalk(pointAdd)) {
                                    pointFrom = pointAdd;
                                    break;
                              }
                              pointAdd = pointFrom;
                              pointAdd.y -= i;
                              if (_vm->_scene->canWalk(pointAdd)) {
                                    pointFrom = pointAdd;
                                    break;
                              }
                              if (_vm->getGameType() == GType_ITE) {
                                    pointAdd = pointFrom;
                                    pointAdd.x += i;
                                    if (_vm->_scene->canWalk(pointAdd)) {
                                          pointFrom = pointAdd;
                                          break;
                                    }
                                    pointAdd = pointFrom;
                                    pointAdd.x -= i;
                                    if (_vm->_scene->canWalk(pointAdd)) {
                                          pointFrom = pointAdd;
                                          break;
                                    }
                              }
                        }
                  }

                  _barrierCount = 0;
                  if (!(actor->_actorFlags & kActorNoCollide)) {
                        collision.x = ACTOR_COLLISION_WIDTH * actor->_screenScale / (256 * 2);
                        collision.y = ACTOR_COLLISION_HEIGHT * actor->_screenScale / (256 * 2);


                        for (i = 0; (i < _actorsCount) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) {
                              anotherActor = _actors[i];
                              if (!anotherActor->_inScene)
                                    continue;
                              if (anotherActor == actor)
                                    continue;

                              anotherActorScreenPosition = anotherActor->_screenPosition;
                              testBox.left = (anotherActorScreenPosition.x - collision.x) & ~1;
                              testBox.right = (anotherActorScreenPosition.x + collision.x) & ~1;
                              testBox.top = anotherActorScreenPosition.y - collision.y;
                              testBox.bottom = anotherActorScreenPosition.y + collision.y;
                              testBox2 = testBox;
                              testBox2.left -= 2;
                              testBox2.right += 2;
                              testBox2.top -= 1;
                              testBox2.bottom += 1;

                              if (testBox2.contains(pointFrom)) {
                                    if (pointFrom.x > anotherActorScreenPosition.x + 4) {
                                          testBox.right = pointFrom.x - 2;
                                    } else if (pointFrom.x < anotherActorScreenPosition.x - 4) {
                                          testBox.left = pointFrom.x + 2;
                                    } else if (pointFrom.y > anotherActorScreenPosition.y) {
                                          testBox.bottom = pointFrom.y - 1;
                                    } else {
                                          testBox.top = pointFrom.y + 1 ;
                                    }
                              }

                              if ((testBox.width() > 0) && (testBox.height() > 0)) {
                                    _barrierList[_barrierCount++] = testBox;
                              }
                        }
                  }


                  pointBest = pointTo;
                  actor->_walkStepsCount = 0;
                  findActorPath(actor, pointFrom, pointTo);

                  if (actor->_walkStepsCount == 0) {
                        error("actor->_walkStepsCount == 0");
                  }

                  if (extraStartNode) {
                        actor->_walkStepIndex = 0;
                  } else {
                        // FIXME: Why is this needed?
                        actor->_walkStepIndex = 1;
                  }

                  if (extraEndNode) {
                        toLocation.toScreenPointXY(tempPoint);
                        actor->_walkStepsCount--;
                        actor->addWalkStepPoint(tempPoint);
                  }


                  pointBest = actor->_walkStepsPoints[actor->_walkStepsCount - 1];

                  pointBest.x &= ~1;
                  delta.x = ABS(pointFrom.x - pointTo.x);
                  delta.y = ABS(pointFrom.y - pointTo.y);

                  bestDelta.x = ABS(pointBest.x - pointTo.x);
                  bestDelta.y = ABS(pointBest.y - pointTo.y);

                  if ((delta.x + delta.y <= bestDelta.x + bestDelta.y) && (actor->_flags & kFollower)) {
                        actor->_actorFlags |= kActorNoFollow;
                  }

                  if (pointBest == pointFrom) {
                        actor->_walkStepsCount = 0;
                  }
            } else {
                  actor->_walkStepsCount = 0;
                  actor->addWalkStepPoint(pointTo);
                  actor->_walkStepIndex = 0;
            }

            actor->_partialTarget = actor->_location;
            actor->_finalTarget = toLocation;
            if (actor->_walkStepsCount == 0) {
                  actorEndWalk(actorId, false);
                  return false;
            } else {
                  if (actor->_flags & kProtagonist) {
                        _actors[1]->_actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2
                        _actors[2]->_actorFlags &= ~kActorNoFollow;
                  }
                  actor->_currentAction = (actor->_walkStepsCount >= ACTOR_MAX_STEPS_COUNT) ? kActionWalkToLink : kActionWalkToPoint;
                  actor->_walkFrameSequence = getFrameType(kFrameWalk);
            }
      }
      return true;
}

bool Actor::actorEndWalk(uint16 actorId, bool recurse) {
      bool walkMore = false;
      ActorData *actor;
      const HitZone *hitZone;
      int hitZoneIndex;
      Point testPoint;

      actor = getActor(actorId);
      actor->_actorFlags &= ~kActorBackwards;

      if (_vm->getGameType() == GType_ITE) {

            if (actor->_location.distance(actor->_finalTarget) > 8 && (actor->_flags & kProtagonist) && recurse && !(actor->_actorFlags & kActorNoCollide)) {
                  actor->_actorFlags |= kActorNoCollide;
                  return actorWalkTo(actorId, actor->_finalTarget);
            }
      }

      actor->_currentAction = kActionWait;
      actor->_actionCycle = 0;
      if (actor->_actorFlags & kActorFinalFace) {
            actor->_facingDirection = actor->_actionDirection = (actor->_actorFlags >> 6) & 0x07; //?
      }

      actor->_actorFlags &= ~(kActorNoCollide | kActorCollided | kActorFinalFace | kActorFacingMask);
      actor->_flags &= ~(kFaster | kFastest);

      if (actor == _protagonist) {
            _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
            if (_vm->_script->_pendingVerb == _vm->_script->getVerbType(kVerbWalkTo)) {
                  if (_vm->getGameType() == GType_ITE)
                        actor->_location.toScreenPointUV(testPoint); // it's wrong calculation, but it is used in ITE
                  else
                        actor->_location.toScreenPointXY(testPoint);
                        
                  hitZoneIndex = _vm->_scene->_actionMap->hitTest(testPoint);
                  if (hitZoneIndex != -1) {
                        hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
                        stepZoneAction(actor, hitZone, false, true);
                  } else {
                        _vm->_script->setNoPendingVerb();
                  }
            } else if (_vm->_script->_pendingVerb != _vm->_script->getVerbType(kVerbNone)) {
                  _vm->_script->doVerb();
            }
      } else {
            if (recurse && (actor->_flags & kFollower))
                  walkMore = followProtagonist(actor);

            _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
      }
      return walkMore;
}

void Actor::moveDragon(ActorData *actor) {
      int16 dir0, dir1, dir2, dir3;
      int16 moveType;
      Event event;
      const DragonMove *dragonMove;

      if ((actor->_actionCycle < 0) ||
            ((actor->_actionCycle == 0) && (actor->_dragonMoveType >= ACTOR_DRAGON_TURN_MOVES))) {

            moveType = kDragonMoveInvalid;
            if (actor->_location.distance(_protagonist->_location) < 24) {
                  if (_dragonHunt && (_protagonist->_currentAction != kActionFall)) {
                        event.type = kEvTOneshot;
                        event.code = kScriptEvent;
                        event.op = kEventExecNonBlocking;
                        event.time = 0;
                        event.param = _vm->_scene->getScriptModuleNumber(); // module number
                        event.param2 = ACTOR_EXP_KNOCK_RIF;             // script entry point number
                        event.param3 = -1;            // Action
                        event.param4 = -1;            // Object
                        event.param5 = -1;            // With Object
                        event.param6 = -1;            // Actor
                        _vm->_events->queue(&event);

                        _dragonHunt = false;
                  }
            } else {
                  _dragonHunt = true;
            }

            if (actor->_walkStepIndex + 2 > actor->_walkStepsCount) {

                  _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, actor->_actionDirection);

                  if (actor->_walkStepsCount == 0) {
                        _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, 0);
                  }

                  if (actor->_walkStepsCount < 2) {
                        return;
                  }

                  actor->_partialTarget = actor->_location;
                  actor->_finalTarget = _protagonist->_location;
                  actor->_walkStepIndex = 0;
            }

            dir0 = actor->_actionDirection;
            dir1 = actor->_tileDirections[actor->_walkStepIndex++];
            dir2 = actor->_tileDirections[actor->_walkStepIndex];
            dir3 = actor->_tileDirections[actor->_walkStepIndex + 1];

            if (dir0 != dir1){
                  actor->_actionDirection = dir0 = dir1;
            }

            actor->_location = actor->_partialTarget;

            if ((dir1 != dir2) && (dir1 == dir3)) {
                  switch (dir1) {
                  case kDirUpLeft:
                        actor->_partialTarget.v() += 16;
                        moveType = kDragonMoveUpLeft;
                        break;
                  case kDirDownLeft:
                        actor->_partialTarget.u() -= 16;
                        moveType = kDragonMoveDownLeft;
                        break;
                  case kDirDownRight:
                        actor->_partialTarget.v() -= 16;
                        moveType = kDragonMoveDownRight;
                        break;
                  case kDirUpRight:
                        actor->_partialTarget.u() += 16;
                        moveType = kDragonMoveUpRight;
                        break;
                  }

                  switch (dir2) {
                  case kDirUpLeft:
                        actor->_partialTarget.v() += 16;
                        break;
                  case kDirDownLeft:
                        actor->_partialTarget.u() -= 16;
                        break;
                  case kDirDownRight:
                        actor->_partialTarget.v() -= 16;
                        break;
                  case kDirUpRight:
                        actor->_partialTarget.u() += 16;
                        break;
                  }

                  actor->_walkStepIndex++;
            } else {
                  switch (dir1) {
                  case kDirUpLeft:
                        actor->_partialTarget.v() += 16;
                        switch (dir2) {
                        case kDirDownLeft:
                              moveType = kDragonMoveUpLeft_Left;
                              actor->_partialTarget.u() -= 16;
                              break;
                        case kDirUpLeft:
                              moveType = kDragonMoveUpLeft;
                              break;
                        case kDirUpRight:
                              actor->_partialTarget.u() += 16;
                              moveType = kDragonMoveUpLeft_Right;
                              break;
                        default:
                              actor->_actionDirection = dir1;
                              actor->_walkStepsCount = 0;
                              break;
                        }
                        break;
                  case kDirDownLeft:
                        actor->_partialTarget.u() -= 16;
                        switch (dir2) {
                        case kDirDownRight:
                              moveType = kDragonMoveDownLeft_Left;
                              actor->_partialTarget.v() -= 16;
                              break;
                        case kDirDownLeft:
                              moveType = kDragonMoveDownLeft;
                              break;
                        case kDirUpLeft:
                              moveType = kDragonMoveDownLeft_Right;
                              actor->_partialTarget.v() += 16;
                              break;
                        default:
                              actor->_actionDirection = dir1;
                              actor->_walkStepsCount = 0;
                              break;
                        }
                        break;
                  case kDirDownRight:
                        actor->_partialTarget.v() -= 16;
                        switch (dir2) {
                        case kDirUpRight:
                              moveType = kDragonMoveDownRight_Left;
                              actor->_partialTarget.u() += 16;
                              break;
                        case kDirDownRight:
                              moveType = kDragonMoveDownRight;
                              break;
                        case kDirDownLeft:
                              moveType = kDragonMoveDownRight_Right;
                              actor->_partialTarget.u() -= 16;
                              break;
                        default:
                              actor->_actionDirection = dir1;
                              actor->_walkStepsCount = 0;
                              break;
                        }
                        break;
                  case kDirUpRight:
                        actor->_partialTarget.u() += 16;
                        switch (dir2) {
                        case kDirUpLeft:
                              moveType = kDragonMoveUpRight_Left;
                              actor->_partialTarget.v() += 16;
                              break;
                        case kDirUpRight:
                              moveType = kDragonMoveUpRight;
                              break;
                        case kDirDownRight:
                              moveType = kDragonMoveUpRight_Right;
                              actor->_partialTarget.v() -= 16;
                              break;
                        default:
                              actor->_actionDirection = dir1;
                              actor->_walkStepsCount = 0;
                              break;
                        }
                        break;

                  default:
                        actor->_actionDirection = dir1;
                        actor->_walkStepsCount = 0;
                        break;
                  }
            }

            actor->_dragonMoveType = moveType;

            if (moveType >= ACTOR_DRAGON_TURN_MOVES) {
                  actor->_dragonStepCycle = 0;
                  actor->_actionCycle = 4;
                  actor->_walkStepIndex++;
            } else {
                  actor->_actionCycle = 4;
            }
      }

      actor->_actionCycle--;

      if ((actor->_walkStepsCount < 1) || (actor->_actionCycle < 0)) {
            return;
      }

      if (actor->_dragonMoveType < ACTOR_DRAGON_TURN_MOVES) {

            actor->_dragonStepCycle++;
            if (actor->_dragonStepCycle >= 7) {
                  actor->_dragonStepCycle = 0;
            }

            actor->_dragonBaseFrame = actor->_dragonMoveType * 7;

            if (actor->_location.u() > actor->_partialTarget.u() + 3) {
                  actor->_location.u() -= 4;
            } else if (actor->_location.u() < actor->_partialTarget.u() - 3) {
                  actor->_location.u() += 4;
            } else {
                  actor->_location.u() = actor->_partialTarget.u();
            }

            if (actor->_location.v() > actor->_partialTarget.v() + 3) {
                  actor->_location.v() -= 4;
            } else if (actor->_location.v() < actor->_partialTarget.v() - 3) {
                  actor->_location.v() += 4;
            } else {
                  actor->_location.v() = actor->_partialTarget.v();
            }
      } else {
            dragonMove = &dragonMoveTable[actor->_dragonMoveType];
            actor->_dragonBaseFrame = dragonMove->baseFrame;


            actor->_location.u() = actor->_partialTarget.u() - dragonMove->offset[actor->_actionCycle][0];
            actor->_location.v() = actor->_partialTarget.v() - dragonMove->offset[actor->_actionCycle][1];

            actor->_dragonStepCycle++;
            if (actor->_dragonStepCycle >= 3) {
                  actor->_dragonStepCycle = 3;
            }
      }

      actor->_frameNumber = actor->_dragonBaseFrame + actor->_dragonStepCycle;
}

// Console wrappers - must be safe to run

void Actor::cmdActorWalkTo(int argc, const char **argv) {
      uint16 actorId = (uint16) atoi(argv[1]);
      Location location;
      Point movePoint;

      movePoint.x = atoi(argv[2]);
      movePoint.y = atoi(argv[3]);

      location.fromScreenPoint(movePoint);

      if (!validActorId(actorId)) {
            _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId);
            return;
      }

      actorWalkTo(actorId, location);
}

} // End of namespace Saga

Generated by  Doxygen 1.6.0   Back to index