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 ¶m, 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