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/modules/module2100_sprites.h"
24
25 namespace Neverhood {
26
AsScene2101Door(NeverhoodEngine * vm,bool isOpen)27 AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen)
28 : AnimatedSprite(vm, 1100) {
29
30 createSurface(100, 328, 347);
31 _x = 320;
32 _y = 240;
33 SetUpdateHandler(&AnimatedSprite::update);
34 SetMessageHandler(&AsScene2101Door::handleMessage);
35 if (isOpen) {
36 startAnimation(0x0C202B9C, -1, -1);
37 _newStickFrameIndex = STICK_LAST_FRAME;
38 } else
39 setVisible(false);
40 }
41
handleMessage(int messageNum,const MessageParam & param,Entity * sender)42 uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
43 uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
44 switch (messageNum) {
45 case NM_ANIMATION_STOP:
46 gotoNextState();
47 break;
48 case NM_KLAYMEN_OPEN_DOOR:
49 stOpenDoor();
50 break;
51 case NM_KLAYMEN_CLOSE_DOOR:
52 stCloseDoor();
53 break;
54 default:
55 break;
56 }
57 return messageResult;
58 }
59
stOpenDoor()60 void AsScene2101Door::stOpenDoor() {
61 startAnimation(0x0C202B9C, 0, -1);
62 _newStickFrameIndex = STICK_LAST_FRAME;
63 setVisible(true);
64 playSound(0, calcHash("fxDoorOpen32"));
65 }
66
stCloseDoor()67 void AsScene2101Door::stCloseDoor() {
68 startAnimation(0xC222A8D4, 0, -1);
69 _newStickFrameIndex = STICK_LAST_FRAME;
70 setVisible(true);
71 playSound(0, calcHash("fxDoorClose32"));
72 NextState(&AsScene2101Door::stCloseDoorDone);
73 }
74
stCloseDoorDone()75 void AsScene2101Door::stCloseDoorDone() {
76 stopAnimation();
77 setVisible(false);
78 }
79
AsScene2101HitByDoorEffect(NeverhoodEngine * vm,Sprite * klaymen)80 AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
81 : AnimatedSprite(vm, 1400), _klaymen(klaymen) {
82
83 SetUpdateHandler(&AnimatedSprite::update);
84 SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
85 createSurface(1200, 88, 165);
86 setVisible(false);
87 }
88
handleMessage(int messageNum,const MessageParam & param,Entity * sender)89 uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
90 uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
91 switch (messageNum) {
92 case 0x2001:
93 _x = _klaymen->getX();
94 _y = _klaymen->getY() - 132;
95 startAnimation(0x0422255A, 0, -1);
96 setVisible(true);
97 break;
98 case NM_ANIMATION_STOP:
99 stopAnimation();
100 setVisible(false);
101 break;
102 default:
103 break;
104 }
105 return messageResult;
106 }
107
SsCommonFloorButton(NeverhoodEngine * vm,Scene * parentScene,uint32 fileHash1,uint32 fileHash2,int surfacePriority,uint32 soundFileHash)108 SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
109 : StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0),
110 _fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) {
111
112 SetUpdateHandler(&SsCommonFloorButton::update);
113 SetMessageHandler(&SsCommonFloorButton::handleMessage);
114 if (_soundFileHash == 0)
115 _soundFileHash = 0x44141000;
116 createSurface(1010, 61, 30);
117 if (_fileHash1)
118 loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
119 else
120 setVisible(false);
121 }
122
update()123 void SsCommonFloorButton::update() {
124 if (_countdown != 0 && (--_countdown == 0)) {
125 sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
126 if (_fileHash1)
127 loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
128 else
129 setVisible(false);
130 }
131 }
132
handleMessage(int messageNum,const MessageParam & param,Entity * sender)133 uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
134 uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
135 switch (messageNum) {
136 case 0x480B:
137 sendMessage(_parentScene, 0x480B, 0);
138 setVisible(true);
139 sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
140 loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition);
141 _countdown = 16;
142 playSound(0, _soundFileHash);
143 break;
144 default:
145 break;
146 }
147 return messageResult;
148 }
149
KmScene2101(NeverhoodEngine * vm,Scene * parentScene,int16 x,int16 y)150 KmScene2101::KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
151 : Klaymen(vm, parentScene, x, y) {
152
153 // Empty
154 }
155
xHandleMessage(int messageNum,const MessageParam & param)156 uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam ¶m) {
157 uint32 messageResult = 0;
158 switch (messageNum) {
159 case NM_ANIMATION_UPDATE:
160 _isSittingInTeleporter = param.asInteger() != 0;
161 messageResult = 1;
162 break;
163 case 0x4001:
164 case 0x4800:
165 startWalkToX(param.asPoint().x, false);
166 break;
167 case NM_KLAYMEN_STAND_IDLE:
168 if (_isSittingInTeleporter)
169 GotoState(&Klaymen::stSitIdleTeleporter);
170 else
171 GotoState(&Klaymen::stTryStandIdle);
172 break;
173 case 0x4811:
174 GotoState(&KmScene2101::stHitByDoor);
175 break;
176 case NM_KLAYMEN_PICKUP:
177 if (param.asInteger() == 2)
178 GotoState(&Klaymen::stPickUpNeedle);
179 else if (param.asInteger() == 1)
180 GotoState(&Klaymen::stPickUpTube);
181 else
182 GotoState(&Klaymen::stPickUpGeneric);
183 break;
184 case NM_KLAYMEN_PRESS_BUTTON:
185 if (param.asInteger() == 1)
186 GotoState(&Klaymen::stPressButton);
187 else if (param.asInteger() == 2)
188 GotoState(&Klaymen::stPressFloorButton);
189 else
190 GotoState(&Klaymen::stPressButtonSide);
191 break;
192 case 0x4817:
193 setDoDeltaX(param.asInteger());
194 gotoNextStateExt();
195 break;
196 case 0x481B:
197 if (param.asPoint().y != 0)
198 startWalkToXDistance(param.asPoint().y, param.asPoint().x);
199 else
200 startWalkToAttachedSpriteXDistance(param.asPoint().x);
201 break;
202 case NM_KLAYMEN_TURN_TO_USE:
203 if (_isSittingInTeleporter)
204 GotoState(&Klaymen::stTurnToUseInTeleporter);
205 break;
206 case NM_KLAYMEN_RETURN_FROM_USE:
207 if (_isSittingInTeleporter)
208 GotoState(&Klaymen::stReturnFromUseInTeleporter);
209 break;
210 case 0x4834:
211 GotoState(&Klaymen::stStepOver);
212 break;
213 case 0x4835:
214 sendMessage(_parentScene, 0x2000, 1);
215 _isSittingInTeleporter = true;
216 GotoState(&Klaymen::stSitInTeleporter);
217 break;
218 case 0x4836:
219 sendMessage(_parentScene, 0x2000, 0);
220 _isSittingInTeleporter = false;
221 GotoState(&Klaymen::stGetUpFromTeleporter);
222 break;
223 case 0x483D:
224 teleporterAppear(0xFF290E30);
225 break;
226 case 0x483E:
227 teleporterDisappear(0x9A28CA1C);
228 break;
229 default:
230 break;
231 }
232 return messageResult;
233 }
234
hmHitByDoor(int messageNum,const MessageParam & param,Entity * sender)235 uint32 KmScene2101::hmHitByDoor(int messageNum, const MessageParam ¶m, Entity *sender) {
236 uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
237 int16 speedUpFrameIndex;
238 switch (messageNum) {
239 case 0x1008:
240 speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
241 if (_currFrameIndex < speedUpFrameIndex) {
242 startAnimation(0x35AA8059, speedUpFrameIndex, -1);
243 _y = 438;
244 }
245 messageResult = 0;
246 break;
247 case NM_ANIMATION_START:
248 if (param.asInteger() == 0x1A1A0785) {
249 playSound(0, 0x40F0A342);
250 } else if (param.asInteger() == 0x60428026) {
251 playSound(0, 0x40608A59);
252 }
253 break;
254 default:
255 break;
256 }
257 return messageResult;
258 }
259
stHitByDoor()260 void KmScene2101::stHitByDoor() {
261 _busyStatus = 1;
262 _acceptInput = false;
263 startAnimation(0x35AA8059, 0, -1);
264 SetUpdateHandler(&Klaymen::update);
265 SetMessageHandler(&KmScene2101::hmHitByDoor);
266 SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
267 playSound(0, 0x402E82D4);
268 }
269
270 } // End of namespace Neverhood
271