aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/actor_walk.cpp
diff options
context:
space:
mode:
authorPeter Kohaut2017-04-01 08:56:30 +0200
committerPeter Kohaut2017-04-01 08:57:57 +0200
commit1740c490d710ec01d41c0b248eb43b782f383705 (patch)
tree5ebdd10e3ad59751889ca92d0cd630e097857d0a /engines/bladerunner/actor_walk.cpp
parent25fcb52d7017b49d4f17542aa99be9504fd04db2 (diff)
downloadscummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.tar.gz
scummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.tar.bz2
scummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.zip
BLADERUNNER: improvements to the walking code
path finding is still missing video player has audio preloading small fixes
Diffstat (limited to 'engines/bladerunner/actor_walk.cpp')
-rw-r--r--engines/bladerunner/actor_walk.cpp271
1 files changed, 189 insertions, 82 deletions
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index 54f6c2dc68..ddf8b4c61b 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/actor.h"
+#include "bladerunner/gameinfo.h"
#include "bladerunner/obstacles.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
@@ -35,40 +36,41 @@ namespace BladeRunner {
ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
_vm = vm;
- _walking = 0;
- _running = 0;
- _facing = -1;
- _status = 0;
+ _walking = 0;
+ _running = 0;
+ _facing = -1;
+ _status = 0;
- _entries.clear();
+ _nearActors.clear();
}
-ActorWalk::~ActorWalk() {
-}
+ActorWalk::~ActorWalk() {}
-bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped) {
+bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *arrived) {
Vector3 next;
- *stopped = false;
- int r = nextOnPath(actorId, from, to, &next);
+ *arrived = false;
+
+ int r = nextOnPath(actorId, from, to, next);
if (r == 0) {
if (actorId != 0) {
_current = from;
_destination = to;
- stop(actorId, false, 4, 0);
+ stop(actorId, false, kAnimationModeCombatIdle, kAnimationModeIdle);
} else {
- stop(actorId, true, 4, 0);
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
}
return false;
}
+
if (r == -1) {
- stop(actorId, true, 4, 0);
- *stopped = true;
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
+ *arrived = true;
return false;
}
- resetList();
+ _nearActors.clear();
_vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true);
_vm->_actors[actorId]->setMoving(true);
@@ -86,65 +88,125 @@ bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3
_vm->_actors[actorId]->changeAnimationMode(animationMode);
_destination = to;
+ _originalDestination = to;
_current = from;
_next = next;
- if (next.x != _current.x || next.z != _current.z) {
- _facing = angle_1024(_current, next);
- _walking = true;
- _running = run;
- _status = 2;
-
- return true;
+ if (next.x == _current.x && next.z == _current.z) {
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
+ *arrived = true;
+ return false;
}
- stop(actorId, true, 4, 0);
- return false;
+ _facing = angle_1024(_current, next);
+ _walking = true;
+ _running = run;
+ _status = 2;
+
+ return true;
}
-bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
+bool ActorWalk::tick(int actorId, float stepDistance, bool inWalkLoop) {
+ bool walkboxFound;
+
if (_status == 5) {
- if (flag) {
- stop(actorId, true, 4, 0);
+ if (inWalkLoop) {
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
return true;
}
- if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) {
+ if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) { // why random?
return false;
}
_status = 3;
}
- // TODO: Handle collisions?
+
+ bool nearActorExists = addNearActors(actorId);
+ if (_nearActors.size() > 0) {
+ nearActorExists = true;
+ if (_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, _destination.x, _destination.z, true, true)) {
+ if (actorId > 0) {
+ if (_vm->_actors[actorId]->inWalkLoop()) {
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
+ _nearActors.clear();
+ return true;
+ } else {
+ Vector3 newDestination;
+ findNearestEmptyPositionToOriginalDestination(actorId, newDestination);
+ _destination = newDestination;
+ return false;
+ }
+ } else {
+ if (_vm->_playerActor->inWalkLoop()) {
+ _destination = _current;
+ }
+ stop(0, true, kAnimationModeCombatIdle, kAnimationModeIdle);
+ _nearActors.clear();
+ return true;
+ }
+ }
+ }
+ _status = 3;
if (stepDistance > distance(_current, _destination)) {
- stop(actorId, true, 4, 0);
+ stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle);
_current = _destination;
- // TODO: Update y from walkbox
+ _current.y = _vm->_scene->_set->getAltitudeAtXZ(_current.x, _current.z, &walkboxFound);
return true;
}
+ float distanceToNext = distance(_current, _next);
+ if (1.0f < distanceToNext) {
+ _facing = angle_1024(_current, _next);
+ }
+
+ bool nextIsCloseEnough = stepDistance > distanceToNext;
+
+ if (nextIsCloseEnough || nearActorExists || _status == 3) {
+ if (nextIsCloseEnough) {
+ _current = _next;
+ }
+ _status = 1;
+ Vector3 next;
+ obstaclesAddNearActors(actorId);
+ int r = nextOnPath(actorId, _current, _destination, next);
+ obstaclesRestore();
+ if (r == 0) {
+ stop(actorId, actorId == 0, kAnimationModeCombatIdle, kAnimationModeIdle);
+ return false;
+ }
+ if (r != -1) {
+ _next = next;
+ _facing = angle_1024(_current, _next);
+ _status = 2;
+ int animationMode;
+ if (_vm->_actors[actorId]->inCombat()) {
+ animationMode = _running ? kAnimationModeCombatRun : kAnimationModeCombatWalk;
+ } else {
+ animationMode = _running ? kAnimationModeRun : kAnimationModeWalk;
+ }
+ _vm->_actors[actorId]->changeAnimationMode(animationMode);
+ if (nextIsCloseEnough) {
+ return false;
+ }
+ }
+ }
+
float angle_rad = _facing / 512.0 * M_PI;
- _current = Vector3(
- _current.x + stepDistance * sinf(angle_rad),
- _current.y, // TODO: Update from walkbox
- _current.z - stepDistance * cosf(angle_rad)
- );
+ _current.x += stepDistance * sinf(angle_rad);
+ _current.z -= stepDistance * cosf(angle_rad);
+ _current.y = _vm->_scene->_set->getAltitudeAtXZ(_current.x, _current.z, &walkboxFound);
return false;
}
-void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) {
+void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) const {
*pos = _current;
*facing = _facing;
}
-void ActorWalk::setRunning() {
- _running = true;
- // TODO: Set animation mode
-}
-
-void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int animationMode) {
+void ActorWalk::stop(int actorId, bool immediately, int combatAnimationMode, int animationMode) {
_vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, false);
_vm->_actors[actorId]->setMoving(false);
@@ -154,7 +216,7 @@ void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int ani
_vm->_actors[actorId]->changeAnimationMode(animationMode, false);
}
- if (unknown) {
+ if (immediately) {
_walking = false;
_running = false;
_status = 0;
@@ -165,7 +227,7 @@ void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int ani
}
}
-bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) {
+bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const {
if (_vm->_scene->_set->findWalkbox(x, z) == -1) {
return true;
}
@@ -175,77 +237,125 @@ bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) {
return _vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, false, false);
}
-int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
+bool ActorWalk::findNearestEmptyPosition(int actorId, const Vector3 &destination, int dist, Vector3 &out) const {
bool inWalkbox;
- int facingFound = -1;
- float distFound = -1.0f;
+ int facingToMinDistance = -1;
+ float minDistance = -1.0f;
float x = 0.0f;
float z = 0.0f;
- out->x = 0.0f;
- out->y = 0.0f;
- out->z = 0.0f;
+ out.x = 0.0f;
+ out.y = 0.0f;
+ out.z = 0.0f;
for (int facing = 0; facing < 1024; facing += 128) {
- x = to.x + sin_1024(facing) * dist;
- z = to.z + cos_1024(facing) * dist;
- float dist2 = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ());
+ x = destination.x + sin_1024(facing) * dist;
+ z = destination.z - cos_1024(facing) * dist;
+ float distanceBetweenActorAndDestination = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ());
- if (distFound == -1.0f || distFound > dist2) {
- distFound = dist2;
- facingFound = facing;
+ if (minDistance == -1.0f || minDistance > distanceBetweenActorAndDestination) {
+ minDistance = distanceBetweenActorAndDestination;
+ facingToMinDistance = facing;
}
}
- int v23 = facingFound;
- int v24 = facingFound;
- int v25 = -1024;
- while (v25 < 0) {
- x = to.x + sin_1024(v24) * dist;
- z = to.z + cos_1024(v24) * dist;
+ int facingLeft = facingToMinDistance;
+ int facingRight = facingToMinDistance;
+ int facing = -1024;
+ while (facing < 0) {
+ x = destination.x + sin_1024(facingRight) * dist;
+ z = destination.z - cos_1024(facingRight) * dist;
if (!_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
break;
}
- x = to.x + sin_1024(v23) * dist;
- z = to.z + cos_1024(v23) * dist;
+ x = destination.x + sin_1024(facingLeft) * dist;
+ z = destination.z - cos_1024(facingLeft) * dist;
if (!_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
break;
}
- v24 -= 64;
- if (v24 < 0) {
- v24 += 1024;
+ facingRight -= 64;
+ if (facingRight < 0) {
+ facingRight += 1024;
}
- v23 += 64;
- if (v23 >= 1024) {
- v23 -= 1024;
+ facingLeft += 64;
+ if (facingLeft >= 1024) {
+ facingLeft -= 1024;
}
- v25 += 64;
+ facing += 64;
}
float y = _vm->_scene->_set->getAltitudeAtXZ(x, z, &inWalkbox);
if (inWalkbox) {
- out->x = x;
- out->y = y;
- out->z = z;
+ out.x = x;
+ out.y = y;
+ out.z = z;
return true;
}
return false;
}
-int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next) {
- *next = from;
+bool ActorWalk::findNearestEmptyPositionToOriginalDestination(int actorId, Vector3 &out) const {
+ return findNearestEmptyPosition(actorId, _originalDestination, 30, out);
+}
+
+bool ActorWalk::addNearActors(int skipActorId) {
+ bool added = false;
+ int setId = _vm->_scene->getSetId();
+ for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+ // TODO: remove null check after implemetantion of all actors
+ if (_vm->_actors[i] != nullptr
+ && _vm->_actors[skipActorId] != nullptr
+ && _vm->_actors[i]->getSetId() == setId
+ && i != skipActorId) {
+
+ if (_nearActors.contains(i)) {
+ _nearActors.setVal(i, false);
+ } else if (_vm->_actors[skipActorId]->distanceFromActor(i) <= 48.0f) {
+ _nearActors.setVal(i, true);
+ added = true;
+ }
+ }
+ }
+ return added;
+}
+
+void ActorWalk::obstaclesAddNearActors(int actorId) const {
+ Vector3 position = _vm->_actors[actorId]->getPosition();
+ for (Common::HashMap<int, bool>::const_iterator it = _nearActors.begin(); it != _nearActors.end(); ++it) {
+ Actor *otherActor = _vm->_actors[it->_key];
+ // TODO: remove null check after implemetantion of all actors
+ if (otherActor == nullptr || otherActor->isRetired()) {
+ continue;
+ }
+ Vector3 otherPosition = otherActor->getPosition();
+ float x0 = otherPosition.x - 12.0f;
+ float z0 = otherPosition.z - 12.0f;
+ float x1 = otherPosition.x + 12.0f;
+ float z1 = otherPosition.z + 12.0f;
+ if (position.x < (x0 - 12.0f) || position.z < (z0 - 12.0f) || position.x > (x1 + 12.0f) || position.z > (z1 + 12.0f)) {
+ _vm->_obstacles->add(x0, z0, x1, z1);
+ }
+ }
+}
+
+void ActorWalk::obstaclesRestore() const {
+ _vm->_obstacles->restore();
+}
+
+int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const {
+ next = from;
if (distance(from, to) < 6.0) {
return -1;
}
if (_vm->_actors[actorId]->isImmuneToObstacles()) {
- *next = to;
+ next = to;
return 1;
}
if (_vm->_scene->_set->findWalkbox(to.x, to.z) == -1) {
@@ -256,13 +366,10 @@ int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, V
}
Vector3 next1;
if (_vm->_obstacles->find(from, to, &next1)) {
- *next = next1;
+ next = next1;
return 1;
}
return 0;
}
-void ActorWalk::resetList() {
- _entries.clear();
-}
} // End of namespace BladeRunner