1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "neverhood/navigationscene.h"
24 #include "neverhood/mouse.h"
25 
26 namespace Neverhood {
27 
28 enum AreaType {
29 	kAreaCanMoveForward = 0,
30 	kAreaCannotMoveForward = 1
31 };
32 
NavigationScene(NeverhoodEngine * vm,Module * parentModule,uint32 navigationListId,int navigationIndex,const byte * itemsTypes)33 NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes)
34 	: Scene(vm, parentModule), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false),
35 	_isWalkingForward(false), _isTurning(false), _smackerFileHash(0), _interactive(true), _leaveSceneAfter(false) {
36 
37 	_navigationList = _vm->_staticData->getNavigationList(navigationListId);
38 	_navigationListId = navigationListId;
39 
40 	if (_navigationIndex < 0) {
41 		_navigationIndex = (int)getGlobalVar(V_NAVIGATION_INDEX);
42 		if (_navigationIndex >= (int)_navigationList->size())
43 			_navigationIndex = 0;
44 	}
45 	setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex);
46 
47 	SetUpdateHandler(&NavigationScene::update);
48 	SetMessageHandler(&NavigationScene::handleMessage);
49 
50 	_smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true));
51 
52 	createMouseCursor();
53 
54 	_vm->_screen->clear();
55 	_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
56 
57 	sendMessage(_parentModule, 0x100A, _navigationIndex);
58 }
59 
~NavigationScene()60 NavigationScene::~NavigationScene() {
61 	_vm->_soundMan->setTwoSoundsPlayFlag(false);
62 	_vm->_soundMan->setSoundThreePlayFlag(false);
63 }
64 
getNavigationAreaType()65 int NavigationScene::getNavigationAreaType() {
66 	NPoint mousePos;
67 	mousePos.x = _mouseCursor->getX();
68 	mousePos.y = _mouseCursor->getY();
69 	return sendPointMessage(_mouseCursor, 0x2064, mousePos);
70 }
71 
update()72 void NavigationScene::update() {
73 	if (_smackerFileHash != 0) {
74 		showMouse(false);
75 		_smackerPlayer->open(_smackerFileHash, false);
76 		_vm->_screen->clear();
77 		_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
78 		_smackerDone = false;
79 		/*
80 		if (!_interactive)
81 			_smackerDone = true;
82 		*/
83 		_smackerFileHash = 0;
84 	} else if (_smackerDone) {
85 		if (_leaveSceneAfter) {
86 			_vm->_screen->setSmackerDecoder(NULL);
87 			sendMessage(_parentModule, 0x1009, _navigationIndex);
88 		} else {
89 			const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
90 			createMouseCursor();
91 			showMouse(true);
92 			_isTurning = false;
93 			_isWalkingForward = false;
94 			_interactive = true;
95 			_vm->_soundMan->setTwoSoundsPlayFlag(false);
96 			_vm->_soundMan->setSoundThreePlayFlag(false);
97 			_smackerDone = false;
98 			_smackerPlayer->open(navigationItem.fileHash, true);
99 			_vm->_screen->clear();
100 			_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
101 			sendMessage(_parentModule, 0x100A, _navigationIndex);
102 		}
103 	}
104 	Scene::update();
105 }
106 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)107 uint32 NavigationScene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
108 	switch (messageNum) {
109 	case NM_MOUSE_MOVE:
110 		if (_interactive)
111 			sendMessage(_mouseCursor, 0x4002, param);
112 		break;
113 	case NM_MOUSE_CLICK:
114 		if (_interactive)
115 			handleNavigation(param.asPoint());
116 		break;
117 	case NM_KEYPRESS_SPACE:
118 		if (!_interactive)
119 			_smackerDone = true;
120 		break;
121 	case NM_ANIMATION_STOP:
122 		_smackerDone = true;
123 		break;
124 	default:
125 		break;
126 	}
127 	return 0;
128 }
129 
createMouseCursor()130 void NavigationScene::createMouseCursor() {
131 	const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
132 	uint32 mouseCursorFileHash;
133 	int areaType;
134 
135 	if (_mouseCursor)
136 		deleteSprite((Sprite**)&_mouseCursor);
137 
138 	mouseCursorFileHash = navigationItem.mouseCursorFileHash;
139 	if (mouseCursorFileHash == 0)
140 		mouseCursorFileHash = 0x63A40028;
141 
142 	if (_itemsTypes)
143 		areaType = _itemsTypes[_navigationIndex];
144 	else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag)
145 		areaType = kAreaCanMoveForward;
146 	else
147 		areaType = kAreaCannotMoveForward;
148 
149 	insertNavigationMouse(mouseCursorFileHash, areaType);
150 	sendPointMessage(_mouseCursor, 0x4002, _vm->getMousePos());
151 }
152 
handleNavigation(const NPoint & mousePos)153 void NavigationScene::handleNavigation(const NPoint &mousePos) {
154 	const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
155 	bool oldIsWalkingForward = _isWalkingForward;
156 	bool oldIsTurning = _isTurning;
157 	uint32 direction = sendPointMessage(_mouseCursor, 0x2064, mousePos);
158 
159 	switch (direction) {
160 	case 0:
161 		if (navigationItem.leftSmackerFileHash != 0) {
162 			_smackerFileHash = navigationItem.leftSmackerFileHash;
163 			_interactive = false;
164 			_isWalkingForward = false;
165 			_isTurning = true;
166 			do {
167 				_navigationIndex--;
168 				if (_navigationIndex < 0)
169 					_navigationIndex = _navigationList->size() - 1;
170 			} while (!(*_navigationList)[_navigationIndex].interactive);
171 			setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex);
172 		} else {
173 			_vm->_screen->setSmackerDecoder(NULL);
174 			sendMessage(_parentModule, 0x1009, _navigationIndex);
175 		}
176 		break;
177 	case 1:
178 		if (navigationItem.rightSmackerFileHash != 0) {
179 			_smackerFileHash = navigationItem.rightSmackerFileHash;
180 			_interactive = false;
181 			_isWalkingForward = false;
182 			_isTurning = true;
183 			do {
184 				_navigationIndex++;
185 				if (_navigationIndex >= (int)_navigationList->size())
186 					_navigationIndex = 0;
187 			} while (!(*_navigationList)[_navigationIndex].interactive);
188 			setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex);
189 		} else {
190 			_vm->_screen->setSmackerDecoder(NULL);
191 			sendMessage(_parentModule, 0x1009, _navigationIndex);
192 		}
193 		break;
194 	case 2:
195 	case 3:
196 	case 4:
197 		if (navigationItem.middleFlag) {
198 			_vm->_screen->setSmackerDecoder(NULL);
199 			sendMessage(_parentModule, 0x1009, _navigationIndex);
200 		} else if (navigationItem.middleSmackerFileHash != 0) {
201 			_smackerFileHash = navigationItem.middleSmackerFileHash;
202 			_interactive = false;
203 			_isWalkingForward = true;
204 			_isTurning = false;
205 			_leaveSceneAfter = true;
206 		}
207 		break;
208 	default:
209 		break;
210 	}
211 
212 	if (oldIsTurning != _isTurning)
213 		_vm->_soundMan->setSoundThreePlayFlag(_isTurning);
214 
215 	if (oldIsWalkingForward != _isWalkingForward)
216 		_vm->_soundMan->setTwoSoundsPlayFlag(_isWalkingForward);
217 }
218 
219 } // End of namespace Neverhood
220