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  *              Originally written by Syn9 in FreeBASIC with SDL
23  *              http://syn9.thehideoutgames.com/index_backup.php
24  *
25  *            Ported to plain C for GCW-Zero handheld by Dmitry Smagin
26  *                http://github.com/dmitrysmagin/griffon_legend
27  *
28  *
29  *                 Programming/Graphics: Daniel "Syn9" Kennedy
30  *                     Music/Sound effects: David Turner
31  *
32  *                   Beta testing and gameplay design help:
33  *                    Deleter, Cha0s, Aether Fox, and Kiz
34  *
35  */
36 
37 #include "griffon/griffon.h"
38 #include "griffon/console.h"
39 
40 namespace Griffon {
41 
attack()42 void GriffonEngine::attack() {
43 	float npx = _player.px + 12;
44 	float npy = _player.py + 20;
45 
46 	int lx = (int)npx / 16;
47 	int ly = (int)npy / 16;
48 
49 	// if facing up
50 	if (_player.walkDir == 0) {
51 		if (ly > 0) {
52 			int o2 = 0; // ??
53 			int o = _objectMap[lx][ly - 1];
54 			if (ly > 1 && (_curMap == 54 || _curMap == 58))
55 				o2 = _objectMap[lx][ly - 2];
56 
57 			// cst
58 			if ((_objectInfo[o].type == 1 && (o == 0 || o > 4)) || (_objectInfo[o2].type == 0 && o2 == 10)) {
59 				if (o2 == 10)
60 					o = 10;
61 
62 				int oscript = _objectInfo[o].script;
63 				switch (oscript) {
64 				case kScriptFlask:
65 					if (_player.inventory[kInvFlask] < 9) {
66 						_player.inventory[kInvFlask]++;
67 						addFloatIcon(6, lx * 16, (ly - 1) * 16);
68 
69 						_objectMapFull[_curMap][lx][ly - 1] = 1;
70 
71 						if (config.effects) {
72 							int snd = playSound(_sfx[kSndPowerUp]);
73 							setChannelVolume(snd, config.effectsVol);
74 						}
75 
76 						if (_objectInfo[o].type == 1)
77 							_objectMap[lx][ly - 1] = 3;
78 
79 						eventText("Found Flask!");
80 					} else {
81 						if (config.effects) {
82 							int snd = playSound(_sfx[kSndChest]);
83 							setChannelVolume(snd, config.effectsVol);
84 						}
85 
86 						eventText("Cannot Carry any more Flasks!");
87 					}
88 					_itemTicks = _ticks + 215;
89 					return;
90 					break;
91 				case kScriptMasterKey:
92 					_player.inventory[kInvMasterKey]++;
93 
94 					addFloatIcon(14, lx * 16, (ly - 1) * 16);
95 
96 					_itemTicks = _ticks + 215;
97 
98 					if (_curMap == 34)
99 						_scriptFlag[kScriptMasterKey][0] = 2;
100 					else if (_curMap == 62)
101 						_scriptFlag[kScriptGardenMasterKey][0] = 2;
102 					else if (_curMap == 81)
103 						_scriptFlag[kScriptCitadelMasterKey][0] = 2;
104 
105 					if (config.effects) {
106 						int snd = playSound(_sfx[kSndPowerUp]);
107 						setChannelVolume(snd, config.effectsVol);
108 					}
109 
110 					if (_objectInfo[o].type == 1)
111 						_objectMap[lx][ly - 1] = 3;
112 					eventText("Found the Temple Key!");
113 					return;
114 				case kScriptFindCrystal:
115 					_player.foundSpell[0] = 1;
116 					_player.spellCharge[0] = 0;
117 
118 					addFloatIcon(7, lx * 16, (ly - 1) * 16);
119 
120 					if (config.effects) {
121 						int snd = playSound(_sfx[kSndPowerUp]);
122 						setChannelVolume(snd, config.effectsVol);
123 					}
124 
125 					if (_objectInfo[o].type == 1)
126 						_objectMap[lx][ly - 1] = 3;
127 
128 					eventText("Found the Infinite Crystal!");
129 					_itemTicks = _ticks + 215;
130 					return;
131 				case kScriptFindShield:
132 					if (_player.shield == 1) {
133 						_player.shield = 2;
134 
135 						addFloatIcon(4, lx * 16, (ly - 1) * 16);
136 
137 						_itemTicks = _ticks + 215;
138 
139 						if (config.effects) {
140 							int snd = playSound(_sfx[kSndPowerUp]);
141 							setChannelVolume(snd, config.effectsVol);
142 						}
143 
144 						if (_objectInfo[o].type == 1)
145 							_objectMap[lx][ly - 1] = 3;
146 
147 						eventText("Found the Obsidian Shield!");
148 						_objectMapFull[4][1][2] = 1;
149 						return;
150 					}
151 					break;
152 				case kScriptFindSword:
153 					if (_player.sword == 1) {
154 						_player.sword = 2;
155 
156 						addFloatIcon(3, lx * 16, (ly - 1) * 16);
157 
158 						_itemTicks = _ticks + 215;
159 
160 						if (config.effects) {
161 							int snd = playSound(_sfx[kSndPowerUp]);
162 							setChannelVolume(snd, config.effectsVol);
163 						}
164 
165 						if (_objectInfo[o].type == 1)
166 							_objectMap[lx][ly - 1] = 3;
167 						eventText("Found the Fidelis Sword!");
168 						return;
169 					}
170 					break;
171 				case kScriptKeyChest:
172 					if (_player.inventory[kInvNormalKey] < 9) {
173 						_player.inventory[kInvNormalKey]++;
174 
175 						for (int s = 20; s <= 23; s++) {
176 							if (_scriptFlag[s][0] == 1) {
177 								_scriptFlag[s][0] = 2;
178 							}
179 						}
180 
181 						if (config.effects) {
182 							int snd = playSound(_sfx[kSndPowerUp]);
183 							setChannelVolume(snd, config.effectsVol);
184 						}
185 
186 						_objectMapFull[_curMap][lx][ly - 1] = 1;
187 
188 						if (_objectInfo[o].type == 1)
189 							_objectMap[lx][ly - 1] = 3;
190 
191 						eventText("Found Key");
192 						addFloatIcon(16, lx * 16, (ly - 1) * 16);
193 					} else {
194 						if (config.effects) {
195 							int snd = playSound(_sfx[kSndChest]);
196 							setChannelVolume(snd, config.effectsVol);
197 						}
198 
199 						eventText("Cannot Carry Any More Keys");
200 					}
201 					break;
202 				case kScriptBlueFlask:
203 					if (_player.inventory[kInvDoubleFlask] < 9) {
204 						_player.inventory[kInvDoubleFlask]++;
205 						addFloatIcon(12, lx * 16, (ly - 1) * 16);
206 
207 						_objectMapFull[_curMap][lx][ly - 1] = 1;
208 
209 						if (config.effects) {
210 							int snd = playSound(_sfx[kSndPowerUp]);
211 							setChannelVolume(snd, config.effectsVol);
212 						}
213 
214 						if (_objectInfo[o].type == 1)
215 							_objectMap[lx][ly - 1] = 3;
216 
217 						eventText("Found Mega Flask!");
218 					} else {
219 						if (config.effects) {
220 							int snd = playSound(_sfx[kSndChest]);
221 							setChannelVolume(snd, config.effectsVol);
222 						}
223 
224 						eventText("Cannot Carry any more Mega Flasks!");
225 					}
226 
227 					_itemTicks = _ticks + 215;
228 					return;
229 					break;
230 				case kScriptBlueFlaskChest:
231 					if (_player.inventory[kInvDoubleFlask] < 9) {
232 						_player.inventory[kInvDoubleFlask]++;
233 						addFloatIcon(12, lx * 16, (ly - 1) * 16);
234 
235 						_objectMapFull[_curMap][lx][ly - 1] = 1;
236 
237 						if (config.effects) {
238 							int snd = playSound(_sfx[kSndPowerUp]);
239 							setChannelVolume(snd, config.effectsVol);
240 						}
241 
242 						if (_objectInfo[o].type == 1)
243 							_objectMap[lx][ly - 1] = 3;
244 
245 						eventText("Found Mega Flask!");
246 					} else {
247 						if (config.effects) {
248 							int snd = playSound(_sfx[kSndChest]);
249 							setChannelVolume(snd, config.effectsVol);
250 						}
251 
252 						eventText("Cannot Carry any more Mega Flasks!");
253 					}
254 					_itemTicks = _ticks + 215;
255 					return;
256 					break;
257 				case kScriptLightningChest:
258 					if (_player.inventory[kInvShock] < 9) {
259 						_player.inventory[kInvShock]++;
260 						addFloatIcon(17, lx * 16, (ly - 1) * 16);
261 
262 						_objectMapFull[_curMap][lx][ly - 1] = 1;
263 
264 						if (config.effects) {
265 							int snd = playSound(_sfx[kSndPowerUp]);
266 							setChannelVolume(snd, config.effectsVol);
267 						}
268 
269 						if (_objectInfo[o].type == 1)
270 							_objectMap[lx][ly - 1] = 3;
271 
272 						eventText("Found Lightning Bomb!");
273 					} else {
274 						if (config.effects) {
275 							int snd = playSound(_sfx[kSndChest]);
276 							setChannelVolume(snd, config.effectsVol);
277 						}
278 
279 						eventText("Cannot Carry any more Lightning Bombs!");
280 					}
281 					_itemTicks = _ticks + 215;
282 					return;
283 					break;
284 				case kScriptArmourChest:
285 					if (_player.armour == 1) {
286 						_player.armour = 2;
287 
288 						addFloatIcon(5, lx * 16, (ly - 1) * 16);
289 
290 						if (config.effects) {
291 							int snd = playSound(_sfx[kSndPowerUp]);
292 							setChannelVolume(snd, config.effectsVol);
293 						}
294 
295 						if (_objectInfo[o].type == 1)
296 							_objectMap[lx][ly - 1] = 3;
297 
298 						eventText("Found the Fidelis Mail!");
299 						_itemTicks = _ticks + 215;
300 						return;
301 					}
302 					break;
303 				case kScriptLever:
304 					if (_curMap == 58 && _scriptFlag[kScriptLever][0] == 0) {
305 						_scriptFlag[kScriptLever][0] = 1;
306 
307 						if (config.effects) {
308 							int snd = playSound(_sfx[kSndLever]);
309 							setChannelVolume(snd, config.effectsVol);
310 						}
311 					} else if (_curMap == 58 && _scriptFlag[kScriptLever][0] > 0) {
312 						if (config.effects) {
313 							int snd = playSound(_sfx[kSndDoor]);
314 							setChannelVolume(snd, config.effectsVol);
315 						}
316 
317 						eventText("It's stuck!");
318 					} else if (_curMap == 54 && _scriptFlag[kScriptLever][0] == 1) {
319 						if (config.effects) {
320 							int snd = playSound(_sfx[kSndLever]);
321 							setChannelVolume(snd, config.effectsVol);
322 						}
323 
324 						_scriptFlag[kScriptLever][0] = 2;
325 					} else if (_curMap == 54 && _scriptFlag[kScriptLever][0] > 1) {
326 						if (config.effects) {
327 							int snd = playSound(_sfx[kSndDoor]);
328 							setChannelVolume(snd, config.effectsVol);
329 						}
330 
331 						eventText("It's stuck!");
332 					}
333 					break;
334 				case kScriptGetSword3:
335 					if (_player.sword < 3) {
336 						_player.sword = 3;
337 
338 						addFloatIcon(18, lx * 16, (ly - 1) * 16);
339 
340 						_itemTicks = _ticks + 215;
341 
342 						if (config.effects) {
343 							int snd = playSound(_sfx[kSndPowerUp]);
344 							setChannelVolume(snd, config.effectsVol);
345 						}
346 
347 						if (_objectInfo[o].type == 1)
348 							_objectMap[lx][ly - 1] = 3;
349 						eventText("Found the Blood Sword!");
350 						_objectMapFull[4][1][2] = 1;
351 						return;
352 					}
353 					break;
354 				case kScriptShield3:
355 					if (_player.shield < 3) {
356 						_player.shield = 3;
357 						addFloatIcon(19, lx * 16, (ly - 1) * 16);
358 						_itemTicks = _ticks + 215;
359 
360 						if (config.effects) {
361 							int snd = playSound(_sfx[kSndPowerUp]);
362 							setChannelVolume(snd, config.effectsVol);
363 						}
364 
365 						if (_objectInfo[o].type == 1)
366 							_objectMap[lx][ly - 1] = 3;
367 						eventText("Found the Entropy Shield!");
368 						_objectMapFull[4][1][2] = 1;
369 						return;
370 					}
371 					break;
372 				case kScriptArmour3:
373 					if (_player.armour < 3) {
374 						_player.armour = 3;
375 						addFloatIcon(20, lx * 16, (ly - 1) * 16);
376 						_itemTicks = _ticks + 215;
377 
378 						if (config.effects) {
379 							int snd = playSound(_sfx[kSndPowerUp]);
380 							setChannelVolume(snd, config.effectsVol);
381 						}
382 
383 						if (_objectInfo[o].type == 1)
384 							_objectMap[lx][ly - 1] = 3;
385 						eventText("Found the Rubyscale Armour!");
386 						_objectMapFull[4][1][2] = 1;
387 						return;
388 					}
389 					break;
390 				default:
391 					break;
392 				}
393 			}
394 		}
395 	}
396 
397 	_attacking = true;
398 	_player.attackFrame = 0;
399 	_movingUp = false;
400 	_movingDown = false;
401 	_movingLeft = false;
402 	_movingRight = false;
403 
404 	for (int i = 0; i <= 15; i++) {
405 		for (int a = 0; a <= 3; a++) {
406 			_playerAttackOfs[a][i].completed = false;
407 		}
408 	}
409 }
410 
castSpell(int spellnum,float homex,float homey,float enemyx,float enemyy,int damagewho)411 void GriffonEngine::castSpell(int spellnum, float homex, float homey, float enemyx, float enemyy, int damagewho) {
412 	// spellnum 7 = sprite 6 spitfire
413 
414 	for (int i = 0; i < kMaxSpell; i++) {
415 		if (ABS(_spellInfo[i].frame) < kEpsilon) {
416 			_spellInfo[i].homex = homex;
417 			_spellInfo[i].homey = homey;
418 			_spellInfo[i].enemyx = enemyx;
419 			_spellInfo[i].enemyy = enemyy;
420 			_spellInfo[i].spellnum = spellnum;
421 			int dw = 0;
422 			int npc = 0;
423 			if (damagewho > 0) {
424 				dw = 1;
425 				npc = damagewho;
426 			}
427 
428 			_spellInfo[i].damagewho = dw;
429 			_spellInfo[i].npc = npc;
430 
431 			_spellInfo[i].frame = 32.0f;
432 			if (damagewho == 0) {
433 				_spellInfo[i].strength = _player.spellStrength / 100;
434 				if (ABS(_player.spellStrength - 100) < kEpsilon)
435 					_spellInfo[i].strength = 1.5f;
436 			}
437 
438 			switch(spellnum) {
439 			case 1:
440 				if (config.effects) {
441 					int snd = playSound(_sfx[kSndThrow]);
442 					setChannelVolume(snd, config.effectsVol);
443 				}
444 				break;
445 			case 2:
446 				// set earthslide vars
447 				for (int f = 0; f <= 8; f++) {
448 					_spellInfo[i].rocky[f] = 0;
449 					_spellInfo[i].rockimg[f] = (int)(RND() * 4);
450 					_spellInfo[i].rockdeflect[f] = ((int)(RND() * 128) - 64) * 1.5;
451 				}
452 				break;
453 			case 3:
454 				// set fire vars
455 				for (int f = 0; f <= 4; f++)
456 					_spellInfo[i].legalive[f] = 32;
457 
458 				break;
459 			case 5:
460 				if (config.effects) {
461 					int snd = playSound(_sfx[kSndCrystal]);
462 					setChannelVolume(snd, config.effectsVol);
463 				}
464 				break;
465 			case 6: {
466 				// room fireball vars
467 				int nballs = 0;
468 				for (int x = 0; x <= 19; x++) {
469 					for (int y = 0; y <= 14; y++) {
470 						if ((_objectMap[x][y] == 1 || _objectMap[x][y] == 2) && nballs < 5 && (int)(RND() * 4) == 0) {
471 							int ax = x * 16;
472 							int ay = y * 16;
473 
474 							_spellInfo[i].fireballs[nballs][0] = ax;
475 							_spellInfo[i].fireballs[nballs][1] = ay;
476 							_spellInfo[i].fireballs[nballs][2] = 0;
477 							_spellInfo[i].fireballs[nballs][3] = 0;
478 
479 							_spellInfo[i].ballon[nballs] = 1;
480 							++nballs;
481 						}
482 					}
483 				}
484 				_spellInfo[i].nfballs = nballs;
485 				}
486 				break;
487 			case 8:
488 			case 9:
489 				if (config.effects) {
490 					int snd = playSound(_sfx[kSndLightning]);
491 					setChannelVolume(snd, config.effectsVol);
492 				}
493 				break;
494 			default:
495 				break;
496 			}
497 
498 			return;
499 		}
500 	}
501 }
502 
checkHit()503 void GriffonEngine::checkHit() {
504 	if (_attacking) {
505 		for (int i = 1; i <= _lastNpc; i++) {
506 			if (_npcInfo[i].hp > 0 && _npcInfo[i].pause < _ticks && (int)(RND() * 2) == 0) {
507 				float npx = _npcInfo[i].x;
508 				float npy = _npcInfo[i].y;
509 
510 				float xdif = _player.px - npx;
511 				float ydif = _player.py - npy;
512 
513 				float ps = _player.sword;
514 				if (ps > 1)
515 					ps *= 0.75;
516 				float damage = (float)_player.swordDamage * (1.0 + RND() * 1.0) * _player.attackStrength / 100.0 * ps;
517 
518 				if (_console->_godMode == kGodModeAll)
519 					damage = 1000;
520 
521 				if (ABS(_player.attackStrength - 100) < kEpsilon)
522 					damage *= 1.5;
523 
524 				bool hit = false;
525 				if (_player.walkDir == 0) {
526 					if (ABS(xdif) <= 8 && ydif >= 0 && ydif < 8)
527 						hit = true;
528 				} else if (_player.walkDir == 1) {
529 					if (ABS(xdif) <= 8 && ydif <= 0 && ydif > -8)
530 						hit = true;
531 				} else if (_player.walkDir == 2) {
532 					if (ABS(ydif) <= 8 && xdif >= -8 && xdif < 8)
533 						hit = true;
534 				} else if (_player.walkDir == 3) {
535 					if (ABS(ydif) <= 8 && xdif <= 8 && xdif > -8)
536 						hit = true;
537 				}
538 
539 				if (hit) {
540 					if (config.effects) {
541 						int snd = playSound(_sfx[kSndSwordHit]);
542 						setChannelVolume(snd, config.effectsVol);
543 					}
544 
545 					damageNPC(i, damage, 0);
546 				}
547 			}
548 		}
549 	}
550 }
551 
damageNPC(int npcnum,int damage,int spell)552 void GriffonEngine::damageNPC(int npcnum, int damage, int spell) {
553 	char line[256];
554 	int fcol;
555 
556 	if (damage == 0) {
557 		strcpy(line, "miss!");
558 		fcol = 2;
559 	} else {
560 		int ratio = 0;
561 		int heal = 0;
562 		if (damage < 0)
563 			heal = 1;
564 		damage = ABS(damage);
565 
566 		if (heal == 0) {
567 			if (damage > _npcInfo[npcnum].hp) {
568 				ratio = (damage - _npcInfo[npcnum].hp) * 100 / damage;
569 				damage = _npcInfo[npcnum].hp;
570 			}
571 
572 			_npcInfo[npcnum].hp -= damage;
573 			if (_npcInfo[npcnum].hp < 0)
574 				_npcInfo[npcnum].hp = 0;
575 
576 			sprintf(line, "-%i", damage);
577 			fcol = 1;
578 		} else {
579 			_npcInfo[npcnum].hp += damage;
580 			if (_npcInfo[npcnum].hp > _npcInfo[npcnum].maxhp)
581 				_npcInfo[npcnum].hp = _npcInfo[npcnum].maxhp;
582 
583 			sprintf(line, "+%i", damage);
584 			fcol = 5;
585 		}
586 
587 		_npcInfo[npcnum].pause = _ticks + 900;
588 
589 		if (spell == 0)
590 			_player.attackStrength = ratio;
591 	}
592 
593 	addFloatText(line, _npcInfo[npcnum].x + 12 - 4 * strlen(line), _npcInfo[npcnum].y + 16, fcol);
594 
595 	if (_npcInfo[npcnum].spriteset == kMonsterBatKitty)
596 		castSpell(9, _npcInfo[npcnum].x, _npcInfo[npcnum].y, _player.px, _player.py, npcnum);
597 
598 	// if enemy is killed
599 	if (_npcInfo[npcnum].hp == 0) {
600 		_player.exp += _npcInfo[npcnum].maxhp;
601 
602 		if (_npcInfo[npcnum].spriteset == kMonsterBabyDragon || _npcInfo[npcnum].spriteset == kMonsterPriest ||
603 				_npcInfo[npcnum].spriteset == kMonsterRedDragon) {
604 			int ff = (int)(RND() * _player.level * 3);
605 			if (ff == 0) {
606 				float npx = _npcInfo[npcnum].x + 12;
607 				float npy = _npcInfo[npcnum].y + 20;
608 
609 				int lx = (int)npx / 16;
610 				int ly = (int)npy / 16;
611 
612 				if (_objectMap[lx][ly] == -1)
613 					_objectMap[lx][ly] = 4;
614 			}
615 		}
616 
617 		if (_npcInfo[npcnum].spriteset == kMonsterOneWing || _npcInfo[npcnum].spriteset == kMonsterTwoWing ||
618 					_npcInfo[npcnum].spriteset == kMonsterBlackKnight || _npcInfo[npcnum].spriteset == kMonsterFireHydra) {
619 			int ff = (int)(RND() * _player.level);
620 			if (ff == 0) {
621 				float npx = _npcInfo[npcnum].x + 12;
622 				float npy = _npcInfo[npcnum].y + 20;
623 
624 				int lx = (int)npx / 16;
625 				int ly = (int)npy / 16;
626 
627 				if (_objectMap[lx][ly] == -1)
628 					_objectMap[lx][ly] = 12;
629 			}
630 		}
631 
632 		if (_npcInfo[npcnum].spriteset == kMonsterTwoWing || _npcInfo[npcnum].spriteset == kMonsterDragon2 ||
633 				_npcInfo[npcnum].spriteset == kMonsterFireHydra) {
634 			int ff = (int)(RND() * _player.level * 2);
635 			if (ff == 0) {
636 				float npx = _npcInfo[npcnum].x + 12;
637 				float npy = _npcInfo[npcnum].y + 20;
638 
639 				int lx = (int)npx / 16;
640 				int ly = (int)npy / 16;
641 
642 				if (_objectMap[lx][ly] == -1)
643 					_objectMap[lx][ly] = 13;
644 			}
645 		}
646 
647 		// academy master key chest script
648 		if (_npcInfo[npcnum].script == kScriptMasterKey) {
649 			bool alive = false;
650 			for (int i = 1; i <= _lastNpc; i++) {
651 				if (_npcInfo[i].hp > 0)
652 					alive = true;
653 			}
654 
655 			if (!alive) {
656 				int cx = 9;
657 				int cy = 7;
658 
659 				_objectMap[cx][cy] = 5;
660 
661 				rcDest.left = cx * 8;
662 				rcDest.top = cy * 8;
663 				rcDest.setWidth(8);
664 				rcDest.setHeight(8);
665 
666 				float npx = _player.px + 12;
667 				float npy = _player.py + 20;
668 
669 				int lx = (int)npx / 16;
670 				int ly = (int)npy / 16;
671 
672 				if (lx == cx && ly == cy)
673 					_player.py += 16;
674 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
675 				_scriptFlag[kScriptMasterKey][0] = 1;
676 			}
677 		}
678 
679 		// academy crystal chest script
680 		if (_npcInfo[npcnum].script == kScriptFindCrystal) {
681 			bool alive = false;
682 			for (int i = 1; i <= _lastNpc; i++) {
683 				if (_npcInfo[i].hp > 0)
684 					alive = true;
685 			}
686 
687 			if (!alive) {
688 				int cx = 9;
689 				int cy = 7;
690 
691 				_objectMap[cx][cy] = 6;
692 
693 				rcDest.left = cx * 8;
694 				rcDest.top = cy * 8;
695 				rcDest.setWidth(8);
696 				rcDest.setHeight(8);
697 
698 				float npx = _player.px + 12;
699 				float npy = _player.py + 20;
700 
701 				int lx = (int)npx / 16;
702 				int ly = (int)npy / 16;
703 
704 				if (lx == cx && ly == cy)
705 					_player.py += 16;
706 				_scriptFlag[kScriptFindCrystal][0] = 1;
707 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
708 			}
709 		}
710 
711 		// tower shield chest script
712 		if (_npcInfo[npcnum].script == kScriptFindShield && _scriptFlag[kScriptFindShield][0] == 0) {
713 			_triggerLoc[9][7] = 5004;
714 
715 			int curTile = 40;
716 			int curTileL = 0;
717 			int curTileX = curTile % 20;
718 			int curTileY = (curTile - curTileX) / 20;
719 
720 			int l = 0; // ?? not defined in original code
721 			_tileinfo[l][9][7][0] = curTile + 1;
722 			_tileinfo[l][9][7][1] = 0;
723 
724 			rcSrc.left = curTileX * 16;
725 			rcSrc.top = curTileY * 16;
726 			rcSrc.setWidth(16);
727 			rcSrc.setHeight(16);
728 
729 			rcDest.left = 9 * 16;
730 			rcDest.top = 7 * 16;
731 			rcDest.setWidth(16);
732 			rcDest.setHeight(16);
733 
734 			_tiles[curTileL]->blit(*_mapBg, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc);
735 		}
736 
737 		// firehydra sword chest
738 		if (_npcInfo[npcnum].script == kScriptFindSword) {
739 			bool alive = false;
740 			for (int i = 1; i <= _lastNpc; i++) {
741 				if (_npcInfo[i].hp > 0)
742 					alive = true;
743 			}
744 
745 			if (!alive) {
746 				int cx = 9;
747 				int cy = 6;
748 
749 				_objectMap[cx][cy] = 9;
750 
751 				rcDest.left = cx * 8;
752 				rcDest.top = cy * 8;
753 				rcDest.setWidth(8);
754 				rcDest.setHeight(8);
755 
756 				float npx = _player.px + 12;
757 				float npy = _player.py + 20;
758 
759 				int lx = (int)npx / 16;
760 				int ly = (int)npy / 16;
761 
762 				if (lx == cx && ly == cy)
763 					_player.py += 16;
764 				_scriptFlag[kScriptFindSword][0] = 1;
765 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
766 			}
767 
768 		}
769 
770 		// gardens master key script
771 		if (_npcInfo[npcnum].script == kScriptGardenMasterKey && _scriptFlag[kScriptKeyChest][0] == 0) {
772 			bool alive = false;
773 			for (int i = 1; i <= _lastNpc; i++) {
774 				if (_npcInfo[i].hp > 0)
775 					alive = true;
776 			}
777 
778 			if (!alive) {
779 				int cx = 13;
780 				int cy = 7;
781 
782 				_objectMap[cx][cy] = 5;
783 
784 				rcDest.left = cx * 8;
785 				rcDest.top = cy * 8;
786 				rcDest.setWidth(8);
787 				rcDest.setHeight(8);
788 
789 				float npx = _player.px + 12;
790 				float npy = _player.py + 20;
791 
792 				int lx = (int)npx / 16;
793 				int ly = (int)npy / 16;
794 
795 				if (lx == cx && ly == cy)
796 					_player.py += 16;
797 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
798 				_scriptFlag[kScriptGardenMasterKey][0] = 1;
799 			}
800 		}
801 
802 		// regular key chest 1
803 		for (int s = 20; s <= 23; s++) {
804 			if (_npcInfo[npcnum].script == s && _scriptFlag[s][0] < 2) {
805 				bool alive = false;
806 				for (int i = 1; i <= _lastNpc; i++) {
807 					if (_npcInfo[i].hp > 0)
808 						alive = true;
809 				}
810 
811 				if (!alive) {
812 					int cx = 9;
813 					int cy = 7;
814 
815 					_objectMap[cx][cy] = 11;
816 
817 					rcDest.left = cx * 8;
818 					rcDest.top = cy * 8;
819 					rcDest.setWidth(8);
820 					rcDest.setHeight(8);
821 
822 					float npx = _player.px + 12;
823 					float npy = _player.py + 20;
824 
825 					int lx = (int)npx / 16;
826 					int ly = (int)npy / 16;
827 
828 					if (lx == cx && ly == cy)
829 						_player.py += 16;
830 					_scriptFlag[s][0] = 1;
831 					_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
832 				}
833 			}
834 		}
835 
836 		// pickup lightning bomb
837 		if (_npcInfo[npcnum].script == kScriptLightningBomb && (_curMap == 41 && _scriptFlag[kScriptLightningBomb][1] == 0)) {
838 			bool alive = false;
839 			for (int i = 1; i <= _lastNpc; i++) {
840 				if (_npcInfo[i].hp > 0)
841 					alive = true;
842 			}
843 
844 			if (!alive) {
845 				int cx = 9;
846 				int cy = 7;
847 
848 				_objectMap[cx][cy] = 13;
849 
850 				rcDest.left = cx * 8;
851 				rcDest.top = cy * 8;
852 				rcDest.setWidth(8);
853 				rcDest.setHeight(8);
854 
855 				float npx = _player.px + 12;
856 				float npy = _player.py + 20;
857 
858 				int lx = (int)npx / 16;
859 				int ly = (int)npy / 16;
860 
861 				if (lx == cx && ly == cy)
862 					_player.py += 16;
863 			}
864 		}
865 
866 		// citadel armour chest
867 		if (_npcInfo[npcnum].script == kScriptArmourChest) {
868 			bool alive = false;
869 			for (int i = 1; i <= _lastNpc; i++) {
870 				if (_npcInfo[i].hp > 0)
871 					alive = true;
872 			}
873 
874 			if (!alive) {
875 				int cx = 8;
876 				int cy = 7;
877 
878 				_objectMap[cx][cy] = 16;
879 
880 				rcDest.left = cx * 8;
881 				rcDest.top = cy * 8;
882 				rcDest.setWidth(8);
883 				rcDest.setHeight(8);
884 
885 				float npx = _player.px + 12;
886 				float npy = _player.py + 20;
887 
888 				int lx = (int)npx / 16;
889 				int ly = (int)npy / 16;
890 
891 				if (lx == cx && ly == cy)
892 					_player.py += 16;
893 				_scriptFlag[kScriptArmourChest][0] = 1;
894 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
895 			}
896 		}
897 
898 		// citadel master key script
899 		if (_npcInfo[npcnum].script == kScriptCitadelMasterKey && _scriptFlag[kScriptCitadelMasterKey][0] == 0) {
900 			bool alive = false;
901 			for (int i = 1; i <= _lastNpc; i++) {
902 				if (_npcInfo[i].hp > 0)
903 					alive = true;
904 			}
905 
906 			if (!alive) {
907 				int cx = 11;
908 				int cy = 10;
909 
910 				_objectMap[cx][cy] = 5;
911 
912 				rcDest.left = cx * 8;
913 				rcDest.top = cy * 8;
914 				rcDest.setWidth(8);
915 				rcDest.setHeight(8);
916 
917 				float npx = _player.px + 12;
918 				float npy = _player.py + 20;
919 
920 				int lx = (int)npx / 16;
921 				int ly = (int)npy / 16;
922 
923 				if (lx == cx && ly == cy)
924 					_player.py += 16;
925 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
926 				_scriptFlag[kScriptCitadelMasterKey][0] = 1;
927 			}
928 		}
929 
930 		// max ups
931 		if (_npcInfo[npcnum].script == kScriptGetSword3 && _scriptFlag[kScriptGetSword3][0] == 0) {
932 			bool alive = false;
933 			for (int i = 1; i <= _lastNpc; i++) {
934 				if (_npcInfo[i].hp > 0)
935 					alive = true;
936 			}
937 
938 			if (!alive) {
939 				int cx = 6;
940 				int cy = 8;
941 
942 				_objectMap[cx][cy] = 18;
943 
944 				rcDest.left = cx * 8;
945 				rcDest.top = cy * 8;
946 				rcDest.setWidth(8);
947 				rcDest.setHeight(8);
948 
949 				float npx = _player.px + 12;
950 				float npy = _player.py + 20;
951 
952 				int lx = (int)npx / 16;
953 				int ly = (int)npy / 16;
954 
955 				if (lx == cx && ly == cy)
956 					_player.py += 16;
957 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
958 				_scriptFlag[kScriptGetSword3][0] = 1;
959 
960 				cx = 9;
961 				cy = 8;
962 
963 				_objectMap[cx][cy] = 19;
964 
965 				rcDest.left = cx * 8;
966 				rcDest.top = cy * 8;
967 				rcDest.setWidth(8);
968 				rcDest.setHeight(8);
969 
970 				npx = _player.px + 12;
971 				npy = _player.py + 20;
972 
973 				lx = (int)npx / 16;
974 				ly = (int)npy / 16;
975 
976 				if (lx == cx && ly == cy)
977 					_player.py += 16;
978 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
979 
980 				_scriptFlag[kScriptShield3][0] = 1;
981 
982 				cx = 12;
983 				cy = 8;
984 
985 				_objectMap[cx][cy] = 20;
986 
987 				rcDest.left = cx * 8;
988 				rcDest.top = cy * 8;
989 				rcDest.setWidth(8);
990 				rcDest.setHeight(8);
991 
992 				npx = _player.px + 12;
993 				npy = _player.py + 20;
994 
995 				lx = (int)npx / 16;
996 				ly = (int)npy / 16;
997 
998 				if (lx == cx && ly == cy)
999 					_player.py += 16;
1000 				_clipBg2->fillRect(rcDest, _clipBg->format.RGBToColor(255, 255, 255));
1001 				_scriptFlag[kScriptArmour3][0] = 1;
1002 			}
1003 		}
1004 
1005 		if (_npcInfo[npcnum].script == kScriptEndOfGame) {
1006 			endOfGame();
1007 			_gameMode = kGameModeIntro;
1008 		}
1009 	}
1010 }
1011 
damagePlayer(int damage)1012 void GriffonEngine::damagePlayer(int damage) {
1013 	char line[256];
1014 
1015 	if (_console->_godMode != kGodModeNone)
1016 		damage = 0;
1017 
1018 	_player.hp -= damage;
1019 
1020 	if (_player.hp < 0)
1021 		_player.hp = 0;
1022 
1023 	sprintf(line, "-%i", damage);
1024 	if (damage == 0)
1025 		strcpy(line, "miss!");
1026 
1027 	addFloatText(line, _player.px + 12 - 4 * strlen(line), _player.py + 16, 4);
1028 
1029 	_player.pause = _ticks + 1000;
1030 }
1031 
1032 
1033 } // end of namespace Griffon
1034