mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
270 lines
5.9 KiB
C++
270 lines
5.9 KiB
C++
/* 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.
|
|
*
|
|
*/
|
|
|
|
#include "bladerunner/actor_walk.h"
|
|
|
|
#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 {
|
|
|
|
ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
|
|
_vm = vm;
|
|
|
|
_walking = 0;
|
|
_running = 0;
|
|
_facing = -1;
|
|
_status = 0;
|
|
|
|
_entries.clear();
|
|
}
|
|
|
|
ActorWalk::~ActorWalk() {
|
|
}
|
|
|
|
bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped) {
|
|
Vector3 next;
|
|
|
|
*stopped = false;
|
|
int r = nextOnPath(actorId, from, to, &next);
|
|
|
|
if (r == 0) {
|
|
if (actorId != 0) {
|
|
_current = from;
|
|
_destination = to;
|
|
stop(actorId, false, 4, 0);
|
|
} else {
|
|
stop(actorId, true, 4, 0);
|
|
}
|
|
return false;
|
|
}
|
|
if (r == -1) {
|
|
stop(actorId, true, 4, 0);
|
|
*stopped = true;
|
|
return false;
|
|
}
|
|
|
|
resetList();
|
|
_vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true);
|
|
_vm->_actors[actorId]->setMoving(true);
|
|
|
|
if (_running) {
|
|
run = true;
|
|
}
|
|
|
|
int animationMode;
|
|
if (_vm->_actors[actorId]->inCombat()) {
|
|
animationMode = run ? 8 : 7;
|
|
} else {
|
|
animationMode = run ? 2 : 1;
|
|
}
|
|
|
|
_vm->_actors[actorId]->changeAnimationMode(animationMode);
|
|
|
|
_destination = 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;
|
|
}
|
|
|
|
stop(actorId, true, 4, 0);
|
|
return false;
|
|
}
|
|
|
|
bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
|
|
if (_status == 5) {
|
|
if (flag) {
|
|
stop(actorId, true, 4, 0);
|
|
return true;
|
|
}
|
|
|
|
if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) {
|
|
return false;
|
|
}
|
|
_status = 3;
|
|
}
|
|
// TODO: Handle collisions?
|
|
|
|
if (stepDistance > distance(_current, _destination)) {
|
|
stop(actorId, true, 4, 0);
|
|
_current = _destination;
|
|
// TODO: Update y from walkbox
|
|
return true;
|
|
}
|
|
|
|
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)
|
|
);
|
|
|
|
return false;
|
|
}
|
|
|
|
void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) {
|
|
*pos = _current;
|
|
*facing = _facing;
|
|
}
|
|
|
|
void ActorWalk::setRunning() {
|
|
_running = true;
|
|
// TODO: Set animation mode
|
|
}
|
|
|
|
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(combatAnimationMode, false);
|
|
} else {
|
|
_vm->_actors[actorId]->changeAnimationMode(animationMode, false);
|
|
}
|
|
|
|
if (unknown) {
|
|
_walking = false;
|
|
_running = false;
|
|
_status = 0;
|
|
} else {
|
|
_walking = true;
|
|
_running = false;
|
|
_status = 5;
|
|
}
|
|
}
|
|
|
|
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]->isImmuneToObstacles()) {
|
|
return false;
|
|
}
|
|
return _vm->_sceneObjects->existsOnXZ(actorId, x, z, false, false);
|
|
}
|
|
|
|
int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
|
|
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) {
|
|
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());
|
|
|
|
if (distFound == -1.0f || distFound > dist2) {
|
|
distFound = dist2;
|
|
facingFound = 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;
|
|
|
|
if (!_vm->_sceneObjects->existsOnXZ(actorId, 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;
|
|
|
|
if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
|
|
break;
|
|
}
|
|
|
|
v24 -= 64;
|
|
if (v24 < 0) {
|
|
v24 += 1024;
|
|
}
|
|
v23 += 64;
|
|
if (v23 >= 1024) {
|
|
v23 -= 1024;
|
|
}
|
|
v25 += 64;
|
|
}
|
|
|
|
float y = _vm->_scene->_set->getAltitudeAtXZ(x, z, &inWalkbox);
|
|
if (inWalkbox) {
|
|
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;
|
|
|
|
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
|