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  * Additional copyright for this file:
8  * Copyright (C) 1995 Presto Studios, Inc.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  */
25 
26 #include "buried/avi_frames.h"
27 #include "buried/biochip_right.h"
28 #include "buried/buried.h"
29 #include "buried/gameui.h"
30 #include "buried/graphics.h"
31 #include "buried/invdata.h"
32 #include "buried/inventory_window.h"
33 #include "buried/navarrow.h"
34 #include "buried/resources.h"
35 #include "buried/scene_view.h"
36 #include "buried/sound.h"
37 #include "buried/environ/scene_base.h"
38 #include "buried/environ/scene_common.h"
39 
40 #include "common/system.h"
41 #include "graphics/surface.h"
42 
43 namespace Buried {
44 
45 enum {
46 	WAR_GOD_HEAD_TIMER_VALUE = 3000
47 };
48 
49 class PlaceCeramicBowl : public SceneBase {
50 public:
51 	PlaceCeramicBowl(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
52 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
53 	int timerCallback(Window *viewWindow);
54 
55 private:
56 	bool _dropped;
57 };
58 
PlaceCeramicBowl(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)59 PlaceCeramicBowl::PlaceCeramicBowl(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
60 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
61 	_dropped = false;
62 }
63 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)64 int PlaceCeramicBowl::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
65 	if (pointLocation.x == -1 && pointLocation.y == -1)
66 		return SIC_REJECT;
67 
68 	if (itemID != kItemCeramicBowl)
69 		return SIC_REJECT;
70 
71 	_staticData.navFrameIndex = 112;
72 	viewWindow->invalidateWindow(false);
73 	_dropped = true;
74 	return SIC_ACCEPT;
75 }
76 
timerCallback(Window * viewWindow)77 int PlaceCeramicBowl::timerCallback(Window *viewWindow) {
78 	if (_dropped) {
79 		if (((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelStatus == 0) {
80 			// Play slide death animation
81 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(4);
82 
83 			// Notify the player of his gruesome death
84 			((SceneViewWindow *)viewWindow)->showDeathScene(11);
85 			return SC_DEATH;
86 		} else {
87 			// Kill the ambient
88 			_vm->_sound->setAmbientSound();
89 
90 			// Jump to the start of the main cavern
91 			DestinationScene newDest;
92 			newDest.destinationScene.timeZone = 2;
93 			newDest.destinationScene.environment = 2;
94 			newDest.destinationScene.node = 0;
95 			newDest.destinationScene.facing = 1;
96 			newDest.destinationScene.orientation = 1;
97 			newDest.destinationScene.depth = 0;
98 			newDest.transitionType = TRANSITION_VIDEO;
99 			newDest.transitionData = 3;
100 			newDest.transitionStartFrame = -1;
101 			newDest.transitionLength = -1;
102 			((SceneViewWindow *)viewWindow)->moveToDestination(newDest);
103 		}
104 	}
105 
106 	return SC_TRUE;
107 }
108 
109 class AdjustWheels : public SceneBase {
110 public:
111 	AdjustWheels(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
112 	void preDestructor();
113 	int paint(Window *viewWindow, Graphics::Surface *preBuffer);
114 	int gdiPaint(Window *viewWindow);
115 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
116 	int mouseMove(Window *viewWindow, const Common::Point &pointLocation);
117 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
118 
119 private:
120 	AVIFrames _leftWheelFrames;
121 	int _curLeftFrame;
122 	AVIFrames _rightWheelFrames;
123 	int _curRightFrame;
124 	Common::Rect _leftUpRegion;
125 	Common::Rect _leftDownRegion;
126 	Common::Rect _rightUpRegion;
127 	Common::Rect _rightDownRegion;
128 	bool _translateText;
129 };
130 
AdjustWheels(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)131 AdjustWheels::AdjustWheels(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
132 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
133 	_curLeftFrame = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelLeftIndex;
134 	_curRightFrame = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelRightIndex;
135 	_leftUpRegion = Common::Rect(46, 0, 200, 70);
136 	_leftDownRegion = Common::Rect(46, 106, 200, 189);
137 	_rightUpRegion = Common::Rect(212, 0, 432, 66);
138 	_rightDownRegion = Common::Rect(212, 109, 432, 189);
139 	_translateText = false;
140 
141 	if (!_leftWheelFrames.open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 9)))
142 		error("Failed to open left wheel frames video");
143 
144 	if (!_rightWheelFrames.open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10)))
145 		error("Failed to open right wheel frames video");
146 }
147 
preDestructor()148 void AdjustWheels::preDestructor() {
149 	_leftWheelFrames.close();
150 	_rightWheelFrames.close();
151 }
152 
paint(Window * viewWindow,Graphics::Surface * preBuffer)153 int AdjustWheels::paint(Window *viewWindow, Graphics::Surface *preBuffer) {
154 	if (_staticData.navFrameIndex >= 0) {
155 		const Graphics::Surface *leftFrame = _leftWheelFrames.getFrame(_curLeftFrame);
156 		if (leftFrame)
157 			_vm->_gfx->crossBlit(preBuffer, 0, 0, 208, 189, leftFrame, 0, 0);
158 
159 		const Graphics::Surface *rightFrame = _rightWheelFrames.getFrame(_curRightFrame);
160 		if (rightFrame)
161 			_vm->_gfx->crossBlit(preBuffer, 208, 0, 224, 189, rightFrame, 0, 0);
162 	}
163 
164 	return SC_REPAINT;
165 }
166 
gdiPaint(Window * viewWindow)167 int AdjustWheels::gdiPaint(Window *viewWindow) {
168 	if (_translateText && ((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
169 		Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
170 		Common::Rect rect(168, 70, 262, 108);
171 		rect.translate(absoluteRect.left, absoluteRect.top);
172 		_vm->_gfx->getScreen()->frameRect(rect, _vm->_gfx->getColor(255, 0, 0));
173 	}
174 
175 	return SC_REPAINT;
176 }
177 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)178 int AdjustWheels::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
179 	// TODO: Wait between frames after figuring out timing
180 
181 	if (_leftUpRegion.contains(pointLocation) || _leftDownRegion.contains(pointLocation) ||
182 			_rightUpRegion.contains(pointLocation) || _rightDownRegion.contains(pointLocation)) {
183 		if (_leftDownRegion.contains(pointLocation)) {
184 			// Move the wheel one frame and redraw
185 			_curLeftFrame++;
186 
187 			if (_curLeftFrame > _leftWheelFrames.getFrameCount() - 1)
188 				_curLeftFrame = 0;
189 
190 			viewWindow->invalidateWindow(false);
191 
192 			// And again for the final frame
193 			_curLeftFrame++;
194 
195 			if (_curLeftFrame > _leftWheelFrames.getFrameCount() - 1)
196 				_curLeftFrame = 0;
197 
198 			viewWindow->invalidateWindow(false);
199 		} else if (_leftUpRegion.contains(pointLocation)) {
200 			// Move the wheel one frame and redraw
201 			_curLeftFrame--;
202 
203 			if (_curLeftFrame < 0)
204 				_curLeftFrame = _leftWheelFrames.getFrameCount() - 1;
205 
206 			viewWindow->invalidateWindow(false);
207 
208 			// And again for the final frame
209 			_curLeftFrame--;
210 
211 			if (_curLeftFrame < 0)
212 				_curLeftFrame = _leftWheelFrames.getFrameCount() - 1;
213 
214 			viewWindow->invalidateWindow(false);
215 		} else if (_rightDownRegion.contains(pointLocation)) {
216 			// Move the wheel one frame and redraw
217 			_curRightFrame++;
218 
219 			if (_curRightFrame > _rightWheelFrames.getFrameCount() - 1)
220 				_curRightFrame = 0;
221 
222 			viewWindow->invalidateWindow(false);
223 
224 			// And again for the final frame
225 			_curRightFrame++;
226 
227 			if (_curRightFrame > _rightWheelFrames.getFrameCount() - 1)
228 				_curRightFrame = 0;
229 
230 			viewWindow->invalidateWindow(false);
231 		} else if (_rightUpRegion.contains(pointLocation)) {
232 			// Move the wheel one frame and redraw
233 			_curRightFrame--;
234 
235 			if (_curRightFrame < 0)
236 				_curRightFrame = _rightWheelFrames.getFrameCount() - 1;
237 
238 			viewWindow->invalidateWindow(false);
239 
240 			// And again for the final frame
241 			_curRightFrame--;
242 
243 			if (_curRightFrame < 0)
244 				_curRightFrame = _rightWheelFrames.getFrameCount() - 1;
245 
246 			viewWindow->invalidateWindow(false);
247 		}
248 
249 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelLeftIndex = _curLeftFrame;
250 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelRightIndex = _curRightFrame;
251 
252 		byte status = 0;
253 		if (_curLeftFrame == 8 && _curRightFrame == 12)
254 			status = 1;
255 		else if (_curLeftFrame == 16 && _curRightFrame == 22)
256 			status = 1;
257 		else if (_curLeftFrame == 20 && _curRightFrame == 4)
258 			status = 1;
259 		else if (_curLeftFrame == 0 && _curRightFrame == 24)
260 			status = 1;
261 		else if (_curLeftFrame == 14 && _curRightFrame == 8)
262 			status = 1;
263 		else if (_curLeftFrame == 6 && _curRightFrame == 6)
264 			status = 1;
265 		else if (_curLeftFrame == 6 && _curRightFrame == 30)
266 			status = 1;
267 		else if (_curLeftFrame == 24 && _curRightFrame == 0)
268 			status = 1;
269 		else if (_curLeftFrame == 10 && _curRightFrame == 28)
270 			status = 1;
271 
272 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelStatus = status;
273 
274 		return SC_TRUE;
275 	}
276 
277 	// Did not click on the wheels, pop back to depth 0
278 	DestinationScene newDest;
279 	newDest.destinationScene = _staticData.location;
280 	newDest.destinationScene.depth = 0;
281 	newDest.transitionType = TRANSITION_NONE;
282 	newDest.transitionData = -1;
283 	newDest.transitionStartFrame = -1;
284 	newDest.transitionLength = -1;
285 	((SceneViewWindow *)viewWindow)->moveToDestination(newDest);
286 	return SC_TRUE;
287 }
288 
mouseMove(Window * viewWindow,const Common::Point & pointLocation)289 int AdjustWheels::mouseMove(Window *viewWindow, const Common::Point &pointLocation) {
290 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
291 		Common::Rect translateTextRegion(168, 72, 260, 106);
292 
293 		if (translateTextRegion.contains(pointLocation)) {
294 			if (!_translateText) {
295 				Common::String leftText = _vm->getString(IDMYTP_WHEELS_LEFT_TRANS_TEXT_BASE + _curLeftFrame / 2);
296 				Common::String rightText = _vm->getString(IDMYTP_WHEELS_RIGHT_TRANS_TEXT_BASE + _curRightFrame / 2);
297 				Common::String finalString = leftText + rightText;
298 
299 				if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 &&
300 						((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCodeWheelStatus == 1) {
301 
302 					if (_vm->getVersion() >= MAKEVERSION(1, 0, 4, 0))
303 						finalString += _vm->getString(IDS_MYTP_WALKTHROUGH_HINT_TEXT);
304 					else
305 						finalString += " (Mayan Sacred Day)";
306 				}
307 
308 				((SceneViewWindow *)viewWindow)->displayTranslationText(finalString);
309 				_translateText = true;
310 				viewWindow->invalidateWindow(false);
311 			}
312 		} else {
313 			if (_translateText) {
314 				_translateText = false;
315 				viewWindow->invalidateWindow(false);
316 			}
317 		}
318 
319 		return SC_TRUE;
320 	}
321 
322 	return SC_FALSE;
323 }
324 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)325 int AdjustWheels::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
326 	if (_leftUpRegion.contains(pointLocation) || _rightUpRegion.contains(pointLocation))
327 		return kCursorArrowUp;
328 
329 	if (_leftDownRegion.contains(pointLocation) || _rightDownRegion.contains(pointLocation))
330 		return kCursorArrowDown;
331 
332 	return kCursorPutDown;
333 }
334 
335 class DateCombinationRead : public SceneBase {
336 public:
337 	DateCombinationRead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
338 	int gdiPaint(Window *viewWindow);
339 	int mouseMove(Window *viewWindow, const Common::Point &pointLocation);
340 
341 private:
342 	int _currentRegion;
343 };
344 
DateCombinationRead(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)345 DateCombinationRead::DateCombinationRead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
346 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
347 	_currentRegion = -1;
348 }
349 
gdiPaint(Window * viewWindow)350 int DateCombinationRead::gdiPaint(Window *viewWindow) {
351 	if (_currentRegion >= 0 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
352 		Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
353 		int left = _currentRegion * 43 + 20 + absoluteRect.left;
354 		Common::Rect rect(left, absoluteRect.top + 18, left + 43, absoluteRect.top + 110);
355 		_vm->_gfx->getScreen()->frameRect(rect, _vm->_gfx->getColor(255, 0, 0));
356 	}
357 
358 	return SC_REPAINT;
359 }
360 
mouseMove(Window * viewWindow,const Common::Point & pointLocation)361 int DateCombinationRead::mouseMove(Window *viewWindow, const Common::Point &pointLocation) {
362 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
363 		Common::Rect symbols(20, 18, 407, 110);
364 
365 		if (symbols.contains(pointLocation)) {
366 			int translatedSymbolIndex = (pointLocation.x - 20) / 43;
367 
368 			if (_currentRegion != translatedSymbolIndex) {
369 				// Update flags
370 				((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPCalendarListTranslated = 1;
371 				((SceneViewWindow *)viewWindow)->getGlobalFlags().myTPTextTranslated = 1;
372 
373 				// Display the text
374 				((SceneViewWindow *)viewWindow)->displayTranslationText(_vm->getString(IDMYTP_WALLS_COMBO_TRANS_TEXT_BASE + translatedSymbolIndex));
375 
376 				// Reset the current region and redraw
377 				_currentRegion = translatedSymbolIndex;
378 				viewWindow->invalidateWindow(false);
379 			}
380 		} else {
381 			if (_currentRegion >= 0) {
382 				_currentRegion = -1;
383 				viewWindow->invalidateWindow(false);
384 			}
385 		}
386 
387 		return SC_TRUE;
388 	}
389 
390 	return SC_FALSE;
391 }
392 
393 class ViewSingleTranslation : public SceneBase {
394 public:
395 	ViewSingleTranslation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
396 			int translatedTextID = -1, int left = -1, int top = -1, int right = -1, int bottom = -1,
397 			int flagAOffset = -1, int flagBOffset = -1, int visitedFlagOffset = -1);
398 	int gdiPaint(Window *viewWindow);
399 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
400 	int mouseMove(Window *viewWindow, const Common::Point &pointLocation);
401 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
402 
403 private:
404 	bool _textTranslated;
405 	int _textID;
406 	Common::Rect _clickableRegion;
407 	int _flagAOffset;
408 	int _flagBOffset;
409 	int _visitedFlagOffset;
410 };
411 
ViewSingleTranslation(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int translatedTextID,int left,int top,int right,int bottom,int flagAOffset,int flagBOffset,int visitedFlagOffset)412 ViewSingleTranslation::ViewSingleTranslation(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
413 		int translatedTextID, int left, int top, int right, int bottom,
414 		int flagAOffset, int flagBOffset, int visitedFlagOffset) :
415 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
416 	_textTranslated = false;
417 	_textID = translatedTextID;
418 	_clickableRegion = Common::Rect(left, top, right, bottom);
419 	_flagAOffset = flagAOffset;
420 	_flagBOffset = flagBOffset;
421 	_visitedFlagOffset = visitedFlagOffset;
422 
423 	if (_visitedFlagOffset >= 0)
424 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_visitedFlagOffset, 1);
425 }
426 
gdiPaint(Window * viewWindow)427 int ViewSingleTranslation::gdiPaint(Window *viewWindow) {
428 	// Draw the translated box, if applicable
429 	if (_textTranslated && ((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
430 		Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
431 		Common::Rect rect(_clickableRegion);
432 		rect.translate(absoluteRect.left, absoluteRect.top);
433 		_vm->_gfx->getScreen()->frameRect(rect, _vm->_gfx->getColor(255, 0, 0));
434 	}
435 
436 	return SC_REPAINT;
437 }
438 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)439 int ViewSingleTranslation::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
440 	if (_staticData.location.depth != 0) {
441 		// If we're not at depth zero, move to depth zero
442 		Location newLocation = _staticData.location;
443 		newLocation.depth = 0;
444 		((SceneViewWindow *)viewWindow)->jumpToScene(newLocation);
445 		return SC_TRUE;
446 	}
447 
448 	return SC_FALSE;
449 }
450 
mouseMove(Window * viewWindow,const Common::Point & pointLocation)451 int ViewSingleTranslation::mouseMove(Window *viewWindow, const Common::Point &pointLocation) {
452 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
453 		if (_clickableRegion.contains(pointLocation)) {
454 			// Make sure we didn't already render the text
455 			if (!_textTranslated) {
456 				if (_flagAOffset >= 0)
457 					((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_flagAOffset, 1);
458 				if (_flagBOffset >= 0)
459 					((SceneViewWindow *)viewWindow)->setGlobalFlagByte(_flagBOffset, 1);
460 
461 				// Load and display the text
462 				((SceneViewWindow *)viewWindow)->displayTranslationText(_vm->getString(_textID));
463 				_textTranslated = true;
464 				viewWindow->invalidateWindow(false);
465 			}
466 		} else {
467 			if (_textTranslated) {
468 				_textTranslated = false;
469 				viewWindow->invalidateWindow(false);
470 			}
471 		}
472 
473 		return SC_TRUE;
474 	}
475 
476 	return SC_FALSE;
477 }
478 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)479 int ViewSingleTranslation::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
480 	if (_staticData.location.depth != 0)
481 		return kCursorPutDown;
482 
483 	return kCursorArrow;
484 }
485 
486 class GenericCavernDoorMainView : public SceneBase {
487 public:
488 	GenericCavernDoorMainView(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
489 			int topZoomDepth = 0, int topLeft = -1, int topTop = -1, int topRight = -1, int topBottom = -1,
490 			int rightZoomDepth = 0, int rightLeft = -1, int rightTop = -1, int rightRight = -1, int rightBottom = -1,
491 			int offeringHeadZoomDepth = 0, int offeringHeadLeft = -1, int offeringHeadTop = -1, int offeringHeadRight = -1, int offeringHeadBottom = -1);
492 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
493 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
494 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
495 
496 private:
497 	int _topZoomDepth;
498 	int _rightZoomDepth;
499 	int _offeringHeadZoomDepth;
500 	Common::Rect _topZoomRegion;
501 	Common::Rect _rightZoomRegion;
502 	Common::Rect _offeringHeadZoomRegion;
503 };
504 
GenericCavernDoorMainView(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int topZoomDepth,int topLeft,int topTop,int topRight,int topBottom,int rightZoomDepth,int rightLeft,int rightTop,int rightRight,int rightBottom,int offeringHeadZoomDepth,int offeringHeadLeft,int offeringHeadTop,int offeringHeadRight,int offeringHeadBottom)505 GenericCavernDoorMainView::GenericCavernDoorMainView(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
506 		int topZoomDepth, int topLeft, int topTop, int topRight, int topBottom,
507 		int rightZoomDepth, int rightLeft, int rightTop, int rightRight, int rightBottom,
508 		int offeringHeadZoomDepth, int offeringHeadLeft, int offeringHeadTop, int offeringHeadRight, int offeringHeadBottom) :
509 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
510 	_topZoomDepth = topZoomDepth;
511 	_rightZoomDepth = rightZoomDepth;
512 	_offeringHeadZoomDepth = offeringHeadZoomDepth;
513 	_topZoomRegion = Common::Rect(topLeft, topTop, topRight, topBottom);
514 	_rightZoomRegion = Common::Rect(rightLeft, rightTop, rightRight, rightBottom);
515 	_offeringHeadZoomRegion = Common::Rect(offeringHeadLeft, offeringHeadTop, offeringHeadRight, offeringHeadBottom);
516 
517 	if (_staticData.location.node == 7)
518 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCViewedDeathGodDoor = 1;
519 }
520 
postEnterRoom(Window * viewWindow,const Location & priorLocation)521 int GenericCavernDoorMainView::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
522 	if (_staticData.location.node == 7 && (_staticData.location.timeZone != priorLocation.timeZone ||
523 			_staticData.location.environment != priorLocation.environment || _staticData.location.node != priorLocation.node ||
524 			_staticData.location.facing != priorLocation.facing || _staticData.location.orientation != priorLocation.orientation ||
525 			_staticData.location.depth != priorLocation.depth) && !((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_BROKEN_GLASS_PYRAMID))
526 		((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
527 	return SC_TRUE;
528 }
529 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)530 int GenericCavernDoorMainView::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
531 	// Build a default structure
532 	DestinationScene newDestination;
533 	newDestination.destinationScene = _staticData.location;
534 	newDestination.transitionType = TRANSITION_FADE;
535 	newDestination.transitionData = -1;
536 	newDestination.transitionStartFrame = -1;
537 	newDestination.transitionLength = -1;
538 
539 	if (_topZoomRegion.contains(pointLocation)) {
540 		newDestination.destinationScene.depth = _topZoomDepth;
541 		((SceneViewWindow *)viewWindow)->moveToDestination(newDestination);
542 		return SC_TRUE;
543 	}
544 
545 	if (_rightZoomRegion.contains(pointLocation)) {
546 		newDestination.destinationScene.depth = _rightZoomDepth;
547 		((SceneViewWindow *)viewWindow)->moveToDestination(newDestination);
548 		return SC_TRUE;
549 	}
550 
551 	if (_offeringHeadZoomRegion.contains(pointLocation)) {
552 		newDestination.destinationScene.depth = _offeringHeadZoomDepth;
553 		((SceneViewWindow *)viewWindow)->moveToDestination(newDestination);
554 		return SC_TRUE;
555 	}
556 
557 	return SC_FALSE;
558 }
559 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)560 int GenericCavernDoorMainView::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
561 	if (_topZoomRegion.contains(pointLocation) || _rightZoomRegion.contains(pointLocation) || _offeringHeadZoomRegion.contains(pointLocation))
562 		return kCursorMagnifyingGlass;
563 
564 	return kCursorArrow;
565 }
566 
567 class GenericCavernDoorOfferingHead : public SceneBase {
568 public:
569 	GenericCavernDoorOfferingHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
570 			int correctOfferingID = -1, int correctOfferingDestDepth = 0, int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
571 	int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
572 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
573 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
574 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
575 
576 private:
577 	DestinationScene _correctDestination;
578 	int _correctOfferingID;
579 	Common::Rect _dropRegion;
580 
581 	bool isValidItemToDrop(Window *viewWindow, int itemID);
582 };
583 
GenericCavernDoorOfferingHead(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int correctOfferingID,int correctOfferingDestDepth,int transitionType,int transitionData,int transitionStartFrame,int transitionLength)584 GenericCavernDoorOfferingHead::GenericCavernDoorOfferingHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
585 		int correctOfferingID, int correctOfferingDestDepth, int transitionType, int transitionData, int transitionStartFrame, int transitionLength) :
586 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
587 	_correctDestination.destinationScene = _staticData.location;
588 	_correctDestination.destinationScene.depth = correctOfferingDestDepth;
589 	_correctDestination.transitionType = transitionType;
590 	_correctDestination.transitionData = transitionData;
591 	_correctDestination.transitionStartFrame = transitionStartFrame;
592 	_correctDestination.transitionLength = transitionLength;
593 	_correctOfferingID = correctOfferingID;
594 	_dropRegion = Common::Rect(24, 92, 226, 154);
595 }
596 
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)597 int GenericCavernDoorOfferingHead::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
598 	// If this is walkthrough mode, only accept the correct item
599 	if (isValidItemToDrop(viewWindow, itemID) && _dropRegion.contains(pointLocation))
600 		return 1;
601 
602 	return 0;
603 }
604 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)605 int GenericCavernDoorOfferingHead::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
606 	if (pointLocation.x == -1 && pointLocation.y == -1)
607 		return SIC_REJECT;
608 
609 	if (!isValidItemToDrop(viewWindow, itemID))
610 		return SIC_REJECT;
611 
612 	if (_dropRegion.contains(pointLocation)) {
613 		switch (itemID) {
614 		case kItemBalconyKey:
615 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(2);
616 			break;
617 		case kItemBloodyArrow:
618 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(3);
619 			break;
620 		case kItemObsidianBlock:
621 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(5);
622 			break;
623 		case kItemCoilOfRope:
624 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(6);
625 			break;
626 		case kItemCopperKey:
627 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
628 			break;
629 		case kItemCopperMedallion:
630 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(8);
631 			break;
632 		case kItemCeramicBowl:
633 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(9);
634 			break;
635 		case kItemGrapplingHook:
636 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(10);
637 			break;
638 		case kItemHammer:
639 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(11);
640 			break;
641 		case kItemPreservedHeart:
642 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(12);
643 			break;
644 		case kItemJadeBlock:
645 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(13);
646 			break;
647 		case kItemLimestoneBlock:
648 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(14);
649 			break;
650 		case kItemMetalBar:
651 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(15);
652 			break;
653 		case kItemCavernSkull:
654 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(16);
655 			break;
656 		case kItemEntrySkull:
657 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(17);
658 			break;
659 		case kItemSpearSkull:
660 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(18);
661 			break;
662 		case kItemWaterCanFull:
663 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(19);
664 			break;
665 		case kItemWoodenPegs:
666 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(20);
667 			break;
668 		case kItemGoldCoins:
669 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(21);
670 			break;
671 		}
672 
673 		// Reset the offering flag
674 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCTransMadeAnOffering = 1;
675 
676 		// If this was the correct offering, move to the open door scene
677 		if (itemID == _correctOfferingID) {
678 			_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10), 128, false, true);
679 			((SceneViewWindow *)viewWindow)->moveToDestination(_correctDestination);
680 		}
681 
682 		// These items don't get consumed
683 		if (itemID == kItemWaterCanFull || itemID == kItemGoldCoins)
684 			return SIC_REJECT;
685 
686 		return SIC_ACCEPT;
687 	}
688 
689 	return SIC_REJECT;
690 }
691 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)692 int GenericCavernDoorOfferingHead::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
693 	Location newLocation = _staticData.location;
694 	newLocation.depth = 0;
695 	((SceneViewWindow *)viewWindow)->jumpToScene(newLocation);
696 	return SC_TRUE;
697 }
698 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)699 int GenericCavernDoorOfferingHead::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
700 	return kCursorPutDown;
701 }
702 
isValidItemToDrop(Window * viewWindow,int itemID)703 bool GenericCavernDoorOfferingHead::isValidItemToDrop(Window *viewWindow, int itemID) {
704 	// If this is walkthrough mode, only accept the correct item
705 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1) {
706 		if (itemID == _correctOfferingID || (_staticData.location.node == 8 && itemID == kItemBloodyArrow))
707 			return true;
708 
709 		return false;
710 	}
711 
712 	// Otherwise, any of the allowed items
713 	switch (itemID) {
714 	case kItemCavernSkull:
715 	case kItemEntrySkull:
716 	case kItemSpearSkull:
717 	case kItemBloodyArrow:
718 	case kItemCopperMedallion:
719 	case kItemCoilOfRope:
720 	case kItemCopperKey:
721 	case kItemJadeBlock:
722 	case kItemLimestoneBlock:
723 	case kItemObsidianBlock:
724 	case kItemGrapplingHook:
725 	case kItemPreservedHeart:
726 	case kItemHammer:
727 	case kItemGoldCoins:
728 	case kItemWaterCanEmpty:
729 	case kItemWaterCanFull:
730 	case kItemWoodenPegs:
731 	case kItemBalconyKey:
732 	case kItemBurnedLetter: // Can't actually drop this, though
733 		return true;
734 	}
735 
736 	return false;
737 }
738 
739 class DeathGodCavernDoorOfferingHead : public SceneBase {
740 public:
741 	DeathGodCavernDoorOfferingHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
742 			int correctOfferingDestDepth = 0, int transitionType = -1, int transitionData = -1, int transitionStartFrame = -1, int transitionLength = -1);
743 	int preExitRoom(Window *viewWindow, const Location &newLocation);
744 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
745 	int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
746 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
747 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
748 
749 private:
750 	DestinationScene _correctDestination;
751 	Common::Rect _dropRegion;
752 };
753 
DeathGodCavernDoorOfferingHead(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int correctOfferingDestDepth,int transitionType,int transitionData,int transitionStartFrame,int transitionLength)754 DeathGodCavernDoorOfferingHead::DeathGodCavernDoorOfferingHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
755 		int correctOfferingDestDepth, int transitionType, int transitionData, int transitionStartFrame, int transitionLength) :
756 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
757 	_correctDestination.destinationScene = _staticData.location;
758 	_correctDestination.destinationScene.depth = correctOfferingDestDepth;
759 	_correctDestination.transitionType = transitionType;
760 	_correctDestination.transitionData = transitionData;
761 	_correctDestination.transitionStartFrame = transitionStartFrame;
762 	_correctDestination.transitionLength = transitionLength;
763 	_dropRegion = Common::Rect(50, 76, 228, 182);
764 
765 	byte offerings = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCDeathGodOfferings;
766 
767 	if (offerings & 1) {
768 		if (offerings & 2) {
769 			if (offerings & 4)
770 				_staticData.navFrameIndex = 190;
771 			else
772 				_staticData.navFrameIndex = 189;
773 		} else if (offerings & 4) {
774 			_staticData.navFrameIndex = 188;
775 		} else {
776 			_staticData.navFrameIndex = 186;
777 		}
778 	} else if (offerings & 2) {
779 		if (offerings & 4)
780 			_staticData.navFrameIndex = 187;
781 		else
782 			_staticData.navFrameIndex = 185;
783 	} else if (offerings & 4) {
784 		_staticData.navFrameIndex = 184;
785 	}
786 }
787 
preExitRoom(Window * viewWindow,const Location & newLocation)788 int DeathGodCavernDoorOfferingHead::preExitRoom(Window *viewWindow, const Location &newLocation) {
789 	// Put any pieces placed in the head back in the inventory
790 	byte &offerings = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCDeathGodOfferings;
791 
792 	if (offerings & 1)
793 		((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemObsidianBlock);
794 	if (offerings & 2)
795 		((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemJadeBlock);
796 	if (offerings & 4)
797 		((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->addItem(kItemLimestoneBlock);
798 
799 	offerings = 0;
800 	return SC_TRUE;
801 }
802 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)803 int DeathGodCavernDoorOfferingHead::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
804 	// Return to depth zero
805 	DestinationScene newDest;
806 	newDest.destinationScene = _staticData.location;
807 	newDest.destinationScene.depth = 0;
808 	newDest.transitionType = TRANSITION_NONE;
809 	newDest.transitionData = -1;
810 	newDest.transitionStartFrame = -1;
811 	newDest.transitionLength = -1;
812 	((SceneViewWindow *)viewWindow)->moveToDestination(newDest);
813 	return SC_TRUE;
814 }
815 
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)816 int DeathGodCavernDoorOfferingHead::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
817 	if ((itemID == kItemJadeBlock || itemID == kItemLimestoneBlock || itemID == kItemObsidianBlock) && _dropRegion.contains(pointLocation)) {
818 		byte offerings = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCDeathGodOfferings;
819 
820 		if ((offerings & 1) != 0 && itemID == kItemObsidianBlock)
821 			return 0;
822 		if ((offerings & 2) != 0 && itemID == kItemJadeBlock)
823 			return 0;
824 		if ((offerings & 4) != 0 && itemID == kItemLimestoneBlock)
825 			return 0;
826 
827 		return 1;
828 	}
829 
830 	return 0;
831 }
832 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)833 int DeathGodCavernDoorOfferingHead::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
834 	if (pointLocation.x == -1 && pointLocation.y == -1)
835 		return SIC_REJECT;
836 
837 	if ((itemID == kItemJadeBlock || itemID == kItemLimestoneBlock || itemID == kItemObsidianBlock) && _dropRegion.contains(pointLocation)) {
838 		byte &offerings = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myMCDeathGodOfferings;
839 
840 		// Make sure we didn't already place the item
841 		if ((offerings & 1) != 0 && itemID == kItemObsidianBlock)
842 			return SIC_REJECT;
843 		if ((offerings & 2) != 0 && itemID == kItemJadeBlock)
844 			return SIC_REJECT;
845 		if ((offerings & 4) != 0 && itemID == kItemLimestoneBlock)
846 			return SIC_REJECT;
847 
848 		// Add the item
849 		if (itemID == kItemObsidianBlock)
850 			offerings |= 1;
851 		else if (itemID == kItemJadeBlock)
852 			offerings |= 2;
853 		else if (itemID == kItemLimestoneBlock)
854 			offerings |= 4;
855 
856 		// Change the image
857 		if (offerings & 1) {
858 			if (offerings & 2) {
859 				if (offerings & 4)
860 					_staticData.navFrameIndex = 190;
861 				else
862 					_staticData.navFrameIndex = 189;
863 			} else if (offerings & 4) {
864 				_staticData.navFrameIndex = 188;
865 			} else {
866 				_staticData.navFrameIndex = 186;
867 			}
868 		} else if (offerings & 2) {
869 			if (offerings & 4)
870 				_staticData.navFrameIndex = 187;
871 			else
872 				_staticData.navFrameIndex = 185;
873 		} else if (offerings & 4) {
874 			_staticData.navFrameIndex = 184;
875 		} else {
876 			_staticData.navFrameIndex = 152;
877 		}
878 
879 		viewWindow->invalidateWindow(false);
880 
881 		if ((offerings & 1) != 0 && (offerings & 2) != 0 && (offerings & 4) != 0) {
882 			_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 10), 128, false, true);
883 			((SceneViewWindow *)viewWindow)->moveToDestination(_correctDestination);
884 		}
885 
886 		return SIC_ACCEPT;
887 	}
888 
889 	return SIC_REJECT;
890 }
891 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)892 int DeathGodCavernDoorOfferingHead::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
893 	return kCursorPutDown;
894 }
895 
896 class WealthGodRopeDrop : public SceneBase {
897 public:
898 	WealthGodRopeDrop(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
899 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
900 	int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
901 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
902 
903 private:
904 	Common::Rect _dropRope;
905 };
906 
WealthGodRopeDrop(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)907 WealthGodRopeDrop::WealthGodRopeDrop(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
908 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
909 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().myWGPlacedRope == 1)
910 		_staticData.navFrameIndex = 121;
911 
912 	_dropRope = Common::Rect(222, 149, 282, 189);
913 }
914 
postEnterRoom(Window * viewWindow,const Location & priorLocation)915 int WealthGodRopeDrop::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
916 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().myWGPlacedRope != 0) {
917 		Location newLocation = _staticData.location;
918 		newLocation.depth = 1;
919 		((SceneViewWindow *)viewWindow)->jumpToScene(newLocation);
920 	}
921 
922 	return SC_TRUE;
923 }
924 
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)925 int WealthGodRopeDrop::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
926 	// OK, I honestly didn't know you could use the grappling hook here
927 	if (_dropRope.contains(pointLocation) && (itemID == kItemCoilOfRope || itemID == kItemGrapplingHook))
928 		return 1;
929 
930 	return 0;
931 }
932 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)933 int WealthGodRopeDrop::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
934 	if (pointLocation.x == -1 && pointLocation.y == -1)
935 		return SIC_REJECT;
936 
937 	if (_dropRope.contains(pointLocation) && (itemID == kItemCoilOfRope || itemID == kItemGrapplingHook)) {
938 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myWGPlacedRope = 1;
939 		Location newLocation = _staticData.location;
940 		newLocation.depth = 1;
941 		((SceneViewWindow *)viewWindow)->jumpToScene(newLocation);
942 		return SIC_ACCEPT;
943 	}
944 
945 	return SIC_REJECT;
946 }
947 
948 class WaterGodInitialWalkSetFlag : public SceneBase {
949 public:
950 	WaterGodInitialWalkSetFlag(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
951 };
952 
WaterGodInitialWalkSetFlag(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)953 WaterGodInitialWalkSetFlag::WaterGodInitialWalkSetFlag(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
954 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
955 	// Set flag on entry
956 	((SceneViewWindow *)viewWindow)->getGlobalFlags().myWTCurrentBridgeStatus = 1;
957 }
958 
959 class WaterGodBridgeJump : public SceneBase {
960 public:
961 	WaterGodBridgeJump(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
962 			int movieFileNameID = 0, int playingStartingFrame = 0, int sequenceStartingFrame = 0, int framesPerCycle = 0,
963 			int jumpFudgeFrames = 0, int sequenceLength = 0, bool jumpMidCycle = false, int frameOffsetToEndOfSwing = 0);
964 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
965 	int preExitRoom(Window *viewWindow, const Location &newLocation);
966 	int postExitRoom(Window *viewWindow, const Location &newLocation);
967 	int timerCallback(Window *viewWindow);
968 	int movieCallback(Window *viewWindow, VideoWindow *movie, int animationID, int status);
969 
970 private:
971 	int _movieID;
972 	int _startingMovieFrame;
973 	int _playingStartingFrame;
974 	int _framesPerCycle;
975 	int _sequenceLength;
976 	int _jumpFudgeFrames;
977 	int _finalFrameIndex;
978 	int _soundID;
979 	DestinationScene _savedDestForward;
980 	bool _jumpMidCycle;
981 	int _frameOffsetToEndOfSwing;
982 };
983 
WaterGodBridgeJump(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int movieFileNameID,int playingStartingFrame,int sequenceStartingFrame,int framesPerCycle,int jumpFudgeFrames,int sequenceLength,bool jumpMidCycle,int frameOffsetToEndOfSwing)984 WaterGodBridgeJump::WaterGodBridgeJump(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
985 		int movieFileNameID, int playingStartingFrame, int sequenceStartingFrame, int framesPerCycle,
986 		int jumpFudgeFrames, int sequenceLength, bool jumpMidCycle, int frameOffsetToEndOfSwing) :
987 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
988 	_movieID = movieFileNameID;
989 	_playingStartingFrame = playingStartingFrame;
990 	_startingMovieFrame = sequenceStartingFrame;
991 	_framesPerCycle = framesPerCycle;
992 	_sequenceLength = sequenceLength;
993 	_jumpFudgeFrames = jumpFudgeFrames;
994 	_finalFrameIndex = -1;
995 	_soundID = -1;
996 	_jumpMidCycle = jumpMidCycle;
997 	_frameOffsetToEndOfSwing = frameOffsetToEndOfSwing;
998 
999 	// Save the forward movement data for later
1000 	_savedDestForward = _staticData.destForward;
1001 	_staticData.destForward.destinationScene = Location(-1, -1, -1, -1, -1, -1);
1002 	_staticData.destForward.transitionType = -1;
1003 	_staticData.destForward.transitionData = -1;
1004 	_staticData.destForward.transitionStartFrame = -1;
1005 	_staticData.destForward.transitionLength = -1;
1006 
1007 	// Set visited flag
1008 	((SceneViewWindow *)viewWindow)->getGlobalFlags().myWTSteppedOnSwings = 1;
1009 }
1010 
postEnterRoom(Window * viewWindow,const Location & priorLocation)1011 int WaterGodBridgeJump::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1012 	// Raise the ambient sound
1013 	_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1014 	uint32 ambientPos = _vm->_sound->getSecondaryAmbientPosition();
1015 
1016 	int frameStartingOffset = (ambientPos / 1838) % _sequenceLength + (_startingMovieFrame - _playingStartingFrame) % _sequenceLength;
1017 
1018 	// Load and start the new asynchronous animation
1019 	((SceneViewWindow *)viewWindow)->startAsynchronousAnimation(_movieID, _startingMovieFrame, _playingStartingFrame + frameStartingOffset, _sequenceLength, true);
1020 	return SC_TRUE;
1021 }
1022 
preExitRoom(Window * viewWindow,const Location & newLocation)1023 int WaterGodBridgeJump::preExitRoom(Window *viewWindow, const Location &newLocation) {
1024 	_finalFrameIndex = ((SceneViewWindow *)viewWindow)->getAsynchronousAnimationCurrentPosition();
1025 
1026 	// Moving to another node should kill the anim
1027 	if (newLocation.node != 4 || newLocation.timeZone != 2 || newLocation.environment != 4)
1028 		((SceneViewWindow *)viewWindow)->stopAsynchronousAnimation();
1029 
1030 	// If we are walking into a node less than 5, kill the ambient
1031 	if (newLocation.node <= 3)
1032 		_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1033 
1034 	return SC_TRUE;
1035 }
1036 
postExitRoom(Window * viewWindow,const Location & newLocation)1037 int WaterGodBridgeJump::postExitRoom(Window *viewWindow, const Location &newLocation) {
1038 	if (newLocation.facing == _staticData.location.facing && newLocation.timeZone == _staticData.location.timeZone &&
1039 			newLocation.environment == _staticData.location.environment) {
1040 		if (_jumpMidCycle) {
1041 			int diff = (_finalFrameIndex - _playingStartingFrame) % (_framesPerCycle * 2);
1042 			int diffB = (_finalFrameIndex - _playingStartingFrame - _framesPerCycle) % _framesPerCycle;
1043 			int diffC = _framesPerCycle - (_finalFrameIndex - _playingStartingFrame) % _framesPerCycle;
1044 
1045 			if (diff > _framesPerCycle || diffB > _framesPerCycle || diffC > _jumpFudgeFrames * 2) {
1046 				if (_staticData.location.facing == 0)
1047 					((SceneViewWindow *)viewWindow)->showDeathScene(14);
1048 				else
1049 					((SceneViewWindow *)viewWindow)->showDeathScene(15);
1050 
1051 				return SC_DEATH;
1052 			}
1053 		} else {
1054 			if ((_finalFrameIndex - _playingStartingFrame) % _framesPerCycle > _jumpFudgeFrames && _framesPerCycle - (_finalFrameIndex - _playingStartingFrame) % _framesPerCycle > _jumpFudgeFrames) {
1055 				if (_staticData.location.facing == 0)
1056 					((SceneViewWindow *)viewWindow)->showDeathScene(14);
1057 				else
1058 					((SceneViewWindow *)viewWindow)->showDeathScene(15);
1059 
1060 				return SC_DEATH;
1061 			}
1062 		}
1063 	}
1064 
1065 	return SC_TRUE;
1066 }
1067 
timerCallback(Window * viewWindow)1068 int WaterGodBridgeJump::timerCallback(Window *viewWindow) {
1069 	// If we have reached the end of the starting sequence, reset the arrows
1070 	if (_staticData.destForward.destinationScene.timeZone == -1 && ((SceneViewWindow *)viewWindow)->getAsynchronousAnimationCurrentPosition() >= _startingMovieFrame) {
1071 		_staticData.destForward = _savedDestForward;
1072 		((GameUIWindow *)viewWindow->getParent())->_navArrowWindow->updateAllArrows(_staticData);
1073 	}
1074 
1075 	return SC_TRUE;
1076 }
1077 
movieCallback(Window * viewWindow,VideoWindow * movie,int animationID,int status)1078 int WaterGodBridgeJump::movieCallback(Window *viewWindow, VideoWindow *movie, int animationID, int status) {
1079 	if (status == MOVIE_LOOPING_RESTART)
1080 		_vm->_sound->restartSecondaryAmbientSound();
1081 
1082 	return SC_TRUE;
1083 }
1084 
1085 class ArrowGodHead : public SceneBase {
1086 public:
1087 	ArrowGodHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
1088 			int headID = 0, int clickLeft = -1, int clickTop = -1, int clickRight = -1, int clickBottom = -1,
1089 			int emptyClosedStill = -1, int emptyOpenStill = -1, int fullClosedStill = -1, int fullOpenStill = -1,
1090 			int emptyClosedAnim = -1, int emptyOpenAnim = -1, int fullClosedAnim = -1, int fullOpenAnim = -1);
1091 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1092 	int mouseDown(Window *viewWindow, const Common::Point &pointLocation);
1093 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1094 	int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1095 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1096 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1097 	int timerCallback(Window *viewWindow);
1098 
1099 private:
1100 	int _headID;
1101 	Common::Rect _skullRegion;
1102 	int _stillFrames[4];
1103 	int _soundID;
1104 	int _headAnimations[4];
1105 };
1106 
ArrowGodHead(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,int headID,int clickLeft,int clickTop,int clickRight,int clickBottom,int emptyClosedStill,int emptyOpenStill,int fullClosedStill,int fullOpenStill,int emptyClosedAnim,int emptyOpenAnim,int fullClosedAnim,int fullOpenAnim)1107 ArrowGodHead::ArrowGodHead(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
1108 		int headID, int clickLeft, int clickTop, int clickRight, int clickBottom,
1109 		int emptyClosedStill, int emptyOpenStill, int fullClosedStill, int fullOpenStill,
1110 		int emptyClosedAnim, int emptyOpenAnim, int fullClosedAnim, int fullOpenAnim) :
1111 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1112 	_soundID = -1;
1113 	_headID = headID;
1114 	_skullRegion = Common::Rect(clickLeft, clickTop, clickRight, clickBottom);
1115 	_stillFrames[0] = emptyClosedStill;
1116 	_stillFrames[1] = emptyOpenStill;
1117 	_stillFrames[2] = fullClosedStill;
1118 	_stillFrames[3] = fullOpenStill;
1119 	_headAnimations[0] = emptyClosedAnim;
1120 	_headAnimations[1] = emptyOpenAnim;
1121 	_headAnimations[2] = fullClosedAnim;
1122 	_headAnimations[3] = fullOpenAnim;
1123 	_staticData.navFrameIndex = _stillFrames[((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID)];
1124 }
1125 
postEnterRoom(Window * viewWindow,const Location & priorLocation)1126 int ArrowGodHead::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1127 	byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1128 	byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1129 
1130 	if (_staticData.location.node == 0) {
1131 		if (headAStatus == 0)
1132 			_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1133 		else if (headDStatus == 0)
1134 			_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1135 		else
1136 			_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1137 	} else if (_staticData.location.node == 2) {
1138 		if (headAStatus == 0 || headDStatus == 0)
1139 			_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1140 		else
1141 			_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1142 	}
1143 
1144 	return SC_TRUE;
1145 }
1146 
mouseDown(Window * viewWindow,const Common::Point & pointLocation)1147 int ArrowGodHead::mouseDown(Window *viewWindow, const Common::Point &pointLocation) {
1148 	// For walkthrough mode, don't allow input
1149 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && (_headID == 0 || _headID == 3))
1150 		return SC_FALSE;
1151 
1152 	if (_skullRegion.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID) == 3) {
1153 		byte skullIndex = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatusSkullID) + _headID);
1154 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatusSkullID) + _headID, 0);
1155 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID, 1);
1156 		_staticData.navFrameIndex = _stillFrames[1];
1157 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadATouched) + _headID, 1);
1158 
1159 		// Begin dragging
1160 		Common::Point ptInventoryWindow = viewWindow->convertPointToWindow(pointLocation, ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow);
1161 		((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->startDraggingNewItem(skullIndex, ptInventoryWindow);
1162 		((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1163 		return SC_TRUE;
1164 	}
1165 
1166 	return SC_FALSE;
1167 }
1168 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1169 int ArrowGodHead::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1170 	// For walkthrough mode, don't allow input
1171 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && (_headID == 0 || _headID == 3))
1172 		return SC_FALSE;
1173 
1174 	// Did we click on the head?
1175 	if (_skullRegion.contains(pointLocation)) {
1176 		byte headStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID);
1177 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadATouched) + _headID, 1);
1178 
1179 		if (headStatus & 1)
1180 			headStatus--;
1181 		else
1182 			headStatus++;
1183 
1184 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID, headStatus);
1185 
1186 		// Play the proper movie
1187 		int currentSoundID = -1;
1188 		if (headStatus == 2)
1189 			currentSoundID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1190 		else
1191 			currentSoundID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
1192 
1193 		if ((_headID == 1 || _headID == 2) && headStatus == 0) {
1194 			if (_staticData.location.node == 0)
1195 				_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
1196 			else
1197 				_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 96);
1198 		}
1199 
1200 		((SceneViewWindow *)viewWindow)->playSynchronousAnimation(_headAnimations[headStatus]);
1201 
1202 		_staticData.navFrameIndex = _stillFrames[headStatus];
1203 		viewWindow->invalidateWindow(false);
1204 
1205 		byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1206 		byte headBStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadBStatus;
1207 		byte headCStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadCStatus;
1208 		byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1209 
1210 		if (_staticData.location.node == 0) {
1211 			if (headAStatus == 0)
1212 				_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1213 			else if (headDStatus == 0)
1214 				_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1215 			else
1216 				_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1217 		} else if (_staticData.location.node == 2) {
1218 			if (headAStatus == 0 || headDStatus == 0)
1219 				_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1220 			else
1221 				_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1222 		}
1223 
1224 		_vm->_sound->stopSoundEffect(currentSoundID);
1225 
1226 		if (_staticData.location.node == 0 && (headBStatus < 3 && headCStatus < 3))
1227 			_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
1228 		else if (_staticData.location.node == 2 && (headBStatus < 3 && headCStatus < 3))
1229 			_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 96);
1230 
1231 		if (headStatus & 1)
1232 			((SceneViewWindow *)viewWindow)->setGlobalFlagDWord(offsetof(GlobalFlags, myAGHeadAOpenedTime) + _headID * 4, g_system->getMillis());
1233 
1234 		((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1235 		return SC_TRUE;
1236 	}
1237 
1238 	return SC_FALSE;
1239 }
1240 
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1241 int ArrowGodHead::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1242 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && (_headID == 0 || _headID == 3))
1243 		return 0;
1244 
1245 	if ((itemID == kItemCavernSkull || itemID == kItemEntrySkull || itemID == kItemSpearSkull) && ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID) < 2 && _skullRegion.contains(pointLocation))
1246 		return 1;
1247 
1248 	return 0;
1249 }
1250 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1251 int ArrowGodHead::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1252 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && (_headID == 0 || _headID == 3))
1253 		return SIC_REJECT;
1254 
1255 	if (pointLocation.x == -1 && pointLocation.y == -1)
1256 		return SIC_REJECT;
1257 
1258 	if ((itemID == kItemCavernSkull || itemID == kItemEntrySkull || itemID == kItemSpearSkull) && ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID) == 1 && _skullRegion.contains(pointLocation)) {
1259 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID, 2);
1260 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadATouched) + _headID, 1);
1261 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatusSkullID) + _headID, itemID);
1262 
1263 		int currentSoundID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1264 
1265 		((SceneViewWindow *)viewWindow)->playSynchronousAnimation(_headAnimations[2]);
1266 
1267 		_staticData.navFrameIndex = _stillFrames[2];
1268 		viewWindow->invalidateWindow(false);
1269 
1270 		byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1271 		byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1272 
1273 		if (_staticData.location.node == 0) {
1274 			if (headAStatus == 0)
1275 				_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1276 			else if (headDStatus == 0)
1277 				_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1278 			else
1279 				_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1280 		} else if (_staticData.location.node == 2) {
1281 			if (headAStatus == 0 || headDStatus == 0)
1282 				_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1283 			else
1284 				_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1285 		}
1286 
1287 		_vm->_sound->stopSoundEffect(currentSoundID);
1288 
1289 		((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1290 		return SIC_ACCEPT;
1291 	}
1292 
1293 	return SIC_REJECT;
1294 }
1295 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1296 int ArrowGodHead::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1297 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && (_headID == 0 || _headID == 3))
1298 		return 0;
1299 
1300 	if (_skullRegion.contains(pointLocation)) {
1301 		if (((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + _headID) == 3)
1302 			return kCursorOpenHand;
1303 
1304 		return kCursorFinger;
1305 	}
1306 
1307 	return 0;
1308 }
1309 
timerCallback(Window * viewWindow)1310 int ArrowGodHead::timerCallback(Window *viewWindow) {
1311 	for (int i = 0; i < 4; i++) {
1312 		uint32 lastStartedTimer = ((SceneViewWindow *)viewWindow)->getGlobalFlagDWord(offsetof(GlobalFlags, myAGHeadAOpenedTime) + i * 4);
1313 
1314 		if (lastStartedTimer > 0 && g_system->getMillis() > (lastStartedTimer + WAR_GOD_HEAD_TIMER_VALUE)) {
1315 			((SceneViewWindow *)viewWindow)->setGlobalFlagDWord(offsetof(GlobalFlags, myAGHeadAOpenedTime) + i * 4, 0);
1316 
1317 			TempCursorChange cursorChange(kCursorWait);
1318 
1319 			if (i == _headID) {
1320 				byte status = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i);
1321 
1322 				if (status & 1) {
1323 					status--;
1324 					((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i, status);
1325 
1326 					int currentSoundID = -1;
1327 					if (status == 2)
1328 						currentSoundID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1329 					else
1330 						currentSoundID = _vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128, false, true);
1331 
1332 					((SceneViewWindow *)viewWindow)->playSynchronousAnimation(_headAnimations[status]);
1333 
1334 					_staticData.navFrameIndex = _stillFrames[status];
1335 					viewWindow->invalidateWindow(false);
1336 
1337 					_vm->_sound->stopSoundEffect(currentSoundID);
1338 
1339 					byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1340 					byte headBStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadBStatus;
1341 					byte headCStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadCStatus;
1342 					byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1343 
1344 					if (_staticData.location.node == 0) {
1345 						if (headAStatus == 0)
1346 							_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1347 						else if (headDStatus == 0)
1348 							_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1349 						else
1350 							_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1351 					} else if (_staticData.location.node == 2) {
1352 						if (headAStatus == 0 || headDStatus == 0)
1353 							_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1354 						else
1355 							_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1356 					}
1357 
1358 					// Play the door closing sound, if applicable
1359 					if (i == 1 || i == 2) {
1360 						if (_staticData.location.node == 0 && (headBStatus == 0 || headCStatus == 0))
1361 							_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
1362 						else if (_staticData.location.node == 2 && (headBStatus == 0 || headCStatus == 0))
1363 							_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 96);
1364 					}
1365 				}
1366 
1367 				((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1368 			} else {
1369 				byte status = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i);
1370 
1371 				if (status & 1) {
1372 					status--;
1373 					((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i, status);
1374 
1375 					if (status == 2)
1376 						_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128);
1377 					else
1378 						_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
1379 
1380 					byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1381 					byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1382 
1383 					if (_staticData.location.node == 0) {
1384 						if (headAStatus == 0)
1385 							_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1386 						else if (headDStatus == 0)
1387 							_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1388 						else
1389 							_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1390 					} else if (_staticData.location.node == 2) {
1391 						if (headAStatus == 0 || headDStatus == 0)
1392 							_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1393 						else
1394 							_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1395 					}
1396 				}
1397 
1398 				((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1399 
1400 				if (_headID == 1 || _headID == 2) {
1401 					if (_staticData.location.node == 0)
1402 						_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 127);
1403 					else if (_staticData.location.node == 2)
1404 						_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), 96);
1405 				}
1406 			}
1407 		}
1408 	}
1409 
1410 	return SC_TRUE;
1411 }
1412 
1413 class ArrowGodDepthChange : public SceneBase {
1414 public:
1415 	ArrowGodDepthChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1416 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1417 	int postExitRoom(Window *viewWindow, const Location &newLocation);
1418 	int timerCallback(Window *viewWindow);
1419 
1420 private:
1421 	bool _scheduledDepthChange;
1422 	int _soundID;
1423 
1424 	bool adjustSpearVolume(Window *viewWindow);
1425 };
1426 
ArrowGodDepthChange(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1427 ArrowGodDepthChange::ArrowGodDepthChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1428 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1429 	_scheduledDepthChange = false;
1430 	_soundID = -1;
1431 
1432 	byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1433 	byte headBStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadBStatus;
1434 	byte headCStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadCStatus;
1435 	byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1436 
1437 	int targetDepth = 0;
1438 
1439 	if (headBStatus > 0 || headCStatus > 0) {
1440 		if (headBStatus > 0) {
1441 			if (headAStatus == 0 || headDStatus == 0) {
1442 				if (headAStatus == 0 && headDStatus == 0) {
1443 					targetDepth = 11;
1444 				} else if (headAStatus > 0 && headDStatus == 0) {
1445 					targetDepth = 10;
1446 				} else if (headAStatus == 0 && headDStatus > 0) {
1447 					targetDepth = 9;
1448 				}
1449 			} else {
1450 				targetDepth = 8;
1451 			}
1452 		} else if (headCStatus > 0) {
1453 			if (headAStatus == 0 || headDStatus == 0) {
1454 				if (headAStatus == 0 && headDStatus == 0) {
1455 					targetDepth = 7;
1456 				} else if (headAStatus > 0 && headDStatus == 0) {
1457 					targetDepth = 6;
1458 				} else if (headAStatus == 0 && headDStatus > 0) {
1459 					targetDepth = 5;
1460 				}
1461 			} else {
1462 				targetDepth = 4;
1463 			}
1464 		}
1465 	} else if (headAStatus == 0 || headDStatus == 0) {
1466 		if (headAStatus == 0 && headBStatus == 0) {
1467 			targetDepth = 3;
1468 		} else {
1469 			if (headAStatus > 0 && headDStatus == 0) {
1470 				targetDepth = 2;
1471 			} else if (headAStatus == 0 && headDStatus > 0) {
1472 				targetDepth = 1;
1473 			}
1474 		}
1475 	}
1476 
1477 	if (_staticData.location.depth != targetDepth) {
1478 		Location newLocation = _staticData.location;
1479 		newLocation.depth = targetDepth;
1480 		((SceneViewWindow *)viewWindow)->getSceneStaticData(newLocation, _staticData);
1481 		_frameCycleCount = _staticData.cycleStartFrame;
1482 
1483 		// Reload the frame files, if applicable
1484 		((SceneViewWindow *)viewWindow)->changeStillFrameMovie(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, SF_STILLS));
1485 
1486 		if (_staticData.cycleStartFrame >= 0)
1487 			((SceneViewWindow *)viewWindow)->changeCycleFrameMovie(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, SF_CYCLES));
1488 	}
1489 }
1490 
postEnterRoom(Window * viewWindow,const Location & priorLocation)1491 int ArrowGodDepthChange::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1492 	if (((priorLocation.depth >= 8 && priorLocation.depth <= 11) && _staticData.location.depth < 8) ||
1493 			((priorLocation.depth >= 4 && priorLocation.depth <= 7) && _staticData.location.depth < 4)) {
1494 		byte headBStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadBStatus;
1495 		byte headCStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadCStatus;
1496 		byte &headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1497 		byte doorLevelVolume = 0;
1498 
1499 		switch (_staticData.location.node) {
1500 		case 0:
1501 		case 1:
1502 			doorLevelVolume = 127;
1503 			break;
1504 		case 2:
1505 			doorLevelVolume = 96;
1506 
1507 			if (headDStatus == 2) {
1508 				headDStatus--;
1509 				_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 13), 128);
1510 				_scheduledDepthChange = true;
1511 				adjustSpearVolume(viewWindow);
1512 				((SceneViewWindow *)viewWindow)->jumpToScene(_staticData.location);
1513 				return SC_TRUE; // Original does not return here, but the status of this would be bad in that case
1514 			}
1515 			break;
1516 		case 3:
1517 			if (headCStatus == 0)
1518 				doorLevelVolume = 127;
1519 			else if (headBStatus == 0)
1520 				doorLevelVolume = 64;
1521 			break;
1522 		}
1523 
1524 		if (doorLevelVolume > 0)
1525 			_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 11), doorLevelVolume);
1526 	}
1527 
1528 	adjustSpearVolume(viewWindow);
1529 	return SC_TRUE;
1530 }
1531 
postExitRoom(Window * viewWindow,const Location & newLocation)1532 int ArrowGodDepthChange::postExitRoom(Window *viewWindow, const Location &newLocation) {
1533 	if (_staticData.location.timeZone == newLocation.timeZone &&
1534 			_staticData.location.environment == newLocation.environment &&
1535 			_staticData.location.node == newLocation.node &&
1536 			_staticData.location.facing == newLocation.facing &&
1537 			_staticData.location.orientation == newLocation.orientation &&
1538 			_staticData.location.depth == newLocation.depth &&
1539 			!_scheduledDepthChange) {
1540 		// Notify the player of his gruesome death
1541 		((SceneViewWindow *)viewWindow)->showDeathScene(13);
1542 		return SC_DEATH;
1543 	}
1544 
1545 	return SC_TRUE;
1546 }
1547 
timerCallback(Window * viewWindow)1548 int ArrowGodDepthChange::timerCallback(Window *viewWindow) {
1549 	SceneBase::timerCallback(viewWindow);
1550 
1551 	// Check to see if we moved into a death scene
1552 	if (_staticData.location.timeZone == 2 && _staticData.location.environment == 5 &&
1553 			_staticData.location.node == 1 && _staticData.location.facing == 3 &&
1554 			_staticData.location.orientation == 1 && (_staticData.location.depth == 1 ||
1555 			_staticData.location.depth == 3 || _staticData.location.depth == 11 ||
1556 			_staticData.location.depth == 7 || _staticData.location.depth == 5 ||
1557 			_staticData.location.depth == 9)) {
1558 		if (_staticData.location.depth == 1)
1559 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(19);
1560 
1561 		((SceneViewWindow *)viewWindow)->showDeathScene(13);
1562 		return SC_DEATH;
1563 	}
1564 
1565 	if (_staticData.location.timeZone == 2 && _staticData.location.environment == 5 &&
1566 			_staticData.location.node == 3 && _staticData.location.facing == 3 &&
1567 			_staticData.location.orientation == 1 && (_staticData.location.depth == 2 ||
1568 			_staticData.location.depth == 3 || _staticData.location.depth == 11 ||
1569 			_staticData.location.depth == 10 || _staticData.location.depth == 6 ||
1570 			_staticData.location.depth == 7)) {
1571 		((SceneViewWindow *)viewWindow)->playSynchronousAnimation(17);
1572 		((SceneViewWindow *)viewWindow)->showDeathScene(13);
1573 		return SC_DEATH;
1574 	}
1575 
1576 	// Loop through the four heads
1577 	for (int i = 0; i < 4; i++) {
1578 		uint32 lastStartedTimer = ((SceneViewWindow *)viewWindow)->getGlobalFlagDWord(offsetof(GlobalFlags, myAGHeadAOpenedTime) + i * 4);
1579 
1580 		// Check if there is a timer going for this head
1581 		if (lastStartedTimer > 0 && (g_system->getMillis() > (lastStartedTimer + WAR_GOD_HEAD_TIMER_VALUE) ||
1582 				i == 0 || (((SceneViewWindow *)viewWindow)->getGlobalFlags().generalWalkthroughMode == 1 && i == 1) ||
1583 				(((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i) == 2 && i == 3))) {
1584 			((SceneViewWindow *)viewWindow)->setGlobalFlagDWord(offsetof(GlobalFlags, myAGHeadAOpenedTime) + i * 4, 0);
1585 			TempCursorChange cursorChange(kCursorWait);
1586 			byte status = ((SceneViewWindow *)viewWindow)->getGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i);
1587 
1588 			if (status & 1) {
1589 				status--;
1590 				((SceneViewWindow *)viewWindow)->setGlobalFlagByte(offsetof(GlobalFlags, myAGHeadAStatus) + i, status);
1591 				_vm->_sound->playSynchronousSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, (status == 2) ? 14 : 13), 128);
1592 				_scheduledDepthChange = true;
1593 				adjustSpearVolume(viewWindow);
1594 			}
1595 
1596 			((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->sceneChanged();
1597 		}
1598 	}
1599 
1600 	if (_scheduledDepthChange) {
1601 		_scheduledDepthChange = false;
1602 		Location location = _staticData.location;
1603 		((SceneViewWindow *)viewWindow)->jumpToScene(location);
1604 	}
1605 
1606 	return SC_TRUE;
1607 }
1608 
adjustSpearVolume(Window * viewWindow)1609 bool ArrowGodDepthChange::adjustSpearVolume(Window *viewWindow) {
1610 	// TODO: Looks like there's a bug in the original. node == 3 should also be in here, I think
1611 	// Need to investigate
1612 	if (_staticData.location.node >= 0 && _staticData.location.node <= 2) {
1613 		byte headAStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadAStatus;
1614 		byte headDStatus = ((SceneViewWindow *)viewWindow)->getGlobalFlags().myAGHeadDStatus;
1615 
1616 		if (headAStatus == 0) {
1617 			_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1618 		} else if (headDStatus == 0) {
1619 			if (_staticData.location.node == 2)
1620 				_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
1621 			else
1622 				_vm->_sound->adjustSecondaryAmbientSoundVolume(64, false, 0, 0);
1623 		} else {
1624 			_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
1625 		}
1626 	}
1627 
1628 	return true;
1629 }
1630 
1631 class DeathGodAltar : public SceneBase {
1632 public:
1633 	DeathGodAltar(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1634 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
1635 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1636 	int draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1637 	int droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags);
1638 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1639 	int locateAttempted(Window *viewWindow, const Common::Point &pointLocation);
1640 
1641 private:
1642 	Common::Rect _heartPool;
1643 	Common::Rect _puzzleBox;
1644 	Common::Rect _blood;
1645 };
1646 
DeathGodAltar(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1647 DeathGodAltar::DeathGodAltar(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1648 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1649 	_heartPool = Common::Rect(89, 80, 159, 112);
1650 	_puzzleBox = Common::Rect(150, 45, 260, 111);
1651 	_blood = Common::Rect(88, 76, 162, 114);
1652 }
1653 
postEnterRoom(Window * viewWindow,const Location & priorLocation)1654 int DeathGodAltar::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
1655 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 1) {
1656 		if (!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_ENVIRON_CART)) {
1657 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(3);
1658 			_staticData.navFrameIndex = 51;
1659 			viewWindow->invalidateWindow(false);
1660 
1661 			if ((_staticData.location.timeZone != priorLocation.timeZone || _staticData.location.environment != priorLocation.environment ||
1662 					_staticData.location.node != priorLocation.node || _staticData.location.facing != priorLocation.facing ||
1663 					_staticData.location.orientation != priorLocation.orientation || _staticData.location.depth != priorLocation.depth) &&
1664 					!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_ENVIRON_CART))
1665 				((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
1666 		}
1667 	} else if ((_staticData.location.timeZone != priorLocation.timeZone || _staticData.location.environment != priorLocation.environment ||
1668 			_staticData.location.node != priorLocation.node || _staticData.location.facing != priorLocation.facing ||
1669 			_staticData.location.orientation != priorLocation.orientation || _staticData.location.depth != priorLocation.depth) &&
1670 			!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_PHONY_BLOOD)) {
1671 		((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
1672 	}
1673 
1674 	return SC_TRUE;
1675 }
1676 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1677 int DeathGodAltar::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1678 	if (_puzzleBox.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 1 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0) {
1679 		Location puzzleLocation = _staticData.location;
1680 		puzzleLocation.depth = 1;
1681 		((SceneViewWindow *)viewWindow)->jumpToScene(puzzleLocation);
1682 	}
1683 
1684 	return SC_FALSE;
1685 }
1686 
draggingItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1687 int DeathGodAltar::draggingItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1688 	if (itemID == kItemPreservedHeart && ((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 0 && _heartPool.contains(pointLocation))
1689 		return 1;
1690 
1691 	return 0;
1692 }
1693 
droppedItem(Window * viewWindow,int itemID,const Common::Point & pointLocation,int itemFlags)1694 int DeathGodAltar::droppedItem(Window *viewWindow, int itemID, const Common::Point &pointLocation, int itemFlags) {
1695 	if (pointLocation.x == -1 && pointLocation.y == -1)
1696 		return SIC_REJECT;
1697 
1698 	if (itemID == kItemPreservedHeart && ((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 0 && _heartPool.contains(pointLocation)) {
1699 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart = 1;
1700 		((SceneViewWindow *)viewWindow)->playSynchronousAnimation(2);
1701 		((SceneViewWindow *)viewWindow)->playSynchronousAnimation(3);
1702 		_staticData.navFrameIndex = 51;
1703 
1704 		if (!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_ENVIRON_CART))
1705 			((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_PRESENT));
1706 
1707 		return SIC_ACCEPT;
1708 	}
1709 
1710 	return SIC_REJECT;
1711 }
1712 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1713 int DeathGodAltar::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1714 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
1715 		if (((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 1 &&
1716 				((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0 &&
1717 				_staticData.navFrameIndex == 51 && _puzzleBox.contains(pointLocation))
1718 			return -2;
1719 
1720 		if (_blood.contains(pointLocation))
1721 			return -2;
1722 
1723 		return -1;
1724 	} else if (_puzzleBox.contains(pointLocation) && ((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOfferedHeart == 1 && ((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0) {
1725 		// This logic is broken in 1.04, 1.05, and 1.10. I fixed it here to match mouseUp
1726 		return kCursorFinger;
1727 	}
1728 
1729 	return kCursorArrow;
1730 }
1731 
locateAttempted(Window * viewWindow,const Common::Point & pointLocation)1732 int DeathGodAltar::locateAttempted(Window *viewWindow, const Common::Point &pointLocation) {
1733 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1 &&
1734 			((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0 &&
1735 			_puzzleBox.contains(pointLocation) && _staticData.navFrameIndex == 51 &&
1736 			!((SceneViewWindow *)viewWindow)->isNumberInGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), MAYAN_EVIDENCE_ENVIRON_CART)) {
1737 		((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_MUST_BE_REVEALED)); // All will be reveaaaaaaaaled (Yes, I used this joke twice now)
1738 		return SC_TRUE;
1739 	}
1740 
1741 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
1742 		if (_blood.contains(pointLocation)) {
1743 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(6);
1744 
1745 			// Attempt to add it to the biochip
1746 			if (((SceneViewWindow *)viewWindow)->addNumberToGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), 12, MAYAN_EVIDENCE_PHONY_BLOOD))
1747 				((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ACQUIRED));
1748 			else
1749 				((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ALREADY_ACQUIRED));
1750 
1751 			// Disable capture
1752 			((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->disableEvidenceCapture();
1753 		}
1754 
1755 		return SC_TRUE;
1756 	}
1757 
1758 	return SC_FALSE;
1759 }
1760 
1761 class DeathGodPuzzleBox : public SceneBase {
1762 public:
1763 	DeathGodPuzzleBox(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1764 	~DeathGodPuzzleBox();
1765 	void preDestructor();
1766 	int paint(Window *viewWindow, Graphics::Surface *preBuffer);
1767 	int gdiPaint(Window *viewWindow);
1768 	int mouseUp(Window *viewWindow, const Common::Point &pointLocation);
1769 	int mouseMove(Window *viewWindow, const Common::Point &pointLocation);
1770 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1771 
1772 private:
1773 	int _puzzleIndexes[4];
1774 	Common::Rect _clickableRegions[4];
1775 	Common::Rect _puzzleRightHandle;
1776 	AVIFrames _puzzleFrames[4];
1777 	bool _translateText;
1778 
1779 	bool isPuzzleSolved() const;
1780 };
1781 
DeathGodPuzzleBox(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)1782 DeathGodPuzzleBox::DeathGodPuzzleBox(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
1783 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
1784 	_translateText = false;
1785 	_puzzleIndexes[0] = _puzzleIndexes[1] = _puzzleIndexes[2] = _puzzleIndexes[3] = 0;
1786 	_clickableRegions[0] = Common::Rect(30, 0, 111, 189);
1787 	_clickableRegions[1] = Common::Rect(112, 0, 187, 189);
1788 	_clickableRegions[2] = Common::Rect(188, 0, 252, 189);
1789 	_clickableRegions[3] = Common::Rect(253, 0, 330, 189);
1790 	_puzzleRightHandle = Common::Rect(380, 0, 432, 189);
1791 
1792 	// Load the spinner movies
1793 	_puzzleFrames[0].open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 4));
1794 	_puzzleFrames[1].open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 5));
1795 	_puzzleFrames[2].open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 6));
1796 	_puzzleFrames[3].open(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 7));
1797 }
1798 
~DeathGodPuzzleBox()1799 DeathGodPuzzleBox::~DeathGodPuzzleBox() {
1800 	preDestructor();
1801 }
1802 
preDestructor()1803 void DeathGodPuzzleBox::preDestructor() {
1804 	_puzzleFrames[0].close();
1805 	_puzzleFrames[1].close();
1806 	_puzzleFrames[2].close();
1807 	_puzzleFrames[3].close();
1808 }
1809 
paint(Window * viewWindow,Graphics::Surface * preBuffer)1810 int DeathGodPuzzleBox::paint(Window *viewWindow, Graphics::Surface *preBuffer) {
1811 	SceneBase::paint(viewWindow, preBuffer);
1812 
1813 	for (int i = 0; i < 4; i++) {
1814 		const Graphics::Surface *spinnerFrame = _puzzleFrames[i].getFrame(_puzzleIndexes[i]);
1815 		_vm->_gfx->crossBlit(preBuffer, _clickableRegions[i].left, _clickableRegions[i].top, _clickableRegions[i].width(), _clickableRegions[i].height(), spinnerFrame, 0, 0);
1816 	}
1817 
1818 	return SC_REPAINT;
1819 }
1820 
gdiPaint(Window * viewWindow)1821 int DeathGodPuzzleBox::gdiPaint(Window *viewWindow) {
1822 	if (_translateText && ((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
1823 		Common::Rect absoluteRect = viewWindow->getAbsoluteRect();
1824 		Common::Rect rect(42, 64, 324, 125);
1825 		rect.translate(absoluteRect.left, absoluteRect.top);
1826 		_vm->_gfx->getScreen()->frameRect(rect, _vm->_gfx->getColor(255, 0, 0));
1827 	}
1828 
1829 	return SC_REPAINT;
1830 }
1831 
mouseUp(Window * viewWindow,const Common::Point & pointLocation)1832 int DeathGodPuzzleBox::mouseUp(Window *viewWindow, const Common::Point &pointLocation) {
1833 	for (int i = 0; i < 4; i++) {
1834 		if (_clickableRegions[i].contains(pointLocation)) {
1835 			if (pointLocation.y - _clickableRegions[i].top > _clickableRegions[i].height() / 2) {
1836 				// Start the roll sound
1837 				_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1838 
1839 				// Spin the wheel, stop at the new value
1840 				// FIXME: Timing
1841 				for (int j = 0; j < 6; j++) {
1842 					_puzzleIndexes[i]--;
1843 					if (_puzzleIndexes[i] < 0)
1844 						_puzzleIndexes[i] = _puzzleFrames[i].getFrameCount() - 2;
1845 					viewWindow->invalidateWindow();
1846 					_vm->_gfx->updateScreen();
1847 				}
1848 
1849 				_translateText = false;
1850 				mouseMove(viewWindow, pointLocation);
1851 			} else {
1852 				// Start the roll sound
1853 				_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, 14), 128, false, true);
1854 
1855 				// Spin the wheel, stop at the new value
1856 				// FIXME: Timing
1857 				for (int j = 0; j < 6; j++) {
1858 					_puzzleIndexes[i]++;
1859 					if (_puzzleIndexes[i] > _puzzleFrames[i].getFrameCount() - 2)
1860 						_puzzleIndexes[i] = 0;
1861 					viewWindow->invalidateWindow();
1862 					_vm->_gfx->updateScreen();
1863 				}
1864 
1865 				_translateText = false;
1866 				mouseMove(viewWindow, pointLocation);
1867 			}
1868 		}
1869 	}
1870 
1871 	if (_puzzleRightHandle.contains(pointLocation)) {
1872 		if (isPuzzleSolved()) {
1873 			DestinationScene newDestination;
1874 			newDestination.destinationScene = _staticData.location;
1875 			newDestination.destinationScene.depth = 2;
1876 			newDestination.transitionType = TRANSITION_VIDEO;
1877 			newDestination.transitionStartFrame = -1;
1878 			newDestination.transitionLength = -1;
1879 
1880 			if (((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0)
1881 				newDestination.transitionData = 4;
1882 			else
1883 				newDestination.transitionData = 5;
1884 
1885 			BuriedEngine *vm = _vm;
1886 			((SceneViewWindow *)viewWindow)->moveToDestination(newDestination);
1887 
1888 			// Play animation capturing the evidence
1889 			// FIXME: Is this right? Shouldn't this be if takenEnvironCart == 0 only?
1890 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(7);
1891 
1892 			// Attempt to add it to the biochip
1893 			if (((SceneViewWindow *)viewWindow)->addNumberToGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), 12, MAYAN_EVIDENCE_ENVIRON_CART))
1894 				((SceneViewWindow *)viewWindow)->displayLiveText(vm->getString(IDS_MBT_EVIDENCE_RIPPLE_DOCUMENTED));
1895 			else
1896 				((SceneViewWindow *)viewWindow)->displayLiveText(vm->getString(IDS_MBT_EVIDENCE_ALREADY_ACQUIRED));
1897 
1898 			// Disable capture
1899 			((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->disableEvidenceCapture();
1900 
1901 			// Set the scoring flag
1902 			((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreCompletedDeathGod = 1;
1903 			((SceneViewWindow *)viewWindow)->getGlobalFlags().myDGOpenedPuzzleBox = 1;
1904 
1905 			// Play an Arthur comment
1906 			if (((SceneViewWindow *)viewWindow)->getGlobalFlags().takenEnvironCart == 0 && ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemBioChipAI))
1907 				vm->_sound->playSoundEffect("BITDATA/MAYAN/MYDG_C01.BTA"); // Broken in 1.01
1908 
1909 			return SC_TRUE;
1910 		} else {
1911 			// We did the puzzle incorrectly, so spin the wheels and kill the player
1912 			((SceneViewWindow *)viewWindow)->playPlacedSynchronousAnimation(8, 320, 0);
1913 			((SceneViewWindow *)viewWindow)->showDeathScene(12);
1914 			return SC_DEATH;
1915 		}
1916 	}
1917 
1918 	return SC_FALSE;
1919 }
1920 
mouseMove(Window * viewWindow,const Common::Point & pointLocation)1921 int DeathGodPuzzleBox::mouseMove(Window *viewWindow, const Common::Point &pointLocation) {
1922 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcTranslateEnabled == 1) {
1923 		Common::Rect translateTextRegion(42, 64, 324, 126);
1924 
1925 		if (translateTextRegion.contains(pointLocation)) {
1926 			if (!_translateText) {
1927 				Common::String translatedText = _vm->getString(IDMYDG_PUZZLE_BOX_TRANS_TEXT_BASE + _puzzleIndexes[0] / 6);
1928 				translatedText += ' ';
1929 				translatedText += _vm->getString(IDMYDG_PUZZLE_BOX_TRANS_TEXT_BASE + 10 + _puzzleIndexes[1] / 6);
1930 				translatedText += ' ';
1931 				translatedText += _vm->getString(IDMYDG_PUZZLE_BOX_TRANS_TEXT_BASE + 20 + _puzzleIndexes[2] / 6);
1932 				translatedText += ' ';
1933 				translatedText += _vm->getString(IDMYDG_PUZZLE_BOX_TRANS_TEXT_BASE + 30 + _puzzleIndexes[3] / 6);
1934 
1935 				((SceneViewWindow *)viewWindow)->displayTranslationText(translatedText);
1936 
1937 				_translateText = true;
1938 				viewWindow->invalidateWindow(false);
1939 			}
1940 		} else {
1941 			if (_translateText) {
1942 				_translateText = false;
1943 				viewWindow->invalidateWindow(false);
1944 			}
1945 		}
1946 	}
1947 
1948 	return SC_FALSE;
1949 }
1950 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)1951 int DeathGodPuzzleBox::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
1952 	for (int i = 0; i < 4; i++) {
1953 		if (_clickableRegions[i].contains(pointLocation)) {
1954 			if (pointLocation.y - _clickableRegions[i].top > _clickableRegions[i].height() / 2)
1955 				return kCursorArrowDown;
1956 
1957 			return kCursorArrowUp;
1958 		}
1959 	}
1960 
1961 	if (_puzzleRightHandle.contains(pointLocation))
1962 		return kCursorFinger;
1963 
1964 	return kCursorArrow;
1965 }
1966 
isPuzzleSolved() const1967 bool DeathGodPuzzleBox::isPuzzleSolved() const {
1968 	// TODO: Ask players for solutions for other languages
1969 	// clone2727 has the English, French, and Japanese source.
1970 	// clone2727 has the Italian and Spanish versions and solved the puzzle
1971 	// manually for those.
1972 
1973 	switch (_vm->getLanguage()) {
1974 	case Common::DE_DEU:
1975 	case Common::ES_ESP:
1976 	case Common::IT_ITA:
1977 		return _puzzleIndexes[0] == 12 && _puzzleIndexes[1] == 18 && _puzzleIndexes[2] == 30 && _puzzleIndexes[3] == 24;
1978 	case Common::EN_ANY:
1979 		return _puzzleIndexes[0] == 18 && _puzzleIndexes[1] == 36 && _puzzleIndexes[2] == 12 && _puzzleIndexes[3] == 24;
1980 	case Common::FR_FRA:
1981 		return _puzzleIndexes[0] == 12 && _puzzleIndexes[1] == 18 && _puzzleIndexes[2] == 42 && _puzzleIndexes[3] == 24;
1982 	case Common::JA_JPN:
1983 		return _puzzleIndexes[0] == 12 && _puzzleIndexes[1] == 24 && _puzzleIndexes[2] == 30 && _puzzleIndexes[3] == 18;
1984 	default:
1985 		// Default to English, but warn about it
1986 		warning("Unknown language for puzzle box");
1987 		return _puzzleIndexes[0] == 18 && _puzzleIndexes[1] == 36 && _puzzleIndexes[2] == 12 && _puzzleIndexes[3] == 24;
1988 	}
1989 
1990 	return false;
1991 }
1992 
1993 class MainCavernGlassCapture : public SceneBase {
1994 public:
1995 	MainCavernGlassCapture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
1996 	int locateAttempted(Window *viewWindow, const Common::Point &pointLocation);
1997 	int specifyCursor(Window *viewWindow, const Common::Point &pointLocation);
1998 
1999 private:
2000 	Common::Rect _glass;
2001 };
2002 
MainCavernGlassCapture(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2003 MainCavernGlassCapture::MainCavernGlassCapture(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2004 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2005 	_glass = Common::Rect(305, 126, 355, 156);
2006 }
2007 
locateAttempted(Window * viewWindow,const Common::Point & pointLocation)2008 int MainCavernGlassCapture::locateAttempted(Window *viewWindow, const Common::Point &pointLocation) {
2009 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
2010 		if (_glass.contains(pointLocation)) {
2011 			// Play the animation
2012 			((SceneViewWindow *)viewWindow)->playSynchronousAnimation(22);
2013 
2014 			// Attempt to add it to the biochip
2015 			if (((SceneViewWindow *)viewWindow)->addNumberToGlobalFlagTable(offsetof(GlobalFlags, evcapBaseID), offsetof(GlobalFlags, evcapNumCaptured), 12, MAYAN_EVIDENCE_BROKEN_GLASS_PYRAMID))
2016 				((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ACQUIRED));
2017 			else
2018 				((SceneViewWindow *)viewWindow)->displayLiveText(_vm->getString(IDS_MBT_EVIDENCE_ALREADY_ACQUIRED));
2019 
2020 			// Disable capture
2021 			((GameUIWindow *)viewWindow->getParent())->_bioChipRightWindow->disableEvidenceCapture();
2022 		}
2023 
2024 		return SC_TRUE;
2025 	}
2026 
2027 	return SC_FALSE;
2028 }
2029 
specifyCursor(Window * viewWindow,const Common::Point & pointLocation)2030 int MainCavernGlassCapture::specifyCursor(Window *viewWindow, const Common::Point &pointLocation) {
2031 	if (((SceneViewWindow *)viewWindow)->getGlobalFlags().bcLocateEnabled == 1) {
2032 		if (_glass.contains(pointLocation))
2033 			return -2;
2034 
2035 		return -1;
2036 	}
2037 
2038 	return kCursorArrow;
2039 }
2040 
2041 class WalkVolumeChange : public SceneBase {
2042 public:
2043 	WalkVolumeChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2044 			byte newVolume = 0, uint32 volumeChangeTime = 0, int stepCount = -1, int entryEffectFileNameID = -1);
2045 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2046 	int preExitRoom(Window *viewWindow, const Location &newLocation);
2047 
2048 private:
2049 	byte _newVolume;
2050 	uint32 _volumeChangeTime;
2051 	int _stepCount;
2052 	int _entryEffectFileNameID;
2053 };
2054 
WalkVolumeChange(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,byte newVolume,uint32 volumeChangeTime,int stepCount,int entryEffectFileNameID)2055 WalkVolumeChange::WalkVolumeChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2056 		byte newVolume, uint32 volumeChangeTime, int stepCount, int entryEffectFileNameID) :
2057 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2058 	_newVolume = newVolume;
2059 	_volumeChangeTime = volumeChangeTime;
2060 	_stepCount = stepCount;
2061 	_entryEffectFileNameID = entryEffectFileNameID;
2062 }
2063 
postEnterRoom(Window * viewWindow,const Location & priorLocation)2064 int WalkVolumeChange::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2065 	if (_entryEffectFileNameID >= 0 && priorLocation.node != _staticData.location.node)
2066 		_vm->_sound->playSoundEffect(_vm->getFilePath(_staticData.location.timeZone, _staticData.location.environment, _entryEffectFileNameID), 128, false, true);
2067 
2068 	return SC_TRUE;
2069 }
2070 
preExitRoom(Window * viewWindow,const Location & newLocation)2071 int WalkVolumeChange::preExitRoom(Window *viewWindow, const Location &newLocation) {
2072 	if (_stepCount >= 0 && newLocation.node != _staticData.location.node)
2073 		_vm->_sound->adjustAmbientSoundVolume(_newVolume, true, _stepCount, _volumeChangeTime);
2074 
2075 	return SC_TRUE;
2076 }
2077 
2078 class AdjustSecondaryAmbientOnEntry : public SceneBase {
2079 public:
2080 	AdjustSecondaryAmbientOnEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation);
2081 	int postEnterRoom(Window *viewWindow, const Location &priorLocation);
2082 	int preExitRoom(Window *viewWindow, const Location &newLocation);
2083 };
2084 
AdjustSecondaryAmbientOnEntry(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2085 AdjustSecondaryAmbientOnEntry::AdjustSecondaryAmbientOnEntry(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) :
2086 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2087 }
2088 
postEnterRoom(Window * viewWindow,const Location & priorLocation)2089 int AdjustSecondaryAmbientOnEntry::postEnterRoom(Window *viewWindow, const Location &priorLocation) {
2090 	_vm->_sound->adjustSecondaryAmbientSoundVolume(128, false, 0, 0);
2091 	return SC_TRUE;
2092 }
2093 
preExitRoom(Window * viewWindow,const Location & newLocation)2094 int AdjustSecondaryAmbientOnEntry::preExitRoom(Window *viewWindow, const Location &newLocation) {
2095 	// Kill the ambient if moving to a different node
2096 	if (newLocation.node != _staticData.location.node)
2097 		_vm->_sound->adjustSecondaryAmbientSoundVolume(0, false, 0, 0);
2098 
2099 	return SC_TRUE;
2100 }
2101 
2102 class WalkDualAmbientVolumeChange : public SceneBase {
2103 public:
2104 	WalkDualAmbientVolumeChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2105 			byte newVolume = 0, byte secondVolume = 0, uint32 volumeChangeTime = 0, int stepCount = -1);
2106 	int preExitRoom(Window *viewWindow, const Location &newLocation);
2107 
2108 private:
2109 	byte _newVolume;
2110 	uint32 _volumeChangeTime;
2111 	int _stepCount;
2112 	byte _secondVolume;
2113 };
2114 
WalkDualAmbientVolumeChange(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,byte newVolume,byte secondVolume,uint32 volumeChangeTime,int stepCount)2115 WalkDualAmbientVolumeChange::WalkDualAmbientVolumeChange(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2116 		byte newVolume, byte secondVolume, uint32 volumeChangeTime, int stepCount) :
2117 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2118 	_newVolume = newVolume;
2119 	_volumeChangeTime = volumeChangeTime;
2120 	_stepCount = stepCount;
2121 	_secondVolume = secondVolume;
2122 
2123 	// If we have stepped on the far ledge, set the flag
2124 	if (_staticData.location.timeZone == 2 && _staticData.location.environment == 4 &&
2125 			_staticData.location.node == 5 && _staticData.location.facing == 0 &&
2126 			_staticData.location.orientation == 1 && _staticData.location.depth == 0)
2127 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myWTSteppedOnFarLedge = 1;
2128 }
2129 
preExitRoom(Window * viewWindow,const Location & newLocation)2130 int WalkDualAmbientVolumeChange::preExitRoom(Window *viewWindow, const Location &newLocation) {
2131 	if (_stepCount >= 0 && newLocation.node != _staticData.location.node) {
2132 		_vm->_sound->adjustAmbientSoundVolume(_newVolume, true, _stepCount, _volumeChangeTime);
2133 		_vm->_sound->adjustSecondaryAmbientSoundVolume(_secondVolume, true, _stepCount, _volumeChangeTime);
2134 	}
2135 
2136 	return SC_TRUE;
2137 }
2138 
2139 class SetVolumeAndFlag : public SceneBase {
2140 public:
2141 	SetVolumeAndFlag(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2142 			byte newVolume = 64, int flagOffset = -1, byte flagValue = 255);
2143 };
2144 
SetVolumeAndFlag(BuriedEngine * vm,Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation,byte newVolume,int flagOffset,byte flagValue)2145 SetVolumeAndFlag::SetVolumeAndFlag(BuriedEngine *vm, Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation,
2146 		byte newVolume, int flagOffset, byte flagValue) :
2147 		SceneBase(vm, viewWindow, sceneStaticData, priorLocation) {
2148 	_vm->_sound->adjustAmbientSoundVolume(newVolume, false, 0, 0);
2149 
2150 	if (flagOffset >= 0)
2151 		((SceneViewWindow *)viewWindow)->setGlobalFlagByte(flagOffset, flagValue);
2152 }
2153 
initializeMayanTimeZoneAndEnvironment(Window * viewWindow,int environment)2154 bool SceneViewWindow::initializeMayanTimeZoneAndEnvironment(Window *viewWindow, int environment) {
2155 	if (environment == -1) {
2156 		GlobalFlags &flags = ((SceneViewWindow *)viewWindow)->getGlobalFlags();
2157 
2158 		flags.myTPCodeWheelStatus = flags.generalWalkthroughMode;
2159 		flags.myTPCodeWheelLeftIndex = flags.generalWalkthroughMode == 1 ? 8 : 0;
2160 		flags.myTPCodeWheelRightIndex = flags.generalWalkthroughMode == 1 ? 12 : 0;
2161 		flags.myMCDeathGodOfferings = 0;
2162 		flags.myWGPlacedRope = flags.generalWalkthroughMode;
2163 		flags.myWTCurrentBridgeStatus = 0;
2164 		flags.myAGHeadAStatus = flags.generalWalkthroughMode == 1 ? 2 : 0;
2165 		flags.myAGHeadBStatus = 0;
2166 		flags.myAGHeadCStatus = 0;
2167 		flags.myAGHeadDStatus = flags.generalWalkthroughMode == 1 ? 2 : 0;
2168 		flags.myAGHeadAStatusSkullID = flags.generalWalkthroughMode == 1 ? kItemCavernSkull : 0;
2169 		flags.myAGHeadBStatusSkullID = 0;
2170 		flags.myAGHeadCStatusSkullID = 0;
2171 		flags.myAGHeadDStatusSkullID = flags.generalWalkthroughMode == 1 ? kItemSpearSkull : 0;
2172 		flags.myAGTimerHeadID = 0;
2173 		flags.myAGTimerStartTime = 0;
2174 		flags.myDGOfferedHeart = 0;
2175 		flags.myAGHeadAOpenedTime = 0;
2176 		flags.myAGHeadBOpenedTime = 0;
2177 		flags.myAGHeadCOpenedTime = 0;
2178 		flags.myAGHeadDOpenedTime = 0;
2179 
2180 		flags.myPickedUpCeramicBowl = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemCeramicBowl) ? 1 : 0;
2181 		flags.myMCPickedUpSkull = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) ? 1 : 0;
2182 		flags.myWGRetrievedJadeBlock = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemJadeBlock) ? 1 : 0;
2183 		flags.myWTRetrievedLimestoneBlock = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemLimestoneBlock) ? 1 : 0;
2184 		flags.myAGRetrievedEntrySkull = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) ? 1 : 0;
2185 		flags.myAGRetrievedSpearSkull = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull) ? 1 : 0;
2186 		flags.myAGRetrievedCopperMedal = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemCopperMedallion) ? 1 : 0;
2187 		flags.myAGRetrievedObsidianBlock = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemObsidianBlock) ? 1 : 0;
2188 		flags.takenEnvironCart = ((GameUIWindow *)viewWindow->getParent())->_inventoryWindow->isItemInInventory(kItemEnvironCart) ? 1 : 0;
2189 
2190 		if (flags.generalWalkthroughMode == 1) {
2191 			flags.myMCPickedUpSkull = 1;
2192 			flags.myAGRetrievedSpearSkull = 1;
2193 			flags.myAGRetrievedCopperMedal = 1;
2194 		}
2195 	} else if (environment == 2) {
2196 		((SceneViewWindow *)viewWindow)->getGlobalFlags().scoreEnteredMainCavern = 1;
2197 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedMainCavern = 1;
2198 	} else if (environment == 3) {
2199 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedWealthGod = 1;
2200 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedSpecRooms = 1;
2201 	} else if (environment == 4) {
2202 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedWaterGod = 1;
2203 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedSpecRooms = 1;
2204 	} else if (environment == 5) {
2205 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedArrowGod = 1;
2206 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedSpecRooms = 1;
2207 	} else if (environment == 6) {
2208 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedDeathGod = 1;
2209 		((SceneViewWindow *)viewWindow)->getGlobalFlags().myVisitedSpecRooms = 1;
2210 	}
2211 
2212 	return true;
2213 }
2214 
startMayanAmbient(int oldTimeZone,int oldEnvironment,int environment,bool fade)2215 bool SceneViewWindow::startMayanAmbient(int oldTimeZone, int oldEnvironment, int environment, bool fade) {
2216 	bool checkFade = true;
2217 
2218 	if (environment == 3) {
2219 		if (oldEnvironment == 2)
2220 			return _vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), checkFade, 64);
2221 
2222 		return _vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), checkFade, 16);
2223 	} else if (environment == 4) {
2224 		if (oldTimeZone == -2)
2225 			_vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), fade, 64);
2226 		else
2227 			_vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), fade, 16);
2228 
2229 		return _vm->_sound->setSecondaryAmbientSound(_vm->getFilePath(2, environment, 13), checkFade, 0);
2230 	} else if (environment == 5) {
2231 		_vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), fade, 64);
2232 		return _vm->_sound->setSecondaryAmbientSound(_vm->getFilePath(2, environment, 12), checkFade, 128);
2233 	}
2234 
2235 	_vm->_sound->setAmbientSound(_vm->getFilePath(2, environment, SF_AMBIENT), fade, 64);
2236 	return true;
2237 }
2238 
checkCustomMayanAICommentDependencies(const Location & commentLocation,const AIComment & commentData)2239 bool SceneViewWindow::checkCustomMayanAICommentDependencies(const Location &commentLocation, const AIComment &commentData) {
2240 	//((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory
2241 
2242 	switch (commentData.dependencyFlagOffsetB) {
2243 	case 1: // Player hasn't translated any inscriptions
2244 		return _globalFlags.myTPTextTranslated == 0;
2245 	case 2: // Player hasn't translated any inscriptions, has translate biochip
2246 		return _globalFlags.myTPTextTranslated == 0 && ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemBioChipTranslate);
2247 	case 3: // Player hasn't translated any inscriptions, doesn't have translate biochip
2248 		return _globalFlags.myTPTextTranslated == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemBioChipTranslate);
2249 	case 4: // Has translated inscription above calendar, calendar not set to sacred day, player has never been to main cavern
2250 		return _globalFlags.myTPCalendarTopTranslated == 1 && _globalFlags.myTPCodeWheelStatus == 0 && _globalFlags.myVisitedMainCavern == 0;
2251 	case 5: // Has translated inscription above calendar, calendar is set to sacred day, player has never been to main cavern
2252 		return _globalFlags.myTPCalendarTopTranslated == 1 && _globalFlags.myTPCodeWheelStatus == 1 && _globalFlags.myVisitedMainCavern == 0;
2253 	case 6: // Player has never been to main cavern
2254 		return _globalFlags.myVisitedMainCavern == 0;
2255 	case 7: // Player has never been to main cavern, calendar not set to sacred day
2256 		return _globalFlags.myVisitedMainCavern == 0 && _globalFlags.myTPCodeWheelStatus == 0;
2257 	case 8: // Ceramic bowl not in the inventory
2258 		return !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCeramicBowl);
2259 	case 9: // If node is not 5, 6, or 8
2260 		return commentLocation.node != 6 && commentLocation.node != 5 && commentLocation.node != 8;
2261 	case 10: // If node is not 1, 0, 7, or 8
2262 		return commentLocation.node != 1 && commentLocation.node != 0 && commentLocation.node != 7 && commentLocation.node != 8;
2263 	case 11: // If node is not 0, 8, or 1
2264 		return commentLocation.node != 0 && commentLocation.node != 8 && commentLocation.node != 1;
2265 	case 12: // If not translated any sacred days
2266 		return _globalFlags.myTPCalendarListTranslated == 0;
2267 	case 13: // Not any door, no translations
2268 		return _globalFlags.myVisitedSpecRooms == 0 && _globalFlags.myMCTransDoor == 0;
2269 	case 14: // Not any door, no translations, has translate chip
2270 		return _globalFlags.myVisitedSpecRooms == 0 && _globalFlags.myMCTransDoor == 0 && ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemBioChipTranslate);
2271 	case 15: // Not any door, has translated arrow or translated water or translated wealth
2272 		return _globalFlags.myVisitedSpecRooms == 0 && (_globalFlags.myMCTransAGOffering == 1 || _globalFlags.myMCTransWGOffering == 1 || _globalFlags.myMCTransWTOffering == 1);
2273 	case 16: // Has translated wealth, has not been through wealth god door
2274 		return _globalFlags.myMCTransWGOffering == 1 && _globalFlags.myVisitedWealthGod == 0;
2275 	case 17: // Has translated water, has not been through water god door
2276 		return _globalFlags.myMCTransWTOffering == 1 && _globalFlags.myVisitedWaterGod == 0;
2277 	case 18: // Has translated arrow, has not been through arrow god door
2278 		return _globalFlags.myMCTransAGOffering == 1 && _globalFlags.myVisitedArrowGod == 0;
2279 	case 19: // Has translated death, has not been through death god door
2280 		return _globalFlags.myMCTransDGOffering == 1 && _globalFlags.myVisitedDeathGod == 0;
2281 	case 20: // Has not been through death god door
2282 		return _globalFlags.myVisitedDeathGod == 0;
2283 	case 21: // Has translated death
2284 		return _globalFlags.myMCTransDGOffering == 1;
2285 	case 22: // After making any offering
2286 		return _globalFlags.myMCTransMadeAnOffering == 1;
2287 	case 23: // Before crossing rope bridge
2288 		return _globalFlags.myWGCrossedRopeBridge == 0;
2289 	case 24: // If player has translated inscription above wealth god door in cavern
2290 		return _globalFlags.myMCTransWGOffering == 1;
2291 	case 25: // If player has not translated inscription above wealth god door in cavern
2292 		return _globalFlags.myMCTransWGOffering == 0;
2293 	case 26: // If player has translated inscription above wealth god door in cavern, has never been to wealth god altar room
2294 		return _globalFlags.myMCTransWGOffering == 1 && _globalFlags.myWGSeenLowerPassage == 0;
2295 	case 27: // Has not attached either rope or grappling hook, has never been to wealth god altar room
2296 		return _globalFlags.myWGPlacedRope == 0 && _globalFlags.myWGSeenLowerPassage == 0;
2297 	case 28: // Player has never stepped on swings
2298 		return _globalFlags.myWTSteppedOnSwings == 0;
2299 	case 29: // Player has never been on far ledge
2300 		return _globalFlags.myWTSteppedOnFarLedge == 0;
2301 	case 30: // Never put in heart
2302 		return _globalFlags.myDGOfferedHeart == 0;
2303 	case 31: // Never put in heart, no heart in inventory
2304 		return _globalFlags.myDGOfferedHeart == 0 && ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemPreservedHeart);
2305 	case 32: // After put in heart, puzzle box never opened
2306 		return _globalFlags.myDGOfferedHeart == 1 && _globalFlags.myDGOpenedPuzzleBox == 0;
2307 	case 33: // After put in heart, puzzle box never opened, player has not translated 'Itzamna' inscription over inside door of temple
2308 		return _globalFlags.myDGOfferedHeart == 1 && _globalFlags.myDGOpenedPuzzleBox == 0 && _globalFlags.myTPTransBreathOfItzamna == 0;
2309 	case 34: // After put in heart, puzzle box never opened, player has translated 'Itzamna' inscription over inside door of temple
2310 		return _globalFlags.myDGOfferedHeart == 1 && _globalFlags.myDGOpenedPuzzleBox == 0 && _globalFlags.myTPTransBreathOfItzamna == 1;
2311 	case 35: // Before interacting with any heads
2312 		return _globalFlags.myAGHeadATouched == 0 && _globalFlags.myAGHeadBTouched == 0 && _globalFlags.myAGHeadCTouched == 0 && _globalFlags.myAGHeadDTouched == 0;
2313 	case 36: // After interacting with any head, before jamming any head
2314 		return (_globalFlags.myAGHeadATouched == 1 || _globalFlags.myAGHeadBTouched == 1 || _globalFlags.myAGHeadCTouched == 1 || _globalFlags.myAGHeadDTouched == 1) && _globalFlags.myAGHeadAStatus == 0 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0;
2315 	case 37: // S2 jam, S1 not jam, not altar
2316 		return _globalFlags.myAGHeadAStatus == 0 && _globalFlags.myAGHeadBStatus == 2 && _globalFlags.myAGVisitedAltar == 0;
2317 	case 38: // S1 jam, S2 not jam, S3 not jam, not altar
2318 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGVisitedAltar == 0;
2319 	case 39: // S1 jam, S2 not jam, S3 not jam, S4 not jam, not altar, no skulls
2320 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGVisitedAltar == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull);
2321 	case 40: // Before interacting with S3 or S4, not altar
2322 		return _globalFlags.myAGHeadCTouched == 0 && _globalFlags.myAGHeadDTouched == 0 && _globalFlags.myAGVisitedAltar == 0;
2323 	case 41: // S1 jam, S2 jam, S3 not jam, S4 not jam, after interacting with S3 and S4, not altar, no skulls
2324 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 2 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGHeadCTouched == 1 && _globalFlags.myAGHeadDTouched == 1 && _globalFlags.myAGVisitedAltar == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull);
2325 	case 42: // S1 jam, S2 not jam, S3 not jam, S4 not jam, after interacting with S3 and S4, not altar, only 1 skull in inventory
2326 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGHeadCTouched == 1 && _globalFlags.myAGHeadDTouched == 1 && _globalFlags.myAGVisitedAltar == 0 && (((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull));
2327 	case 43: // S1 jam, S2 jam, S3 not jam, S4 not jam, after interacting with S3 and S4, not altar, no skulls
2328 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 2 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGHeadCTouched == 1 && _globalFlags.myAGHeadDTouched == 1 && _globalFlags.myAGVisitedAltar == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull);
2329 	case 44: // S1 jam, S2 not jam, S3 jam, S4 not jam, not altar, no skulls
2330 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 2 && _globalFlags.myAGHeadDStatus == 0 && _globalFlags.myAGVisitedAltar == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull);
2331 	case 45: // S1 jam, S2 not jam, S3 not jam, S4 jam, not altar, no skulls
2332 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 2 && _globalFlags.myAGVisitedAltar == 0 && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) && !((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull);
2333 	case 46: // S1 jam, S2 not jam, S3 not jam, S4 jam, not altar, only 1 skull in inventory
2334 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadBStatus == 0 && _globalFlags.myAGHeadCStatus == 0 && _globalFlags.myAGHeadDStatus == 2 && _globalFlags.myAGVisitedAltar == 0 && (((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull));
2335 	case 47: // S1 jam, S3 jam, S4 jam, not altar
2336 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadCStatus == 2 && _globalFlags.myAGHeadDStatus == 2 && _globalFlags.myAGVisitedAltar == 0;
2337 	case 48: // S1 jam, S3 jam, not altar, only 1 skull in inventory
2338 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadCStatus == 2 && _globalFlags.myAGHeadDStatus == 2 && _globalFlags.myAGVisitedAltar == 0 && (((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemCavernSkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemEntrySkull) ^ ((GameUIWindow *)getParent())->_inventoryWindow->isItemInInventory(kItemSpearSkull));
2339 	case 49: // S1 jam, S2 jam, S3 jam, not altar
2340 		return _globalFlags.myAGHeadAStatus == 2 && _globalFlags.myAGHeadCStatus == 2 && _globalFlags.myAGHeadDStatus == 2 && _globalFlags.myAGVisitedAltar == 0;
2341 	case 50: // S1 not jam, S2 jam, not altar
2342 		return _globalFlags.myAGHeadAStatus == 0 && _globalFlags.myAGHeadBStatus == 2 && _globalFlags.myAGVisitedAltar == 0;
2343 	}
2344 
2345 	return false;
2346 }
2347 
constructMayanSceneObject(Window * viewWindow,const LocationStaticData & sceneStaticData,const Location & priorLocation)2348 SceneBase *SceneViewWindow::constructMayanSceneObject(Window *viewWindow, const LocationStaticData &sceneStaticData, const Location &priorLocation) {
2349 	// Special scene for the trial version
2350 	if (_vm->isTrial())
2351 		return new TrialRecallScene(_vm, viewWindow, sceneStaticData, priorLocation);
2352 
2353 	switch (sceneStaticData.classID) {
2354 	case 0:
2355 		// Default scene
2356 		break;
2357 	case 1:
2358 		return new VideoDeath(_vm, viewWindow, sceneStaticData, priorLocation, 10, IDS_HUMAN_PRESENCE_500METERS);
2359 	case 2:
2360 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 60, 134, 118, 180, kItemCeramicBowl, 96, offsetof(GlobalFlags, myPickedUpCeramicBowl));
2361 	case 3:
2362 		return new PlaceCeramicBowl(_vm, viewWindow, sceneStaticData, priorLocation);
2363 	case 4:
2364 		return new ClickChangeDepth(_vm, viewWindow, sceneStaticData, priorLocation, 1, kCursorMagnifyingGlass, 0, 0, 432, 189);
2365 	case 5:
2366 		return new AdjustWheels(_vm, viewWindow, sceneStaticData, priorLocation);
2367 	case 6:
2368 		return new DateCombinationRead(_vm, viewWindow, sceneStaticData, priorLocation);
2369 	case 7:
2370 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_INNER_DOOR_TRANS_TEXT, 16, 6, 402, 110, offsetof(GlobalFlags, myTPTextTranslated), offsetof(GlobalFlags, myTPTransBreathOfItzamna));
2371 	case 8:
2372 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_INNER_LEFT_TRANS_TEXT, 1, 6, 431, 98, offsetof(GlobalFlags, myTPTextTranslated));
2373 	case 9:
2374 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_INNER_MIDDLE_TRANS_TEXT, 16, 8, 430, 114, offsetof(GlobalFlags, myTPTextTranslated), offsetof(GlobalFlags, myTPCalendarTopTranslated));
2375 	case 10:
2376 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_OUTER_SOUTHLEFT_TRANS_TEXT, 4, 55, 426, 95, offsetof(GlobalFlags, myTPTextTranslated));
2377 	case 11:
2378 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_OUTER_WEST_TRANS_TEXT, 4, 72, 420, 108, offsetof(GlobalFlags, myTPTextTranslated));
2379 	case 12:
2380 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYTP_OUTER_NORTH_TRANS_TEXT, 6, 38, 428, 76, offsetof(GlobalFlags, myTPTextTranslated));
2381 	case 13:
2382 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 140, 124, 174, 158, kItemCavernSkull, 3, offsetof(GlobalFlags, myMCPickedUpSkull));
2383 	case 14:
2384 		return new GenericCavernDoorMainView(_vm, viewWindow, sceneStaticData, priorLocation, 1, 126, 1, 306, 30, 2, 287, 30, 379, 82, 3, 275, 84, 401, 174);
2385 	case 15:
2386 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_WG_DOOR_TOP_TRANS_TEXT, 12, 128, 426, 156, offsetof(GlobalFlags, myMCTransDoor), offsetof(GlobalFlags, myWGTransDoorTop));
2387 	case 16:
2388 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_WG_DOOR_RIGHT_TRANS_TEXT, 46, 1, 315, 188, offsetof(GlobalFlags, myMCTransDoor), offsetof(GlobalFlags, myMCTransWGOffering));
2389 	case 17:
2390 		return new GenericCavernDoorOfferingHead(_vm, viewWindow, sceneStaticData, priorLocation, kItemGoldCoins, 4, TRANSITION_WALK, -1, 1082, 13);
2391 	case 18:
2392 		return new GenericCavernDoorMainView(_vm, viewWindow, sceneStaticData, priorLocation, 1, 126, 1, 306, 30, 2, 287, 30, 379, 82, 3, 275, 84, 401, 174);
2393 	case 19:
2394 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_WATERGOD_DOOR_TOP_TRANS_TEXT, 12, 128, 426, 156, offsetof(GlobalFlags, myMCTransDoor));
2395 	case 20:
2396 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_WATERGOD_DOOR_RIGHT_TRANS_TEXT, 46, 1, 315, 188, offsetof(GlobalFlags, myMCTransDoor), offsetof(GlobalFlags, myMCTransWTOffering));
2397 	case 21:
2398 		return new GenericCavernDoorOfferingHead(_vm, viewWindow, sceneStaticData, priorLocation, kItemWaterCanFull, 4, TRANSITION_WALK, -1, 1125, 13);
2399 	case 22:
2400 		return new GenericCavernDoorMainView(_vm, viewWindow, sceneStaticData, priorLocation, 1, 126, 1, 306, 30, 2, 287, 30, 379, 82, 3, 275, 84, 401, 174);
2401 	case 23:
2402 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_AG_DOOR_TOP_TRANS_TEXT, 12, 128, 426, 156, offsetof(GlobalFlags, myMCTransDoor));
2403 	case 24:
2404 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_AG_DOOR_RIGHT_TRANS_TEXT, 46, 1, 315, 188, offsetof(GlobalFlags, myMCTransDoor), offsetof(GlobalFlags, myMCTransAGOffering));
2405 	case 25:
2406 		return new GenericCavernDoorOfferingHead(_vm, viewWindow, sceneStaticData, priorLocation, kItemBloodyArrow, 4, TRANSITION_WALK, -1, 1010, 12);
2407 	case 26:
2408 		return new GenericCavernDoorMainView(_vm, viewWindow, sceneStaticData, priorLocation, 1, 126, 1, 306, 30, 2, 287, 30, 379, 82, 3, 275, 84, 401, 174);
2409 	case 27:
2410 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_DEATHGOD_DOOR_TOP_TRANS_TEXT, 12, 128, 426, 156, offsetof(GlobalFlags, myMCTransDoor));
2411 	case 28:
2412 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDMYMC_DEATHGOD_DOOR_RIGHT_TRANS_TEXT, 46, 1, 315, 188, offsetof(GlobalFlags, myMCTransDoor), offsetof(GlobalFlags, myMCTransDGOffering));
2413 	case 29:
2414 		return new DeathGodCavernDoorOfferingHead(_vm, viewWindow, sceneStaticData, priorLocation, 4, TRANSITION_WALK, -1, 1045, 13);
2415 	case 30:
2416 		return new WealthGodRopeDrop(_vm, viewWindow, sceneStaticData, priorLocation);
2417 	case 31:
2418 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 194, 106, 278, 126, kItemJadeBlock, 105, offsetof(GlobalFlags, myWGRetrievedJadeBlock));
2419 	case 32:
2420 		return new BasicDoor(_vm, viewWindow, sceneStaticData, priorLocation, 140, 22, 306, 189, 2, 3, 0, 3, 1, 1, TRANSITION_WALK, -1, 264, 14, 14);
2421 	case 33:
2422 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 158, 88, 288, 116, kItemLimestoneBlock, 84, offsetof(GlobalFlags, myWTRetrievedLimestoneBlock));
2423 	case 34:
2424 		return new BasicDoor(_vm, viewWindow, sceneStaticData, priorLocation, 80, 0, 332, 189, 2, 4, 0, 2, 1, 1, TRANSITION_WALK, -1, 401, 14, 14);
2425 	case 35:
2426 		return new WaterGodInitialWalkSetFlag(_vm, viewWindow, sceneStaticData, priorLocation);
2427 	case 36:
2428 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 0, 93, 37, 10, 73, false, 18);
2429 	case 37:
2430 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 166, 259, 37, 10, 73);
2431 	case 38:
2432 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 332, 425, 37, 10, 73);
2433 	case 39:
2434 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 498, 591, 37, 10, 73);
2435 	case 40:
2436 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 664, 757, 37, 10, 73);
2437 	case 41:
2438 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 830, 925, 37, 10, 71, true);
2439 	case 42:
2440 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 999, 1075, 37, 10, 73);
2441 	case 43:
2442 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 1149, 1242, 37, 10, 73);
2443 	case 44:
2444 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 1315, 1408, 37, 10, 73);
2445 	case 45:
2446 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 1481, 1574, 37, 10, 73);
2447 	case 46:
2448 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 1647, 1740, 37, 10, 73);
2449 	case 47:
2450 		return new WaterGodBridgeJump(_vm, viewWindow, sceneStaticData, priorLocation, 4, 1813, 1906, 37, 10, 73);
2451 	case 50:
2452 		return new BasicDoor(_vm, viewWindow, sceneStaticData, priorLocation,106, 0, 294, 189, 2, 5, 0, 1, 1, 1, TRANSITION_WALK, -1, 427, 13, 11);
2453 	case 51:
2454 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 235, 144, 285, 181, kItemEntrySkull, 3, offsetof(GlobalFlags, myAGRetrievedEntrySkull));
2455 	case 52:
2456 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 200, 138, 231, 185, kItemSpearSkull, 46, offsetof(GlobalFlags, myAGRetrievedSpearSkull));
2457 	case 53:
2458 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 201, 4, 235, 22, kItemCopperMedallion, 45, offsetof(GlobalFlags, myAGRetrievedCopperMedal));
2459 	case 54:
2460 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 206, 110, 280, 142, kItemObsidianBlock, 72, offsetof(GlobalFlags, myAGRetrievedObsidianBlock));
2461 	case 55:
2462 		return new ArrowGodHead(_vm, viewWindow, sceneStaticData, priorLocation, 0,  182, 87, 242, 189, 4, 75, 83, 79, 0, 2, 1, 3);
2463 	case 56:
2464 		return new ArrowGodHead(_vm, viewWindow, sceneStaticData, priorLocation, 1,  194, 89, 256, 189, 10, 76, 84, 80, 4, 6, 5, 7);
2465 	case 57:
2466 		return new ArrowGodHead(_vm, viewWindow, sceneStaticData, priorLocation, 2,  178, 93, 246, 189, 28, 77, 85, 81, 8, 10, 9, 11);
2467 	case 58:
2468 		return new ArrowGodHead(_vm, viewWindow, sceneStaticData, priorLocation, 3,  188, 92, 252, 189, 34, 78, 86, 82, 12, 14, 13, 15);
2469 	case 59:
2470 		return new ArrowGodDepthChange(_vm, viewWindow, sceneStaticData, priorLocation);
2471 	case 60:
2472 		return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 11);
2473 	case 65:
2474 		return new BasicDoor(_vm, viewWindow, sceneStaticData, priorLocation, 90, 15, 346, 189, 2, 6, 0, 0, 1, 1, TRANSITION_WALK, -1, 33, 12, 13);
2475 	case 66:
2476 		return new DeathGodAltar(_vm, viewWindow, sceneStaticData, priorLocation);
2477 	case 67:
2478 		return new DeathGodPuzzleBox(_vm, viewWindow, sceneStaticData, priorLocation);
2479 	case 68:
2480 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 206, 76, 246, 116, kItemEnvironCart, 53, offsetof(GlobalFlags, takenEnvironCart));
2481 	case 69:
2482 		return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 10);
2483 	case 70:
2484 		return new PlayStingers(_vm, viewWindow, sceneStaticData, priorLocation, 128, offsetof(GlobalFlags, myMCStingerID), offsetof(GlobalFlags, myMCStingerChannelID), 11, 14);
2485 	case 71:
2486 		return new DisplayMessageWithEvidenceWhenEnteringNode(_vm, viewWindow, sceneStaticData, priorLocation, MAYAN_EVIDENCE_BROKEN_GLASS_PYRAMID, IDS_MBT_EVIDENCE_PRESENT);
2487 	case 72:
2488 		return new MainCavernGlassCapture(_vm, viewWindow, sceneStaticData, priorLocation);
2489 	case 75:
2490 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 40, 4500, 12, 14);
2491 	case 76:
2492 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 64, 6333, 12);
2493 	case 77:
2494 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 2, 1000, 2);
2495 	case 78:
2496 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 2, 1000, 2, 14);
2497 	case 79:
2498 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 40, 6500, 12);
2499 	case 80:
2500 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 16, 4750, 12);
2501 	case 81:
2502 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 30, 7750, 6);
2503 	case 82:
2504 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 16, 2250, 18);
2505 	case 83:
2506 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 30, 2410, 6);
2507 	case 84:
2508 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 64, 7666, 18);
2509 	case 85:
2510 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 255, 0, -1, 10); // First param has to be wrong
2511 	case 86:
2512 		return new SetVolumeAndFlag(_vm, viewWindow, sceneStaticData, priorLocation, 64, offsetof(GlobalFlags, myWGSeenLowerPassage));
2513 	case 87:
2514 		return new SetVolumeAndFlag(_vm, viewWindow, sceneStaticData, priorLocation, 64, offsetof(GlobalFlags, myWGCrossedRopeBridge));
2515 	case 88:
2516 		return new SetVolumeAndFlag(_vm, viewWindow, sceneStaticData, priorLocation, 64);
2517 	case 90:
2518 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 40, 3160, 12, 14);
2519 	case 91:
2520 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 64, 4160, 12);
2521 	case 92:
2522 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 40, 4160, 12);
2523 	case 93:
2524 		return new WalkVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 16, 3160, 12);
2525 	case 100:
2526 		return new AdjustSecondaryAmbientOnEntry(_vm, viewWindow, sceneStaticData, priorLocation);
2527 	case 101:
2528 		return new WalkDualAmbientVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 16, 32, 6900, 12);
2529 	case 102:
2530 		return new WalkDualAmbientVolumeChange(_vm, viewWindow, sceneStaticData, priorLocation, 64, 128, 6900, 12);
2531 	case 103:
2532 		return new PlaySoundEnteringFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 12, 2, 4, 4, 2, 1, 5);
2533 	case 120:
2534 		return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 10);
2535 	case 121:
2536 		return new PlaySoundExitingFromScene(_vm, viewWindow, sceneStaticData, priorLocation, 14);
2537 	case 125:
2538 		return new GenericItemAcquire(_vm, viewWindow, sceneStaticData, priorLocation, 226, 90, 256, 104, kItemCopperMedallion, 15, offsetof(GlobalFlags, myAGRetrievedCopperMedal));
2539 	case 126:
2540 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDS_MY_AG_ALTAR_TEXT, 120, 44, 330, 72, -1, -1, offsetof(GlobalFlags, myAGVisitedAltar));
2541 	case 127:
2542 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDS_MY_WG_ALTAR_TEXT, 118, 14, 338, 44);
2543 	case 128:
2544 		return new ViewSingleTranslation(_vm, viewWindow, sceneStaticData, priorLocation, IDS_MY_WT_ALTAR_TEXT, 106, 128, 344, 162);
2545 	default:
2546 		warning("Unknown Mayan scene object %d", sceneStaticData.classID);
2547 		break;
2548 	}
2549 
2550 	return new SceneBase(_vm, viewWindow, sceneStaticData, priorLocation);
2551 }
2552 
2553 } // End of namespace Buried
2554