From 1740c490d710ec01d41c0b248eb43b782f383705 Mon Sep 17 00:00:00 2001 From: Peter Kohaut Date: Sat, 1 Apr 2017 08:56:30 +0200 Subject: BLADERUNNER: improvements to the walking code path finding is still missing video player has audio preloading small fixes --- engines/bladerunner/actor.cpp | 42 +++--- engines/bladerunner/actor.h | 27 ++-- engines/bladerunner/actor_walk.cpp | 271 +++++++++++++++++++++++++----------- engines/bladerunner/actor_walk.h | 39 +++--- engines/bladerunner/bladerunner.cpp | 2 - engines/bladerunner/obstacles.cpp | 2 + engines/bladerunner/scene.h | 13 +- engines/bladerunner/set.cpp | 30 ++-- engines/bladerunner/set.h | 22 +-- engines/bladerunner/settings.cpp | 2 +- engines/bladerunner/vqa_player.cpp | 28 ++-- engines/bladerunner/waypoints.h | 2 +- 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::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 _entries; -// int _field15; + Common::HashMap _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; -- cgit v1.2.3