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 "common/file.h"
38 #include "common/system.h"
39 
40 #include "image/bmp.h"
41 
42 #include "griffon/griffon.h"
43 
44 namespace Griffon {
45 
46 // HELPER MACRO ---------------------------------------------------------------
47 #define INPUT(A, B)                 \
48 	do {                            \
49 		Common::String line;        \
50 		line = file.readLine();     \
51 		sscanf(line.c_str(), A, B); \
52 	} while(0)
53 
54 
initialize()55 void GriffonEngine::initialize() {
56 	// init char *_floatstri[kMaxFloat]
57 	for (int i = 0; i < kMaxFloat; i++) {
58 		_floatText[i].text = (char *)malloc(64); // 64 bytes each string (should be enough)
59 		_floatText[i].framesLeft = 0;
60 		_floatText[i].x = 0;
61 		_floatText[i].y = 0;
62 		_floatText[i].col = 0;
63 
64 		_floatIcon[i].framesLeft = 0;
65 		_floatIcon[i].x = 0;
66 		_floatIcon[i].y = 0;
67 		_floatIcon[i].ico = 0;
68 	}
69 
70 	_video = new Graphics::TransparentSurface;
71 	_video->create(320, 240, g_system->getScreenFormat());
72 	_videoBuffer = new Graphics::TransparentSurface;
73 	_videoBuffer->create(320, 240, g_system->getScreenFormat());
74 	_videoBuffer2 = new Graphics::TransparentSurface;
75 	_videoBuffer2->create(320, 240, g_system->getScreenFormat());
76 	_videoBuffer3 = new Graphics::TransparentSurface;
77 	_videoBuffer3->create(320, 240, g_system->getScreenFormat());
78 	_mapBg = new Graphics::TransparentSurface;
79 	_mapBg->create(320, 240, g_system->getScreenFormat());
80 	_clipBg = new Graphics::TransparentSurface;
81 	_clipBg->create(320, 240, g_system->getScreenFormat());
82 	_clipBg2 = new Graphics::TransparentSurface;
83 	_clipBg2->create(320, 240, g_system->getScreenFormat());
84 
85 	for (int i = 0; i <= 3; i++) {
86 		char name[128];
87 
88 		sprintf(name, "art/map%i.bmp", i + 1);
89 		mapImg[i] = loadImage(name, true);
90 	}
91 
92 	_cloudImg = loadImage("art/clouds.bmp", true);
93 	_cloudImg->setAlpha(64, true);
94 
95 	_saveLoadImg = nullptr;
96 
97 	_titleImg = loadImage("art/titleb.bmp");
98 	_titleImg2 = loadImage("art/titlea.bmp", true);
99 	//_titleimg2->setAlpha(204, true);
100 
101 	_inventoryImg = loadImage("art/inventory.bmp", true);
102 
103 	_logosImg = loadImage("art/logos.bmp");
104 	_theEndImg = loadImage("art/theend.bmp");
105 
106 
107 	loadTiles();
108 	loadTriggers();
109 	loadObjectDB();
110 	loadAnims();
111 	loadFont();
112 	loadItemImgs();
113 
114 	_fpsr = 1.0f;
115 	_nextTicks = _ticks + 1000;
116 
117 	for (int i = 0; i <= 15; i++) {
118 		_playerAttackOfs[0][i].x = 0; // -1// -(i + 1)
119 		_playerAttackOfs[0][i].y = -sin(3.14159 * 2 * (i + 1) / 16) * 2 - 1;
120 
121 		_playerAttackOfs[1][i].x = 0; // i + 1
122 		_playerAttackOfs[1][i].y = -sin(3.14159 * 2 * (i + 1) / 16) * 2 + 1;
123 
124 		_playerAttackOfs[2][i].x = -1; // -(i + 1)
125 		_playerAttackOfs[2][i].y = -sin(3.14159 * 2 * (i + 1) / 16) * 2;
126 
127 		_playerAttackOfs[3][i].x = 1; // i + 1
128 		_playerAttackOfs[3][i].y = -sin(3.14159 * 2 * (i + 1) / 16) * 2;
129 	}
130 
131 	setupAudio();
132 }
133 
loadImage(const char * name,bool colorkey)134 Graphics::TransparentSurface *GriffonEngine::loadImage(const char *name, bool colorkey) {
135 	Common::File file;
136 
137 	file.open(name);
138 	if (!file.isOpen()) {
139 		error("Cannot open file %s", name);
140 	}
141 
142 	debug(1, "Loading: %s", name);
143 
144 	Image::BitmapDecoder bitmapDecoder;
145 	bitmapDecoder.loadStream(file);
146 	file.close();
147 
148 	Graphics::TransparentSurface *surface = new Graphics::TransparentSurface(*bitmapDecoder.getSurface()->convertTo(g_system->getScreenFormat()));
149 
150 	if (colorkey)
151 		surface->applyColorKey(255, 0, 255);
152 
153 	return surface;
154 }
155 
loadMap(int mapnum)156 void GriffonEngine::loadMap(int mapnum) {
157 	debug(2, "Loaded map %d", mapnum);
158 
159 	unsigned int ccc = _clipBg->format.RGBToColor(255, 255, 255);
160 
161 	_curMap = mapnum;
162 	Common::Rect trect(320, 240);
163 
164 	_mapBg->fillRect(trect, 0);
165 	_clipBg->fillRect(trect, ccc);
166 	_clipBg2->fillRect(trect, ccc);
167 
168 	_forcePause = false;
169 	_cloudsOn = false;
170 	if (mapnum < 6)
171 		_cloudsOn = true;
172 	if (mapnum > 41)
173 		_cloudsOn = true;
174 	if (mapnum > 47)
175 		_cloudsOn = false;
176 	if (mapnum == 52)
177 		_cloudsOn = true;
178 	if (mapnum == 60)
179 		_cloudsOn = true;
180 	if (mapnum == 50)
181 		_cloudsOn = true;
182 	if (mapnum == 54)
183 		_cloudsOn = true;
184 	if (mapnum == 58)
185 		_cloudsOn = true;
186 	if (mapnum == 62)
187 		_cloudsOn = true;
188 	if (mapnum == 83)
189 		_cloudsOn = true;
190 
191 	// -----------special case
192 	_dontDrawOver = false;
193 	if (mapnum == 24)
194 		_dontDrawOver = true;
195 
196 	if ((mapnum == 53 || mapnum == 57 || mapnum == 61 || mapnum == 65 || mapnum == 62) && _scriptFlag[kScriptLever][0] > 0)
197 		mapnum = mapnum + 100;
198 	if ((mapnum == 161 || mapnum == 162) && _scriptFlag[kScriptLever][0] == 2)
199 		mapnum = mapnum + 100;
200 
201 	for (int i = 0; i < kMaxSpell; i++)
202 		_spellInfo[i].frame = 0;
203 
204 	_roomLock = false;
205 	_saidLocked = false;
206 	_saidJammed = false;
207 	_itemSelOn = false;
208 	_selEnemyOn = false;
209 	_curItem = 0;
210 	_player.itemselshade = 0;
211 
212 	char name[256];
213 	// read *.map file
214 	sprintf(name, "mapdb/%04i.map", mapnum);
215 	debug(1, "Reading %s", name);
216 
217 	Common::File file;
218 	file.open(name);
219 
220 	if (!file.isOpen())
221 		error("Cannot open file %s", name);
222 
223 	int tempmap[320][200];
224 	for (int x = 0; x <= 319; x++) {
225 		for (int y = 0; y <= 199; y++)
226 			INPUT("%i", &tempmap[x][y]);
227 	}
228 	file.close();
229 
230 	for (int x = 0; x <= 319; x++) {
231 		for (int y = 0; y <= 239; y++)
232 			_triggerLoc[x][y] = -1;
233 	}
234 
235 	// read *.trg file
236 	sprintf(name, "mapdb/%04i.trg", mapnum);
237 	debug(1, "Reading %s", name);
238 	file.open(name);
239 
240 	if (!file.isOpen())
241 		error("Cannot open file %s", name);
242 
243 	INPUT("%i", &_triggerNbr);
244 
245 	for (int i = 0; i < _triggerNbr; i++) {
246 		int mapx, mapy, trig;
247 
248 		INPUT("%i", &mapx);
249 		INPUT("%i", &mapy);
250 		INPUT("%i", &trig);
251 
252 		_triggerLoc[mapx][mapy] = trig;
253 	}
254 	file.close();
255 
256 
257 	for (int y = 0; y <= 23; y++) {
258 		for (int x = 0; x <= 39; x++)
259 			_rampData[x][y] = tempmap[3 * 40 + x][y + 40];
260 	}
261 
262 	for (int y = 0; y <= 23; y++) {
263 		for (int x = 0; x <= 39; x++) {
264 			for (int l = 0; l <= 2; l++) {
265 				for (int a = 0; a <= 2; a++)
266 					_tileinfo[l][x][y][a] = 0;
267 			}
268 		}
269 	}
270 
271 	if (_scriptFlag[kScriptFindShield][0] == 1 && _curMap == 4) {
272 		_triggerLoc[9][7] = 5004;
273 		tempmap[9][7] = 41;
274 		tempmap[9][7 + 40] = 0;
275 	}
276 
277 	for (int y = 0; y <= 23; y++) {
278 		for (int x = 0; x <= 39; x++) {
279 			for (int l = 0; l <= 2; l++) {
280 				int ly = y;
281 				int lx = x + l * 40;
282 
283 				// tile
284 				int curtile = tempmap[lx][ly];
285 				int curtilelayer = tempmap[lx][ly + 40];
286 
287 				if (curtile > 0) {
288 					curtile = curtile - 1;
289 					int curtilel = curtilelayer;
290 					int curtilex = curtile % 20;
291 					int curtiley = (curtile - curtilex) / 20;
292 
293 					_tileinfo[l][x][y][0] = curtile + 1;
294 					_tileinfo[l][x][y][1] = curtilelayer;
295 
296 					rcSrc.left = curtilex * 16;
297 					rcSrc.top = curtiley * 16;
298 					rcSrc.setWidth(16);
299 					rcSrc.setHeight(16);
300 
301 					rcDest.left = x * 16;
302 					rcDest.top = y * 16;
303 					rcDest.setWidth(16);
304 					rcDest.setHeight(16);
305 
306 					int alpha = 255;
307 					if (l == 2 && curtilel == 1) {
308 						for (int ff = 0; ff <= 5; ff++) {
309 							int ffa = 20 * 5 - 1 + ff * 20;
310 							int ffb = 20 * 5 + 4 + ff * 20;
311 							if (curtile > ffa && curtile < ffb) {
312 								alpha = 128;
313 							}
314 						}
315 					}
316 					if (l == 1 && curtilel == 2) {
317 						for (int ff = 0; ff <= 4; ff++) {
318 							int ffa = 20 * (5 + ff) + 3;
319 							if (curtile == ffa) {
320 								alpha = 192;
321 							}
322 						}
323 					}
324 
325 					_tiles[curtilel]->blit(*_mapBg, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, TS_ARGB(alpha, 255, 255, 255));
326 
327 					rcDest.left = x * 8;
328 					rcDest.top = y * 8;
329 					rcDest.setWidth(8);
330 					rcDest.setHeight(8);
331 
332 					_clipBg->fillRect(rcDest, 0);
333 				}
334 			}
335 		}
336 	}
337 
338 	for (int x = 0; x <= 39; x++) {
339 		for (int y = 0; y <= 23; y++) {
340 			int d = tempmap[3 * 40 + x][y];
341 
342 			if (_scriptFlag[kScriptFindShield][0] == 1 && x == 9 && y == 7)
343 				d = 99;
344 
345 			if (d > 0) {
346 				int clip = d % 2;
347 				d = (d - clip) / 2;
348 				int npc = d % 2;
349 				d = (d - npc) / 2;
350 
351 				if (d == 99 && x == 9 && y == 7)
352 					clip = 1;
353 
354 				if (clip) {
355 					if (d != 99)
356 						d = tempmap[6 * 40 + x][y];
357 					if (d == 99)
358 						d = 1;
359 
360 					int x1 = x * 8;
361 					int y1 = y * 8;
362 
363 					if (d == 1) {
364 						for (int i = 0; i <= 7; i++) {
365 							drawLine(_clipBg, x1, y1 + i, x1 + 7 - i, y1 + i, ccc);
366 						}
367 					} else if (d == 2) {
368 						drawLine(_clipBg, x1, y1, x1 + 7, y1, ccc);
369 						drawLine(_clipBg, x1, y1 + 1, x1 + 7, y1 + 1, ccc);
370 					} else if (d == 3) {
371 						for (int i = 0; i <= 7; i++) {
372 							drawLine(_clipBg, x1 + i, y1 + i, x1 + 7, y1 + i, ccc);
373 						}
374 					} else if (d == 4) {
375 						drawLine(_clipBg, x1, y1, x1, y1 + 7, ccc);
376 						drawLine(_clipBg, x1 + 1, y1, x1 + 1, y1 + 7, ccc);
377 					} else if (d == 5) {
378 						rcDest.left = x1;
379 						rcDest.top = y1;
380 						rcDest.setWidth(8);
381 						rcDest.setHeight(8);
382 						_clipBg->fillRect(rcDest, ccc);
383 					} else if (d == 6) {
384 						drawLine(_clipBg, x1 + 7, y1, x1 + 7, y1 + 7, ccc);
385 						drawLine(_clipBg, x1 + 6, y1, x1 + 6, y1 + 7, ccc);
386 					} else if (d == 7) {
387 						for (int i = 0; i <= 7; i++) {
388 							drawLine(_clipBg, x1, y1 + i, x1 + i, y1 + i, ccc);
389 						}
390 					} else if (d == 8) {
391 						drawLine(_clipBg, x1, y1 + 7, x1 + 7, y1 + 7, ccc);
392 						drawLine(_clipBg, x1, y1 + 7, x1 + 6, y1 + 6, ccc);
393 					} else if (d == 9) {
394 						for (int i = 0; i <= 7; i++) {
395 							drawLine(_clipBg, x1 + 7 - i, y1 + i, x1 + 7, y1 + i, ccc);
396 						}
397 					}
398 				}
399 			}
400 		}
401 	}
402 
403 	_lastObj = 0;
404 	_lastNpc = 0;
405 
406 	for (int i = 0; i < kMaxNPC; i++)
407 		_npcInfo[i].onMap = false;
408 
409 	for (int x = 0; x <= 20; x++) {
410 		for (int y = 0; y <= 14; y++) {
411 			int d = tempmap[3 * 40 + x][y];
412 
413 			int npc = 0;
414 			int obj = 0;
415 			if (d > 0) {
416 				int clip = d % 2;
417 				d = (d - clip) / 2;
418 				npc = d % 2;
419 				d = (d - npc) / 2;
420 				obj = d % 2;
421 			}
422 
423 			_objectMap[x][y] = -1;
424 
425 			if (obj == 1) {
426 
427 				int o = tempmap[5 * 40 + x][y];
428 
429 				if (_objectMapFull[_curMap][x][y] == 0) {
430 					_objectMap[x][y] = o;
431 
432 					if (_objectInfo[o].nFrames > 1) {
433 						if (o > _lastObj)
434 							_lastObj = o;
435 					}
436 
437 					int x1 = x * 8;
438 					int y1 = y * 8;
439 
440 					rcDest.left = x1;
441 					rcDest.top = y1;
442 					rcDest.setWidth(8);
443 					rcDest.setHeight(8);
444 
445 					if (_objectInfo[o].type == 1)
446 						_clipBg->fillRect(rcDest, ccc);
447 					if (_objectInfo[o].type == 3)
448 						_clipBg->fillRect(rcDest, ccc);
449 				}
450 			}
451 			if (npc == 1) {
452 				int o = tempmap[4 * 40 + x][y];
453 
454 				if (o > _lastNpc)
455 					_lastNpc = o;
456 
457 				_npcInfo[o].x = x * 16 - 4;
458 				_npcInfo[o].y = y * 16 - 5;
459 
460 				_npcInfo[o].walkdir = 1;
461 				_npcInfo[o].onMap = true;
462 			}
463 		}
464 	}
465 
466 
467 	if (_curMap == 62 && _scriptFlag[kScriptGardenMasterKey][0] > 0)
468 		_lastNpc = 0;
469 	if (_curMap == 73 && _scriptFlag[kScriptArmourChest][0] > 0)
470 		_lastNpc = 0;
471 	if (_curMap == 81 && _scriptFlag[kScriptCitadelMasterKey][0] > 0)
472 		_lastNpc = 0;
473 
474 	if (_curMap == 73 && _scriptFlag[kScriptArmourChest][0] == 0)
475 		_roomLock = true;
476 	if (_curMap == 81 && _scriptFlag[kScriptCitadelMasterKey][0] == 0)
477 		_roomLock = true;
478 	if (_curMap == 83 && _scriptFlag[kScriptGetSword3][0] == 0)
479 		_roomLock = true;
480 	if (_curMap == 82)
481 		_roomLock = true;
482 
483 	// read *.npc file
484 	sprintf(name, "mapdb/%04i.npc", mapnum);
485 	debug(1, "Reading %s", name);
486 	file.open(name);
487 
488 	if (!file.isOpen())
489 		error("Cannot open file %s", name);
490 
491 	for (int i = 0; i < kMaxNPC; i++) {
492 		INPUT("%i", &_npcInfo[i].spriteset);
493 		INPUT("%i", &_npcInfo[i].x1);
494 		INPUT("%i", &_npcInfo[i].y1);
495 		INPUT("%i", &_npcInfo[i].x2);
496 		INPUT("%i", &_npcInfo[i].y2);
497 		INPUT("%i", &_npcInfo[i].movementmode);
498 		INPUT("%i", &_npcInfo[i].hp);
499 		INPUT("%i", &_npcInfo[i].item1);
500 		INPUT("%i", &_npcInfo[i].item2);
501 		INPUT("%i", &_npcInfo[i].item3);
502 		INPUT("%i", &_npcInfo[i].script);
503 
504 		_npcInfo[i].cframe = 0;
505 		_npcInfo[i].frame = 0;
506 		_npcInfo[i].frame2 = 0;
507 		_npcInfo[i].attackattempt = 0;
508 		_npcInfo[i].ticks = 0;
509 
510 		// baby dragon
511 		if (_npcInfo[i].spriteset == kMonsterBabyDragon) {
512 			_npcInfo[i].hp = 12;
513 			_npcInfo[i].attackdelay = 2000;
514 
515 			_npcInfo[i].attackDamage = 2;
516 			_npcInfo[i].spellDamage = 0;
517 
518 			_npcInfo[i].walkspd = 1;
519 
520 			if (RND() * 5 == 0)
521 				_npcInfo[i].hp = 0;
522 		}
523 
524 		// onewing
525 		if (_npcInfo[i].spriteset == kMonsterOneWing) {
526 			_npcInfo[i].hp = 200;
527 			_npcInfo[i].attackdelay = 2000;
528 			_npcInfo[i].swaySpeed = 1;
529 
530 			_npcInfo[i].attackDamage = 24;
531 			_npcInfo[i].spellDamage = 30;
532 
533 			_npcInfo[i].walkspd = 1.4f;
534 			_npcInfo[i].castPause = _ticks;
535 		}
536 
537 		// boss1
538 		if (_npcInfo[i].spriteset == kMonsterBoss1) {
539 			_npcInfo[i].hp = 300;
540 			_npcInfo[i].attackdelay = 2200;
541 
542 			_npcInfo[i].attackDamage = 0;
543 			_npcInfo[i].spellDamage = 30;
544 
545 			_npcInfo[i].walkspd = 1.2f;
546 		}
547 
548 		// black knights
549 		if (_npcInfo[i].spriteset == kMonsterBlackKnight) {
550 			_npcInfo[i].hp = 200;
551 			_npcInfo[i].attackdelay = 2800;
552 
553 			_npcInfo[i].attackDamage = 0;
554 			_npcInfo[i].spellDamage = 30;
555 
556 			_npcInfo[i].walkspd = 1;
557 		}
558 
559 		// boss2 firehydra
560 		if (_npcInfo[i].spriteset == kMonsterFireHydra) {
561 			_npcInfo[i].hp = 600;
562 			_npcInfo[i].attackdelay = 2200;
563 
564 			_npcInfo[i].attackDamage = 50;
565 			_npcInfo[i].spellDamage = 30;
566 
567 			_npcInfo[i].walkspd = 1.3f;
568 
569 			_npcInfo[i].swayAngle = 0;
570 		}
571 
572 		// baby fire dragon
573 		if (_npcInfo[i].spriteset == kMonsterRedDragon) {
574 			_npcInfo[i].hp = 20;
575 			_npcInfo[i].attackdelay = 1500;
576 
577 			_npcInfo[i].attackDamage = 0;
578 			_npcInfo[i].spellDamage = 12;
579 
580 			_npcInfo[i].walkspd = 1;
581 
582 			if (RND() * 5 == 0)
583 				_npcInfo[i].hp = 0;
584 		}
585 
586 		// priest1
587 		if (_npcInfo[i].spriteset == kMonsterPriest) {
588 			_npcInfo[i].hp = 40;
589 			_npcInfo[i].attackdelay = 5000;
590 
591 			_npcInfo[i].attackDamage = 0;
592 			_npcInfo[i].spellDamage = 8;
593 
594 			_npcInfo[i].walkspd = 1;
595 
596 			if (RND() * 8 == 0)
597 				_npcInfo[i].hp = 0;
598 		}
599 
600 		// yellow fire dragon
601 		if (_npcInfo[i].spriteset == kMonsterYellowDragon) {
602 			_npcInfo[i].hp = 100;
603 			_npcInfo[i].attackdelay = 1500;
604 
605 			_npcInfo[i].attackDamage = 0;
606 			_npcInfo[i].spellDamage = 24;
607 
608 			_npcInfo[i].walkspd = 1;
609 
610 			if (RND() * 5 == 0)
611 				_npcInfo[i].hp = 0;
612 		}
613 
614 		// twowing
615 		if (_npcInfo[i].spriteset == kMonsterTwoWing) {
616 			_npcInfo[i].hp = 140;
617 			_npcInfo[i].attackdelay = 2000;
618 			_npcInfo[i].swaySpeed = 1;
619 
620 			_npcInfo[i].attackDamage = 30;
621 			_npcInfo[i].spellDamage = 0;
622 
623 			_npcInfo[i].walkspd = 1;
624 
625 			_npcInfo[i].castPause = 0;
626 		}
627 
628 		// dragon2
629 		if (_npcInfo[i].spriteset == kMonsterDragon2) {
630 			_npcInfo[i].hp = 80;
631 			_npcInfo[i].attackdelay = 1500;
632 
633 			_npcInfo[i].attackDamage = 24;
634 			_npcInfo[i].spellDamage = 0;
635 
636 			_npcInfo[i].walkspd = 1;
637 
638 			_npcInfo[i].floating = RND() * 16;
639 		}
640 
641 		// end boss
642 		if (_npcInfo[i].spriteset == kMonsterFinalBoss) {
643 			_npcInfo[i].hp = 1200;
644 			_npcInfo[i].attackdelay = 2000;
645 
646 			_npcInfo[i].attackDamage = 100;
647 			_npcInfo[i].spellDamage = 60;
648 
649 			_npcInfo[i].walkspd = 1;
650 
651 			_npcInfo[i].floating = RND() * 16;
652 		}
653 
654 		// bat kitty
655 		if (_npcInfo[i].spriteset == kMonsterBatKitty) {
656 			_npcInfo[i].hp = 800;
657 			_npcInfo[i].attackdelay = 2000;
658 
659 			_npcInfo[i].attackDamage = 100;
660 			_npcInfo[i].spellDamage = 50;
661 
662 			_npcInfo[i].walkspd = 1;
663 
664 			_npcInfo[i].floating = RND() * 16;
665 		}
666 
667 		if (!_npcInfo[i].onMap)
668 			_npcInfo[i].hp = 0;
669 
670 		_npcInfo[i].maxhp = _npcInfo[i].hp;
671 
672 		_npcInfo[i].attacking = false;
673 		_npcInfo[i].attackframe = 0;
674 		_npcInfo[i].cattackframe = 0;
675 		_npcInfo[i].attackspd = 1.5;
676 		_npcInfo[i].attacknext = _ticks + _npcInfo[i].attackdelay * (1 + RND() * 2);
677 
678 		if (_npcInfo[i].spriteset == kMonsterOneWing || _npcInfo[i].spriteset == kMonsterTwoWing) {
679 			_npcInfo[i].bodysection[0].sprite = 0;
680 			_npcInfo[i].bodysection[1].sprite = 1;
681 			_npcInfo[i].bodysection[2].sprite = 2;
682 			_npcInfo[i].bodysection[3].sprite = 3;
683 			_npcInfo[i].bodysection[4].sprite = 4;
684 			_npcInfo[i].bodysection[5].sprite = 3;
685 			_npcInfo[i].bodysection[6].sprite = 3;
686 			_npcInfo[i].bodysection[7].sprite = 5;
687 
688 			_npcInfo[i].bodysection[0].bonelength = 8;
689 			_npcInfo[i].bodysection[1].bonelength = 7;
690 			_npcInfo[i].bodysection[2].bonelength = 6;
691 			_npcInfo[i].bodysection[3].bonelength = 4;
692 			_npcInfo[i].bodysection[4].bonelength = 4;
693 			_npcInfo[i].bodysection[5].bonelength = 4;
694 			_npcInfo[i].bodysection[6].bonelength = 4;
695 
696 			for (int f = 0; f <= 7; f++) {
697 				_npcInfo[i].bodysection[f].x = _npcInfo[i].x + 12;
698 				_npcInfo[i].bodysection[f].y = _npcInfo[i].y + 14;
699 			}
700 
701 			_npcInfo[i].headTargetX[0] = _npcInfo[i].x + 12;
702 			_npcInfo[i].headTargetY[0] = _npcInfo[i].y + 14;
703 
704 		}
705 
706 		if (_npcInfo[i].spriteset == kMonsterFireHydra) {
707 			for (int f = 0; f <= 29; f++) {
708 				_npcInfo[i].bodysection[f].x = _npcInfo[i].x + 12;
709 				_npcInfo[i].bodysection[f].y = _npcInfo[i].y + 14;
710 			}
711 
712 			for (int f = 0; f <= 2; f++) {
713 				_npcInfo[i].headTargetX[f] = _npcInfo[i].x + 12;
714 				_npcInfo[i].headTargetY[f] = _npcInfo[i].y + 14;
715 
716 				_npcInfo[i].attacking2[f] = false;
717 				_npcInfo[i].attackframe2[f] = 0;
718 			}
719 		}
720 
721 		if (_npcInfo[i].script == kScriptMasterKey) {
722 			_roomLock = true;
723 			if (_scriptFlag[kScriptMasterKey][0] > 0) {
724 				_roomLock = false;
725 				_npcInfo[i].hp = 0;
726 			}
727 		}
728 
729 		if (_npcInfo[i].script == kScriptFindCrystal) {
730 			_roomLock = true;
731 			if (_scriptFlag[kScriptFindCrystal][0] > 0) {
732 				_roomLock = false;
733 				_npcInfo[i].hp = 0;
734 			}
735 		}
736 
737 		if (_npcInfo[i].script == kScriptFindSword) {
738 			_roomLock = true;
739 			if (_scriptFlag[kScriptFindSword][0] > 0) {
740 				_roomLock = false;
741 				_npcInfo[i].hp = 0;
742 			}
743 		}
744 
745 		if (_npcInfo[i].script == kScriptGetSword3) {
746 			_roomLock = true;
747 			if (_scriptFlag[kScriptGetSword3][0] > 0) {
748 				_roomLock = false;
749 				_npcInfo[i].hp = 0;
750 			}
751 		}
752 
753 		_npcInfo[i].pause = _ticks;
754 	}
755 
756 	file.close();
757 
758 
759 	int cx, cy, npx, npy, lx, ly;
760 
761 	// academy master key
762 	if (_curMap == 34 && _scriptFlag[kScriptMasterKey][0] == 1) {
763 		cx = 9;
764 		cy = 7;
765 
766 		_objectMap[cx][cy] = 5;
767 
768 		rcDest.left = cx * 8;
769 		rcDest.top = cy * 8;
770 		rcDest.setWidth(8);
771 		rcDest.setHeight(8);
772 
773 		npx = _player.px + 12;
774 		npy = _player.py + 20;
775 
776 		lx = (int)npx / 16;
777 		ly = (int)npy / 16;
778 
779 		if (lx == cx && ly == cy)
780 			_player.py = _player.py + 16;
781 
782 		_clipBg->fillRect(rcDest, ccc);
783 	}
784 
785 	// academy crystal
786 	if (_curMap == 24 && !_player.foundSpell[0] && _scriptFlag[kScriptFindCrystal][0] == 1) {
787 		cx = 9;
788 		cy = 7;
789 
790 		_objectMap[cx][cy] = 6;
791 
792 		rcDest.left = cx * 8;
793 		rcDest.top = cy * 8;
794 		rcDest.setWidth(8);
795 		rcDest.setHeight(8);
796 
797 		npx = _player.px + 12;
798 		npy = _player.py + 20;
799 
800 		lx = (int)npx / 16;
801 		ly = (int)npy / 16;
802 
803 		if (lx == cx && ly == cy)
804 			_player.py = _player.py + 16;
805 
806 		_clipBg->fillRect(rcDest, ccc);
807 	}
808 
809 	// gardens master key
810 	if (_curMap == 62 && _scriptFlag[kScriptGardenMasterKey][0] == 1) {
811 		cx = 13;
812 		cy = 7;
813 
814 		_objectMap[cx][cy] = 5;
815 
816 		rcDest.left = cx * 8;
817 		rcDest.top = cy * 8;
818 		rcDest.setWidth(8);
819 		rcDest.setHeight(8);
820 
821 		npx = _player.px + 12;
822 		npy = _player.py + 20;
823 
824 		lx = (int)npx / 16;
825 		ly = (int)npy / 16;
826 
827 		if (lx == cx && ly == cy)
828 			_player.py = _player.py + 16;
829 
830 		_clipBg->fillRect(rcDest, ccc);
831 	}
832 
833 	// gardens fidelis sword
834 	if (_curMap == 66 && _scriptFlag[kScriptFindSword][0] == 1 && _player.sword == 1) {
835 		cx = 9;
836 		cy = 6;
837 
838 		_objectMap[cx][cy] = 9;
839 
840 		rcDest.left = cx * 8;
841 		rcDest.top = cy * 8;
842 		rcDest.setWidth(8);
843 		rcDest.setHeight(8);
844 
845 		npx = _player.px + 12;
846 		npy = _player.py + 20;
847 
848 		lx = (int)npx / 16;
849 		ly = (int)npy / 16;
850 
851 		if (lx == cx && ly == cy)
852 			_player.py = _player.py + 16;
853 
854 		_clipBg->fillRect(rcDest, ccc);
855 	}
856 
857 	// citadel armour
858 	if (_curMap == 73 && _scriptFlag[kScriptArmourChest][0] == 1 && _player.armour == 1) {
859 		cx = 8;
860 		cy = 7;
861 
862 		_objectMap[cx][cy] = 16;
863 
864 		rcDest.left = cx * 8;
865 		rcDest.top = cy * 8;
866 		rcDest.setWidth(8);
867 		rcDest.setHeight(8);
868 
869 		npx = _player.px + 12;
870 		npy = _player.py + 20;
871 
872 		lx = (int)npx / 16;
873 		ly = (int)npy / 16;
874 
875 		if (lx == cx && ly == cy)
876 			_player.py = _player.py + 16;
877 
878 		_clipBg->fillRect(rcDest, ccc);
879 	}
880 
881 	// citadel master key
882 	if (_curMap == 81 && _scriptFlag[kScriptCitadelMasterKey][0] == 1) {
883 		cx = 11;
884 		cy = 10;
885 
886 		_objectMap[cx][cy] = 5;
887 
888 		rcDest.left = cx * 8;
889 		rcDest.top = cy * 8;
890 		rcDest.setWidth(8);
891 		rcDest.setHeight(8);
892 
893 		npx = _player.px + 12;
894 		npy = _player.py + 20;
895 
896 		lx = (int)npx / 16;
897 		ly = (int)npy / 16;
898 
899 		if (lx == cx && ly == cy)
900 			_player.py = _player.py + 16;
901 
902 		_clipBg->fillRect(rcDest, ccc);
903 	}
904 
905 
906 	// max ups
907 	if (_curMap == 83 && _scriptFlag[kScriptGetSword3][0] == 1 && _player.sword < 3) {
908 		cx = 6;
909 		cy = 8;
910 
911 		_objectMap[cx][cy] = 18;
912 
913 		rcDest.left = cx * 8;
914 		rcDest.top = cy * 8;
915 		rcDest.setWidth(8);
916 		rcDest.setHeight(8);
917 
918 		npx = _player.px + 12;
919 		npy = _player.py + 20;
920 
921 		lx = (int)npx / 16;
922 		ly = (int)npy / 16;
923 
924 		if (lx == cx && ly == cy)
925 			_player.py = _player.py + 16;
926 
927 		_clipBg->fillRect(rcDest, ccc);
928 	}
929 
930 	if (_curMap == 83 && _scriptFlag[kScriptShield3][0] == 1 && _player.shield < 3) {
931 		cx = 9;
932 		cy = 8;
933 
934 		_objectMap[cx][cy] = 19;
935 
936 		rcDest.left = cx * 8;
937 		rcDest.top = cy * 8;
938 		rcDest.setWidth(8);
939 		rcDest.setHeight(8);
940 
941 		npx = _player.px + 12;
942 		npy = _player.py + 20;
943 
944 		lx = (int)npx / 16;
945 		ly = (int)npy / 16;
946 
947 		if (lx == cx && ly == cy)
948 			_player.py = _player.py + 16;
949 
950 		_clipBg->fillRect(rcDest, ccc);
951 	}
952 
953 	if (_curMap == 83 && _scriptFlag[kScriptArmour3][0] == 1 && _player.armour < 3) {
954 		cx = 12;
955 		cy = 8;
956 
957 		_objectMap[cx][cy] = 20;
958 
959 		rcDest.left = cx * 8;
960 		rcDest.top = cy * 8;
961 		rcDest.setWidth(8);
962 		rcDest.setHeight(8);
963 
964 		npx = _player.px + 12;
965 		npy = _player.py + 20;
966 
967 		lx = (int)npx / 16;
968 		ly = (int)npy / 16;
969 
970 		if (lx == cx && ly == cy)
971 			_player.py = _player.py + 16;
972 
973 		_clipBg->fillRect(rcDest, ccc);
974 	}
975 
976 	_clipBg2->copyRectToSurface(_clipBg->getPixels(), _clipBg->pitch, 0, 0, _clipBg->w, _clipBg->h);
977 }
978 
loadAnims()979 void GriffonEngine::loadAnims() {
980 	_spellImg = loadImage("art/spells.bmp", true);
981 	_anims[0] = loadImage("art/anims0.bmp", true);
982 	_animsAttack[0] = loadImage("art/anims0a.bmp", true);
983 	_anims[13] = loadImage("art/anims0x.bmp", true);
984 	_animsAttack[13] = loadImage("art/anims0xa.bmp", true);
985 	_anims[1] = loadImage("art/anims1.bmp", true);
986 	_animsAttack[1] = loadImage("art/anims1a.bmp", true);
987 	_anims[2] = loadImage("art/anims2.bmp", true);
988 
989 	// huge
990 	_animSet2[0].xofs = 8;
991 	_animSet2[0].yofs = 7;
992 	_animSet2[0].x = 123;
993 	_animSet2[0].y = 0;
994 	_animSet2[0].w = 18;
995 	_animSet2[0].h = 16;
996 	// big
997 	_animSet2[1].xofs = 7;
998 	_animSet2[1].yofs = 7;
999 	_animSet2[1].x = 107;
1000 	_animSet2[1].y = 0;
1001 	_animSet2[1].w = 16;
1002 	_animSet2[1].h = 14;
1003 	// med
1004 	_animSet2[2].xofs = 6;
1005 	_animSet2[2].yofs = 6;
1006 	_animSet2[2].x = 93;
1007 	_animSet2[2].y = 0;
1008 	_animSet2[2].w = 14;
1009 	_animSet2[2].h = 13;
1010 	// small
1011 	_animSet2[3].xofs = 4;
1012 	_animSet2[3].yofs = 4;
1013 	_animSet2[3].x = 83;
1014 	_animSet2[3].y = 0;
1015 	_animSet2[3].w = 10;
1016 	_animSet2[3].h = 10;
1017 	// wing
1018 	_animSet2[4].xofs = 4;
1019 	_animSet2[4].yofs = 20;
1020 	_animSet2[4].x = 42;
1021 	_animSet2[4].y = 0;
1022 	_animSet2[4].w = 41;
1023 	_animSet2[4].h = 33;
1024 	// head
1025 	_animSet2[5].xofs = 20;
1026 	_animSet2[5].yofs = 18;
1027 	_animSet2[5].x = 0;
1028 	_animSet2[5].y = 0;
1029 	_animSet2[5].w = 42;
1030 	_animSet2[5].h = 36;
1031 
1032 	_anims[9] = loadImage("art/anims9.bmp", true);
1033 
1034 	// huge
1035 	_animSet9[0].xofs = 8;
1036 	_animSet9[0].yofs = 7;
1037 	_animSet9[0].x = 154;
1038 	_animSet9[0].y = 0;
1039 	_animSet9[0].w = 18;
1040 	_animSet9[0].h = 16;
1041 	// big
1042 	_animSet9[1].xofs = 7;
1043 	_animSet9[1].yofs = 7;
1044 	_animSet9[1].x = 138;
1045 	_animSet9[1].y = 0;
1046 	_animSet9[1].w = 16;
1047 	_animSet9[1].h = 14;
1048 	// med
1049 	_animSet9[2].xofs = 6;
1050 	_animSet9[2].yofs = 6;
1051 	_animSet9[2].x = 93 + 31;
1052 	_animSet9[2].y = 0;
1053 	_animSet9[2].w = 14;
1054 	_animSet9[2].h = 13;
1055 	// small
1056 	_animSet9[3].xofs = 4;
1057 	_animSet9[3].yofs = 4;
1058 	_animSet9[3].x = 83 + 31;
1059 	_animSet9[3].y = 0;
1060 	_animSet9[3].w = 10;
1061 	_animSet9[3].h = 10;
1062 	// wing
1063 	_animSet9[4].xofs = 36;
1064 	_animSet9[4].yofs = 20;
1065 	_animSet9[4].x = 42;
1066 	_animSet9[4].y = 0;
1067 	_animSet9[4].w = 72;
1068 	_animSet9[4].h = 33;
1069 	// head
1070 	_animSet9[5].xofs = 20;
1071 	_animSet9[5].yofs = 18;
1072 	_animSet9[5].x = 0;
1073 	_animSet9[5].y = 0;
1074 	_animSet9[5].w = 42;
1075 	_animSet9[5].h = 36;
1076 
1077 	_anims[3] = loadImage("art/anims3.bmp", true);
1078 	_anims[4] = loadImage("art/anims4.bmp", true);
1079 	_anims[5] = loadImage("art/anims5.bmp", true);
1080 	_anims[6] = loadImage("art/anims6.bmp", true);
1081 	_anims[7] = loadImage("art/anims7.bmp", true);
1082 	_anims[8] = loadImage("art/anims8.bmp", true);
1083 	_anims[10] = loadImage("art/anims10.bmp", true);
1084 	_animsAttack[10] = loadImage("art/anims10a.bmp", true);
1085 	_anims[11] = loadImage("art/anims11.bmp", true);
1086 	_animsAttack[11] = loadImage("art/anims11a.bmp", true);
1087 	_anims[12] = loadImage("art/anims12.bmp", true);
1088 }
1089 
loadItemImgs()1090 void GriffonEngine::loadItemImgs() {
1091 	Graphics::TransparentSurface *temp = loadImage("art/icons.bmp", true);
1092 
1093 	for (int i = 0; i <= 20; i++) {
1094 		_itemImg[i] = new Graphics::TransparentSurface;
1095 		_itemImg[i]->create(16, 16, g_system->getScreenFormat());
1096 
1097 		rcSrc.left = i * 16;
1098 		rcSrc.top = 0;
1099 		rcSrc.setWidth(16);
1100 		rcSrc.setHeight(16);
1101 
1102 		temp->blit(*_itemImg[i], 0, 0, Graphics::FLIP_NONE, &rcSrc);
1103 	}
1104 
1105 	temp->free();
1106 }
1107 
loadFont()1108 void GriffonEngine::loadFont() {
1109 	Graphics::TransparentSurface *font = loadImage("art/font.bmp", true);
1110 
1111 	for (int i = 32; i <= 255; i++)
1112 		for (int f = 0; f <= 4; f++) {
1113 			int i2 = i - 32;
1114 
1115 			_fontChr[i2][f] = new Graphics::TransparentSurface;
1116 			_fontChr[i2][f]->create(8, 8, g_system->getScreenFormat());
1117 
1118 			int col = i2 % 40;
1119 
1120 			int row = (i2 - col) / 40;
1121 
1122 			rcSrc.left = col * 8;
1123 			rcSrc.top = row * 8 + f * 48;
1124 			rcSrc.setWidth(8);
1125 			rcSrc.setHeight(8);
1126 
1127 			rcDest.left = 0;
1128 			rcDest.top = 0;
1129 			font->blit(*_fontChr[i2][f], rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc);
1130 		}
1131 
1132 	font->free();
1133 }
1134 
loadTiles()1135 void GriffonEngine::loadTiles() {
1136 	_tiles[0] = loadImage("art/tx.bmp", true);
1137 	_tiles[1] = loadImage("art/tx1.bmp", true);
1138 	_tiles[2] = loadImage("art/tx2.bmp", true);
1139 	_tiles[3] = loadImage("art/tx3.bmp", true);
1140 
1141 	_windowImg = loadImage("art/window.bmp", true);
1142 }
1143 
loadTriggers()1144 void GriffonEngine::loadTriggers() {
1145 	Common::File file;
1146 	file.open("data/triggers.dat");
1147 
1148 	if (!file.isOpen())
1149 		error("Cannot open file data/Triggers.dat");
1150 
1151 	for (int i = 0; i <= 9999; i++) {
1152 		for (int a = 0; a <= 8; a++)
1153 			INPUT("%i", &_triggers[i][a]);
1154 	}
1155 
1156 	file.close();
1157 }
1158 
loadObjectDB()1159 void GriffonEngine::loadObjectDB() {
1160 	Common::File file;
1161 
1162 	file.open("objectdb.dat");
1163 	if (!file.isOpen())
1164 		error("Cannot open file objectdb.dat");
1165 
1166 	for (int a = 0; a <= 32; a++) {
1167 		INPUT("%i", &_objectInfo[a].nFrames);
1168 		INPUT("%i", &_objectInfo[a].xTiles);
1169 		INPUT("%i", &_objectInfo[a].yTiles);
1170 		INPUT("%i", &_objectInfo[a].speed);
1171 		INPUT("%i", &_objectInfo[a].type);
1172 		INPUT("%i", &_objectInfo[a].script);
1173 
1174 		for (int b = 0; b <= 8; b++) {
1175 			for (int c = 0; c <= 2; c++) {
1176 				for (int d = 0; d <= 2; d++) {
1177 					for (int e = 0; e <= 1; e++) {
1178 						INPUT("%i", &_objectTile[a][b][c][d][e]);
1179 					}
1180 				}
1181 			}
1182 		}
1183 	}
1184 
1185 	file.close();
1186 }
1187 
1188 
1189 } // end of namespace Griffon
1190