1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ultima/shared/gfx/dungeon_surface.h"
24 #include "ultima/shared/maps/map.h"
25 #include "ultima/shared/early/game.h"
26 
27 namespace Ultima {
28 namespace Shared {
29 
30 const byte ARRAY_X[] = { 0, 72, 108, 126, 135, 144 };
31 const byte ARRAY_Y[] = { 0, 36, 54, 63, 68, 72 };
32 
DungeonSurface(const Graphics::ManagedSurface & src,const Rect & bounds,Game * game,DrawWidgetFn widgetFn)33 DungeonSurface::DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn) :
34 		Gfx::VisualSurface(src, bounds), _widgetFn(widgetFn) {
35 	_edgeColor = game->_edgeColor;
36 	_highlightColor = game->_highlightColor;
37 	_widgetColor = 0;
38 }
39 
drawWall(uint distance)40 void DungeonSurface::drawWall(uint distance) {
41 	int offsetX = !distance ? 8 : 0, offsetY = !distance ? 8 : 0;
42 
43 	if (distance <= 5) {
44 		hLine(ARRAY_X[distance] + 16 + offsetX, ARRAY_Y[distance] + 8 + offsetY,
45 			303 - ARRAY_X[distance] - offsetX, _edgeColor);
46 		hLine(ARRAY_X[distance] + 16 + offsetX, 151 - ARRAY_Y[distance] - offsetY,
47 			303 - ARRAY_X[distance] - offsetX, _edgeColor);
48 	}
49 }
50 
drawDoorway(uint distance)51 void DungeonSurface::drawDoorway(uint distance) {
52 	int offsetY = !distance ? 8 : 0;
53 	byte color = !distance ? 0 : _edgeColor;
54 
55 	if (distance < 5) {
56 		drawWall(distance);
57 		drawLine(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY,
58 			ARRAY_X[distance + 1] + 16, ARRAY_Y[distance + 1] + 8, _edgeColor);
59 		drawLineTo(303 - ARRAY_X[distance + 1], ARRAY_Y[distance + 1] + 8, _edgeColor);
60 		drawLineTo(303 - ARRAY_X[distance + 1], 151 - ARRAY_Y[distance] - offsetY, _edgeColor);
61 		drawLineTo(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY, color);
62 	}
63 }
64 
drawLeftEdge(uint distance)65 void DungeonSurface::drawLeftEdge(uint distance) {
66 	if (distance <= 5) {
67 		vLine(ARRAY_X[distance] + 16, ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
68 	}
69 }
70 
drawRightEdge(uint distance)71 void DungeonSurface::drawRightEdge(uint distance) {
72 	if (distance <= 5) {
73 		vLine(303 - ARRAY_X[distance], ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
74 	}
75 }
76 
drawWidget(uint widgetId,uint distance,byte color)77 void DungeonSurface::drawWidget(uint widgetId, uint distance, byte color) {
78 	_widgetFn(*this, widgetId, distance, color);
79 }
80 
drawLadderDownFaceOn(uint distance)81 void DungeonSurface::drawLadderDownFaceOn(uint distance) {
82 	if (distance <= 5) {
83 		drawWidget(27, distance, _edgeColor);
84 		drawWidget(28, distance, _edgeColor);
85 	}
86 }
87 
drawLadderDownSideOn(uint distance)88 void DungeonSurface::drawLadderDownSideOn(uint distance) {
89 	if (distance <= 5) {
90 		drawWidget(27, distance, _edgeColor);
91 		drawWidget(29, distance, _edgeColor);
92 	}
93 }
94 
drawLadderUpFaceOn(uint distance)95 void DungeonSurface::drawLadderUpFaceOn(uint distance) {
96 	if (distance <= 5) {
97 		drawWidget(26, distance, _edgeColor);
98 		drawWidget(28, distance, _edgeColor);
99 	}
100 }
101 
drawLadderUpSideOn(uint distance)102 void DungeonSurface::drawLadderUpSideOn(uint distance) {
103 	if (distance <= 5) {
104 		drawWidget(26, distance, _edgeColor);
105 		drawWidget(29, distance, _edgeColor);
106 	}
107 }
108 
drawLeftDoor(uint distance)109 void DungeonSurface::drawLeftDoor(uint distance) {
110 	if (distance <= 5) {
111 		drawLeftWall(distance);
112 
113 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
114 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
115 		Point diff = p1 - p2;
116 		diff.x /= 9;
117 		diff.y /= 5;
118 
119 		drawLine(p2.x + diff.x * 2 + 16, 151 - diff.y - p2.y - 1, p2.x + diff.x * 2 + 16,
120 			p1.y + 8 - diff.y, _edgeColor);
121 		drawLineTo(p2.x + diff.x * 6 + 16, p1.y + diff.y + 8, _edgeColor);
122 		drawLineTo(p2.x + diff.x * 6 + 16, 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
123 	}
124 }
125 
drawLeftWall(uint distance)126 void DungeonSurface::drawLeftWall(uint distance) {
127 	if (distance <= 5) {
128 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
129 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
130 		drawLine(p2.x + 16, p2.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
131 		drawLine(p2.x + 16, 151 - p2.y, p1.x + 16, 151 - p1.y, _edgeColor);
132 	}
133 }
134 
drawLeftBlank(uint distance)135 void DungeonSurface::drawLeftBlank(uint distance) {
136 	if (distance <= 5) {
137 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
138 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
139 		drawLine(p2.x + 16, p1.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
140 		drawLine(p2.x + 16, 151 - p1.y, p1.x + 16, 151 - p1.y, _edgeColor);
141 	}
142 }
143 
drawRightDoor(uint distance)144 void DungeonSurface::drawRightDoor(uint distance) {
145 	if (distance <= 5) {
146 		drawRightWall(distance);
147 
148 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
149 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
150 		Point diff = p1 - p2;
151 		diff.x /= 9;
152 		diff.y /= 5;
153 
154 		drawLine(303 - (p2.x + diff.x * 2), 151 - diff.y - p2.y - 1, 303 - (p2.x + diff.x * 2),
155 			p1.y + 8 - diff.y, _edgeColor);
156 		drawLineTo(303 - (diff.x * 6 + p2.x), p1.y + 8 + diff.y, _edgeColor);
157 		drawLineTo(303 - (diff.x * 6 + p2.x), 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
158 	}
159 }
160 
drawRightWall(uint distance)161 void DungeonSurface::drawRightWall(uint distance) {
162 	if (distance <= 5) {
163 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
164 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
165 
166 		drawLine(303 - p2.x, p2.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
167 		drawLine(303 - p2.x, 151 - p2.y, 303 - p1.x, 151 - p1.y, _edgeColor);
168 	}
169 }
170 
drawRightBlank(uint distance)171 void DungeonSurface::drawRightBlank(uint distance) {
172 	if (distance <= 5) {
173 		Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
174 			p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
175 		drawLine(303 - p2.x, p1.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
176 		drawLine(303 - p2.x, 151 - p1.y, 303 - p1.x, 151 - p1.y, _edgeColor);
177 	}
178 }
179 
drawBeams(uint distance)180 void DungeonSurface::drawBeams(uint distance) {
181 	if (distance <= 5) {
182 		// Figure out the Y difference between each beam
183 		const int Y_START = ARRAY_Y[distance] + 8;
184 		const int Y_END = 151 - ARRAY_Y[distance];
185 		const int HEIGHT = (Y_END - Y_START) / 4;
186 
187 		for (int beamNum = 0; beamNum < 4; ++beamNum) {
188 			const int YP = Y_START + HEIGHT * beamNum + (distance / 2);
189 
190 			drawLine(ARRAY_X[distance] + 16, YP, 303 - ARRAY_X[distance], YP, _highlightColor);
191 		}
192 	}
193 }
194 
195 } // End of namespace Shared
196 } // End of namespace Ultima
197