aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorjohndoe1232014-03-31 19:54:55 +0200
committerEugene Sandulenko2018-07-20 06:43:33 +0000
commitf2c48e3ae0e5775da6f3dcac841414cf8b5379ef (patch)
tree61eb9c915e846d26922d7c584b7b929102927034 /engines
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')
-rw-r--r--engines/illusions/actor.cpp266
-rw-r--r--engines/illusions/actor.h20
-rw-r--r--engines/illusions/fixedpoint.cpp21
-rw-r--r--engines/illusions/fixedpoint.h9
-rw-r--r--engines/illusions/scriptman.cpp2
-rw-r--r--engines/illusions/scriptopcodes.cpp5
6 files changed, 274 insertions, 49 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
diff --git a/engines/illusions/actor.h b/engines/illusions/actor.h
index 50d3f7c1c8..4dd8ba50f4 100644
--- a/engines/illusions/actor.h
+++ b/engines/illusions/actor.h
@@ -66,6 +66,7 @@ protected:
};
typedef Common::Functor2<Control*, uint32, void> ActorControlRoutine;
+typedef Common::Array<Common::Point> PointArray;
class Actor {
public:
@@ -134,8 +135,17 @@ public:
int _seqCodeValue2;
int _seqCodeValue3;
- int _pathCtrY;
- int _path40;
+ int _pathCtrX, _pathCtrY;
+ int _pathAngle;
+ int32 _posXShl, _posYShl;
+ uint _pathPointIndex;
+ uint _pathPointsCount;
+ Common::Point _pathInitialPos;
+ bool _pathInitialPosFlag;
+ bool _pathFlag50;
+ PointArray *_pathNode;
+ uint _pathPoints;
+ uint32 _walkCallerThreadId1;
};
@@ -176,6 +186,10 @@ public:
void setActorIndexTo2();
void startSubSequence(int linkIndex, uint32 sequenceId);
void stopSubSequence(int linkIndex);
+ void startMoveActor(uint32 sequenceId, Common::Point destPt, uint32 callerThreadId1, uint32 callerThreadId2);
+ PointArray *createPath(Common::Point destPt);
+ void updateActorMovement(uint32 deltaTime);
+ void refreshSequenceCode();
public:
IllusionsEngine *_vm;
uint _flags;
@@ -211,7 +225,7 @@ public:
void unpauseControlsByTag(uint32 tag);
bool getOverlappedObject(Control *control, Common::Point pt, Control **outOverlappedControl, int minPriority);
bool findNamedPoint(uint32 namedPointId, Common::Point &pt);
- void actorControlRoutine(Control *control, uint32 deltaTime);
+ void actorControlRoutine(Control *control, uint32 deltaTime);
public:
typedef Common::List<Control*> Items;
typedef Items::iterator ItemsIterator;
diff --git a/engines/illusions/fixedpoint.cpp b/engines/illusions/fixedpoint.cpp
index 7fc15e424e..54dbb137cd 100644
--- a/engines/illusions/fixedpoint.cpp
+++ b/engines/illusions/fixedpoint.cpp
@@ -41,20 +41,33 @@ FP16 fixedDiv(FP16 a, FP16 b) {
return ((float)a / b) * 65536.0;
}
-int fixedTrunc(FP16 value) {
+int16 fixedTrunc(FP16 value) {
// CHECKME Not sure if this correct
- int result = value >> 16;
+ int16 result = (value >> 16) & 0xFFFF;
if ((value & 0xFFFF) >= 0x8000)
++result;
return result;
}
FP16 fixedDistance(FP16 x1, FP16 y1, FP16 x2, FP16 y2) {
- float xd = ABS(fixedToFloat(x1) - fixedToFloat(x2));
- float yd = ABS(fixedToFloat(y1) - fixedToFloat(y2));
+ float xd = fixedToFloat(x1) - fixedToFloat(x2);
+ float yd = fixedToFloat(y1) - fixedToFloat(y2);
if (xd != 0.0 || yd != 0.0)
return floatToFixed(sqrt(xd * xd + yd * yd));
return 0;
}
+FP16 fixedAtan(FP16 value) {
+ //return floatToFixed(atan2(1.0, fixedToFloat(value)));
+ return floatToFixed(atan(fixedToFloat(value)));
+}
+
+FP16 fixedCos(FP16 value) {
+ return floatToFixed(cos(fixedToFloat(value)));
+}
+
+FP16 fixedSin(FP16 value) {
+ return floatToFixed(sin(fixedToFloat(value)));
+}
+
} // End of namespace Illusions
diff --git a/engines/illusions/fixedpoint.h b/engines/illusions/fixedpoint.h
index a14eb8b51b..1320daa7e7 100644
--- a/engines/illusions/fixedpoint.h
+++ b/engines/illusions/fixedpoint.h
@@ -29,16 +29,15 @@ namespace Illusions {
typedef int32 FP16;
-struct FPRect {
- FP16 x1, y1, x2, y2;
-};
-
FP16 floatToFixed(float value);
float fixedToFloat(FP16 value);
FP16 fixedMul(FP16 a, FP16 b);
FP16 fixedDiv(FP16 a, FP16 b);
-int fixedTrunc(FP16 value);
+int16 fixedTrunc(FP16 value);
FP16 fixedDistance(FP16 x1, FP16 y1, FP16 x2, FP16 y2);
+FP16 fixedAtan(FP16 value);
+FP16 fixedCos(FP16 value);
+FP16 fixedSin(FP16 value);
} // End of namespace Illusions
diff --git a/engines/illusions/scriptman.cpp b/engines/illusions/scriptman.cpp
index 20749438d1..8a59d70a1e 100644
--- a/engines/illusions/scriptman.cpp
+++ b/engines/illusions/scriptman.cpp
@@ -354,7 +354,7 @@ void ScriptMan::newScriptThread(uint32 threadId, uint32 callingThreadId, uint no
scriptThread->pause();
if (_doScriptThreadInit) {
int updateResult = 4;
- while (scriptThread->_pauseCtr <= 0 && updateResult != 1 && updateResult != 2)
+ while (scriptThread->_pauseCtr <= 0 && updateResult != kTSTerminate && updateResult != kTSYield)
updateResult = scriptThread->update();
}
}
diff --git a/engines/illusions/scriptopcodes.cpp b/engines/illusions/scriptopcodes.cpp
index 77a7d1f523..00f57956dc 100644
--- a/engines/illusions/scriptopcodes.cpp
+++ b/engines/illusions/scriptopcodes.cpp
@@ -422,10 +422,7 @@ void ScriptOpcodes::opStartMoveActor(ScriptThread *scriptThread, OpCall &opCall)
// NOTE Skipped checking for stalled sequence, not sure if needed
Control *control = _vm->_dict->getObjectControl(objectId);
Common::Point pos = _vm->getNamedPointPosition(namedPointId);
- // TODO _control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
-
- //DEBUG Resume calling thread, later done by the walking
- _vm->notifyThreadId(opCall._threadId);
+ control->startMoveActor(sequenceId, pos, opCall._callerThreadId, opCall._threadId);
}
void ScriptOpcodes::opSetActorToNamedPoint(ScriptThread *scriptThread, OpCall &opCall) {