diff options
83 files changed, 4303 insertions, 898 deletions
@@ -39,6 +39,11 @@ Drascula: MADS: - Fixed a bug that caused a crash after starting Rex Nebular and the Cosmic Gender Bender. + SCI: + - Fixed a script bug in Laura Bow 2: Dagger of Amon Ra that made it impossible to exit the + party room with the large golden head inside the museum (room 350). + This bug is also present, when using the original interpreter. + TsAGE: - Fixed recently introduced bug preventing animations in Return to Ringworld from playing. diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index a1657468a8..946a1af23f 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -545,11 +545,6 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { #if SDL_VERSION_ATLEAST(2, 0, 0) case SDL_MOUSEWHEEL: { Sint32 yDir = ev.wheel.y; -#if SDL_VERSION_ATLEAST(2, 0, 4) - if (ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) { - yDir *= -1; - } -#endif // HACK: It seems we want the mouse coordinates supplied // with a mouse wheel event. However, SDL2 does not supply // these, thus we use whatever we got last time. It seems @@ -2791,7 +2791,7 @@ if test -n "$_host"; then _mt32emu=no _timidity=no ;; - androidsdl | androidsdl-armeabi | androidsdl-armeabi-v7a | androidsdl-mips | androidsdl-x86 | androidsdl-arm64-v8a) + androidsdl | androidsdl-armeabi | androidsdl-armeabi-v7a | androidsdl-mips | androidsdl-x86 | androidsdl-arm64-v8a | androidsdl-x86_64) DEFINES="$DEFINES -DANDROIDSDL" _unix=yes _seq_midi=no diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index 9a8892cf6c..597dc60454 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -91,6 +91,9 @@ void Actor::setup(int actorId) { _retiredWidth = 0; _retiredHeight = 0; + _movementTrackWalkingToWaypointId = -1; + _movementTrackDelayOnNextWaypoint = -1; + for (int i = 0; i != 7; ++i) { _timersRemain[i] = 0; _timersStart[i] = _vm->getTotalPlayTime(); @@ -107,6 +110,12 @@ void Actor::setup(int actorId) { _maxHP = 50; _goalNumber = -1; + _movementTrackPaused = false; + _movementTrackNextWaypointId = -1; + _movementTrackNextDelay = -1; + _movementTrackNextAngle = -1; + _movementTrackNextRunning = false; + _timersRemain[4] = 60000; _animationMode = -1; _screenRectangle = Common::Rect(-1, -1, -1, -1); @@ -151,30 +160,174 @@ void Actor::setFPS(int fps) { } } -void Actor::processMovement() { - /*if (movementTrack::is_paused(this->movementTrack) != 1 && this->id) - { - if (this->walkingWaypointId >= 0 && this->timeoutWalkingWaypoint >= 0) - { - worldWaypoints::get_sceneId(WorldWaypoints, this->walkingWaypointId); - if (!this->timeoutWalkingWaypoint) - { - this->timeoutWalkingWaypoint = 1; +void Actor::countdownTimerStart(int timerId, int interval) { + assert(timerId >= 0 && timerId < 7); + _timersRemain[timerId] = interval; + _timersStart[timerId] = _vm->getTotalPlayTime(); +} + +void Actor::countdownTimerReset(int timerId) { + assert(timerId >= 0 && timerId < 7); + _timersRemain[timerId] = 0; +} + +int Actor::countdownTimerGetRemainingTime(int timerId) { + assert(timerId >= 0 && timerId < 7); + return _timersRemain[timerId]; +} + +void Actor::countdownTimersUpdate() { + for (int i = 0; i <= 6; i++) { + countdownTimerUpdate(i); + } +} + +void Actor::countdownTimerUpdate(int timerId) { + if (_timersRemain[timerId] == 0) { + return; + } + + uint32 now = _vm->getTotalPlayTime(); + int tickInterval = now - _timersStart[timerId]; + _timersStart[timerId] = now; + + //warning("tickInterval: %d", tickInterval); + _timersRemain[timerId] -= tickInterval; + + if (_timersRemain[timerId] <= 0) { + switch (timerId) { + case 0: + case 1: + case 2: + if (!_vm->_aiScripts->IsInsideScript() && !_vm->_script->IsInsideScript()) { + _vm->_aiScripts->TimerExpired(this->_id, timerId); + this->_timersRemain[timerId] = 0; + } else { + this->_timersRemain[timerId] = 1; + } + break; + case 3: + _timersRemain[3] = 0; + if (_movementTrack->isPaused()) { + _timersRemain[3] = 1; + } else { + movementTrackNext(false); + } + break; + case 4: + // Something timer + break; + case 5: + // Actor animation frame timer + break; + case 6: + if (isRunning()) { + if (_fps > 15) { + int newFps = _fps - 2; + if (newFps < 15) { + newFps = 15; + } + setFPS(newFps); + } + } + _timersRemain[6] = 200; + break; + } + } +} + +void Actor::movementTrackNext(bool omitAiScript) { + bool hasNextMovement; + int waypointSetId; + int running; + int angle; + int delay; + int waypointId; + Vector3 waypointPosition; + bool stopped; + + hasNextMovement = _movementTrack->next(&waypointId, &delay, &angle, &running); + _movementTrackNextWaypointId = waypointId; + _movementTrackNextDelay = delay; + _movementTrackNextAngle = angle; + _movementTrackNextRunning = running; + if (hasNextMovement) { + if (angle == -1) { + angle = 0; + } + waypointSetId = _vm->_waypoints->getSetId(waypointId); + _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); + + _movementTrackWalkingToWaypointId = waypointId; + _movementTrackDelayOnNextWaypoint = delay; + if (stopped) { + movementTrackWaypointReached(); + } + } else { + setSetId(waypointSetId); + setAtXYZ(waypointPosition, angle, true, false, false); + + if (!delay) { + delay = 1; + } + if (delay > 1) { + changeAnimationMode(0, false); + } + countdownTimerStart(3, delay); + } + //return true; + } else { + if (!omitAiScript) { + _vm->_aiScripts->CompletedMovementTrack(_id); + } + //return false; + } +} + +void Actor::movementTrackPause() { + _movementTrack->pause(); + if (isWalking()) { + _movementTrackPaused = true; + stopWalking(false); + } else { + _movementTrackPaused = false; + } +} + +void Actor::movementTrackUnpause() { + Vector3 waypointPosition; + bool stopped; + + _movementTrack->unpause(); + if (_movementTrackNextWaypointId >= 0 && _movementTrackPaused) { + _vm->_waypoints->getXYZ(_movementTrackNextWaypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z); + _walkInfo->setup(_id, _movementTrackNextRunning, _position, waypointPosition, false, &stopped); + _movementTrackPaused = false; + } +} + +void Actor::movementTrackWaypointReached() { + int seconds; + if (!_movementTrack->isPaused() && _id != 0) { + if (_movementTrackWalkingToWaypointId >= 0 && _movementTrackDelayOnNextWaypoint) { + if (!_movementTrackDelayOnNextWaypoint) { + _movementTrackDelayOnNextWaypoint = 1; } - if (actorScript::call_ReachedMovementTrackWaypoint(ActorScript, this->id, this->walkingWaypointId) == 1) - { - seconds = this->timeoutWalkingWaypoint; - if (seconds > 1) - { - actor::changeAnimationMode(this, 0, 0); - seconds = this->timeoutWalkingWaypoint; + if (_vm->_aiScripts->ReachedMovementTrackWaypoint(_id, _movementTrackWalkingToWaypointId)) { + seconds = _movementTrackDelayOnNextWaypoint; + if (seconds > 1) { + changeAnimationMode(0, false); + seconds = _movementTrackDelayOnNextWaypoint; // todo: analyze if movement is changed in some aiscript->ChangeAnimationMode? } - actor::startTimer(this, 3, seconds); + countdownTimerStart(3, seconds); } } - this->walkingWaypointId = -1; - this->timeoutWalkingWaypoint = 0; - }*/ + _movementTrackWalkingToWaypointId = -1; + _movementTrackDelayOnNextWaypoint = 0; + } } bool Actor::loopWalkToActor(int otherActorId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) { @@ -203,10 +356,10 @@ void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool setBoundingBox(_position, retired); - _vm->_sceneObjects->remove(_id); + _vm->_sceneObjects->remove(_id + SCENE_OBJECTS_ACTORS_OFFSET); if (_vm->_scene->getSetId() == _setId) { - _vm->_sceneObjects->addActor(_id, _bbox, &_screenRectangle, 1, moving, _isTargetable, retired); + _vm->_sceneObjects->addActor(_id + SCENE_OBJECTS_ACTORS_OFFSET, _bbox, &_screenRectangle, 1, moving, _isTargetable, retired); } } @@ -375,10 +528,8 @@ bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, } 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); - + Vector3 waypointPosition; + _vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z); return loopWalk(waypointPosition, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false); } @@ -432,7 +583,7 @@ bool Actor::tick(bool forceDraw) { if (walked) { _vm->_actors[_id]->changeAnimationMode(0); - this->processMovement(); + this->movementTrackWaypointReached(); if (this->inCombat()) { this->changeAnimationMode(this->_combatAnimationMode, false); } else { @@ -477,7 +628,7 @@ bool Actor::tick(bool forceDraw) { this->_position.z = this->_position.z + positionChange.x * sinx + positionChange.y * cosx; this->_position.y = this->_position.y + positionChange.z; - if (_vm->_sceneObjects->existsOnXZ(this->_id, this->_position.x, this->_position.z, false, false) == 1 && !this->_isImmuneToObstacles) { + if (_vm->_sceneObjects->existsOnXZ(this->_id + SCENE_OBJECTS_ACTORS_OFFSET, this->_position.x, this->_position.z, false, false) == 1 && !this->_isImmuneToObstacles) { this->_position.x = originalX; this->_position.y = originalY; this->_position.z = originalZ; @@ -530,16 +681,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: _vm->_aiScripts->OtherAgentExitedThisScene( i, _id); + _vm->_aiScripts->OtherAgentExitedThisScene(i, _id); } } } _setId = setId; - // TODO: _vm->_aiScripts->EnteredScene(_id, set); + _vm->_aiScripts->EnteredScene(_id, _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: _vm->_aiScripts->OtherAgentEnteredThisScene(i, _id); + _vm->_aiScripts->OtherAgentEnteredThisScene(i, _id); } } } @@ -613,6 +764,10 @@ bool Actor::isWalking() { return _walkInfo->isWalking(); } +bool Actor::isRunning() { + return _walkInfo->isRunning(); +} + void Actor::stopWalking(bool value) { if (value && _id == 0) { _vm->_playerActorIdle = true; @@ -851,12 +1006,14 @@ int Actor::getAnimationMode() { } void Actor::setGoal(int goalNumber) { - if (goalNumber == _goalNumber) + int oldGoalNumber = _goalNumber; + _goalNumber = goalNumber; + if (goalNumber == oldGoalNumber) { return; + } - //TODO: _vm->actorScript->GoalChanged(_id, _goalNumber, goalNumber); - - _vm->_script->ActorChangedGoal(_id, goalNumber, _goalNumber, _vm->_scene->getSetId() == _setId); + _vm->_aiScripts->GoalChanged(_id, oldGoalNumber, goalNumber); + _vm->_script->ActorChangedGoal(_id, goalNumber, oldGoalNumber, _vm->_scene->getSetId() == _setId); } int Actor::getGoal() { @@ -927,56 +1084,6 @@ int Actor::soundBalance() { return 127.0f * (MAX(MIN(screenPosition.x / 640.0f, 1.0f), 0.0f) * 2.0f - 1.0f); } -void Actor::countdownTimerStart(int timerId, int interval) { - assert(timerId >= 0 && timerId < 7); - _timersRemain[timerId] = interval; - _timersStart[timerId] = _vm->getTotalPlayTime(); -} - -void Actor::countdownTimerReset(int timerId) { - assert(timerId >= 0 && timerId < 7); - _timersRemain[timerId] = 0; -} - -int Actor::countdownTimerGetRemainingTime(int timerId) { - assert(timerId >= 0 && timerId < 7); - return _timersRemain[timerId]; -} - -void Actor::countdownTimerUpdate(int timerId) { - if (_timersRemain[timerId] == 0) - return; - - uint32 now = _vm->getTotalPlayTime(); - int tickInterval = now - _timersStart[timerId]; - _timersStart[timerId] = now; - - // warning("tickInterval: %d", tickInterval); - _timersRemain[timerId] -= tickInterval; - - if (_timersRemain[timerId] <= 0) { - switch (timerId) { - case 0: - case 1: - case 2: - // AI timers, call AI dll - break; - case 3: - // Movement track timer - break; - case 4: - // Something timer - break; - case 5: - // Actor animation frame timer - break; - case 6: - // Slow down actor run timer? - break; - } - } -} - bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float size, Vector3 *newDestination) { newDestination->x = 0.0f; newDestination->y = 0.0f; diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h index b2b52c623d..d924730b4b 100644 --- a/engines/bladerunner/actor.h +++ b/engines/bladerunner/actor.h @@ -78,6 +78,16 @@ private: bool _isMoving; bool _damageAnimIfMoving; + // Movement + bool _movementTrackPaused; + int _movementTrackNextWaypointId; + int _movementTrackNextDelay; // probably not used + int _movementTrackNextAngle; // probably not used + bool _movementTrackNextRunning; + + int _movementTrackWalkingToWaypointId; + int _movementTrackDelayOnNextWaypoint; + // Animation int _width; int _height; @@ -122,7 +132,16 @@ public: void changeAnimationMode(int animationMode, bool force = false); void setFPS(int fps); - void processMovement(); + void countdownTimerStart(int timerId, int interval); + void countdownTimerReset(int timerId); + int countdownTimerGetRemainingTime(int timerId); + void countdownTimersUpdate(); + void countdownTimerUpdate(int timerId); + + void movementTrackNext(bool omitAiScript); + void movementTrackPause(); + void movementTrackUnpause(); + void movementTrackWaypointReached(); 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); @@ -133,11 +152,6 @@ public: bool tick(bool forceUpdate); void draw(); - void countdownTimerStart(int timerId, int interval); - void countdownTimerReset(int timerId); - int countdownTimerGetRemainingTime(int timerId); - void countdownTimerUpdate(int timerId); - int getSetId(); void setSetId(int setId); BoundingBox *getBoundingBox() { return _bbox; } @@ -151,6 +165,7 @@ public: bool isMoving() { return _isMoving; } void setMoving(bool value) { _isMoving = value; } bool isWalking(); + bool isRunning(); void stopWalking(bool value); void faceActor(int otherActorId, bool animate); diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp index 556f7b9afa..6287ac8ad0 100644 --- a/engines/bladerunner/actor_walk.cpp +++ b/engines/bladerunner/actor_walk.cpp @@ -146,7 +146,7 @@ void ActorWalk::setRunning() { } void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int animationMode) { - _vm->_sceneObjects->setMoving(actorId, false); + _vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, false); _vm->_actors[actorId]->setMoving(false); if (_vm->_actors[actorId]->inCombat()) { @@ -173,7 +173,7 @@ bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) { if (_vm->_actors[actorId]->isImmuneToObstacles()) { return false; } - return _vm->_sceneObjects->existsOnXZ(actorId, x, z, false, false); + 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) { @@ -206,14 +206,14 @@ int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) { 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) { + 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; - if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { + if (!_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { break; } @@ -252,7 +252,7 @@ int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, V if (_vm->_scene->_set->findWalkbox(to.x, to.z) == -1) { return 0; } - if (_vm->_sceneObjects->existsOnXZ(actorId, to.x, to.z, false, false)) { + if (_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, to.x, to.z, false, false)) { return 0; } Vector3 next1; diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index e60fe77d26..6a06422a24 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -60,7 +60,7 @@ #include "engines/util.h" #include "graphics/pixelformat.h" -#include "suspects_database.h" +#include "suspects_database.h" namespace BladeRunner { @@ -337,7 +337,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { initScript.SCRIPT_Initialize_Game(); // TODO: Load AI-ACT1.DLL - _aiScripts = new AIScripts(this); + _aiScripts = new AIScripts(this, actorCount); initChapterAndScene(); @@ -488,6 +488,9 @@ void BladeRunnerEngine::shutdown() { delete _actors[i]; _actors[i] = nullptr; } + delete _actors[VOICEOVER_ACTOR]; + _actors[VOICEOVER_ACTOR] = nullptr; + _playerActor = nullptr; // TODO: Delete proper ZBuf class @@ -619,17 +622,20 @@ void BladeRunnerEngine::gameTick() { #endif // TODO: Render overlays - // TODO: Tick Actor AI and Timers - if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) { + //if (!dialogueMenu) + actorsUpdate(); + + if (_settings->getNewScene() == -1 || _script->IsInsideScript() || _aiScripts->IsInsideScript()) { _sliceRenderer->setView(*_view); // Tick and draw all actors in current set - //int setId = _scene->_setId; + int setId = _scene->getSetId(); for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) { - //if (_actors[i]->getSetId() == setId) { - if (i == 0 || i == 23) { // Currently limited to McCoy and Officer Leroy - _actors[i]->tick(backgroundChanged); + if (_actors[i]->getSetId() == setId) { + if (i == 0 || i == 15 || i == 23) { // Currently limited to McCoy, Runciter and Officer Leroy + _actors[i]->tick(backgroundChanged); + } } } @@ -724,16 +730,30 @@ void BladeRunnerEngine::gameTick() { } - for (int i = 0; i < (int)_lights->_lights.size(); i++) { - Light *light = _lights->_lights[i]; - Matrix4x3 m = light->_matrix; - Vector3 pos = Vector3(m(0, 3), m(1, 3), m(2, 3)); +// for (int i = 0; i < (int)_lights->_lights.size(); i++) { +// Light *light = _lights->_lights[i]; +// Matrix4x3 m = light->_matrix; +// Vector3 pos = Vector3(m(0, 3), m(1, 3), m(2, 3)); +// Vector3 size = Vector3(5.0f, 5.0f, 5.0f); +// int colorR = (light->_color.r * 31.0f); +// int colorG = (light->_color.g * 31.0f); +// int colorB = (light->_color.b * 31.0f); +// int color = (colorR << 10) + (colorG << 5) + colorB; +// drawBBox(pos - size, pos + size, _view, &_surface2, color); +// } + + for(int i = 0; i < _waypoints->_count; i++) { + Waypoint *waypoint = &_waypoints->_waypoints[i]; + if(waypoint->_setId != _scene->getSetId()) + continue; + Vector3 pos = waypoint->_position; Vector3 size = Vector3(5.0f, 5.0f, 5.0f); - int colorR = (light->_color.r * 31.0f); - int colorG = (light->_color.g * 31.0f); - int colorB = (light->_color.b * 31.0f); - int color = (colorR << 10) + (colorG << 5) + colorB; + int color = 0b111111111111111; drawBBox(pos - size, pos + size, _view, &_surface2, color); + Vector3 spos = _view->calculateScreenPosition(pos); + char waypointText[40]; + sprintf(waypointText, "waypoint %i", i); + _mainFont->drawColor(waypointText, _surface2, spos.x, spos.y, color); } #endif @@ -745,6 +765,22 @@ void BladeRunnerEngine::gameTick() { } } +void BladeRunnerEngine::actorsUpdate() { + int actorCount = (int)_gameInfo->getActorCount(); + int setId = _scene->getSetId(); + + //TODO: original game updates every non-visible characters by updating only one character in one frame + if (setId != 89 || _gameVars[1] != 4 || _gameFlags->query(670) != 1 || !_aiScripts->IsInsideScript()) { + for (int i = 0; i < actorCount; i++) { + Actor *actor = _actors[i]; + if (actor->getSetId() == setId) { + _aiScripts->Update(i); + actor->countdownTimersUpdate(); + } + } + } +} + void BladeRunnerEngine::handleEvents() { if (shouldQuit()) { _gameIsRunning = false; diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 23ea88b43a..0aab57625b 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -155,6 +155,7 @@ public: void gameLoop(); void gameTick(); + void actorsUpdate(); void handleEvents(); void handleMouseClick(int x, int y); void handleMouseClickExit(int x, int y, int exitIndex); diff --git a/engines/bladerunner/gameflags.cpp b/engines/bladerunner/gameflags.cpp index db4271d9d5..0e04a1c49d 100644 --- a/engines/bladerunner/gameflags.cpp +++ b/engines/bladerunner/gameflags.cpp @@ -59,7 +59,7 @@ void GameFlags::reset(int flag) { } bool GameFlags::query(int flag) { - debug("GameFlags::query(%d): %d", flag, !!(flags[flag / 32] & (1 << (flag % 32)))); + //debug("GameFlags::query(%d): %d", flag, !!(flags[flag / 32] & (1 << (flag % 32)))); assert(flag >= 0 && flag <= flagCount); return !!(flags[flag / 32] & (1 << (flag % 32))); diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index fb656efac1..f8394e9318 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -39,7 +39,8 @@ MODULE_OBJS = \ scene.o \ scene_objects.o \ script/ai_00_mccoy.o \ - script/aiscript_officer_leroy.o \ + script/ai_15_runciter.o \ + script/ai_23_officer_leroy.o \ script/init.o \ script/kia.o \ script/vk.o \ diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp index bd74116566..702a1187f1 100644 --- a/engines/bladerunner/movement_track.cpp +++ b/engines/bladerunner/movement_track.cpp @@ -34,9 +34,9 @@ MovementTrack::~MovementTrack() { void MovementTrack::reset() { _currentIndex = -1; - _lastIndex = -1; - _hasNext = 0; - _paused = 0; + _lastIndex = 0; + _hasNext = false; + _paused = false; for (int i = 0; i < 100; i++) { _entries[i].waypointId = -1; _entries[i].delay = -1; @@ -49,9 +49,10 @@ int MovementTrack::append(int waypointId, int delay, int running) { return append(waypointId, delay, -1, running); } -int MovementTrack::append(int waypointId, int delay, int angle, int running) { - if (_lastIndex >= ARRAYSIZE(_entries)) +int MovementTrack::append(int waypointId, int delay, int angle, int running) { + if (_lastIndex >= 100) { return 0; + } _entries[_lastIndex].waypointId = waypointId; _entries[_lastIndex].delay = delay; @@ -59,7 +60,7 @@ int MovementTrack::append(int waypointId, int delay, int angle, int running) { _entries[_lastIndex].running = running; _lastIndex++; - _hasNext = 1; + _hasNext = true; _currentIndex = 0; return 1; } @@ -70,42 +71,39 @@ void MovementTrack::flush() { void MovementTrack::repeat() { _currentIndex = 0; - _hasNext = 1; + _hasNext = true; } -int MovementTrack::pause() { - _paused = 1; - return 1; +void MovementTrack::pause() { + _paused = true; } -int MovementTrack::unpause() { - _paused = 0; - return 1; +void MovementTrack::unpause() { + _paused = false; } -int MovementTrack::isPaused() { +bool MovementTrack::isPaused() { return _paused; } -int MovementTrack::hasNext() { +bool MovementTrack::hasNext() { return _hasNext; } -int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running) { - if (_currentIndex < _lastIndex && this->_hasNext) - { +bool MovementTrack::next(int *waypointId, int *delay, int *angle, int *running) { + if (_currentIndex < _lastIndex && _hasNext) { *waypointId = _entries[_currentIndex].waypointId; *delay = _entries[_currentIndex].delay; *angle = _entries[_currentIndex].angle; *running = _entries[_currentIndex++].running; - return 1; + return true; } else { *waypointId = -1; *delay = -1; *angle = -1; *running = 0; - _hasNext = 0; - return 0; + _hasNext = false; + return false; } } diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h index 450592210a..bffac4855a 100644 --- a/engines/bladerunner/movement_track.h +++ b/engines/bladerunner/movement_track.h @@ -43,8 +43,8 @@ class MovementTrack { private: int _currentIndex; int _lastIndex; - int _hasNext; - int _paused; + bool _hasNext; + bool _paused; MovementTrackEntry _entries[100]; void reset(); @@ -55,11 +55,11 @@ public: int append(int waypointId, int delay, int angle, int running); void flush(); void repeat(); - int pause(); - int unpause(); - int isPaused(); - int hasNext(); - int next(int *waypointId, int *delay, int *angle, int *running); + void pause(); + void unpause(); + bool isPaused(); + bool hasNext(); + bool next(int *waypointId, int *delay, int *angle, int *running); //int saveGame(); }; diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index c29a6345cc..abf0285660 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -108,7 +108,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) { _vm->_scene->advanceFrame(_vm->_surface1, _vm->_zBuffer1); _vm->_playerActor->setAtXYZ(_actorStartPosition, _actorStartFacing); - //_vm->_playerActor->setSetId(setId); + _vm->_playerActor->setSetId(setId); _vm->_script->SceneLoaded(); @@ -120,7 +120,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) { Actor *actor = _vm->_actors[i]; if (actor->getSetId() == setId) { _vm->_sceneObjects->addActor( - i, + i + SCENE_OBJECTS_ACTORS_OFFSET, actor->getBoundingBox(), actor->getScreenRectangle(), 1, @@ -251,14 +251,14 @@ bool Scene::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) { void Scene::objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded) { _set->objectSetIsClickable(objectId, isClickable); if (sceneLoaded) { - _vm->_sceneObjects->setIsClickable(objectId + 198, isClickable); + _vm->_sceneObjects->setIsClickable(objectId + SCENE_OBJECTS_OBJECTS_OFFSET, isClickable); } } void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath) { _set->objectSetIsObstacle(objectId, isObstacle); if (sceneLoaded) { - _vm->_sceneObjects->setIsObstacle(objectId + 198, isObstacle); + _vm->_sceneObjects->setIsObstacle(objectId + SCENE_OBJECTS_OBJECTS_OFFSET, isObstacle); if (updateWalkpath) { _vm->_sceneObjects->updateObstacles(); } @@ -270,7 +270,7 @@ void Scene::objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded) { for (i = 0; i < (int)_set->getObjectCount(); i++) { _set->objectSetIsObstacle(i, isObstacle); if (sceneLoaded) { - _vm->_sceneObjects->setIsObstacle(i + 198, isObstacle); + _vm->_sceneObjects->setIsObstacle(i + SCENE_OBJECTS_OBJECTS_OFFSET, isObstacle); } } } @@ -278,7 +278,7 @@ void Scene::objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded) { void Scene::objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded) { _set->objectSetIsTarget(objectId, isTarget); if (sceneLoaded) { - _vm->_sceneObjects->setIsTarget(objectId + 198, isTarget); + _vm->_sceneObjects->setIsTarget(objectId + SCENE_OBJECTS_OBJECTS_OFFSET, isTarget); } } diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp index c55097358d..b66467e859 100644 --- a/engines/bladerunner/scene_objects.cpp +++ b/engines/bladerunner/scene_objects.cpp @@ -86,7 +86,7 @@ bool SceneObjects::remove(int sceneObjectId) { if (i == -1) { return false; } - + _sceneObjects[i]._present = 0; int j; for (j = 0; j < _count; ++j) { if (_sceneObjectsSortedByDistance[j] == i) { @@ -107,7 +107,7 @@ int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, fl *isTarget = 0; for (int i = 0; i < _count; ++i) { - assert(_sceneObjectsSortedByDistance[i] < _count); + assert(_sceneObjectsSortedByDistance[i] < SCENE_OBJECTS_COUNT); SceneObject &sceneObject = _sceneObjects[_sceneObjectsSortedByDistance[i]]; @@ -171,8 +171,10 @@ bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5 int SceneObjects::findById(int sceneObjectId) { for (int i = 0; i < _count; ++i) { - if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) { - return i; + int j = this->_sceneObjectsSortedByDistance[i]; + + if (_sceneObjects[j]._present && _sceneObjects[j]._sceneObjectId == sceneObjectId) { + return j; } } return -1; diff --git a/engines/bladerunner/script/ai_00_mccoy.cpp b/engines/bladerunner/script/ai_00_mccoy.cpp index fa37efb63e..70f127213f 100644 --- a/engines/bladerunner/script/ai_00_mccoy.cpp +++ b/engines/bladerunner/script/ai_00_mccoy.cpp @@ -211,13 +211,13 @@ void AIScript_McCoy::ClickedByPlayer() { void AIScript_McCoy::EnteredScene(int sceneId) { } -void AIScript_McCoy::OtherAgentEnteredThisScene() { +void AIScript_McCoy::OtherAgentEnteredThisScene(int otherActorId) { } -void AIScript_McCoy::OtherAgentExitedThisScene() { +void AIScript_McCoy::OtherAgentExitedThisScene(int otherActorId) { } -void AIScript_McCoy::OtherAgentEnteredCombatMode() { +void AIScript_McCoy::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) { } void AIScript_McCoy::ShotAtAndMissed() { @@ -248,7 +248,8 @@ void AIScript_McCoy::Retired(int byActorId) { } } -void AIScript_McCoy::GetFriendlinessModifierIfGetsClue() { +int AIScript_McCoy::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) { + return 0; } bool AIScript_McCoy::GoalChanged(int currentGoalNumber, int newGoalNumber) { @@ -1660,10 +1661,12 @@ void AIScript_McCoy::SetAnimationState(int animationState, int a2, int a3, int a dword_46271C = a4; } -bool AIScript_McCoy::ReachedMovementTrackWaypoint() { +bool AIScript_McCoy::ReachedMovementTrackWaypoint(int waypointId) { return true; } +void AIScript_McCoy::FledCombat() {} + void AIScript_McCoy::sub_4053E0() { float x, y, z; Actor_Query_XYZ(0, &x, &y, &z); diff --git a/engines/bladerunner/script/ai_00_mccoy.h b/engines/bladerunner/script/ai_00_mccoy.h index eedae2f99b..2fda82f2de 100644 --- a/engines/bladerunner/script/ai_00_mccoy.h +++ b/engines/bladerunner/script/ai_00_mccoy.h @@ -54,19 +54,20 @@ public: void ReceivedClue(int clueId, int fromActorId); void ClickedByPlayer(); void EnteredScene(int sceneId); - void OtherAgentEnteredThisScene(); - void OtherAgentExitedThisScene(); - void OtherAgentEnteredCombatMode(); + void OtherAgentEnteredThisScene(int otherActorId); + void OtherAgentExitedThisScene(int otherActorId); + void OtherAgentEnteredCombatMode(int otherActorId, int combatMode); void ShotAtAndMissed(); void ShotAtAndHit(); void Retired(int byActorId); - void GetFriendlinessModifierIfGetsClue(); + int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId); bool GoalChanged(int currentGoalNumber, int newGoalNumber); bool UpdateAnimation(int *animation, int *frame); bool ChangeAnimationMode(int mode); void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4); void SetAnimationState(int animationState, int a2, int a3, int a4); - bool ReachedMovementTrackWaypoint(); + bool ReachedMovementTrackWaypoint(int a1); + void FledCombat(); private: void sub_4053E0(); diff --git a/engines/bladerunner/script/ai_15_runciter.cpp b/engines/bladerunner/script/ai_15_runciter.cpp new file mode 100644 index 0000000000..b26339b653 --- /dev/null +++ b/engines/bladerunner/script/ai_15_runciter.cpp @@ -0,0 +1,656 @@ +/* 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/script/ai_15_runciter.h" + +namespace BladeRunner { + +AIScript_Runciter::AIScript_Runciter(BladeRunnerEngine *vm) + : AIScriptBase(vm) {} + +void AIScript_Runciter::Initialize() { + var_45CD70_animation_state = 0; + var_45CD74_animation_frame = 0; + var_462800 = 0; + var_45CD78 = 0; + var_45CD7C = 6; + var_45CD80 = 1; + var_45CD84 = 0; + var_45CD88 = 0; + Actor_Set_Goal_Number(15, 0); +} + +bool AIScript_Runciter::Update() { + if (Actor_Query_Goal_Number(15) == 0 && Game_Flag_Query(186)) { + Actor_Set_Goal_Number(15, 2); + } + if (Global_Variable_Query(1) == 4 && Actor_Query_Goal_Number(15) < 300) { + Actor_Set_Goal_Number(15, 300); + } + return false; +} + +void AIScript_Runciter::TimerExpired(int timer) {} + +void AIScript_Runciter::CompletedMovementTrack() { + if (Actor_Query_Goal_Number(15) == 1) { + if (Player_Query_Current_Scene() == 79) { + switch (Random_Query(1, 5)) { + case 2: + case 3: + ADQ_Add(15, 530, -1); + break; + case 1: + case 5: + ADQ_Add(15, 80, -1); + break; + case 4: + ADQ_Add(15, 930, -1); + break; + } + } + Actor_Set_Goal_Number(15, 99); + Actor_Set_Goal_Number(15, 1); + //return true; + } + //return false; +} + +void AIScript_Runciter::ReceivedClue(int clueId, int fromActorId) {} + +void AIScript_Runciter::ClickedByPlayer() {} + +void AIScript_Runciter::EnteredScene(int sceneId) {} + +void AIScript_Runciter::OtherAgentEnteredThisScene(int otherActorId) {} + +void AIScript_Runciter::OtherAgentExitedThisScene(int otherActorId) {} + +void AIScript_Runciter::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) { + if (Actor_Query_Goal_Number(15) == 300 && combatMode == 1 && !Game_Flag_Query(705)) { + Actor_Set_Targetable(15, true); + Actor_Face_Actor(15, 0, true); + Actor_Says(15, 420, 12); + Actor_Face_Actor(0, 15, true); + Actor_Change_Animation_Mode(0, 5); + if (Actor_Clue_Query(0, 158)) { + Actor_Says(0, 4770, -1); + Actor_Says(15, 590, 13); + Actor_Says(0, 4775, -1); + Actor_Says(15, 600, 17); + Sound_Play(492, 100, 0, 100, 50); + Actor_Says(0, 4780, -1); + Actor_Says(15, 610, 18); + Actor_Says(0, 4785, -1); + Actor_Says(15, 620, 15); + if (Game_Flag_Query(46)) { + Actor_Says(15, 630, 12); + Actor_Says(15, 640, 17); + Actor_Says(0, 4790, -1); + Actor_Says(15, 650, 18); + Actor_Says(15, 660, 19); + Actor_Clue_Acquire(0, 280, 1, 15); + } else { + Actor_Says(15, 670, 18); + Actor_Says(0, 4795, -1); + Actor_Says(15, 730, 17); + } + } else if (Actor_Clue_Query(0, 76)) { + Actor_Says(0, 4730, -1); + Actor_Says(15, 480, 17); + Actor_Says(0, 4735, -1); + Actor_Says(15, 490, 16); + Sound_Play(492, 100, 0, 100, 50); + Actor_Says(0, 4740, -1); + Actor_Says(15, 500, 18); + Actor_Says(15, 510, 19); + Actor_Says(0, 4745, -1); + Actor_Says(0, 4750, -1); + Actor_Says(15, 520, 17); + Actor_Says(15, 530, 18); + Actor_Says(15, 540, 16); + } + Game_Flag_Set(705); + } +} + +void AIScript_Runciter::ShotAtAndMissed() {} + +void AIScript_Runciter::ShotAtAndHit() { + Actor_Set_Targetable(15, false); + Actor_Change_Animation_Mode(15, 48); + Actor_Set_Goal_Number(15, 599); + Delay(2000); + if (Actor_Clue_Query(0, 158)) { + Actor_Voice_Over(2050, 99); + Actor_Voice_Over(2060, 99); + } else { + Actor_Voice_Over(2070, 99); + Actor_Voice_Over(2080, 99); + Actor_Voice_Over(2090, 99); + } + Actor_Modify_Friendliness_To_Other(5, 0, 3); +} + +void AIScript_Runciter::Retired(int byActorId) {} + +int AIScript_Runciter::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) { + return 0; +} + +bool AIScript_Runciter::GoalChanged(int currentGoalNumber, int newGoalNumber) { + if (newGoalNumber == 0) { + Actor_Put_In_Set(15, 16); + Actor_Set_At_Waypoint(15, 92, 567); + return false; + } + if (newGoalNumber == 1) { + AI_Movement_Track_Flush(15); + if (Random_Query(0, 1) == 1) { + if (Random_Query(0, 1) == 0) { + AI_Movement_Track_Append_With_Facing(15, 89, Random_Query(6, 10), 567); + } + AI_Movement_Track_Append_With_Facing(15, 93, Random_Query(2, 6), 1002); + AI_Movement_Track_Append(15, 92, 5); + } else { + AI_Movement_Track_Append_With_Facing(15, 91, Random_Query(3, 10), 120); + if (Random_Query(1, 3) == 1) { + AI_Movement_Track_Append_With_Facing(15, 93, Random_Query(2, 6), 1002); + } + AI_Movement_Track_Append_With_Facing(15, 90, Random_Query(5, 10), 170); + } + AI_Movement_Track_Repeat(15); + return true; + } + if (newGoalNumber == 2) { + AI_Movement_Track_Flush(15); + AI_Movement_Track_Append(15, 39, 120); + AI_Movement_Track_Append(15, 40, 0); + AI_Movement_Track_Repeat(15); + return false; + } + if (newGoalNumber == 300) { + Actor_Put_In_Set(15, 16); + Actor_Set_At_Waypoint(15, 93, 1007); + return false; + } + return false; +} + +bool AIScript_Runciter::UpdateAnimation(int *animation, int *frame) { + + switch (var_45CD70_animation_state) { + case 15: + *animation = 528; + var_45CD74_animation_frame = Slice_Animation_Query_Number_Of_Frames(528) - 1; + *frame = var_45CD74_animation_frame; + break; + case 14: + *animation = 528; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(528) - 1) { + *animation = 528; + var_45CD70_animation_state = 15; + } + *frame = var_45CD74_animation_frame; + break; + case 13: + if (var_45CD78 == 0) { + var_45CD74_animation_frame = 0; + var_45CD70_animation_state = var_462800; + *animation = var_462804; + } else if (var_45CD78 == 1) { + *animation = 530; + var_45CD74_animation_frame += 3; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(530)) { + var_45CD74_animation_frame = 0; + var_45CD70_animation_state = var_462800; + *animation = var_462804; + } + } else if (var_45CD78 == 2) { + *animation = 531; + var_45CD74_animation_frame -= 3; + if (var_45CD74_animation_frame - 3 < 0) { + var_45CD74_animation_frame = 0; + var_45CD70_animation_state = var_462800; + *animation = var_462804; + } + } + *frame = var_45CD74_animation_frame; + break; + case 12: + *animation = 532; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(532)) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD74_animation_frame = 0; + var_45CD78 = 0; + Actor_Change_Animation_Mode(15, 0); + } + *frame = var_45CD74_animation_frame; + break; + case 11: + *animation = 541; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(541)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 10: + *animation = 540; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(540)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 9: + *animation = 539; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(539)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 8: + *animation = 538; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(538)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 7: + *animation = 537; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(537)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 6: + *animation = 536; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(536)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 5: + *animation = 535; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(535)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 4: + *animation = 534; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(534)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + *animation = 533; + var_45CD70_animation_state = 2; + } + } + *frame = var_45CD74_animation_frame; + break; + case 2: + *animation = 533; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(533)) { + var_45CD74_animation_frame = 0; + if (var_45CD88) { + *animation = 529; + var_45CD70_animation_state = 0; + var_45CD78 = 0; + } else { + var_45CD70_animation_state = 4; + } + } + *frame = var_45CD74_animation_frame; + break; + case 1: + *animation = 526; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(526)) { + var_45CD74_animation_frame = 0; + } + *frame = var_45CD74_animation_frame; + break; + case 0: + if (var_45CD78 == 0) { + *animation = 529; + if (var_45CD84) { + var_45CD84--; + } else { + var_45CD74_animation_frame += var_45CD80; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(529)) { + var_45CD74_animation_frame = 0; + } + if (var_45CD74_animation_frame < 0) { + var_45CD74_animation_frame = Slice_Animation_Query_Number_Of_Frames(529) - 1; + } + --var_45CD7C; + if (var_45CD7C == 0) { + var_45CD80 = 2 * Random_Query(0, 1) - 1; + var_45CD7C = Random_Query(6, 14); + var_45CD84 = Random_Query(0, 4); + } + if (var_45CD74_animation_frame == 0) { + if (Random_Query(0, 1) == 1) { + var_45CD78 = Random_Query(1, 2); + var_45CD80 = 1; + var_45CD84 = 0; + } + } + } + } else if (var_45CD78 == 1) { + *animation = 530; + var_45CD74_animation_frame++; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(530)) { + var_45CD74_animation_frame = 0; + var_45CD78 = 0; + *animation = 529; + var_45CD7C = Random_Query(6, 14); + var_45CD80 = 2 * Random_Query(0, 1) - 1; + } + } else if (var_45CD78 == 2) { + *animation = 531; + if (var_45CD84) { + var_45CD84--; + } else { + var_45CD74_animation_frame += var_45CD80; + if (var_45CD74_animation_frame >= Slice_Animation_Query_Number_Of_Frames(*animation) - 1) { + var_45CD84 = Random_Query(5, 15); + var_45CD80 = -1; + } + if (var_45CD74_animation_frame <= 0) { + var_45CD74_animation_frame = 0; + var_45CD78 = 0; + *animation = 529; + var_45CD7C = Random_Query(6, 14); + var_45CD80 = 2 * Random_Query(0, 1) - 1; + } + } + } + *frame = var_45CD74_animation_frame; + break; + default: + *animation = 399; + var_45CD74_animation_frame = 0; + *frame = var_45CD74_animation_frame; + break; + } + return true; +} + +bool AIScript_Runciter::ChangeAnimationMode(int mode) { + + switch (mode) { + case 23: + var_45CD70_animation_state = 12; + var_45CD74_animation_frame = 0; + break; + case 19: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 11; + var_462804 = 541; + } + var_45CD88 = 0; + break; + case 18: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 10; + var_462804 = 540; + } + var_45CD88 = 0; + break; + case 17: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 9; + var_462804 = 539; + } + var_45CD88 = 0; + break; + case 16: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 8; + var_462804 = 538; + } + var_45CD88 = 0; + break; + case 15: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 7; + var_462804 = 537; + } + var_45CD88 = 0; + break; + case 14: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 6; + var_462804 = 536; + } + var_45CD88 = 0; + break; + case 13: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 5; + var_462804 = 535; + } + var_45CD88 = 0; + break; + case 12: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 4; + var_462804 = 534; + } + var_45CD88 = 0; + break; + case 3: + if (var_45CD70_animation_state) { + var_45CD70_animation_state = 2; + var_45CD74_animation_frame = 0; + } else { + var_45CD70_animation_state = 13; + var_462800 = 2; + var_462804 = 526; + } + var_45CD88 = 0; + break; + case 1: + if (var_45CD70_animation_state > 1) { + var_45CD70_animation_state = 1; + var_45CD74_animation_frame = 0; + } else if (!var_45CD70_animation_state) { + var_45CD70_animation_state = 13; + var_462800 = 1; + var_462804 = 526; + } + break; + case 0: + if (var_45CD70_animation_state >= 2 && var_45CD70_animation_state <= 11) { + var_45CD88 = 1; + } else { + var_45CD70_animation_state = 0; + var_45CD74_animation_frame = 0; + var_45CD78 = 0; + } + break; + case 2: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 20: + case 21: + case 22: + break; + default: + if (mode == 48) { + var_45CD70_animation_state = 14; + var_45CD74_animation_frame = 0; + } + break; + } + return true; +} + +void AIScript_Runciter::QueryAnimationState(int *animationState, int *animationFrame, int *a3, int *a4) { + *animationState = var_45CD70_animation_state; + *animationFrame = var_45CD74_animation_frame; + *a3 = var_462800; + *a4 = var_462804; +} + +void AIScript_Runciter::SetAnimationState(int animationState, int animationFrame, int a3, int a4) { + var_45CD70_animation_state = animationState; + var_45CD74_animation_frame = animationFrame; + var_462800 = a3; + var_462804 = a4; +} + +bool AIScript_Runciter::ReachedMovementTrackWaypoint(int waypointId) { + switch (waypointId) { + case 93: + Actor_Face_Heading(15, 1002, true); + break; + case 92: + Actor_Face_Heading(15, 664, true); + break; + case 91: + Actor_Face_Heading(15, 120, true); + break; + case 90: + Actor_Face_Heading(15, 170, true); + break; + case 89: + Actor_Face_Heading(15, 567, true); + break; + default: + return true; + } + return true; +} + +void AIScript_Runciter::FledCombat() {} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/script/ai_15_runciter.h b/engines/bladerunner/script/ai_15_runciter.h new file mode 100644 index 0000000000..b2cb70d2f8 --- /dev/null +++ b/engines/bladerunner/script/ai_15_runciter.h @@ -0,0 +1,65 @@ +/* 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/script/script.h" + +#include "bladerunner/bladerunner.h" + +namespace BladeRunner { + +class AIScript_Runciter : public AIScriptBase { + int var_45CD70_animation_state; + int var_45CD74_animation_frame; + int var_462800; + int var_462804; + int var_45CD78; + int var_45CD7C; + int var_45CD80; + int var_45CD84; + int var_45CD88; +public: + AIScript_Runciter(BladeRunnerEngine *vm); + + void Initialize(); + bool Update(); + void TimerExpired(int timer); + void CompletedMovementTrack(); + void ReceivedClue(int clueId, int fromActorId); + void ClickedByPlayer(); + void EnteredScene(int sceneId); + void OtherAgentEnteredThisScene(int otherActorId); + void OtherAgentExitedThisScene(int otherActorId); + void OtherAgentEnteredCombatMode(int otherActorId, int combatMode); + void ShotAtAndMissed(); + void ShotAtAndHit(); + void Retired(int byActorId); + int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId); + bool GoalChanged(int currentGoalNumber, int newGoalNumber); + bool UpdateAnimation(int *animation, int *frame); + bool ChangeAnimationMode(int mode); + void QueryAnimationState(int *animationState, int *animationFrame, int *a3, int *a4); + void SetAnimationState(int animationState, int animationFrame, int a3, int a4); + bool ReachedMovementTrackWaypoint(int a1); + void FledCombat(); +}; + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/script/ai_23_officer_leroy.cpp b/engines/bladerunner/script/ai_23_officer_leroy.cpp new file mode 100644 index 0000000000..8f97466a8a --- /dev/null +++ b/engines/bladerunner/script/ai_23_officer_leroy.cpp @@ -0,0 +1,1217 @@ +/* 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/script/ai_23_officer_leroy.h" + +namespace BladeRunner { + +AIScript_Officer_Leroy::AIScript_Officer_Leroy(BladeRunnerEngine *vm) + : AIScriptBase(vm), var_45D5B0_animation_state(0), var_45D5B4_animation_frame(0), var_45D5B8(0), var_45D5BC(0), var_462880(0), var_462884(0) {} + +void AIScript_Officer_Leroy::Initialize() { + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + var_462880 = 0; + var_45D5B8 = 0; + var_45D5BC = 0; + + Actor_Put_In_Set(23, 69); + Actor_Set_At_XYZ(23, -261.80f, 6.00f, 79.58f, 512); + Actor_Set_Goal_Number(23, 0); + Actor_Set_Frame_Rate_FPS(23, 8); +} + +bool AIScript_Officer_Leroy::Update() { + if (Global_Variable_Query(1) == 4 && Actor_Query_Goal_Number(23) < 300) { + AI_Movement_Track_Flush(23); + Actor_Set_Goal_Number(23, 300); + } else if (Global_Variable_Query(1) == 5 && Actor_Query_Goal_Number(23) < 400) { + AI_Movement_Track_Flush(23); + Actor_Set_Goal_Number(23, 400); + } else if (!Game_Flag_Query(182) && Game_Flag_Query(147) == 1 && Game_Flag_Query(163) == 1 && Player_Query_Current_Scene() != 78 && Global_Variable_Query(1) < 3) { + Game_Flag_Set(186); + Actor_Set_Goal_Number(23, 3); + } else if (Actor_Query_Goal_Number(23) != 1 && Actor_Query_Goal_Number(23) != 2 && Game_Flag_Query(199) == 1) { + Game_Flag_Reset(199); + } else if (Global_Variable_Query(15) > 4 && !Actor_Clue_Query(23, 239)) { + Actor_Clue_Acquire(23, 239, 1, -1); + } else if (Game_Flag_Query(629) == 1) { + Game_Flag_Reset(629); + } else if (Game_Flag_Query(623) == 1 && !Game_Flag_Query(664)) { + Game_Flag_Set(664); + Actor_Set_Goal_Number(23, 305); + } else if (Actor_Query_Goal_Number(23) == 310 && Actor_Query_Which_Set_In(23) != Player_Query_Current_Set()) { + Non_Player_Actor_Combat_Mode_Off(23); + Actor_Set_Goal_Number(23, 305); + } else if (Actor_Query_Goal_Number(23) == 599 && Actor_Query_Which_Set_In(23) != Player_Query_Current_Set()) { + Actor_Set_Health(23, 40, 40); + Actor_Set_Goal_Number(23, 305); + } else if (Actor_Query_Goal_Number(23) == 305) { + switch (Actor_Query_Which_Set_In(23)) { + case 7: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 0, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 20: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 1, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 33: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 5, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 53: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 7, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 54: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 3, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 70: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 18, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 74: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 11, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 77: + case 78: + case 79: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 10, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 81: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 13, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 83: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 84: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 16, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + case 86: + if (Actor_Query_Which_Set_In(23) == Player_Query_Current_Set()) { + Actor_Set_Goal_Number(23, 310); + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 17, 4, 7, 8, -1, -1, -1, 10, 300, 0); + } + break; + } + } + return false; +} + +void AIScript_Officer_Leroy::TimerExpired(int timer) { + if (timer == 1) { + AI_Countdown_Timer_Reset(23, 1); + if (Actor_Query_In_Set(0, 41)) { + Actor_Set_Goal_Number(23, 430); + Actor_Set_Goal_Number(24, 430); + } else { + Game_Flag_Set(684); + } + } else if (timer == 2) { + AI_Countdown_Timer_Reset(23, 2); + sub_431420(); + } +} + +void AIScript_Officer_Leroy::CompletedMovementTrack() { + int v0; + unsigned int v1; + + v0 = Actor_Query_Goal_Number(23); + if (v0 == 1) { + Actor_Set_Goal_Number(23, 2); + return; + } + //todo: tidyup + v1 = v0 - 305; + if (v1 > 3) { + return; + } + if (!v1) { + Actor_Set_Goal_Number(23, 306); + return; + } + if (v1 != 2) { + if (v1 == 3) { + Actor_Change_Animation_Mode(23, 4); + Actor_Face_Actor(23, 0, true); + Actor_Set_Goal_Number(23, 309); + } + return; + } + Non_Player_Actor_Combat_Mode_On(23, 0, 1, 0, 12, 4, 7, 8, 0, -1, -1, 15, 300, 0); +} + +void AIScript_Officer_Leroy::ReceivedClue(int clueId, int fromActorId) { + if (clueId == 222) { + Actor_Modify_Friendliness_To_Other(23, 0, 5); + } + if (clueId == 215) { + Actor_Modify_Friendliness_To_Other(23, 0, -4); + } +} + +void AIScript_Officer_Leroy::ClickedByPlayer() {} + +void AIScript_Officer_Leroy::EnteredScene(int sceneId) {} + +void AIScript_Officer_Leroy::OtherAgentEnteredThisScene(int otherActorId) {} + +void AIScript_Officer_Leroy::OtherAgentExitedThisScene(int otherActorId) {} + +void AIScript_Officer_Leroy::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {} + +void AIScript_Officer_Leroy::ShotAtAndMissed() {} + +void AIScript_Officer_Leroy::ShotAtAndHit() { + if (Actor_Query_Goal_Number(23) == 307) { + Actor_Set_Health(23, 50, 50); + } +} + +void AIScript_Officer_Leroy::Retired(int byActorId) { + Actor_Set_Goal_Number(23, 599); + Game_Flag_Set(607); +} + +int AIScript_Officer_Leroy::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) { + if (otherActorId) { + return 0; + } + switch (clueId) { + case 242: + return -6; + case 240: + return -2; + case 239: + return -5; + case 228: + return 2; + case 227: + return 4; + case 226: + return 4; + case 225: + return 3; + case 224: + return 3; + case 223: + return 2; + case 222: + return 3; + case 215: + return -5; + } + return 0; +} + +bool AIScript_Officer_Leroy::GoalChanged(int currentGoalNumber, int newGoalNumber) { + switch (newGoalNumber) { + case 1: + AI_Movement_Track_Flush(23); + if (Random_Query(1, 2) == 1) { + AI_Movement_Track_Append(23, 57, 7); + AI_Movement_Track_Append(23, 58, 7); + } else { + AI_Movement_Track_Append(23, 58, 7); + AI_Movement_Track_Append(23, 57, 7); + } + AI_Movement_Track_Repeat(23); + return true; + case 2: + if (Random_Query(1, 3) == 1) { + if (Random_Query(1, 2) == 1 && !Actor_Clue_Query(23, 16)) { + Actor_Clue_Acquire(23, 16, 0, -1); + } else if (!Actor_Clue_Query(23, 17)) { + Actor_Clue_Acquire(23, 17, 0, -1); + } + } + if (Game_Flag_Query(182)) { + if (Actor_Clue_Query(23, 16) && Actor_Clue_Query(23, 17)) { + Actor_Set_Goal_Number(23, 0); + } else { + Actor_Set_Goal_Number(23, 1); + } + } else { + Actor_Set_Goal_Number(23, 0); + } + return true; + case 3: + AI_Movement_Track_Flush(23); + AI_Movement_Track_Append(23, 39, Random_Query(120, 240)); + AI_Movement_Track_Append(23, 35, 0); + AI_Movement_Track_Repeat(23); + return true; + case 99: + AI_Movement_Track_Flush(23); + return false; + case 102: + AI_Movement_Track_Flush(23); + AI_Movement_Track_Append(23, 107, 0); + AI_Movement_Track_Append(23, 108, 0); + AI_Movement_Track_Repeat(23); + return true; + case 300: + Actor_Set_Goal_Number(23, 305); + return true; + case 305: + AI_Movement_Track_Flush(23); + switch (Random_Query(1, 10)) { + case 1: + AI_Movement_Track_Append(23, 398, 15); + AI_Movement_Track_Append(23, 399, 0); + AI_Movement_Track_Append(23, 400, 0); + AI_Movement_Track_Append(23, 401, 0); + AI_Movement_Track_Append_With_Facing(23, 402, 3, 276); + AI_Movement_Track_Append(23, 403, 0); + AI_Movement_Track_Append(23, 404, 15); + AI_Movement_Track_Repeat(23); + break; + case 2: + AI_Movement_Track_Append(23, 385, 10); + AI_Movement_Track_Append(23, 242, 2); + AI_Movement_Track_Append(23, 386, 2); + AI_Movement_Track_Append(23, 387, 15); + AI_Movement_Track_Repeat(23); + break; + case 3: + AI_Movement_Track_Append(23, 390, 10); + AI_Movement_Track_Append(23, 391, 0); + AI_Movement_Track_Append(23, 392, 5); + AI_Movement_Track_Append(23, 345, 0); + AI_Movement_Track_Append(23, 393, 15); + AI_Movement_Track_Repeat(23); + break; + case 4: + AI_Movement_Track_Append(23, 381, 15); + AI_Movement_Track_Append(23, 382, 0); + AI_Movement_Track_Append(23, 383, 15); + AI_Movement_Track_Append(23, 382, 3); + AI_Movement_Track_Append(23, 384, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 5: + AI_Movement_Track_Append(23, 388, 10); + AI_Movement_Track_Append(23, 389, 10); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 6: + AI_Movement_Track_Append(23, 385, 10); + AI_Movement_Track_Append(23, 242, 2); + AI_Movement_Track_Append(23, 386, 2); + AI_Movement_Track_Append(23, 387, 15); + AI_Movement_Track_Repeat(23); + break; + case 7: + AI_Movement_Track_Append(23, 394, 15); + AI_Movement_Track_Append(23, 395, 0); + AI_Movement_Track_Append(23, 396, 0); + AI_Movement_Track_Append(23, 397, 15); + AI_Movement_Track_Append(23, 396, 0); + AI_Movement_Track_Append(23, 395, 0); + AI_Movement_Track_Append(23, 430, 15); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 8: + switch (Random_Query(1, 7)) { + case 1: + AI_Movement_Track_Append(23, 302, 0); + AI_Movement_Track_Append(23, 407, 0); + AI_Movement_Track_Append(23, 408, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 2: + AI_Movement_Track_Append(23, 536, 0); + AI_Movement_Track_Append(23, 537, 0); + AI_Movement_Track_Append(23, 538, 1); + AI_Movement_Track_Append(23, 537, 0); + AI_Movement_Track_Append(23, 536, 0); + AI_Movement_Track_Repeat(23); + break; + case 3: + AI_Movement_Track_Append(23, 296, 10); + AI_Movement_Track_Append(23, 409, 2); + AI_Movement_Track_Append(23, 296, 10); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 4: + AI_Movement_Track_Append(23, 411, 10); + AI_Movement_Track_Append(23, 412, 5); + AI_Movement_Track_Append(23, 411, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 5: + AI_Movement_Track_Append(23, 413, 10); + AI_Movement_Track_Append(23, 414, 0); + AI_Movement_Track_Append_With_Facing(23, 431, 0, 1017); + AI_Movement_Track_Append(23, 432, 10); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 6: + AI_Movement_Track_Append(23, 415, 0); + AI_Movement_Track_Append_With_Facing(23, 416, 0, 620); + AI_Movement_Track_Append(23, 417, 0); + AI_Movement_Track_Append(23, 418, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + break; + case 7: + AI_Movement_Track_Append(23, 405, 10); + AI_Movement_Track_Append(23, 406, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + return false; + default: + return false; + } + //no break + case 9: + if (Random_Query(1, 2) - 1 == 1) { + AI_Movement_Track_Append(23, 433, 10); + AI_Movement_Track_Append(23, 434, 0); + AI_Movement_Track_Append(23, 435, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + return false; + } + AI_Movement_Track_Append(23, 420, 10); + AI_Movement_Track_Append(23, 422, 2); + AI_Movement_Track_Append(23, 421, 1); + AI_Movement_Track_Append_With_Facing(23, 422, 4, 182); + AI_Movement_Track_Append(23, 420, 10); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + //no break + case 10: + AI_Movement_Track_Append(23, 310, 0); + AI_Movement_Track_Append(23, 307, 0); + AI_Movement_Track_Append(23, 309, 0); + AI_Movement_Track_Append(23, 310, 0); + AI_Movement_Track_Append(23, 35, 30); + AI_Movement_Track_Repeat(23); + return false; + default: + return false; + } + //no break + case 306: + Actor_Set_Goal_Number(23, 305); + return true; + case 307: + AI_Movement_Track_Flush(23); + AI_Movement_Track_Append_With_Facing(23, 416, 0, 556); + Actor_Change_Animation_Mode(23, 4); + AI_Movement_Track_Repeat(23); + return true; + case 308: + AI_Movement_Track_Flush(23); + AI_Movement_Track_Append_Run_With_Facing(23, 440, 2, 355); + AI_Movement_Track_Append_Run_With_Facing(23, 441, 0, 825); + AI_Movement_Track_Repeat(23); + return true; + case 400: + AI_Movement_Track_Flush(23); + AI_Movement_Track_Append(23, 35, 0); + AI_Movement_Track_Repeat(23); + Actor_Set_Goal_Number(23, 410); + return true; + case 420: + AI_Countdown_Timer_Reset(23, 1); + AI_Countdown_Timer_Start(23, 1, 120); + Actor_Set_Goal_Number(23, 410); + return true; + case 425: + AI_Countdown_Timer_Reset(23, 1); + AI_Countdown_Timer_Start(23, 1, 60); + Actor_Set_Goal_Number(23, 410); + return true; + case 430: + Actor_Set_Goal_Number(23, 410); + Actor_Set_Goal_Number(24, 410); + return false; + default: + return false; + } +} + +bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame) { + int v57; + int a1; + + switch (var_45D5B0_animation_state) { + case 32: + *animation = 603; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(603)) { + *animation = 589; + var_45D5B0_animation_state = 0; + var_45D5B8 = 0; + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 31: + *animation = 604; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(604)) { + *animation = 601; + var_45D5B0_animation_state = 1; + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 30: + *animation = 587; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(587)) { + *animation = 589; + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + Actor_Change_Animation_Mode(23, 0); + } + *frame = var_45D5B4_animation_frame; + return true; + case 29: + *animation = 586; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(586)) { + *animation = 589; + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + Actor_Change_Animation_Mode(23, 0); + } + *frame = var_45D5B4_animation_frame; + return true; + case 28: + *animation = 576; + if (var_45D5B4_animation_frame < Slice_Animation_Query_Number_Of_Frames(576) - 1) { + ++var_45D5B4_animation_frame; + } + *frame = var_45D5B4_animation_frame; + return true; + case 27: + *animation = 588; + if (var_45D5B4_animation_frame < Slice_Animation_Query_Number_Of_Frames(588) - 1) { + ++var_45D5B4_animation_frame; + } + *frame = var_45D5B4_animation_frame; + return true; + case 26: + *animation = 573; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(573)) { + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + *animation = 571; + Actor_Change_Animation_Mode(23, 4); + } + *frame = var_45D5B4_animation_frame; + return true; + case 25: + *animation = 572; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(572)) { + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + *animation = 571; + Actor_Change_Animation_Mode(23, 4); + } + *frame = var_45D5B4_animation_frame; + return true; + case 24: + *animation = 581; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame == 4) { + if (Random_Query(1, 2) == 1) { + Sound_Play_Speech_Line(23, 9010, 75, 0, 99); + } else { + Sound_Play_Speech_Line(23, 9015, 75, 0, 99); + } + } + if (var_45D5B4_animation_frame == 5) { + Actor_Combat_AI_Hit_Attempt(23); + } + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(581)) { + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + *animation = 571; + Actor_Change_Animation_Mode(23, 4); + } + *frame = var_45D5B4_animation_frame; + return true; + case 23: + *animation = 580; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(580)) { + *animation = 589; + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 22: + *animation = 579; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(579)) { + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + *animation = 571; + } + *frame = var_45D5B4_animation_frame; + return true; + case 21: + *animation = 571; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(571)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 20: + *animation = 571; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame > Slice_Animation_Query_Number_Of_Frames(571) - 1) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 19: + *animation = 600; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(600)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 18: + *animation = 599; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(599)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 17: + *animation = 598; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(598)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 16: + *animation = 597; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(597)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 15: + *animation = 596; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(596)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 14: + *animation = 595; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(595)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 13: + *animation = 594; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(594)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 12: + *animation = 593; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(593)) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + *animation = 592; + } + *frame = var_45D5B4_animation_frame; + return true; + case 11: + if (var_45D5BC && var_45D5B4_animation_frame <= 2) { + var_45D5BC = 0; + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + *animation = 589; + var_45D5B8 = Random_Query(0, 1); + *frame = var_45D5B4_animation_frame; + return true; + } + + *animation = 592; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(592)) { + var_45D5B4_animation_frame = 0; + if (var_45D5BC) { + var_45D5BC = 0; + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + *animation = 589; + var_45D5B8 = Random_Query(0, 1); + } else { + var_45D5B0_animation_state = Random_Query(0, 8) + 11; + } + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 10: + *animation = 578; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(578)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 9: + *animation = 577; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(577)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 8: + *animation = 575; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(575)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 7: + *animation = 574; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(574)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 6: + *animation = 585; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(585)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 5: + *animation = 584; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(584)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 4: + *animation = 583; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(583)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 3: + *animation = 582; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(582)) { + var_45D5B4_animation_frame = 0; + } + *frame = var_45D5B4_animation_frame; + return true; + case 2: + if (Game_Flag_Query(199)) { + *animation = 603; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame > Slice_Animation_Query_Number_Of_Frames(603) - 1) { + Game_Flag_Reset(199); + var_45D5B4_animation_frame = 0; + var_45D5B0_animation_state = var_462880; + *animation = var_462884; + } + } else { + if (var_45D5B8 == 0) { + *animation = 589; + } + if (var_45D5B8 == 1) { + *animation = 590; + } + if (var_45D5B8 == 2) { + *animation = 591; + } + if (var_45D5B4_animation_frame > Slice_Animation_Query_Number_Of_Frames(*animation) / 2) { + a1 = *animation; + var_45D5B4_animation_frame += 3; + v57 = var_45D5B4_animation_frame; + if (v57 > Slice_Animation_Query_Number_Of_Frames(a1) - 1) { + var_45D5B4_animation_frame = 0; + var_45D5B0_animation_state = var_462880; + *animation = var_462884; + } + } else { + var_45D5B4_animation_frame -= 3; + if (var_45D5B4_animation_frame < 0) { + var_45D5B4_animation_frame = 0; + var_45D5B0_animation_state = var_462880; + *animation = var_462884; + } + } + } + *frame = var_45D5B4_animation_frame; + return true; + case 1: + *animation = 601; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(601)) { + var_45D5B4_animation_frame = 0; + } + if (!Game_Flag_Query(199)) { + var_45D5B0_animation_state = 32; + var_45D5B4_animation_frame = 0; + *animation = 603; + } + *frame = var_45D5B4_animation_frame; + return true; + case 0: + if (Game_Flag_Query(199) && !Game_Flag_Query(392)) { + var_45D5B0_animation_state = 31; + var_45D5B4_animation_frame = 0; + *animation = 604; + } else if (var_45D5B8 == 1) { + *animation = 590; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(590)) { + var_45D5B8 = Random_Query(0, 2); + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B8 == 2) { + *animation = 591; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(591)) { + var_45D5B8 = Random_Query(0, 2); + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B8 == 0) { + *animation = 589; + var_45D5B4_animation_frame++; + if (var_45D5B4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(589)) { + var_45D5B8 = Random_Query(0, 2); + var_45D5B4_animation_frame = 0; + } + } + *frame = var_45D5B4_animation_frame; + return true; + default: + *animation = 399; + *frame = var_45D5B4_animation_frame; + return true; + } +} + +bool AIScript_Officer_Leroy::ChangeAnimationMode(int mode) { + int v1; + + switch (mode) { + case 28: + Game_Flag_Set(199); + break; + case 27: + Game_Flag_Reset(199); + break; + case 22: + if (Random_Query(0, 1)) { + var_45D5B0_animation_state = 25; + } else { + var_45D5B0_animation_state = 26; + } + var_45D5B4_animation_frame = 0; + break; + case 21: + if (var_45D5B0_animation_state == 21 || var_45D5B0_animation_state == 24) { + if (Random_Query(0, 1)) { + var_45D5B0_animation_state = 25; + } else { + var_45D5B0_animation_state = 26; + } + var_45D5B4_animation_frame = 0; + } else { + if (Random_Query(0, 1)) { + var_45D5B0_animation_state = 29; + } else { + var_45D5B0_animation_state = 30; + } + var_45D5B4_animation_frame = 0; + } + break; + case 19: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 19; + var_462884 = 600; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 19; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 18: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 18; + var_462884 = 599; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 18; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 17: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 17; + var_462884 = 598; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 17; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 16: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 16; + var_462884 = 597; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 16; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 15: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 15; + var_462884 = 596; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 15; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 14: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 14; + var_462884 = 595; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 14; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 13: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 13; + var_462884 = 594; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 13; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 12: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 12; + var_462884 = 593; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 12; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 8: + var_45D5B0_animation_state = 8; + var_45D5B4_animation_frame = 0; + break; + case 7: + var_45D5B0_animation_state = 7; + var_45D5B4_animation_frame = 0; + break; + case 6: + var_45D5B0_animation_state = 24; + var_45D5B4_animation_frame = 0; + break; + case 4: + switch (var_45D5B0_animation_state) { + case 21: + case 22: + case 24: + return true; + case 7: + case 8: + case 9: + case 10: + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + break; + case 0: + var_45D5B0_animation_state = 22; + var_45D5B4_animation_frame = 0; + break; + default: + var_45D5B0_animation_state = 21; + var_45D5B4_animation_frame = 0; + break; + } + break; + case 3: + if (var_45D5B0_animation_state == 0 || var_45D5B0_animation_state == 1) { + var_45D5B0_animation_state = 2; + var_462880 = 11; + var_462884 = 592; + if (Game_Flag_Query(199) == 1) { + var_45D5B4_animation_frame = 0; + } + } else if (var_45D5B0_animation_state < 11 || var_45D5B0_animation_state > 19) { + var_45D5B0_animation_state = 11; + var_45D5B4_animation_frame = 0; + var_45D5BC = 0; + } + break; + case 2: + var_45D5B0_animation_state = 4; + var_45D5B4_animation_frame = 0; + break; + case 1: + var_45D5B0_animation_state = 3; + var_45D5B4_animation_frame = 0; + break; + case 0: + switch (var_45D5B0_animation_state) { + case 21: + case 24: + var_45D5B0_animation_state = 23; + var_45D5B4_animation_frame = 0; + break; + case 20: + v1 = var_45D5B4_animation_frame; + Actor_Change_Animation_Mode(23, 4); + var_45D5B4_animation_frame = v1; + var_45D5B0_animation_state = 21; + break; + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + var_45D5BC = 1; + break; + case 0: + case 23: + return true; + default: + var_45D5B0_animation_state = 0; + var_45D5B4_animation_frame = 0; + var_45D5B8 = Random_Query(0, 1); + break; + } + break; + case 5: + case 9: + case 10: + case 11: + case 20: + case 23: + case 24: + case 25: + case 26: + return true; + default: + switch (mode) { + case 58: + var_45D5B0_animation_state = 20; + var_45D5B4_animation_frame = 0; + break; + case 48: + if (var_45D5B0_animation_state == 21 || var_45D5B0_animation_state == 22 || var_45D5B0_animation_state == 24) { + var_45D5B0_animation_state = 28; + var_45D5B4_animation_frame = 0; + } else { + var_45D5B0_animation_state = 27; + var_45D5B4_animation_frame = 0; + } + break; + case 47: + var_45D5B0_animation_state = 10; + var_45D5B4_animation_frame = 0; + break; + case 46: + var_45D5B0_animation_state = 9; + var_45D5B4_animation_frame = 0; + break; + case 45: + var_45D5B0_animation_state = 6; + var_45D5B4_animation_frame = 0; + break; + case 44: + var_45D5B0_animation_state = 5; + var_45D5B4_animation_frame = 0; + break; + default: + return true; + } + break; + } + return true; +} + +void AIScript_Officer_Leroy::QueryAnimationState(int *animationState, int *animationFrame, int *a3, int *a4) { + *animationState = var_45D5B0_animation_state; + *animationFrame = var_45D5B4_animation_frame; + *a3 = var_462880; + *a4 = var_462884; +} + +void AIScript_Officer_Leroy::SetAnimationState(int animationState, int animationFrame, int a3, int a4) { + var_45D5B0_animation_state = animationState; + var_45D5B4_animation_frame = animationFrame; + var_462880 = a3; + var_462884 = a4; +} + +bool AIScript_Officer_Leroy::ReachedMovementTrackWaypoint(int waypointId) { + if (waypointId == 57 || waypointId == 58) { + sub_431408(); + AI_Countdown_Timer_Reset(23, 2); + AI_Countdown_Timer_Start(23, 2, 6); + } + return true; +} + +void AIScript_Officer_Leroy::FledCombat() { + Actor_Set_Goal_Number(23, 300); +} + +bool AIScript_Officer_Leroy::sub_431408() { + Game_Flag_Set(199); + return true; +} + +bool AIScript_Officer_Leroy::sub_431420() { + Game_Flag_Reset(199); + return true; +} +} // End of namespace BladeRunner diff --git a/engines/bladerunner/script/aiscript_officer_leroy.h b/engines/bladerunner/script/ai_23_officer_leroy.h index 152ba83463..c78d80db4e 100644 --- a/engines/bladerunner/script/aiscript_officer_leroy.h +++ b/engines/bladerunner/script/ai_23_officer_leroy.h @@ -28,8 +28,11 @@ namespace BladeRunner { class AIScript_Officer_Leroy : public AIScriptBase { int var_45D5B0_animation_state; - int var_45D5B4_frame; + int var_45D5B4_animation_frame; int var_45D5B8; + int var_45D5BC; + int var_462880; + int var_462884; public: AIScript_Officer_Leroy(BladeRunnerEngine *vm); @@ -40,19 +43,24 @@ public: void ReceivedClue(int clueId, int fromActorId); void ClickedByPlayer(); void EnteredScene(int sceneId); - void OtherAgentEnteredThisScene(); - void OtherAgentExitedThisScene(); - void OtherAgentEnteredCombatMode(); + void OtherAgentEnteredThisScene(int otherActorId); + void OtherAgentExitedThisScene(int otherActorId); + void OtherAgentEnteredCombatMode(int otherActorId, int combatMode); void ShotAtAndMissed(); void ShotAtAndHit(); void Retired(int byActorId); - void GetFriendlinessModifierIfGetsClue(); + int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId); bool GoalChanged(int currentGoalNumber, int newGoalNumber); bool UpdateAnimation(int *animation, int *frame); bool ChangeAnimationMode(int mode); - void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4); - void SetAnimationState(int animationState, int a2, int a3, int a4); - bool ReachedMovementTrackWaypoint(); + void QueryAnimationState(int *animationState, int *animationFrame, int *a3, int *a4); + void SetAnimationState(int animationState, int animationFrame, int a3, int a4); + bool ReachedMovementTrackWaypoint(int a1); + void FledCombat(); + +private: + bool sub_431408(); + bool sub_431420(); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/script/aiscript_officer_leroy.cpp b/engines/bladerunner/script/aiscript_officer_leroy.cpp deleted file mode 100644 index 7881984154..0000000000 --- a/engines/bladerunner/script/aiscript_officer_leroy.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* 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/script/aiscript_officer_leroy.h" - -namespace BladeRunner { - -AIScript_Officer_Leroy::AIScript_Officer_Leroy(BladeRunnerEngine *vm) - : AIScriptBase(vm) { -} - -void AIScript_Officer_Leroy::Initialize() { - var_45D5B0_animation_state = 0; - var_45D5B4_frame = 0; - var_45D5B8 = 0; - - Actor_Put_In_Set(23, 69); - Actor_Set_At_XYZ(23, -261.80f, 6.00f, 79.58f, 512); - // Actor_Set_Goal_Number(23, 0); - // Actor_Set_Frame_Rate_FPS(23, 8); -} - -bool AIScript_Officer_Leroy::Update() { - return false; -} - -void AIScript_Officer_Leroy::TimerExpired(int timer) { -} - -void AIScript_Officer_Leroy::CompletedMovementTrack() { -} - -void AIScript_Officer_Leroy::ReceivedClue(int clueId, int fromActorId) { -} - -void AIScript_Officer_Leroy::ClickedByPlayer() { -} - -void AIScript_Officer_Leroy::EnteredScene(int sceneId) { -} - -void AIScript_Officer_Leroy::OtherAgentEnteredThisScene() { -} - -void AIScript_Officer_Leroy::OtherAgentExitedThisScene() { -} - -void AIScript_Officer_Leroy::OtherAgentEnteredCombatMode() { -} - -void AIScript_Officer_Leroy::ShotAtAndMissed() { -} - -void AIScript_Officer_Leroy::ShotAtAndHit() { -} - -void AIScript_Officer_Leroy::Retired(int byActorId) { -} - -void AIScript_Officer_Leroy::GetFriendlinessModifierIfGetsClue() { -} - -bool AIScript_Officer_Leroy::GoalChanged(int currentGoalNumber, int newGoalNumber) { - return false; -} - -bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame) { - if (var_45D5B8 == 0) { - *animation = 589; - var_45D5B4_frame++; - - if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(589)) { - var_45D5B4_frame = 0; - var_45D5B8 = Random_Query(0, 2); - } - } else if (var_45D5B8 == 1) { - *animation = 590; - var_45D5B4_frame++; - - if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(590)) { - var_45D5B4_frame = 0; - var_45D5B8 = Random_Query(0, 2); - } - } else if (var_45D5B8 == 2) { - *animation = 591; - var_45D5B4_frame++; - - if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(591)) { - var_45D5B4_frame = 0; - var_45D5B8 = Random_Query(0, 2); - } - } - *frame = var_45D5B4_frame; - return true; -} - -bool AIScript_Officer_Leroy::ChangeAnimationMode(int mode) { - switch (mode) { - case 1: - var_45D5B0_animation_state = 32; - break; - } - return true; -} - -void AIScript_Officer_Leroy::QueryAnimationState(int *animationState, int *a2, int *a3, int *a4) { -} - -void AIScript_Officer_Leroy::SetAnimationState(int animationState, int a2, int a3, int a4) { -} - -bool AIScript_Officer_Leroy::ReachedMovementTrackWaypoint() { - return false; -} -} // End of namespace BladeRunner diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp index 45b23120d5..bc6679051c 100644 --- a/engines/bladerunner/script/script.cpp +++ b/engines/bladerunner/script/script.cpp @@ -48,7 +48,8 @@ #include "bladerunner/waypoints.h" #include "bladerunner/script/ai_00_mccoy.h" -#include "bladerunner/script/aiscript_officer_leroy.h" +#include "bladerunner/script/ai_15_runciter.h" +#include "bladerunner/script/ai_23_officer_leroy.h" namespace BladeRunner { @@ -190,7 +191,7 @@ void ScriptBase::Actor_Set_At_XYZ(int actorId, float x, float y, float z, int di } void ScriptBase::Actor_Set_At_Waypoint(int actorId, int waypointId, int angle) { - _vm->_actors[actorId]->setAtWaypoint(waypointId, angle, 0, 0); + _vm->_actors[actorId]->setAtWaypoint(waypointId, angle, 0, false); } bool ScriptBase::Region_Check(int left, int top, int right, int down) { @@ -500,11 +501,11 @@ bool ScriptBase::Actor_Query_In_Between_Two_Actors(int actorId, int otherActor1I float z1 = _vm->_actors[otherActor1Id]->getZ(); float x2 = _vm->_actors[otherActor2Id]->getX(); float z2 = _vm->_actors[otherActor2Id]->getZ(); - return _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1, z1, x2, z1) - || _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 - 12.0f, z1 - 12.0f, x2 - 12.0f, z2 - 12.0f) - || _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 + 12.0f, z1 - 12.0f, x2 + 12.0f, z2 - 12.0f) - || _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 + 12.0f, z1 + 12.0f, x2 + 12.0f, z2 + 12.0f) - || _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 - 12.0f, z1 + 12.0f, x2 - 12.0f, z2 + 12.0f); + return _vm->_sceneObjects->isBetweenTwoXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x1, z1, x2, z1) + || _vm->_sceneObjects->isBetweenTwoXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x1 - 12.0f, z1 - 12.0f, x2 - 12.0f, z2 - 12.0f) + || _vm->_sceneObjects->isBetweenTwoXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x1 + 12.0f, z1 - 12.0f, x2 + 12.0f, z2 - 12.0f) + || _vm->_sceneObjects->isBetweenTwoXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x1 + 12.0f, z1 + 12.0f, x2 + 12.0f, z2 + 12.0f) + || _vm->_sceneObjects->isBetweenTwoXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x1 - 12.0f, z1 + 12.0f, x2 - 12.0f, z2 + 12.0f); } void ScriptBase::Actor_Set_Goal_Number(int actorId, int goalNumber) { @@ -542,26 +543,61 @@ int ScriptBase::Actor_Query_Animation_Mode(int actorId) { } 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, run); - return false; + _vm->gameWaitForActive(); + + if (actorId == _vm->_walkingActorId) { + run = true; + } + _vm->_playerActorIdle = false; + bool isRunning; + bool result = _vm->_actors[actorId]->loopWalkToActor(otherActorId, a3, a4, run, true, &isRunning); + if (_vm->_playerActorIdle) { + result = true; + _vm->_playerActorIdle = false; + } + if (isRunning == 1) { + _vm->_walkingActorId = actorId; + } + Global_Variable_Set(37, actorId); + Global_Variable_Set(38, isRunning); + return result; } 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, run); - return false; + _vm->gameWaitForActive(); + + if (_vm->_walkingActorId == actorId) { + run = true; + } + _vm->_playerActorIdle = false; + bool isRunning; + bool result = _vm->_actors[actorId]->loopWalkToItem(itemId, a3, a4, run, true, &isRunning); + if (_vm->_playerActorIdle == 1) { + result = true; + _vm->_playerActorIdle = false; + } + if (isRunning == 1) { + _vm->_walkingActorId = actorId; + } + Global_Variable_Set(37, actorId); + Global_Variable_Set(38, isRunning); + return result; } bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int destinationOffset, bool a4, bool run) { _vm->gameWaitForActive(); - if(_vm->_walkingActorId == actorId) { + if (_vm->_walkingActorId == actorId) { run = true; } + _vm->_playerActorIdle = false; bool isRunning; bool result = _vm->_actors[actorId]->loopWalkToSceneObject(objectName, destinationOffset, a4, run, true, &isRunning); - if(isRunning == 1) { + if (_vm->_playerActorIdle) { + result = true; + _vm->_playerActorIdle = false; + } + if (isRunning == 1) { _vm->_walkingActorId = actorId; } Global_Variable_Set(37, actorId); @@ -1070,28 +1106,21 @@ void ScriptBase::Scene_2D_Region_Remove(int index) { _vm->_scene->_regions->remove(index); } -void ScriptBase::World_Waypoint_Set(int waypointId, int sceneId, float x, float y, float z) { - //TODO - warning("World_Waypoint_Set(%d, %d, %f, %f, %f)", waypointId, sceneId, x, y, z); +void ScriptBase::World_Waypoint_Set(int waypointId, int setId, float x, float y, float z) { + _vm->_waypoints->set(waypointId, setId, Vector3(x, y, z)); } // ScriptBase::World_Waypoint_Reset float ScriptBase::World_Waypoint_Query_X(int waypointId) { - //TODO - warning("World_Waypoint_Query_X(%d)", waypointId); - return 0.0f; + return _vm->_waypoints->getX(waypointId); } float ScriptBase::World_Waypoint_Query_Y(int waypointId) { - //TODO - warning("World_Waypoint_Query_Y(%d)", waypointId); - return 0.0f; + return _vm->_waypoints->getY(waypointId); } float ScriptBase::World_Waypoint_Query_Z(int waypointId) { - //TODO - warning("World_Waypoint_Query_Z(%d)", waypointId); - return 0.0f; + return _vm->_waypoints->getZ(waypointId); } void ScriptBase::Combat_Cover_Waypoint_Set_Data(int combatCoverId, int a2, int sceneId, int a4, float x, float y, float z) { @@ -1243,7 +1272,7 @@ void ScriptBase::Actor_Retired_Here(int actorId, int width, int height, int reti actor->getXYZ(&actorPosition.x, &actorPosition.y, &actorPosition.z); actor->retire(retired, width, height, retiredByActorId); actor->setAtXYZ(actorPosition, actor->getFacing(), true, 0, true); - _vm->_sceneObjects->setRetired(actorId, true); + _vm->_sceneObjects->setRetired(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true); } void ScriptBase::Clickable_Object(const char *objectName) { @@ -1335,26 +1364,28 @@ void ScriptBase::I_Sez(const char *str) { } void ScriptBase::AI_Countdown_Timer_Start(int actorId, signed int timer, int seconds) { -// if (timer >= 0 && timer <= 2) -// _vm->_actors[actorId]->timerSet(timer, 1000 * seconds); + if (timer >= 0 && timer <= 2) { + _vm->_actors[actorId]->countdownTimerStart(timer, 1000 * seconds); + } } void ScriptBase::AI_Countdown_Timer_Reset(int actorId, int timer) { -// if (timer >= 0 && timer <= 2) -// _vm->_actors[actorId]->timerReset(timer); + if (timer >= 0 && timer <= 2) { + _vm->_actors[actorId]->countdownTimerReset(timer); + } } void ScriptBase::AI_Movement_Track_Unpause(int actorId) { - //_vm->_actors[actorId]->movementTrackUnpause(); + _vm->_actors[actorId]->movementTrackUnpause(); } void ScriptBase::AI_Movement_Track_Pause(int actorId) { - //_vm->_actors[actorId]->movementTrackPause(); + _vm->_actors[actorId]->movementTrackPause(); } void ScriptBase::AI_Movement_Track_Repeat(int actorId) { _vm->_actors[actorId]->_movementTrack->repeat(); - //_vm->_actors[actorId]->movementTrackRepeat(1); + _vm->_actors[actorId]->movementTrackNext(true); } void ScriptBase::AI_Movement_Track_Append_Run_With_Facing(int actorId, int waypointId, int delay, int angle) { @@ -1423,37 +1454,131 @@ void ScriptBase::VK_Play_Speech_Line(int actorIndex, int a2, float a3) { warning("VK_Play_Speech_Line(%d, %d, %g)", actorIndex, a2, a3); } -AIScripts::AIScripts(BladeRunnerEngine *vm) : _vm(vm), _inScriptCounter(0) { - for (int i = 0; i != 100; ++i) +AIScripts::AIScripts(BladeRunnerEngine *vm, int actorsCount) : _vm(vm), _inScriptCounter(0) { + _actorsCount = actorsCount; + _actorUpdating = new bool[actorsCount]; + _AIScripts = new AIScriptBase*[actorsCount]; + for (int i = 0; i < actorsCount; ++i) { _AIScripts[i] = nullptr; + _actorUpdating[i] = false; + } _AIScripts[0] = new AIScript_McCoy(_vm); + _AIScripts[15] = new AIScript_Runciter(_vm); _AIScripts[23] = new AIScript_Officer_Leroy(_vm); } AIScripts::~AIScripts() { - for (int i = 0; i != 100; ++i) { + for (int i = 0; i < _actorsCount; ++i) { delete _AIScripts[i]; _AIScripts[i] = nullptr; } + delete[] _AIScripts; + delete[] _actorUpdating; } void AIScripts::Initialize(int actor) { + assert(actor < _actorsCount); if (_AIScripts[actor]) _AIScripts[actor]->Initialize(); } +void AIScripts::Update(int actor) { + assert(actor < _actorsCount); + if (this->_actorUpdating[actor] != 1) { + this->_actorUpdating[actor] = true; + ++this->_inScriptCounter; + if (_AIScripts[actor]) + _AIScripts[actor]->Update(); + --this->_inScriptCounter; + this->_actorUpdating[actor] = false; + } +} + +void AIScripts::TimerExpired(int actor, int timer) { + assert(actor < _actorsCount); + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->TimerExpired(timer); + } + _inScriptCounter--; +} + +void AIScripts::CompletedMovementTrack(int actor) { + assert(actor < _actorsCount); + if (!_vm->_actors[actor]->inCombat()) { + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->CompletedMovementTrack(); + } + _inScriptCounter--; + } +} + +void AIScripts::EnteredScene(int actor, int setId) { + assert(actor < _actorsCount); + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->EnteredScene(setId); + } + _inScriptCounter--; +} + +void AIScripts::OtherAgentEnteredThisScene(int actor, int otherActorId) { + assert(actor < _actorsCount); + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->OtherAgentEnteredThisScene(otherActorId); + } + _inScriptCounter--; +} + +void AIScripts::OtherAgentExitedThisScene(int actor, int otherActorId) { + assert(actor < _actorsCount); + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->OtherAgentExitedThisScene(otherActorId); + } + _inScriptCounter--; +} + +void AIScripts::GoalChanged(int actor, int currentGoalNumber, int newGoalNumber) { + assert(actor < _actorsCount); + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->GoalChanged(currentGoalNumber, newGoalNumber); + } + _inScriptCounter--; +} + +bool AIScripts::ReachedMovementTrackWaypoint(int actor, int waypointId) { + assert(actor < _actorsCount); + bool result = false; + if (!_vm->_actors[actor]->inCombat()) { + _inScriptCounter++; + if (_AIScripts[actor]) { + result = _AIScripts[actor]->ReachedMovementTrackWaypoint(waypointId); + } + _inScriptCounter--; + } + return result; +} + void AIScripts::UpdateAnimation(int actor, int *animation, int *frame) { + assert(actor < _actorsCount); _inScriptCounter++; - if (_AIScripts[actor]) + if (_AIScripts[actor]) { _AIScripts[actor]->UpdateAnimation(animation, frame); + } _inScriptCounter--; } void AIScripts::ChangeAnimationMode(int actor, int mode) { + assert(actor < _actorsCount); _inScriptCounter++; - if (_AIScripts[actor]) + if (_AIScripts[actor]) { _AIScripts[actor]->ChangeAnimationMode(mode); + } _inScriptCounter--; } diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h index 5966b67868..8577078c0d 100644 --- a/engines/bladerunner/script/script.h +++ b/engines/bladerunner/script/script.h @@ -304,11 +304,12 @@ public: */ class Script { -public: +protected: BladeRunnerEngine *_vm; int _inScriptCounter; SceneScriptBase *_currentScript; +public: Script(BladeRunnerEngine *vm) : _vm(vm), _inScriptCounter(0), @@ -331,6 +332,7 @@ public: void PlayerWalkedIn(); void PlayerWalkedOut(); void DialogueQueueFlushed(int a1); + bool IsInsideScript() { return _inScriptCounter > 0; } }; #define DECLARE_SCRIPT(name) \ @@ -820,34 +822,47 @@ public: virtual void CompletedMovementTrack() = 0; virtual void ReceivedClue(int clueId, int fromActorId) = 0; virtual void ClickedByPlayer() = 0; - virtual void EnteredScene(int sceneId) = 0; - virtual void OtherAgentEnteredThisScene() = 0; - virtual void OtherAgentExitedThisScene() = 0; - virtual void OtherAgentEnteredCombatMode() = 0; + virtual void EnteredScene(int setId) = 0; + virtual void OtherAgentEnteredThisScene(int otherActorId) = 0; + virtual void OtherAgentExitedThisScene(int otherActorId) = 0; + virtual void OtherAgentEnteredCombatMode(int otherActorId, int combatMode) = 0; virtual void ShotAtAndMissed() = 0; virtual void ShotAtAndHit() = 0; virtual void Retired(int byActorId) = 0; - virtual void GetFriendlinessModifierIfGetsClue() = 0; + virtual int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) = 0; virtual bool GoalChanged(int currentGoalNumber, int newGoalNumber) = 0; virtual bool UpdateAnimation(int *animation, int *frame) = 0; virtual bool ChangeAnimationMode(int mode) = 0; virtual void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4) = 0; virtual void SetAnimationState(int animationState, int a2, int a3, int a4) = 0; - virtual bool ReachedMovementTrackWaypoint() = 0; + virtual bool ReachedMovementTrackWaypoint(int waypointId) = 0; + virtual void FledCombat() = 0; }; class AIScripts { -public: +private: BladeRunnerEngine *_vm; int _inScriptCounter; - AIScriptBase *_AIScripts[100]; - - AIScripts(BladeRunnerEngine *vm); + int _actorsCount; + AIScriptBase **_AIScripts; + bool *_actorUpdating; +public: + AIScripts(BladeRunnerEngine *vm, int actorsCount); ~AIScripts(); void Initialize(int actor); + void Update(int actor); + void TimerExpired(int actor, int timer); + void CompletedMovementTrack(int actor); + void EnteredScene(int actor, int setId); + void OtherAgentEnteredThisScene(int actor, int otherActorId); + void OtherAgentExitedThisScene(int actor, int otherActorId); + void GoalChanged(int actor, int currentGoalNumber, int newGoalNumber); + bool ReachedMovementTrackWaypoint(int actor, int waypointId); void UpdateAnimation(int actor, int *animation, int *frame); void ChangeAnimationMode(int actor, int mode); + + bool IsInsideScript() { return _inScriptCounter > 0; } }; } // End of namespace BladeRunner diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp index f426107ee3..340db3d9c1 100644 --- a/engines/director/archive.cpp +++ b/engines/director/archive.cpp @@ -275,8 +275,8 @@ bool RIFFArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff if (tag == 0) break; - uint16 startResPos = stream->pos(); - stream->seek(offset + 12); + uint32 startResPos = stream->pos(); + stream->seek(startOffset + offset + 12); Common::String name = ""; byte nameSize = stream->readByte(); @@ -289,11 +289,11 @@ bool RIFFArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff stream->seek(startResPos); - debug(3, "Found RIFF resource '%s' %d: %d @ 0x%08x", tag2str(tag), id, size, offset); + debug(3, "Found RIFF resource '%s' %d: %d @ 0x%08x", tag2str(tag), id, size, startOffset + offset); ResourceMap &resMap = _types[tag]; Resource &res = resMap[id]; - res.offset = offset; + res.offset = offset + startOffset; res.size = size; res.name = name; } diff --git a/engines/director/events.cpp b/engines/director/events.cpp index 32fe58859e..f4806f332e 100644 --- a/engines/director/events.cpp +++ b/engines/director/events.cpp @@ -46,13 +46,13 @@ void DirectorEngine::processEvents() { uint endTime = g_system->getMillis() + 200; Score *sc = getCurrentScore(); + if (sc->getCurrentFrame() >= sc->_frames.size()) { + warning("processEvents: request to access frame %d of %d", sc->getCurrentFrame(), sc->_frames.size() - 1); + return; + } Frame *currentFrame = sc->_frames[sc->getCurrentFrame()]; uint16 spriteId = 0; - // TODO: re-instate when we know which script to run. - //if (currentFrame > 0) - // _lingo->processEvent(kEventIdle, currentFrame - 1); - Common::Point pos; while (g_system->getMillis() < endTime) { @@ -70,6 +70,8 @@ void DirectorEngine::processEvents() { spriteId = currentFrame->getSpriteIDFromPos(pos); sc->_currentMouseDownSpriteId = spriteId; + debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); + if (getVersion() > 3) { // TODO: check that this is the order of script execution! _lingo->processEvent(kEventMouseDown, kCastScript, currentFrame->_sprites[spriteId]->_castId); @@ -85,16 +87,19 @@ void DirectorEngine::processEvents() { pos = g_system->getEventManager()->getMousePos(); spriteId = currentFrame->getSpriteIDFromPos(pos); + + debugC(3, kDebugEvents, "event: Button Up @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); + if (getVersion() > 3) { // TODO: check that this is the order of script execution! - _lingo->processEvent(kEventMouseUp, kCastScript, currentFrame->_sprites[spriteId]->_castId); - _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventNone, kCastScript, currentFrame->_sprites[spriteId]->_castId); + _lingo->processEvent(kEventNone, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); } else { // Frame script overrides sprite script if (!currentFrame->_sprites[spriteId]->_scriptId) - _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_castId + 1024); + _lingo->processEvent(kEventNone, kSpriteScript, currentFrame->_sprites[spriteId]->_castId + 1024); else - _lingo->processEvent(kEventMouseUp, kFrameScript, currentFrame->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventNone, kFrameScript, currentFrame->_sprites[spriteId]->_scriptId); } sc->_currentMouseDownSpriteId = 0; @@ -131,6 +136,9 @@ void DirectorEngine::processEvents() { g_system->updateScreen(); g_system->delayMillis(10); + + if (sc->getCurrentFrame() > 0) + _lingo->processEvent(kEventIdle, kFrameScript, sc->getCurrentFrame()); } } diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index cceecdd579..92aa851d06 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -222,10 +222,14 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { sprite._unk3 = stream->readUint32(); } - debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d/%d] script:%d", - sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, - sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height, - sprite._lineSize, sprite._scriptId); + if (sprite._castId) { + debugC(kDebugLoading, 4, "CH: %-3d castId: %03d(%s) (e:%d) [%x,%x, flags:%04x, %dx%d@%d,%d linesize: %d] script: %d", + i + 1, sprite._castId, numToCastNum(sprite._castId), sprite._enabled, sprite._x1, sprite._x2, sprite._flags, + sprite._width, sprite._height, sprite._startPoint.x, sprite._startPoint.y, + sprite._lineSize, sprite._scriptId); + } else { + debugC(kDebugLoading, 4, "CH: %-3d castId: 000", i + 1); + } } } diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index cb6a7d67ec..e12b20a3c2 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -1232,7 +1232,7 @@ void Lingo::b_rollOver(int nargs) { Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()]; - if (arg >= frame->_sprites.size()) { + if (arg >= (int32) frame->_sprites.size()) { g_lingo->push(d); return; } diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp index 307d79a0a2..0f2110d8f1 100644 --- a/engines/director/lingo/lingo-funcs.cpp +++ b/engines/director/lingo/lingo-funcs.cpp @@ -182,14 +182,15 @@ void Lingo::func_goto(Datum &frame, Datum &movie) { Common::String cleanedFilename; - for (const byte *p = (const byte *)movie.u.s->c_str(); *p; p++) - if (*p >= 0x20 && *p <= 0x7f) - cleanedFilename += (const char) *p; - bool fileExists = false; if (_vm->getPlatform() == Common::kPlatformMacintosh) { Common::MacResManager resMan; + + for (const byte *p = (const byte *)movie.u.s->c_str(); *p; p++) + if (*p >= 0x20 && *p <= 0x7f) + cleanedFilename += (const char) *p; + if (resMan.open(*movie.u.s)) { fileExists = true; cleanedFilename = *movie.u.s; @@ -198,6 +199,8 @@ void Lingo::func_goto(Datum &frame, Datum &movie) { } } else { Common::File file; + cleanedFilename = *movie.u.s + ".MMM"; + if (file.open(*movie.u.s)) { fileExists = true; cleanedFilename = *movie.u.s; diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index f00d9a7d32..482531d455 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -299,7 +299,7 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { if (entityId < 0) return; - debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); + debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); _currentEntityId = entityId; @@ -307,11 +307,14 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { error("processEvent: Unknown event %d for entity %d", event, entityId); if (_handlers.contains(ENTITY_INDEX(event, entityId))) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), _eventHandler", _eventHandlerTypes[event], scriptType2str(st), entityId); call(_eventHandlerTypes[event], 0); // D4+ Events - } else if (_scripts[st].contains(entityId)) { + } else if (event == kEventNone && _scripts[st].contains(entityId)) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), script", _eventHandlerTypes[event], scriptType2str(st), entityId); + executeScript(st, entityId); // D3 list of scripts. } else { - debugC(3, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId); + //debugC(3, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId); } } diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp index 5a964c1687..dc961b86eb 100644 --- a/engines/director/resource.cpp +++ b/engines/director/resource.cpp @@ -20,7 +20,9 @@ * */ +#include "common/config-manager.h" #include "common/macresman.h" + #include "graphics/macgui/macwindowmanager.h" #include "graphics/macgui/macfontmanager.h" @@ -76,6 +78,7 @@ void DirectorEngine::loadEXE(const Common::String movie) { exeStream->seek(exeStream->readUint32LE()); switch (getVersion()) { + case 2: case 3: loadEXEv3(exeStream); break; @@ -100,16 +103,51 @@ void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) { stream->skip(5); // unknown - stream->readUint32LE(); // Main MMM size + uint32 mmmSize = stream->readUint32LE(); // Main MMM size + Common::String mmmFileName = stream->readPascalString(); Common::String directoryName = stream->readPascalString(); debugC(1, kDebugLoading, "Main MMM: '%s'", mmmFileName.c_str()); debugC(1, kDebugLoading, "Directory Name: '%s'", directoryName.c_str()); + debugC(1, kDebugLoading, "Main mmmSize: %d (0x%x)", mmmSize, mmmSize); - openMainArchive(mmmFileName); + if (mmmSize) { + uint32 riffOffset = stream->pos(); + + debugC(1, kDebugLoading, "RIFF offset: %d (%x)", riffOffset, riffOffset); + + if (ConfMan.getBool("dump_scripts")) { + Common::DumpFile out; + byte *buf = (byte *)malloc(mmmSize); + stream->read(buf, mmmSize); + stream->seek(riffOffset); + Common::String fname = Common::String::format("./dumps/%s", mmmFileName.c_str()); + + + if (!out.open(fname.c_str())) { + warning("Can not open dump file %s", fname.c_str()); + return; + } + + out.write(buf, mmmSize); + + out.flush(); + out.close(); + + free(buf); + } + + + _mainArchive = new RIFFArchive(); + + if (!_mainArchive->openStream(stream, riffOffset)) + error("Failed to load RIFF from EXE"); + + return; + } - delete stream; + openMainArchive(mmmFileName); } void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) { @@ -200,13 +238,7 @@ void DirectorEngine::loadMac(const Common::String movie) { void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Archive *shardcst = createArchive(); - debug(0, "Loading Shared cast '%s'", filename.c_str()); - - if (!shardcst->openFile(filename)) { - warning("No shared cast %s", filename.c_str()); - - return; - } + debug(0, "****** Loading Shared cast '%s'", filename.c_str()); _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; @@ -214,6 +246,12 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; _sharedScore = new Score(this); + if (!shardcst->openFile(filename)) { + warning("No shared cast %s", filename.c_str()); + + return; + } + _sharedScore->setArchive(shardcst); if (shardcst->hasResource(MKTAG('F', 'O', 'N', 'D'), -1)) { @@ -229,12 +267,16 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> cast = shardcst->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { + debug(0, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) _sharedScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator, NULL); } Common::Array<uint16> vwci = shardcst->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debug(0, "****** Loading %d CastInfo resources", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) _sharedScore->loadCastInfo(*shardcst->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } @@ -243,7 +285,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); if (dib.size() != 0) { - debugC(3, kDebugLoading, "Loading %d DIBs", dib.size()); + debugC(3, kDebugLoading, "****** Loading %d DIBs", dib.size()); for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) { debugC(3, kDebugLoading, "Shared DIB %d", *iterator); @@ -253,7 +295,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() != 0) { - debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size()); + debugC(3, kDebugLoading, "****** Loading %d STXTs", stxt.size()); for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { debugC(3, kDebugLoading, "Shared STXT %d", *iterator); @@ -263,7 +305,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); if (bmp.size() != 0) { - debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size()); + debugC(3, kDebugLoading, "****** Loading %d BITDs", bmp.size()); for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { debugC(3, kDebugLoading, "Shared BITD %d (%s)", *iterator, numToCastNum(*iterator - 1024)); _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); @@ -272,7 +314,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); if (sound.size() != 0) { - debugC(3, kDebugLoading, "Loading %d SNDs", sound.size()); + debugC(3, kDebugLoading, "****** Loading %d SNDs", sound.size()); for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) { debugC(3, kDebugLoading, "Shared SND %d", *iterator); _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); diff --git a/engines/director/score.cpp b/engines/director/score.cpp index 97152f818c..4b65044baa 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -120,6 +120,7 @@ void Score::loadArchive() { } else { Common::SeekableSubReadStreamEndian *pal = _movieArchive->getResource(MKTAG('C', 'L', 'U', 'T'), clutList[0]); + debugC(2, kDebugLoading, "****** Loading Palette"); loadPalette(*pal); g_system->getPaletteManager()->setPalette(_vm->getPalette(), 0, _vm->getPaletteColorCount()); } @@ -155,12 +156,16 @@ void Score::loadArchive() { Common::Array<uint16> vwci = _movieArchive->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CastInfos", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) loadCastInfo(*_movieArchive->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } Common::Array<uint16> cast = _movieArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't')); if (cast.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) { Common::SeekableSubReadStreamEndian *stream = _movieArchive->getResource(MKTAG('C', 'A', 'S', 't'), *iterator); Resource res = _movieArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), *iterator); @@ -175,6 +180,8 @@ void Score::loadArchive() { if (_vm->getVersion() <= 3) { Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d STXT resources", stxt.size()); + for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *iterator)); } @@ -183,6 +190,8 @@ void Score::loadArchive() { } void Score::loadSpriteImages(bool isSharedCast) { + debugC(1, kDebugLoading, "****** Preloading sprite images"); + Common::HashMap<int, BitmapCast *>::iterator bc; for (bc = _loadedBitmaps->begin(); bc != _loadedBitmaps->end(); ++bc) { if (bc->_value) { @@ -277,6 +286,8 @@ void Score::loadPalette(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading frames"); + uint32 size = stream.readUint32(); size -= 4; @@ -306,7 +317,7 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { byte channelData[kChannelDataSize]; memset(channelData, 0, kChannelDataSize); - while (size != 0) { + while (size != 0 && !stream.eos()) { uint16 frameSize = stream.readUint16(); debugC(kDebugLoading, 8, "++++ score frame %d (frameSize %d) size %d", _frames.size(), frameSize, size); size -= frameSize; @@ -334,7 +345,7 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { //Common::hexdump(channelData, ARRAYSIZE(channelData)); frame->readChannels(str); - debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size() + 1, frame->_actionId); + debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size(), frame->_actionId); delete str; @@ -343,6 +354,8 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadConfig(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading Config"); + /*uint16 unk1 = */ stream.readUint16(); /*ver1 = */ stream.readUint16(); _movieRect = Score::readRect(stream); @@ -362,7 +375,7 @@ void Score::readVersion(uint32 rid) { } void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { - debugC(1, kDebugLoading, "Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); + debugC(1, kDebugLoading, "****** Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); for (uint16 id = _castArrayStart; id <= _castArrayEnd; id++) { byte size = stream.readByte(); @@ -376,18 +389,22 @@ void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { switch (castType) { case kCastBitmap: + debugC(3, kDebugLoading, "CastTypes id: %d BitmapCast", id); _loadedBitmaps->setVal(id, new BitmapCast(stream)); _castTypes[id] = kCastBitmap; break; case kCastText: + debugC(3, kDebugLoading, "CastTypes id: %d TextCast", id); _loadedText->setVal(id, new TextCast(stream)); _castTypes[id] = kCastText; break; case kCastShape: + debugC(3, kDebugLoading, "CastTypes id: %d ShapeCast", id); _loadedShapes->setVal(id, new ShapeCast(stream)); _castTypes[id] = kCastShape; break; case kCastButton: + debugC(3, kDebugLoading, "CastTypes id: %d ButtonCast", id); _loadedButtons->setVal(id, new ButtonCast(stream)); _castTypes[id] = kCastButton; break; @@ -612,15 +629,15 @@ void Score::setCastMemberModified(int castId) { void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { _labels = new Common::SortedArray<Label *>(compareLabels); uint16 count = stream.readUint16() + 1; - uint16 offset = count * 4 + 2; + uint32 offset = count * 4 + 2; uint16 frame = stream.readUint16(); - uint16 stringPos = stream.readUint16() + offset; + uint32 stringPos = stream.readUint16() + offset; for (uint16 i = 0; i < count; i++) { uint16 nextFrame = stream.readUint16(); - uint16 nextStringPos = stream.readUint16() + offset; - uint16 streamPos = stream.pos(); + uint32 nextStringPos = stream.readUint16() + offset; + uint32 streamPos = stream.pos(); stream.seek(stringPos); Common::String label; @@ -638,6 +655,7 @@ void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { Common::SortedArray<Label *>::iterator j; + debugC(2, kDebugLoading, "****** Loading labels"); for (j = _labels->begin(); j != _labels->end(); ++j) { debugC(2, kDebugLoading, "Frame %d, Label %s", (*j)->number, (*j)->name.c_str()); } @@ -648,19 +666,21 @@ int Score::compareLabels(const void *a, const void *b) { } void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading Actions"); + uint16 count = stream.readUint16() + 1; - uint16 offset = count * 4 + 2; + uint32 offset = count * 4 + 2; byte id = stream.readByte(); byte subId = stream.readByte(); // I couldn't find how it used in continuity (except print). Frame actionId = 1 byte. - uint16 stringPos = stream.readUint16() + offset; + uint32 stringPos = stream.readUint16() + offset; for (uint16 i = 0; i < count; i++) { uint16 nextId = stream.readByte(); byte nextSubId = stream.readByte(); - uint16 nextStringPos = stream.readUint16() + offset; - uint16 streamPos = stream.pos(); + uint32 nextStringPos = stream.readUint16() + offset; + uint32 streamPos = stream.pos(); stream.seek(stringPos); @@ -672,7 +692,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { _actions[i + 1] += ch; } - debugC(3, kDebugLoading, "id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); + debugC(3, kDebugLoading, "Action id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); stream.seek(streamPos); @@ -935,6 +955,8 @@ Common::String Score::getString(Common::String str) { } void Score::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading FileInfo"); + Common::Array<Common::String> fileInfoStrings = loadStrings(stream, _flags); _script = fileInfoStrings[0]; @@ -964,6 +986,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn uint16 count = stream.readUint16() + 1; + debugC(3, kDebugLoading, "Strings: %d entries", count); + uint32 *entries = (uint32 *)calloc(count, sizeof(uint32)); for (uint i = 0; i < count; i++) @@ -982,6 +1006,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn entryString += data[j]; strings.push_back(entryString); + + debugC(6, kDebugLoading, "String %d:\n%s\n", i, entryString.c_str()); } free(data); @@ -994,9 +1020,11 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { if (stream.size() == 0) return; + debugC(2, kDebugLoading, "****** Loading FontMap"); + uint16 count = stream.readUint16(); uint32 offset = (count * 2) + 2; - uint16 currentRawPosition = offset; + uint32 currentRawPosition = offset; for (uint16 i = 0; i < count; i++) { uint16 id = stream.readUint16(); @@ -1014,7 +1042,7 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { _fontMap[id] = font; _vm->_wm->_fontMan->registerFontMapping(id, font); - debug(3, "Fontmap. ID %d Font %s", id, font.c_str()); + debugC(3, kDebugLoading, "Fontmap. ID %d Font %s", id, font.c_str()); currentRawPosition = stream.pos(); stream.seek(positionInfo); } @@ -1050,7 +1078,9 @@ void Score::startLoop() { while (!_stopPlay && _currentFrame < _frames.size()) { debugC(1, kDebugImages, "****************************** Current frame: %d", _currentFrame + 1); update(); - _vm->processEvents(); + + if (_currentFrame < _frames.size()) + _vm->processEvents(); } } @@ -1065,7 +1095,7 @@ void Score::update() { // Enter and exit from previous frame (Director 4) _lingo->processEvent(kEventEnterFrame, kFrameScript, _frames[_currentFrame]->_actionId); - _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); + _lingo->processEvent(kEventNone, kFrameScript, _frames[_currentFrame]->_actionId); // TODO Director 6 - another order // TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame @@ -1133,11 +1163,13 @@ void Score::update() { } } + _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); + _nextFrameTime = g_system->getMillis() + (float)_currentFrameRate / 60 * 1000; } Sprite *Score::getSpriteById(uint16 id) { - if (_currentFrame >= _frames.size() || _currentFrame < 0 || id >= _frames[_currentFrame]->_sprites.size()) { + if (_currentFrame >= _frames.size() || id >= _frames[_currentFrame]->_sprites.size()) { warning("Score::getSpriteById(%d): out of bounds. frame: %d", id, _currentFrame); return nullptr; } diff --git a/engines/director/util.cpp b/engines/director/util.cpp index ccde2b3127..dbd1cd351f 100644 --- a/engines/director/util.cpp +++ b/engines/director/util.cpp @@ -48,7 +48,7 @@ char *numToCastNum(int num) { res[3] = '\0'; num--; - if (num > 0 && num <= 512) { + if (num >= 0 && num < 512) { int c = num / 64; res[0] = 'A' + c; num -= 64 * c; diff --git a/engines/gnap/fontdata.h b/engines/gnap/fontdata.h index 0631d1d214..10f7b15ba5 100644 --- a/engines/gnap/fontdata.h +++ b/engines/gnap/fontdata.h @@ -747,105 +747,51 @@ const byte _dejaVuSans9ptCharBitmaps[] = { }; /* Character descriptors for DejaVu Sans 9pt */ -/* { [Char width in bits], [Offset into dejaVuSans9ptCharBitmaps in bytes] } */ -const FONT_CHAR_INFO _dejaVuSans9ptCharDescriptors[] = { - FONT_CHAR_INFO(5, 0), /* */ - FONT_CHAR_INFO(1, 10), /* ! */ - FONT_CHAR_INFO(3, 12), /* " */ - FONT_CHAR_INFO(8, 18), /* # */ - FONT_CHAR_INFO(5, 34), /* $ */ - FONT_CHAR_INFO(10, 44), /* % */ - FONT_CHAR_INFO(8, 64), /* & */ - FONT_CHAR_INFO(1, 80), /* ' */ - FONT_CHAR_INFO(3, 82), /* ( */ - FONT_CHAR_INFO(3, 88), /* ) */ - FONT_CHAR_INFO(5, 94), /* * */ - FONT_CHAR_INFO(7, 104), /* + */ - FONT_CHAR_INFO(1, 118), /* , */ - FONT_CHAR_INFO(3, 120), /* - */ - FONT_CHAR_INFO(1, 126), /* . */ - FONT_CHAR_INFO(4, 128), /* / */ - FONT_CHAR_INFO(6, 136), /* 0 */ - FONT_CHAR_INFO(5, 148), /* 1 */ - FONT_CHAR_INFO(6, 158), /* 2 */ - FONT_CHAR_INFO(6, 170), /* 3 */ - FONT_CHAR_INFO(6, 182), /* 4 */ - FONT_CHAR_INFO(6, 194), /* 5 */ - FONT_CHAR_INFO(6, 206), /* 6 */ - FONT_CHAR_INFO(6, 218), /* 7 */ - FONT_CHAR_INFO(6, 230), /* 8 */ - FONT_CHAR_INFO(6, 242), /* 9 */ - FONT_CHAR_INFO(1, 254), /* : */ - FONT_CHAR_INFO(1, 256), /* ; */ - FONT_CHAR_INFO(8, 258), /* < */ - FONT_CHAR_INFO(8, 274), /* = */ - FONT_CHAR_INFO(8, 290), /* > */ - FONT_CHAR_INFO(5, 306), /* ? */ - FONT_CHAR_INFO(11, 316), /* @ */ - FONT_CHAR_INFO(8, 338), /* A */ - FONT_CHAR_INFO(6, 354), /* B */ - FONT_CHAR_INFO(6, 366), /* C */ - FONT_CHAR_INFO(7, 378), /* D */ - FONT_CHAR_INFO(6, 392), /* E */ - FONT_CHAR_INFO(5, 404), /* F */ - FONT_CHAR_INFO(7, 414), /* G */ - FONT_CHAR_INFO(7, 428), /* H */ - FONT_CHAR_INFO(1, 442), /* I */ - FONT_CHAR_INFO(3, 444), /* J */ - FONT_CHAR_INFO(6, 450), /* K */ - FONT_CHAR_INFO(5, 462), /* L */ - FONT_CHAR_INFO(8, 472), /* M */ - FONT_CHAR_INFO(7, 488), /* N */ - FONT_CHAR_INFO(7, 502), /* O */ - FONT_CHAR_INFO(6, 516), /* P */ - FONT_CHAR_INFO(7, 528), /* Q */ - FONT_CHAR_INFO(7, 542), /* R */ - FONT_CHAR_INFO(6, 556), /* S */ - FONT_CHAR_INFO(7, 568), /* T */ - FONT_CHAR_INFO(7, 582), /* U */ - FONT_CHAR_INFO(8, 596), /* V */ - FONT_CHAR_INFO(11, 612), /* W */ - FONT_CHAR_INFO(7, 634), /* X */ - FONT_CHAR_INFO(7, 648), /* Y */ - FONT_CHAR_INFO(7, 662), /* Z */ - FONT_CHAR_INFO(2, 676), /* [ */ - FONT_CHAR_INFO(4, 680), /* \ */ - FONT_CHAR_INFO(2, 688), /* ] */ - FONT_CHAR_INFO(6, 692), /* ^ */ - FONT_CHAR_INFO(6, 704), /* _ */ - FONT_CHAR_INFO(2, 716), /* ` */ - FONT_CHAR_INFO(6, 720), /* a */ - FONT_CHAR_INFO(6, 732), /* b */ - FONT_CHAR_INFO(5, 744), /* c */ - FONT_CHAR_INFO(6, 754), /* d */ - FONT_CHAR_INFO(6, 766), /* e */ - FONT_CHAR_INFO(4, 778), /* f */ - FONT_CHAR_INFO(6, 786), /* g */ - FONT_CHAR_INFO(6, 798), /* h */ - FONT_CHAR_INFO(1, 810), /* i */ - FONT_CHAR_INFO(2, 812), /* j */ - FONT_CHAR_INFO(5, 816), /* k */ - FONT_CHAR_INFO(1, 826), /* l */ - FONT_CHAR_INFO(9, 828), /* m */ - FONT_CHAR_INFO(6, 846), /* n */ - FONT_CHAR_INFO(6, 858), /* o */ - FONT_CHAR_INFO(6, 870), /* p */ - FONT_CHAR_INFO(6, 882), /* q */ - FONT_CHAR_INFO(4, 894), /* r */ - FONT_CHAR_INFO(5, 902), /* s */ - FONT_CHAR_INFO(4, 912), /* t */ - FONT_CHAR_INFO(6, 920), /* u */ - FONT_CHAR_INFO(6, 932), /* v */ - FONT_CHAR_INFO(9, 944), /* w */ - FONT_CHAR_INFO(6, 962), /* x */ - FONT_CHAR_INFO(6, 974), /* y */ - FONT_CHAR_INFO(5, 986), /* z */ - FONT_CHAR_INFO(5, 996), /* { */ - FONT_CHAR_INFO(1, 1006), /* | */ - FONT_CHAR_INFO(5, 1008), /* ) */ - FONT_CHAR_INFO(8, 1018) /* ~ */ +const byte _dejaVuSans9ptWidth[] = { + 5, /* */ 1, /* ! */ 3, /* " */ 8, /* # */ 5, /* $ */ + 10,/* % */ 8, /* & */ 1, /* ' */ 3, /* ( */ 3, /* ) */ + 5, /* * */ 7, /* + */ 1, /* , */ 3, /* - */ 1, /* . */ + 4, /* / */ 6, /* 0 */ 5, /* 1 */ 6, /* 2 */ 6, /* 3 */ + 6, /* 4 */ 6, /* 5 */ 6, /* 6 */ 6, /* 7 */ 6, /* 8 */ + 6, /* 9 */ 1, /* : */ 1, /* ; */ 8, /* < */ 8, /* = */ + 8, /* > */ 5, /* ? */ 11,/* @ */ 8, /* A */ 6, /* B */ + 6, /* C */ 7, /* D */ 6, /* E */ 5, /* F */ 7, /* G */ + 7, /* H */ 1, /* I */ 3, /* J */ 6, /* K */ 5, /* L */ + 8, /* M */ 7, /* N */ 7, /* O */ 6, /* P */ 7, /* Q */ + 7, /* R */ 6, /* S */ 7, /* T */ 7, /* U */ 8, /* V */ + 11,/* W */ 7, /* X */ 7, /* Y */ 7, /* Z */ 2, /* [ */ + 4, /* \ */ 2, /* ] */ 6, /* ^ */ 6, /* _ */ 2, /* ` */ + 6, /* a */ 6, /* b */ 5, /* c */ 6, /* d */ 6, /* e */ + 4, /* f */ 6, /* g */ 6, /* h */ 1, /* i */ 2, /* j */ + 5, /* k */ 1, /* l */ 9, /* m */ 6, /* n */ 6, /* o */ + 6, /* p */ 6, /* q */ 4, /* r */ 5, /* s */ 4, /* t */ + 6, /* u */ 6, /* v */ 9, /* w */ 6, /* x */ 6, /* y */ + 5, /* z */ 5, /* { */ 1, /* | */ 5, /* ) */ 8 /* ~ */ +}; + +const uint16 _dejaVuSans9ptOffsets[] = { + 0, /* */ 10, /* ! */ 12, /* " */ 18, /* # */ 34, /* $ */ + 44, /* % */ 64, /* & */ 80, /* ' */ 82, /* ( */ 88, /* */ + 94, /* * */ 104, /* + */ 118, /* , */ 120, /* - */ 126, /* . */ + 128, /* / */ 136, /* 0 */ 148, /* 1 */ 158, /* 2 */ 170, /* 3 */ + 182, /* 4 */ 194, /* 5 */ 206, /* 6 */ 218, /* 7 */ 230, /* 8 */ + 242, /* 9 */ 254, /* : */ 256, /* ; */ 258, /* < */ 274, /* = */ + 290, /* > */ 306, /* ? */ 316, /* @ */ 338, /* A */ 354, /* B */ + 366, /* C */ 378, /* D */ 392, /* E */ 404, /* F */ 414, /* G */ + 428, /* H */ 442, /* I */ 444, /* J */ 450, /* K */ 462, /* L */ + 472, /* M */ 488, /* N */ 502, /* O */ 516, /* P */ 528, /* Q */ + 542, /* R */ 556, /* S */ 568, /* T */ 582, /* U */ 596, /* V */ + 612, /* W */ 634, /* X */ 648, /* Y */ 662, /* Z */ 676, /* [ */ + 680, /* \ */ 688, /* ] */ 692, /* ^ */ 704, /* _ */ 716, /* ` */ + 720, /* a */ 732, /* b */ 744, /* c */ 754, /* d */ 766, /* e */ + 778, /* f */ 786, /* g */ 798, /* h */ 810, /* i */ 812, /* j */ + 816, /* k */ 826, /* l */ 828, /* m */ 846, /* n */ 858, /* o */ + 870, /* p */ 882, /* q */ 894, /* r */ 902, /* s */ 912, /* t */ + 920, /* u */ 932, /* v */ 944, /* w */ 962, /* x */ 974, /* y */ + 986, /* z */ 996, /* { */ 1006, /* | */ 1008, /* */ 1018 /* ~ */ }; } // End of namespace Gnap #endif // GNAP_RESOURCE_H + diff --git a/engines/gnap/gamesys.cpp b/engines/gnap/gamesys.cpp index 08a4af39ee..04247c5d46 100644 --- a/engines/gnap/gamesys.cpp +++ b/engines/gnap/gamesys.cpp @@ -294,8 +294,8 @@ void GameSys::drawTextToSurface(Graphics::Surface *surface, int x, int y, byte r if (c < 32 || c >= 127) c = (byte)'_'; c -= 32; - int w = _dejaVuSans9ptCharDescriptors[c]._width; - const byte *data = _dejaVuSans9ptCharBitmaps + _dejaVuSans9ptCharDescriptors[c]._offset; + int w = _dejaVuSans9ptWidth[c]; + const byte *data = _dejaVuSans9ptCharBitmaps + _dejaVuSans9ptOffsets[c]; for (int xc = 0; xc < w; ++xc) { for (int yc = 15; yc >= 0; --yc) { byte *dst = (byte *)surface->getBasePtr(x + xc, y + yc); @@ -319,7 +319,7 @@ int GameSys::getTextHeight(const char *text) { if (c < 32 || c >= 127) c = (byte)'_'; c -= 32; - height = MAX(height, _dejaVuSans9ptCharDescriptors[c]._width); + height = MAX(height, _dejaVuSans9ptWidth[c]); } return height; } @@ -331,7 +331,7 @@ int GameSys::getTextWidth(const char *text) { if (c < 32 || c >= 127) c = (byte)'_'; c -= 32; - width += _dejaVuSans9ptCharDescriptors[c]._width + 1; + width += _dejaVuSans9ptWidth[c] + 1; } return width; } @@ -555,6 +555,7 @@ void GameSys::seqRemoveGfx(int sequenceId, int id) { bool GameSys::updateSequenceDuration(int sequenceId, int id, int *outDuration) { bool found = false; int duration = 0x7FFFFFFF; + *outDuration = 0; for (int i = 0; i < _gfxItemsCount; ++i) { GfxItem *gfxItem = &_gfxItems[i]; if (gfxItem->_sequenceId == sequenceId && gfxItem->_id == id) { @@ -577,8 +578,10 @@ bool GameSys::updateSequenceDuration(int sequenceId, int id, int *outDuration) { } } } + if (found) *outDuration = duration; + return found; } diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 9cc52a78b3..7da3c14633 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -48,6 +48,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0, }, + // Myst + // English Windows 3.11, v1.0 + // From vonLeheCreative, #9645 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "0e4b6fcbd2419d4371365314fb7443f8"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUI_OPTIONS_MYST + }, + GType_MYST, + 0, + 0, + }, + // Myst Demo // English Windows 3.11 // From CD-ROM Today July, 1994 diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp index 596180ddb2..267d644b65 100644 --- a/engines/mohawk/myst_scripts.cpp +++ b/engines/mohawk/myst_scripts.cpp @@ -355,7 +355,26 @@ void MystScriptParser::o_changeCardSwitchRtL(uint16 op, uint16 var, uint16 argc, } void MystScriptParser::o_takePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - uint16 cursorId = argv[0]; + // In most game releases, the first opcode argument is the new mouse cursor. + // However, in the original v1.0 English release this opcode takes no argument. + uint16 cursorId; // = argv[0]; + switch (var) { + case 41: // Vault white page + cursorId = kWhitePageCursor; + break; + case 25: // Fireplace red page + case 102: // Red page + cursorId = kRedPageCursor; + break; + case 24: // Fireplace blue page + case 103: // Blue page + cursorId = kBluePageCursor; + break; + default: + warning("Unexpected take page variable '%d'", var); + cursorId = kDefaultMystCursor; + } + uint16 oldPage = _globals.heldPage; debugC(kDebugScript, "Opcode %d: takePage Var %d CursorId %d", op, var, cursorId); diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp index 21c3042359..f006a8e3ea 100644 --- a/engines/mohawk/myst_stacks/channelwood.cpp +++ b/engines/mohawk/myst_stacks/channelwood.cpp @@ -368,6 +368,7 @@ void Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint1 for (uint i = 0; i < 2; i++) for (uint16 imageId = 3601; imageId >= 3595; imageId--) { _vm->_gfx->copyImageToScreen(imageId, rect); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } @@ -699,6 +700,7 @@ void Channelwood::o_waterTankValveClose(uint16 op, uint16 var, uint16 argc, uint for (uint i = 0; i < 2; i++) for (uint16 imageId = 3595; imageId <= 3601; imageId++) { _vm->_gfx->copyImageToScreen(imageId, rect); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index f9ba6a42fa..424dd2f07c 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -864,6 +864,7 @@ void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *a // Unset button for (uint i = 4795; i >= 4779; i--) { _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect()); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } _fireplaceLines[var - 17] &= ~bitmask; @@ -871,6 +872,7 @@ void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *a // Set button for (uint i = 4779; i <= 4795; i++) { _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect()); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } _fireplaceLines[var - 17] |= bitmask; diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index c542be7ef2..cf3a981347 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -103,6 +103,7 @@ static const char *const selectorNameTable[] = { "modNum", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support "cycler", // Space Quest 4 / system selector "setLoop", // Laura Bow 1 Colonel's Bequest + "ignoreActors", // Laura Bow 1 Colonel's Bequest #ifdef ENABLE_SCI32 "newWith", // SCI2 array script "scrollSelections", // GK2 @@ -135,7 +136,8 @@ enum ScriptPatcherSelectors { SELECTOR_startAudio, SELECTOR_modNum, SELECTOR_cycler, - SELECTOR_setLoop + SELECTOR_setLoop, + SELECTOR_ignoreActors #ifdef ENABLE_SCI32 , SELECTOR_newWith, @@ -554,14 +556,12 @@ static const uint16 freddypharkasSignatureIntroScaling[] = { static const uint16 freddypharkasPatchIntroScaling[] = { // remove setLoop(), objects in heap are already prepared, saves 5 bytes 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (setStep) + PATCH_GETORIGINALUINT16(+6), // pushi (setStep) 0x7a, // push2 0x39, 0x05, // pushi 05 0x3c, // dup 0x72, - PATCH_GETORIGINALBYTE(+13), - PATCH_GETORIGINALBYTE(+14), // lofsa (view) + PATCH_GETORIGINALUINT16(+13), // lofsa (view) 0x4a, 0x18, // send 18 - adjusted 0x35, 0x0a, // ldi 0a 0xa3, 0x02, // sal local[2] @@ -1314,8 +1314,7 @@ static const uint16 kq6PatchInventoryStackFix[] = { 0x12, // and 0x65, 0x30, // aTop state 0x38, // pushi "show" - PATCH_GETORIGINALBYTE(+22), - PATCH_GETORIGINALBYTE(+23), + PATCH_GETORIGINALUINT16(+22), 0x78, // push1 0x87, 0x00, // lap param[0] 0x31, 0x04, // bnt [call show using global 0] @@ -1600,8 +1599,7 @@ static const uint16 kq6CDPatchAudioTextSupport3[] = { 0x65, 0x12, // aTop dialog // followed by original addText-calling code 0x38, - PATCH_GETORIGINALBYTE(+95), - PATCH_GETORIGINALBYTE(+96), // pushi addText + PATCH_GETORIGINALUINT16(+95), // pushi (addText) 0x78, // push1 0x8f, 0x02, // lsp param[2] 0x59, 0x03, // &rest 03 @@ -1949,8 +1947,7 @@ static const uint16 kq7PatchSubtitleFix3[] = { PATCH_ADDTOOFFSET(+2), // skip over "pToa initialized code" 0x2f, 0x0c, // bt [skip init code] - saved 1 byte 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (init) + PATCH_GETORIGINALUINT16(+6), // pushi (init) 0x76, // push0 0x54, PATCH_UINT16(0x0004), // self 04 // additionally set background color here (5 bytes) @@ -2488,12 +2485,79 @@ static const uint16 laurabow1PatchArmorOilingArmFix[] = { PATCH_END }; +// When you tell Lilly about Gertie in room 35, Lilly will then walk to the left and off the screen. +// In case Laura (ego) is in the way, the whole game will basically block and you won't be able +// to do anything except saving + restoring the game. +// +// If this happened already, the player can enter +// "send Lillian ignoreActors 1" inside the debugger to fix this situation. +// +// This issue is very difficult to solve, because Lilly also walks diagonally after walking to the left right +// under the kitchen table. This means that even if we added a few more rectangle checks, there could still be +// spots, where the game would block. +// +// Also the mover "PathOut" is used for Lillian instead of the regular "MoveTo", which would avoid other +// actors by itself. +// +// So instead we set Lilly to ignore other actors during that cutscene, which is the least invasive solution. +// +// Applies to at least: English PC Floppy, English Amiga Floppy, English Atari ST Floppy +// Responsible method: goSee::changeState(1) in script 236 +// Fixes bug: (happened during GOG Let's Play) +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix1[] = { + 0x7a, // puah2 + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x00c1), // pushi 00C1h + 0x38, SIG_UINT16(0x008f), // pushi 008Fh + 0x38, SIG_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix1[] = { + PATCH_ADDTOOFFSET(+11), // skip over until push0 + 0x78, // push1 (change push0 to push1) + PATCH_END +}; + +// a second patch to call Lillian::ignoreActors(1) on goSee::changeState(9) in script 236 +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix2[] = { + 0x3c, // dup + 0x35, 0x09, // ldi 09 + 0x1a, // eq? + 0x30, SIG_UINT16(0x003f), // bnt [ret] + 0x39, SIG_ADDTOOFFSET(+1), // pushi (view) + 0x78, // push1 + 0x38, SIG_UINT16(0x0203), // pushi 203h (515d) + 0x38, SIG_ADDTOOFFSET(+2), // pushi (posn) + 0x7a, // push2 + 0x38, SIG_UINT16(0x00c9), // pushi C9h (201d) + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x0084), // pushi 84h (132d) + 0x72, SIG_ADDTOOFFSET(+2), // lofsa Lillian (different offsets for different platforms) + 0x4a, 0x0e, // send 0Eh + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix2[] = { + 0x38, PATCH_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + 0x33, 0x00, // ldi 00 (waste 2 bytes) + PATCH_ADDTOOFFSET(+19), // skip over until send + 0x4a, 0x14, // send 14h + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry laurabow1Signatures[] = { - { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, - { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, - { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, - { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, + { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, + { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, + { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 236, "tell Lilly about Gertie blocking fix 1/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix1, laurabow1PatchTellLillyAboutGertieBlockingFix1 }, + { true, 236, "tell Lilly about Gertie blocking fix 2/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix2, laurabow1PatchTellLillyAboutGertieBlockingFix2 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -2614,6 +2678,98 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { PATCH_END }; +// When entering the main musem party room (w/ the golden Egyptian head), +// Laura is waslking a bit into the room automatically. +// In case you press a mouse button while this is happening, you will get +// stuck inside that room and won't be able to exit it anymore. +// +// Users, who played the game w/ a previous version of ScummVM can simply +// enter the debugger and then enter "send rm350 script 0:0", which will +// fix the script state. +// +// This is caused by the user controls not being locked at that point. +// Pressing a button will cause the cue from the PolyPath walker to never +// happen, which then causes sEnterSouth to never dispose itself. +// +// User controls are locked in the previous room 335, but controls +// are unlocked by frontDoor::cue. +// We do not want to change this, because it could have side-effects. +// We instead add another LB2::handsOff call inside the script responsible +// for making Laura walk into the room (sEnterSouth::changeState(0). +// +// Applies to at least: English PC-CD, English PC-Floppy, German PC-Floppy +// Responsible method: sEnterSouth::changeState +// Fixes bug: (no bug report, from GOG forum post) +static const uint16 laurabow2SignatureMuseumPartyFixEnteringSouth1[] = { + 0x3c, // dup + 0x35, 0x00, // ldi 00 + 0x1a, // eq? + 0x30, SIG_UINT16(0x0097), // bnt [state 1 code] + SIG_ADDTOOFFSET(+141), // skip to end of follow-up code + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x008d for CD, 0x007d for floppy) + 0x35, 0x01, // ldi 01 + 0x65, 0x1a, // aTop cycles + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x0086 for CD, 0x0076 for floppy) + // state 1 code + 0x3c, // dup + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + SIG_MAGICDWORD, + 0x31, 0x05, // bnt [state 2 code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x007b for CD, 0x006b for floppy) + // state 2 code + 0x3c, // dup + SIG_END +}; + +static const uint16 laurabow2PatchMuseumPartyFixEnteringSouth1[] = { + 0x2e, PATCH_UINT16(0x00a6), // bt [state 2 code] (we skip state 1, because it's a NOP anyways) + // state 0 processing + 0x32, PATCH_UINT16(+151), + SIG_ADDTOOFFSET(+149), // skip to end of follow-up code + // save 1 byte by replacing jump to [ret] into straight toss/ret + 0x3a, // toss + 0x48, // ret + + // additional code, that gets called right at the start of step 0 processing + 0x18, // not -- this here is where pushi handsOff will be inserted by the second patch + 0x18, // not offset and handsOff is different for floppy + CD, that's why we do this + 0x18, // not floppy also does not have a selector table, so we can't go by "handsOff" name + 0x18, // not + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 + 0x32, PATCH_UINT16(0xFF5e), // jmp [back to start of step 0 processing] + PATCH_END +}; + +// second patch, which only inserts pushi handsOff inside our new code +// There is no other way to do this except making 2 full patches for floppy + CD, because handsOff/handsOn +// is not the same value between floppy + CD *and* floppy doesn't even have a vocab, so we can't figure out the id +// by ourselves. +static const uint16 laurabow2SignatureMuseumPartyFixEnteringSouth2[] = { + 0x18, // our injected code + 0x18, + 0x18, + SIG_ADDTOOFFSET(+92), // skip to the handsOn code, that we are interested in + 0x38, SIG_ADDTOOFFSET(+2), // pushi handsOn (0x0189 for CD, 0x024b for floppy) + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 + 0x38, SIG_ADDTOOFFSET(+2), // pushi 0274h + SIG_MAGICDWORD, + 0x78, // push1 + 0x38, SIG_UINT16(0x033f), // pushi 033f + SIG_END +}; + +static const uint16 laurabow2PatchMuseumPartyFixEnteringSouth2[] = { + 0x38, // pushi + PATCH_GETORIGINALUINT16ADJUST(+96, -1), // get handsOff code and ubstract 1 from it to get handsOn + PATCH_END +}; + // Opening/Closing the east door in the pterodactyl room doesn't // check, if it's locked and will open/close the door internally // even when it is. @@ -2628,7 +2784,7 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { // Responsible method (CD): eastDoor::doVerb // Responsible method (Floppy): eastDoor::<noname300> // Fixes bug: #6458 (partly, see additional patch below) -static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { +static const uint16 laurabow2SignatureFixWiredEastDoor[] = { 0x30, SIG_UINT16(0x0022), // bnt [skip hand action] 0x67, SIG_ADDTOOFFSET(+1), // pTos CD: doorState, Floppy: state 0x35, 0x00, // ldi 00 @@ -2651,7 +2807,7 @@ static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { SIG_END }; -static const uint16 laurabow2CDPatchFixWiredEastDoor[] = { +static const uint16 laurabow2PatchFixWiredEastDoor[] = { 0x31, 0x23, // bnt [skip hand action] (saves 1 byte) 0x81, 97, // lag 97d (get our eastDoor-wired-global) 0x31, 0x04, // bnt [skip setting locked property] @@ -2780,20 +2936,22 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport2[] = { // script, description, signature patch static const SciScriptPatcherEntry laurabow2Signatures[] = { - { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, - { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, - { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, - { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2CDSignatureFixWiredEastDoor, laurabow2CDPatchFixWiredEastDoor }, + { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, + { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, + { true, 350, "CD/Floppy: museum party fix entering south 1/2", 1, laurabow2SignatureMuseumPartyFixEnteringSouth1, laurabow2PatchMuseumPartyFixEnteringSouth1 }, + { true, 350, "CD/Floppy: museum party fix entering south 2/2", 1, laurabow2SignatureMuseumPartyFixEnteringSouth2, laurabow2PatchMuseumPartyFixEnteringSouth2 }, + { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, + { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2SignatureFixWiredEastDoor, laurabow2PatchFixWiredEastDoor }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support - { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, - { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, - { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, - { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, - { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, - { false, 0, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, - { false, 100, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, - { false, 24, "CD: audio + text support LB2 menu 1", 1, laurabow2CDSignatureAudioTextMenuSupport1, laurabow2CDPatchAudioTextMenuSupport1 }, - { false, 24, "CD: audio + text support LB2 menu 2", 1, laurabow2CDSignatureAudioTextMenuSupport2, laurabow2CDPatchAudioTextMenuSupport2 }, + { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, + { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, + { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, + { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, + { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, + { false, 0, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, + { false, 100, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, + { false, 24, "CD: audio + text support LB2 menu 1", 1, laurabow2CDSignatureAudioTextMenuSupport1, laurabow2CDPatchAudioTextMenuSupport1 }, + { false, 24, "CD: audio + text support LB2 menu 2", 1, laurabow2CDSignatureAudioTextMenuSupport2, laurabow2CDPatchAudioTextMenuSupport2 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -3939,8 +4097,7 @@ static const uint16 qfg3PatchMissingPoints1[] = { PATCH_UINT16(0xFFD6), // -42 "Greet" PATCH_UINT16(0xFFB0), // -80 "Say Good-bye" PATCH_UINT16(0x03E7), // 999 END MARKER - PATCH_GETORIGINALBYTE(+28), // local[$aa][0].low - PATCH_GETORIGINALBYTE(+29), // local[$aa][0].high + PATCH_GETORIGINALUINT16(+28), // local[$aa][0] PATCH_END }; @@ -4841,14 +4998,6 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc break; } case PATCH_CODE_GETORIGINALBYTE: { - // get original byte from script - if (patchValue >= orgDataSize) - error("Script-Patcher: can not get requested original byte from script"); - scriptData[offset] = orgData[patchValue]; - offset++; - break; - } - case PATCH_CODE_GETORIGINALBYTEADJUST: { // get original byte from script and adjust it if (patchValue >= orgDataSize) error("Script-Patcher: can not get requested original byte from script"); @@ -4859,6 +5008,30 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc offset++; break; } + case PATCH_CODE_GETORIGINALUINT16: { + // get original byte from script and adjust it + if ((patchValue >= orgDataSize) || (((uint32)patchValue + 1) >= orgDataSize)) + error("Script-Patcher: can not get requested original uint16 from script"); + uint16 orgUINT16; + int16 adjustValue; + + if (!_isMacSci11) { + orgUINT16 = orgData[patchValue] | (orgData[patchValue + 1] << 8); + } else { + orgUINT16 = orgData[patchValue + 1] | (orgData[patchValue] << 8); + } + patchData++; adjustValue = (int16)(*patchData); + orgUINT16 += adjustValue; + if (!_isMacSci11) { + scriptData[offset] = orgUINT16 & 0xFF; + scriptData[offset + 1] = orgUINT16 >> 8; + } else { + scriptData[offset] = orgUINT16 >> 8; + scriptData[offset + 1] = orgUINT16 & 0xFF; + } + offset += 2; + break; + } case PATCH_CODE_UINT16: case PATCH_CODE_SELECTOR16: { byte byte1; @@ -5134,7 +5307,8 @@ void ScriptPatcher::calculateMagicDWordAndVerify(const char *signatureDescriptio } break; } - case PATCH_CODE_GETORIGINALBYTEADJUST: { + case PATCH_CODE_GETORIGINALBYTE: + case PATCH_CODE_GETORIGINALUINT16: { signatureData++; // skip over extra uint16 break; } diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h index f95806a3f3..b5797be847 100644 --- a/engines/sci/engine/script_patches.h +++ b/engines/sci/engine/script_patches.h @@ -44,23 +44,25 @@ namespace Sci { #define SIG_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) #define SIG_CODE_BYTE 0x0000 -#define PATCH_END SIG_END -#define PATCH_COMMANDMASK SIG_COMMANDMASK -#define PATCH_VALUEMASK SIG_VALUEMASK -#define PATCH_BYTEMASK SIG_BYTEMASK -#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET -#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) -#define PATCH_CODE_GETORIGINALBYTE 0xD000 -#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_) -#define PATCH_CODE_GETORIGINALBYTEADJUST 0xC000 -#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTEADJUST | (_offset_), (uint16)(_adjustValue_) -#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 -#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ -#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 -#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ -#define PATCH_CODE_UINT16 SIG_CODE_UINT16 -#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) -#define PATCH_CODE_BYTE SIG_CODE_BYTE +#define PATCH_END SIG_END +#define PATCH_COMMANDMASK SIG_COMMANDMASK +#define PATCH_VALUEMASK SIG_VALUEMASK +#define PATCH_BYTEMASK SIG_BYTEMASK +#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET +#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) +#define PATCH_CODE_GETORIGINALBYTE 0xC000 +#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_), 0 +#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTE | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_GETORIGINALUINT16 0xD000 +#define PATCH_GETORIGINALUINT16(_offset_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), 0 +#define PATCH_GETORIGINALUINT16ADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 +#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ +#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 +#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ +#define PATCH_CODE_UINT16 SIG_CODE_UINT16 +#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) +#define PATCH_CODE_BYTE SIG_CODE_BYTE // defines maximum scratch area for getting original bytes from unpatched script data #define PATCH_VALUELIMIT 4096 diff --git a/engines/titanic/star_control/base_star.cpp b/engines/titanic/star_control/base_star.cpp index ffe5fd05b4..b1e813b0ae 100644 --- a/engines/titanic/star_control/base_star.cpp +++ b/engines/titanic/star_control/base_star.cpp @@ -214,4 +214,10 @@ int CBaseStar::baseFn2(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12) { return ref._index; } +/*------------------------------------------------------------------------*/ + +void CStarVector::apply() { + _owner->addMatrixRow(_vector); +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/base_star.h b/engines/titanic/star_control/base_star.h index 1c75efd26b..ff096520e5 100644 --- a/engines/titanic/star_control/base_star.h +++ b/engines/titanic/star_control/base_star.h @@ -53,11 +53,14 @@ struct CBaseStarEntry { bool operator==(const CBaseStarEntry &s) const; }; -struct CStarPosition { - Common::Point _position; +struct CStarPosition : public Common::Point { int _index1; int _index2; CStarPosition() : _index1(0), _index2(0) {} + + bool operator==(const CStarPosition &sp) const { + return x == sp.x && y == sp.y && _index1 == sp._index1 && _index2 == sp._index2; + } }; class CBaseStar { @@ -143,6 +146,19 @@ public: int baseFn2(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12); }; +class CStarVector { +private: + CStarControlSub12 *_owner; + FVector _vector; +public: + CStarVector(CStarControlSub12 *owner, const FVector &v) : _owner(owner), _vector(v) {} + + /** + * Applies the saved vector + */ + void apply(); +}; + } // End of namespace Titanic #endif /* TITANIC_STAR_CONTROL_SUB3_H */ diff --git a/engines/titanic/star_control/dmatrix.cpp b/engines/titanic/star_control/dmatrix.cpp index 1405f4f693..1808b13dc2 100644 --- a/engines/titanic/star_control/dmatrix.cpp +++ b/engines/titanic/star_control/dmatrix.cpp @@ -29,21 +29,30 @@ namespace Titanic { DMatrix *DMatrix::_static; DMatrix::DMatrix() : - _row1(1.875, 0.0, 0.0), _row2(0.0, 1.875, 0.0), _row3(0.0, 0.0, 1.875) { + _row1(0.0, 0.0, 0.0), _row2(0.0, 0.0, 0.0), _row3(0.0, 0.0, 0.0) { } -DMatrix::DMatrix(int mode, const FMatrix *src) { - assert(!mode); - - _row1._x = 1.875; - _row2._y = 1.875; - _row3._z = 1.875; - _frow1._x = src->_row1._x; - _frow1._y = src->_row1._y; - _frow1._z = src->_row1._z; - _frow2._x = src->_row2._x; - _frow2._y = src->_row2._y; - _frow2._z = src->_row2._z; +DMatrix::DMatrix(int mode, const DVector &src) { + switch (mode) { + case 0: + _row1._x = 1.0; + _row2._y = 1.0; + _row3._z = 1.0; + _row4 = src; + break; + + case 1: + _row1._x = src._x; + _row2._y = src._y; + _row3._z = src._z; + break; + + default: + _row1._x = 1.0; + _row2._y = 1.0; + _row3._z = 1.0; + break; + } } DMatrix::DMatrix(Axis axis, double amount) { diff --git a/engines/titanic/star_control/dmatrix.h b/engines/titanic/star_control/dmatrix.h index a015ebdb1d..c3490770fb 100644 --- a/engines/titanic/star_control/dmatrix.h +++ b/engines/titanic/star_control/dmatrix.h @@ -42,14 +42,13 @@ public: DVector _row1; DVector _row2; DVector _row3; - FVector _frow1; - FVector _frow2; + DVector _row4; public: static void init(); static void deinit(); public: DMatrix(); - DMatrix(int mode, const FMatrix *src); + DMatrix(int mode, const DVector &src); DMatrix(Axis axis, double amount); DMatrix(const FMatrix &src); diff --git a/engines/titanic/star_control/dvector.cpp b/engines/titanic/star_control/dvector.cpp index dc1376537e..9cd610fc0a 100644 --- a/engines/titanic/star_control/dvector.cpp +++ b/engines/titanic/star_control/dvector.cpp @@ -38,8 +38,9 @@ double DVector::getDistance(const DVector &src) { return sqrt((src._x - _x) * (src._x - _x) + (src._y - _y) * (src._y - _y) + (src._z - _z) * (src._z - _z)); } -void DVector::fn1(DVector &dest, const DMatrix &m) { +DVector *DVector::fn1(DVector &dest, const DMatrix &m) { // TODO + return nullptr; } void DVector::fn2(double val) { diff --git a/engines/titanic/star_control/dvector.h b/engines/titanic/star_control/dvector.h index a216be15fe..a447f253e1 100644 --- a/engines/titanic/star_control/dvector.h +++ b/engines/titanic/star_control/dvector.h @@ -48,11 +48,45 @@ public: */ double getDistance(const DVector &src); - void fn1(DVector &dest, const DMatrix &m); + DVector *fn1(DVector &dest, const DMatrix &m); void fn2(double val); void fn3(DVector &dest); const DMatrix *fn4(const DVector &v, DMatrix &m); void fn5(DMatrix &dest); + + /** + * Returns true if the passed vector equals this one + */ + bool operator==(const DVector &src) const { + return _x != src._x || _y != src._y || _z != src._z; + } + + /** + * Returns true if the passed vector does not equal this one + */ + bool operator!=(const DVector &src) const { + return !operator==(src); + } + + DVector operator+(const DVector &delta) const { + return DVector(_x + delta._x, _y + delta._y, _z + delta._z); + } + + DVector operator-(const DVector &delta) const { + return DVector(_x - delta._x, _y - delta._y, _z - delta._z); + } + + void operator+=(const DVector &delta) { + _x += delta._x; + _y += delta._y; + _z += delta._z; + } + + void operator-=(const DVector &delta) { + _x -= delta._x; + _y -= delta._y; + _z -= delta._z; + } }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/fmatrix.cpp b/engines/titanic/star_control/fmatrix.cpp index e0c270ba7d..54e674cad8 100644 --- a/engines/titanic/star_control/fmatrix.cpp +++ b/engines/titanic/star_control/fmatrix.cpp @@ -78,10 +78,16 @@ void FMatrix::identity() { _row3 = FVector(0.0, 0.0, 1.0); } -void FMatrix::set(FVector *row1, FVector *row2, FVector *row3) { - _row1 = *row1; - _row2 = *row2; - _row3 = *row3; +void FMatrix::set(const FVector &row1, const FVector &row2, const FVector &row3) { + _row1 = row1; + _row2 = row2; + _row3 = row3; +} + +void FMatrix::set(const DVector &row1, const DVector &row2, const DVector &row3) { + _row1 = row1; + _row2 = row2; + _row3 = row3; } void FMatrix::fn1(const FVector &v) { @@ -94,13 +100,13 @@ void FMatrix::fn1(const FVector &v) { _row2._y = tempVector._y; _row2._z = tempVector._z; - _row3.crossProduct(&tempVector, &_row2); + _row3.crossProduct(tempVector, _row2); _row1._x = _row2._x; _row1._y = _row2._y; _row1._z = _row2._z; _row1.normalize(); - _row3.crossProduct(&tempVector, &_row1); + _row3.crossProduct(tempVector, _row1); _row2._x = _row1._x; _row2._y = _row1._y; _row2._z = _row1._z; diff --git a/engines/titanic/star_control/fmatrix.h b/engines/titanic/star_control/fmatrix.h index 7ab90fb7e1..0cbecb2ff8 100644 --- a/engines/titanic/star_control/fmatrix.h +++ b/engines/titanic/star_control/fmatrix.h @@ -29,6 +29,7 @@ namespace Titanic { class DMatrix; +class DVector; /** * Floating point matrix class. @@ -72,7 +73,12 @@ public: /** * Sets the data for the matrix */ - void set(FVector *row1, FVector *row2, FVector *row3); + void set(const FVector &row1, const FVector &row2, const FVector &row3); + + /** + * Sets the data for the matrix + */ + void set(const DVector &row1, const DVector &row2, const DVector &row3); void fn1(const FVector &v); void fn2(const FMatrix &m); @@ -91,6 +97,15 @@ public: bool operator!=(const FMatrix &src) { return !operator==(src); } + + /** + * Allows accessing rows as an array + */ + FVector &operator[](int idx) { + assert(idx >= 0 && idx <= 2); + FVector *rows[3] = { &_row1, &_row2, &_row3 }; + return *rows[idx]; + } }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/fvector.cpp b/engines/titanic/star_control/fvector.cpp index b0667c532b..666b22eb3a 100644 --- a/engines/titanic/star_control/fvector.cpp +++ b/engines/titanic/star_control/fvector.cpp @@ -21,12 +21,16 @@ */ #include "titanic/star_control/fvector.h" +#include "titanic/star_control/dvector.h" #include "titanic/star_control/star_control_sub6.h" #include "common/algorithm.h" #include "common/textconsole.h" namespace Titanic { +FVector::FVector(const DVector &src) : _x(src._x), _y(src._y), _z(src._z) { +} + void FVector::fn1(FVector *v) { v->_x = (ABS(_x - _y) < 0.00001 && ABS(_y - _z) < 0.00001 && ABS(_x - _z) < 0.00001) ? -_x : _x; @@ -34,10 +38,10 @@ void FVector::fn1(FVector *v) { v->_z = _z; } -void FVector::crossProduct(FVector *dest, const FVector *src) { - dest->_x = (src->_z * _y) - (_z * src->_y); - dest->_y = (src->_x * _z) - (_x * src->_z); - dest->_z = (src->_y * _x) - (_y * src->_x); +void FVector::crossProduct(FVector &dest, const FVector &src) { + dest._x = (src._z * _y) - (_z * src._y); + dest._y = (src._x * _z) - (_x * src._z); + dest._z = (src._y * _x) - (_y * src._x); } double FVector::normalize() { @@ -50,22 +54,23 @@ double FVector::normalize() { return hyp; } -void FVector::addAndNormalize(FVector *dest, const FVector *v1, const FVector *v2) { - FVector tempVector(v1->_x + v2->_x, v1->_y + v2->_y, v1->_z + v2->_z); +const FVector *FVector::addAndNormalize(FVector &dest, const FVector &v1, const FVector &v2) { + FVector tempVector(v1._x + v2._x, v1._y + v2._y, v1._z + v2._z); tempVector.normalize(); - *dest = tempVector; + dest = tempVector; + return &dest; } -double FVector::getDistance(const FVector *src) const { - double xd = src->_x - _x; - double yd = src->_y - _y; - double zd = src->_z - _z; +double FVector::getDistance(const FVector &src) const { + double xd = src._x - _x; + double yd = src._y - _y; + double zd = src._z - _z; return sqrt(xd * xd + yd * yd + zd * zd); } -void FVector::fn5(FVector *dest, const CStarControlSub6 *sub6) const { +FVector FVector::fn5(const CStarControlSub6 *sub6) const { error("TODO: FVector::fn5"); } diff --git a/engines/titanic/star_control/fvector.h b/engines/titanic/star_control/fvector.h index bf446fc640..67eba6b5c9 100644 --- a/engines/titanic/star_control/fvector.h +++ b/engines/titanic/star_control/fvector.h @@ -30,6 +30,7 @@ namespace Titanic { enum Axis { X_AXIS, Y_AXIS, Z_AXIS }; class CStarControlSub6; +class DVector; /** * Floating point vector class. @@ -41,6 +42,7 @@ public: public: FVector() : _x(0), _y(0), _z(0) {} FVector(double x, double y, double z) : _x(x), _y(y), _z(z) {} + FVector(const DVector &src); /** * Clears the vector @@ -54,7 +56,7 @@ public: /** * Calculates the cross-product between this matrix and a passed one */ - void crossProduct(FVector *dest, const FVector *src); + void crossProduct(FVector &dest, const FVector &src); /** * Normalizes the vector so the length from origin equals 1.0 @@ -64,14 +66,14 @@ public: /** * Adds two vectors together and then normalizes the result */ - static void addAndNormalize(FVector *dest, const FVector *v1, const FVector *v2); + static const FVector *addAndNormalize(FVector &dest, const FVector &v1, const FVector &v2); /** * Returns the distance between a specified point and this one */ - double getDistance(const FVector *src) const; + double getDistance(const FVector &src) const; - void fn5(FVector *dest, const CStarControlSub6 *sub6) const; + FVector fn5(const CStarControlSub6 *sub6) const; /** * Returns true if the passed vector equals this one @@ -95,6 +97,10 @@ public: return FVector(_x - delta._x, _y - delta._y, _z - delta._z); } + const FVector operator*(double right) const { + return FVector(_x * right, _y * right, _z * right); + } + void operator+=(const FVector &delta) { _x += delta._x; _y += delta._y; diff --git a/engines/titanic/star_control/star_control_sub12.cpp b/engines/titanic/star_control/star_control_sub12.cpp index 7ed65357d3..45cebec836 100644 --- a/engines/titanic/star_control/star_control_sub12.cpp +++ b/engines/titanic/star_control/star_control_sub12.cpp @@ -23,6 +23,8 @@ #include "titanic/star_control/star_control_sub12.h" #include "titanic/star_control/star_control_sub21.h" #include "titanic/star_control/star_control_sub22.h" +#include "titanic/star_control/dmatrix.h" +#include "titanic/star_control/fmatrix.h" namespace Titanic { @@ -30,12 +32,12 @@ FMatrix *CStarControlSub12::_matrix1; FMatrix *CStarControlSub12::_matrix2; CStarControlSub12::CStarControlSub12(const CStar20Data *data) : - _currentIndex(-1), _handlerP(nullptr), _field108(0) { + _matrixRow(-1), _handlerP(nullptr), _field108(0) { setupHandler(data); } CStarControlSub12::CStarControlSub12(CStarControlSub13 *src) : - _currentIndex(-1), _handlerP(nullptr), _field108(0), _sub13(src) { + _matrixRow(-1), _handlerP(nullptr), _field108(0), _sub13(src) { } void CStarControlSub12::init() { @@ -215,22 +217,204 @@ FVector CStarControlSub12::proc31(int index, const FVector &v) { return _sub13.fn18(index, v); } -void CStarControlSub12::setViewportPosition(const FPoint &pt) { - // TODO +void CStarControlSub12::setViewportPosition(const FPoint &angles) { + if (isLocked()) + return; + + if (_matrixRow == -1) { + CStarControlSub6 subX(X_AXIS, angles._x); + CStarControlSub6 subY(Y_AXIS, angles._y); + CStarControlSub6 sub(&subX, &subY); + subY.copyFrom(&sub); + proc22(subY); + } else if (_matrixRow == 0) { + FVector row1 = _matrix._row1; + CStarControlSub6 subX(X_AXIS, angles._x); + CStarControlSub6 subY(Y_AXIS, angles._y); + CStarControlSub6 sub(&subX, &subY); + subX.copyFrom(&sub); + + FMatrix m1 = _sub13.getMatrix(); + FVector tempV1 = _sub13._position; + FVector tempV2, tempV3, tempV4, tempV5, tempV6; + tempV2._y = m1._row1._y * 100000.0; + tempV2._z = m1._row1._z * 100000.0; + tempV3._x = m1._row1._x * 100000.0 + tempV1._x; + tempV4._x = tempV3._x; + tempV3._y = tempV2._y + tempV1._y; + tempV4._y = tempV3._y; + tempV3._z = tempV2._z + tempV1._z; + tempV4._z = tempV3._z; + tempV2._x = m1._row2._x * 100000.0; + tempV2._y = m1._row2._y * 100000.0; + tempV2._z = m1._row2._z * 100000.0; + tempV2._x = m1._row3._x * 100000.0; + tempV2._y = m1._row3._y * 100000.0; + tempV2._z = m1._row3._z * 100000.0; + tempV2._x = tempV2._x + tempV1._x; + tempV2._y = tempV2._y + tempV1._y; + tempV2._z = tempV2._z + tempV1._z; + tempV3._x = tempV2._x + tempV1._x; + tempV3._y = tempV2._y + tempV1._y; + tempV5._x = tempV2._x; + tempV5._y = tempV2._y; + tempV3._z = tempV2._z + tempV1._z; + tempV5._z = tempV2._z; + tempV6._x = tempV3._x; + tempV6._y = tempV3._y; + tempV6._z = tempV3._z; + tempV1._x = tempV1._x - row1._x; + tempV1._y = tempV1._y - row1._y; + tempV1._z = tempV1._z - row1._z; + tempV4._x = tempV3._x - row1._x; + tempV4._y = tempV4._y - row1._y; + tempV4._z = tempV4._z - row1._z; + tempV5._x = tempV2._x - row1._x; + + tempV5._y = tempV5._y - row1._y; + tempV5._z = tempV5._z - row1._z; + tempV6._x = tempV3._x - row1._x; + tempV6._y = tempV6._y - row1._y; + tempV6._z = tempV6._z - row1._z; + + FVector modV1 = tempV1.fn5(&subX); + FVector modV2 = tempV4.fn5(&subX); + FVector modV3 = tempV5.fn5(&subX); + FVector modV4 = tempV6.fn5(&subX); + tempV1 = modV1; + tempV4 = modV2; + tempV5 = modV3; + tempV4 = modV4; + + tempV2._x = tempV4._x - tempV1._x; + tempV2._y = tempV4._y - tempV1._y; + tempV2._z = tempV4._z - tempV1._z; + tempV4._x = tempV2._x; + tempV4._y = tempV2._y; + tempV2._x = tempV5._x - tempV1._x; + tempV4._z = tempV2._z; + tempV5._x = tempV2._x; + tempV2._y = tempV5._y - tempV1._y; + tempV5._y = tempV2._y; + tempV2._z = tempV5._z - tempV1._z; + tempV5._z = tempV2._z; + tempV2._x = tempV6._x - tempV1._x; + tempV2._y = tempV6._y - tempV1._y; + tempV2._z = tempV6._z - tempV1._z; + tempV6 = tempV2; + + tempV4.normalize(); + tempV5.normalize(); + tempV6.normalize(); + tempV1 += row1; + + m1.set(tempV4, tempV5, tempV6); + _sub13.setMatrix(m1); + _sub13.setPosition(tempV1); + } else if (_matrixRow == 1) { + FVector tempV2; + DMatrix m1, m2, sub; + DVector mrow1, mrow2, mrow3; + DVector tempV1, diffV, multV, multV2, tempV3, tempV4, tempV5, tempV6, tempV7; + DVector tempV8, tempV9, tempV10, tempV11, tempV12; + DVector tempV13, tempV14, tempV15, tempV16; + + DMatrix subX(0, _matrix._row1); + DMatrix subY(Y_AXIS, angles._x); + + tempV1 = _matrix._row2 - _matrix._row1; + diffV = tempV1; + diffV.fn5(m1); + sub.fn4(sub, m1, subX); + m1 = sub; + m1.fn1(subX); + subX.fn4(m2, subX, subY); + subX = m2; + + FMatrix m3 = _sub13.getMatrix(); + tempV2 = _sub13._position; + multV._x = m3._row1._x * 1000000.0; + multV._y = m3._row1._y * 1000000.0; + multV._z = m3._row1._z * 1000000.0; + tempV3._x = tempV2._x; + tempV3._y = tempV2._y; + tempV3._z = tempV2._z; + multV2._z = m3._row2._z * 1000000.0; + + tempV1._x = multV._x + tempV3._x; + tempV1._y = multV._y + tempV3._y; + tempV1._z = multV._z + tempV3._z; + mrow3._z = 0.0; + mrow3._y = 0.0; + mrow3._x = 0.0; + multV2._x = m3._row2._x * 1000000.0; + multV2._y = m3._row2._y * 1000000.0; + mrow1 = tempV1; + multV = multV2 + tempV3; + mrow2 = multV; + + tempV7._z = m3._row3._z * 1000000.0 + tempV3._z; + tempV7._y = m3._row3._y * 1000000.0 + tempV3._y; + tempV7._x = m3._row3._x * 1000000.0 + tempV3._x; + + mrow3 = tempV8; + DVector *v = tempV3.fn1(tempV9, subX); + tempV3 = *v; + v = mrow1.fn1(tempV10, subX); + mrow1 = *v; + v = mrow2.fn1(tempV11, subX); + mrow2 = *v; + v = mrow3.fn1(tempV12, subX); + mrow3 = *v; + + v = tempV3.fn1(tempV13, m1); + tempV3 = *v; + v = mrow1.fn1(tempV14, m1); + mrow1 = *v; + v = mrow2.fn1(tempV15, m1); + mrow2 = *v; + v = mrow3.fn1(tempV16, m1); + mrow3 = *v; + + mrow1 -= tempV3; + mrow2 -= tempV3; + mrow3 -= tempV3; + mrow1.normalize(); + mrow2.normalize(); + mrow3.normalize(); + tempV16 = tempV3; + + m3.set(mrow1, mrow2, mrow3); + _sub13.setMatrix(m3); + _sub13.setPosition(tempV16); + } } -bool CStarControlSub12::setArrayVector(const FVector &v) { - if (_currentIndex >= 2) +bool CStarControlSub12::addMatrixRow(const FVector &v) { + if (_matrixRow >= 2) return false; - error("TODO: CStarControlSub12::setArrayVector"); + CStar20Data data; + _handlerP->copyTo(&data); + deleteHandler(); + + FVector &row = _matrix[++_matrixRow]; + row = v; + setupHandler(&data); + return true; } -bool CStarControlSub12::proc35() { - if (_currentIndex == -1) +bool CStarControlSub12::removeMatrixRow() { + if (_matrixRow == -1) return false; - error("TODO: CStarControlSub12::proc35"); + CStar20Data data; + _handlerP->copyTo(&data); + deleteHandler(); + + --_matrixRow; + setupHandler(&data); + return true; } void CStarControlSub12::proc36(double *v1, double *v2, double *v3, double *v4) { @@ -248,7 +432,7 @@ void CStarControlSub12::save(SimpleFile *file, int indent) { bool CStarControlSub12::setupHandler(const CStar20Data *src) { CStarControlSub20 *handler = nullptr; - switch (_currentIndex) { + switch (_matrixRow) { case -1: handler = new CStarControlSub21(src); break; @@ -281,15 +465,143 @@ void CStarControlSub12::deleteHandler() { } void CStarControlSub12::fn1(CStarControlSub13 *sub13, const FVector &v) { - // TODO + if (_matrixRow == 1) { + FMatrix m1 = sub13->getMatrix(); + FMatrix m2 = _sub13.getMatrix(); + FVector v1 = sub13->_position; + FVector v2 = _sub13._position; + + _handlerP->proc8(v2, v1, m2, m1); + CStarVector *sv = new CStarVector(this, v); + _handlerP->setVector(sv); + } } void CStarControlSub12::fn2(FVector v1, FVector v2, FVector v3) { - // TODO + if (_matrixRow == -1) { + FVector tempV; + tempV._z = _sub13._field10; + v3._z = v1._z; + tempV._x = _sub13._fieldD0 * v1._y * v1._z / _sub13._fieldC8; + v3._y = _sub13._fieldCC * tempV._z * v3._x / _sub13._fieldC8; + v3._x = _sub13._fieldCC * v1._x * v1._z / _sub13._fieldC8 - _sub13._valArray[2]; + tempV._y = _sub13._fieldD0 * tempV._z * v3._y / _sub13._fieldC8; + tempV._x = tempV._x - _sub13._valArray[2]; + + v3.normalize(); + tempV.normalize(); + + FMatrix matrix = _sub13.getMatrix(); + const FVector &pos = _sub13._position; + _handlerP->proc10(v3, tempV, pos, matrix); + + CStarVector *sv = new CStarVector(this, v2); + _handlerP->setVector(sv); + } } void CStarControlSub12::fn3(CStarControlSub13 *sub13, const FVector &v) { - // TODO + if (_matrixRow != 0) + return; + + DMatrix m1; + DVector tempV1 = _matrix._row1; + DMatrix m2(0, tempV1); + + tempV1 = v - _matrix._row1; + tempV1.fn5(m1); + + DMatrix m3; + const DMatrix *m = m1.fn4(m3, m1, m2); + m1 = *m; + m1.fn1(m2); + + DVector tempV2 = _sub13._position; + DMatrix m4; + m4._row1 = sub13->_position; + m4._row2 = DVector(0.0, 0.0, 0.0); + m4._row3 = DVector(0.0, 0.0, 0.0); + m4._row4 = DVector(0.0, 0.0, 0.0); + + FMatrix m5 = sub13->getMatrix(); + DVector tempV3, tempV4; + tempV4._x = m5._row1._x * 1000000.0 + m4._row1._x; + tempV4._y = m5._row1._y * 1000000.0 + m4._row1._y; + tempV4._z = m5._row1._z * 1000000.0 + m4._row1._z; + tempV3._x = m5._row2._x * 1000000.0 + m4._row1._x; + tempV3._y = m5._row2._y * 1000000.0 + m4._row1._y; + tempV3._z = m5._row2._z * 1000000.0 + m4._row1._z; + m4._row3 = tempV4; + m4._row2 = tempV3; + + tempV4._x = m5._row3._x * 1000000.0; + tempV4._y = m5._row3._y * 1000000.0; + tempV3._x = tempV4._x + m4._row1._x; + tempV3._y = tempV4._y + m4._row1._y; + tempV3._z = m5._row3._z * 1000000.0 + m4._row1._z; + m4._row4 = tempV3; + + DVector *dv = tempV2.fn1(tempV3, m2); + tempV3 = *dv; + dv = m4._row1.fn1(tempV3, m2); + m4._row1 = *dv; + dv = m4._row3.fn1(tempV3, m2); + m4._row3 = *dv; + dv = m4._row2.fn1(tempV3, m2); + m4._row2 = *dv; + dv = m4._row4.fn1(tempV3, m2); + m4._row4 = *dv; + + // Find the angle that gives the minimum distance + DVector tempV5; + double minDistance = 1.0e20; + int minDegree = 0; + for (int degree = 0; degree < 360; ++degree) { + tempV5 = m4._row1; + tempV5.fn2((double)degree); + double distance = tempV2.getDistance(tempV5); + + if (distance < minDistance) { + minDistance = distance; + minDegree = degree; + } + } + + m4._row1.fn2((double)minDegree); + m4._row2.fn2((double)minDegree); + m4._row3.fn2((double)minDegree); + m4._row4.fn2((double)minDegree); + dv = m4._row1.fn1(tempV3, m1); + m4._row1 = *dv; + dv = m4._row3.fn1(tempV3, m1); + m4._row3 = *dv; + dv = m4._row2.fn1(tempV3, m1); + m4._row2 = *dv; + dv = m4._row4.fn1(tempV3, m1); + m4._row4 = *dv; + + m4._row3._x -= m4._row1._x; + m4._row3._y -= m4._row1._y; + m4._row3._z -= m4._row1._z; + m4._row2._x -= m4._row1._x; + m4._row2._y -= m4._row1._y; + m4._row2._z = m4._row2._z - m4._row1._z; + + m4._row4._x = m4._row4._x - m4._row1._x; + m4._row4._y = m4._row4._y - m4._row1._y; + m4._row4._z = m4._row4._z - m4._row1._z; + + m4._row3.normalize(); + m4._row2.normalize(); + m4._row4.normalize(); + m5.set(m4._row3, m4._row2, m4._row4); + + FVector tempV6 = m4._row1; + FMatrix m6 = _sub13.getMatrix(); + _handlerP->proc8(_sub13._position, tempV6, m6, m5); + + CStarVector *sv = new CStarVector(this, v); + _handlerP->setVector(sv); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub12.h b/engines/titanic/star_control/star_control_sub12.h index fbd7b88f9d..c36960e24a 100644 --- a/engines/titanic/star_control/star_control_sub12.h +++ b/engines/titanic/star_control/star_control_sub12.h @@ -38,8 +38,8 @@ private: static FMatrix *_matrix1; static FMatrix *_matrix2; private: - int _currentIndex; - FVector _array[3]; + int _matrixRow; + FMatrix _matrix; CStarControlSub20 *_handlerP; CStarControlSub13 _sub13; int _field108; @@ -100,11 +100,11 @@ public: /** * Sets the viewport position within the starfield */ - virtual void setViewportPosition(const FPoint &pt); + virtual void setViewportPosition(const FPoint &angles); - virtual int getCurrentIndex() const { return _currentIndex; } - virtual bool setArrayVector(const FVector &v); - virtual bool proc35(); + virtual int getMatrixRow() const { return _matrixRow; } + virtual bool addMatrixRow(const FVector &v); + virtual bool removeMatrixRow(); virtual void proc36(double *v1, double *v2, double *v3, double *v4); /** diff --git a/engines/titanic/star_control/star_control_sub13.cpp b/engines/titanic/star_control/star_control_sub13.cpp index e82ad3a3f1..190ae20179 100644 --- a/engines/titanic/star_control/star_control_sub13.cpp +++ b/engines/titanic/star_control/star_control_sub13.cpp @@ -68,6 +68,7 @@ void CStarControlSub13::copyFrom(const CStarControlSub13 *src) { _position = src->_position; _fieldC = src->_field18; _field10 = src->_field1C; + error("TODO: Remainder of CStarControlSub13::copyFrom"); } } @@ -116,8 +117,7 @@ void CStarControlSub13::setPosition(const FVector &v) { } void CStarControlSub13::setPosition(const CStarControlSub6 *sub6) { - FVector vector; - _position.fn5(&vector, sub6); + _position.fn5(sub6); _position = sub6->_row1; _flag = false; } @@ -163,12 +163,10 @@ void CStarControlSub13::fn12() { CStarControlSub6 m2(Y_AXIS, g_vm->getRandomNumber(359)); CStarControlSub6 m3(Z_AXIS, g_vm->getRandomNumber(359)); - CStarControlSub6 s1, s2; - CStarControlSub6 *s; - s = CStarControlSub6::setup(&s1, &m1, &m2); - s = CStarControlSub6::setup(&s2, s, &m3); + CStarControlSub6 s1(&m1, &m2); + CStarControlSub6 s2(&s1, &m3); - m1.copyFrom(*s); + m1.copyFrom(s2); _matrix.fn2(m1); _flag = false; } @@ -225,9 +223,8 @@ void CStarControlSub13::fn16(int index, const FVector &src, FVector &dest) { FVector CStarControlSub13::fn17(int index, const FVector &src) { FVector dest; - FVector tv; CStarControlSub6 sub6 = getSub1(); - src.fn5(&tv, &sub6); + FVector tv = src.fn5(&sub6); dest._x = (_valArray[index] + tv._x) * _fieldC8 / (_fieldCC * tv._z); @@ -238,9 +235,8 @@ FVector CStarControlSub13::fn17(int index, const FVector &src) { FVector CStarControlSub13::fn18(int index, const FVector &src) { FVector dest; - FVector tv; CStarControlSub6 sub6 = getSub2(); - src.fn5(&tv, &sub6); + FVector tv = src.fn5(&sub6); dest._x = (_valArray[index] + tv._x) * _fieldC8 / (_fieldCC * tv._z); @@ -257,13 +253,13 @@ void CStarControlSub13::fn19(double *v1, double *v2, double *v3, double *v4) { } void CStarControlSub13::reset() { - const double FACTOR = 3.1415927 * 0.0055555557; + const double FACTOR = 2 * M_PI / 360.0; _sub2.copyFrom(_matrix); _sub2._vector._x = _position._x; _sub2._vector._y = _position._y; _sub2._vector._z = _position._z; - _sub2.fn3(_sub1); + _sub2.fn4(&_sub1); double widthV = (double)_width * 0.5; double heightV = (double)_height * 0.5; diff --git a/engines/titanic/star_control/star_control_sub20.cpp b/engines/titanic/star_control/star_control_sub20.cpp index ca60cc9948..fd12573fac 100644 --- a/engines/titanic/star_control/star_control_sub20.cpp +++ b/engines/titanic/star_control/star_control_sub20.cpp @@ -27,7 +27,7 @@ namespace Titanic { CStarControlSub20::CStarControlSub20(const CStar20Data *src) { _lockCounter = 0; - _dataP = nullptr; + _starVector = nullptr; if (src) { copyFrom(src); @@ -90,7 +90,7 @@ void CStarControlSub20::proc7() { } } -void CStarControlSub20::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { +void CStarControlSub20::proc11(CErrorCode &errorCode, FVector &v, FMatrix &m) { if (_size > 0.0) { v._x += m._row3._x * _size; v._y += m._row3._y * _size; @@ -100,15 +100,15 @@ void CStarControlSub20::proc11(CErrorCode &errorCode, FVector &v, const FMatrix } } -void CStarControlSub20::setData(void *data) { +void CStarControlSub20::setVector(CStarVector *sv) { clear(); - _dataP = (byte *)data; + _starVector = sv; } void CStarControlSub20::clear() { - if (_dataP) { - delete _dataP; - _dataP = nullptr; + if (_starVector) { + delete _starVector; + _starVector = nullptr; } } diff --git a/engines/titanic/star_control/star_control_sub20.h b/engines/titanic/star_control/star_control_sub20.h index 49b63d5d5d..eed5e94ad1 100644 --- a/engines/titanic/star_control/star_control_sub20.h +++ b/engines/titanic/star_control/star_control_sub20.h @@ -24,6 +24,7 @@ #define TITANIC_STAR_CONTROL_SUB20_H #include "titanic/support/simple_file.h" +#include "titanic/star_control/base_star.h" #include "titanic/star_control/error_code.h" #include "titanic/star_control/fmatrix.h" @@ -43,7 +44,7 @@ struct CStar20Data { class CStarControlSub20 : public CStar20Data { public: int _lockCounter; - byte *_dataP; + CStarVector *_starVector; public: CStarControlSub20(const CStar20Data *src); virtual ~CStarControlSub20(); @@ -57,12 +58,8 @@ public: virtual void proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) {} virtual void proc9(FVector &v1, FVector &v2, FMatrix &matrix) {} virtual void proc10(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m) {} - virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); - - /** - * Set the data - */ - virtual void setData(void *data); + virtual void proc11(CErrorCode &errorCode, FVector &v, FMatrix &m); + virtual void setVector(CStarVector *sv); /** * Clear the class diff --git a/engines/titanic/star_control/star_control_sub21.cpp b/engines/titanic/star_control/star_control_sub21.cpp index 1e676b7703..a70460aa53 100644 --- a/engines/titanic/star_control/star_control_sub21.cpp +++ b/engines/titanic/star_control/star_control_sub21.cpp @@ -53,18 +53,22 @@ void CStarControlSub21::proc10(const FVector &v1, const FVector &v2, const FVect incLockCount(); } -void CStarControlSub21::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { +void CStarControlSub21::proc11(CErrorCode &errorCode, FVector &v, FMatrix &m) { if (_sub24.get8()) { + decLockCount(); int val = _sub24.proc5(errorCode, v, m); if (val == 1) incLockCount(); if (val == 2) { proc7(); - error("TODO: _dataP"); + if (_starVector) + _starVector->apply(); } } else if (_size != 0.0) { - // TODO - error("TODO"); + v._x += m._row3._x * _size; + v._y += m._row3._y * _size; + v._z += m._row3._z * _size; + errorCode.set(); } } diff --git a/engines/titanic/star_control/star_control_sub21.h b/engines/titanic/star_control/star_control_sub21.h index 66ce535993..17e0a427a6 100644 --- a/engines/titanic/star_control/star_control_sub21.h +++ b/engines/titanic/star_control/star_control_sub21.h @@ -37,7 +37,7 @@ public: virtual void proc9(FVector &v1, FVector &v2, FMatrix &matrix); virtual void proc10(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m); - virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); + virtual void proc11(CErrorCode &errorCode, FVector &v, FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub22.cpp b/engines/titanic/star_control/star_control_sub22.cpp index b76d96e47a..68681c0a6f 100644 --- a/engines/titanic/star_control/star_control_sub22.cpp +++ b/engines/titanic/star_control/star_control_sub22.cpp @@ -37,8 +37,23 @@ void CStarControlSub22::proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2 incLockCount(); } -void CStarControlSub22::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { - // TODO +void CStarControlSub22::proc11(CErrorCode &errorCode, FVector &v, FMatrix &m) { + if (_sub27.get8()) { + decLockCount(); + int val = _sub27.proc5(errorCode, v, m); + if (val == 1) + incLockCount(); + if (val == 2) { + proc7(); + if (_starVector) + _starVector->apply(); + } + } else if (_size != 0.0) { + v._x += m._row3._x * _size; + v._y += m._row3._y * _size; + v._z += m._row3._z * _size; + errorCode.set(); + } } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub22.h b/engines/titanic/star_control/star_control_sub22.h index 61f60b10f1..704cfa7d6c 100644 --- a/engines/titanic/star_control/star_control_sub22.h +++ b/engines/titanic/star_control/star_control_sub22.h @@ -36,7 +36,7 @@ public: virtual ~CStarControlSub22() {} virtual void proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2); - virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); + virtual void proc11(CErrorCode &errorCode, FVector &v, FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub23.cpp b/engines/titanic/star_control/star_control_sub23.cpp index 4587fd3e27..ad4cb65f8a 100644 --- a/engines/titanic/star_control/star_control_sub23.cpp +++ b/engines/titanic/star_control/star_control_sub23.cpp @@ -37,10 +37,8 @@ CStarControlSub23::CStarControlSub23() : _row1(0.0, 1000000.0, 0.0) { _field48 = 0; _field4C = 0; _field54 = 0; - _field58 = 0; - _field5C = 0; - _field60 = 0; - _field64 = 0; + _field58 = 0.0; + _field60 = 0.0; } void CStarControlSub23::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) { @@ -52,7 +50,7 @@ void CStarControlSub23::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2 _field58 = 0; _field8 = 0; _field34 = 0; - _field5C = 1.875; + _field58 = 1.0; _field40 = -1; _field44 = -1; _field48 = -1; @@ -62,11 +60,10 @@ void CStarControlSub23::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2 void CStarControlSub23::proc3(const FMatrix &m1, const FMatrix &m2) { _row1.clear(); _row2.clear(); - _field58 = 0; + _field58 = 1.0; _field24 = 0.0; _field8 = 0; _field34 = 0; - _field5C = 1.875; } void CStarControlSub23::proc4(FVector &v1, FVector &v2, FMatrix &m) { @@ -82,8 +79,7 @@ void CStarControlSub23::proc4(FVector &v1, FVector &v2, FMatrix &m) { _field44 = -1; _field48 = -1; _field4C = -1; - _field58 = 0; - _field5C = 1.875; + _field58 = 1.0; } void CStarControlSub23::proc6(int val1, int val2, float val) { diff --git a/engines/titanic/star_control/star_control_sub23.h b/engines/titanic/star_control/star_control_sub23.h index 9e90e021a2..d8233ec91d 100644 --- a/engines/titanic/star_control/star_control_sub23.h +++ b/engines/titanic/star_control/star_control_sub23.h @@ -46,10 +46,8 @@ protected: int _field4C; Common::Array<double> _powers; int _field54; - int _field58; - double _field5C; + double _field58; double _field60; - double _field64; CStarControlSub25 _sub25; public: CStarControlSub23(); diff --git a/engines/titanic/star_control/star_control_sub24.cpp b/engines/titanic/star_control/star_control_sub24.cpp index 27f29b41ca..28b69f71a7 100644 --- a/engines/titanic/star_control/star_control_sub24.cpp +++ b/engines/titanic/star_control/star_control_sub24.cpp @@ -26,18 +26,142 @@ namespace Titanic { void CStarControlSub24::proc3(const FMatrix &m1, const FMatrix &m2) { - + CStarControlSub23::proc3(m1, m2); + _sub25.fn1(m1, m2); + _field60 = 0.1; + _field58 = 0.0; + _field40 = _field44 = _field48 = -1; + _field8 = 1; } void CStarControlSub24::proc4(FVector &v1, FVector &v2, FMatrix &m) { CStarControlSub23::proc4(v1, v2, m); - // TODO + if (_field24 > 8000.0) { + _field8 = 1; + _field34 = 1; + proc6(120, 4, _field24 - 8000.0); + } + + FVector row3 = m._row3; + double mult = _row3._x * row3._x + _row3._y * row3._y+ _row3._z * row3._z; + _field58 = 1.0; + + bool flag = false; + if (mult < 1.0) { + if (mult >= 1.0 - 1.0e-10) + flag = true; + } else { + if (mult <= 1.0 + 1.0e-10) + flag = true; + } + + if (!flag) { + const FVector *tv; + FVector tempV1, tempV2; + FVector::addAndNormalize(tempV1, row3, _row3); + tv = FVector::addAndNormalize(tempV2, row3, tempV1); + tempV1 = *tv; + + tv = FVector::addAndNormalize(tempV2, row3, tempV1); + tempV1 = *tv; + + tv = FVector::addAndNormalize(tempV2, row3, tempV1); + tempV1 = *tv; + + FMatrix m1; + m1.fn1(tempV1); + _sub25.fn1(m, m1); + + _field58 = 0.0; + _field60 = 0.1; + _field8 = 1; + } } -int CStarControlSub24::proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m) { - // TODO - return 0; +int CStarControlSub24::proc5(CErrorCode &errorCode, FVector &v, FMatrix &m) { + FVector v1, v2, v3, v4; + const FVector *tv; + + if (_field8) + return 0; + + if (_field58 < 1.0) { + _sub25.fn2(_field60 + _field58, m); + errorCode.set(); + return 1; + } + + if (!_field34) { + _field8 = 0; + return 2; + } + + v2 = m._row3; + v3 = _row2 - v; + v3.normalize(); + + double val = m._row3._x * v3._x + m._row3._y * v3._y + m._row3._z * v3._z; + bool flag = false; + if (val > 1.0) { + if (val >= 1.0 - 1.0e-10) + flag = true; + } else { + if (val <= 1.0 + 1.0e-10) + flag = true; + } + + if (!flag) { + v2.addAndNormalize(v1, v2, v3); + tv = v2.addAndNormalize(v4, v2, v1); + v1 = *tv; + tv = v2.addAndNormalize(v4, v2, v1); + v1 = *tv; + tv = v2.addAndNormalize(v4, v2, v1); + v1 = *tv; + + m.fn1(v1); + v2 = v1; + } + + if (_field40 >= 0) { + double powVal = _powers[_field40]; + v1 = v2 * powVal; + v += v1; + + --_field40; + errorCode.set(); + return 1; + } + + if (_field44 > 0) { + v1._z = v2._z * _field38; + v1._x = v2._x * _field38; + v._x = v1._x + v._x; + v._y = v2._y * _field38 + v._y; + v._z = v1._z + v._z; + + --_field44; + errorCode.set(); + return 1; + } + + if (_field48 >= 0) { + double powVal = _powers[31 - _field48]; + v1._y = v2._y * powVal; + v1._z = v2._z * powVal; + v1._x = v2._x * powVal; + v._y = v1._y + v._y; + v._z = v1._z + v._z; + v._x = v._x + v1._x; + + --_field48; + errorCode.set(); + return 1; + } + + _field8 = 0; + return 2; } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub24.h b/engines/titanic/star_control/star_control_sub24.h index 34b9cf4eac..16f53610ec 100644 --- a/engines/titanic/star_control/star_control_sub24.h +++ b/engines/titanic/star_control/star_control_sub24.h @@ -33,7 +33,7 @@ public: virtual void proc3(const FMatrix &m1, const FMatrix &m2); virtual void proc4(FVector &v1, FVector &v2, FMatrix &m); - virtual int proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m); + virtual int proc5(CErrorCode &errorCode, FVector &v, FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub25.cpp b/engines/titanic/star_control/star_control_sub25.cpp index 73c72e6a77..a8e13473f2 100644 --- a/engines/titanic/star_control/star_control_sub25.cpp +++ b/engines/titanic/star_control/star_control_sub25.cpp @@ -21,7 +21,7 @@ */ #include "titanic/star_control/star_control_sub25.h" -#include "common/textconsole.h" +#include "titanic/star_control/dmatrix.h" namespace Titanic { @@ -31,4 +31,19 @@ void CStarControlSub25::fn1(const FMatrix &m1, const FMatrix &m2) { } +void CStarControlSub25::fn2(double val, FMatrix &m) { + if (val < 0.0) { + m = _matrix1; + } else if (val > 1.0) { + m = _matrix2; + } else { + CStarControlSub26 sub26; + sub26.fn5(val, &_sub2, &sub26); + + DMatrix m1; + m1.fn3(&sub26); + m = m1; + } +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub25.h b/engines/titanic/star_control/star_control_sub25.h index 85692cf62d..cb7d61023e 100644 --- a/engines/titanic/star_control/star_control_sub25.h +++ b/engines/titanic/star_control/star_control_sub25.h @@ -36,6 +36,7 @@ public: CStarControlSub26 _sub2; public: void fn1(const FMatrix &m1, const FMatrix &m2); + void fn2(double val, FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub26.cpp b/engines/titanic/star_control/star_control_sub26.cpp index 546a3e9fae..91dd1576f9 100644 --- a/engines/titanic/star_control/star_control_sub26.cpp +++ b/engines/titanic/star_control/star_control_sub26.cpp @@ -42,4 +42,8 @@ void CStarControlSub26::copyFrom(const CStarControlSub26 *src) { _sub = src->_sub; } +void CStarControlSub26::fn5(double val, CStarControlSub26 *s1, CStarControlSub26 *s2) { + // TODO +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub26.h b/engines/titanic/star_control/star_control_sub26.h index 9023da906c..670007efa8 100644 --- a/engines/titanic/star_control/star_control_sub26.h +++ b/engines/titanic/star_control/star_control_sub26.h @@ -50,7 +50,7 @@ public: void copyFrom(const CStarControlSub26 *src); double fn1() const; - + void fn5(double val, CStarControlSub26 *s1, CStarControlSub26 *s2); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub27.cpp b/engines/titanic/star_control/star_control_sub27.cpp index 706e947a05..e9559b250b 100644 --- a/engines/titanic/star_control/star_control_sub27.cpp +++ b/engines/titanic/star_control/star_control_sub27.cpp @@ -37,12 +37,10 @@ void CStarControlSub27::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2 if (m1 != m2) { _sub25.fn1(m1, m2); - _field58 = 0; - _field5C = 0.0; + _field58 = 0.0; if (_field4C == 0) { - _field60 = -1.5881868e-23; - _field64 = 1.4499999; + _field60 = 0.1; _field8 = 1; } else { _field60 = 1.0 / (double)v24; @@ -51,7 +49,7 @@ void CStarControlSub27::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2 } } -int CStarControlSub27::proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m) { +int CStarControlSub27::proc5(CErrorCode &errorCode, FVector &v, FMatrix &m) { // TODO return 0; } diff --git a/engines/titanic/star_control/star_control_sub27.h b/engines/titanic/star_control/star_control_sub27.h index 801591294e..f8aa3d6ce7 100644 --- a/engines/titanic/star_control/star_control_sub27.h +++ b/engines/titanic/star_control/star_control_sub27.h @@ -32,7 +32,7 @@ public: virtual ~CStarControlSub27() {} virtual void proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2); - virtual int proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m); + virtual int proc5(CErrorCode &errorCode, FVector &v, FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub5.cpp b/engines/titanic/star_control/star_control_sub5.cpp index 4ca22ff922..8c332975c6 100644 --- a/engines/titanic/star_control/star_control_sub5.cpp +++ b/engines/titanic/star_control/star_control_sub5.cpp @@ -26,6 +26,8 @@ namespace Titanic { +#define MKTAG_BE(a3,a2,a1,a0) ((uint32)((a3) | ((a2) << 8) | ((a1) << 16) | ((a0) << 24))) + void CStarControlSub5::SubEntry::clear() { _data1.clear(); _data2.clear(); @@ -37,7 +39,7 @@ bool CStarControlSub5::SineTable::setup() { if (_data.empty()) { _data.resize(1024); for (int idx = 0; idx < 1024; ++idx) - _data[idx] = sin((double)idx * 6.283185307179586 * 0.001953125); + _data[idx] = sin((double)idx * 2 * M_PI / 512.0); } return true; @@ -63,7 +65,7 @@ bool CStarControlSub5::setup() { bool CStarControlSub5::setup2(int val1, int val2) { // TODO: Original set an explicit random seed here. Could be // problematic if following random values need to be deterministic - const double FACTOR = 3.1415927 * 0.0055555557; + const double FACTOR = 2 * M_PI / 360.0; const int VALUES1[] = { 0x800, 0xC00, 0x1000, 0x1400, 0x1800 }; const int VALUES2[] = { 0xF95BCD, 0xA505A0, 0xFFAD43, 0x98F4EB, 0xF3EFA5, 0, @@ -76,9 +78,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { for (int idx = 0; idx < 256; ++idx) { if (idx == 0) { e->_field0 = 0x4C8; - e->_field4 = 0x40; - e->_field5 = 0x40; - e->_field6 = 0x40; + e->_pixel1 = 0x40; + e->_pixel2 = 0x40; + e->_pixel3 = 0x40; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 7.0; @@ -86,9 +88,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x574; - e->_field4 = 0x7f; - e->_field5 = 0; - e->_field6 = 0; + e->_pixel1 = 0x7f; + e->_pixel2 = 0; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 3.0; @@ -96,9 +98,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x603; - e->_field4 = 0; - e->_field5 = 0; - e->_field6 = 0xff; + e->_pixel1 = 0; + e->_pixel2 = 0; + e->_pixel3 = 0xff; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = 0; @@ -106,9 +108,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x712; - e->_field4 = 0xff; - e->_field5 = 0; - e->_field6 = 0; + e->_pixel1 = 0xff; + e->_pixel2 = 0; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 2.0; @@ -116,9 +118,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0xe7f; - e->_field4 = 0xe6; - e->_field5 = 0xbe; - e->_field6 = 0; + e->_pixel1 = 0xe6; + e->_pixel2 = 0xbe; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 1.0; @@ -126,9 +128,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x173f; - e->_field4 = 0xf0; - e->_field5 = 0xf0; - e->_field6 = 0xe6; + e->_pixel1 = 0xf0; + e->_pixel2 = 0xf0; + e->_pixel3 = 0xe6; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 3.0; @@ -136,9 +138,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x2ab8; - e->_field4 = 0x28; - e->_field5 = 0x32; - e->_field6 = 0x28; + e->_pixel1 = 0x28; + e->_pixel2 = 0x32; + e->_pixel3 = 0x28; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 1.0; @@ -146,9 +148,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x40ac; - e->_field4 = 0x0; - e->_field5 = 0xbe; - e->_field6 = 0xf0; + e->_pixel1 = 0x0; + e->_pixel2 = 0xbe; + e->_pixel3 = 0xf0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 2.0; @@ -156,27 +158,27 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x539c; - e->_field4 = 0x20; - e->_field5 = 0x20; - e->_field6 = 0x20; + e->_pixel1 = 0x20; + e->_pixel2 = 0x20; + e->_pixel3 = 0x20; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 17.0; - e->_field14 = 0.00390625; + e->_field14 = 1 / 256.0; } else { for (int ctr = 0; ctr < 5; ++ctr) { e->_field0 = static_cast<int>(g_vm->getRandomFloat() * 1350.0 - 675.0) + VALUES1[idx]; int val = VALUES2[g_vm->getRandomNumber(15)]; - e->_field4 = val & 0xff; - e->_field5 = (val >> 8) & 0xff; - e->_field6 = (val >> 16) & 0xff; + e->_pixel1 = val & 0xff; + e->_pixel2 = (val >> 8) & 0xff; + e->_pixel3 = (val >> 16) & 0xff; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * (double)g_vm->getRandomNumber(15); e->_field14 = ((double)g_vm->getRandomNumber(0xfffffffe) - * 50.0 * 0.000015259022) * 0.00390625; + * 50.0 / 65536.0) / 256.0; } } } @@ -194,13 +196,23 @@ void CStarControlSub5::proc2(CStarControlSub6 *sub6, FVector *vector, double v1, const int VALUES[] = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4 }; double val1 = sub12->proc25(); int val2 = sub12->proc27(); + if (!_flag) + return; + + int f1, f3, size2, size1; + double f2, f4, f5, f6, f7, f8, f9; + double f10, f11, f12, f13, f14, f15, f16, f17, f18, f19; + double f20, f21, f22, f23, f24, f25, f26, f27, f28; + double f34, f35, f36, f37, f38, f39, f40; + double f41, f42, f43, f44, f45, f46; + FVector tempV; if (v3 >= 6.0e9) { int count, start; if (vector->_x != 0.0 && (vector->_y != 0.0 || vector->_z != 0.0)) { - // TODO: Non-sensical randSeed((int)vector->_x); + // WORKAROUND: Ignoring non-sensical randSeed((int)vector->_x); count = VALUES[g_vm->getRandomNumber(15)]; - start = g_vm->getRandomNumber(255); + start = 5 * g_vm->getRandomNumber(255); } else { count = 9; start = 0; @@ -208,45 +220,280 @@ void CStarControlSub5::proc2(CStarControlSub6 *sub6, FVector *vector, double v1, Entry *entryP = &_entries[start]; for (; count > 0; --count, ++entryP) { - //eax=sineIndex1, ecx=sineIndex2, - int sineIndex1 = (entryP->_field8 * _multiplier) & 0x1ff; - int sineIndex2 = (entryP->_fieldC * _multiplier + entryP->_fieldC) & 0x1ff; - - double t1 = _sineTable[sineIndex2]; - double t2 = sin(_sineTable[sineIndex1] * entryP->_field10); - double t3 = cos(_sineTable[sineIndex1] * entryP->_field10); - double t4 = _sineTable[sineIndex2 + 512]; - double t5 = t3 * t4; - t3 = t3 * t1; - double t6 = entryP->_field14 * t5; - double t7 = t2 * entryP->_field14; - double t8 = entryP->_field14 * t3; - double t9 = -(t2 * t4 * entryP->_field14); - double t10 = t3 * entryP->_field14; - double t11 = -(t2 * t1 * entryP->_field14); - t4 = -(t1 * entryP->_field14); - t1 = t4 * entryP->_field14; - - _sub1._row1._x = t6; - _sub1._row1._y = t2 * entryP->_field14; - _sub1._row1._z = entryP->_field14 * t3; - _sub1._row2._x = -(t2 * t4 * entryP->_field14); - _sub1._row2._y = t3 * entryP->_field14; - _sub1._row2._z = -(t2 * t1 * entryP->_field14); - _sub1._row3._x = -(t1 * entryP->_field14); - _sub1._row3._z = t4 * entryP->_field14; - - double t12 = entryP->_field0; - _sub1._vector._x = t12 * t5 + vector->_x; - _sub1._vector._y = t12 * t2 + vector->_y; - _sub1._vector._z = t12 * t3 + vector->_z; - - // TODO - warning("TODO: %f %f %f %f %f %f %d", t7, t8, t9, t10, t11, val1, val2); + f1 = _multiplier * entryP->_field8; + f2 = entryP->_field14; + f3 = (f1 + entryP->_fieldC) & 0x1FF; + f4 = _sineTable[f1 & 0x1FF] * entryP->_field10; + f5 = _sineTable[f3]; + f6 = cos(f4); + f7 = sin(f4); + f8 = _sineTable[f3 + 128]; + f9 = f7; + f10 = f6 * f8; + f11 = f6; + f12 = f6 * f5; + f13 = f2 * f10; + f14 = f8 * f2; + f15 = f9 * f2; + f16 = f2 * f12; + f17 = -(f7 * f8 * f2); + f18 = f11 * f2; + f19 = -(f9 * f5 * f2); + f20 = -(f5 * f2); + f21 = f14; + _sub1._row1._x = f13; + _sub1._row1._y = f15; + _sub1._row1._z = f16; + _sub1._row2._x = f17; + _sub1._row2._y = f18; + _sub1._row2._z = f19; + _sub1._row3._x = f20; + _sub1._row3._z = f14; + + f22 = (double)entryP->_field0; + _sub1._vector._x = f22 * f10 + vector->_x; + _sub1._vector._y = f9 * f22 + vector->_y; + _sub1._vector._z = f22 * f12 + vector->_z; + _sub2._row1._x = sub6->_row1._x * f13 + f16 * sub6->_row3._x + f15 * sub6->_row2._x; + _sub2._row1._y = f15 * sub6->_row2._y + f16 * sub6->_row3._y + f13 * sub6->_row1._y; + _sub2._row1._z = f16 * sub6->_row3._z + f13 * sub6->_row1._z + f15 * sub6->_row2._z; + _sub2._row2._x = sub6->_row1._x * f17 + f19 * sub6->_row3._x + f18 * sub6->_row2._x; + _sub2._row2._y = f18 * sub6->_row2._y + f17 * sub6->_row1._y + f19 * sub6->_row3._y; + _sub2._row2._z = f18 * sub6->_row2._z + f19 * sub6->_row3._z + f17 * sub6->_row1._z; + _sub2._row3._x = sub6->_row1._x * f20 + f21 * sub6->_row3._x; + _sub2._row3._y = f20 * sub6->_row1._y + f21 * sub6->_row3._y; + _sub2._row3._z = f20 * sub6->_row1._z + f21 * sub6->_row3._z; + + f23 = _sub1._vector._y; + f24 = _sub1._vector._z; + f25 = _sub1._vector._x; + f26 = _sub1._vector._z; + f27 = _sub1._vector._x; + + f28 = _sub1._vector._y; + _sub2._vector._x = sub6->_row1._x * _sub1._vector._x + + sub6->_row3._x * _sub1._vector._z + + sub6->_row2._x * f28 + + sub6->_vector._x; + _sub2._vector._y = f23 * sub6->_row2._y + + f24 * sub6->_row3._y + + f25 * sub6->_row1._y + + sub6->_vector._y; + _sub2._vector._z = f26 * sub6->_row3._z + + f27 * sub6->_row1._z + + f28 * sub6->_row2._z + + sub6->_vector._z; + + size2 = (int)_array[1]._data2.size(); + size1 = (int)_array[1]._data1.size(); + + if (size2 > 0) { + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + FVector &currVector = _array[1]._data2[ctr2]; + GridEntry &gridEntry = _grid[ctr2]; + + f34 = currVector._x; + f35 = currVector._y; + f36 = f35 * _sub2._row2._x; + f37 = currVector._z; + f38 = f37 * _sub2._row3._x + f36; + f39 = f38 + f34 * _sub2._row1._x; + f40 = f39 + _sub2._vector._x; + + gridEntry._x = f40; + gridEntry._y = f37 * _sub2._row3._y + + f35 * _sub2._row2._y + + f34 * _sub2._row1._y + + _sub2._vector._y; + gridEntry._z = f37 * _sub2._row3._z + + f35 * _sub2._row2._z + + f34 * _sub2._row1._z + + _sub2._vector._z; + } + } + + if (val2 <= 0) { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = MKTAG_BE(entryP->_pixel1, entryP->_pixel2, + entryP->_pixel3, 0); + surfaceArea->setColorFromPixel(); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } else { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = entryP->_pixel1; + surfaceArea->setColorFromPixel(); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(0, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + + surfaceArea->_pixel = entryP->_pixel3; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(SA_MODE2); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(1, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } + } + } + + uint pixel1 = 0x81EEF5, pixel2 = 0xF5, pixel3 = 0x810000; + int arrIndex = 0; + + if (v3 >= 200000000.0) { + if (v3 >= 900000000.0) { + if (v3 >= 6000000000.0) { + arrIndex = 3; + if (v3 >= 1.0e10) + arrIndex = 4; + } else { + arrIndex = 2; + } + } else { + arrIndex = 1; } + } else { + arrIndex = 0; } - // TODO + SubEntry &entry = _array[arrIndex]; + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + const FVector &d2v = entry._data2[ctr]; + FVector newV = d2v + *vector; + + f41 = sub6->_row1._x; + f42 = sub6->_row3._x; + f43 = sub6->_row2._x; + f44 = f43 * newV._y; + f45 = f41 * newV._x + f42 * newV._z + f44; + f46 = f45 + sub6->_vector._x; + + gridEntry._x = f46; + gridEntry._y = newV._y * sub6->_row2._y + + newV._z * sub6->_row3._y + + newV._x * sub6->_row1._y + + sub6->_vector._y; + gridEntry._z = newV._z * sub6->_row3._z + + newV._y * sub6->_row2._z + + newV._x * sub6->_row1._z + + sub6->_vector._z; + } + + if (val2 <= 0) { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = pixel1; + surfaceArea->setColorFromPixel(); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } else { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = pixel2; + surfaceArea->setColorFromPixel(); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + + surfaceArea->_pixel = pixel3; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(SA_MODE2); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } } void CStarControlSub5::proc3(CErrorCode *errorCode) { @@ -259,40 +506,85 @@ void CStarControlSub5::fn1() { } bool CStarControlSub5::setupEntry(int width, int height, int index, double val) { - /* if (width < 2 || height < 3) return false; SubEntry &entry = _array[index]; entry.clear(); - int height2 = height - 2; - int height1 = height - 1; - entry._data1.resize((2 * height - 3) * width); - entry._data2.resize(width * height2 + 2); - entry._data2[0] = FVector(0.0, val, 0.0); + const double FACTOR = 2 * M_PI / 360.0; + int d1Count, d2Count, size3, height1; + int ctr, ctr2, idx, offset, f11; + double vx, vy, f5, f6, f7, f8, f9, f10; + + d1Count = width * (2 * height - 3); + d2Count = (height - 2) * width + 2; + entry._data1.resize(d1Count); + entry._data2.resize(d2Count); + + height1 = height - 1; + entry._data2[0]._y = val; + + vy = 180.0 / (double)height1; + vx = 360.0 / (double)width; + + for (ctr = height - 2, idx = 0; ctr > 0; --ctr, vy *= 2) { + f5 = 0.0; + f6 = cos(vy * FACTOR); + f7 = sin(vy * FACTOR); - index = 1; - double vy = 180.0 / (double)height1; - double vx = 360.0 / (double)width; - const double FACTOR = 3.1415927 * 0.0055555557; + if (width > 0) { + f8 = f6 * val; - if (height1 > 1) { - double yAmount = vy; - int width12 = width * 12; - for (int yCtr = height1 - 1; yCtr > 0; --yCtr, yAmount += vy) { - double sineVal = sin(yAmount * FACTOR); + for (int xp = width; xp > 0; --xp, ++idx, f5 += vx) { + f9 = f5 * FACTOR; + f10 = cos(f9) * f7 * val; + FVector &tempV = entry._data2[idx]; + tempV._x = sin(f9) * f7 * val; + tempV._y = f8; + tempV._z = f10; + } + } + } + entry._data2[idx] = FVector(0.0, -1.0, 0.0); + + size3 = width * (height - 3) + 1; + offset = 0; + Data1 *data1P = &entry._data1[0]; + for (ctr = 0; ctr < width; ++ctr, ++size3) { + data1P->_index1 = 0; + data1P->_index2 = size3 - width * (height - 3); + ++data1P; + + data1P->_index1 = d2Count - 1; + data1P->_index2 = size3; + ++data1P; + } - | 0.0 * FACTOR | - | cos(yAmount * FACTOR) * val | - | 0.0 | - |yAmount| + f11 = 1; + for (ctr = 1; ctr < height1; ++ctr, f11 += width) { + data1P = &entry._data1[offset]; + + for (ctr2 = 0; ctr2 < width; ++ctr2) { + data1P->_index1 = ctr2 + f11; + if (ctr2 == width - 1) + data1P->_index2 = f11; + else + data1P->_index2 = ctr2 + f11 + 1; + + ++offset; + ++data1P; + + if (ctr < height - 2) { + data1P->_index1 = ctr2 + f11; + ++offset; + data1P->_index2 = width + ctr2 + f11; + ++data1P; + } } } - // TODO - */ return true; } diff --git a/engines/titanic/star_control/star_control_sub5.h b/engines/titanic/star_control/star_control_sub5.h index 32094f5227..b5e5bb1b6a 100644 --- a/engines/titanic/star_control/star_control_sub5.h +++ b/engines/titanic/star_control/star_control_sub5.h @@ -33,8 +33,14 @@ namespace Titanic { class CStarControlSub12; class CStarControlSub5 { + struct Data1 { + int _index1; + int _index2; + Data1() : _index1(0), _index2(0) {} + }; + struct SubEntry { - Common::Array<FPoint> _data1; + Common::Array<Data1> _data1; Common::Array<FVector> _data2; ~SubEntry() { clear(); } @@ -46,28 +52,23 @@ class CStarControlSub5 { struct Entry { int _field0; - byte _field4; - byte _field5; - byte _field6; + byte _pixel1; + byte _pixel2; + byte _pixel3; int _field8; int _fieldC; double _field10; double _field14; - Entry() : _field0(0), _field4(0), _field5(0), _field6(0), _field8(0), + Entry() : _field0(0), _pixel1(0), _pixel2(0), _pixel3(0), _field8(0), _fieldC(0), _field10(0), _field14(0) {} }; - struct GridEntry { - int _field0; - int _field4; - int _field8; - int _fieldC; - int _field10; + struct GridEntry : public FVector { + FPoint _position; int _field14; - GridEntry() : _field0(0), _field4(0), _field8(0), _fieldC(0), - _field10(0), _field14(0) {} + GridEntry() : FVector(), _field14(0) {} }; /** diff --git a/engines/titanic/star_control/star_control_sub6.cpp b/engines/titanic/star_control/star_control_sub6.cpp index e45d6d2c57..0ced3df9fe 100644 --- a/engines/titanic/star_control/star_control_sub6.cpp +++ b/engines/titanic/star_control/star_control_sub6.cpp @@ -38,6 +38,48 @@ CStarControlSub6::CStarControlSub6(const CStarControlSub6 *src) { copyFrom(src); } +CStarControlSub6::CStarControlSub6(const CStarControlSub6 *s1, const CStarControlSub6 *s2) { + _row1._x = s2->_row1._x * s1->_row1._x + + s1->_row1._z * s2->_row3._x + + s1->_row1._y * s2->_row2._x; + _row1._y = s1->_row1._x * s2->_row1._y + + s2->_row3._y * s1->_row1._z + + s2->_row2._y * s1->_row1._y; + _row1._z = s1->_row1._x * s2->_row1._z + + s2->_row3._z * s1->_row1._z + + s2->_row2._z * s1->_row1._y; + _row2._x = s2->_row1._x * s1->_row2._x + + s1->_row2._y * s2->_row2._x + + s1->_row2._z * s2->_row3._x; + _row2._y = s1->_row2._y * s2->_row2._y + + s1->_row2._z * s2->_row3._y + + s2->_row1._y * s1->_row2._x; + _row2._z = s2->_row1._z * s1->_row2._x + + s1->_row2._y * s2->_row2._z + + s1->_row2._z * s2->_row3._z; + _row3._x = s2->_row1._x * s1->_row3._x + + s1->_row3._y * s2->_row2._x + + s1->_row3._z * s2->_row3._x; + _row3._y = s1->_row3._z * s2->_row3._y + + s1->_row3._y * s2->_row2._y + + s2->_row1._y * s1->_row3._x; + _row3._z = s2->_row3._z * s1->_row3._z + + s2->_row2._z * s1->_row3._y + + s2->_row1._z * s1->_row3._x; + _vector._x = s2->_row1._x * s1->_vector._x + + s1->_vector._y * s2->_row2._x + + s1->_vector._z * s2->_row3._x + + s2->_vector._x; + _vector._y = s1->_vector._z * s2->_row3._y + + s1->_vector._y * s2->_row2._y + + s1->_vector._x * s2->_row1._y + + s2->_vector._y; + _vector._z = s1->_vector._y * s2->_row2._z + + s1->_vector._z * s2->_row3._z + + s1->_vector._x * s2->_row1._z + + s2->_vector._z; +} + void CStarControlSub6::init() { _static = nullptr; } @@ -53,7 +95,7 @@ void CStarControlSub6::identity() { } void CStarControlSub6::setRotationMatrix(Axis axis, double amount) { - const double ROTATION = 3.1415927 * 0.0055555557; + const double ROTATION = 2 * M_PI / 360.0; double sinVal = sin(amount * ROTATION); double cosVal = cos(amount * ROTATION); @@ -114,53 +156,67 @@ void CStarControlSub6::copyFrom(const FMatrix &src) { _row3 = src._row3; } -CStarControlSub6 *CStarControlSub6::setup(CStarControlSub6 *dest, const CStarControlSub6 *s2, const CStarControlSub6 *s3) { - CStarControlSub6 &d = *dest; - - d._row1._x = s3->_row1._x * s2->_row1._x - + s2->_row1._z * s3->_row3._x - + s2->_row1._y * s3->_row2._x; - d._row1._y = s2->_row1._x * s3->_row1._y - + s3->_row3._y * s2->_row1._z - + s3->_row2._y * s2->_row1._y; - d._row1._z = s2->_row1._x * s3->_row1._z - + s3->_row3._z * s2->_row1._z - + s3->_row2._z * s2->_row1._y; - d._row2._x = s3->_row1._x * s2->_row2._x - + s2->_row2._y * s3->_row2._x - + s2->_row2._z * s3->_row3._x; - d._row2._y = s2->_row2._y * s3->_row2._y - + s2->_row2._z * s3->_row3._y - + s3->_row1._y * s2->_row2._x; - d._row2._z = s3->_row1._z * s2->_row2._x - + s2->_row2._y * s3->_row2._z - + s2->_row2._z * s3->_row3._z; - d._row3._x = s3->_row1._x * s2->_row3._x - + s2->_row3._y * s3->_row2._x - + s2->_row3._z * s3->_row3._x; - d._row3._y = s2->_row3._z * s3->_row3._y - + s2->_row3._y * s3->_row2._y - + s3->_row1._y * s2->_row3._x; - d._row3._z = s3->_row3._z * s2->_row3._z - + s3->_row2._z * s2->_row3._y - + s3->_row1._z * s2->_row3._x; - d._vector._x = s3->_row1._x * s2->_vector._x - + s2->_vector._y * s3->_row2._x - + s2->_vector._z * s3->_row3._x - + s3->_vector._x; - d._vector._y = s2->_vector._z * s3->_row3._y - + s2->_vector._y * s3->_row2._y - + s2->_vector._x * s3->_row1._y - + s3->_vector._y; - d._vector._z = s2->_vector._y * s3->_row2._z - + s2->_vector._z * s3->_row3._z - + s2->_vector._x * s3->_row1._z - + s3->_vector._z; - return dest; -} - -void CStarControlSub6::fn1(CStarControlSub6 *sub6) { - // TODO +void CStarControlSub6::fn4(CStarControlSub6 *sub6) { + double v2, v3, v6, v7, v8, v9, v10, v11; + double v12, v13, v14, v15, v16, v17, v18; + + v16 = _row3._z * _row2._y; + v2 = _row1._x * v16; + v3 = 0.0; + v18 = v2; + if (v2 < 0.0) { + v3 = v18; + v2 = 0.0; + } + v6 = _row3._x * _row1._y * _row2._z; + if (v6 < 0.0) + v3 = v3 + v6; + else + v2 = v2 + v6; + v7 = _row3._y * _row1._z * _row2._x; + if (v7 < 0.0) + v3 = v3 + v7; + else + v2 = v2 + v7; + if (-(_row3._x * _row1._z * _row2._y) < 0.0) + v3 = v3 - _row3._x * _row1._z * _row2._y; + else + v2 = v2 - _row3._x * _row1._z * _row2._y; + if (-(_row1._y * _row2._x * _row3._z) < 0.0) + v3 = v3 - _row1._y * _row2._x * _row3._z; + else + v2 = v2 - _row1._y * _row2._x * _row3._z; + v17 = _row2._z * _row3._y; + if (-(_row1._x * v17) < 0.0) + v3 = v3 - _row1._x * v17; + else + v2 = v2 - _row1._x * v17; + v18 = v3 + v2; + assert(!(v18 == 0.0 || fabs(v18 / (v2 - v3)) < 1.0e-10)); + + v8 = 1.0 / v18; + v18 = v8; + sub6->_row1._x = (v16 - v17) * v8; + sub6->_row2._x = -(_row2._x * _row3._z - _row3._x * _row2._z) * v8; + sub6->_row3._x = (_row3._y * _row2._x - _row3._x * _row2._y) * v8; + sub6->_row1._y = -(_row1._y * _row3._z - _row3._y * _row1._z) * v8; + sub6->_row2._y = (_row1._x * _row3._z - _row3._x * _row1._z) * v8; + sub6->_row3._y = -(_row1._x * _row3._y - _row3._x * _row1._y) * v8; + sub6->_row1._z = (_row1._y * _row2._z - _row1._z * _row2._y) * v8; + sub6->_row2._z = -(_row1._x * _row2._z - _row1._z * _row2._x) * v8; + v9 = sub6->_row1._x; + v10 = sub6->_row2._y; + v11 = sub6->_row3._y; + v12 = sub6->_row1._z; + v13 = sub6->_row2._z; + sub6->_row3._z = (_row1._x * _row2._y - _row1._y * _row2._x) * v18; + v14 = v9; + v15 = sub6->_row3._z; + sub6->_vector._x = -(v14 * _vector._x + + _vector._y * sub6->_row2._x + + _vector._z * sub6->_row3._x); + sub6->_vector._y = -(_vector._x * sub6->_row1._y + v10 * _vector._y + v11 * _vector._z); + sub6->_vector._z = -(v12 * _vector._x + v13 * _vector._y + v15 * _vector._z); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub6.h b/engines/titanic/star_control/star_control_sub6.h index 27b91628ba..91def29973 100644 --- a/engines/titanic/star_control/star_control_sub6.h +++ b/engines/titanic/star_control/star_control_sub6.h @@ -39,6 +39,7 @@ public: CStarControlSub6(); CStarControlSub6(Axis axis, double amount); CStarControlSub6(const CStarControlSub6 *src); + CStarControlSub6(const CStarControlSub6 *s1, const CStarControlSub6 *s2); /** * Sets an identity matrix @@ -46,11 +47,6 @@ public: void identity(); /** - * Sets up a passed instance from the specified two other ones - */ - static CStarControlSub6 *setup(CStarControlSub6 *dest, const CStarControlSub6 *s2, const CStarControlSub6 *s3); - - /** * Sets a rotation matrix for the given axis for the given amount */ void setRotationMatrix(Axis axis, double val); @@ -62,7 +58,7 @@ public: */ void copyFrom(const FMatrix &src); - void fn1(CStarControlSub6 *sub6); + void fn4(CStarControlSub6 *sub6); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub7.cpp b/engines/titanic/star_control/star_control_sub7.cpp index c2c9030700..8386e7305f 100644 --- a/engines/titanic/star_control/star_control_sub7.cpp +++ b/engines/titanic/star_control/star_control_sub7.cpp @@ -21,11 +21,55 @@ */ #include "titanic/star_control/star_control_sub7.h" +#include "titanic/star_control/star_control_sub12.h" namespace Titanic { void CStarControlSub7::draw(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStarControlSub5 *sub5) { - // TODO + if (_data.empty()) + return; + + CStarControlSub6 sub6 = sub12->proc23(); + double threshold = sub12->proc25(); + FPoint center((double)surfaceArea->_width * 0.5, + surfaceArea->_height * 0.5); + FVector newV; + + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 0xffff; + surfaceArea->setColorFromPixel(); + + for (uint idx = 0; idx < _data.size(); ++idx) { + const CBaseStarEntry &star = _data[idx]; + + newV._x = sub6._row1._x * star._position._x + sub6._row3._x * star._position._z + + sub6._row2._x * star._position._y + sub6._vector._x; + newV._y = sub6._row1._y * star._position._x + sub6._row3._y * star._position._z + + sub6._row2._y * star._position._x + sub6._vector._y; + newV._z = sub6._row1._z * star._position._x + sub6._row3._z * star._position._z + + sub6._row2._z * star._position._y + sub6._vector._z; + + if (newV._z > threshold) { + FVector vTemp; + sub12->proc28(2, newV, vTemp); + + FRect r1(center._x + vTemp._x, center._y + vTemp._y, + center._x + vTemp._x + 4.0, center._y + vTemp._y + 4.0); + surfaceArea->fn1(r1); + + FRect r2(r1.right, r1.bottom, r1.right + 4.0, r1.top); + surfaceArea->fn1(r2); + + FRect r3(r2.right, r1.top, r1.right, r1.top - 4.0); + surfaceArea->fn1(r3); + + FRect r4(r1.right, r1.top - 4.0, r1.left, r1.top); + surfaceArea->fn1(r4); + } + } + + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); } bool CStarControlSub7::addStar(const CBaseStarEntry *entry) { diff --git a/engines/titanic/star_control/star_control_sub8.cpp b/engines/titanic/star_control/star_control_sub8.cpp index 19be7f9d41..bf29b053c5 100644 --- a/engines/titanic/star_control/star_control_sub8.cpp +++ b/engines/titanic/star_control/star_control_sub8.cpp @@ -31,14 +31,66 @@ namespace Titanic { CStarControlSub8::CStarControlSub8() : _field8(-1), _entryIndex(-1) { } -int CStarControlSub8::findStar(const Common::Point &pt) { - // TODO - return -1; -} - void CStarControlSub8::selectStar(int index, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { - // TODO + if (_entryIndex >= 0) { + if (_entryIndex == _field8) { + if (_field8 != 2) { + if (_positions[index] != _positions[_entryIndex + 1]) { + surface->lock(); + + CSurfaceArea surfaceArea(surface); + fn4(index, &surfaceArea); + surface->unlock(); + + ++_entryIndex; + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } + } + } else if (_entryIndex == _field8 + 1) { + if (_positions[index] == _positions[_entryIndex + 1]) { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn6(&surfaceArea); + surface->unlock(); + + --_entryIndex; + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } else { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn6(&surfaceArea); + fn4(index, &surfaceArea); + surface->unlock(); + + const CBaseStarEntry *starP; + starP = starField->getDataPtr(_positions[_entryIndex]._index1); + sub7->addStar(starP); + starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + } + } + } else { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn4(index, &surfaceArea); + surface->unlock(); + + ++_entryIndex; + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } } bool CStarControlSub8::fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarControlSub12 *sub12) { @@ -53,13 +105,21 @@ bool CStarControlSub8::fn1(CStarField *starField, CSurfaceArea *surfaceArea, CSt clear(); return false; } - - // TODO - return true; } void CStarControlSub8::fn2(CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { - // TODO + if (_field8 <= -1) { + if (_entryIndex > -1) { + fn5(_entryIndex, surface, starField, sub7); + --_entryIndex; + } + } else { + --_field8; + if (_entryIndex - _field8 > 1) { + fn5(_entryIndex, surface, starField, sub7); + --_entryIndex; + } + } } void CStarControlSub8::fn3() { @@ -69,26 +129,29 @@ void CStarControlSub8::fn3() { FPoint CStarControlSub8::getPosition() const { return (_entryIndex >= 0 && _entryIndex <= 2) ? - FPoint(_entries[_entryIndex].left, _entries[_entryIndex].top) : FPoint(); + FPoint(_entries[_entryIndex]) : FPoint(); } void CStarControlSub8::draw(CSurfaceArea *surfaceArea) { if (!_positions.empty()) { - uint oldPixel = surfaceArea->_pixel; - surfaceArea->_pixel = 0xFF; + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 0xff; surfaceArea->setColorFromPixel(); - SurfaceAreaMode oldMode = surfaceArea->setMode(SA_NONE); + SurfaceAreaMode savedMode = surfaceArea->setMode(SA_NONE); - // TODO: Loop - /* for (int idx = 0; idx < _entryIndex; ++idx) { - Common::Rect &r = _entries[idx]; + const CStarPosition &src = _entries[idx]; + double xp = src.x, yp = src.y; + surfaceArea->fn1(FRect(xp - 8.0, yp, xp - 4.0, yp)); + surfaceArea->fn1(FRect(xp + 4.0, yp, xp + 8.0, yp)); + surfaceArea->fn1(FRect(xp, yp - 8.0, xp, yp - 4.0)); + surfaceArea->fn1(FRect(xp, yp + 4.0, xp, yp + 8.0)); } - */ - surfaceArea->_pixel = oldPixel; - surfaceArea->setMode(oldMode); + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(savedMode); } } @@ -112,7 +175,7 @@ int CStarControlSub8::indexOf(const Common::Point &pt) const { Common::Rect r(pt.x - 2, pt.y - 2, pt.x + 2, pt.y + 2); for (int idx = 0; idx < (int)_positions.size(); ++idx) { - if (r.contains(_positions[idx]._position)) + if (r.contains(_positions[idx])) return idx; } @@ -120,19 +183,42 @@ int CStarControlSub8::indexOf(const Common::Point &pt) const { } void CStarControlSub8::fn4(int index, CSurfaceArea *surfaceArea) { - // TODO + if (index >= 0 && index < (int)_positions.size()) { + const CStarPosition &pt = _positions[index]; + fn7(pt, surfaceArea); + } } void CStarControlSub8::fn5(int index, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { - // TODO + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn7(_positions[index + 1], &surfaceArea); + surface->unlock(); + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index + 1]._index1); + sub7->addStar(starP); } void CStarControlSub8::fn6(CSurfaceArea *surfaceArea) { - // TODO + const CStarPosition &pt = _positions[_entryIndex]; + fn7(pt, surfaceArea); } void CStarControlSub8::fn7(const FPoint &pt, CSurfaceArea *surfaceArea) { - // TODO + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 255; + surfaceArea->setColorFromPixel(); + SurfaceAreaMode savedMode = surfaceArea->setMode(SA_MODE3); + + + surfaceArea->fn1(FRect(pt._x - 8.0, pt._y, pt._x - 4.0, pt._y)); + surfaceArea->fn1(FRect(pt._x - -4.0, pt._y, pt._x + 8.0, pt._y)); + surfaceArea->fn1(FRect(pt._x, pt._y - 8.0, pt._x, pt._y - 4.0)); + surfaceArea->fn1(FRect(pt._x, pt._y + 4.0, pt._x, pt._y + 8.0)); + + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(savedMode); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub8.h b/engines/titanic/star_control/star_control_sub8.h index b9b544d78e..4939179481 100644 --- a/engines/titanic/star_control/star_control_sub8.h +++ b/engines/titanic/star_control/star_control_sub8.h @@ -41,7 +41,7 @@ class CStarControlSub8 { private: Common::Array<CStarPosition> _positions; int _entryIndex; - Common::Rect _entries[3]; + CStarPosition _entries[3]; private: /** * Allocates space in the _rects array @@ -69,8 +69,6 @@ public: */ void save(SimpleFile *file, int indent) {} - int findStar(const Common::Point &pt); - void selectStar(int starNum, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7); diff --git a/engines/titanic/star_control/star_field.cpp b/engines/titanic/star_control/star_field.cpp index 07c5ff4a73..5c22e5e308 100644 --- a/engines/titanic/star_control/star_field.cpp +++ b/engines/titanic/star_control/star_field.cpp @@ -232,7 +232,7 @@ bool CStarField::mouseButtonDown(CVideoSurface *surface, CStarControlSub12 *sub1 CSurfaceArea surfaceArea(surface); return selectStar(&surfaceArea, sub12, pt); } else { - int starNum = _sub8.findStar(pt); + int starNum = _sub8.indexOf(pt); if (starNum >= 0) { _sub8.selectStar(starNum, surface, this, &_sub7); return true; diff --git a/engines/titanic/star_control/star_points1.cpp b/engines/titanic/star_control/star_points1.cpp index c72795f11d..ab5da111ac 100644 --- a/engines/titanic/star_control/star_points1.cpp +++ b/engines/titanic/star_control/star_points1.cpp @@ -27,7 +27,7 @@ namespace Titanic { #define ARRAY_COUNT 876 -const double FACTOR = 3.1415927 * 0.0055555557; +const double FACTOR = 2 * M_PI / 360.0; CStarPoints1::CStarPoints1() { } diff --git a/engines/titanic/star_control/star_points2.cpp b/engines/titanic/star_control/star_points2.cpp index 9c4cfe8cf5..7a3e873e90 100644 --- a/engines/titanic/star_control/star_points2.cpp +++ b/engines/titanic/star_control/star_points2.cpp @@ -27,7 +27,7 @@ namespace Titanic { #define ARRAY_COUNT 80 -const double FACTOR = 3.1415927 * 0.0055555557; +const double FACTOR = 2 * M_PI / 360.0; bool CStarPoints2::initialize() { // Get a reference to the starfield points resource @@ -47,7 +47,7 @@ bool CStarPoints2::initialize() { v1 = stream->readSint32LE(); v2 = stream->readSint32LE(); v1 *= 0.015 * FACTOR; - v2 *= 0.0099999998 * FACTOR; + v2 *= FACTOR / 100.0; entry._x = cos(v1) * 3000000.0 * cos(v2); entry._y = sin(v1) * 3000000.0 * cos(v2); diff --git a/engines/titanic/star_control/star_ref.cpp b/engines/titanic/star_control/star_ref.cpp index 0b9898035f..7f36ae7473 100644 --- a/engines/titanic/star_control/star_ref.cpp +++ b/engines/titanic/star_control/star_ref.cpp @@ -47,7 +47,8 @@ bool CStarRef2::check(const Common::Point &pt, int index) { return false; CStarPosition &sp = (*_positions)[index]; - sp._position = pt; + sp.x = pt.x; + sp.y = pt.y; sp._index1 = sp._index2 = index; return true; } diff --git a/engines/titanic/star_control/star_view.cpp b/engines/titanic/star_control/star_view.cpp index 34fd371bac..6ed5f3b2f3 100644 --- a/engines/titanic/star_control/star_view.cpp +++ b/engines/titanic/star_control/star_view.cpp @@ -409,7 +409,7 @@ void CStarView::fn16() { void CStarView::fn17() { if (_starField && !_showingPhoto) { - _sub12.proc35(); + _sub12.removeMatrixRow(); _starField->fn8(_videoSurface2); } } diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 6f9fd8b13a..76f557711d 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -261,7 +261,7 @@ void GuiManager::addToTrash(GuiObject* object, Dialog* parent) { t.parent = 0; // If a dialog was provided, check it is in the dialog stack if (parent != 0) { - for (int i = 0 ; i < _dialogStack.size() ; ++i) { + for (uint i = 0 ; i < _dialogStack.size() ; ++i) { if (_dialogStack[i] == parent) { t.parent = parent; break; diff --git a/gui/options.cpp b/gui/options.cpp index 179fa65991..d9361493d0 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -567,7 +567,7 @@ void OptionsDialog::apply() { if (_enableShaderSettings) { if (g_system->hasFeature(OSystem::kFeatureShader)) { if (_shaderPopUp) { - if (ConfMan.getInt("shader", _domain) != _shaderPopUp->getSelectedTag()) { + if (ConfMan.getInt("shader", _domain) != (int32)_shaderPopUp->getSelectedTag()) { ConfMan.setInt("shader", _shaderPopUp->getSelectedTag(), _domain); g_system->setShader(_shaderPopUp->getSelectedTag()); } |