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 "common/random.h"
24
25 #include "hdb/hdb.h"
26 #include "hdb/ai.h"
27 #include "hdb/ai-player.h"
28 #include "hdb/file-manager.h"
29 #include "hdb/gfx.h"
30 #include "hdb/sound.h"
31 #include "hdb/menu.h"
32 #include "hdb/lua-script.h"
33 #include "hdb/map.h"
34 #include "hdb/mpc.h"
35 #include "hdb/window.h"
36
37 namespace HDB {
38
aiPlayerInit(AIEntity * e)39 void aiPlayerInit(AIEntity *e) {
40 g_hdb->_ai->clearInventory();
41 e->aiAction = aiPlayerAction;
42 e->draw = g_hdb->_ai->getStandFrameDir(e);
43
44 switch (e->dir) {
45 case DIR_UP:
46 e->state = STATE_STANDUP;
47 break;
48 case DIR_DOWN:
49 e->state = STATE_STANDDOWN;
50 break;
51 case DIR_LEFT:
52 e->state = STATE_STANDLEFT;
53 break;
54 case DIR_RIGHT:
55 e->state = STATE_STANDRIGHT;
56 break;
57 case DIR_NONE:
58 break;
59 }
60
61 e->moveSpeed = kPlayerMoveSpeed;
62 strcpy(e->entityName, "player");
63 g_hdb->_ai->assignPlayer(e);
64 }
65
aiPlayerInit2(AIEntity * e)66 void aiPlayerInit2(AIEntity *e) {
67 if (!g_hdb->_ai->_clubUpGfx[0]) {
68 g_hdb->_ai->_weaponSelGfx = g_hdb->_gfx->loadTile(TILE_WEAPON_EQUIPPED);
69 g_hdb->_ai->_clubUpGfx[0] = g_hdb->_gfx->getPicGfx(CLUBUP1, -1);
70 g_hdb->_ai->_clubUpGfx[1] = g_hdb->_gfx->getPicGfx(CLUBUP2, -1);
71 g_hdb->_ai->_clubUpGfx[2] = g_hdb->_gfx->getPicGfx(CLUBUP3, -1);
72 g_hdb->_ai->_clubUpGfx[3] = g_hdb->_gfx->getPicGfx(CLUBUP3, -1);
73
74 g_hdb->_ai->_clubDownGfx[0] = g_hdb->_gfx->getPicGfx(CLUBDOWN1, -1);
75 g_hdb->_ai->_clubDownGfx[1] = g_hdb->_gfx->getPicGfx(CLUBDOWN2, -1);
76 g_hdb->_ai->_clubDownGfx[2] = g_hdb->_gfx->getPicGfx(CLUBDOWN3, -1);
77 g_hdb->_ai->_clubDownGfx[3] = g_hdb->_gfx->getPicGfx(CLUBDOWN3, -1);
78
79 g_hdb->_ai->_clubLeftGfx[0] = g_hdb->_gfx->getPicGfx(CLUBLEFT1, -1);
80 g_hdb->_ai->_clubLeftGfx[1] = g_hdb->_gfx->getPicGfx(CLUBLEFT2, -1);
81 g_hdb->_ai->_clubLeftGfx[2] = g_hdb->_gfx->getPicGfx(CLUBLEFT3, -1);
82 g_hdb->_ai->_clubLeftGfx[3] = g_hdb->_gfx->getPicGfx(CLUBLEFT3, -1);
83
84 g_hdb->_ai->_clubRightGfx[0] = g_hdb->_gfx->getPicGfx(CLUBRIGHT1, -1);
85 g_hdb->_ai->_clubRightGfx[1] = g_hdb->_gfx->getPicGfx(CLUBRIGHT2, -1);
86 g_hdb->_ai->_clubRightGfx[2] = g_hdb->_gfx->getPicGfx(CLUBRIGHT3, -1);
87 g_hdb->_ai->_clubRightGfx[3] = g_hdb->_gfx->getPicGfx(CLUBRIGHT3, -1);
88
89 g_hdb->_ai->_clubUpFrames = g_hdb->_ai->_clubDownFrames =
90 g_hdb->_ai->_clubLeftFrames = g_hdb->_ai->_clubRightFrames = 4;
91
92 g_hdb->_ai->_slugAttackGfx[0] = g_hdb->_gfx->loadPic(SLUG_SHOT1);
93 g_hdb->_ai->_slugAttackGfx[1] = g_hdb->_gfx->loadPic(SLUG_SHOT2);
94 g_hdb->_ai->_slugAttackGfx[2] = g_hdb->_gfx->loadPic(SLUG_SHOT3);
95 g_hdb->_ai->_slugAttackGfx[3] = g_hdb->_gfx->loadPic(SLUG_SHOT4);
96
97 int32 size = g_hdb->_fileMan->getLength("shock_spark_sit01", TYPE_TILE32);
98 g_hdb->_ai->_stunLightningGfx[0] = g_hdb->_gfx->getTileGfx("shock_spark_sit01", size);
99 size = g_hdb->_fileMan->getLength("shock_spark_sit02", TYPE_TILE32);
100 g_hdb->_ai->_stunLightningGfx[1] = g_hdb->_gfx->getTileGfx("shock_spark_sit02", size);
101 size = g_hdb->_fileMan->getLength("shock_spark_sit03", TYPE_TILE32);
102 g_hdb->_ai->_stunLightningGfx[2] = g_hdb->_gfx->getTileGfx("shock_spark_sit03", size);
103 size = g_hdb->_fileMan->getLength("shock_spark_sit04", TYPE_TILE32);
104 g_hdb->_ai->_stunLightningGfx[3] = g_hdb->_gfx->getTileGfx("shock_spark_sit04", size);
105
106 size = g_hdb->_fileMan->getLength("starstun_sit01", TYPE_TILE32);
107 g_hdb->_ai->_stunnedGfx[0] = g_hdb->_gfx->getTileGfx("starstun_sit01", size);
108 size = g_hdb->_fileMan->getLength("starstun_sit02", TYPE_TILE32);
109 g_hdb->_ai->_stunnedGfx[1] = g_hdb->_gfx->getTileGfx("starstun_sit02", size);
110 size = g_hdb->_fileMan->getLength("starstun_sit03", TYPE_TILE32);
111 g_hdb->_ai->_stunnedGfx[2] = g_hdb->_gfx->getTileGfx("starstun_sit03", size);
112 size = g_hdb->_fileMan->getLength("starstun_sit04", TYPE_TILE32);
113 g_hdb->_ai->_stunnedGfx[3] = g_hdb->_gfx->getTileGfx("starstun_sit04", size);
114 }
115
116 e->draw = g_hdb->_ai->getStandFrameDir(e);
117 }
118
aiPlayerAction(AIEntity * e)119 void aiPlayerAction(AIEntity *e) {
120 static const AIState stand[5] = {STATE_NONE, STATE_STANDUP, STATE_STANDDOWN, STATE_STANDLEFT, STATE_STANDRIGHT};
121 static const int xvAhead[5] = {9, 0, 0, -1, 1};
122 static const int yvAhead[5] = {9, -1, 1, 0, 0};
123
124 AIEntity *hit = NULL;
125
126 // Draw the STUN lightning if it exists
127 if (e->sequence) {
128 e->aiDraw = aiPlayerDraw;
129 g_hdb->_sound->playSound(SND_STUNNER_FIRE);
130 hit = g_hdb->_ai->findEntity(e->tileX + xvAhead[e->dir], e->tileY + yvAhead[e->dir]);
131 if (hit)
132 switch (hit->type) {
133 case AI_MEERKAT:
134 if (hit->sequence > 2)
135 g_hdb->_ai->stunEnemy(hit, 8);
136 break;
137 case AI_ICEPUFF:
138 if (hit->state == STATE_ICEP_APPEAR || hit->state == STATE_ICEP_THROWDOWN || hit->state == STATE_ICEP_THROWLEFT || hit->state == STATE_ICEP_THROWRIGHT) {
139 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
140 g_hdb->_ai->stunEnemy(hit, 8);
141 }
142 break;
143 case AI_BADFAIRY:
144 case AI_GOODFAIRY:
145 case AI_CHICKEN:
146 case AI_OMNIBOT:
147 case AI_TURNBOT:
148 case AI_PUSHBOT:
149 case AI_DEADEYE:
150 case AI_FATFROG:
151 case AI_BUZZFLY:
152 case AI_MAINTBOT:
153 case AI_RIGHTBOT:
154 case AI_GATEPUDDLE:
155 g_hdb->_ai->stunEnemy(hit, 8);
156 break;
157 default:
158 break;
159 }
160
161 hit = g_hdb->_ai->findEntity(e->tileX + (xvAhead[e->dir] << 1), e->tileY + (yvAhead[e->dir] << 1));
162 if (hit)
163 switch (hit->type) {
164 case AI_MEERKAT:
165 if (hit->sequence > 2)
166 g_hdb->_ai->stunEnemy(hit, 8);
167 break;
168 case AI_ICEPUFF:
169 if (hit->state == STATE_ICEP_APPEAR || hit->state == STATE_ICEP_THROWDOWN || hit->state == STATE_ICEP_THROWLEFT || hit->state == STATE_ICEP_THROWRIGHT) {
170 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
171 g_hdb->_ai->stunEnemy(hit, 8);
172 }
173 break;
174 case AI_BADFAIRY:
175 case AI_GOODFAIRY:
176 case AI_CHICKEN:
177 case AI_OMNIBOT:
178 case AI_TURNBOT:
179 case AI_PUSHBOT:
180 case AI_DEADEYE:
181 case AI_FATFROG:
182 case AI_BUZZFLY:
183 case AI_MAINTBOT:
184 case AI_RIGHTBOT:
185 case AI_GATEPUDDLE:
186 g_hdb->_ai->stunEnemy(hit, 8);
187 break;
188 default:
189 break;
190 }
191 }
192
193 int xOff[] = {0, 0, -8,-16};
194 int yOff[] = {-8,-24,-16,-16};
195 // If the player is supposed to animate for abit, check for it here
196 switch (e->state) {
197 case STATE_GRABUP:
198 case STATE_GRABDOWN:
199 case STATE_GRABLEFT:
200 case STATE_GRABRIGHT:
201 if (!e->animFrame--) {
202 // Done with the Grabbing Animation, switch to standing
203 switch (e->state) {
204 case STATE_GRABUP:
205 e->draw = e->standupGfx[0];
206 e->state = STATE_STANDUP;
207 break;
208 case STATE_GRABDOWN:
209 e->draw = e->standdownGfx[0];
210 e->state = STATE_STANDDOWN;
211 break;
212 case STATE_GRABLEFT:
213 e->draw = e->standleftGfx[0];
214 e->state = STATE_STANDLEFT;
215 break;
216 case STATE_GRABRIGHT:
217 e->draw = e->standrightGfx[0];
218 e->state = STATE_STANDRIGHT;
219 break;
220 default:
221 break;
222 }
223 e->animDelay = 1;
224 e->animCycle = 1;
225 }
226 break;
227 case STATE_ATK_CLUB_UP:
228 case STATE_ATK_CLUB_DOWN:
229 case STATE_ATK_CLUB_LEFT:
230 case STATE_ATK_CLUB_RIGHT:
231 g_hdb->_ai->setPlayerInvisible(true);
232 e->aiDraw = aiPlayerDraw;
233 e->drawXOff = xOff[e->state - STATE_ATK_CLUB_UP];
234 e->drawYOff = yOff[e->state - STATE_ATK_CLUB_UP];
235 switch (e->state) {
236 case STATE_ATK_CLUB_UP:
237 cycleFrames(e, g_hdb->_ai->_clubUpFrames);
238 break;
239 case STATE_ATK_CLUB_DOWN:
240 cycleFrames(e, g_hdb->_ai->_clubDownFrames);
241 break;
242 case STATE_ATK_CLUB_LEFT:
243 cycleFrames(e, g_hdb->_ai->_clubLeftFrames);
244 break;
245 case STATE_ATK_CLUB_RIGHT:
246 cycleFrames(e, g_hdb->_ai->_clubRightFrames);
247 break;
248 default:
249 break;
250 }
251 // Whack!
252 if ((e->animFrame >= 1) && (e->animDelay == e->animCycle)) {
253 switch (e->dir) {
254 case DIR_UP:
255 hit = g_hdb->_ai->playerCollision(32, 0, 16, 16);
256 break;
257 case DIR_DOWN:
258 hit = g_hdb->_ai->playerCollision(0, 32, 16, 16);
259 break;
260 case DIR_LEFT:
261 hit = g_hdb->_ai->playerCollision(16, 16, 32, 0);
262 break;
263 case DIR_RIGHT:
264 hit = g_hdb->_ai->playerCollision(16, 16, 0, 32);
265 break;
266 default:
267 break;
268 }
269
270 if (hit && hit->level == e->level && !hit->stunnedWait) {
271 switch (hit->type) {
272 case AI_MEERKAT:
273 if (hit->sequence > 2) // out of the ground?
274 g_hdb->_ai->stunEnemy(hit, 2);
275 break;
276 case AI_ICEPUFF:
277 if (hit->state == STATE_ICEP_APPEAR ||
278 hit->state == STATE_ICEP_THROWDOWN ||
279 hit->state == STATE_ICEP_THROWLEFT ||
280 hit->state == STATE_ICEP_THROWRIGHT)
281 g_hdb->_ai->stunEnemy(hit, 2);
282 break;
283 case AI_CHICKEN:
284 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
285 g_hdb->_ai->removeEntity(hit);
286 break;
287 case AI_BADFAIRY:
288 case AI_GOODFAIRY:
289 case AI_OMNIBOT:
290 case AI_TURNBOT:
291 case AI_PUSHBOT:
292 case AI_DEADEYE:
293 case AI_FATFROG:
294 case AI_BUZZFLY:
295 case AI_MAINTBOT:
296 case AI_RIGHTBOT:
297 case AI_SHOCKBOT:
298 case AI_GATEPUDDLE:
299 g_hdb->_ai->stunEnemy(hit, 2);
300 g_hdb->_sound->playSound(g_hdb->_ai->metalOrFleshSND(hit));
301 break;
302 default:
303 break;
304 }
305 }
306 }
307 if ((!e->animFrame) && (e->animDelay == e->animCycle)) {
308 e->state = stand[e->dir];
309 e->aiDraw = NULL;
310 switch (e->state) {
311 case STATE_ATK_CLUB_UP:
312 e->draw = e->standupGfx[0];
313 break;
314 case STATE_ATK_CLUB_DOWN:
315 e->draw = e->standdownGfx[0];
316 break;
317 case STATE_ATK_CLUB_LEFT:
318 e->draw = e->standleftGfx[0];
319 break;
320 case STATE_ATK_CLUB_RIGHT:
321 e->draw = e->standrightGfx[0];
322 break;
323 default:
324 break;
325 }
326 g_hdb->_ai->setPlayerInvisible(false);
327 e->drawXOff = e->drawYOff = 0;
328 }
329 return;
330 case STATE_ATK_STUN_UP:
331 e->draw = g_hdb->_ai->_stunUpGfx[e->animFrame];
332 cycleFrames(e, g_hdb->_ai->_stunUpFrames);
333 if (!e->animFrame && e->animDelay == e->animCycle) {
334 e->state = stand[e->dir];
335 e->aiDraw = NULL;
336 e->sequence = 0;
337 }
338 return;
339 case STATE_ATK_STUN_DOWN:
340 e->draw = g_hdb->_ai->_stunDownGfx[e->animFrame];
341 cycleFrames(e, g_hdb->_ai->_stunDownFrames);
342 if (!e->animFrame && e->animDelay == e->animCycle) {
343 e->state = stand[e->dir];
344 e->aiDraw = NULL;
345 e->sequence = 0;
346 }
347 return;
348 case STATE_ATK_STUN_LEFT:
349 e->draw = g_hdb->_ai->_stunLeftGfx[e->animFrame];
350 cycleFrames(e, g_hdb->_ai->_stunLeftFrames);
351 if (!e->animFrame && e->animDelay == e->animCycle) {
352 e->state = stand[e->dir];
353 e->aiDraw = NULL;
354 e->sequence = 0;
355 }
356 return;
357 case STATE_ATK_STUN_RIGHT:
358 e->draw = g_hdb->_ai->_stunRightGfx[e->animFrame];
359 cycleFrames(e, g_hdb->_ai->_stunRightFrames);
360 if (!e->animFrame && e->animDelay == e->animCycle) {
361 e->state = stand[e->dir];
362 e->aiDraw = NULL;
363 e->sequence = 0;
364 }
365 return;
366 case STATE_ATK_SLUG_UP:
367 e->draw = g_hdb->_ai->_slugUpGfx[e->animFrame];
368 cycleFrames(e, g_hdb->_ai->_slugUpFrames);
369 if (!e->animFrame && e->animDelay == e->animCycle) {
370 e->state = stand[e->dir];
371 e->sequence = 0;
372 }
373 return;
374 case STATE_ATK_SLUG_DOWN:
375 e->draw = g_hdb->_ai->_slugDownGfx[e->animFrame];
376 cycleFrames(e, g_hdb->_ai->_slugDownFrames);
377 if (!e->animFrame && e->animDelay == e->animCycle) {
378 e->state = stand[e->dir];
379 e->sequence = 0;
380 }
381 return;
382 case STATE_ATK_SLUG_LEFT:
383 e->draw = g_hdb->_ai->_slugLeftGfx[e->animFrame];
384 cycleFrames(e, g_hdb->_ai->_slugLeftFrames);
385 if (!e->animFrame && e->animDelay == e->animCycle) {
386 e->state = stand[e->dir];
387 e->sequence = 0;
388 }
389 return;
390 case STATE_ATK_SLUG_RIGHT:
391 e->draw = g_hdb->_ai->_slugRightGfx[e->animFrame];
392 cycleFrames(e, g_hdb->_ai->_slugRightFrames);
393 if (!e->animFrame && e->animDelay == e->animCycle) {
394 e->state = stand[e->dir];
395 e->sequence = 0;
396 }
397 return;
398 default:
399 break;
400 }
401
402 // If the touchplate wait is on, keep it timing
403 if (e->touchpWait) {
404 e->touchpWait--;
405 if (!e->touchpWait)
406 e->touchpTile = -e->touchpTile;
407 } else if (e->touchpTile < 0 && (e->touchpX != e->tileX || e->touchpY != e->tileY)) {
408 g_hdb->_ai->checkActionList(e, e->touchpX, e->touchpY, false);
409 g_hdb->_map->setMapBGTileIndex(e->touchpX, e->touchpY, -e->touchpTile);
410 e->touchpX = e->touchpY = e->touchpTile = 0;
411 }
412
413 // If the player is moving somewhere, animate him
414 int bgFlags, fgFlags;
415 if (e->goalX) {
416 if (onEvenTile(e->x, e->y)) {
417 g_hdb->_ai->playerOnIce() ? g_hdb->_sound->playSound(SND_STEPS_ICE) : g_hdb->_sound->playSound(SND_FOOTSTEPS);
418
419 // Did we just fall down a PLUMMET?
420 bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
421 fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
422 if ((bgFlags & kFlagPlummet) && !(fgFlags & kFlagGrating) && !g_hdb->_ai->playerDead()) {
423 g_hdb->_ai->killPlayer(DEATH_PLUMMET);
424 g_hdb->_ai->animEntFrames(e);
425 return;
426 }
427 }
428 g_hdb->_ai->animateEntity(e);
429 } else {
430 // Sometimes the fading stays black
431 if (!g_hdb->_ai->cinematicsActive() && g_hdb->_gfx->isFadeStaying())
432 g_hdb->_gfx->turnOffFade();
433
434 // Did we just fall down a PLUMMET?
435 bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
436 fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
437 if ((bgFlags & kFlagPlummet) && !(fgFlags & kFlagGrating) && !g_hdb->_ai->playerDead()) {
438 g_hdb->_ai->killPlayer(DEATH_PLUMMET);
439 g_hdb->_ai->animEntFrames(e);
440 return;
441 }
442
443 // Standing on a TouchPlate will activate something WHILE standing on it
444 int bgTile = g_hdb->_ai->checkForTouchplate(e->tileX, e->tileY);
445 if (bgTile && !e->touchpWait && !e->touchpTile) {
446 if (g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false)) {
447 e->touchpTile = bgTile;
448 e->touchpX = e->tileX;
449 e->touchpY = e->tileY;
450 e->touchpWait = kPlayerTouchPWait;
451 g_hdb->_ai->stopEntity(e);
452 }
453 }
454 g_hdb->_ai->animEntFrames(e);
455 }
456 }
457
aiPlayerDraw(AIEntity * e,int mx,int my)458 void aiPlayerDraw(AIEntity *e, int mx, int my) {
459 switch (e->state) {
460 case STATE_ATK_CLUB_UP:
461 g_hdb->_ai->_clubUpGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
462 break;
463 case STATE_ATK_CLUB_DOWN:
464 g_hdb->_ai->_clubDownGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
465 break;
466 case STATE_ATK_CLUB_LEFT:
467 g_hdb->_ai->_clubLeftGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
468 break;
469 case STATE_ATK_CLUB_RIGHT:
470 g_hdb->_ai->_clubRightGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
471 break;
472 default:
473 break;
474 }
475
476 if (e->sequence) {
477 static int frame = 0;
478 switch (e->dir) {
479 case DIR_UP:
480 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y - 32 - my);
481 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y - 64 - my);
482 break;
483 case DIR_DOWN:
484 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y + 32 - my);
485 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y + 64 - my);
486 break;
487 case DIR_LEFT:
488 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - 32 - mx, e->y - my);
489 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - 64 - mx, e->y - my);
490 break;
491 case DIR_RIGHT:
492 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x + 32 - mx, e->y - my);
493 g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x + 64 - mx, e->y - my);
494 break;
495 case DIR_NONE:
496 break;
497 }
498
499 frame = (frame + 1) & 3;
500 }
501 }
502
aiGemAttackInit(AIEntity * e)503 void aiGemAttackInit(AIEntity *e) {
504 static const int xv[5] = {9, 0, 0, -1, 1};
505 static const int yv[5] = {9, -1, 1, 0, 0};
506
507 e->moveSpeed = kPlayerMoveSpeed << 1;
508 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
509 e->state = STATE_MOVEDOWN; // so it will draw & animate
510 e->sequence = 0; // flying out at something
511 e->aiAction = aiGemAttackAction;
512 e->draw = e->movedownGfx[0];
513 g_hdb->_sound->playSound(SND_GEM_THROW);
514 }
515
aiGemAttackAction(AIEntity * e)516 void aiGemAttackAction(AIEntity *e) {
517 static const int xv[5] = {9, 0, 0, -1, 1};
518 static const int yv[5] = {9, -1, 1, 0, 0};
519
520 switch (e->sequence) {
521 // flying out at something
522 case 0:
523 if (e->goalX)
524 g_hdb->_ai->animateEntity(e);
525 else {
526 g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false);
527 g_hdb->_ai->checkAutoList(e, e->tileX, e->tileY);
528
529 AIEntity *hit = g_hdb->_ai->findEntityIgnore(e->tileX, e->tileY, e);
530 uint32 bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
531 uint32 fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
532 int result = (e->level == 1 ? (bgFlags & (kFlagSolid)) : !(fgFlags & kFlagGrating) && (bgFlags & (kFlagSolid)));
533 if (hit) {
534 switch (hit->type) {
535 case AI_CHICKEN:
536 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
537 g_hdb->_ai->removeEntity(hit);
538 g_hdb->_sound->playSound(SND_CHICKEN_BAGAWK);
539 break;
540 case AI_BADFAIRY:
541 g_hdb->_ai->stunEnemy(hit, 2);
542 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
543 break;
544 case AI_NONE:
545 if (hit->value1 == (int)AI_DRAGON) {
546 // pull dragon's coords out of "lua_func_use" string.
547 char num1[4], num2[4];
548 memset(num1, 0, 4);
549 memset(num2, 0, 4);
550 memcpy(num1, hit->luaFuncUse, 3);
551 memcpy(num2, hit->luaFuncUse + 3, 3);
552
553 g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
554 AIEntity *found = g_hdb->_ai->findEntity(atoi(num1), atoi(num2));
555 if (found)
556 aiDragonWake(found);
557 }
558 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
559 g_hdb->_sound->playSound(SND_INV_SELECT);
560 break;
561 case AI_DRAGON:
562 g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
563 aiDragonWake(hit);
564 // fallthrough
565 default:
566 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
567 g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
568 }
569 if (e->value1)
570 e->sequence = 1;
571 else
572 g_hdb->_ai->removeEntity(e); // bye bye!
573 return;
574 } else if (result) { // hit a wall
575 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
576 g_hdb->_sound->playSound(SND_INV_SELECT);
577 // come back to daddy?
578 if (e->value1)
579 e->sequence = 1;
580 else {
581 g_hdb->_ai->removeEntity(e);
582 return;
583 }
584 } else {
585 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
586 e->state = STATE_MOVEDOWN; // so it will draw & animate
587 }
588 g_hdb->_ai->animateEntity(e);
589 }
590 break;
591 // coming back to daddy?
592 case 1:
593 AIEntity *p = g_hdb->_ai->getPlayer();
594 if (e->x < p->x)
595 e->x++;
596 else
597 e->x--;
598
599 if (e->y < p->y)
600 e->y++;
601 else
602 e->y--;
603
604 if (abs(e->x - p->x) < 4 && abs(e->y - p->y) < 4)
605 {
606 int amt = g_hdb->_ai->getGemAmount();
607 g_hdb->_ai->setGemAmount(amt + 1);
608 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
609 g_hdb->_ai->removeEntity(e);
610 g_hdb->_sound->playSound(SND_GET_GEM);
611 }
612 break;
613 }
614 }
615
aiChickenAction(AIEntity * e)616 void aiChickenAction(AIEntity *e) {
617 static int delay = 64;
618
619 if (g_hdb->_map->checkEntOnScreen(e) && !delay) {
620 g_hdb->_sound->playSound(SND_CHICKEN_AMBIENT);
621 delay = g_hdb->_rnd->getRandomNumber(127) + 160;
622 aiChickenUse(e);
623 }
624
625 if (delay)
626 delay--;
627
628 if (e->goalX)
629 g_hdb->_ai->animateEntity(e);
630 else
631 g_hdb->_ai->animEntFrames(e);
632 }
633
aiChickenUse(AIEntity * e)634 void aiChickenUse(AIEntity *e) {
635 g_hdb->_sound->playSound(SND_CHICKEN_BAGAWK);
636 }
637
aiChickenInit(AIEntity * e)638 void aiChickenInit(AIEntity *e) {
639 e->aiUse = aiChickenUse;
640 e->aiAction = aiChickenAction;
641 }
642
aiChickenInit2(AIEntity * e)643 void aiChickenInit2(AIEntity *e) {
644 e->draw = e->standdownGfx[0];
645 }
646
aiDollyInit(AIEntity * e)647 void aiDollyInit(AIEntity *e) {
648 e->moveSpeed = kPlayerMoveSpeed >> 1;
649 e->aiAction = aiGenericAction;
650 }
651
aiDollyInit2(AIEntity * e)652 void aiDollyInit2(AIEntity *e) {
653 e->draw = e->movedownGfx[0];
654 }
655
aiSergeantInit(AIEntity * e)656 void aiSergeantInit(AIEntity *e) {
657 e->moveSpeed = kPlayerMoveSpeed >> 1;
658 if (e->value1)
659 e->aiAction = aiSergeantAction;
660 }
661
aiSergeantInit2(AIEntity * e)662 void aiSergeantInit2(AIEntity *e) {
663 e->draw = g_hdb->_ai->getStandFrameDir(e);
664 }
665
aiSergeantAction(AIEntity * e)666 void aiSergeantAction(AIEntity *e) {
667 if (e->goalX) {
668 g_hdb->_sound->playSound(SND_FOOTSTEPS);
669 g_hdb->_ai->animateEntity(e);
670 } else
671 g_hdb->_ai->animEntFrames(e);
672 }
673
aiSpacedudeInit(AIEntity * e)674 void aiSpacedudeInit(AIEntity *e) {
675 e->moveSpeed = kPlayerMoveSpeed >> 1;
676 if (e->value1)
677 e->aiAction = aiGenericAction;
678 }
679
aiSpacedudeInit2(AIEntity * e)680 void aiSpacedudeInit2(AIEntity *e) {
681 e->standdownFrames = 1;
682 e->standdownGfx[0] = e->movedownGfx[0];
683 e->standupFrames = 1;
684 e->standupGfx[0] = e->moveupGfx[0];
685 e->standleftFrames = 1;
686 e->standleftGfx[0] = e->moveleftGfx[0];
687 e->standrightFrames = 1;
688 e->standrightGfx[0] = e->moverightGfx[0];
689 e->draw = g_hdb->_ai->getStandFrameDir(e);
690 }
691
aiCrateAction(AIEntity * e)692 void aiCrateAction(AIEntity *e) {
693 // if crate isn't moving somewhere, don't move it
694 if (!e->goalX) {
695 // crate is stopped in the water... should it continue downstream?
696 // not if it's marked by the Number of the Beast!
697 if (e->state == STATE_FLOATING) {
698 if (e->value1 != 0x666) {
699 int flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
700 if (flags & (kFlagPushRight | kFlagPushLeft | kFlagPushUp | kFlagPushDown)) {
701 g_hdb->_ai->setEntityGoal(e, e->tileX, e->tileY);
702 g_hdb->_ai->animateEntity(e);
703 } else
704 g_hdb->_ai->animEntFrames(e);
705 } else
706 g_hdb->_ai->animEntFrames(e);
707 }
708 return;
709 }
710
711 g_hdb->_ai->animateEntity(e);
712 }
713
aiCrateInit2(AIEntity * e)714 void aiCrateInit2(AIEntity *e) {
715 // point all crate move frames to the standing one
716 e->movedownFrames =
717 e->moveleftFrames =
718 e->moverightFrames =
719 e->moveupFrames = 1;
720
721 e->movedownGfx[0] =
722 e->moveupGfx[0] =
723 e->moveleftGfx[0] =
724 e->moverightGfx[0] = e->standdownGfx[0];
725
726 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
727 }
728
aiCrateInit(AIEntity * e)729 void aiCrateInit(AIEntity *e) {
730 e->moveSpeed = kPushMoveSpeed;
731 e->aiAction = aiCrateAction;
732 e->value1 = 0;
733 }
734
aiBarrelLightAction(AIEntity * e)735 void aiBarrelLightAction(AIEntity *e) {
736 if (!e->goalX) {
737 if (e->state == STATE_FLOATING)
738 g_hdb->_ai->animEntFrames(e);
739 return;
740 }
741
742 g_hdb->_ai->animateEntity(e);
743 }
744
aiBarrelLightInit2(AIEntity * e)745 void aiBarrelLightInit2(AIEntity *e) {
746 // point all light barrel move frames to the standing one
747 e->movedownFrames =
748 e->moveleftFrames =
749 e->moverightFrames =
750 e->moveupFrames = 1;
751
752 e->movedownGfx[0] =
753 e->moveupGfx[0] =
754 e->moveleftGfx[0] =
755 e->moverightGfx[0] = e->standdownGfx[0];
756
757 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
758 }
759
aiBarrelLightInit(AIEntity * e)760 void aiBarrelLightInit(AIEntity *e) {
761 e->moveSpeed = kPushMoveSpeed;
762 e->aiAction = aiBarrelLightAction;
763 }
764
aiBarrelHeavyAction(AIEntity * e)765 void aiBarrelHeavyAction(AIEntity *e) {
766 if (!e->goalX) {
767 if (e->state == STATE_FLOATING)
768 g_hdb->_ai->animEntFrames(e);
769 return;
770 }
771
772 g_hdb->_ai->animateEntity(e);
773 }
774
aiBarrelHeavyInit2(AIEntity * e)775 void aiBarrelHeavyInit2(AIEntity *e) {
776 // point all heavy barrel move frames to the standing one
777 e->movedownFrames =
778 e->moveleftFrames =
779 e->moverightFrames =
780 e->moveupFrames = 1;
781
782 e->movedownGfx[0] =
783 e->moveupGfx[0] =
784 e->moveleftGfx[0] =
785 e->moverightGfx[0] = e->standdownGfx[0];
786
787 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
788 }
789
aiBarrelHeavyInit(AIEntity * e)790 void aiBarrelHeavyInit(AIEntity *e) {
791 e->moveSpeed = kPushMoveSpeed;
792 e->aiAction = aiBarrelHeavyAction;
793 }
794
aiBarrelExplode(AIEntity * e)795 void aiBarrelExplode(AIEntity *e) {
796 e->state = STATE_EXPLODING;
797 e->animDelay = e->animCycle;
798 e->animFrame = 0;
799
800 if (!g_hdb->isDemo())
801 g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
802
803 g_hdb->_map->setBoomBarrel(e->tileX, e->tileY, 0);
804 }
805
aiBarrelExplodeInit(AIEntity * e)806 void aiBarrelExplodeInit(AIEntity *e) {
807 e->moveSpeed = kPushMoveSpeed;
808 e->aiAction = aiBarrelExplodeAction;
809 g_hdb->_map->setBoomBarrel(e->tileX, e->tileY, 1);
810 }
811
aiBarrelExplodeInit2(AIEntity * e)812 void aiBarrelExplodeInit2(AIEntity *e) {
813 // point all exploding barrel MOVE frames to the standing one
814 e->blinkFrames =
815 e->movedownFrames =
816 e->moveleftFrames =
817 e->moverightFrames =
818 e->moveupFrames = 1;
819
820 e->blinkGfx[0] =
821 e->movedownGfx[0] =
822 e->moveupGfx[0] =
823 e->moveleftGfx[0] =
824 e->moverightGfx[0] = e->standdownGfx[0];
825
826 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
827 }
828
aiBarrelExplodeAction(AIEntity * e)829 void aiBarrelExplodeAction(AIEntity *e) {
830 if (e->goalX)
831 g_hdb->_ai->animateEntity(e);
832 else if (e->state == STATE_EXPLODING)
833 g_hdb->_ai->animEntFrames(e);
834 }
835
aiBarrelExplodeSpread(AIEntity * e)836 void aiBarrelExplodeSpread(AIEntity *e) {
837 static const int xv1[4] = {-1, 1, -1, 0};
838 static const int yv1[4] = {-1, -1, 0, -1};
839 static const int xv2[4] = {1, 0, 1, -1};
840 static const int yv2[4] = {0, 1, 1, 1};
841
842 int x = e->tileX;
843 int y = e->tileY;
844 int index = e->animFrame;
845
846 // are we just starting an explosion ring?
847 if (e->animDelay != e->animCycle)
848 return;
849
850 // the animation frame is the index into which set of 2 explosions to spawn
851 int xv = xv1[index];
852 int yv = yv1[index];
853
854 // explosion 1: check to see if we can explode (non-solid tile)
855 // if so, spawn it and mark it in the explosion matrix
856 if (!(g_hdb->_map->getMapBGTileFlags(x + xv, y + yv) & kFlagSolid) && !g_hdb->_map->explosionExist(x + xv, y + yv)) {
857 aiBarrelBlowup(e, x + xv, y + yv);
858 // are we blowing up on another BOOMBARREL? if so, start it exploding.
859 AIEntity *e2 = g_hdb->_ai->findEntity(x + xv, y + yv);
860 if (e2 && e2->state != STATE_EXPLODING) {
861 switch (e2->type) {
862 case AI_GUY:
863 g_hdb->_ai->killPlayer(DEATH_FRIED);
864 break;
865 case AI_BOOMBARREL:
866 aiBarrelExplode(e2);
867 break;
868 case AI_OMNIBOT:
869 case AI_TURNBOT:
870 case AI_SHOCKBOT:
871 case AI_RIGHTBOT:
872 case AI_PUSHBOT:
873 case AI_RAILRIDER:
874 case AI_MAINTBOT:
875 case AI_DEADEYE:
876 case AI_FATFROG:
877 case AI_ICEPUFF:
878 case AI_MEERKAT:
879 case AI_BUZZFLY:
880 case AI_GOODFAIRY:
881 case AI_GATEPUDDLE:
882 case AI_BADFAIRY:
883 g_hdb->_ai->addAnimateTarget(x * kTileWidth,
884 y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
885 if (e2->type != AI_LASERBEAM)
886 g_hdb->_ai->removeEntity(e2);
887 break;
888 default:
889 break;
890 }
891 }
892 }
893
894 xv = xv2[index];
895 yv = yv2[index];
896
897 // explosion 2: check to see if we can explode (non-solid tile)
898 // if so, spawn it and mark it in the explosion matrix
899
900 if (!(g_hdb->_map->getMapBGTileFlags(x + xv, y + yv) & kFlagSolid) && !g_hdb->_map->explosionExist(x + xv, y + yv)) {
901 aiBarrelBlowup(e, x + xv, y + yv);
902 // are we blowing up on another BOOMBARREL? if so, start it exploding.
903 AIEntity *e2 = g_hdb->_ai->findEntity(x + xv, y + yv);
904 if (e2 && e2->state != STATE_EXPLODING) {
905 switch (e2->type) {
906 case AI_GUY:
907 g_hdb->_ai->killPlayer(DEATH_FRIED);
908 break;
909 case AI_BOOMBARREL:
910 aiBarrelExplode(e2);
911 break;
912 case AI_OMNIBOT:
913 case AI_TURNBOT:
914 case AI_SHOCKBOT:
915 case AI_RIGHTBOT:
916 case AI_PUSHBOT:
917 case AI_RAILRIDER:
918 case AI_MAINTBOT:
919 case AI_DEADEYE:
920 case AI_FATFROG:
921 case AI_ICEPUFF:
922 case AI_MEERKAT:
923 case AI_BUZZFLY:
924 case AI_GOODFAIRY:
925 case AI_GATEPUDDLE:
926 case AI_BADFAIRY:
927 g_hdb->_ai->addAnimateTarget(x * kTileWidth,
928 y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
929 if (e2->type != AI_LASERBEAM)
930 g_hdb->_ai->removeEntity(e2);
931 break;
932 default:
933 break;
934 }
935 }
936 }
937 }
938
aiBarrelExplosionEnd(int x,int y)939 void aiBarrelExplosionEnd(int x, int y) {
940 g_hdb->_map->setExplosion(x, y, 0);
941 }
942
aiBarrelBlowup(AIEntity * e,int x,int y)943 void aiBarrelBlowup(AIEntity *e, int x, int y) {
944 g_hdb->_ai->addAnimateTarget(x * kTileWidth,
945 y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
946 g_hdb->_map->setExplosion(x, y, 1);
947 g_hdb->_ai->addCallback(AI_BARREL_EXPLOSION_END, x, y, e->animCycle * 4);
948 }
949
aiScientistInit(AIEntity * e)950 void aiScientistInit(AIEntity *e) {
951 e->moveSpeed = kPlayerMoveSpeed >> 1;
952 if (g_hdb->_ai->findPath(e))
953 e->aiAction = aiGenericAction;
954 else if (e->value1)
955 e->aiAction = aiGenericAction;
956 }
957
aiScientistInit2(AIEntity * e)958 void aiScientistInit2(AIEntity *e) {
959 e->draw = g_hdb->_ai->getStandFrameDir(e);
960 }
961
aiSlugAttackAction(AIEntity * e)962 void aiSlugAttackAction(AIEntity *e) {
963 static const int xv[5] = {9, 0, 0, -1, 1};
964 static const int yv[5] = {9, -1, 1, 0, 0};
965
966 if (e->goalX)
967 g_hdb->_ai->animateEntity(e);
968
969 g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false);
970 g_hdb->_ai->checkAutoList(e, e->tileX, e->tileY);
971
972 AIEntity *hit = g_hdb->_ai->findEntityIgnore(e->tileX, e->tileY, e);
973 if (hit && hit->type == AI_GUY)
974 hit = NULL;
975
976 // don't hit anything you can walk through...
977 if (hit && true == g_hdb->_ai->getTableEnt(hit->type))
978 hit = NULL;
979
980 // don't hit floating stuff
981 if (hit && hit->state == STATE_FLOATING)
982 hit = NULL;
983
984 uint32 bg_flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
985 uint32 fg_flags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
986 int result = (e->level == 1 ? (bg_flags & (kFlagSolid)) : !(fg_flags & kFlagGrating) && (bg_flags & (kFlagSolid)));
987 if (hit) {
988 g_hdb->_sound->playSound(SND_SLUG_HIT);
989 g_hdb->_sound->playSound(g_hdb->_ai->metalOrFleshSND(hit));
990 switch (hit->type) {
991 case AI_MEERKAT:
992 if (hit->sequence > 2) { // out of the ground?
993 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
994 g_hdb->_ai->stunEnemy(hit, 8);
995 } else {
996 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
997 e->state = STATE_MOVEDOWN; // so it will draw & animate
998 g_hdb->_ai->animateEntity(e);
999 return;
1000 }
1001 break;
1002 case AI_ICEPUFF:
1003 if (hit->state == STATE_ICEP_APPEAR ||
1004 hit->state == STATE_ICEP_THROWDOWN ||
1005 hit->state == STATE_ICEP_THROWLEFT ||
1006 hit->state == STATE_ICEP_THROWRIGHT) {
1007 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
1008 g_hdb->_ai->stunEnemy(hit, 8);
1009 } else {
1010 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
1011 e->state = STATE_MOVEDOWN; // so it will draw & animate
1012 g_hdb->_ai->animateEntity(e);
1013 return;
1014 }
1015 break;
1016 case AI_OMNIBOT:
1017 case AI_TURNBOT:
1018 case AI_SHOCKBOT:
1019 case AI_RIGHTBOT:
1020 case AI_PUSHBOT:
1021 case AI_LISTENBOT:
1022 case AI_MAINTBOT:
1023 case AI_FATFROG:
1024 case AI_BADFAIRY:
1025 case AI_BUZZFLY:
1026 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
1027 g_hdb->_ai->stunEnemy(hit, 8);
1028 break;
1029
1030 case AI_CHICKEN:
1031 g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
1032 g_hdb->_ai->removeEntity(hit);
1033 break;
1034 case AI_BOOMBARREL:
1035 g_hdb->_sound->playSound(SND_CLUB_HIT_METAL);
1036 aiBarrelExplode(hit);
1037 aiBarrelBlowup(hit, hit->tileX, hit->tileY);
1038 break;
1039 // ACTION MODE entities go away - except the FOURFIRER
1040 case AI_GATEPUDDLE:
1041 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 7, ANIM_NORMAL, false, false, TELEPORT_FLASH);
1042 g_hdb->_ai->removeEntity(hit);
1043 g_hdb->_sound->playSound(SND_TELEPORT);
1044 break;
1045 case AI_DEADEYE:
1046 g_hdb->_ai->addAnimateTarget(e->tileX * kTileWidth,
1047 e->tileY * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
1048 g_hdb->_ai->removeEntity(hit);
1049 g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
1050 break;
1051
1052 case AI_NONE:
1053 if (hit->value1 == (int)AI_DRAGON) {
1054 // pull dragon's coords out of "lua_func_use" string.
1055 char num1[4], num2[4];
1056 memset(num1, 0, 4);
1057 memset(num2, 0, 4);
1058 memcpy(num1, hit->luaFuncUse, 3);
1059 memcpy(num2, hit->luaFuncUse + 3, 3);
1060
1061 g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
1062 AIEntity *found = g_hdb->_ai->findEntity(atoi(num1), atoi(num2));
1063 if (found)
1064 aiDragonWake(found);
1065 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
1066 }
1067 break;
1068 case AI_DRAGON:
1069 aiDragonWake(hit);
1070 break;
1071 default:
1072 break;
1073 }
1074 g_hdb->_ai->removeEntity(e); // bye bye!
1075 return;
1076 } else if (result) { // hit a wall
1077 g_hdb->_sound->playSound(SND_SLUG_HIT);
1078 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
1079 g_hdb->_ai->removeEntity(e);
1080 } else {
1081 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
1082 e->state = STATE_MOVEDOWN; // so it will draw & animate
1083 g_hdb->_ai->animateEntity(e);
1084 }
1085 }
1086
aiSlugAttackDraw(AIEntity * e,int mx,int my)1087 void aiSlugAttackDraw(AIEntity *e, int mx, int my) {
1088 g_hdb->_ai->_slugAttackGfx[e->animFrame]->drawMasked(e->x - mx + 8, e->y - my + 8);
1089 }
1090
aiSlugAttackInit(AIEntity * e)1091 void aiSlugAttackInit(AIEntity *e) {
1092 static const int xv[5] = {9, 0, 0, -1, 1};
1093 static const int yv[5] = {9, -1, 1, 0, 0};
1094
1095 if (g_hdb->isDemo())
1096 return;
1097
1098 e->moveSpeed = kPlayerMoveSpeed << 1;
1099 g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
1100 e->draw = NULL; // use custom draw function
1101 e->aiDraw = aiSlugAttackDraw;
1102 e->state = STATE_MOVEDOWN; // so it will draw & animate
1103 e->aiAction = aiSlugAttackAction;
1104 g_hdb->_sound->playSound(SND_SLUG_FIRE);
1105 }
1106
aiSlugAttackInit2(AIEntity * e)1107 void aiSlugAttackInit2(AIEntity *e) {
1108 e->movedownFrames = 4;
1109 }
1110
aiDeadWorkerInit(AIEntity * e)1111 void aiDeadWorkerInit(AIEntity *e) {
1112 }
1113
aiDeadWorkerInit2(AIEntity * e)1114 void aiDeadWorkerInit2(AIEntity *e) {
1115 e->draw = e->standdownGfx[0];
1116 }
1117
aiWorkerInit(AIEntity * e)1118 void aiWorkerInit(AIEntity *e) {
1119 if (e->value1)
1120 e->aiAction = aiGenericAction;
1121 e->moveSpeed = kPlayerMoveSpeed >> 1;
1122 }
1123
aiWorkerInit2(AIEntity * e)1124 void aiWorkerInit2(AIEntity *e) {
1125 e->draw = g_hdb->_ai->getStandFrameDir(e);
1126 }
1127
aiAccountantInit(AIEntity * e)1128 void aiAccountantInit(AIEntity *e) {
1129 }
1130
aiAccountantInit2(AIEntity * e)1131 void aiAccountantInit2(AIEntity *e) {
1132 e->draw = g_hdb->_ai->getStandFrameDir(e);
1133 }
1134
aiFrogStatueInit(AIEntity * e)1135 void aiFrogStatueInit(AIEntity *e) {
1136 e->moveSpeed = kPushMoveSpeed;
1137 e->aiAction = aiFrogStatueAction;
1138 }
1139
aiFrogStatueInit2(AIEntity * e)1140 void aiFrogStatueInit2(AIEntity *e) {
1141 // point all frog statue MOVE frames to the standing one
1142 e->blinkFrames =
1143 e->movedownFrames =
1144 e->moveleftFrames =
1145 e->moverightFrames =
1146 e->moveupFrames = 1;
1147
1148 e->blinkGfx[0] =
1149 e->movedownGfx[0] =
1150 e->moveupGfx[0] =
1151 e->moveleftGfx[0] =
1152 e->moverightGfx[0] = e->standdownGfx[0];
1153
1154 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
1155 }
1156
aiFrogStatueAction(AIEntity * e)1157 void aiFrogStatueAction(AIEntity *e) {
1158 // if frog statue isn't moving somewhere, don't move it
1159 if (!e->goalX)
1160 return;
1161
1162 g_hdb->_ai->animateEntity(e);
1163 }
1164
aiRoboStunnerAction(AIEntity * e)1165 void aiRoboStunnerAction(AIEntity *e) {
1166 aiAnimateStanddown(e, 1);
1167 aiGetItemAction(e);
1168 }
1169
aiRoboStunnerInit(AIEntity * e)1170 void aiRoboStunnerInit(AIEntity *e) {
1171 e->aiAction = aiRoboStunnerAction;
1172 strcpy(e->printedName, "Robostunner");
1173 }
1174
aiRoboStunnerInit2(AIEntity * e)1175 void aiRoboStunnerInit2(AIEntity *e) {
1176 e->draw = e->standdownGfx[0];
1177 }
1178
aiClubInit(AIEntity * e)1179 void aiClubInit(AIEntity *e) {
1180 strcpy(e->printedName, "Creature Clubber");
1181 e->aiAction = aiGetItemAction;
1182 }
1183
aiClubInit2(AIEntity * e)1184 void aiClubInit2(AIEntity *e) {
1185 e->draw = e->standdownGfx[0];
1186 }
1187
aiSlugSlingerInit(AIEntity * e)1188 void aiSlugSlingerInit(AIEntity *e) {
1189 strcpy(e->printedName, "Slugslinger");
1190 e->aiAction = aiGetItemAction;
1191 }
1192
aiSlugSlingerInit2(AIEntity * e)1193 void aiSlugSlingerInit2(AIEntity *e) {
1194 e->draw = e->standdownGfx[0];
1195 }
1196
aiEnvelopeGreenInit(AIEntity * e)1197 void aiEnvelopeGreenInit(AIEntity *e) {
1198 strcpy(e->printedName, "Green envelope");
1199 e->aiAction = aiGetItemAction;
1200 }
1201
aiEnvelopeGreenInit2(AIEntity * e)1202 void aiEnvelopeGreenInit2(AIEntity *e) {
1203 e->draw = e->standdownGfx[0];
1204 }
1205
aiGemBlueInit(AIEntity * e)1206 void aiGemBlueInit(AIEntity *e) {
1207 e->aiAction = aiGemAction;
1208 }
1209
aiGemBlueInit2(AIEntity * e)1210 void aiGemBlueInit2(AIEntity *e) {
1211 e->draw = e->standdownGfx[0];
1212 }
1213
aiGemRedInit(AIEntity * e)1214 void aiGemRedInit(AIEntity *e) {
1215 e->aiAction = aiGemAction;
1216 }
1217
aiGemRedInit2(AIEntity * e)1218 void aiGemRedInit2(AIEntity *e) {
1219 e->draw = e->standdownGfx[0];
1220 }
1221
aiGemGreenInit(AIEntity * e)1222 void aiGemGreenInit(AIEntity *e) {
1223 e->aiAction = aiGemAction;
1224 }
1225
aiGemGreenInit2(AIEntity * e)1226 void aiGemGreenInit2(AIEntity *e) {
1227 e->draw = e->standdownGfx[0];
1228 }
1229
aiTeaCupInit(AIEntity * e)1230 void aiTeaCupInit(AIEntity *e) {
1231 strcpy(e->printedName, "a Teacup");
1232 e->aiAction = aiGetItemAction;
1233 }
1234
aiTeaCupInit2(AIEntity * e)1235 void aiTeaCupInit2(AIEntity *e) {
1236 e->draw = e->standdownGfx[0];
1237 }
1238
aiCookieInit(AIEntity * e)1239 void aiCookieInit(AIEntity *e) {
1240 strcpy(e->printedName, "a Cookie");
1241 e->aiAction = aiGetItemAction;
1242 }
1243
aiCookieInit2(AIEntity * e)1244 void aiCookieInit2(AIEntity *e) {
1245 e->draw = e->standdownGfx[0];
1246 }
1247
aiBurgerInit(AIEntity * e)1248 void aiBurgerInit(AIEntity *e) {
1249 strcpy(e->printedName, "a Burger");
1250 e->aiAction = aiGetItemAction;
1251 }
1252
aiBurgerInit2(AIEntity * e)1253 void aiBurgerInit2(AIEntity *e) {
1254 e->draw = e->standdownGfx[0];
1255 }
1256
aiBookInit(AIEntity * e)1257 void aiBookInit(AIEntity *e) {
1258 strcpy(e->printedName, "a Book");
1259 e->aiAction = aiGetItemAction;
1260 }
1261
aiBookInit2(AIEntity * e)1262 void aiBookInit2(AIEntity *e) {
1263 e->draw = e->standdownGfx[0];
1264 }
1265
aiClipboardInit(AIEntity * e)1266 void aiClipboardInit(AIEntity *e) {
1267 strcpy(e->printedName, "a Clipboard");
1268 e->aiAction = aiGetItemAction;
1269 }
1270
aiClipboardInit2(AIEntity * e)1271 void aiClipboardInit2(AIEntity *e) {
1272 e->draw = e->standdownGfx[0];
1273 }
1274
aiNoteInit(AIEntity * e)1275 void aiNoteInit(AIEntity *e) {
1276 strcpy(e->printedName, "a Note");
1277 e->aiAction = aiGetItemAction;
1278 }
1279
aiNoteInit2(AIEntity * e)1280 void aiNoteInit2(AIEntity *e) {
1281 e->draw = e->standdownGfx[0];
1282 }
1283
aiKeycardWhiteInit(AIEntity * e)1284 void aiKeycardWhiteInit(AIEntity *e) {
1285 strcpy(e->printedName, "a White keycard");
1286 e->aiAction = aiGetItemAction;
1287 }
1288
aiKeycardWhiteInit2(AIEntity * e)1289 void aiKeycardWhiteInit2(AIEntity *e) {
1290 e->draw = e->standdownGfx[0];
1291 }
1292
aiKeycardBlueInit(AIEntity * e)1293 void aiKeycardBlueInit(AIEntity *e) {
1294 strcpy(e->printedName, "a Blue keycard");
1295 e->aiAction = aiGetItemAction;
1296 }
1297
aiKeycardBlueInit2(AIEntity * e)1298 void aiKeycardBlueInit2(AIEntity *e) {
1299 e->draw = e->standdownGfx[0];
1300 }
1301
aiKeycardRedInit(AIEntity * e)1302 void aiKeycardRedInit(AIEntity *e) {
1303 strcpy(e->printedName, "a Red keycard");
1304 e->aiAction = aiGetItemAction;
1305 }
1306
aiKeycardRedInit2(AIEntity * e)1307 void aiKeycardRedInit2(AIEntity *e) {
1308 e->draw = e->standdownGfx[0];
1309 }
1310
aiKeycardGreenInit(AIEntity * e)1311 void aiKeycardGreenInit(AIEntity *e) {
1312 strcpy(e->printedName, "a Green keycard");
1313 e->aiAction = aiGetItemAction;
1314 }
1315
aiKeycardGreenInit2(AIEntity * e)1316 void aiKeycardGreenInit2(AIEntity *e) {
1317 e->draw = e->standdownGfx[0];
1318 }
1319
aiKeycardPurpleInit(AIEntity * e)1320 void aiKeycardPurpleInit(AIEntity *e) {
1321 strcpy(e->printedName, "a Purple keycard");
1322 e->aiAction = aiGetItemAction;
1323 }
1324
aiKeycardPurpleInit2(AIEntity * e)1325 void aiKeycardPurpleInit2(AIEntity *e) {
1326 e->draw = e->standdownGfx[0];
1327 }
1328
aiKeycardBlackInit(AIEntity * e)1329 void aiKeycardBlackInit(AIEntity *e) {
1330 strcpy(e->printedName, "a Black keycard");
1331 e->aiAction = aiGetItemAction;
1332 }
1333
aiKeycardBlackInit2(AIEntity * e)1334 void aiKeycardBlackInit2(AIEntity *e) {
1335 e->draw = e->standdownGfx[0];
1336 }
1337
aiSeedInit(AIEntity * e)1338 void aiSeedInit(AIEntity *e) {
1339 strcpy(e->printedName, "some Henscratch");
1340 e->aiAction = aiGetItemAction;
1341 }
1342
aiSeedInit2(AIEntity * e)1343 void aiSeedInit2(AIEntity *e) {
1344 e->draw = e->standdownGfx[0];
1345 }
1346
aiSodaInit(AIEntity * e)1347 void aiSodaInit(AIEntity *e) {
1348 strcpy(e->printedName, "a Dr. Frostee");
1349 e->aiAction = aiGetItemAction;
1350 }
1351
aiSodaInit2(AIEntity * e)1352 void aiSodaInit2(AIEntity *e) {
1353 e->draw = e->standdownGfx[0];
1354 }
1355
aiDollyTool1Init(AIEntity * e)1356 void aiDollyTool1Init(AIEntity *e) {
1357 strcpy(e->printedName, "Dolly's Wrench");
1358 e->aiAction = aiGetItemAction;
1359 }
1360
aiDollyTool1Init2(AIEntity * e)1361 void aiDollyTool1Init2(AIEntity *e) {
1362 e->draw = e->standdownGfx[0];
1363 }
1364
aiDollyTool2Init(AIEntity * e)1365 void aiDollyTool2Init(AIEntity *e) {
1366 strcpy(e->printedName, "Dolly's Torch");
1367 e->aiAction = aiGetItemAction;
1368 }
1369
aiDollyTool2Init2(AIEntity * e)1370 void aiDollyTool2Init2(AIEntity *e) {
1371 e->draw = e->standdownGfx[0];
1372 }
1373
aiDollyTool3Init(AIEntity * e)1374 void aiDollyTool3Init(AIEntity *e) {
1375 strcpy(e->printedName, "Dolly's EMF Resonator");
1376 e->aiAction = aiGetItemAction;
1377 }
1378
aiDollyTool3Init2(AIEntity * e)1379 void aiDollyTool3Init2(AIEntity *e) {
1380 e->draw = e->standdownGfx[0];
1381 }
1382
aiDollyTool4Init(AIEntity * e)1383 void aiDollyTool4Init(AIEntity *e) {
1384 strcpy(e->printedName, "Dolly's Toolbox");
1385 e->aiAction = aiGetItemAction;
1386 }
1387
aiDollyTool4Init2(AIEntity * e)1388 void aiDollyTool4Init2(AIEntity *e) {
1389 e->draw = e->standdownGfx[0];
1390 }
1391
aiRouterInit(AIEntity * e)1392 void aiRouterInit(AIEntity *e) {
1393 strcpy(e->printedName, "a Computer Router");
1394 e->aiAction = aiGetItemAction;
1395 }
1396
aiRouterInit2(AIEntity * e)1397 void aiRouterInit2(AIEntity *e) {
1398 e->draw = e->standdownGfx[0];
1399 }
1400
aiSlicerInit(AIEntity * e)1401 void aiSlicerInit(AIEntity *e) {
1402 strcpy(e->printedName, "a Pizza Slicer");
1403 e->aiAction = aiGetItemAction;
1404 }
1405
aiSlicerInit2(AIEntity * e)1406 void aiSlicerInit2(AIEntity *e) {
1407 e->draw = e->standdownGfx[0];
1408 }
1409
aiPackageInit(AIEntity * e)1410 void aiPackageInit(AIEntity *e) {
1411 strcpy(e->printedName, "a Package");
1412 e->aiAction = aiGetItemAction;
1413 }
1414
aiPackageInit2(AIEntity * e)1415 void aiPackageInit2(AIEntity *e) {
1416 e->draw = e->standdownGfx[0];
1417 }
1418
aiMagicEggAction(AIEntity * e)1419 void aiMagicEggAction(AIEntity *e) {
1420 // if magic egg isn't moving somewhere, don't move it
1421 if (!e->goalX)
1422 return;
1423
1424 g_hdb->_ai->animateEntity(e);
1425 }
1426
aiMagicEggInit(AIEntity * e)1427 void aiMagicEggInit(AIEntity *e) {
1428 e->moveSpeed = kPushMoveSpeed;
1429 e->aiAction = aiMagicEggAction;
1430 }
1431
aiMagicEggInit2(AIEntity * e)1432 void aiMagicEggInit2(AIEntity *e) {
1433 // point all magic egg move frames to the standing one
1434 e->movedownFrames =
1435 e->moveleftFrames =
1436 e->moverightFrames =
1437 e->moveupFrames = 1;
1438
1439 e->movedownGfx[0] =
1440 e->moveupGfx[0] =
1441 e->moveleftGfx[0] =
1442 e->moverightGfx[0] = e->standdownGfx[0];
1443
1444 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
1445 }
1446
aiMagicEggUse(AIEntity * e)1447 void aiMagicEggUse(AIEntity *e) {
1448 if (!scumm_strnicmp(e->luaFuncAction, "ai_", 3) || !scumm_strnicmp(e->luaFuncAction, "item_", 5)) {
1449 AIEntity *spawned = NULL;
1450 for (int i = 0; aiEntList[i].type != END_AI_TYPES; ++i) {
1451 if (!scumm_stricmp(aiEntList[i].luaName, e->luaFuncAction)) {
1452 spawned = g_hdb->_ai->spawn(aiEntList[i].type, e->dir, e->tileX, e->tileY, NULL, NULL, NULL, DIR_NONE, e->level, 0, 0, 1);
1453 break;
1454 }
1455 }
1456
1457 if (spawned) {
1458 g_hdb->_ai->addAnimateTarget(e->tileX * kTileWidth,
1459 e->tileY * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
1460
1461 if (!g_hdb->isDemo())
1462 g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
1463
1464 g_hdb->_ai->removeEntity(e);
1465 }
1466 }
1467 }
1468
aiIceBlockAction(AIEntity * e)1469 void aiIceBlockAction(AIEntity *e) {
1470 // if ice block isn't moving somewhere, don't move it
1471 if (!e->goalX)
1472 return;
1473
1474 g_hdb->_ai->animateEntity(e);
1475 }
1476
aiIceBlockInit(AIEntity * e)1477 void aiIceBlockInit(AIEntity *e) {
1478 e->moveSpeed = kPushMoveSpeed;
1479 e->aiAction = aiIceBlockAction;
1480 }
1481
aiIceBlockInit2(AIEntity * e)1482 void aiIceBlockInit2(AIEntity *e) {
1483 // point all ice block move frames to the standing one
1484 e->movedownFrames =
1485 e->moveleftFrames =
1486 e->moverightFrames =
1487 e->moveupFrames = 1;
1488
1489 e->movedownGfx[0] =
1490 e->moveupGfx[0] =
1491 e->moveleftGfx[0] =
1492 e->moverightGfx[0] = e->standdownGfx[0];
1493
1494 e->draw = e->standdownGfx[0]; // standing frame - doesn't move
1495 }
1496
aiCabKeyInit(AIEntity * e)1497 void aiCabKeyInit(AIEntity *e) {
1498 strcpy(e->printedName, "a Cabinet key");
1499 }
1500
aiCabKeyInit2(AIEntity * e)1501 void aiCabKeyInit2(AIEntity *e) {
1502 e->draw = e->standdownGfx[0];
1503 }
1504
aiItemChickenInit(AIEntity * e)1505 void aiItemChickenInit(AIEntity *e) {
1506 strcpy(e->printedName, "Cooper's chicken");
1507 }
1508
aiItemChickenInit2(AIEntity * e)1509 void aiItemChickenInit2(AIEntity *e) {
1510 e->draw = e->standdownGfx[0];
1511 }
1512
aiPdaInit(AIEntity * e)1513 void aiPdaInit(AIEntity *e) {
1514 strcpy(e->printedName, "a P.D.A.");
1515 e->aiAction = aiGetItemAction;
1516 }
1517
aiPdaInit2(AIEntity * e)1518 void aiPdaInit2(AIEntity *e) {
1519 e->draw = e->standdownGfx[0];
1520 }
1521
1522 #if 0
1523 void aiCellUse(AIEntity *e) {
1524 g_hdb->_window->openMessageBar("You got the Energy Cell!", kMsgDelay);
1525 }
1526 #endif
1527
aiCellInit2(AIEntity * e)1528 void aiCellInit2(AIEntity *e) {
1529 e->draw = e->standdownGfx[0];
1530 }
1531
aiCellInit(AIEntity * e)1532 void aiCellInit(AIEntity *e) {
1533 strcpy(e->printedName, "Energy Cell");
1534 e->aiAction = aiGetItemAction;
1535 }
1536
aiEnvelopeWhiteInit(AIEntity * e)1537 void aiEnvelopeWhiteInit(AIEntity *e) {
1538 strcpy(e->printedName, "White envelope");
1539 e->aiAction = aiGetItemAction;
1540 }
1541
aiEnvelopeWhiteInit2(AIEntity * e)1542 void aiEnvelopeWhiteInit2(AIEntity *e) {
1543 e->draw = e->standdownGfx[0];
1544 }
1545
aiEnvelopeBlueInit(AIEntity * e)1546 void aiEnvelopeBlueInit(AIEntity *e) {
1547 strcpy(e->printedName, "Blue envelope");
1548 e->aiAction = aiGetItemAction;
1549 }
1550
aiEnvelopeBlueInit2(AIEntity * e)1551 void aiEnvelopeBlueInit2(AIEntity *e) {
1552 e->draw = e->standdownGfx[0];
1553 }
1554
aiEnvelopeRedInit(AIEntity * e)1555 void aiEnvelopeRedInit(AIEntity *e) {
1556 strcpy(e->printedName, "Red envelope");
1557 e->aiAction = aiGetItemAction;
1558 }
1559
aiEnvelopeRedInit2(AIEntity * e)1560 void aiEnvelopeRedInit2(AIEntity *e) {
1561 e->draw = e->standdownGfx[0];
1562 }
1563
aiTransceiverInit(AIEntity * e)1564 void aiTransceiverInit(AIEntity *e) {
1565 e->aiAction = aiTransceiverAction;
1566 strcpy(e->printedName, "Transceiver");
1567 }
1568
aiTransceiverInit2(AIEntity * e)1569 void aiTransceiverInit2(AIEntity *e) {
1570 e->draw = e->standdownGfx[0];
1571 }
1572
aiTransceiverAction(AIEntity * e)1573 void aiTransceiverAction(AIEntity *e) {
1574 aiAnimateStanddown(e, 5);
1575 if (e->onScreen)
1576 aiGetItemAction(e);
1577 }
1578
1579 #if 0
1580 void aiTransceiverUse(AIEntity *e) {
1581 g_hdb->_window->openMessageBar("You got the Transceiver!", kMsgDelay);
1582 }
1583 #endif
1584
aiMonkeystoneInit(AIEntity * e)1585 void aiMonkeystoneInit(AIEntity *e) {
1586 e->aiUse = aiMonkeystoneUse;
1587 e->aiAction = aiMonkeystoneAction;
1588 }
1589
aiMonkeystoneAction(AIEntity * e)1590 void aiMonkeystoneAction(AIEntity *e) {
1591 if (!e->onScreen)
1592 return;
1593
1594 AIEntity *p = g_hdb->_ai->getPlayer();
1595 if (abs(p->x - e->x) < 16 && abs(p->y - e->y) < 16 && e->level == p->level) {
1596 if (e->luaFuncUse[0])
1597 g_hdb->_lua->callFunction(e->luaFuncUse, 0);
1598
1599 g_hdb->_ai->addToInventory(e);
1600 aiMonkeystoneUse(NULL);
1601 }
1602 }
1603
aiMonkeystoneInit2(AIEntity * e)1604 void aiMonkeystoneInit2(AIEntity *e) {
1605 e->draw = e->standdownGfx[0];
1606 }
1607
aiMonkeystoneUse(AIEntity * e)1608 void aiMonkeystoneUse(AIEntity *e) {
1609 int val = g_hdb->_ai->getMonkeystoneAmount();
1610 Common::String monkString = Common::String::format("You have %d Monkeystone%s!", val, (val > 1) ? "s" : "");
1611 g_hdb->_sound->playSound(SND_GET_MONKEYSTONE);
1612 g_hdb->_window->openMessageBar(monkString.c_str(), kMsgDelay);
1613
1614 // have we unlocked a secret star(tm)???
1615 if (val == 7) {
1616 g_hdb->_window->openMessageBar("Red Star is Ready!", kMsgDelay * 2);
1617 g_hdb->setStarsMonkeystone7(STARS_MONKEYSTONE_7);
1618 g_hdb->_menu->writeConfig();
1619 g_hdb->_gfx->turnOnBonusStars(0);
1620 }
1621 if (val == 14) {
1622 g_hdb->_window->openMessageBar("Green Star is GO!", kMsgDelay * 2);
1623 g_hdb->setStarsMonkeystone14(STARS_MONKEYSTONE_14);
1624 g_hdb->_menu->writeConfig();
1625 g_hdb->_gfx->turnOnBonusStars(1);
1626 }
1627 if (val == 21) {
1628 g_hdb->_window->openMessageBar("Blue Star is Born!", kMsgDelay * 2);
1629 g_hdb->setStarsMonkeystone21(STARS_MONKEYSTONE_21);
1630 g_hdb->_menu->writeConfig();
1631 g_hdb->_gfx->turnOnBonusStars(2);
1632 }
1633 }
1634
aiGemAction(AIEntity * e)1635 void aiGemAction(AIEntity *e) {
1636 e->animFrame++;
1637 if (e->animFrame >= e->standdownFrames) {
1638 e->animFrame = 0;
1639
1640 // every 4th frame, check for player collision &
1641 // add to inventory if it happens
1642 AIEntity *p = g_hdb->_ai->getPlayer();
1643 int tolerance = 16;
1644 if (g_hdb->_ai->playerRunning())
1645 tolerance = 24;
1646
1647 if (e->onScreen && abs(p->x - e->x) < tolerance && abs(p->y - e->y) < tolerance && e->level == p->level) {
1648 g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
1649 g_hdb->_ai->addToInventory(e);
1650 g_hdb->_sound->playSound(SND_GET_GEM);
1651 return;
1652 }
1653 }
1654 e->draw = e->standdownGfx[e->animFrame];
1655 }
1656
aiGemWhiteInit(AIEntity * e)1657 void aiGemWhiteInit(AIEntity *e) {
1658 e->aiAction = aiGemAction;
1659 }
1660
aiGemWhiteInit2(AIEntity * e)1661 void aiGemWhiteInit2(AIEntity *e) {
1662 e->draw = e->standdownGfx[0];
1663 }
1664
aiGooCupUse(AIEntity * e)1665 void aiGooCupUse(AIEntity *e) {
1666 g_hdb->_window->openMessageBar("Got a... cup of goo.", kMsgDelay);
1667 }
1668
aiGooCupInit(AIEntity * e)1669 void aiGooCupInit(AIEntity *e) {
1670 e->aiUse = aiGooCupUse;
1671 e->aiAction = aiGetItemAction;
1672 }
1673
aiGooCupInit2(AIEntity * e)1674 void aiGooCupInit2(AIEntity *e) {
1675 e->draw = e->standdownGfx[0];
1676 }
1677
aiVortexianAction(AIEntity * e)1678 void aiVortexianAction(AIEntity *e) {
1679 // anim the alpha blending : down to 32, up to 180, back down...
1680 e->value2 += e->value1;
1681 if ((e->value2 & 0xff) > 128) {
1682 e->value2 = (e->value2 & 0xff00) | 128;
1683 e->value1 = -e->value1;
1684 } else if ((e->value2 & 0xff) < 32) {
1685 e->value2 = (e->value2 & 0xff00) | 32;
1686 e->value1 = -e->value1;
1687 }
1688
1689 // anim the shape
1690 e->animFrame++;
1691 if (e->animFrame >= e->standdownFrames) {
1692 e->animFrame = 0;
1693
1694 // every 4th frame, check for player collision &
1695 // do an autosave
1696 AIEntity *p = g_hdb->_ai->getPlayer();
1697 if (abs(p->x - e->x) < 4 && abs(p->y - e->y) < 4) {
1698 if (!(e->value2 & 0xff00)) {
1699 // let's make sure we don't autosave every frikken second!
1700 e->value2 |= 0xff00;
1701
1702 g_hdb->saveWhenReady(kAutoSaveSlot);
1703 g_hdb->_window->openMessageBar("Saving progress at Vortexian...", 1);
1704 }
1705 } else
1706 e->value2 &= 0x00ff;
1707 }
1708 e->draw = e->standdownGfx[e->animFrame];
1709 }
1710
aiVortexianUse(AIEntity * e)1711 void aiVortexianUse(AIEntity *e) {
1712 }
1713
aiVortexianInit(AIEntity * e)1714 void aiVortexianInit(AIEntity *e) {
1715 e->aiUse = aiVortexianUse;
1716 e->aiAction = aiVortexianAction;
1717 e->value1 = 5;
1718 e->value2 = 128;
1719 }
1720
aiVortexianInit2(AIEntity * e)1721 void aiVortexianInit2(AIEntity *e) {
1722 e->draw = e->standdownGfx[0];
1723 }
1724
aiNoneInit(AIEntity * e)1725 void aiNoneInit(AIEntity *e) {
1726 }
1727
1728 // Utility Functions
aiAnimateStanddown(AIEntity * e,int speed)1729 void aiAnimateStanddown(AIEntity *e, int speed) {
1730 if (e->value2-- > 0)
1731 return;
1732 e->value2 = speed;
1733
1734 if (e->type == AI_GUY && e->animFrame > 0)
1735 e->value2 = 0;
1736 e->draw = e->standdownGfx[e->animFrame];
1737 e->animFrame++;
1738 if (e->animFrame >= e->standdownFrames)
1739 e->animFrame = 0;
1740 }
1741
aiGenericAction(AIEntity * e)1742 void aiGenericAction(AIEntity *e) {
1743 if (!e->goalX)
1744 g_hdb->_ai->findPath(e);
1745 else if (onEvenTile(e->x, e->y))
1746 g_hdb->_sound->playSound(SND_FOOTSTEPS);
1747 g_hdb->_ai->animateEntity(e);
1748 }
1749
aiGetItemAction(AIEntity * e)1750 void aiGetItemAction(AIEntity *e) {
1751 if (!e->onScreen)
1752 return;
1753
1754 AIEntity *p = g_hdb->_ai->getPlayer();
1755 if (abs(p->x - e->x) < 16 && abs(p->y - e->y) < 16 && e->level == p->level) {
1756 if (e->aiUse)
1757 e->aiUse(e);
1758 if (e->luaFuncUse[0])
1759 g_hdb->_lua->callFunction(e->luaFuncUse, 0);
1760
1761 g_hdb->_ai->getItemSound(e->type);
1762 g_hdb->_ai->addToInventory(e);
1763 }
1764 }
1765
1766 } // End of Namespace
1767