scummvm/engines/twine/holomap.cpp

554 lines
20 KiB
C++
Raw Normal View History

/* 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 "twine/holomap.h"
2020-12-22 17:16:27 +01:00
#include "common/debug.h"
#include "common/memstream.h"
#include "common/stream.h"
#include "common/types.h"
#include "twine/audio/sound.h"
#include "twine/menu/interface.h"
#include "twine/renderer/redraw.h"
#include "twine/renderer/renderer.h"
#include "twine/renderer/screens.h"
2021-01-11 20:21:49 +01:00
#include "twine/resources/hqr.h"
#include "twine/resources/resources.h"
#include "twine/scene/animations.h"
#include "twine/scene/collision.h"
2021-01-11 20:21:49 +01:00
#include "twine/scene/gamestate.h"
#include "twine/scene/movements.h"
#include "twine/scene/scene.h"
#include "twine/shared.h"
#include "twine/text.h"
#include "twine/twine.h"
namespace TwinE {
Holomap::Holomap(TwinEEngine *engine) : _engine(engine) {}
bool Holomap::loadLocations() {
uint8 *locationsPtr = nullptr;
const int32 locationsSize = HQR::getAllocEntry(&locationsPtr, Resources::HQR_RESS_FILE, RESSHQR_HOLOARROWINFO);
if (locationsSize == 0) {
warning("Could not find holomap locations at index %i in %s", RESSHQR_HOLOARROWINFO, Resources::HQR_RESS_FILE);
return false;
}
Common::MemoryReadStream stream(locationsPtr, locationsSize, DisposeAfterUse::YES);
_numLocations = locationsSize / sizeof(Location);
if (_numLocations > NUM_LOCATIONS) {
warning("Amount of locations (%i) exceeds the maximum of %i", _numLocations, NUM_LOCATIONS);
return false;
}
for (int i = 0; i < _numLocations; i++) {
_locations[i].x = ClampAngle(stream.readSint16LE());
_locations[i].y = ClampAngle(stream.readSint16LE());
_locations[i].z = ClampAngle(stream.readSint16LE());
_locations[i].textIndex = stream.readUint16LE();
}
return true;
}
void Holomap::setHolomapPosition(int32 locationIdx) {
assert(locationIdx >= 0 && locationIdx <= ARRAYSIZE(_engine->_gameState->holomapFlags));
_engine->_gameState->holomapFlags[locationIdx] = 0x81;
if (_engine->_gameState->hasItem(InventoryItems::kiHolomap)) {
_engine->_redraw->addOverlay(OverlayType::koInventoryItem, InventoryItems::kiHolomap, 0, 0, 0, OverlayPosType::koNormal, 3);
}
2020-10-14 14:20:38 +02:00
}
void Holomap::clearHolomapPosition(int32 locationIdx) {
assert(locationIdx >= 0 && locationIdx <= ARRAYSIZE(_engine->_gameState->holomapFlags));
_engine->_gameState->holomapFlags[locationIdx] &= 0x7E;
_engine->_gameState->holomapFlags[locationIdx] |= 0x40;
}
void Holomap::loadHolomapGFX() {
_engine->_screens->loadCustomPalette(RESSHQR_HOLOPAL);
int32 j = 576;
for (int32 i = 0; i < 96; i += 3, j += 3) {
2020-10-23 10:52:33 +02:00
paletteHolomap[i + 0] = _engine->_screens->palette[j + 0];
paletteHolomap[i + 1] = _engine->_screens->palette[j + 1];
paletteHolomap[i + 2] = _engine->_screens->palette[j + 2];
}
j = 576;
for (int32 i = 96; i < 189; i += 3, j += 3) {
2020-10-23 10:52:33 +02:00
paletteHolomap[i + 0] = _engine->_screens->palette[j + 0];
paletteHolomap[i + 1] = _engine->_screens->palette[j + 1];
paletteHolomap[i + 2] = _engine->_screens->palette[j + 2];
}
2021-01-24 16:19:39 +01:00
holomapPaletteIndex = 0;
}
2021-01-24 15:16:37 +01:00
static int sortHolomapSurfaceCoordsByDepth(const void *a1, const void *a2) {
return *(const int16 *)a1 - *(const int16 *)a2;
}
void Holomap::prepareHolomapSurface() {
Common::MemoryReadStream stream(_engine->_resources->holomapSurfacePtr, _engine->_resources->holomapSurfaceSize);
2021-01-24 15:16:37 +01:00
int holomapSurfaceArrayIdx = 0;
int projectedIndex = 0;
for (int32 angle = -ANGLE_90; angle <= ANGLE_90; angle += ANGLE_11_25) {
2021-01-24 15:16:37 +01:00
int rotation = 0;
for (int32 stepWidth = ANGLE_11_25; stepWidth != 0; --stepWidth) {
const int32 destX = stream.readSint16LE();
const int32 destY = stream.readSint16LE();
const int32 destZ = stream.readSint16LE();
_engine->_renderer->getBaseRotationPosition(destX, destY, destZ);
2021-01-24 15:16:37 +01:00
if (angle != ANGLE_90) {
_holomapSurface[holomapSurfaceArrayIdx].z = destZ;
_holomapSurface[holomapSurfaceArrayIdx].projectedPosIdx = projectedIndex;
++holomapSurfaceArrayIdx;
}
_engine->_renderer->projectPositionOnScreen(destX, destY, destZ);
2021-01-24 15:16:37 +01:00
_projectedSurfacePositions[projectedIndex].x = _engine->_renderer->projPosX;
_projectedSurfacePositions[projectedIndex].y = _engine->_renderer->projPosY;
2021-01-24 15:31:54 +01:00
_projectedSurfacePositions[projectedIndex].unk1 = _engine->_screens->crossDot(0, 0xffff, ANGLE_360 - 1, rotation);
2021-01-24 15:16:37 +01:00
if (angle == ANGLE_90) {
_projectedSurfacePositions[projectedIndex].unk2 = 0xffff;
} else {
2021-01-24 15:31:54 +01:00
_projectedSurfacePositions[projectedIndex].unk2 = (int16)(((angle + ANGLE_90) * ANGLE_90) / 2);
2021-01-24 15:16:37 +01:00
}
rotation = rotation + ANGLE_11_25;
++projectedIndex;
}
const int32 destX = stream.readSint16LE();
const int32 destY = stream.readSint16LE();
const int32 destZ = stream.readSint16LE();
_engine->_renderer->getBaseRotationPosition(destX, destY, destZ);
_engine->_renderer->projectPositionOnScreen(destX, destY, destZ);
2021-01-24 15:16:37 +01:00
_projectedSurfacePositions[projectedIndex].x = _engine->_renderer->projPosX;
_projectedSurfacePositions[projectedIndex].y = _engine->_renderer->projPosY;
_projectedSurfacePositions[projectedIndex].unk1 = 0xffff;
if (angle == ANGLE_90) {
_projectedSurfacePositions[projectedIndex].unk2 = 0xffff;
} else {
2021-01-24 15:31:54 +01:00
_projectedSurfacePositions[projectedIndex].unk2 = (int16)(((angle + ANGLE_90) * ANGLE_90) / 2);
2021-01-24 15:16:37 +01:00
}
++projectedIndex;
}
2021-01-24 15:16:37 +01:00
qsort(_holomapSurface, ARRAYSIZE(_holomapSurface), sizeof(HolomapSurface), sortHolomapSurfaceCoordsByDepth);
}
2021-01-24 15:16:37 +01:00
void Holomap::renderHolomapSurfacePolygons() {
prepareHolomapSurface();
for (int32 i = 0; i < ARRAYSIZE(_holomapSurface); ++i) {
// const HolomapProjectedPos &pos1 = _projectedSurfacePositions[_holomapSurface[i].projectedPosIdx + 0];
// const HolomapProjectedPos &pos2 = _projectedSurfacePositions[_holomapSurface[i].projectedPosIdx + 1];
// const HolomapProjectedPos &pos3 = _projectedSurfacePositions[_holomapSurface[i].projectedPosIdx + 2];
// const HolomapProjectedPos &pos4 = _projectedSurfacePositions[_holomapSurface[i].projectedPosIdx + 3];
// TODO: build triangles from projected pos with texcoords from holomapimg
# if 0
v2 = _projectedSurfacePositions + 2 * *(_WORD *)(i + _holomapSurface + 2);
backDialogueBoxRight = *(_WORD *)v2;
backDialogueBoxBottom = *(_WORD *)(v2 + 2);
back2DialogueBoxRight = *(_WORD *)(v2 + 264);
back2DialogueBoxBottom = *(_WORD *)(v2 + 266);
back3DialogueBoxRight = *(_WORD *)(v2 + 8);
back3DialogueBoxBottom = *(_WORD *)(v2 + 10);
if (sub_26DAB(v0)) {
word_4B776 = *(_WORD *)(v2 + 4);
word_4B778 = *(_WORD *)(v2 + 6);
word_4B77C = *(_WORD *)(v2 + 268);
word_4B77E = *(_WORD *)(v2 + 270);
word_4B782 = *(_WORD *)(v2 + 12);
word_4B784 = *(_WORD *)(v2 + 14);
sub_2E894(); // handles polyTab, polyTab2, circleBuffer, maybe model rendering?
sub_2F1D1(v0); // some kind of blitting?
}
backDialogueBoxRight = *(_WORD *)(v2 + 264);
backDialogueBoxBottom = *(_WORD *)(v2 + 266);
back2DialogueBoxRight = *(_WORD *)(v2 + 272);
back2DialogueBoxBottom = *(_WORD *)(v2 + 274);
back3DialogueBoxRight = *(_WORD *)(v2 + 8);
back3DialogueBoxBottom = *(_WORD *)(v2 + 10);
v3 = sub_26DAB(v0);
if (v3) {
word_4B776 = *(_WORD *)(v2 + 268);
word_4B778 = *(_WORD *)(v2 + 270);
word_4B77C = *(_WORD *)(v2 + 276);
word_4B77E = *(_WORD *)(v2 + 278);
word_4B782 = *(_WORD *)(v2 + 12);
word_4B784 = *(_WORD *)(v2 + 14);
sub_2E894();
LOBYTE(v3) = sub_2F1D1(v0); // some kind of blitting?
}
#endif
}
2021-01-24 09:54:13 +01:00
}
2020-12-22 17:16:27 +01:00
void Holomap::drawHolomapText(int32 centerx, int32 top, const char *title) {
const int32 size = _engine->_text->getTextSize(title);
const int32 x = centerx - size / 2;
const int32 y = top;
_engine->_text->setFontColor(COLOR_WHITE);
2020-12-22 17:16:27 +01:00
_engine->_text->drawText(x, y, title);
}
2021-01-24 16:19:39 +01:00
void Holomap::renderHolomapModel(const uint8 *bodyPtr, int32 x, int32 y, int32 zPos) {
_engine->_renderer->setBaseRotation(x, y, 0);
2021-01-24 09:54:13 +01:00
_engine->_renderer->getBaseRotationPosition(0, 0, zPos + 1000);
2021-01-24 16:19:39 +01:00
_engine->_renderer->getBaseRotationPosition(_engine->_renderer->destX, _engine->_renderer->destY, _engine->_renderer->destZ);
2021-01-24 09:54:13 +01:00
_engine->_interface->resetClip();
2021-01-24 16:19:39 +01:00
_engine->_renderer->renderIsoModel(_engine->_renderer->destX, _engine->_renderer->destY, _engine->_renderer->destZ, x, y, 0, bodyPtr);
2021-01-24 09:54:13 +01:00
}
Holomap::TrajectoryData Holomap::loadTrajectoryData(int32 trajectoryIdx) {
TrajectoryData data;
2021-01-24 15:16:37 +01:00
Common::MemoryReadStream stream(_engine->_resources->holomapPointAnimPtr, _engine->_resources->holomapPointAnimSize);
2021-01-24 09:54:13 +01:00
for (int32 trajIdx = 0; trajIdx < trajectoryIdx; ++trajIdx) {
2021-01-24 15:16:37 +01:00
stream.skip(12);
const int16 animVal = stream.readSint16LE();
stream.skip(4 * animVal);
}
data.locationIdx = stream.readSint16LE();
data.trajLocationIdx = stream.readSint16LE();
data.vehicleIdx = stream.readSint16LE();
data.x = stream.readSint16LE();
data.y = stream.readSint16LE();
data.z = stream.readSint16LE();
data.numAnimFrames = stream.readSint16LE();
assert(data.numAnimFrames < ARRAYSIZE(data.positions));
for (int32 i = 0; i < data.numAnimFrames; ++i) {
data.positions[i].x = stream.readSint16LE();
data.positions[i].y = stream.readSint16LE();
2021-01-24 09:54:13 +01:00
}
return data;
}
void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
debug("Draw trajectory index %i", trajectoryIndex);
2021-01-24 16:19:39 +01:00
_engine->_interface->resetClip();
_engine->_screens->clearScreen();
_engine->setPalette(_engine->_screens->paletteRGBA);
loadHolomapGFX();
2021-01-24 09:54:13 +01:00
const Holomap::TrajectoryData &data = loadTrajectoryData(trajectoryIndex);
2021-01-11 20:21:49 +01:00
ScopedEngineFreeze timeFreeze(_engine);
_engine->_renderer->setCameraPosition(400, 240, 128, 1024, 1024);
2021-01-24 15:16:37 +01:00
renderHolomapSurfacePolygons();
2021-01-24 09:54:13 +01:00
2021-01-24 15:16:37 +01:00
const Location &loc = _locations[data.locationIdx];
2021-01-24 16:19:39 +01:00
_engine->_renderer->setCameraAngle(0, 0, 0, data.x, data.y, data.z, 5300);
2021-01-24 09:54:13 +01:00
renderHolomapModel(_engine->_resources->holomapPointModelPtr, loc.x, loc.y, 0);
_engine->flip();
2021-01-11 20:21:49 +01:00
ActorMoveStruct move;
2021-01-24 15:16:37 +01:00
AnimTimerDataStruct animData;
uint8 *animPtr = nullptr;
HQR::getAllocEntry(&animPtr, Resources::HQR_RESS_FILE, data.getAnimation());
uint8 *modelPtr = nullptr;
HQR::getAllocEntry(&modelPtr, Resources::HQR_RESS_FILE, data.getModel());
2021-01-24 16:19:39 +01:00
Renderer::prepareIsoModel(modelPtr);
int frameNumber = 0;
int frameTime = _engine->lbaTime;
2021-01-24 15:16:37 +01:00
int trajAnimFrameIdx = 0;
2021-01-24 16:19:39 +01:00
int32 local18 = 0;
bool fadeInPalette = true;
_engine->_input->enableKeyMap(holomapKeyMapId);
2021-01-11 20:21:49 +01:00
for (;;) {
ScopedFPS scopedFps;
_engine->readKeys();
if (_engine->shouldQuit() || _engine->_input->toggleAbortAction()) {
break;
}
2021-01-24 16:19:39 +01:00
if (!fadeInPalette && local18 < _engine->lbaTime) {
// TODO: setPalette2(576 / 3, 96 / 3, (int)&paletteHolomap[3 * holomapPaletteIndex++]);
if (holomapPaletteIndex == 96 / 3) {
holomapPaletteIndex = 0;
2021-01-11 20:21:49 +01:00
}
2021-01-24 16:19:39 +01:00
local18 = _engine->lbaTime + 3;
2021-01-11 20:21:49 +01:00
}
const int16 newAngle = move.getRealAngle(_engine->lbaTime);
if (move.numOfStep == 0) {
2021-01-24 16:19:39 +01:00
_engine->_movements->setActorAngleSafe(ANGLE_0, -ANGLE_90, 500, &move);
2021-01-11 20:21:49 +01:00
}
2021-01-24 15:16:37 +01:00
if (_engine->_animations->setModelAnimation(frameNumber, animPtr, modelPtr, &animData)) {
frameNumber++;
if (frameNumber >= _engine->_animations->getNumKeyframes(animPtr)) {
frameNumber = _engine->_animations->getStartKeyframe(animPtr);
2021-01-11 20:21:49 +01:00
}
}
_engine->_renderer->setCameraPosition(100, 400, 128, 900, 900);
2021-01-24 16:19:39 +01:00
_engine->_renderer->setCameraAngle(0, 0, 0, 60, 128, 0, 30000);
_engine->_renderer->setLightVector(0xffffffc4, 128, 0);
const Common::Rect rect(0, 200, 199, 479);
2021-01-30 14:35:12 +01:00
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
2021-01-24 15:16:37 +01:00
_engine->_renderer->renderIsoModel(0, 0, 0, 0, newAngle, 0, modelPtr);
2021-01-24 16:19:39 +01:00
_engine->copyBlockPhys(rect);
2021-01-11 20:21:49 +01:00
_engine->_renderer->setCameraPosition(400, 240, 128, 1024, 1024);
2021-01-24 16:19:39 +01:00
_engine->_renderer->setCameraAngle(0, 0, 0, data.x, data.y, data.z, 5300);
_engine->_renderer->setLightVector(data.x, data.y, 0);
if (frameTime + 40 <= _engine->lbaTime) {
frameTime = _engine->lbaTime;
2021-01-24 16:19:39 +01:00
int32 modelX;
int32 modelY;
2021-01-24 15:16:37 +01:00
if (trajAnimFrameIdx < data.numAnimFrames) {
2021-01-24 16:19:39 +01:00
modelX = data.positions[trajAnimFrameIdx].x;
modelY = data.positions[trajAnimFrameIdx].y;
2021-01-24 09:54:13 +01:00
} else {
2021-01-24 15:16:37 +01:00
if (data.numAnimFrames < trajAnimFrameIdx) {
2021-01-24 09:54:13 +01:00
break;
}
2021-01-24 16:19:39 +01:00
modelX = _locations[data.trajLocationIdx].x;
modelY = _locations[data.trajLocationIdx].y;
2021-01-11 20:21:49 +01:00
}
2021-01-24 16:19:39 +01:00
renderHolomapModel(_engine->_resources->holomapPointModelPtr, modelX, modelY, 0);
2021-01-24 15:16:37 +01:00
trajAnimFrameIdx = trajAnimFrameIdx + 1;
2021-01-11 20:21:49 +01:00
}
2021-01-24 16:19:39 +01:00
if (fadeInPalette) {
fadeInPalette = false;
_engine->_screens->fadeToPal(_engine->_screens->paletteRGBA);
2021-01-11 20:21:49 +01:00
}
}
_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBA);
_engine->_screens->fadeIn(_engine->_screens->paletteRGBA);
2021-01-25 23:07:48 +01:00
//_engine->setPalette(_engine->_screens->paletteRGBA);
_engine->_gameState->initEngineProjections();
_engine->_interface->loadClip();
_engine->_text->initSceneTextBank();
_engine->_input->enableKeyMap(mainKeyMapId);
2021-01-24 15:16:37 +01:00
free(animPtr);
free(modelPtr);
}
int32 Holomap::getNextHolomapLocation(int32 currentLocation, int32 dir) const {
const uint32 idx = currentLocation;
for (uint32 i = currentLocation + dir; i != idx; i = (i + dir) % NUM_LOCATIONS) {
if (_engine->_gameState->holomapFlags[i % NUM_LOCATIONS] & 0x81) {
return i;
}
}
return -1;
2020-12-22 17:16:27 +01:00
}
2021-01-13 00:09:57 +01:00
void Holomap::renderLocations(int xRot, int yRot, int zRot, bool lower) {
int n = 0;
for (int locationIdx = 0; locationIdx < NUM_LOCATIONS; ++locationIdx) {
if ((_engine->_gameState->holomapFlags[locationIdx] & 0x80) || locationIdx == _engine->_scene->currentSceneIdx) {
uint8 flags = _engine->_gameState->holomapFlags[locationIdx] & 1;
if (locationIdx == _engine->_scene->currentSceneIdx) {
flags |= 2u; // model type
}
const Location &loc = _locations[locationIdx];
2021-01-17 00:04:44 +01:00
_engine->_renderer->setBaseRotation(loc.x, loc.y, 0);
_engine->_renderer->getBaseRotationPosition(0, 0, loc.z + 1000);
int32 xpos1 = _engine->_renderer->destX;
int32 ypos1 = _engine->_renderer->destY;
int32 zpos1 = _engine->_renderer->destZ;
2021-01-17 00:04:44 +01:00
_engine->_renderer->getBaseRotationPosition(0, 0, 1500);
int32 xpos2 = _engine->_renderer->destX;
int32 ypos2 = _engine->_renderer->destY;
int32 zpos2 = _engine->_renderer->destZ;
_engine->_renderer->setBaseRotation(xRot, yRot, zRot, true);
2021-01-13 00:09:57 +01:00
_engine->_renderer->baseRotPosX = 0;
_engine->_renderer->baseRotPosY = 0;
_engine->_renderer->baseRotPosZ = 9500;
_engine->_renderer->getBaseRotationPosition(xpos1, ypos1, zpos1);
int zpos1_copy = _engine->_renderer->destZ;
_engine->_renderer->getBaseRotationPosition(xpos2, ypos2, zpos2);
2021-01-13 00:09:57 +01:00
if (lower) {
if (zpos1_copy > _engine->_renderer->destY) {
2021-01-13 00:09:57 +01:00
continue;
}
} else {
if (zpos1_copy < _engine->_renderer->destY) {
2021-01-13 00:09:57 +01:00
continue;
}
}
DrawListStruct &drawList = _engine->_redraw->drawList[n];
drawList.posValue = zpos1_copy;
2021-01-17 00:04:44 +01:00
drawList.actorIdx = locationIdx;
drawList.type = 0;
drawList.x = xpos1;
drawList.y = ypos1;
drawList.z = zpos1_copy;
2021-01-17 00:04:44 +01:00
drawList.offset = n;
drawList.field_C = flags;
drawList.field_E = 0;
drawList.field_10 = 0;
2021-01-13 00:09:57 +01:00
++n;
}
}
2021-01-17 00:04:44 +01:00
_engine->_redraw->sortDrawingList(_engine->_redraw->drawList, n);
for (int i = 0; i < n; ++i) {
const DrawListStruct &drawList = _engine->_redraw->drawList[i];
2021-01-17 00:04:44 +01:00
const uint16 flags = drawList.field_C;
const uint8 *bodyPtr = nullptr;
2021-01-24 15:16:37 +01:00
if (flags == 1u) {
2021-01-17 00:04:44 +01:00
bodyPtr = _engine->_resources->holomapArrowPtr;
} else if (flags == 2u) {
bodyPtr = _engine->_resources->holomapTwinsenModelPtr;
2021-01-24 15:16:37 +01:00
} else if (flags == 3u) {
2021-01-17 00:04:44 +01:00
bodyPtr = _engine->_resources->holomapTwinsenArrowPtr;
2021-01-13 00:09:57 +01:00
}
if (bodyPtr != nullptr) {
2021-01-17 00:04:44 +01:00
int32 angleX = _locations[drawList.actorIdx].x;
int32 angleY = _locations[drawList.actorIdx].y;
_engine->_renderer->renderIsoModel(drawList.x, drawList.y, drawList.z, angleX, angleY, 0, bodyPtr);
2021-01-13 00:09:57 +01:00
}
}
}
void Holomap::processHolomap() {
2020-11-02 23:09:27 +01:00
ScopedEngineFreeze freeze(_engine);
2020-10-23 10:52:33 +02:00
const int32 alphaLightTmp = _engine->_scene->alphaLight;
const int32 betaLightTmp = _engine->_scene->betaLight;
_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBA);
_engine->_sound->stopSamples();
2020-12-22 17:16:27 +01:00
_engine->_interface->saveClip();
_engine->_interface->resetClip();
_engine->_screens->clearScreen();
2020-12-22 17:16:27 +01:00
_engine->setPalette(_engine->_screens->paletteRGBA);
loadHolomapGFX();
2021-01-24 15:16:37 +01:00
renderHolomapSurfacePolygons();
_engine->_renderer->setCameraPosition(_engine->width() / 2, 190, 128, 1024, 1024);
2020-11-01 22:35:29 +01:00
_engine->_text->initTextBank(TextBankId::Inventory_Intro_and_Holomap);
2021-01-26 00:29:24 +01:00
_engine->_text->setFontCrossColor(COLOR_9);
int currentLocation = _engine->_scene->currentSceneIdx;
_engine->_text->drawHolomapLocation(_locations[currentLocation].textIndex);
2020-12-22 17:16:27 +01:00
_engine->flip();
// TODO: load RESSHQR_HOLOSURFACE and project the texture to the surface
//_engine->_screens->loadImage(RESSHQR_HOLOIMG, RESSHQR_HOLOPAL);
2021-01-17 00:04:44 +01:00
int32 time = _engine->lbaTime;
int32 xRot = 0;
int32 yRot = 0;
bool rotate = false;
bool redraw = true;
_engine->_input->enableKeyMap(holomapKeyMapId);
2020-12-22 14:44:56 +01:00
for (;;) {
FrameMarker frame;
2020-12-22 14:44:56 +01:00
ScopedFPS scopedFps;
_engine->_input->readKeys();
if (_engine->shouldQuit() || _engine->_input->toggleAbortAction()) {
break;
}
if (_engine->_input->toggleActionIfActive(TwinEActionType::HolomapPrev)) {
const int32 nextLocation = getNextHolomapLocation(currentLocation, -1);
if (nextLocation != -1) {
currentLocation = nextLocation;
_engine->_text->drawHolomapLocation(_locations[currentLocation].textIndex);
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
rotate = true;
}
} else if (_engine->_input->toggleActionIfActive(TwinEActionType::HolomapNext)) {
const int32 nextLocation = getNextHolomapLocation(currentLocation, 1);
if (nextLocation != -1) {
currentLocation = nextLocation;
_engine->_text->drawHolomapLocation(_locations[currentLocation].textIndex);
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
rotate = true;
}
2020-12-22 14:44:56 +01:00
}
2021-01-17 00:04:44 +01:00
if (_engine->_input->isActionActive(TwinEActionType::HolomapLeft)) {
xRot += 8;
rotate = true;
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
} else if (_engine->_input->isActionActive(TwinEActionType::HolomapRight)) {
xRot -= 8;
rotate = true;
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
}
2021-01-17 00:04:44 +01:00
if (_engine->_input->isActionActive(TwinEActionType::HolomapUp)) {
yRot += 8;
rotate = true;
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
} else if (_engine->_input->isActionActive(TwinEActionType::HolomapDown)) {
yRot -= 8;
rotate = true;
2021-01-17 00:04:44 +01:00
time = _engine->lbaTime;
}
2021-01-17 00:04:44 +01:00
if (rotate) {
2021-01-17 00:04:44 +01:00
const int32 dt = _engine->lbaTime - time;
xRot = _engine->_collision->getAverageValue(ClampAngle(xRot), _locations[currentLocation].x, 75, dt);
yRot = _engine->_collision->getAverageValue(ClampAngle(yRot), _locations[currentLocation].y, 75, dt);
redraw = true;
2020-12-22 14:44:56 +01:00
}
if (redraw) {
redraw = false;
2021-01-13 00:09:57 +01:00
const Common::Rect rect(170, 0, 470, 330);
2021-01-30 14:35:12 +01:00
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
drawHolomapText(_engine->width() / 2, 25, "HoloMap");
2021-01-13 00:09:57 +01:00
_engine->_renderer->setBaseRotation(xRot, yRot, 0);
_engine->_renderer->setLightVector(xRot, yRot, 0);
2021-01-26 00:09:24 +01:00
renderLocations(xRot, yRot, 0, false);
2021-01-13 00:09:57 +01:00
_engine->_renderer->setBaseRotation(xRot, yRot, 0);
2021-01-24 15:16:37 +01:00
renderHolomapSurfacePolygons();
2021-01-26 00:09:24 +01:00
renderLocations(xRot, yRot, 0, true);
2021-01-13 00:09:57 +01:00
if (rotate) {
_engine->_menu->drawBox(300, 170, 340, 210);
}
2021-01-17 00:04:44 +01:00
//_engine->copyBlockPhys(rect);
_engine->flip();
2021-01-13 00:09:57 +01:00
}
2021-01-13 00:09:57 +01:00
if (rotate && xRot == _locations[currentLocation].x && yRot == _locations[currentLocation].y) {
rotate = false;
}
2020-12-22 14:44:56 +01:00
2021-01-17 00:04:44 +01:00
++_engine->lbaTime;
2021-01-13 00:09:57 +01:00
// TODO: text afterwards on top (not before as it is currently implemented)?
// pos 0x140,0x19?
2020-12-22 14:44:56 +01:00
//_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
//_engine->flip();
}
_engine->_text->drawTextBoxBackground = true;
_engine->_screens->fadeToBlack(_engine->_screens->paletteRGBA);
_engine->_scene->alphaLight = alphaLightTmp;
_engine->_scene->betaLight = betaLightTmp;
_engine->_gameState->initEngineProjections();
2020-12-22 17:16:27 +01:00
_engine->_interface->loadClip();
_engine->_input->enableKeyMap(mainKeyMapId);
_engine->_text->initSceneTextBank();
2020-10-14 14:20:38 +02:00
}
} // namespace TwinE