dragon wip1

svn-id: r18476
This commit is contained in:
Andrew Kurushin 2005-06-29 20:00:44 +00:00
parent ac071d6470
commit 0a29c11bc9
5 changed files with 541 additions and 3 deletions

View File

@ -151,6 +151,26 @@ static const int tileDirectionLUT[8][2] = {
{ 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 } }},
};
Actor::Actor(SagaEngine *vm) : _vm(vm) {
int i;
int result;
@ -267,6 +287,8 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_protagonist = &dummyActor;
}
_dragonHunt = true;
}
Actor::~Actor() {
@ -1381,7 +1403,11 @@ void Actor::drawSpeech(void) {
if (_activeSpeech.actorIds[0] != 0) {
for (i = 0; i < _activeSpeech.actorsCount; i++){
_vm->textDraw(MEDIUM_FONT_ID, back_buf, outputString, _activeSpeech.speechCoords[i].x, _activeSpeech.speechCoords[i].y, _activeSpeech.speechColor[i], _activeSpeech.outlineColor[i], textDrawFlags);
_vm->textDraw(MEDIUM_FONT_ID, back_buf, outputString,
_activeSpeech.speechCoords[i].x,
_activeSpeech.speechCoords[i].y,
_activeSpeech.speechColor[i],
_activeSpeech.outlineColor[i], textDrawFlags);
}
} else { // non actors speech
@ -1850,6 +1876,253 @@ void Actor::abortSpeech() {
_activeSpeech.playingTime = 0;
}
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 = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_EXEC_NONBLOCKING;
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;
}
void Actor::findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
Point iteratorPoint;
Point bestPoint;

View File

@ -63,8 +63,12 @@ class HitZone;
#define ACTOR_SPEECH_STRING_MAX 16 // speech const
#define ACTOR_SPEECH_ACTORS_MAX 8
#define ACTOR_DRAGON_TURN_MOVES 4
#define ACTOR_NO_ENTRANCE -1
#define ACTOR_EXP_KNOCK_RIF 24
#define PATH_NODE_EMPTY -1
enum ActorActions {
@ -122,6 +126,22 @@ enum PathCellType {
kPathCellBarrier = 0x57
};
enum DragonMoveTypes {
kDragonMoveUpLeft = 0,
kDragonMoveUpRight = 1,
kDragonMoveDownLeft = 2,
kDragonMoveDownRight = 3,
kDragonMoveUpLeft_Left = 4,
kDragonMoveUpLeft_Right = 5,
kDragonMoveUpRight_Left = 6,
kDragonMoveUpRight_Right = 7,
kDragonMoveDownLeft_Left = 8,
kDragonMoveDownLeft_Right = 9,
kDragonMoveDownRight_Left = 10,
kDragonMoveDownRight_Right = 11,
kDragonMoveInvalid = 12
};
struct PathDirectionData {
int8 direction;
int16 x;
@ -295,6 +315,10 @@ public:
int16 fallAcceleration;
int16 fallPosition;
uint8 dragonBaseFrame;
uint8 dragonStepCycle;
uint8 dragonMoveType;
int32 frameNumber; // current frame number
int32 tileDirectionsAlloced;
@ -326,6 +350,9 @@ public:
out->writeSint16LE(fallVelocity);
out->writeSint16LE(fallAcceleration);
out->writeSint16LE(fallPosition);
out->writeByte(dragonBaseFrame);
out->writeByte(dragonStepCycle);
out->writeByte(dragonMoveType);
out->writeSint32LE(frameNumber);
out->writeSint32LE(tileDirectionsAlloced);
@ -367,6 +394,14 @@ public:
} else {
fallVelocity = fallAcceleration = fallPosition = 0;
}
if (_vm->getCurrentLoadVersion() > 2) {
dragonBaseFrame = in->readByte();
dragonStepCycle = in->readByte();
dragonMoveType = in->readByte();
} else {
dragonBaseFrame = dragonStepCycle = dragonMoveType = 0;
}
frameNumber = in->readSint32LE();
@ -562,6 +597,7 @@ private:
void nodeToPath();
void removePathPoints();
bool validFollowerLocation(const Location &location);
void moveDragon(ActorData *actor);
protected:
@ -587,6 +623,7 @@ public:
protected:
SpeechData _activeSpeech;
int _protagState;
bool _dragonHunt;
private:
//path stuff

View File

@ -897,7 +897,51 @@ void IsoMap::drawTile(SURFACE *ds, uint16 tileIndex, const Point &point, const L
}
//
bool IsoMap::checkDragonPoint(int16 u, int16 v, uint16 direction) {
DragonPathCell *pathCell;
if ((u < 1) || (u >= SAGA_DRAGON_SEARCH_DIAMETER - 1) || (v < 1) || (v >= SAGA_DRAGON_SEARCH_DIAMETER - 1)) {
return false;
}
pathCell = _dragonSearchArray.getPathCell(u, v);
if (pathCell->visited) {
return false;
}
pathCell->visited = 1;
pathCell->direction = direction;
return true;
}
void IsoMap::pushDragonPoint(int16 u, int16 v, uint16 direction) {
DragonTilePoint *tilePoint;
DragonPathCell *pathCell;
if ((u < 1) || (u >= SAGA_DRAGON_SEARCH_DIAMETER - 1) || (v < 1) || (v >= SAGA_DRAGON_SEARCH_DIAMETER - 1)) {
return;
}
pathCell = _dragonSearchArray.getPathCell(u, v);
if (pathCell->visited) {
return;
}
tilePoint = _dragonSearchArray.getQueue(_queueCount);
_queueCount++;
if (_queueCount >= SAGA_SEARCH_QUEUE_SIZE) {
_queueCount = 0;
}
tilePoint->u = u;
tilePoint->v = v;
tilePoint->direction = direction;
pathCell->visited = 1;
pathCell->direction = direction;
}
void IsoMap::pushPoint(int16 u, int16 v, uint16 cost, uint16 direction) {
int16 upper;
@ -1211,6 +1255,163 @@ void IsoMap::placeOnTileMap(const Location &start, Location &result, int16 dista
result.v() = ((vBase + bestV) << 4) + 8;
}
void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Location &end, uint16 initialDirection) {
byte *res;
int i;
int16 u;
int16 v;
int16 u1;
int16 v1;
uint16 dir;
int16 bestDistance;
int16 bestU;
int16 bestV;
int16 uBase;
int16 vBase;
int16 uFinish;
int16 vFinish;
DragonPathCell *pcell;
IsoTileData *tile;
uint16 mask;
DragonTilePoint *tilePoint;
int16 dist;
bool first;
bestDistance = SAGA_DRAGON_SEARCH_DIAMETER;
bestU = SAGA_DRAGON_SEARCH_CENTER,
bestV = SAGA_DRAGON_SEARCH_CENTER;
uBase = (start.u() >> 4) - SAGA_DRAGON_SEARCH_CENTER;
vBase = (start.v() >> 4) - SAGA_DRAGON_SEARCH_CENTER;
uFinish = (end.u() >> 4) - uBase;
vFinish = (end.v() >> 4) - vBase;
_platformHeight = _vm->_actor->_protagonist->location.z / 8;
memset( &_dragonSearchArray, 0, sizeof(_dragonSearchArray));
for (u = 0; u < SAGA_DRAGON_SEARCH_CENTER; u++) {
for (v = 0; v < SAGA_DRAGON_SEARCH_CENTER; v++) {
pcell = _dragonSearchArray.getPathCell(u, v);
u1 = uBase + u;
v1 = vBase + v;
if ((u1 > 127) || (u1 < 48) || (v1 > 127) || (v1 < 0)) {
pcell->visited = 1;
continue;
}
tile = getTile(u1, v1, _platformHeight );
if (tile != NULL) {
mask = tile->terrainMask;
if ( ((tile->terrainMask != 0) && (tile->GetFGDAttr() >= kTerrBlock)) ||
((tile->terrainMask != 0xFFFF) && (tile->GetBGDAttr() >= kTerrBlock)) ) {
pcell->visited = 1;
}
} else {
pcell->visited = 1;
}
}
}
first = true;
_queueCount = _readCount = 0;
pushDragonPoint( SAGA_DRAGON_SEARCH_CENTER, SAGA_DRAGON_SEARCH_CENTER, initialDirection);
while (_queueCount != _readCount) {
tilePoint = _dragonSearchArray.getQueue(_readCount++);
if (_readCount >= SAGA_SEARCH_QUEUE_SIZE) {
_readCount = 0;
}
dist = ABS(tilePoint->u - uFinish) + ABS(tilePoint->v - vFinish);
if (dist < bestDistance) {
bestU = tilePoint->u;
bestV = tilePoint->v;
bestDistance = dist;
if (dist == 0) {
break;
}
}
switch (tilePoint->direction) {
case kDirUpRight:
if (checkDragonPoint( tilePoint->u + 1, tilePoint->v + 0, 1)) {
pushDragonPoint( tilePoint->u + 2, tilePoint->v + 0, 1);
pushDragonPoint( tilePoint->u + 1, tilePoint->v + 1, 7);
pushDragonPoint( tilePoint->u + 1, tilePoint->v - 1, 3);
}
break;
case kDirDownRight:
if (checkDragonPoint( tilePoint->u + 0, tilePoint->v - 1, 3)) {
pushDragonPoint( tilePoint->u + 0, tilePoint->v - 2, 3);
pushDragonPoint( tilePoint->u + 1, tilePoint->v - 1, 1);
pushDragonPoint( tilePoint->u - 1, tilePoint->v - 1, 5);
}
break;
case kDirDownLeft:
if (checkDragonPoint( tilePoint->u - 1, tilePoint->v + 0, 5)) {
pushDragonPoint( tilePoint->u - 2, tilePoint->v + 0, 5);
pushDragonPoint( tilePoint->u - 1, tilePoint->v - 1, 3);
pushDragonPoint( tilePoint->u - 1, tilePoint->v + 1, 7);
}
break;
case kDirUpLeft:
if (checkDragonPoint( tilePoint->u + 0, tilePoint->v + 1, 7)) {
pushDragonPoint( tilePoint->u + 0, tilePoint->v + 2, 7);
pushDragonPoint( tilePoint->u - 1, tilePoint->v + 1, 5);
pushDragonPoint( tilePoint->u + 1, tilePoint->v + 1, 1);
}
break;
}
if (first && (_queueCount == _readCount)) {
pushDragonPoint( tilePoint->u + 1, tilePoint->v + 0, 1);
pushDragonPoint( tilePoint->u + 0, tilePoint->v - 1, 3);
pushDragonPoint( tilePoint->u - 1, tilePoint->v + 0, 5);
pushDragonPoint( tilePoint->u + 0, tilePoint->v + 1, 7);
}
first = false;
}
res = &_pathDirections[SAGA_MAX_PATH_DIRECTIONS];
i = 0;
while ((bestU != SAGA_DRAGON_SEARCH_CENTER) || (bestV != SAGA_DRAGON_SEARCH_CENTER)) {
pcell = _dragonSearchArray.getPathCell(bestU, bestV);
*--res = pcell->direction;
i++;
if (i >= SAGA_MAX_PATH_DIRECTIONS) {
break;
}
dir = (pcell->direction + 4) & 0x07;
bestU += normalDirTable[dir].u;
bestV += normalDirTable[dir].v;
}
/* if (i > 64) {
i = 64;
}*/
actor->walkStepsCount = i;
if (i) {
actor->setTileDirectionsSize(i, false);
memcpy(actor->tileDirections, res, i );
}
}
void IsoMap::findTilePath(ActorData* actor, const Location &start, const Location &end) {
ActorData *other;
int i;

View File

@ -53,6 +53,9 @@ namespace Saga {
#define SAGA_SCROLL_LIMIT_Y1 8
#define SAGA_SCROLL_LIMIT_Y2 32
#define SAGA_DRAGON_SEARCH_CENTER 24
#define SAGA_DRAGON_SEARCH_DIAMETER (SAGA_DRAGON_SEARCH_CENTER * 2)
#define SAGA_SEARCH_CENTER 15
#define SAGA_SEARCH_DIAMETER (SAGA_SEARCH_CENTER * 2)
#define SAGA_SEARCH_QUEUE_SIZE 128
@ -164,6 +167,7 @@ public:
}
void screenPointToTileCoords(const Point &position, Location &location);
void placeOnTileMap(const Location &start, Location &result, int16 distance, uint16 direction);
void findDragonTilePath(ActorData* actor, const Location &start, const Location &end, uint16 initialDirection);
void findTilePath(ActorData* actor, const Location &start, const Location &end);
bool nextTileTarget(ActorData* actor);
void setTileDoorState(int doorNumber, int doorState);
@ -197,6 +201,8 @@ private:
}
int16 findMulti(int16 tileIndex, int16 absU, int16 absV, int16 absH);
void pushPoint(int16 u, int16 v, uint16 cost, uint16 direction);
void pushDragonPoint(int16 u, int16 v, uint16 direction);
bool checkDragonPoint(int16 u, int16 v, uint16 direction);
void testPossibleDirections(int16 u, int16 v, uint16 terraComp[8], int skipCenter);
IsoTileData *getTile(int16 u, int16 v, int16 z);
@ -223,6 +229,13 @@ private:
// path finding stuff
uint16 _platformHeight;
struct DragonPathCell {
uint16 visited:1,direction:3;
};
struct DragonTilePoint {
int8 u, v;
uint16 direction:4;
};
struct PathCell {
uint16 visited:1,direction:3,cost:12;
};
@ -234,6 +247,18 @@ public:
};
private:
struct DragonSearchArray {
DragonPathCell cell[SAGA_DRAGON_SEARCH_DIAMETER][SAGA_DRAGON_SEARCH_DIAMETER];
DragonTilePoint queue[SAGA_SEARCH_QUEUE_SIZE];
DragonTilePoint *getQueue(uint16 i) {
assert(i < SAGA_SEARCH_QUEUE_SIZE);
return &queue[i];
}
DragonPathCell *getPathCell(uint16 u, uint16 v) {
assert((u < SAGA_DRAGON_SEARCH_DIAMETER) && (v < SAGA_DRAGON_SEARCH_DIAMETER));
return &cell[u][v];
}
};
struct SearchArray {
PathCell cell[SAGA_SEARCH_DIAMETER][SAGA_SEARCH_DIAMETER];
TilePoint queue[SAGA_SEARCH_QUEUE_SIZE];
@ -248,7 +273,9 @@ private:
};
int16 _queueCount;
int16 _readCount;
SearchArray _searchArray;
DragonSearchArray _dragonSearchArray;
byte _pathDirections[SAGA_MAX_PATH_DIRECTIONS];

View File

@ -38,7 +38,7 @@
#include "saga/render.h"
#include "saga/events.h"
#define CURRENT_SAGA_VER 2
#define CURRENT_SAGA_VER 3
namespace Saga {