aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Kohaut2017-04-01 08:56:30 +0200
committerPeter Kohaut2017-04-01 08:57:57 +0200
commit1740c490d710ec01d41c0b248eb43b782f383705 (patch)
tree5ebdd10e3ad59751889ca92d0cd630e097857d0a
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
-rw-r--r--engines/bladerunner/actor.cpp42
-rw-r--r--engines/bladerunner/actor.h27
-rw-r--r--engines/bladerunner/actor_walk.cpp271
-rw-r--r--engines/bladerunner/actor_walk.h39
-rw-r--r--engines/bladerunner/bladerunner.cpp2
-rw-r--r--engines/bladerunner/obstacles.cpp2
-rw-r--r--engines/bladerunner/scene.h13
-rw-r--r--engines/bladerunner/set.cpp30
-rw-r--r--engines/bladerunner/set.h22
-rw-r--r--engines/bladerunner/settings.cpp2
-rw-r--r--engines/bladerunner/vqa_player.cpp28
-rw-r--r--engines/bladerunner/waypoints.h2
12 files changed, 292 insertions, 188 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index d4613c1be0..52cebb659d 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -247,7 +247,7 @@ void Actor::movementTrackNext(bool omitAiScript) {
int delay;
int waypointId;
Vector3 waypointPosition;
- bool stopped;
+ bool arrived;
hasNextMovement = _movementTrack->next(&waypointId, &delay, &angle, &running);
_movementTrackNextWaypointId = waypointId;
@@ -262,11 +262,11 @@ void Actor::movementTrackNext(bool omitAiScript) {
_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
if (_setId == waypointSetId && waypointSetId == _vm->_actors[0]->_setId) {
stopWalking(false);
- _walkInfo->setup(_id, running, _position, waypointPosition, false, &stopped);
+ _walkInfo->setup(_id, running, _position, waypointPosition, false, &arrived);
_movementTrackWalkingToWaypointId = waypointId;
_movementTrackDelayOnNextWaypoint = delay;
- if (stopped) {
+ if (arrived) {
movementTrackWaypointReached();
}
} else {
@@ -302,12 +302,12 @@ void Actor::movementTrackPause() {
void Actor::movementTrackUnpause() {
Vector3 waypointPosition;
- bool stopped;
+ bool arrived;
_movementTrack->unpause();
if (_movementTrackNextWaypointId >= 0 && _movementTrackPaused) {
_vm->_waypoints->getXYZ(_movementTrackNextWaypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
- _walkInfo->setup(_id, _movementTrackNextRunning, _position, waypointPosition, false, &stopped);
+ _walkInfo->setup(_id, _movementTrackNextRunning, _position, waypointPosition, false, &arrived);
_movementTrackPaused = false;
}
}
@@ -351,7 +351,7 @@ void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool
_position = position;
setFacing(facing, snapFacing);
- if (_vm->_scene->_setId == _setId) {
+ if (_vm->_scene->getSetId() == _setId) {
_walkboxId = _vm->_scene->_set->findWalkbox(_position.x, _position.y);
} else {
_walkboxId = -1;
@@ -375,8 +375,8 @@ void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired) {
bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3, bool run, const Vector3 &start, float targetWidth, float targetSize, bool a8, bool *flagIsRunning, bool async) {
if (true) { // simple walking
*flagIsRunning = false;
- bool stopped;
- _walkInfo->setup(_id, false, _position, destination, false, &stopped);
+ bool arrived;
+ _walkInfo->setup(_id, false, _position, destination, false, &arrived);
for (;;) {
_vm->gameTick();
@@ -400,7 +400,7 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3,
if (a8 && !async && _id && destinationOffset <= 24) {
if (distance(_vm->_playerActor->_position, destination) <= 24.0f) {
- _vm->_playerActor->walkToU(destination, 48.0f);
+ _vm->_playerActor->walkToNearestPoint(destination, 48.0f);
}
}
@@ -476,9 +476,9 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3,
}
bool Actor::walkTo(bool run, const Vector3 &destination, bool a3) {
- bool flagIsRunning;
+ bool arrived;
- return _walkInfo->setup(_id, run, _position, destination, a3, &flagIsRunning);
+ return _walkInfo->setup(_id, run, _position, destination, a3, &arrived);
}
bool Actor::loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *flagIsRunning) {
@@ -765,17 +765,17 @@ void Actor::setBoundingBox(const Vector3 &position, bool retired) {
}
}
-float Actor::distanceFromView(View *view) {
+float Actor::distanceFromView(View *view) const{
float xDist = this->_position.x - view->_cameraPosition.x;
float zDist = this->_position.z - view->_cameraPosition.z;
return sqrt(xDist * xDist + zDist * zDist);
}
-bool Actor::isWalking() {
+bool Actor::isWalking() const {
return _walkInfo->isWalking();
}
-bool Actor::isRunning() {
+bool Actor::isRunning() const {
return _walkInfo->isRunning();
}
@@ -794,7 +794,7 @@ void Actor::stopWalking(bool value) {
}
void Actor::faceActor(int otherActorId, bool animate) {
- if (_setId != _vm->_scene->_setId) {
+ if (_setId != _vm->_scene->getSetId()) {
return;
}
@@ -1085,12 +1085,12 @@ void Actor::copyClues(int actorId) {
}
}
-int Actor::soundVolume() {
+int Actor::soundVolume() const {
float dist = distanceFromView(_vm->_view);
return 255.0f * MAX(MIN(dist / 1200.0f, 1.0f), 0.0f);
}
-int Actor::soundBalance() {
+int Actor::soundBalance() const {
Vector3 screenPosition = _vm->_view->calculateScreenPosition(_position);
return 127.0f * (MAX(MIN(screenPosition.x / 640.0f, 1.0f), 0.0f) * 2.0f - 1.0f);
}
@@ -1105,8 +1105,8 @@ bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPositi
int facing2 = facing;
int facing3 = 0;
while (true) {
- float rotatedX = size * sin_1024(facing) + targetPosition.x;
- float rotatedZ = size * cos_1024(facing) + targetPosition.z;
+ float rotatedX = targetPosition.x + size * sin_1024(facing);
+ float rotatedZ = targetPosition.z - size * cos_1024(facing);
if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) {
if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) {
@@ -1161,10 +1161,10 @@ bool Actor::walkFindU2(Vector3 *newDestination, float targetWidth, int destinati
}
}
-bool Actor::walkToU(const Vector3 &destination, float distance) {
+bool Actor::walkToNearestPoint(const Vector3 &destination, float distance) {
Vector3 out;
bool flagIsRunning;
- if (_walkInfo->findU1(_id, destination, distance, &out)) {
+ if (_walkInfo->findNearestEmptyPosition(_id, destination, distance, out)) {
loopWalk(out, 0, false, false, _position, 0.0f, 24.0f, false, &flagIsRunning, false);
return true;
}
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index ea77e881e8..cf93a7f2e0 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -153,18 +153,19 @@ public:
int getSetId();
void setSetId(int setId);
- BoundingBox *getBoundingBox() { return _bbox; }
+ BoundingBox *getBoundingBox() const { return _bbox; }
Common::Rect *getScreenRectangle() { return &_screenRectangle; }
- int getWalkbox() { return _walkboxId; }
- bool isRetired() { return _isRetired; }
- bool isTargetable() { return _isTargetable; }
+ int getWalkbox() const { return _walkboxId; }
+ bool isRetired()const { return _isRetired; }
+ bool isTargetable() const { return _isTargetable; }
void setTargetable(bool targetable);
- bool isImmuneToObstacles() { return _isImmuneToObstacles; }
- bool inCombat() { return _inCombat; }
- bool isMoving() { return _isMoving; }
+ bool isImmuneToObstacles() const { return _isImmuneToObstacles; }
+ bool inCombat() const { return _inCombat; }
+ bool isMoving() const { return _isMoving; }
void setMoving(bool value) { _isMoving = value; }
- bool isWalking();
- bool isRunning();
+ bool inWalkLoop() const { return _inWalkLoop; }
+ bool isWalking() const;
+ bool isRunning() const;
void stopWalking(bool value);
void faceActor(int otherActorId, bool animate);
@@ -212,19 +213,19 @@ public:
bool hasClue(int clueId);
void copyClues(int actorId);
- int soundVolume();
- int soundBalance();
+ int soundVolume() const;
+ int soundBalance() const;
private:
void setFacing(int facing, bool halfOrSet = true);
void setBoundingBox(const Vector3 &position, bool retired);
- float distanceFromView(View* view);
+ float distanceFromView(View* view) const;
bool loopWalk(const Vector3 &destination, int destinationOffset, bool a3, bool run, const Vector3 &start, float a6, float a7, bool a8, bool *isRunning, bool async);
bool walkTo(bool run, const Vector3 &destination, bool a3);
bool walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float a3, Vector3 *newDestination);
bool walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition);
- bool walkToU(const Vector3 &destination, float distance);
+ bool walkToNearestPoint(const Vector3 &destination, float distance);
//bool walkFindU3(int actorId, Vector3 from, int distance, Vector3 *out);
};
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
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index e0558a69be..c6f2ed7478 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -24,17 +24,12 @@
#define BLADERUNNER_ACTOR_WALK_H
#include "bladerunner/vector.h"
-#include "common/array.h"
+#include "common/hashmap.h"
namespace BladeRunner {
class BladeRunnerEngine;
-struct ActorWalkEntry {
- int _actorId;
- int _present;
-};
-
class ActorWalk {
BladeRunnerEngine *_vm;
@@ -42,36 +37,38 @@ private:
int _walking;
int _running;
Vector3 _destination;
- Vector3 _unknown;
+ Vector3 _originalDestination;
Vector3 _current;
Vector3 _next;
int _facing;
- Common::Array<ActorWalk> _entries;
-// int _field15;
+ Common::HashMap<int, bool> _nearActors;
int _status;
public:
ActorWalk(BladeRunnerEngine *vm);
~ActorWalk();
-
- bool setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped);
- void getCurrentPosition(int actorId, Vector3 *pos, int *facing);
+ bool setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *arrived);
+ void getCurrentPosition(int actorId, Vector3 *pos, int *facing) const;
bool tick(int actorId, float stepDistance, bool flag);
- bool isWalking() { return _walking; }
- bool isRunning() { return _running; }
- void setRunning();
+ bool isWalking() const { return _walking; }
+ bool isRunning() const { return _running; }
- void stop(int actorId, bool unknown, int combatAnimationMode, int animationMode);
- // void setWalkingMode(int actorId, int active, int unk2 = 4, int unk3 = 0);
+ bool isXYZEmpty(float x, float y, float z, int actorId) const;
+ bool findNearestEmptyPosition(int actorId, const Vector3 &from, int distance, Vector3 &out) const;
+
+ void stop(int actorId, bool immediately, int combatAnimationMode, int animationMode);
+
+private:
+ int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const;
- int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next);
+ bool findNearestEmptyPositionToOriginalDestination(int actorId, Vector3 &out) const;
- void resetList();
+ bool addNearActors(int skipActorId);
- bool isXYZEmpty(float x, float y, float z, int actorId);
- int findU1(int actorId, const Vector3 &to, int distance, Vector3 *out);
+ void obstaclesAddNearActors(int actorId) const;
+ void obstaclesRestore() const;
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 57159c22bb..e11cc0b53f 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -803,8 +803,6 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
int exitIndex = _scene->_exits->getRegionAtXY(x, y);
- debug("%d %d", sceneObjectId, exitIndex);
-
if ((sceneObjectId < 0 || sceneObjectId > 73) && exitIndex >= 0) {
handleMouseClickExit(x, y, exitIndex);
return;
diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp
index 9e701a9341..9fbdc0ad5e 100644
--- a/engines/bladerunner/obstacles.cpp
+++ b/engines/bladerunner/obstacles.cpp
@@ -66,5 +66,7 @@ bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) {
void Obstacles::backup() {
}
+void Obstacles::restore() {}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index fac67ff5f4..90cb936bf8 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -37,8 +37,7 @@ class BladeRunnerEngine;
class Scene {
BladeRunnerEngine *_vm;
-public:
- Set *_set;
+private:
int _setId;
int _sceneId;
VQAPlayer *_vqaPlayer;
@@ -57,6 +56,8 @@ public:
int _actorStartFacing;
bool _playerWalkedIn;
+public:
+ Set *_set;
Regions* _regions;
Regions* _exits;
@@ -66,15 +67,15 @@ public:
public:
Scene(BladeRunnerEngine *vm)
: _vm(vm),
- _set(new Set(vm)),
_setId(-1),
_sceneId(-1),
_vqaPlayer(nullptr),
_defaultLoop(0),
+ _introFinished(false),
_nextSetId(-1),
_nextSceneId(-1),
_playerWalkedIn(false),
- _introFinished(false),
+ _set(new Set(vm)),
_regions(new Regions()),
_exits(new Regions())
{}
@@ -94,8 +95,8 @@ public:
void loopSetDefault(int a);
void loopStartSpecial(int a, int b, int c);
- int getSetId() { return _setId; }
- int getSceneId() { return _sceneId; }
+ int getSetId() const { return _setId; }
+ int getSceneId() const { return _sceneId; }
bool didPlayerWalkIn() { bool r = _playerWalkedIn; _playerWalkedIn = false; return r; }
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index f8a480c181..5501f27a2c 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -126,7 +126,7 @@ bool Set::open(const Common::String &name) {
return true;
}
-void Set::addObjectsToScene(SceneObjects *sceneObjects) {
+void Set::addObjectsToScene(SceneObjects *sceneObjects) const {
for (int i = 0; i < _objectCount; i++) {
sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isTarget);
}
@@ -172,17 +172,17 @@ static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) {
return found & 1;
}
-float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) {
+float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) const {
float altitude = _walkboxes[0]._altitude;
*inWalkbox = false;
for (int i = 0; i < _walkboxCount; ++i) {
- const Walkbox &w = _walkboxes[i];
+ const Walkbox &walkbox = _walkboxes[i];
- if (isXZInWalkbox(x, z, w)) {
- *inWalkbox = true;
- if (w._altitude > altitude) {
- altitude = w._altitude;
+ if (isXZInWalkbox(x, z, walkbox)) {
+ if (!*inWalkbox || altitude < walkbox._altitude) {
+ altitude = walkbox._altitude;
+ *inWalkbox = true;
}
}
}
@@ -190,7 +190,7 @@ float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) {
return altitude;
}
-int Set::findWalkbox(float x, float z) {
+int Set::findWalkbox(float x, float z) const {
int result = -1;
for (int i = 0; i < _walkboxCount; ++i) {
@@ -206,7 +206,7 @@ int Set::findWalkbox(float x, float z) {
return result;
}
-int Set::findObject(const char *objectName) {
+int Set::findObject(const char *objectName) const {
int i;
for (i = 0; i < (int)_objectCount; i++) {
if (scumm_stricmp(objectName, _objects[i]._name) == 0) {
@@ -219,7 +219,7 @@ int Set::findObject(const char *objectName) {
return -1;
}
-bool Set::objectSetHotMouse(int objectId) {
+bool Set::objectSetHotMouse(int objectId) const {
if (!_objects || objectId < 0 || objectId >= (int)_objectCount) {
return false;
}
@@ -228,7 +228,7 @@ bool Set::objectSetHotMouse(int objectId) {
return true;
}
-bool Set::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) {
+bool Set::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) const {
assert(boundingBox);
if (!_objects || objectId < 0 || objectId >= (int)_objectCount) {
@@ -243,19 +243,19 @@ bool Set::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) {
return true;
}
-void Set::objectSetIsClickable(int objectId, bool isClickable) {
+void Set::objectSetIsClickable(int objectId, bool isClickable) const {
_objects[objectId]._isClickable = isClickable;
}
-void Set::objectSetIsObstacle(int objectId, bool isObstacle) {
+void Set::objectSetIsObstacle(int objectId, bool isObstacle) const {
_objects[objectId]._isObstacle = isObstacle;
}
-void Set::objectSetIsTarget(int objectId, bool isTarget) {
+void Set::objectSetIsTarget(int objectId, bool isTarget) const {
_objects[objectId]._isTarget = isTarget;
}
-const char *Set::objectGetName(int objectId) {
+const char *Set::objectGetName(int objectId) const {
return _objects[objectId]._name;
}
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index 4b4a4d92df..d3540c5c0f 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -77,20 +77,20 @@ public:
bool open(const Common::String &name);
- void addObjectsToScene(SceneObjects *sceneObjects);
- uint32 getObjectCount() { return _objectCount; }
+ void addObjectsToScene(SceneObjects *sceneObjects) const;
+ uint32 getObjectCount() const { return _objectCount; }
- float getAltitudeAtXZ(float x, float z, bool *inWalkbox);
+ float getAltitudeAtXZ(float x, float z, bool *inWalkbox) const;
- int findWalkbox(float x, float z);
- int findObject(const char *objectName);
+ int findWalkbox(float x, float z) const;
+ int findObject(const char *objectName) const;
- bool objectSetHotMouse(int objectId);
- bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
- void objectSetIsClickable(int objectId, bool isClickable);
- void objectSetIsObstacle(int objectId, bool isObstacle);
- void objectSetIsTarget(int objectId, bool isTarget);
- const char *objectGetName(int objectId);
+ bool objectSetHotMouse(int objectId) const;
+ bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox) const;
+ void objectSetIsClickable(int objectId, bool isClickable) const;
+ void objectSetIsObstacle(int objectId, bool isObstacle) const;
+ void objectSetIsTarget(int objectId, bool isTarget) const;
+ const char *objectGetName(int objectId) const;
void setWalkboxStepSound(int walkboxId, int soundId);
void setFoodstepSoundOverride(int soundId);
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index 679db5193e..81def7ea93 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -60,7 +60,7 @@ bool Settings::openNewScene() {
// music::stop(Music, 2);
}
- int currentSet = _vm->_scene->_setId;
+ int currentSet = _vm->_scene->getSetId();
int newSet = _newSet;
int newScene = _newScene;
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index da4749b532..845e2ee1a7 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -108,31 +108,29 @@ int VQAPlayer::update() {
}
-// TODO: preload audio
-// int audioPreloadFrames = 1;
+// TODO: preload audio in better way
+ int audioPreloadFrames = 3;
if (now >= _frameNextTime) {
int frame = _frameNext;
-// _decoder.readFrame(_frameNext, 0x2);
- _decoder.readFrame(_frameNext, 0);
+ _decoder.readFrame(_frameNext, 0x2);
_surface = _decoder.decodeVideoFrame();
if (_hasAudio) {
- queueAudioFrame(_decoder.decodeAudioFrame());
if (!_audioStarted) {
-// for (int i = 0; i < audioPreloadFrames; i++) {
-// if (_frameNext + i < _frameEnd) {
-// _decoder.readFrame(_frameNext + i, 0x1);
-// queueAudioFrame(_decoder.decodeAudioFrame());
-// }
-// }
+ for (int i = 0; i < audioPreloadFrames; i++) {
+ if (_frameNext + i < _frameEnd) {
+ _decoder.readFrame(_frameNext + i, 0x1);
+ queueAudioFrame(_decoder.decodeAudioFrame());
+ }
+ }
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _audioStream);
_audioStarted = true;
}
-// if (_frameNext + audioPreloadFrames < _frameEnd) {
-// _decoder.readFrame(_frameNext + audioPreloadFrames, 0x1);
-// queueAudioFrame(_decoder.decodeAudioFrame());
-// }
+ if (_frameNext + audioPreloadFrames < _frameEnd) {
+ _decoder.readFrame(_frameNext + audioPreloadFrames, 0x1);
+ queueAudioFrame(_decoder.decodeAudioFrame());
+ }
}
if (_frameNextTime == 0) {
_frameNextTime = now + 60000 / 15;
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index c75cf00098..8319c77f92 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -39,7 +39,7 @@ struct Waypoint {
class Waypoints {
BladeRunnerEngine *_vm;
-private:
+public:
int _count;
Waypoint *_waypoints;