Files
scummvm-cursorfix/engines/ultima/shared/gfx/dungeon_surface.cpp
2026-02-02 04:50:13 +01:00

196 lines
6.3 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/shared/gfx/dungeon_surface.h"
#include "ultima/shared/maps/map.h"
#include "ultima/shared/early/game.h"
namespace Ultima {
namespace Shared {
const byte ARRAY_X[] = { 0, 72, 108, 126, 135, 144 };
const byte ARRAY_Y[] = { 0, 36, 54, 63, 68, 72 };
DungeonSurface::DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn) :
Gfx::VisualSurface(src, bounds), _widgetFn(widgetFn) {
_edgeColor = game->_edgeColor;
_highlightColor = game->_highlightColor;
_widgetColor = 0;
}
void DungeonSurface::drawWall(uint distance) {
int offsetX = !distance ? 8 : 0, offsetY = !distance ? 8 : 0;
if (distance <= 5) {
hLine(ARRAY_X[distance] + 16 + offsetX, ARRAY_Y[distance] + 8 + offsetY,
303 - ARRAY_X[distance] - offsetX, _edgeColor);
hLine(ARRAY_X[distance] + 16 + offsetX, 151 - ARRAY_Y[distance] - offsetY,
303 - ARRAY_X[distance] - offsetX, _edgeColor);
}
}
void DungeonSurface::drawDoorway(uint distance) {
int offsetY = !distance ? 8 : 0;
byte color = !distance ? 0 : _edgeColor;
if (distance < 5) {
drawWall(distance);
drawLine(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY,
ARRAY_X[distance + 1] + 16, ARRAY_Y[distance + 1] + 8, _edgeColor);
drawLineTo(303 - ARRAY_X[distance + 1], ARRAY_Y[distance + 1] + 8, _edgeColor);
drawLineTo(303 - ARRAY_X[distance + 1], 151 - ARRAY_Y[distance] - offsetY, _edgeColor);
drawLineTo(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY, color);
}
}
void DungeonSurface::drawLeftEdge(uint distance) {
if (distance <= 5) {
vLine(ARRAY_X[distance] + 16, ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
}
}
void DungeonSurface::drawRightEdge(uint distance) {
if (distance <= 5) {
vLine(303 - ARRAY_X[distance], ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
}
}
void DungeonSurface::drawWidget(uint widgetId, uint distance, byte color) {
_widgetFn(*this, widgetId, distance, color);
}
void DungeonSurface::drawLadderDownFaceOn(uint distance) {
if (distance <= 5) {
drawWidget(27, distance, _edgeColor);
drawWidget(28, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderDownSideOn(uint distance) {
if (distance <= 5) {
drawWidget(27, distance, _edgeColor);
drawWidget(29, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderUpFaceOn(uint distance) {
if (distance <= 5) {
drawWidget(26, distance, _edgeColor);
drawWidget(28, distance, _edgeColor);
}
}
void DungeonSurface::drawLadderUpSideOn(uint distance) {
if (distance <= 5) {
drawWidget(26, distance, _edgeColor);
drawWidget(29, distance, _edgeColor);
}
}
void DungeonSurface::drawLeftDoor(uint distance) {
if (distance <= 5) {
drawLeftWall(distance);
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
Point diff = p1 - p2;
diff.x /= 9;
diff.y /= 5;
drawLine(p2.x + diff.x * 2 + 16, 151 - diff.y - p2.y - 1, p2.x + diff.x * 2 + 16,
p1.y + 8 - diff.y, _edgeColor);
drawLineTo(p2.x + diff.x * 6 + 16, p1.y + diff.y + 8, _edgeColor);
drawLineTo(p2.x + diff.x * 6 + 16, 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
}
}
void DungeonSurface::drawLeftWall(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(p2.x + 16, p2.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
drawLine(p2.x + 16, 151 - p2.y, p1.x + 16, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawLeftBlank(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(p2.x + 16, p1.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
drawLine(p2.x + 16, 151 - p1.y, p1.x + 16, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawRightDoor(uint distance) {
if (distance <= 5) {
drawRightWall(distance);
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
Point diff = p1 - p2;
diff.x /= 9;
diff.y /= 5;
drawLine(303 - (p2.x + diff.x * 2), 151 - diff.y - p2.y - 1, 303 - (p2.x + diff.x * 2),
p1.y + 8 - diff.y, _edgeColor);
drawLineTo(303 - (diff.x * 6 + p2.x), p1.y + 8 + diff.y, _edgeColor);
drawLineTo(303 - (diff.x * 6 + p2.x), 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
}
}
void DungeonSurface::drawRightWall(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(303 - p2.x, p2.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
drawLine(303 - p2.x, 151 - p2.y, 303 - p1.x, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawRightBlank(uint distance) {
if (distance <= 5) {
Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
drawLine(303 - p2.x, p1.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
drawLine(303 - p2.x, 151 - p1.y, 303 - p1.x, 151 - p1.y, _edgeColor);
}
}
void DungeonSurface::drawBeams(uint distance) {
if (distance <= 5) {
// Figure out the Y difference between each beam
const int Y_START = ARRAY_Y[distance] + 8;
const int Y_END = 151 - ARRAY_Y[distance];
const int HEIGHT = (Y_END - Y_START) / 4;
for (int beamNum = 0; beamNum < 4; ++beamNum) {
const int YP = Y_START + HEIGHT * beamNum + (distance / 2);
drawLine(ARRAY_X[distance] + 16, YP, 303 - ARRAY_X[distance], YP, _highlightColor);
}
}
}
} // End of namespace Shared
} // End of namespace Ultima