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