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 "dreamweb/dreamweb.h"
24
25 namespace DreamWeb {
26
turnPathOn(uint8 param)27 void DreamWebEngine::turnPathOn(uint8 param) {
28 findOrMake(param, 0xff, _roomNum + 100);
29 PathNode *roomsPaths = getRoomsPaths()->nodes;
30 if (param == 0xff)
31 return;
32 roomsPaths[param].on = 0xff;
33 }
34
turnPathOff(uint8 param)35 void DreamWebEngine::turnPathOff(uint8 param) {
36 findOrMake(param, 0x00, _roomNum + 100);
37 PathNode *roomsPaths = getRoomsPaths()->nodes;
38 if (param == 0xff)
39 return;
40 roomsPaths[param].on = 0x00;
41 }
42
turnAnyPathOn(uint8 param,uint8 room)43 void DreamWebEngine::turnAnyPathOn(uint8 param, uint8 room) {
44 findOrMake(param, 0xff, room + 100);
45 _pathData[room].nodes[param].on = 0xff;
46 }
47
turnAnyPathOff(uint8 param,uint8 room)48 void DreamWebEngine::turnAnyPathOff(uint8 param, uint8 room) {
49 findOrMake(param, 0x00, room + 100);
50 _pathData[room].nodes[param].on = 0x00;
51 }
52
getRoomsPaths()53 RoomPaths *DreamWebEngine::getRoomsPaths() {
54 return &_pathData[_roomNum];
55 }
56
faceRightWay()57 void DreamWebEngine::faceRightWay() {
58 PathNode *paths = getRoomsPaths()->nodes;
59 uint8 dir = paths[_mansPath].dir;
60 _turnToFace = dir;
61 _leaveDirection = dir;
62 }
63
setWalk()64 void DreamWebEngine::setWalk() {
65 if (_linePointer != 254) {
66 // Already walking
67 _finalDest = _pointersPath;
68 } else if (_pointersPath == _mansPath) {
69 // Can't walk
70 faceRightWay();
71 } else if (_vars._watchMode == 1) {
72 // Holding reel
73 _vars._destAfterHold = _pointersPath;
74 _vars._watchMode = 2;
75 } else if (_vars._watchMode == 2) {
76 // Can't walk
77 } else {
78 _destination = _pointersPath;
79 _finalDest = _pointersPath;
80 if (_mouseButton != 2 || _commandType == 3) {
81 autoSetWalk();
82 } else {
83 _walkAndExam = 1;
84 _walkExamType = _commandType;
85 _walkExamNum = _command;
86 autoSetWalk();
87 }
88 }
89 }
90
autoSetWalk()91 void DreamWebEngine::autoSetWalk() {
92 if (_finalDest == _mansPath)
93 return;
94 const RoomPaths *roomsPaths = getRoomsPaths();
95 checkDest(roomsPaths);
96 _lineStartX = roomsPaths->nodes[_mansPath].x - 12;
97 _lineStartY = roomsPaths->nodes[_mansPath].y - 12;
98 _lineEndX = roomsPaths->nodes[_destination].x - 12;
99 _lineEndY = roomsPaths->nodes[_destination].y - 12;
100 bresenhams();
101 if (_lineDirection != 0) {
102 _linePointer = _lineLength - 1;
103 _lineDirection = 1;
104 return;
105 }
106 _linePointer = 0;
107 }
108
checkDest(const RoomPaths * roomsPaths)109 void DreamWebEngine::checkDest(const RoomPaths *roomsPaths) {
110 const PathSegment *segments = roomsPaths->segments;
111 const uint8 tmp = _mansPath << 4;
112 uint8 destination = _destination;
113 for (uint i = 0; i < 24; ++i) {
114 if ((segments[i].b0 & 0xf0) == tmp &&
115 (segments[i].b0 & 0x0f) == _destination) {
116 _destination = segments[i].b1 & 0x0f;
117 return;
118 }
119
120 if (((segments[i].b0 & 0x0f) << 4) == tmp &&
121 ((segments[i].b0 & 0xf0) >> 4) == _destination) {
122 destination = segments[i].b1 & 0x0f;
123 }
124 }
125 _destination = destination;
126 }
127
findXYFromPath()128 void DreamWebEngine::findXYFromPath() {
129 const PathNode *roomsPaths = getRoomsPaths()->nodes;
130 _ryanX = roomsPaths[_mansPath].x - 12;
131 _ryanY = roomsPaths[_mansPath].y - 12;
132 }
133
checkIfPathIsOn(uint8 index)134 bool DreamWebEngine::checkIfPathIsOn(uint8 index) {
135 RoomPaths *roomsPaths = getRoomsPaths();
136 uint8 pathOn = roomsPaths->nodes[index].on;
137 return pathOn == 0xff;
138 }
139
bresenhams()140 void DreamWebEngine::bresenhams() {
141 workoutFrames();
142 Common::Point *lineData = &_lineData[0];
143 int16 startX = (int16)_lineStartX;
144 int16 startY = (int16)_lineStartY;
145 int16 endX = (int16)_lineEndX;
146 int16 endY = (int16)_lineEndY;
147
148 if (endX == startX) {
149 uint16 deltaY;
150 int8 y;
151 if (endY < startY) {
152 deltaY = startY - endY;
153 y = (int8)endY;
154 _lineDirection = 1;
155 } else {
156 deltaY = endY - startY;
157 y = (int8)startY;
158 _lineDirection = 0;
159 }
160 ++deltaY;
161 int8 x = (int8)startX;
162 _lineLength = deltaY;
163 for (; deltaY; --deltaY) {
164 lineData->x = x;
165 lineData->y = y;
166 ++lineData;
167 ++y;
168 }
169 return;
170 }
171 uint16 deltaX;
172 if (endX < startX) {
173 deltaX = startX - endX;
174 SWAP(startX, endX);
175 SWAP(startY, endY);
176 _lineStartX = (uint16)startX;
177 _lineStartY = (uint16)startY;
178 _lineEndX = (uint16)endX;
179 _lineEndY = (uint16)endY;
180 _lineDirection = 1;
181 } else {
182 deltaX = endX - startX;
183 _lineDirection = 0;
184 }
185
186 int16 increment;
187 if (endY == startY) {
188 int8 x = (int8)startX;
189 int8 y = (int8)startY;
190 ++deltaX;
191 _lineLength = deltaX;
192 for (; deltaX; --deltaX) {
193 lineData->x = x;
194 lineData->y = y;
195 ++lineData;
196 ++x;
197 }
198 return;
199 }
200 uint16 deltaY;
201 if (startY > endY) {
202 deltaY = startY - endY;
203 increment = -1;
204 } else {
205 deltaY = endY - startY;
206 increment = 1;
207 }
208
209 uint16 delta1, delta2;
210 byte lineRoutine;
211
212 if (deltaY > deltaX) {
213 lineRoutine = 1;
214 delta1 = deltaY;
215 delta2 = deltaX;
216 } else {
217 lineRoutine = 0;
218 delta1 = deltaX;
219 delta2 = deltaY;
220 }
221
222 uint16 increment1 = delta2 * 2;
223 uint16 increment2 = delta2 * 2 - delta1 * 2;
224 int16 remainder = delta2 * 2 - delta1;
225 ++delta1;
226 int8 x = (int8)startX;
227 int8 y = (int8)startY;
228 _lineLength = delta1;
229 if (lineRoutine != 1) {
230 for (; delta1; --delta1) {
231 lineData->x = x;
232 lineData->y = y;
233 ++lineData;
234 ++x;
235 if (remainder < 0) {
236 remainder += increment1;
237 } else {
238 remainder += increment2;
239 y += increment;
240 }
241 }
242 } else {
243 for (; delta1; --delta1) {
244 lineData->x = x;
245 lineData->y = y;
246 ++lineData;
247 y += increment;
248 if (remainder < 0) {
249 remainder += increment1;
250 } else {
251 remainder += increment2;
252 ++x;
253 }
254 }
255 }
256 }
257
workoutFrames()258 void DreamWebEngine::workoutFrames() {
259 byte tmp;
260 int diffx, diffy;
261
262 // We have to use signed arithmetic here because these values can
263 // be slightly negative when walking off-screen
264 int lineStartX = (int16)_lineStartX;
265 int lineStartY = (int16)_lineStartY;
266 int lineEndX = (int16)_lineEndX;
267 int lineEndY = (int16)_lineEndY;
268
269
270 diffx = ABS(lineStartX - lineEndX);
271 diffy = ABS(lineStartY - lineEndY);
272
273 if (diffx < diffy) {
274 tmp = 2;
275 if (diffx >= (diffy >> 1))
276 tmp = 1;
277 } else {
278 // tendstohoriz
279 tmp = 0;
280 if (diffy >= (diffx >> 1))
281 tmp = 1;
282 }
283
284 if (lineStartX >= lineEndX) {
285 // isinleft
286 if (lineStartY < lineEndY) {
287 if (tmp != 1)
288 tmp ^= 2;
289 tmp += 4;
290 } else {
291 // topleft
292 tmp += 6;
293 }
294 } else {
295 // isinright
296 if (lineStartY < lineEndY) {
297 tmp += 2;
298 } else {
299 // botright
300 if (tmp != 1)
301 tmp ^= 2;
302 }
303 }
304
305 _turnToFace = tmp & 7;
306 _turnDirection = 0;
307 }
308
findFirstPath(byte x,byte y)309 byte DreamWebEngine::findFirstPath(byte x, byte y) {
310 PathNode *paths = _pathData[_roomNum].nodes;
311
312 for (uint8 index = 0; index < 12; index++) {
313 if (paths[index].x1 == 0xff && paths[index].y1 == 0xff)
314 continue; // "nofirst"
315
316 if (x < paths[index].x1 || y < paths[index].y1)
317 continue; // "nofirst"
318
319 if (x >= paths[index].x2 || y >= paths[index].y2)
320 continue; // "nofirst"
321
322 return paths[index].on; // "gotfirst"
323 }
324
325 return 0;
326 }
327
findPathOfPoint(byte x,byte y)328 byte DreamWebEngine::findPathOfPoint(byte x, byte y) {
329 PathNode *paths = _pathData[_roomNum].nodes;
330
331 for (uint8 index = 0; index < 12; index++) {
332 if (paths[index].on != 0xff)
333 continue; // "flunkedit"
334
335 if (paths[index].x1 == 0xff && paths[index].y1 == 0xff)
336 continue; // "flunkedit"
337
338 if (x < paths[index].x1 || y < paths[index].y1)
339 continue; // "flunkedit"
340
341 if (x >= paths[index].x2 || y >= paths[index].y2)
342 continue; // "flunkedit"
343
344 return index; // "gotvalidpath"
345 }
346
347 return 0xff;
348 }
349
350 } // End of namespace DreamWeb
351