From 6547c35e15252fd24f260ebd6b8f01d9edd01aa2 Mon Sep 17 00:00:00 2001 From: Peter Kohaut Date: Tue, 4 Oct 2016 02:21:08 +0200 Subject: BLADERUNNER: trying to figure out walking, added structures for obstacles used for pathfinding, fixed bug in searching for walkboxes --- engines/bladerunner/actor.cpp | 337 ++++++++++++++++++++++++++-------- engines/bladerunner/actor.h | 24 ++- engines/bladerunner/actor_walk.cpp | 181 ++++++++++++------ engines/bladerunner/actor_walk.h | 16 +- engines/bladerunner/adq.cpp | 2 +- engines/bladerunner/adq.h | 23 ++- engines/bladerunner/bladerunner.cpp | 6 +- engines/bladerunner/bladerunner.h | 16 +- engines/bladerunner/item.cpp | 11 +- engines/bladerunner/item.h | 8 +- engines/bladerunner/items.cpp | 7 + engines/bladerunner/items.h | 3 + engines/bladerunner/module.mk | 1 + engines/bladerunner/obstacles.cpp | 46 +++++ engines/bladerunner/obstacles.h | 64 +++++++ engines/bladerunner/scene.cpp | 2 +- engines/bladerunner/scene_objects.cpp | 18 +- engines/bladerunner/scene_objects.h | 2 +- engines/bladerunner/script/nr03.cpp | 4 +- engines/bladerunner/script/nr05.cpp | 2 +- engines/bladerunner/script/rc01.cpp | 8 +- engines/bladerunner/script/script.cpp | 67 +++++-- engines/bladerunner/script/script.h | 12 +- engines/bladerunner/set.cpp | 9 +- engines/bladerunner/vector.h | 48 +++++ 25 files changed, 707 insertions(+), 210 deletions(-) create mode 100644 engines/bladerunner/obstacles.cpp create mode 100644 engines/bladerunner/obstacles.h (limited to 'engines') diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index 1ea2b17de8..d1493b9300 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -31,6 +31,7 @@ #include "bladerunner/boundingbox.h" #include "bladerunner/gameinfo.h" #include "bladerunner/items.h" +#include "bladerunner/mouse.h" #include "bladerunner/movement_track.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" @@ -39,8 +40,6 @@ #include "bladerunner/slice_renderer.h" #include "bladerunner/waypoints.h" -#include "common/system.h" - namespace BladeRunner { Actor::Actor(BladeRunnerEngine *vm, int actorId) { @@ -176,7 +175,21 @@ void Actor::processMovement() { }*/ } -void Actor::setAtXYZ(Vector3 position, int facing, bool snapFacing, bool moving, bool retired) { +bool Actor::loopWalkToActor(int otherActorId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) { + return loopWalk(_vm->_actors[otherActorId]->_position, destinationOffset, a3, run, _position, 24.0f, 24.0f, a5, isRunning, false); +} + +bool Actor::loopWalkToItem(int itemId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) { + float x, y, z; + int width, height; + _vm->_items->getXYZ(itemId, &x, &y, &z); + _vm->_items->getWidthHeight(itemId, &width, &height); + Vector3 itemPosition(x, y, z); + + return loopWalk(itemPosition, destinationOffset, a3, run, _position, width, 24.0f, a5, isRunning, false); +} + +void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool moving, bool retired) { _position = position; setFacing(facing, snapFacing); @@ -201,76 +214,170 @@ void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired) { setAtXYZ(waypointPosition, angle, true, moving, retired); } -void Actor::loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7) { - this->loopWalkToXYZ(Vector3(x, y, z)); -} +bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3, bool run, const Vector3 &start, float targetWidth, float targetSize, bool a8, bool *isRunning, bool async) { + if (true) { // simple walking + *isRunning = false; + bool stopped; + _walkInfo->setup(_id, false, _position, destination, false, &stopped); + + for (;;) { + _vm->gameTick(); + if (!_walkInfo->isWalking() && !_walkInfo->isRunning()) + break; + if (!_vm->_gameIsRunning) + break; + } + return false; + } else { + //TODO: + // original code, not yet working + *isRunning = false; + + if (destinationOffset > 0) { + float dist = distance(_position, destination); + if (dist - targetSize <= destinationOffset) { + return false; + } + } + + if (a8 && !async && _id && destinationOffset <= 24) { + if (distance(_vm->_playerActor->_position, destination) <= 24.0f) { + _vm->_playerActor->walkToU(destination, 48.0f); + } + } -void Actor::loopWalkToXYZ(Vector3 destination) { - int unk1; - _walkInfo->setup(_id, false, _position, destination, 0, &unk1); + if (_id) { + a3 = false; + } - for (;;) { - _vm->gameTick(); - if (!_walkInfo->isWalking() && !_walkInfo->isRunning()) - break; - if (!_vm->_gameIsRunning) - break; + Vector3 destinationX(destination); + + if (destinationOffset > 0) { + walkFindU2(&destinationX, targetWidth, destinationOffset, targetSize, _position, destination); + } + + bool walking = walkTo(run, destinationX, a8); + + if (async) { + return false; + } + + if (!walking && destinationOffset > 0) { + walking = walkTo(run, destination, a8); + } + + if (!walking) { + return false; + } + + if (async) { + return false; + } + if (_id) { + _vm->_mouse->disable(); + } + if (a3) { + // TODO: + // dword_482990 = 1; + // dword_482994 = 0; + } else { + _vm->playerLosesControl(); + } + + if (a8) { + _inWalkLoop = true; + } + + bool v46 = false; + while (_walkInfo->isWalking() && _vm->_gameIsRunning) { + if (_walkInfo->isRunning()) { + *isRunning = true; + } + _vm->gameTick(); + if (_id == 0 && a3 /*&& dword_482994*/) { + stopWalking(false); + v46 = true; + } + } + if (a8) { + _inWalkLoop = false; + } + if (a3) { + // dword_482990 = 1; + } else { + _vm->playerGainsControl(); + } + if (!v46 && destinationOffset == 0 /* && !PlayerActorIdle*/) { + setAtXYZ(destination, _facing, true, false, false); + } + if (_id) { + _vm->_mouse->enable(); + } + return v46; } } -float distance(float, float, float, float); -float distance(Vector3 &v1, Vector3 &v2); +bool Actor::walkTo(bool run, const Vector3 &destination, bool a3) { + bool isRunning; + + return _walkInfo->setup(_id, run, _position, destination, a3, &isRunning); +} + +bool Actor::loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning) { + return loopWalk(destination, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false); +} -void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset) { +bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning) { int sceneObject = _vm->_scene->_set->findObject(objectName); - if (sceneObject < 0) - return; + if (sceneObject < 0) { + return true; + } BoundingBox bbox; - if (!_vm->_scene->_set->objectGetBoundingBox(sceneObject, &bbox)) - return; + if (!_vm->_scene->_set->objectGetBoundingBox(sceneObject, &bbox)) { + return true; + } float x0, y0, z0, x1, y1, z1; bbox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); - // debug("[%f %f] -> [%f %f %f, %f %f %f]", _position.x, _position.z, x0, y0, z0, x1, y1, z1); - - float closest_distance = distance(_position.x, _position.z, x0, z0); - float closest_x = x0; - float closest_z = z0; + float closestDistance = distance(_position.x, _position.z, x0, z0); + float closestX = x0; + float closestZ = z0; float d = distance(_position.x, _position.z, x1, z0); - // debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0); - if (d < closest_distance) { - closest_x = x1; - closest_z = z0; - closest_distance = d; + if (d < closestDistance) { + closestX = x1; + closestZ = z0; + closestDistance = d; } d = distance(_position.x, _position.z, x1, z1); - // debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0); - if (d < closest_distance) { - closest_x = x1; - closest_z = z1; - closest_distance = d; + if (d < closestDistance) { + closestX = x1; + closestZ = z1; + closestDistance = d; } d = distance(_position.x, _position.z, x0, z1); - // debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0); - if (d < closest_distance) { - closest_x = x0; - closest_z = z1; - closest_distance = d; + if (d < closestDistance) { + closestX = x0; + closestZ = z1; + closestDistance = d; } + bool inWalkbox; + float y = _vm->_scene->_set->getAltitudeAtXZ(closestX, closestZ, &inWalkbox); + Vector3 destination(closestX, y, closestZ); - // debug("%f = %f %f %f %f", closest_distance, _position.x, _position.z, closest_x, closest_z); - - Vector3 destination(closest_x, _position.y, closest_z); + return loopWalk(destination, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false); +} - // Vector3 properDestination(-124.2592, -0.3046913, 204.0923); - // debug("delta: %f\n", distance(destination, properDestination)); +bool Actor::loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) { + float x, y, z; + _vm->_waypoints->getXYZ(waypointId, &x, &y, &z); + Vector3 waypointPosition(x, y, z); - loopWalkToXYZ(destination); + return loopWalk(waypointPosition, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false); } bool Actor::tick(bool forceDraw) { @@ -299,7 +406,7 @@ bool Actor::tick(bool forceDraw) { _animationFrame = newFrame; Vector3 positionChange = _vm->_sliceAnimations->getPositionChange(_animationId); - float facingChange = _vm->_sliceAnimations->getFacingChange(_animationId); + float angleChange = _vm->_sliceAnimations->getFacingChange(_animationId); if (_id == 47) { positionChange.x = 0.0f; @@ -331,10 +438,10 @@ bool Actor::tick(bool forceDraw) { } } } else { - if (facingChange != 0.0f) { - int v27 = (512.0f / M_PI) * facingChange; - if (v27 != 0) { - this->_facing = this->_facing - v27; + if (angleChange != 0.0f) { + int facingChange = angleChange * (512.0f / M_PI); + if (facingChange != 0) { + this->_facing = this->_facing - facingChange; if (this->_facing < 0) { this->_facing += 1024; } @@ -356,9 +463,9 @@ bool Actor::tick(bool forceDraw) { positionChange.z = positionChange.z * this->_actorSpeed.z; } - float facing = (_facing / 512.0f) * M_PI; - float sinx = sin(facing); - float cosx = cos(facing); + float angle = _facing * (M_PI / 512.0f); + float sinx = sin(angle); + float cosx = cos(angle); float originalX = this->_position.x; float originalY = this->_position.y; @@ -397,13 +504,13 @@ bool Actor::tick(bool forceDraw) { } void Actor::draw() { - Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0); - float draw_facing = M_PI - _facing * M_PI / 512.0; - float draw_scale = _scale; + Vector3 drawPosition(_position.x, -_position.z, _position.y + 2.0); + float drawAngle = M_PI - _facing * (M_PI / 512.0f); + float drawScale = _scale; // TODO: Handle SHORTY mode - _vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2); + _vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2); //todo udpate screenrect } @@ -421,16 +528,16 @@ void Actor::setSetId(int setId) { if (_setId > 0) { for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) { if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) { - // TODO: actorScript->OtherAgentExitedThisScene( i, _id); + // TODO: _vm->_aiScripts->OtherAgentExitedThisScene( i, _id); } } } _setId = setId; - // TODO: actorScript->EnteredScene(_id, set); + // TODO: _vm->_aiScripts->EnteredScene(_id, set); if (_setId > 0) { for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) { if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) { - // TODO: actorScript->OtherAgentEnteredThisScene(i, _id); + // TODO: _vm->_aiScripts->OtherAgentEnteredThisScene(i, _id); } } } @@ -474,7 +581,7 @@ void Actor::setFacing(int facing, bool halfOrSet) { _facing = (_facing + offset) % 1024; } -void Actor::setBoundingBox(Vector3 position, bool retired) { +void Actor::setBoundingBox(const Vector3 &position, bool retired) { if (retired) { _bbox->setXYZ(position.x - (_retiredWidth / 2.0f), position.y, @@ -510,11 +617,11 @@ void Actor::stopWalking(bool value) { } if (isWalking()) { - _walkInfo->stop(_id, 1, _combatAnimationMode, 0); + _walkInfo->stop(_id, true, _combatAnimationMode, 0); } else if (inCombat()) { - changeAnimationMode(_combatAnimationMode, 0); + changeAnimationMode(_combatAnimationMode, false); } else { - changeAnimationMode(0, 0); + changeAnimationMode(0, false); } } @@ -563,13 +670,13 @@ void Actor::faceWaypoint(int waypointId, bool animate) { void Actor::faceXYZ(float x, float y, float z, bool animate) { if (isWalking()) { - stopWalking(0); + stopWalking(false); } if (x == _position.x && z == _position.z) { return; } - int heading = int(512.0f * atan2f(_position.x - x, _position.z - z) / M_PI) % 1024; + int heading = angle_1024(_position.x, _position.z, x, z); faceHeading(heading, animate); } @@ -622,7 +729,7 @@ void Actor::setImmunityToObstacles(bool isImmune) { void Actor::modifyCurrentHP(signed int change) { _currentHP = MIN(MAX(_currentHP + change, 0), 100); if (_currentHP > 0) - retire(0, 0, 0, -1); + retire(false, 0, 0, -1); } void Actor::modifyMaxHP(signed int change) { @@ -674,7 +781,7 @@ void Actor::setHealth(int hp, int maxHp) { _currentHP = hp; _maxHP = maxHp; if (hp > 0) { - retire(0, 0, 0, -1); + retire(false, 0, 0, -1); } } @@ -685,8 +792,8 @@ void Actor::combatModeOn(int a2, int a3, int otherActorId, int a5, int combatAni _inCombat = true; if (_id > 0) _combatInfo->combatOn(_id, a2, a3, otherActorId, a5, a9, a10, a11, ammoDamage, a13, a14); - stopWalking(0); - changeAnimationMode(_combatAnimationMode, 0); + stopWalking(false); + changeAnimationMode(_combatAnimationMode, false); int i; for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) { Actor *otherActor = _vm->_actors[i]; @@ -700,8 +807,8 @@ void Actor::combatModeOff() { if (_id > 0) _combatInfo->combatOff(); _inCombat = false; - stopWalking(0); - changeAnimationMode(0, 0); + stopWalking(false); + changeAnimationMode(0, false); int i; for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) { Actor *otherActor = _vm->_actors[i]; @@ -868,4 +975,84 @@ void Actor::countdownTimerUpdate(int timerId) { } } +bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float size, Vector3 *newDestination) { + newDestination->x = 0.0f; + newDestination->y = 0.0f; + newDestination->z = 0.0f; + int facing = angle_1024(targetPosition, startPosition); + int facing1 = 0; + + int facing2 = facing; + int facing3 = 0; + while (true) { + float cos = cos_1024(facing); + float sin = sin_1024(facing); + float rotatedX = size * sin + targetPosition.x; + float rotatedZ = size * cos + targetPosition.z; + + if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) { + if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) { + newDestination->x = rotatedX; + newDestination->y = targetPosition.y; + newDestination->z = rotatedZ; + return true; + } + } else { + facing += 20; + if (facing > 1024) { + facing -= 1024; + } + facing3 += 20; + } + + cos = cos_1024(facing2); + sin = sin_1024(facing2); + rotatedX = size * sin + targetPosition.x; + rotatedZ = size * cos + targetPosition.z; + + if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) { + if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) { + newDestination->x = rotatedX; + newDestination->y = targetPosition.y; + newDestination->z = rotatedZ; + return true; + } + } else { + facing2 -= 20; + if (facing2 < 0) { + facing2 += 1024; + } + facing1 += 20; + } + + if (facing3 > 1024 && facing1 > 1024) { + return false; + } + } +} + +bool Actor::walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition) { + newDestination->x = 0.0f; + newDestination->y = 0.0f; + newDestination->z = 0.0f; + float size = destinationOffset + targetSize * 0.5f + targetWidth * 0.5f; + float distance = (startPosition - targetPosition).length() - targetWidth * 0.5f - targetSize * 0.5f; + if (size < distance) { + return walkFindU1(startPosition, targetPosition, size, newDestination); + } else { + *newDestination = targetPosition; + return true; + } +} + +bool Actor::walkToU(const Vector3 &destination, float distance) { + Vector3 out; + bool isRunning; + if (_walkInfo->findU1(_id, destination, distance, &out)) { + loopWalk(out, 0, false, false, _position, 0.0f, 24.0f, false, &isRunning, false); + return true; + } + return false; +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h index 1edbea49b4..b2b52c623d 100644 --- a/engines/bladerunner/actor.h +++ b/engines/bladerunner/actor.h @@ -72,6 +72,7 @@ private: bool _isTargetable; bool _isInvisible; bool _isImmuneToObstacles; + bool _inWalkLoop; bool _isRetired; bool _inCombat; bool _isMoving; @@ -106,7 +107,7 @@ public: void setup(int actorId); - void setAtXYZ(Vector3 pos, int facing, bool setFacing = true, bool moving = false, bool retired = false); + void setAtXYZ(const Vector3 &pos, int facing, bool setFacing = true, bool moving = false, bool retired = false); void setAtWaypoint(int waypointId, int angle, int unknown, bool retired); float getX(); @@ -123,9 +124,11 @@ public: void processMovement(); - void loopWalkToXYZ(Vector3 destination); - void loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7); - void loopWalkToSceneObject(const char *objectName, int destinationOffset = 0); + bool loopWalkToActor(int otherActorId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning); + bool loopWalkToItem(int itemId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning); + bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning); + bool loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning); + bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning); bool tick(bool forceUpdate); void draw(); @@ -141,8 +144,9 @@ public: Common::Rect *getScreenRectangle() { return &_screenRectangle; } int getWalkbox() { return _walkboxId; } bool isRetired() { return _isRetired; } - bool isTargetable() { return _isTargetable; } + bool isTargetable() { return _isTargetable; } void setTargetable(bool targetable); + bool isImmuneToObstacles() { return _isImmuneToObstacles; } bool inCombat() { return _inCombat; } bool isMoving() { return _isMoving; } void setMoving(bool value) { _isMoving = value; } @@ -198,8 +202,16 @@ public: int soundBalance(); private: void setFacing(int facing, bool halfOrSet = true); - void setBoundingBox(Vector3 position, bool retired); + void setBoundingBox(const Vector3 &position, bool retired); float distanceFromView(View* view); + + 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 walkFindU3(int actorId, Vector3 from, int distance, Vector3 *out); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp index ed55bd0277..717422f60d 100644 --- a/engines/bladerunner/actor_walk.cpp +++ b/engines/bladerunner/actor_walk.cpp @@ -25,14 +25,13 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/actor.h" +#include "bladerunner/obstacles.h" +#include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" +#include "bladerunner/set.h" -namespace BladeRunner { -static int angle_1024(float x1, float z1, float x2, float z2); -static int angle_1024(Vector3 &v1, Vector3 &v2); -float distance(float x1, float x2, float z1, float z2); -float distance(Vector3 &v1, Vector3 &v2); +namespace BladeRunner { ActorWalk::ActorWalk(BladeRunnerEngine *vm) { _vm = vm; @@ -41,36 +40,38 @@ ActorWalk::ActorWalk(BladeRunnerEngine *vm) { _running = 0; _facing = -1; _status = 0; + + _entries.clear(); } ActorWalk::~ActorWalk() { } -int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2) { +bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped) { Vector3 next; - *unk2 = 0; + *stopped = false; int r = nextOnPath(actorId, from, to, &next); if (r == 0) { if (actorId != 0) { _current = from; _destination = to; - stop(actorId, false); + stop(actorId, false, 4, 0); } else { - stop(actorId, true); + stop(actorId, true, 4, 0); } - return 0; + return false; } if (r == -1) { - stop(actorId, true); - *unk2 = 1; - return 0; + stop(actorId, true, 4, 0); + *stopped = true; + return false; } - // TODO: Init array - // TODO: Update screen index - // Set actor field e8 + resetList(); + _vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true); + _vm->_actors[actorId]->setMoving(true); if (_running) { run = true; @@ -95,17 +96,17 @@ int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, i _running = run; _status = 2; - return 1; + return true; } - stop(actorId, true); - return 0; + stop(actorId, true, 4, 0); + return false; } bool ActorWalk::tick(int actorId, float stepDistance, bool flag) { if (_status == 5) { if (flag) { - stop(actorId, true); + stop(actorId, true, 4, 0); return true; } @@ -117,7 +118,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) { // TODO: Handle collisions? if (stepDistance > distance(_current, _destination)) { - stop(actorId, true); + stop(actorId, true, 4, 0); _current = _destination; // TODO: Update y from walkbox return true; @@ -127,7 +128,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) { _current = Vector3( _current.x + stepDistance * sinf(angle_rad), - _current.y, // TODO: Update from walkbox + _current.y, // TODO: Update from walkbox _current.z - stepDistance * cosf(angle_rad) ); @@ -135,7 +136,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) { } void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) { - *pos = _current; + *pos = _current; *facing = _facing; } @@ -144,14 +145,14 @@ void ActorWalk::setRunning() { // TODO: Set animation mode } -void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused) { - _vm->_sceneObjects->setMoving(actorId, 0); - _vm->_actors[actorId]->setMoving(0); +void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int animationMode) { + _vm->_sceneObjects->setMoving(actorId, false); + _vm->_actors[actorId]->setMoving(false); if (_vm->_actors[actorId]->inCombat()) { - _vm->_actors[actorId]->changeAnimationMode(animationMode, 0); + _vm->_actors[actorId]->changeAnimationMode(combatAnimationMode, false); } else { - _vm->_actors[actorId]->changeAnimationMode(notused, 0); + _vm->_actors[actorId]->changeAnimationMode(animationMode, false); } if (unknown) { @@ -165,45 +166,111 @@ void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused) } } -int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next) { - if (distance(from, to) < 6.0) { - return -1; +bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) { + if (_vm->_scene->_set->findWalkbox(x, z) == -1) { + return true; } - - // if (_vm->_actors[actorId]->getImmunityToObstacles()) { - *next = to; - return 1; - // } - - error("TODO!"); + if (_vm->_actors[actorId]->isImmuneToObstacles()) { + return false; + } + return _vm->_sceneObjects->existsOnXZ(actorId, x, z, false, false); } -static int angle_1024(float x1, float z1, float x2, float z2) { - float angle_rad = atan2(x2 - x1, z1 - z2); - int a = int(512.0 * angle_rad / M_PI); - return (a + 1024) % 1024; -} +int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) { + float cos, sin; + bool inWalkbox; + + int facingFound = -1; + float distFound = -1.0f; + float x = 0.0f; + float z = 0.0f; + + out->x = 0.0f; + out->y = 0.0f; + out->z = 0.0f; + + for (int facing = 0; facing < 1024; facing += 128) { + sin = sin_1024(facing); + cos = cos_1024(facing); + x = to.x + sin * dist; + z = to.z + cos * dist; + float dist2 = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ()); + + if (distFound == -1.0f || distFound > dist2) { + distFound = dist2; + facingFound = facing; + } + } -static int angle_1024(Vector3 &v1, Vector3 &v2) { - return angle_1024(v1.x, v1.z, v2.x, v2.z); -} + int v23 = facingFound; + int v24 = facingFound; + int v25 = -1024; + while (v25 < 0) { + sin = sin_1024(v24); + cos = cos_1024(v24); + x = to.x + sin * dist; + z = to.z + cos * dist; + + if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { + break; + } -float distance(float x1, float z1, float x2, float z2) { - float dx = x1 - x2; - float dz = z1 - z2; - float d = sqrt(dx * dx + dz * dz); + sin = sin_1024(v23); + cos = cos_1024(v23); + x = to.x + sin * dist; + z = to.z + cos * dist; - float int_part = (int)d; - float frac_part = d - int_part; + if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { + break; + } - if (frac_part < 0.001) - frac_part = 0.0; + v24 -= 64; + if (v24 < 0) { + v24 += 1024; + } + v23 += 64; + if (v23 >= 1024) { + v23 -= 1024; + } + v25 += 64; + } - return int_part + frac_part; + float y = _vm->_scene->_set->getAltitudeAtXZ(x, z, &inWalkbox); + if (inWalkbox) { + out->x = x; + out->y = y; + out->z = z; + return true; + } + return false; } -float distance(Vector3 &v1, Vector3 &v2) { - return distance(v1.x, v1.z, v2.x, v2.z); +int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next) { + *next = from; + + if (distance(from, to) < 6.0) { + return -1; + } + + if (_vm->_actors[actorId]->isImmuneToObstacles()) { + *next = to; + return 1; + } + if (_vm->_scene->_set->findWalkbox(to.x, to.z) == -1) { + return 0; + } + if (_vm->_sceneObjects->existsOnXZ(actorId, to.x, to.z, false, false)) { + return 0; + } + Vector3 next1; + if (_vm->_obstacles->find(from, to, &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 12da69bead..6cd5850672 100644 --- a/engines/bladerunner/actor_walk.h +++ b/engines/bladerunner/actor_walk.h @@ -24,6 +24,7 @@ #define BLADERUNNER_ACTOR_WALK_H #include "bladerunner/vector.h" +#include "common/array.h" namespace BladeRunner { @@ -45,8 +46,7 @@ private: Vector3 _current; Vector3 _next; int _facing; - ActorWalkEntry _actors[20]; - int _actorsCount; + Common::Array _entries; int _field15; int _status; @@ -54,7 +54,8 @@ public: ActorWalk(BladeRunnerEngine *vm); ~ActorWalk(); - int setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2); + + 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 tick(int actorId, float stepDistance, bool flag); @@ -62,10 +63,15 @@ public: bool isRunning() { return _running; } void setRunning(); - void stop(int actorId, bool unknown, int animationMode = 4, int notused = 0); + void stop(int actorId, bool unknown, int combatAnimationMode, int animationMode); // void setWalkingMode(int actorId, int active, int unk2 = 4, int unk3 = 0); - int nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next); + int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next); + + void resetList(); + + bool isXYZEmpty(float x, float y, float z, int actorId); + int findU1(int actorId, const Vector3 &to, int distance, Vector3 *out); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/adq.cpp b/engines/bladerunner/adq.cpp index b8611ee665..ca72497b99 100644 --- a/engines/bladerunner/adq.cpp +++ b/engines/bladerunner/adq.cpp @@ -32,7 +32,7 @@ namespace BladeRunner { -ADQ::ADQEntry::ADQEntry() { +ADQEntry::ADQEntry() { this->_isNotPause = false; this->_isPause = false; this->_actorId = -1; diff --git a/engines/bladerunner/adq.h b/engines/bladerunner/adq.h index b0619c7650..f4e69df684 100644 --- a/engines/bladerunner/adq.h +++ b/engines/bladerunner/adq.h @@ -28,22 +28,21 @@ namespace BladeRunner { class BladeRunnerEngine; +struct ADQEntry { + bool _isNotPause; + bool _isPause; + int _actorId; + int _sentenceId; + int _animationMode; + int _delay; + + ADQEntry(); +}; + // actor dialogue queue?? class ADQ { BladeRunnerEngine *_vm; - class ADQEntry { - public: - bool _isNotPause; - bool _isPause; - int _actorId; - int _sentenceId; - int _animationMode; - int _delay; - - ADQEntry(); - }; - Common::Array _entries; bool _isNotPause; diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 3365bb1c09..66ed387e0d 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -37,6 +37,7 @@ #include "bladerunner/lights.h" #include "bladerunner/mouse.h" #include "bladerunner/outtake.h" +#include "bladerunner/obstacles.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/script/init.h" @@ -73,6 +74,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) _lights = new Lights(this); _combat = new Combat(this); _adq = new ADQ(this); + _obstacles = new Obstacles(this); _walkSoundId = -1; _walkSoundVolume = 0; @@ -100,6 +102,7 @@ BladeRunnerEngine::~BladeRunnerEngine() { // delete[] _zBuffer1; // delete[] _zBuffer2; + delete _obstacles; delete _adq; delete _combat; delete _lights; @@ -743,7 +746,8 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) { } if (sceneObjectId == -1) { - _actors[0]->loopWalkToXYZ(mousePosition); + bool isRunning; + _playerActor->loopWalkToXYZ(mousePosition, 0, false, false, false, &isRunning); debug("Clicked on nothing %f, %f, %f", mousePosition.x, mousePosition.y, mousePosition.z); return; } else if (sceneObjectId >= 0 && sceneObjectId <= 73) { diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 273449fcf6..d3759d6ce8 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -49,6 +49,7 @@ class GameInfo; class Items; class Lights; class Mouse; +class Obstacles; class Scene; class SceneObjects; class Script; @@ -65,7 +66,7 @@ public: bool _gameIsRunning; bool _windowIsActive; int _playerLosesControlCounter; - + ADQ *_adq; AIScripts *_aiScripts; AmbientSounds *_ambientSounds; @@ -73,9 +74,13 @@ public: AudioSpeech *_audioSpeech; Chapters *_chapters; Clues *_clues; + Combat *_combat; GameFlags *_gameFlags; GameInfo *_gameInfo; + Items *_items; + Lights *_lights; Mouse *_mouse; + Obstacles *_obstacles; Scene *_scene; SceneObjects *_sceneObjects; Script *_script; @@ -83,13 +88,9 @@ public: SliceAnimations *_sliceAnimations; SliceRenderer *_sliceRenderer; View *_view; - int *_gameVars; - - Lights *_lights; Waypoints *_waypoints; - Items *_items; - Combat *_combat; - + int *_gameVars; + TextResource *_textActorNames; TextResource *_textCrimes; TextResource *_textCluetype; @@ -124,6 +125,7 @@ public: int _walkSoundId; int _walkSoundVolume; int _walkSoundBalance; + int _walkingActorId; private: static const int kArchiveCount = 10; diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp index 11e75e93e6..00f98d35b8 100644 --- a/engines/bladerunner/item.cpp +++ b/engines/bladerunner/item.cpp @@ -66,6 +66,11 @@ void Item::getXYZ(float *x, float *y, float *z) { *z = _position.z; } +void Item::getWidthHeight(int *width, int *height) { + *width = _width; + *height = _height; +} + bool Item::isTargetable() { return _isTargetable; } @@ -84,7 +89,7 @@ void Item::tick(bool special) { } else if (_facing < 0) { _facing += 1024; } - _angle = M_PI / 512.0f * _facing; + _angle = _facing * (M_PI / 512.0f); if (_facingChange > 0) { _facingChange = _facingChange - 20; @@ -108,7 +113,7 @@ void Item::tick(bool special) { void Item::setXYZ(Vector3 position) { _position = position; int halfWidth = _width / 2; - _boundingBox.setXYZ(_position.x - halfWidth, _position.y, _position.z - halfWidth, + _boundingBox.setXYZ(_position.x - halfWidth, _position.y, _position.z - halfWidth, _position.x + halfWidth, _position.y + _height, _position.z + halfWidth); Vector3 screenPosition = _vm->_view->calculateScreenPosition(_position); _screenX = screenPosition.x; @@ -121,7 +126,7 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f _setId = setId; _animationId = animationId; _facing = facing; - _angle = M_PI / 512.0f * facing; + _angle = facing * (M_PI / 512.0f); _width = width; _height = height; _isTargetable = isTargetable; diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h index bdcaea7846..0035985751 100644 --- a/engines/bladerunner/item.h +++ b/engines/bladerunner/item.h @@ -62,12 +62,16 @@ private: public: Item(BladeRunnerEngine* vm); ~Item(); - + void getXYZ(float *x, float *y, float *z); + void setXYZ(Vector3 position); + void getWidthHeight(int * width, int * height); + bool isTargetable(); void tick(bool special); - void setXYZ(Vector3 position); + void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy); + }; } diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp index e9cb013246..51145a3b14 100644 --- a/engines/bladerunner/items.cpp +++ b/engines/bladerunner/items.cpp @@ -44,6 +44,13 @@ void Items::getXYZ(int itemId, float* x, float* y, float* z) { _items[itemIndex]->getXYZ(x, y, z); } +void Items::getWidthHeight(int itemId, int *width, int *height) { + int itemIndex = findItem(itemId); + assert(itemIndex != -1); + + _items[itemIndex]->getWidthHeight(width, height); +} + void Items::tick() { int setId = _vm->_scene->getSetId(); for(int i = 0; i < (int)_items.size(); i++) { diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h index e6e1cb2500..0b5c7e09a9 100644 --- a/engines/bladerunner/items.h +++ b/engines/bladerunner/items.h @@ -40,9 +40,12 @@ public: ~Items(); void getXYZ(int itemId, float *x, float *y, float *z); + void getWidthHeight(int itemId, int * width, int * height); + void tick(); bool add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b); bool remove(int itemId); + private: int findItem(int itemId); }; diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index 3867331a36..b7c85ceeec 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -31,6 +31,7 @@ MODULE_OBJS = \ matrix.o \ mouse.o \ movement_track.o \ + obstacles.o \ outtake.o \ regions.o \ scene.o \ diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp new file mode 100644 index 0000000000..3c9552d231 --- /dev/null +++ b/engines/bladerunner/obstacles.cpp @@ -0,0 +1,46 @@ +#include "bladerunner/obstacles.h" + +#include "bladerunner/bladerunner.h" + +namespace BladeRunner { + +Obstacles::Obstacles(BladeRunnerEngine* vm) { + _vm = vm; + _polygons = new ObstaclesPolygon[50]; + _polygons2 = new ObstaclesPolygon[50]; + _unknown = new int[50]; + clear(); +} + +Obstacles::~Obstacles() { + delete[] _unknown; + delete[] _polygons2; + delete[] _polygons; +} + +void Obstacles::clear() { + for(int i = 0; i < 50; i++) { + _polygons[i]._isPresent = false; + _polygons[i]._verticesCount = 0; + for(int j = 0; j < 160; j++) { + _polygons[i]._vertices[j].x = 0.0f; + _polygons[i]._vertices[j].y = 0.0f; + } + } + _count = 0; + _processed = false; +} + +void Obstacles::add(float x0, float z0, float x1, float z1) { + +} + +bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) { + //TODO + *next = to; + return true; +} + +void Obstacles::process() { +} +} // End of namespace BladeRunner diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h new file mode 100644 index 0000000000..2caa3cd580 --- /dev/null +++ b/engines/bladerunner/obstacles.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +*/ + +#ifndef BLADERUNNER_OBSTACLES_H +#define BLADERUNNER_OBSTACLES_H +#include "vector.h" + +namespace BladeRunner { + +struct ObstaclesPolygon { + bool _isPresent; + int _verticesCount; + float _left; + float _bottom; + float _right; + float _top; + Vector2 _vertices[160]; + int _vertexType[160]; +}; + +class BladeRunnerEngine; + +class Obstacles { + BladeRunnerEngine *_vm; + +private: + ObstaclesPolygon *_polygons; + ObstaclesPolygon *_polygons2; + int *_unknown; + int _count; + bool _processed; + +public: + Obstacles(BladeRunnerEngine *vm); + ~Obstacles(); + + void clear(); + void add(float x0, float z0, float x1, float z1); + bool find(const Vector3 &from, const Vector3 &to, Vector3 *next); + void process(); +}; + +} // End of namespace BladeRunner + +#endif diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index 06563b7d51..f9a112eff5 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -236,7 +236,7 @@ void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, if (sceneLoaded) { _vm->_sceneObjects->setIsObstacle(objectId + 198, isObstacle); if(updateWalkpath) { - _vm->_sceneObjects->updateWalkpath(); + _vm->_sceneObjects->updateObstacles(); } } } diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp index 4c038fa9c7..59df6c12b4 100644 --- a/engines/bladerunner/scene_objects.cpp +++ b/engines/bladerunner/scene_objects.cpp @@ -22,8 +22,12 @@ #include "bladerunner/scene_objects.h" +#include "bladerunner/bladerunner.h" + +#include "bladerunner/obstacles.h" #include "bladerunner/view.h" + namespace BladeRunner { SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) { @@ -280,8 +284,18 @@ void SceneObjects::setIsTarget(int sceneObjectId, bool isTarget) { } -void SceneObjects::updateWalkpath() { - //TODO: implement +void SceneObjects::updateObstacles() { + _vm->_obstacles->clear(); + for(int i = 0; i < _count; i++) { + int index = _sceneObjectsSortedByDistance[i]; + SceneObject sceneObject = _sceneObjects[index]; + if(sceneObject._isObstacle) { + float x0, y0, z0, x1, y1, z1; + sceneObject._boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); + _vm->_obstacles->add(x0, z0, x1, z1); + } + } + _vm->_obstacles->process(); } } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h index 947ee17336..010dc43532 100644 --- a/engines/bladerunner/scene_objects.h +++ b/engines/bladerunner/scene_objects.h @@ -87,7 +87,7 @@ public: void setIsClickable(int sceneObjectId, bool isClickable); void setIsObstacle(int sceneObjectId, bool isObstacle); void setIsTarget(int sceneObjectId, bool isTarget); - void updateWalkpath(); + void updateObstacles(); private: int findById(int sceneObjectId); diff --git a/engines/bladerunner/script/nr03.cpp b/engines/bladerunner/script/nr03.cpp index f0d2f359b5..a4afdd36ec 100644 --- a/engines/bladerunner/script/nr03.cpp +++ b/engines/bladerunner/script/nr03.cpp @@ -305,7 +305,7 @@ void ScriptNR03::sub_40259C(int frame) { float z = -60.21f * s + 36.49f * c + -408.79f; if (Actor_Query_Goal_Number(4) == 201) { - facing = angle * (1024.0f / (2.0f * M_PI)); + facing = angle * (512.0f / M_PI); facing = facing + 144; if (facing < 0) { facing = facing + 1168; @@ -315,7 +315,7 @@ void ScriptNR03::sub_40259C(int frame) { } Actor_Set_At_XYZ(4, x, -70.19f, z, facing); } else { - facing = angle * (1024.0f / (2.0f * M_PI)); + facing = angle * (512.0f / M_PI); facing = facing + 400; if (facing < 0) { facing = facing + 1424; diff --git a/engines/bladerunner/script/nr05.cpp b/engines/bladerunner/script/nr05.cpp index a62052bdfd..d686bce374 100644 --- a/engines/bladerunner/script/nr05.cpp +++ b/engines/bladerunner/script/nr05.cpp @@ -205,7 +205,7 @@ void ScriptNR05::sub_401F74(int frame) { float x = 6.0f * s - 80.0f * c + -450.0f; float z = 80.0f * s + 6.0f * c + -531.0f; - int facing = angle * (1024.0f / (2.0f * M_PI)); + int facing = angle * (512.0f / M_PI); facing = facing + 765; if (facing < 0) { facing = facing + 1789; diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp index 9d88d2dec3..d94f104403 100644 --- a/engines/bladerunner/script/rc01.cpp +++ b/engines/bladerunner/script/rc01.cpp @@ -215,7 +215,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) { } if (Object_Query_Click("HYDRANT02", objectName)) { - if (!Loop_Actor_Walk_To_Scene_Object(0, "HYDRANT02", 60, 1, false)) { + if (!Loop_Actor_Walk_To_Scene_Object(0, "HYDRANT02", 60, true, false)) { if (Actor_Clue_Query(0, 26)) { Actor_Says(0, 6975, 3); } else { @@ -230,7 +230,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) { } if (Object_Query_Click("DOOR LEFT", objectName)) { - if (!Loop_Actor_Walk_To_Scene_Object(0, "DOOR LEFT", 48, 1, false)) { + if (!Loop_Actor_Walk_To_Scene_Object(0, "DOOR LEFT", 48, true, false)) { Actor_Face_Object(0, "DOOR LEFT", true); if (!Actor_Clue_Query(0, 2) && Actor_Query_In_Set(23, 69) && Global_Variable_Query(1)) { Actor_Set_Goal_Number(23, 0); @@ -247,7 +247,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) { } if (Object_Query_Click("T-CAN01", objectName)) { - if (!Loop_Actor_Walk_To_Scene_Object(0, "T-CAN01", 24, 1, false)) { + if (!Loop_Actor_Walk_To_Scene_Object(0, "T-CAN01", 24, true, false)) { Actor_Face_Object(0, "T-CAN01", true); Actor_Voice_Over(1810, 99); Actor_Voice_Over(1820, 99); @@ -530,7 +530,7 @@ bool ScriptRC01::ClickedOnExit(int exitId) { } void ScriptRC01::sub_403850() { - if (!Game_Flag_Query(186) && !Loop_Actor_Walk_To_Scene_Object(0, "BARICADE03", 36, 1, false)) { + if (!Game_Flag_Query(186) && !Loop_Actor_Walk_To_Scene_Object(0, "BARICADE03", 36, true, false)) { Actor_Set_Goal_Number(23, 0); Actor_Face_Object(0, "BARICADE03", true); Loop_Actor_Walk_To_Actor(23, 0, 36, 1, false); diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp index 216428c2f8..180e8cb96e 100644 --- a/engines/bladerunner/script/script.cpp +++ b/engines/bladerunner/script/script.cpp @@ -540,48 +540,75 @@ int ScriptBase::Actor_Query_Animation_Mode(int actorId) { return _vm->_actors[actorId]->getAnimationMode(); } -bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool running) { +bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool run) { //TODO - warning("Loop_Actor_Walk_To_Actor(%d, %d, %d, %d, %d)", actorId, otherActorId, a3, a4, running); + warning("Loop_Actor_Walk_To_Actor(%d, %d, %d, %d, %d)", actorId, otherActorId, a3, a4, run); return false; } -bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool running) { +bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool run) { //TODO - warning("Loop_Actor_Walk_To_Item(%d, %d, %d, %d, %d)", actorId, itemId, a3, a4, running); + warning("Loop_Actor_Walk_To_Item(%d, %d, %d, %d, %d)", actorId, itemId, a3, a4, run); return false; } -bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, bool running) { +bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int destinationOffset, bool a4, bool run) { _vm->gameWaitForActive(); - _vm->_actors[actorId]->loopWalkToSceneObject(objectName); - - return false; + if(_vm->_walkingActorId == actorId) { + run = true; + } + bool isRunning; + bool result = _vm->_actors[actorId]->loopWalkToSceneObject(objectName, destinationOffset, a4, run, true, &isRunning); + if(isRunning == 1) { + _vm->_walkingActorId = actorId; + } + Global_Variable_Set(37, actorId); + Global_Variable_Set(38, isRunning); + return result; } -bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool running) { +bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, int a4, bool run) { //TODO - warning("Loop_Actor_Walk_To_Waypoint(%d, %d, %d, %d, %d)", actorId, waypointId, a3, a4, running); + warning("Loop_Actor_Walk_To_Waypoint(%d, %d, %d, %d, %d)", actorId, waypointId, destinationOffset, a4, run); return false; } -bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool running, int a7) { +bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, int a5, bool run, int a7) { _vm->gameWaitForActive(); - _vm->_actors[actorId]->loopWalkToXYZ(x, y, z, a4, a5, running, 1); - - return false; + if(_vm->_walkingActorId == actorId) { + if(a7) { + _vm->_walkingActorId = -1; + } else { + run = true; + } + } + //TODO: + //PlayerActorIdle = 0; + bool isRunning; + bool result = _vm->_actors[actorId]->loopWalkToXYZ(Vector3(x, y, z), destinationOffset, a5, run, 1, &isRunning); + +// if (PlayerActorIdle == 1) { +// result = 1; +// PlayerActorIdle = 0; +// } + if(isRunning) { + _vm->_walkingActorId = actorId; + } + Global_Variable_Set(37, actorId); + Global_Variable_Set(38, isRunning); + return result; } -void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int running) { +void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, int run) { //TODO - warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, waypointId, a3, running); + warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, waypointId, destinationOffset, run); } -void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool running) { +void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, bool run) { //TODO - warning("Async_Actor_Walk_To_XYZ(%d, %f, %f, %f, %d, %d)", actorId, x, y, z, a5, running); + warning("Async_Actor_Walk_To_XYZ(%d, %f, %f, %f, %d, %d)", actorId, x, y, z, destinationOffset, run); } void ScriptBase::Actor_Force_Stop_Walking(int actorId) { @@ -692,11 +719,11 @@ void ScriptBase::Delay(int miliseconds) { } void ScriptBase::Player_Loses_Control() { - _vm->playerLosesControl(); + _vm->playerLosesControl(); } void ScriptBase::Player_Gains_Control() { - _vm->playerGainsControl(); + _vm->playerGainsControl(); } void ScriptBase::Player_Set_Combat_Mode(bool activate) { diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h index 0e4c0e9f62..fb38fdaf91 100644 --- a/engines/bladerunner/script/script.h +++ b/engines/bladerunner/script/script.h @@ -99,12 +99,12 @@ protected: void Actor_Change_Animation_Mode(int actorId, int animationMode); int Actor_Query_Animation_Mode(int actorId); bool Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool running); - bool Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool running); - bool Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, bool running); - bool Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool running); - bool Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool running, int a7); - void Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int running); - void Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool running); + bool Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool run); + bool Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, bool a4, bool run); + bool Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool run); + bool Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool run, int a7); + void Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int run); + void Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool run); void Actor_Force_Stop_Walking(int actorId); bool Loop_Actor_Travel_Stairs(int actorId, int a2, int a3, int a4); bool Loop_Actor_Travel_Ladder(int actorId, int a2, int a3, int a4); diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp index 12db84ae24..f8a480c181 100644 --- a/engines/bladerunner/set.cpp +++ b/engines/bladerunner/set.cpp @@ -91,10 +91,10 @@ bool Set::open(const Common::String &name) { assert(_walkboxCount <= 95); for (int i = 0; i < _walkboxCount; ++i) { - float x, y, z; + float x, z; s->read(_walkboxes[i]._name, 20); - y = s->readFloatLE(); + _walkboxes[i]._altitude = s->readFloatLE(); _walkboxes[i]._vertexCount = s->readUint32LE(); assert(_walkboxes[i]._vertexCount <= 8); @@ -103,7 +103,7 @@ bool Set::open(const Common::String &name) { x = s->readFloatLE(); z = s->readFloatLE(); - _walkboxes[i]._vertices[j] = Vector3(x, y, z); + _walkboxes[i]._vertices[j] = Vector3(x, _walkboxes[i]._altitude, z); } // debug("WALKBOX: %s", _walkboxes[i]._name); @@ -166,7 +166,8 @@ static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) { if (x < lineX) found++; } - + lastX = currentX; + lastZ = currentZ; } return found & 1; } diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h index 070ca86190..84e4df63bb 100644 --- a/engines/bladerunner/vector.h +++ b/engines/bladerunner/vector.h @@ -108,6 +108,54 @@ inline Vector4 operator/(Vector4 a, Vector4 b) { return Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); } +inline +int angle_1024(float x1, float z1, float x2, float z2) +{ + float angle_rad = atan2(x2 - x1, z1 - z2); + int a = int(512.0 * angle_rad / M_PI); + return (a + 1024) % 1024; +} + +inline +int angle_1024(const Vector3 &v1, const Vector3 &v2) +{ + return angle_1024(v1.x, v1.z, v2.x, v2.z); +} + +inline +float distance(float x1, float z1, float x2, float z2) +{ + float dx = x1 - x2; + float dz = z1 - z2; + float d = sqrt(dx*dx + dz*dz); + + float int_part = (int)d; + float frac_part = d - int_part; + + if (frac_part < 0.001) + frac_part = 0.0; + + return int_part + frac_part; +} + +inline +float distance(const Vector3 &v1, const Vector3 &v2) +{ + return distance(v1.x, v1.z, v2.x, v2.z); +} + +inline +float cos_1024(int angle1024) { + return cos(angle1024 * (M_PI / 512.0f)); +} + +inline +float sin_1024(int angle1024) { + return sin(angle1024 * (M_PI / 512.0f)); +} + + + } // End of namespace BladeRunner #endif -- cgit v1.2.3