aboutsummaryrefslogtreecommitdiff
path: root/engines/illusions/actor.cpp
diff options
context:
space:
mode:
authorjohndoe1232014-03-31 19:54:55 +0200
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commitf2c48e3ae0e5775da6f3dcac841414cf8b5379ef (patch)
tree61eb9c915e846d26922d7c584b7b929102927034 /engines/illusions/actor.cpp
parente0e4d2ffa92fccdef1ea3eae0228ec812c7dbac5 (diff)
downloadscummvm-rg350-f2c48e3ae0e5775da6f3dcac841414cf8b5379ef.tar.gz
scummvm-rg350-f2c48e3ae0e5775da6f3dcac841414cf8b5379ef.tar.bz2
scummvm-rg350-f2c48e3ae0e5775da6f3dcac841414cf8b5379ef.zip
ILLUSIONS: Implement pathwalking (actual pathfinding todo)
Diffstat (limited to 'engines/illusions/actor.cpp')
-rw-r--r--engines/illusions/actor.cpp266
1 files changed, 234 insertions, 32 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp
index d9eb94975f..2973a92f73 100644
--- a/engines/illusions/actor.cpp
+++ b/engines/illusions/actor.cpp
@@ -25,6 +25,7 @@
#include "illusions/camera.h"
#include "illusions/cursor.h"
#include "illusions/dictionary.h"
+#include "illusions/fixedpoint.h"
#include "illusions/input.h"
#include "illusions/screen.h"
#include "illusions/scriptman.h"
@@ -94,29 +95,29 @@ Actor::Actor(IllusionsEngine *vm)
_notifyId3C = 0;
- _pathCtrY = 0;
-
_controlRoutine = 0;
setControlRoutine(new Common::Functor2Mem<Control*, uint32, void, Controls>(_vm->_controls, &Controls::actorControlRoutine));
-#if 0 // TODO
- _field2 = 0;
- _path40 = 0;
- _path4C = 0;
- _pathFlag50 = 0;
+ _walkCallerThreadId1 = 0;
+ _pathAngle = 0;
+ _pathFlag50 = false;
_pathCtrX = 0;
- _pathInitialPosFlag = 1;
+ _pathCtrY = 0;
+ _pathInitialPosFlag = true;
_pathInitialPos.x = 0;
_pathInitialPos.y = 0;
+ _pathPoints = 0;
+ _pathPointIndex = 0;
+ _pathPointsCount = 0;
+ _pathNode = 0;
+
+#if 0 // TODO
+ _field2 = 0;
_namedPointsCount = 0;
_namedPoints = 0;
_field164 = 0;
_pathWalkRects = 0;
_pathWalkPoints = 0;
- _pathNode = 0;
- _pathPoints = 0;
- _pathPointIndex = 0;
- _pathPointsCount = 0;
_regionLayer = 0;
_transitionRegionId = 0;
_field18C = 0;
@@ -342,7 +343,7 @@ void Control::setActorScale(int scale) {
for (uint i = 0; i < kSubObjectsCount; ++i)
if (_actor->_subobjects[i]) {
Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[i]);
- subControl->activateObject();
+ subControl->setActorScale(scale);
}
}
@@ -528,19 +529,17 @@ void Control::setActorFrameIndex(int16 frameIndex) {
void Control::stopActor() {
_actor->_seqCodeIp = 0;
- /* TODO
if (_actor->_pathNode) {
if (_actor->_flags & 0x0400) {
- // TODO delete _actor->_pathNode;
+ delete _actor->_pathNode;
_actor->_flags &= ~0x0400;
}
_actor->_pathNode = 0;
_actor->_pathPoints = 0;
_actor->_pathPointsCount = 0;
_actor->_pathPointIndex = 0;
- _actor->_path40 = 0;
+ _actor->_walkCallerThreadId1 = 0;
}
- */
_vm->notifyThreadId(_actor->_notifyThreadId1);
_vm->notifyThreadId(_actor->_notifyId3C);
}
@@ -570,16 +569,14 @@ void Control::startTalkActor(uint32 sequenceId, byte *entryTblPtr, uint32 thread
if (_actor->_linkIndex2) {
Control *subControl = _vm->_dict->getObjectControl(_actor->_subobjects[_actor->_linkIndex2 - 1]);
if (subControl->_actor->_flags & 1) {
- /* TODO
- if (control->_actor->pathNode) {
+ if (subControl->_actor->_pathNode) {
doSeq = false;
- subControl->_actor->notifyThreadId2 = threadId;
- subControl->_actor->entryTblPtr = entryTblPtr;
- subControl->_actor->flags |= 0x80;
- Thread *thread = _vm->_threads->findThread(threadId);
+ subControl->_actor->_notifyThreadId2 = threadId;
+ subControl->_actor->_entryTblPtr = entryTblPtr;
+ subControl->_actor->_flags |= 0x80;
+ Thread *thread = _vm->_scriptMan->_threads->findThread(threadId);
thread->sendMessage(kMsgClearSequenceId2, 0);
}
- */
}
}
if (doSeq)
@@ -653,7 +650,7 @@ void Control::startSubSequence(int linkIndex, uint32 sequenceId) {
linkedActor->_sequenceId = sequenceId;
linkedActor->_notifyThreadId1 = 0;
linkedActor->_notifyId3C = 0;
- linkedActor->_path40 = 0;
+ linkedActor->_walkCallerThreadId1 = 0;
Sequence *sequence = _vm->_dict->findSequence(sequenceId);
linkedActor->_seqCodeIp = sequence->_sequenceCode;
@@ -688,6 +685,213 @@ void Control::stopSubSequence(int linkIndex) {
}
}
+void Control::startMoveActor(uint32 sequenceId, Common::Point destPt, uint32 callerThreadId1, uint32 callerThreadId2) {
+ PointArray *pathNode;
+ ActorType *actorType = _vm->_dict->findActorType(_actorTypeId);
+
+ _actor->_pathAngle = 0;
+ _actor->_pathFlag50 = false;
+ _actor->_seqCodeValue3 = 0;
+ _actor->_seqCodeValue1 = 0;
+ // TODO _actor->_field_BC = _actor->_position.x;
+ // TODO _actor->_field_BE = _actor->_position.x;
+ _actor->_pathInitialPosFlag = true;
+ // TODO _actor->_field_C0 = destPt.x;
+ // TODO _actor->_field_C2 = destPt.y;
+
+ /* TODO
+ uint newFacing;
+ if (calcPointDirection(_actor->_position, destPt, newFacing))
+ faceActor(newFacing);
+ */
+
+ if (actorType->_value1E)
+ _actor->_pathCtrY = actorType->_value1E;
+ else
+ _actor->_pathCtrY = 140;
+
+ pathNode = createPath(destPt);
+
+ if (pathNode->size() == 1 &&
+ _actor->_position.x == (*pathNode)[0].x &&
+ _actor->_position.y == (*pathNode)[0].y) {
+ delete pathNode;
+ _vm->notifyThreadId(callerThreadId2);
+ } else {
+ _actor->_posXShl = _actor->_position.x << 16;
+ _actor->_posYShl = _actor->_position.y << 16;
+ startSequenceActor(sequenceId, 1, 0);
+ _actor->_pathNode = pathNode;
+ _actor->_pathPointsCount = pathNode->size();
+ _actor->_pathPoints = pathNode->size();
+ _actor->_flags |= 0x0400;
+ _actor->_walkCallerThreadId1 = callerThreadId1;
+ _vm->notifyThreadId(_actor->_notifyId3C);
+ _actor->_notifyId3C = callerThreadId2;
+ _actor->_pathPointIndex = 0;
+ _vm->_input->discardButtons(0x10);
+ }
+
+}
+
+PointArray *Control::createPath(Common::Point destPt) {
+ // TODO Implement actual pathfinding
+ PointArray *pathNode = new PointArray();
+ pathNode->push_back(destPt);
+ return pathNode;
+}
+
+void Control::updateActorMovement(uint32 deltaTime) {
+ // TODO This needs some cleanup
+
+ static const int16 kAngleTbl[] = {60, 0, 120, 0, 60, 0, 120, 0};
+
+ while (1) {
+
+ bool again = false;
+
+ /* TODO
+ if (controla->objectId == GameScript_getField0() && again == const0 && Input_pollButton__(0x10u)) {
+ again = 1;
+ Control_disappearActor__(controla);
+ HIBYTE(_actor->_flags) |= 0x80u;
+ _actor->_seqCodeIp = 0;
+ deltaTime = 2;
+ }
+ */
+
+ Common::Point prevPt;
+ if (_actor->_pathPointIndex == 0) {
+ if (_actor->_pathInitialPosFlag) {
+ _actor->_pathCtrX = 0;
+ _actor->_pathInitialPos = _actor->_position;
+ _actor->_pathInitialPosFlag = false;
+ }
+ prevPt = _actor->_pathInitialPos;
+ } else {
+ prevPt = (*_actor->_pathNode)[_actor->_pathPointIndex - 1];
+ }
+
+ Common::Point currPt = (*_actor->_pathNode)[_actor->_pathPointIndex];
+
+ int16 deltaX = currPt.x - prevPt.x;
+ int16 deltaY = currPt.y - prevPt.y;
+
+ if (!_actor->_pathFlag50) {
+
+ // TODO Move to own function
+ FP16 angle;
+ if (currPt.x == prevPt.x) {
+ if (prevPt.y >= currPt.y)
+ angle = fixedMul(-0x5A0000, 0x478);
+ else
+ angle = fixedMul(0x5A0000, 0x478);
+ } else {
+ angle = fixedAtan(fixedDiv(deltaY << 16, deltaX << 16));
+ }
+ _actor->_pathAngle = angle;
+
+ // TODO Move to own function
+ int16 v13 = (fixedTrunc(fixedMul(angle, 0x394BB8)) + 360) % 360;
+ if (deltaX >= 0)
+ v13 += 180;
+ v13 = (v13 + 90) % 360;
+ int16 v15 = kAngleTbl[0] / -2;
+ uint newFacing = 1;
+ for (uint i = 0; i < 8; ++i) {
+ v15 += kAngleTbl[i];
+ if (v13 < v15) {
+ newFacing = 1 << i;
+ break;
+ }
+ }
+ if (newFacing != _actor->_facing) {
+ refreshSequenceCode();
+ faceActor(newFacing);
+ }
+
+ _actor->_pathFlag50 = true;
+
+ }
+
+ FP16 deltaX24, deltaY24;
+
+ if (_actor->_flags & 0x0400) {
+
+ FP16 v20 = fixedMul((deltaTime + _actor->_pathCtrX) << 16, _actor->_pathCtrY << 16);
+ FP16 v21 = fixedDiv(v20, 100 << 16);
+ FP16 v22 = fixedMul(v21, _actor->_scale << 16);
+ FP16 v23 = fixedDiv(v22, 100 << 16);
+ _actor->_seqCodeValue1 = 100 * _actor->_pathCtrY * deltaTime / 100;
+ if (v23) {
+ FP16 prevDistance = fixedDistance(prevPt.x << 16, prevPt.y << 16, _actor->_posXShl, _actor->_posYShl);
+ FP16 distance = prevDistance + v23;
+ if (prevPt.x > currPt.x)
+ distance = -distance;
+ deltaX24 = fixedMul(fixedCos(_actor->_pathAngle), distance);
+ deltaY24 = fixedMul(fixedSin(_actor->_pathAngle), distance);
+ } else {
+ deltaX24 = _actor->_posXShl - (prevPt.x << 16);
+ deltaY24 = _actor->_posYShl - (prevPt.y << 16);
+ }
+ } else {
+ if (100 * (int)deltaTime <= _actor->_seqCodeValue2)
+ break;
+ deltaX24 = deltaX << 16;
+ deltaY24 = deltaY << 16;
+ }
+
+ if (ABS(deltaX24) < ABS(deltaX << 16) ||
+ ABS(deltaY24) < ABS(deltaY << 16)) {
+ FP16 newX = (prevPt.x << 16) + deltaX24;
+ FP16 newY = (prevPt.y << 16) + deltaY24;
+ if (newX == _actor->_posXShl && newY == _actor->_posYShl) {
+ _actor->_pathCtrX += deltaTime;
+ } else {
+ _actor->_pathCtrX = 0;
+ _actor->_posXShl = newX;
+ _actor->_posYShl = newY;
+ _actor->_position.x = fixedTrunc(_actor->_posXShl);
+ _actor->_position.y = fixedTrunc(_actor->_posYShl);
+ }
+ } else {
+ _actor->_position = currPt;
+ _actor->_posXShl = _actor->_position.x << 16;
+ _actor->_posYShl = _actor->_position.y << 16;
+ --_actor->_pathPointsCount;
+ ++_actor->_pathPointIndex;
+ ++_actor->_pathPoints;
+ _actor->_pathInitialPosFlag = true;
+ if (_actor->_pathPointsCount == 0) {
+ if (_actor->_flags & 0x0400) {
+ delete _actor->_pathNode;
+ _actor->_flags &= ~0x0400;
+ }
+ _actor->_pathNode = 0;
+ _actor->_pathPoints = 0;
+ _actor->_pathPointsCount = 0;
+ _actor->_pathPointIndex = 0;
+ if (_actor->_notifyId3C) {
+ _vm->notifyThreadId(_actor->_notifyId3C);
+ _actor->_walkCallerThreadId1 = 0;
+ }
+ again = false;
+ }
+ _actor->_pathFlag50 = false;
+ }
+
+ if (!again)
+ break;
+
+ }
+
+}
+
+void Control::refreshSequenceCode() {
+ Sequence *sequence = _vm->_dict->findSequence(_actor->_sequenceId);
+ _actor->_seqCodeIp = sequence->_sequenceCode;
+}
+
void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entryTblPtr, uint32 notifyThreadId) {
stopActor();
@@ -701,7 +905,7 @@ void Control::startSequenceActorIntern(uint32 sequenceId, int value, byte *entry
_actor->_sequenceId = sequenceId;
_actor->_notifyThreadId1 = notifyThreadId;
_actor->_notifyId3C = 0;
- _actor->_path40 = 0;
+ _actor->_walkCallerThreadId1 = 0;
Sequence *sequence = _vm->_dict->findSequence(sequenceId);
@@ -963,8 +1167,8 @@ void Controls::actorControlRoutine(Control *control, uint32 deltaTime) {
if (actor->_pauseCtr > 0)
return;
- if (false/*actor->_pathNode*/) {
- // TODO Update pathwalking
+ if (control->_actor->_pathNode) {
+ control->updateActorMovement(deltaTime);
} else {
actor->_seqCodeValue1 = 100 * deltaTime;
}
@@ -1014,10 +1218,8 @@ void Controls::destroyControl(Control *control) {
_vm->_cursor->setControl(0);
if (control->_actor) {
- /* TODO
- if (actor->_pathNode && (actor->_flags & 0x400))
- delete actor->_pathNode;
- */
+ if (control->_actor->_pathNode && (control->_actor->_flags & 0x400))
+ delete control->_actor->_pathNode;
if (!(control->_actor->_flags & 0x200))
control->_actor->destroySurface();
/* TODO