2004-04-12 21:40:49 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
2005-01-01 16:20:17 +00:00
|
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
2004-04-12 21:40:49 +00:00
|
|
|
*
|
|
|
|
* The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-05-01 06:16:57 +00:00
|
|
|
// Actor management module header file
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
#ifndef SAGA_ACTOR_H__
|
|
|
|
#define SAGA_ACTOR_H__
|
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
#include "common/file.h"
|
|
|
|
|
2004-08-03 01:07:34 +00:00
|
|
|
#include "saga/sprite.h"
|
2005-01-28 12:54:09 +00:00
|
|
|
#include "saga/itedata.h"
|
2004-12-15 00:24:12 +00:00
|
|
|
#include "saga/list.h"
|
2005-01-08 20:30:07 +00:00
|
|
|
#include "saga/saga.h"
|
2004-08-02 15:47:42 +00:00
|
|
|
|
2004-04-12 21:40:49 +00:00
|
|
|
namespace Saga {
|
|
|
|
|
2005-01-15 23:46:43 +00:00
|
|
|
class HitZone;
|
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
|
2005-01-08 20:30:07 +00:00
|
|
|
#define ACTOR_DEBUG
|
2005-01-06 23:02:53 +00:00
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
#define ACTOR_BARRIERS_MAX 16
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2005-01-05 19:03:49 +00:00
|
|
|
#define ACTOR_MAX_STEPS_COUNT 32
|
2004-04-12 21:40:49 +00:00
|
|
|
|
|
|
|
#define ACTOR_DIALOGUE_HEIGHT 100
|
|
|
|
|
2004-10-27 21:32:28 +00:00
|
|
|
#define ACTOR_LMULT 4
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
#define ACTOR_COLLISION_WIDTH 32
|
|
|
|
#define ACTOR_COLLISION_HEIGHT 8
|
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
#define ACTOR_DIRECTIONS_COUNT 4 // for ActorFrameSequence
|
|
|
|
#define ACTOR_DIRECTION_RIGHT 0
|
|
|
|
#define ACTOR_DIRECTION_LEFT 1
|
|
|
|
#define ACTOR_DIRECTION_BACK 2
|
|
|
|
#define ACTOR_DIRECTION_FORWARD 3
|
2004-12-17 20:38:17 +00:00
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
#define ACTOR_SPEECH_STRING_MAX 16 // speech const
|
2004-12-21 06:49:07 +00:00
|
|
|
#define ACTOR_SPEECH_ACTORS_MAX 8
|
|
|
|
|
2005-05-08 14:04:06 +00:00
|
|
|
#define ACTOR_NO_ENTRANCE -1
|
|
|
|
|
2004-12-29 21:49:25 +00:00
|
|
|
#define PATH_NODE_EMPTY -1
|
|
|
|
|
2004-12-21 06:49:07 +00:00
|
|
|
enum ActorActions {
|
|
|
|
kActionWait = 0,
|
|
|
|
kActionWalkToPoint = 1,
|
|
|
|
kActionWalkToLink = 2,
|
|
|
|
kActionWalkDir = 3,
|
|
|
|
kActionSpeak = 4,
|
|
|
|
kActionAccept = 5,
|
|
|
|
kActionStoop = 6,
|
|
|
|
kActionLook = 7,
|
|
|
|
kActionCycleFrames = 8,
|
|
|
|
kActionPongFrames = 9,
|
|
|
|
kActionFreeze = 10,
|
|
|
|
kActionFall = 11,
|
|
|
|
kActionClimb = 12
|
|
|
|
};
|
|
|
|
|
|
|
|
enum SpeechFlags {
|
|
|
|
kSpeakNoAnimate = 1,
|
|
|
|
kSpeakAsync = 2,
|
|
|
|
kSpeakSlow = 4
|
|
|
|
};
|
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
enum ActorFrameTypes {
|
|
|
|
kFrameStand = 0,
|
|
|
|
kFrameWalk = 1,
|
|
|
|
kFrameSpeak = 2,
|
|
|
|
kFrameGive = 3,
|
|
|
|
kFrameGesture = 4,
|
|
|
|
kFrameWait = 5,
|
|
|
|
kFramePickUp = 6,
|
|
|
|
kFrameLook = 7
|
|
|
|
//...some special
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ActorFlagsEx {
|
|
|
|
kActorNoCollide = (1 << 0),
|
|
|
|
kActorNoFollow = (1 << 1),
|
|
|
|
kActorCollided = (1 << 2),
|
|
|
|
kActorBackwards = (1 << 3),
|
|
|
|
kActorContinuous = (1 << 4),
|
|
|
|
kActorFinalFace = (1 << 5),
|
|
|
|
kActorFinishLeft = ((1 << 5) | (kDirLeft << 6)),
|
|
|
|
kActorFinishRight = ((1 << 5) | (kDirRight << 6)),
|
|
|
|
kActorFinishUp = ((1 << 5) | (kDirUp << 6)),
|
|
|
|
kActorFinishDown = ((1 << 5) | (kDirDown << 6)),
|
2004-12-25 11:17:03 +00:00
|
|
|
kActorFacingMask = (0xf << 5),
|
2004-12-22 21:04:50 +00:00
|
|
|
kActorRandom = (1 << 10)
|
|
|
|
};
|
|
|
|
|
2004-12-29 14:33:14 +00:00
|
|
|
enum PathCellType {
|
|
|
|
kPathCellEmpty = -1,
|
2005-01-06 22:22:20 +00:00
|
|
|
//kDirUp = 0 .... kDirUpLeft = 7
|
2004-12-29 14:33:14 +00:00
|
|
|
kPathCellBarrier = 0x57
|
|
|
|
};
|
2004-08-02 15:47:42 +00:00
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
struct PathDirectionData {
|
2005-01-06 22:22:20 +00:00
|
|
|
int8 direction;
|
2005-01-16 20:30:57 +00:00
|
|
|
int16 x;
|
|
|
|
int16 y;
|
2004-12-28 21:27:18 +00:00
|
|
|
};
|
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
struct ActorFrameRange {
|
2004-12-17 20:38:17 +00:00
|
|
|
int frameIndex;
|
|
|
|
int frameCount;
|
2004-04-25 14:42:14 +00:00
|
|
|
};
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
struct ActorFrameSequence {
|
|
|
|
ActorFrameRange directions[ACTOR_DIRECTIONS_COUNT];
|
2004-04-25 14:42:14 +00:00
|
|
|
};
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2005-01-15 20:12:49 +00:00
|
|
|
struct Location {
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 x; // logical coordinates
|
|
|
|
int32 y; //
|
|
|
|
int32 z; //
|
2005-01-15 20:12:49 +00:00
|
|
|
Location() {
|
2004-12-28 21:27:18 +00:00
|
|
|
x = y = z = 0;
|
|
|
|
}
|
2005-05-10 22:56:25 +00:00
|
|
|
void saveState(Common::File& out) {
|
2005-04-27 11:51:11 +00:00
|
|
|
out.writeSint32LE(x);
|
|
|
|
out.writeSint32LE(y);
|
|
|
|
out.writeSint32LE(z);
|
|
|
|
}
|
2005-05-10 22:56:25 +00:00
|
|
|
void loadState(Common::File& in) {
|
2005-04-27 11:51:11 +00:00
|
|
|
x = in.readSint32LE();
|
|
|
|
y = in.readSint32LE();
|
|
|
|
z = in.readSint32LE();
|
|
|
|
}
|
|
|
|
|
2005-01-15 20:12:49 +00:00
|
|
|
int distance(const Location &location) const {
|
2004-12-28 21:27:18 +00:00
|
|
|
return MAX(ABS(x - location.x), ABS(y - location.y));
|
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 &u() {
|
2005-02-09 20:30:45 +00:00
|
|
|
return x;
|
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 &v() {
|
2005-02-09 20:30:45 +00:00
|
|
|
return y;
|
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 u() const {
|
2005-02-18 00:00:00 +00:00
|
|
|
return x;
|
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 v() const {
|
2005-02-18 00:00:00 +00:00
|
|
|
return y;
|
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 uv() const {
|
2005-03-13 17:43:50 +00:00
|
|
|
return u() + v();
|
|
|
|
}
|
2005-01-15 20:12:49 +00:00
|
|
|
void delta(const Location &location, Location &result) const {
|
2004-12-28 21:27:18 +00:00
|
|
|
result.x = x - location.x;
|
2005-01-04 18:54:29 +00:00
|
|
|
result.y = y - location.y;
|
2004-12-28 21:27:18 +00:00
|
|
|
result.z = z - location.z;
|
|
|
|
}
|
2005-04-19 11:07:06 +00:00
|
|
|
void addXY(const Location &location) {
|
|
|
|
x += location.x;
|
|
|
|
y += location.y;
|
|
|
|
}
|
2005-01-15 20:12:49 +00:00
|
|
|
void add(const Location &location) {
|
2004-12-28 21:27:18 +00:00
|
|
|
x += location.x;
|
|
|
|
y += location.y;
|
|
|
|
z += location.z;
|
2004-12-25 11:17:03 +00:00
|
|
|
}
|
2005-01-04 16:10:43 +00:00
|
|
|
void fromScreenPoint(const Point &screenPoint) {
|
|
|
|
x = (screenPoint.x * ACTOR_LMULT);
|
|
|
|
y = (screenPoint.y * ACTOR_LMULT);
|
|
|
|
z = 0;
|
|
|
|
}
|
2005-01-05 19:03:49 +00:00
|
|
|
void toScreenPointXY(Point &screenPoint) const {
|
|
|
|
screenPoint.x = x / ACTOR_LMULT;
|
|
|
|
screenPoint.y = y / ACTOR_LMULT;
|
|
|
|
}
|
2005-03-13 17:43:50 +00:00
|
|
|
void toScreenPointUV(Point &screenPoint) const {
|
|
|
|
screenPoint.x = u();
|
|
|
|
screenPoint.y = v();
|
|
|
|
}
|
2005-01-05 19:03:49 +00:00
|
|
|
void toScreenPointXYZ(Point &screenPoint) const {
|
|
|
|
screenPoint.x = x / ACTOR_LMULT;
|
|
|
|
screenPoint.y = y / ACTOR_LMULT - z;
|
|
|
|
}
|
2004-12-22 21:04:50 +00:00
|
|
|
};
|
2004-12-28 21:27:18 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
class CommonObjectData {
|
|
|
|
public:
|
2005-04-27 11:51:11 +00:00
|
|
|
//constant
|
2005-05-18 18:28:10 +00:00
|
|
|
bool disabled; // disabled in init section
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 index; // index in local array
|
2005-05-18 18:28:10 +00:00
|
|
|
uint16 id; // object id
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 scriptEntrypointNumber; // script entrypoint number
|
2005-04-18 20:03:14 +00:00
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
//variables
|
|
|
|
uint16 flags; // initial flags
|
|
|
|
int32 nameIndex; // index in name string list
|
|
|
|
int32 sceneNumber; // scene
|
2005-05-18 18:28:10 +00:00
|
|
|
int32 spriteListResourceId; // sprite list resource id
|
2005-04-27 11:51:11 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
Location location; // logical coordinates
|
|
|
|
Point screenPosition; // screen coordinates
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 screenDepth; //
|
|
|
|
int32 screenScale; //
|
|
|
|
|
2005-05-10 22:56:25 +00:00
|
|
|
void saveState(Common::File& out) {
|
2005-04-27 11:51:11 +00:00
|
|
|
out.writeUint16LE(flags);
|
|
|
|
out.writeSint32LE(nameIndex);
|
|
|
|
out.writeSint32LE(sceneNumber);
|
2005-05-18 18:28:10 +00:00
|
|
|
out.writeSint32LE(spriteListResourceId);
|
2005-04-27 11:51:11 +00:00
|
|
|
location.saveState(out);
|
|
|
|
out.writeSint16LE(screenPosition.x);
|
|
|
|
out.writeSint16LE(screenPosition.y);
|
|
|
|
out.writeSint32LE(screenDepth);
|
|
|
|
out.writeSint32LE(screenScale);
|
|
|
|
}
|
2005-05-10 22:56:25 +00:00
|
|
|
void loadState(Common::File& in) {
|
2005-04-27 11:51:11 +00:00
|
|
|
flags = in.readUint16LE();
|
|
|
|
nameIndex = in.readSint32LE();
|
|
|
|
sceneNumber = in.readSint32LE();
|
2005-05-18 18:28:10 +00:00
|
|
|
spriteListResourceId = in.readSint32LE();
|
2005-04-27 11:51:11 +00:00
|
|
|
location.loadState(in);
|
|
|
|
screenPosition.x = in.readSint16LE();
|
|
|
|
screenPosition.y = in.readSint16LE();
|
|
|
|
screenDepth = in.readSint32LE();
|
|
|
|
screenScale = in.readSint32LE();
|
2005-01-18 21:13:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef CommonObjectData *CommonObjectDataPointer;
|
|
|
|
|
|
|
|
typedef SortedList<CommonObjectDataPointer> CommonObjectOrderList;
|
|
|
|
|
|
|
|
class ObjectData: public CommonObjectData {
|
|
|
|
public:
|
2005-04-27 11:51:11 +00:00
|
|
|
//constant
|
2005-01-18 21:13:44 +00:00
|
|
|
uint16 interactBits;
|
2005-04-27 11:51:11 +00:00
|
|
|
ObjectData() {
|
|
|
|
memset(this, 0, sizeof(*this));
|
|
|
|
}
|
2005-01-18 21:13:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ActorData: public CommonObjectData {
|
|
|
|
public:
|
2005-04-27 11:51:11 +00:00
|
|
|
//constant
|
|
|
|
SpriteList spriteList; // sprite list data
|
|
|
|
|
|
|
|
ActorFrameSequence *frames; // Actor's frames
|
|
|
|
int framesCount; // Actor's frames count
|
|
|
|
int frameListResourceId; // Actor's frame list resource id
|
2005-03-18 17:11:37 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
byte speechColor; // Actor dialogue color
|
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
//variables
|
2004-12-21 06:49:07 +00:00
|
|
|
uint16 actorFlags; // dynamic flags
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 currentAction; // ActorActions type
|
|
|
|
int32 facingDirection; // orientation
|
|
|
|
int32 actionDirection;
|
|
|
|
int32 actionCycle;
|
2005-01-15 23:46:43 +00:00
|
|
|
uint16 targetObject;
|
|
|
|
const HitZone *lastZone;
|
2004-12-18 20:33:02 +00:00
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 cycleFrameSequence;
|
2004-12-22 21:04:50 +00:00
|
|
|
uint8 cycleDelay;
|
|
|
|
uint8 cycleTimeCount;
|
|
|
|
uint8 cycleFlags;
|
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 frameNumber; // current frame number
|
2004-12-25 11:17:03 +00:00
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 tileDirectionsAlloced;
|
2005-02-26 17:37:16 +00:00
|
|
|
byte *tileDirections;
|
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 walkStepsAlloced;
|
2005-01-05 19:03:49 +00:00
|
|
|
Point *walkStepsPoints;
|
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 walkStepsCount;
|
|
|
|
int32 walkStepIndex;
|
2005-02-26 17:37:16 +00:00
|
|
|
|
2005-01-15 20:12:49 +00:00
|
|
|
Location finalTarget;
|
|
|
|
Location partialTarget;
|
2005-04-27 11:51:11 +00:00
|
|
|
int32 walkFrameSequence;
|
|
|
|
|
2005-05-10 22:56:25 +00:00
|
|
|
void saveState(Common::File& out) {
|
2005-04-27 11:51:11 +00:00
|
|
|
CommonObjectData::saveState(out);
|
|
|
|
out.writeUint16LE(actorFlags);
|
|
|
|
out.writeSint32LE(currentAction);
|
|
|
|
out.writeSint32LE(facingDirection);
|
|
|
|
out.writeSint32LE(actionDirection);
|
|
|
|
out.writeSint32LE(actionCycle);
|
|
|
|
out.writeUint16LE(targetObject);
|
|
|
|
|
|
|
|
//TODO: write lastZone
|
|
|
|
out.writeSint32LE(cycleFrameSequence);
|
|
|
|
out.writeByte(cycleDelay);
|
|
|
|
out.writeByte(cycleTimeCount);
|
|
|
|
out.writeByte(cycleFlags);
|
|
|
|
out.writeSint32LE(frameNumber);
|
|
|
|
|
|
|
|
out.writeSint32LE(tileDirectionsAlloced);
|
2005-05-08 21:49:52 +00:00
|
|
|
for (int i = 0; i < tileDirectionsAlloced; i++) {
|
2005-04-27 11:51:11 +00:00
|
|
|
out.writeByte(tileDirections[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
out.writeSint32LE(walkStepsAlloced);
|
2005-05-08 21:49:52 +00:00
|
|
|
for (int i = 0; i < walkStepsAlloced; i++) {
|
2005-04-27 11:51:11 +00:00
|
|
|
out.writeSint16LE(walkStepsPoints[i].x);
|
|
|
|
out.writeSint16LE(walkStepsPoints[i].y);
|
|
|
|
}
|
|
|
|
|
|
|
|
out.writeSint32LE(walkStepsCount);
|
|
|
|
out.writeSint32LE(walkStepIndex);
|
|
|
|
finalTarget.saveState(out);
|
|
|
|
partialTarget.saveState(out);
|
|
|
|
out.writeSint32LE(walkFrameSequence);
|
|
|
|
}
|
2005-05-10 22:56:25 +00:00
|
|
|
void loadState(Common::File& in) {
|
2005-04-27 11:51:11 +00:00
|
|
|
CommonObjectData::loadState(in);
|
|
|
|
actorFlags = in.readUint16LE();
|
|
|
|
currentAction = in.readSint32LE();
|
|
|
|
facingDirection = in.readSint32LE();
|
|
|
|
actionDirection = in.readSint32LE();
|
|
|
|
actionCycle = in.readSint32LE();
|
|
|
|
targetObject = in.readUint16LE();
|
|
|
|
|
|
|
|
//TODO: read lastZone
|
|
|
|
lastZone = NULL;
|
|
|
|
cycleFrameSequence = in.readSint32LE();
|
|
|
|
cycleDelay = in.readByte();
|
|
|
|
cycleTimeCount = in.readByte();
|
|
|
|
cycleFlags = in.readByte();
|
|
|
|
frameNumber = in.readSint32LE();
|
|
|
|
|
|
|
|
|
|
|
|
setTileDirectionsSize(in.readSint32LE(), true);
|
2005-05-08 21:49:52 +00:00
|
|
|
for (int i = 0; i < tileDirectionsAlloced; i++) {
|
2005-04-27 11:51:11 +00:00
|
|
|
tileDirections[i] = in.readByte();
|
|
|
|
}
|
|
|
|
|
|
|
|
setWalkStepsPointsSize(in.readSint32LE(), true);
|
2005-05-08 21:49:52 +00:00
|
|
|
for (int i = 0; i < walkStepsAlloced; i++) {
|
2005-04-27 11:51:11 +00:00
|
|
|
walkStepsPoints[i].x = in.readSint16LE();
|
|
|
|
walkStepsPoints[i].y = in.readSint16LE();
|
|
|
|
}
|
|
|
|
|
|
|
|
walkStepsCount = in.readSint32LE();
|
|
|
|
walkStepIndex = in.readSint32LE();
|
|
|
|
finalTarget.loadState(in);
|
|
|
|
partialTarget.loadState(in);
|
|
|
|
walkFrameSequence = in.readSint32LE();
|
|
|
|
}
|
|
|
|
|
|
|
|
void setTileDirectionsSize(int size, bool forceRealloc) {
|
|
|
|
if ((size <= tileDirectionsAlloced) && !forceRealloc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tileDirectionsAlloced = size;
|
|
|
|
tileDirections = (byte*)realloc(tileDirections, tileDirectionsAlloced * sizeof(*tileDirections));
|
|
|
|
}
|
|
|
|
|
2004-12-22 21:04:50 +00:00
|
|
|
void cycleWrap(int cycleLimit) {
|
|
|
|
if (actionCycle >= cycleLimit)
|
|
|
|
actionCycle = 0;
|
|
|
|
}
|
2005-01-05 19:03:49 +00:00
|
|
|
|
2005-04-27 11:51:11 +00:00
|
|
|
void setWalkStepsPointsSize(int size, bool forceRealloc) {
|
|
|
|
if ((size <= walkStepsAlloced) && !forceRealloc) {
|
|
|
|
return;
|
2005-01-05 19:03:49 +00:00
|
|
|
}
|
2005-04-27 11:51:11 +00:00
|
|
|
walkStepsAlloced = size;
|
|
|
|
walkStepsPoints = (Point*)realloc(walkStepsPoints, walkStepsAlloced * sizeof(*walkStepsPoints));
|
|
|
|
}
|
|
|
|
|
|
|
|
void addWalkStepPoint(const Point &point) {
|
|
|
|
setWalkStepsPointsSize(walkStepsCount + 1, false);
|
2005-01-05 19:03:49 +00:00
|
|
|
walkStepsPoints[walkStepsCount++] = point;
|
2004-12-28 21:27:18 +00:00
|
|
|
}
|
2004-12-17 20:38:17 +00:00
|
|
|
|
|
|
|
ActorData() {
|
2005-04-27 11:51:11 +00:00
|
|
|
memset(this, 0, sizeof(*this));
|
2005-01-05 19:03:49 +00:00
|
|
|
}
|
|
|
|
~ActorData() {
|
2005-01-15 20:12:49 +00:00
|
|
|
free(frames);
|
2005-02-26 17:37:16 +00:00
|
|
|
free(tileDirections);
|
2005-01-05 19:03:49 +00:00
|
|
|
free(walkStepsPoints);
|
2005-01-15 20:12:49 +00:00
|
|
|
spriteList.freeMem();
|
2004-12-15 00:24:12 +00:00
|
|
|
}
|
2004-04-25 14:42:14 +00:00
|
|
|
};
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
|
2004-12-15 00:24:12 +00:00
|
|
|
|
2004-12-21 06:49:07 +00:00
|
|
|
struct SpeechData {
|
2005-01-13 07:47:04 +00:00
|
|
|
int speechColor[ACTOR_SPEECH_ACTORS_MAX];
|
|
|
|
int outlineColor[ACTOR_SPEECH_ACTORS_MAX];
|
2004-12-21 06:49:07 +00:00
|
|
|
int speechFlags;
|
|
|
|
const char *strings[ACTOR_SPEECH_STRING_MAX];
|
2005-01-13 07:47:04 +00:00
|
|
|
Point speechCoords[ACTOR_SPEECH_ACTORS_MAX];
|
2004-12-21 06:49:07 +00:00
|
|
|
int stringsCount;
|
|
|
|
int slowModeCharIndex;
|
|
|
|
uint16 actorIds[ACTOR_SPEECH_ACTORS_MAX];
|
|
|
|
int actorsCount;
|
|
|
|
int sampleResourceId;
|
|
|
|
bool playing;
|
|
|
|
int playingTime;
|
|
|
|
|
|
|
|
SpeechData() {
|
|
|
|
memset(this, 0, sizeof(*this));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2005-01-15 23:46:43 +00:00
|
|
|
|
|
|
|
|
2004-08-02 15:47:42 +00:00
|
|
|
class Actor {
|
2005-04-22 14:11:04 +00:00
|
|
|
friend class IsoMap;
|
|
|
|
friend class SagaEngine;
|
2004-10-31 13:51:01 +00:00
|
|
|
public:
|
2004-12-22 21:04:50 +00:00
|
|
|
|
2004-08-02 15:47:42 +00:00
|
|
|
Actor(SagaEngine *vm);
|
|
|
|
~Actor();
|
2005-01-08 20:30:07 +00:00
|
|
|
|
|
|
|
void cmdActorWalkTo(int argc, const char **argv);
|
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
bool validActorId(uint16 id) { return (id == ID_PROTAG) || ((id >= objectIndexToId(kGameObjectActor, 0)) && (id < objectIndexToId(kGameObjectActor, _actorsCount))); }
|
2005-01-18 15:01:21 +00:00
|
|
|
int actorIdToIndex(uint16 id) { return (id == ID_PROTAG ) ? 0 : objectIdToIndex(id); }
|
|
|
|
uint16 actorIndexToId(int index) { return (index == 0 ) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); }
|
2005-01-18 21:13:44 +00:00
|
|
|
ActorData *getActor(uint16 actorId);
|
|
|
|
|
|
|
|
// clarification: Obj - means game object, such Hat, Spoon etc, Object - means Actor,Obj,HitZone,StepZone
|
|
|
|
|
|
|
|
bool validObjId(uint16 id) { return (id >= objectIndexToId(kGameObjectObject, 0)) && (id < objectIndexToId(kGameObjectObject, _objsCount)); }
|
|
|
|
int objIdToIndex(uint16 id) { return objectIdToIndex(id); }
|
|
|
|
uint16 objIndexToId(int index) { return objectIndexToId(kGameObjectObject, index); }
|
|
|
|
ObjectData *getObj(uint16 objId);
|
|
|
|
|
|
|
|
int getObjectScriptEntrypointNumber(uint16 id) {
|
|
|
|
int objectType;
|
|
|
|
objectType = objectTypeId(id);
|
|
|
|
if (!(objectType & (kGameObjectObject | kGameObjectActor))) {
|
|
|
|
error("Actor::getObjectScriptEntrypointNumber wrong id 0x%X", id);
|
|
|
|
}
|
|
|
|
return (objectType == kGameObjectObject) ? getObj(id)->scriptEntrypointNumber : getActor(id)->scriptEntrypointNumber;
|
|
|
|
}
|
|
|
|
int getObjectFlags(uint16 id) {
|
|
|
|
int objectType;
|
|
|
|
objectType = objectTypeId(id);
|
|
|
|
if (!(objectType & (kGameObjectObject | kGameObjectActor))) {
|
|
|
|
error("Actor::getObjectFlags wrong id 0x%X", id);
|
|
|
|
}
|
|
|
|
return (objectType == kGameObjectObject) ? getObj(id)->flags : getActor(id)->flags;
|
|
|
|
}
|
2005-01-08 20:30:07 +00:00
|
|
|
|
2004-08-02 15:47:42 +00:00
|
|
|
int direct(int msec);
|
2005-05-08 14:04:06 +00:00
|
|
|
void drawActors();
|
2005-01-15 23:46:43 +00:00
|
|
|
void updateActorsScene(int actorsEntrance); // calls from scene loading to update Actors info
|
2004-08-02 15:47:42 +00:00
|
|
|
|
2005-05-23 02:23:34 +00:00
|
|
|
void drawSpeech();
|
|
|
|
|
2005-01-06 19:15:01 +00:00
|
|
|
void drawPathTest();
|
|
|
|
|
2005-04-18 20:03:14 +00:00
|
|
|
uint16 hitTest(const Point &testPoint, bool skipProtagonist);
|
2005-01-15 23:46:43 +00:00
|
|
|
void takeExit(uint16 actorId, const HitZone *hitZone);
|
2004-12-25 11:17:03 +00:00
|
|
|
bool actorEndWalk(uint16 actorId, bool recurse);
|
2005-01-18 21:13:44 +00:00
|
|
|
bool actorWalkTo(uint16 actorId, const Location &toLocation);
|
2004-12-22 21:04:50 +00:00
|
|
|
ActorFrameRange *getActorFrameRange(uint16 actorId, int frameType);
|
2005-01-15 20:12:49 +00:00
|
|
|
void actorFaceTowardsPoint(uint16 actorId, const Location &toLocation);
|
2005-01-06 19:15:01 +00:00
|
|
|
void actorFaceTowardsObject(uint16 actorId, uint16 objectId);
|
2004-08-02 15:47:42 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
void realLocation(Location &location, uint16 objectId, uint16 walkFlags);
|
|
|
|
|
2004-12-21 06:49:07 +00:00
|
|
|
// speech
|
|
|
|
void actorSpeech(uint16 actorId, const char **strings, int stringsCount, uint16 sampleResourceId, int speechFlags);
|
|
|
|
void nonActorSpeech(const char **strings, int stringsCount, int speechFlags);
|
2005-05-22 01:20:47 +00:00
|
|
|
void simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags, int sampleResourceId);
|
2004-12-21 06:49:07 +00:00
|
|
|
void setSpeechColor(int speechColor, int outlineColor) {
|
2005-01-13 07:47:04 +00:00
|
|
|
_activeSpeech.speechColor[0] = speechColor;
|
|
|
|
_activeSpeech.outlineColor[0] = outlineColor;
|
2004-12-21 06:49:07 +00:00
|
|
|
}
|
|
|
|
void abortAllSpeeches();
|
|
|
|
void abortSpeech();
|
|
|
|
bool isSpeaking() {
|
|
|
|
return _activeSpeech.stringsCount > 0;
|
|
|
|
}
|
2005-04-21 01:30:07 +00:00
|
|
|
|
2005-05-10 22:56:25 +00:00
|
|
|
void saveState(Common::File& out);
|
|
|
|
void loadState(Common::File& in);
|
2005-04-28 17:19:43 +00:00
|
|
|
|
2005-04-21 01:30:07 +00:00
|
|
|
void setProtagState(int state);
|
|
|
|
int getProtagState() { return _protagState; }
|
2004-12-18 20:33:02 +00:00
|
|
|
|
2004-10-31 13:51:01 +00:00
|
|
|
private:
|
2004-12-30 18:45:48 +00:00
|
|
|
bool loadActorResources(ActorData *actor);
|
2005-01-15 23:46:43 +00:00
|
|
|
void stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, bool stopped);
|
|
|
|
|
2004-12-18 20:33:02 +00:00
|
|
|
void createDrawOrderList();
|
2005-01-18 21:13:44 +00:00
|
|
|
void calcScreenPosition(CommonObjectData *commonObjectData);
|
2005-01-18 23:15:41 +00:00
|
|
|
bool getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber, SpriteList *&spriteList);
|
2005-01-18 21:13:44 +00:00
|
|
|
|
2004-12-30 18:45:48 +00:00
|
|
|
bool followProtagonist(ActorData *actor);
|
|
|
|
void findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint);
|
2004-12-21 06:49:07 +00:00
|
|
|
void handleSpeech(int msec);
|
2004-12-22 21:04:50 +00:00
|
|
|
void handleActions(int msec, bool setup);
|
2005-01-04 18:54:29 +00:00
|
|
|
bool validPathCellPoint(const Point &testPoint) {
|
|
|
|
return !((testPoint.x < 0) || (testPoint.x >= _xCellCount) ||
|
|
|
|
(testPoint.y < 0) || (testPoint.y >= _yCellCount));
|
|
|
|
}
|
2005-01-06 22:22:20 +00:00
|
|
|
void setPathCell(const Point &testPoint, int8 value) {
|
2005-01-04 18:54:29 +00:00
|
|
|
if (!validPathCellPoint(testPoint)) {
|
|
|
|
error("Actor::setPathCell wrong point");
|
|
|
|
}
|
2004-12-28 21:27:18 +00:00
|
|
|
_pathCell[testPoint.x + testPoint.y * _xCellCount] = value;
|
|
|
|
}
|
2005-01-06 22:22:20 +00:00
|
|
|
int8 getPathCell(const Point &testPoint) {
|
2005-01-04 18:54:29 +00:00
|
|
|
if (!validPathCellPoint(testPoint)) {
|
|
|
|
error("Actor::getPathCell wrong point");
|
|
|
|
}
|
2004-12-28 21:27:18 +00:00
|
|
|
return _pathCell[testPoint.x + testPoint.y * _xCellCount];
|
|
|
|
}
|
|
|
|
bool scanPathLine(const Point &point1, const Point &point2);
|
2004-12-29 21:49:25 +00:00
|
|
|
int fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint);
|
2004-12-30 18:45:48 +00:00
|
|
|
void setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint);
|
2004-12-29 21:49:25 +00:00
|
|
|
void pathToNode();
|
|
|
|
void condenseNodeList();
|
|
|
|
void removeNodes();
|
|
|
|
void nodeToPath();
|
|
|
|
void removePathPoints();
|
2005-01-15 20:12:49 +00:00
|
|
|
bool validFollowerLocation(const Location &location);
|
2005-01-04 16:10:43 +00:00
|
|
|
|
2005-01-18 21:13:44 +00:00
|
|
|
|
2005-02-26 11:44:30 +00:00
|
|
|
protected:
|
2005-04-28 17:19:43 +00:00
|
|
|
//constants
|
2005-01-15 20:12:49 +00:00
|
|
|
int _actorsCount;
|
|
|
|
ActorData **_actors;
|
2005-01-18 21:13:44 +00:00
|
|
|
|
|
|
|
int _objsCount;
|
|
|
|
ObjectData **_objs;
|
|
|
|
|
2005-04-28 17:19:43 +00:00
|
|
|
SagaEngine *_vm;
|
|
|
|
RSCFILE_CONTEXT *_actorContext;
|
|
|
|
|
|
|
|
StringsTable _actorsStrings;
|
|
|
|
int _lastTickMsec;
|
|
|
|
CommonObjectOrderList _drawOrderList;
|
|
|
|
|
|
|
|
//variables
|
|
|
|
public:
|
|
|
|
ActorData *_centerActor;
|
|
|
|
ActorData *_protagonist;
|
2005-05-18 18:28:10 +00:00
|
|
|
int _handleActionDiv;
|
2005-04-28 17:19:43 +00:00
|
|
|
protected:
|
2004-12-21 06:49:07 +00:00
|
|
|
SpeechData _activeSpeech;
|
2005-04-21 01:30:07 +00:00
|
|
|
int _protagState;
|
2004-12-29 21:49:25 +00:00
|
|
|
|
2005-04-28 17:19:43 +00:00
|
|
|
private:
|
2004-12-29 21:49:25 +00:00
|
|
|
//path stuff
|
2005-01-18 21:13:44 +00:00
|
|
|
struct PathNode {
|
|
|
|
Point point;
|
|
|
|
int link;
|
|
|
|
};
|
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
Rect _barrierList[ACTOR_BARRIERS_MAX];
|
|
|
|
int _barrierCount;
|
2005-01-06 22:22:20 +00:00
|
|
|
int8 *_pathCell;
|
2005-01-06 21:57:10 +00:00
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
int _xCellCount;
|
|
|
|
int _yCellCount;
|
|
|
|
Rect _pathRect;
|
2005-01-06 21:57:10 +00:00
|
|
|
|
2005-01-16 20:30:57 +00:00
|
|
|
PathDirectionData *_pathDirectionList;
|
|
|
|
int _pathDirectionListCount;
|
|
|
|
int _pathDirectionListAlloced;
|
|
|
|
PathDirectionData * addPathDirectionListData() {
|
|
|
|
if (_pathDirectionListCount + 1 >= _pathDirectionListAlloced) {
|
|
|
|
_pathDirectionListAlloced += 100;
|
|
|
|
_pathDirectionList = (PathDirectionData*) realloc(_pathDirectionList, _pathDirectionListAlloced * sizeof(*_pathDirectionList));
|
|
|
|
}
|
|
|
|
return &_pathDirectionList[_pathDirectionListCount++];
|
|
|
|
}
|
|
|
|
|
2005-01-06 21:57:10 +00:00
|
|
|
Point *_pathList;
|
2004-12-29 21:49:25 +00:00
|
|
|
int _pathListIndex;
|
2005-01-06 21:57:10 +00:00
|
|
|
int _pathListAlloced;
|
|
|
|
void addPathListPoint(const Point &point) {
|
|
|
|
++_pathListIndex;
|
|
|
|
if (_pathListIndex >= _pathListAlloced) {
|
|
|
|
_pathListAlloced += 100;
|
|
|
|
_pathList = (Point*) realloc(_pathList, _pathListAlloced * sizeof(*_pathList));
|
|
|
|
|
|
|
|
}
|
|
|
|
_pathList[_pathListIndex] = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
int _pathNodeListIndex;
|
|
|
|
int _pathNodeListAlloced;
|
|
|
|
PathNode *_pathNodeList;
|
|
|
|
void addPathNodeListPoint(const Point &point) {
|
|
|
|
++_pathNodeListIndex;
|
|
|
|
if (_pathNodeListIndex >= _pathNodeListAlloced) {
|
|
|
|
_pathNodeListAlloced += 100;
|
|
|
|
_pathNodeList = (PathNode*) realloc(_pathNodeList, _pathNodeListAlloced * sizeof(*_pathNodeList));
|
2004-12-28 21:27:18 +00:00
|
|
|
|
2005-01-06 21:57:10 +00:00
|
|
|
}
|
|
|
|
_pathNodeList[_pathNodeListIndex].point = point;
|
|
|
|
}
|
2005-01-15 23:46:43 +00:00
|
|
|
|
|
|
|
int _newPathNodeListIndex;
|
|
|
|
int _newPathNodeListAlloced;
|
|
|
|
PathNode *_newPathNodeList;
|
|
|
|
void incrementNewPathNodeListIndex() {
|
|
|
|
++_newPathNodeListIndex;
|
|
|
|
if (_newPathNodeListIndex >= _newPathNodeListAlloced) {
|
|
|
|
_newPathNodeListAlloced += 100;
|
|
|
|
_newPathNodeList = (PathNode*) realloc(_newPathNodeList, _newPathNodeListAlloced * sizeof(*_newPathNodeList));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2005-01-18 21:13:44 +00:00
|
|
|
void addNewPathNodeListPoint(const PathNode &pathNode) {
|
2005-01-15 23:46:43 +00:00
|
|
|
incrementNewPathNodeListIndex();
|
2005-01-18 21:13:44 +00:00
|
|
|
_newPathNodeList[_newPathNodeListIndex] = pathNode;
|
2005-01-15 23:46:43 +00:00
|
|
|
}
|
|
|
|
|
2005-01-06 19:15:01 +00:00
|
|
|
public:
|
2005-01-06 23:02:53 +00:00
|
|
|
#ifdef ACTOR_DEBUG
|
2005-01-06 19:15:01 +00:00
|
|
|
//path debug - use with care
|
|
|
|
struct DebugPoint {
|
|
|
|
Point point;
|
|
|
|
byte color;
|
|
|
|
};
|
|
|
|
DebugPoint *_debugPoints;
|
|
|
|
int _debugPointsCount;
|
|
|
|
int _debugPointsAlloced;
|
|
|
|
void addDebugPoint(const Point &point, byte color) {
|
|
|
|
if (_debugPointsCount + 1 > _debugPointsAlloced) {
|
|
|
|
_debugPointsAlloced += 1000;
|
|
|
|
_debugPoints = (DebugPoint*) realloc(_debugPoints, _debugPointsAlloced * sizeof(*_debugPoints));
|
|
|
|
}
|
|
|
|
_debugPoints[_debugPointsCount].color = color;
|
|
|
|
_debugPoints[_debugPointsCount++].point = point;
|
|
|
|
}
|
2005-01-06 23:02:53 +00:00
|
|
|
#endif
|
2004-08-02 15:47:42 +00:00
|
|
|
};
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-12-28 21:27:18 +00:00
|
|
|
inline int16 quickDistance(const Point &point1, const Point &point2) {
|
|
|
|
Point delta;
|
|
|
|
delta.x = ABS(point1.x - point2.x);
|
|
|
|
delta.y = ABS(point1.y - point2.y);
|
|
|
|
return ((delta.x < delta.y) ? (delta.y + delta.x / 2) : (delta.x + delta.y / 2));
|
|
|
|
}
|
2004-04-12 21:40:49 +00:00
|
|
|
} // End of namespace Saga
|
|
|
|
|
2004-05-01 06:16:57 +00:00
|
|
|
#endif
|