1 /*
2 Copyright (C) 2004 Parallel Realities
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include "game.h"
22 
medalWorker(void * data)23 int medalWorker(void *data)
24 {
25 	char *tname = (char*)data;
26 
27 	SDL_mutexP(medalServer.lock);
28 
29 	int type = medalServer.postMedal(tname);
30 
31 	while (!graphics.canShowMedalMessage())
32 	{
33 		SDL_Delay(100);
34 	}
35 
36 	SDL_Delay(100);
37 
38 	if (type >= 1 && type <= 3)
39 	{
40 		audio.playSound(SND_ITEM, 0);
41 		graphics.showMedalMessage(type, medalServer.getMessage());
42 
43 		if (medalServer.hasRuby())
44 		{
45 			while (!graphics.canShowMedalMessage())
46 			{
47 				SDL_Delay(100);
48 			}
49 
50 			SDL_Delay(100);
51 
52 			audio.playSound(SND_ITEM, 0);
53 			graphics.showMedalMessage(4, medalServer.getRubyMessage());
54 		}
55 	}
56 
57 	SDL_mutexV(medalServer.lock);
58 
59 	delete tname;
60 
61 	return type;
62 }
63 
presentPlayerMedal(const char * tname)64 void presentPlayerMedal(const char *tname)
65 {
66 	// Copy the input, so that threading
67 	// doesn't trip us up!
68 	char *data = new char[128];
69 	strcpy(data, tname);
70 
71 	SDL_Thread *thread = SDL_CreateThread(medalWorker, (void*)data);
72 
73 	if (thread == NULL)
74 	{
75 		printf("Unable to create thread: %s\n", SDL_GetError());
76 		printf("Calling medal server directly\n");
77 		medalWorker((void*)data);
78 		return;
79 	}
80 }
81 
addScore(int amount)82 void addScore(int amount)
83 {
84 	if (gameData.skill > MODE_EASY && gameData.skill < MODE_NIGHTMARE)
85 	{
86 		if (gameData.score < 1000000 && gameData.score + amount >= 1000000)
87 		{
88 			presentPlayerMedal("VK_Score1000000");
89 		}
90 		else if (gameData.score < 500000 && gameData.score + amount >= 500000)
91 		{
92 			presentPlayerMedal("VK_Score500000");
93 		}
94 		else if (gameData.score < 250000 && gameData.score + amount >= 250000)
95 		{
96 			presentPlayerMedal("VK_Score250000");
97 		}
98 	}
99 
100 	gameData.score += amount;
101 }
102 
showInGameOptions()103 int showInGameOptions()
104 {
105 	float brightness;
106 
107 	engine.flushInput();
108 	engine.clearInput();
109 
110 	if (!engine.loadWidgets("data/inGameWidgets"))
111 		graphics.showErrorAndExit(ERR_FILE, "data/inGameWidgets");
112 
113 	int cont, options, quit, quitno, quityes, back;
114 	cont = options = quit = quitno = quityes = back = 0;
115 
116 	engine.setWidgetVariable("fullscreen", &engine.fullScreen);
117 	engine.setWidgetVariable("sound", &gameData.soundVolume);
118 	engine.setWidgetVariable("music", &gameData.musicVolume);
119 	engine.setWidgetVariable("gamma", &gameData.gamma);
120 	engine.setWidgetVariable("back", &back);
121 
122 	engine.setWidgetVariable("continue", &cont);
123 	engine.setWidgetVariable("options", &options);
124 	engine.setWidgetVariable("quit", &quit);
125 
126 	engine.setWidgetVariable("quitno", &quitno);
127 	engine.setWidgetVariable("quityes", &quityes);
128 	engine.showWidgetGroup("quitconf", false);
129 	engine.showWidgetGroup("gameoptions", true);
130 	engine.showWidgetGroup("options", false);
131 
132 	engine.highlightWidget("continue");
133 
134 	engine.flushInput();
135 	engine.clearInput();
136 
137 	graphics.fade(210);
138 
139 	graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
140 	drawWidgets();
141 
142 	while (true)
143 	{
144 		graphics.updateScreen();
145 		engine.getInput();
146 
147 		if (engine.keyState[SDLK_ESCAPE])
148 		{
149 			engine.keyState[SDLK_ESCAPE] = 0;
150 			break;
151 		}
152 
153 		if (engine.processWidgets())
154 		{
155 			if (engine.widgetChanged("sound"))
156 				audio.setSoundVolume(gameData.soundVolume);
157 
158 			if (engine.widgetChanged("music"))
159 				audio.setMusicVolume(gameData.musicVolume);
160 
161 			if (engine.widgetChanged("fullscreen"))
162 				SDL_WM_ToggleFullScreen(graphics.screen);
163 
164 			if (engine.widgetChanged("gamma"))
165 			{
166 				brightness = gameData.gamma;
167 				brightness /= 10;
168 				SDL_SetGamma(brightness, brightness, brightness);
169 			}
170 
171 			graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
172 			drawWidgets();
173 		}
174 
175 		if (cont)
176 			break;
177 
178 		if (options)
179 		{
180 			options = 0;
181 			engine.highlightWidget("fullscreen");
182 			engine.showWidgetGroup("gameoptions", false);
183 			engine.showWidgetGroup("options", true);
184 			graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
185 			drawWidgets();
186 		}
187 
188 		if (back)
189 		{
190 			back = 0;
191 			engine.highlightWidget("continue");
192 			engine.showWidgetGroup("gameoptions", true);
193 			engine.showWidgetGroup("options", false);
194 			graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
195 			drawWidgets();
196 		}
197 
198 		if (quitno)
199 		{
200 			engine.highlightWidget("continue");
201 			engine.showWidgetGroup("gameoptions", true);
202 			engine.showWidgetGroup("quitconf", false);
203 			graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
204 			drawWidgets();
205 			quitno = 0;
206 		}
207 
208 		if (quityes)
209 			return 1;
210 
211 		if (quit)
212 		{
213 			engine.showWidgetGroup("options", false);
214 			engine.showWidgetGroup("gameoptions", false);
215 			engine.showWidgetGroup("quitconf", true);
216 			engine.highlightWidget("quitno");
217 
218 			graphics.drawRect(200, 150, 400, 300, graphics.black, graphics.white, graphics.screen);
219 			drawWidgets();
220 			quit = 0;
221 		}
222 	}
223 
224 	return 0;
225 }
226 
GameOver()227 void GameOver()
228 {
229 	audio.stopMusic();
230 
231 	if (engine.useAudio)
232 	{
233 		for (int i = 0 ; i < 8 ; i++)
234 		{
235 			Mix_HaltChannel(i);
236 		}
237 	}
238 
239 	int x = 0;
240 	int y = 0;
241 
242 	SDL_Rect r;
243 
244 	for (int i = 0 ; i < 100 ; i++)
245 	{
246 		r.x = x;
247 		r.y = y;
248 		r.w = 80;
249 		r.h = 60;
250 
251 		if (SDL_BlitSurface(graphics.screen, &r, graphics.tile[i], NULL))
252 			graphics.showErrorAndExit("Game Over section didn't work", "");
253 
254 		x += 80;
255 		if (x == 800)
256 		{
257 			x = 0;
258 			y += 60;
259 		}
260 	}
261 
262 	x = y = 0;
263 
264 	float tx[100];
265 	float ty[100];
266 	float dx[100];
267 	float dy[100];
268 
269 	for (int i = 0 ; i < 100 ; i++)
270 	{
271 		tx[i] = x;
272 		ty[i] = y;
273 
274 		x += 80;
275 		if (x == 800)
276 		{
277 			x = 0;
278 			y += 60;
279 		}
280 
281 		dx[i] = 0.00 + Math::rrand(-300, 300);
282 		if (dx[i])
283 			dx[i] /= 100;
284 
285 		dy[i] = 0.00 + Math::rrand(-300, 300);
286 		if (dy[i])
287 			dy[i] /= 100;
288 	}
289 
290 	graphics.clearScreen(graphics.black);
291 	graphics.drawString(400, 300, TXT_CENTERED, graphics.screen, "Game Over");
292 
293 	for (int i = 0 ; i < 100 ; i++)
294 	{
295 		tx[i] += dx[i];
296 		ty[i] += dy[i];
297 		graphics.blit(graphics.tile[i], (int)tx[i], (int)ty[i], graphics.screen, false);
298 	}
299 
300 	audio.playSound(SND_DIRDESTROYED6, 0);
301 
302 	graphics.delay(250);
303 
304 	audio.playSound(SND_GAMEOVER, 0);
305 
306 	graphics.delay(1000);
307 
308 	unsigned int then = SDL_GetTicks() + 6000;
309 
310 	graphics.setFontSize(4);
311 	graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
312 
313 	engine.resetTimeDifference();
314 
315 	audio.playSound(SND_DIRDESTROYED3, 1);
316 
317 	while (true)
318 	{
319 		engine.doTimeDifference();
320 		graphics.updateScreen();
321 		engine.getInput();
322 
323 		graphics.clearScreen(graphics.black);
324 		graphics.drawString(400, 300, TXT_CENTERED, graphics.screen, "Game Over");
325 
326 		for (int i = 0 ; i < 100 ; i++)
327 		{
328 			graphics.blit(graphics.tile[i], (int)tx[i], (int)ty[i], graphics.screen, false);
329 			tx[i] += (dx[i] * engine.getTimeDifference());
330 			ty[i] += (dy[i] * engine.getTimeDifference());
331 		}
332 
333 		if (SDL_GetTicks() > then)
334 			break;
335 	}
336 }
337 
doGameStuff()338 void doGameStuff()
339 {
340 	engine.doTimeDifference();
341 	graphics.updateScreen();
342 	engine.getInput();
343 
344 	graphics.drawBackground();
345 	doDirectories();
346 	doItems();
347 	doViruses();
348 	doParticles();
349 
350 	if (gameData.skill < 3)
351 		for (int i = 0 ; i < 4 ; i++)
352 			graphics.blit(gameData.base[i].image, gameData.base[i].x, gameData.base[i].y, graphics.screen, true);
353 
354 	graphics.blit(graphics.infoBar, 0, 0, graphics.screen, false);
355 
356 	graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
357 	graphics.setFontSize(0);
358 	graphics.drawString(10, 10, TXT_LEFT, graphics.screen, "Score: %.7d", gameData.score);
359 	graphics.drawString(789, 10, TXT_RIGHT, graphics.screen, "Round: %d", gameData.level);
360 
361 	graphics.drawString(265, 10, TXT_RIGHT, graphics.screen, "Kernel Power");
362 	graphics.drawRect(275, 11, 152, 12, graphics.black, graphics.white, graphics.screen);
363 	if (gameData.kernelPower > 0)
364 	{
365 		if (gameData.kernelPower > 150)
366 			graphics.drawRect(276, 12, ((int)gameData.kernelPower / 2), 10, graphics.green, graphics.screen);
367 		else if (gameData.kernelPower > 50)
368 			graphics.drawRect(276, 12, ((int)gameData.kernelPower / 2), 10, graphics.yellow, graphics.screen);
369 		else
370 			graphics.drawRect(276, 12, ((int)gameData.kernelPower / 2), 10, graphics.red, graphics.screen);
371 	}
372 
373 	graphics.drawString(515, 10, TXT_LEFT, graphics.screen, "Thread Blockers: %d", gameData.threadStops);
374 }
375 
doRoundClear()376 void doRoundClear()
377 {
378 	if (engine.useAudio)
379 	{
380 		Mix_HaltChannel(6);
381 		Mix_HaltChannel(7);
382 		Mix_ResumeMusic();
383 	}
384 
385 	Sprite *targeter = graphics.getSprite("Targeter", true);
386 
387 	unsigned int now;
388 	unsigned int info = 0;
389 
390 	int bonus = 0;
391 
392 	bonus = gameData.roundVirusesKilled;
393 
394 	if (gameData.roundFilesLost)
395 	{
396 		bonus /= gameData.roundFilesLost;
397 	}
398 
399 	bonus *= (gameData.activeDirs * 10);
400 
401 	unsigned int then = SDL_GetTicks() + 2000;
402 
403 	if (gameData.level + 1 == 5)
404 	{
405 		presentPlayerMedal("VK_Round5");
406 	}
407 	else if (gameData.level + 1 == 10)
408 	{
409 		presentPlayerMedal("VK_Round10");
410 	}
411 	else if (gameData.level + 1 == 15)
412 	{
413 		presentPlayerMedal("VK_Round15");
414 	}
415 	else if (gameData.level + 1 == 20)
416 	{
417 		presentPlayerMedal("VK_Round20");
418 	}
419 
420 	while (true)
421 	{
422 		doGameStuff();
423 
424 		now = SDL_GetTicks();
425 
426 		if (now > then + 500)
427 		{
428 			graphics.fade(210);
429 		}
430 
431 		if (now > then + 1000)
432 		{
433 			info = 1;
434 		}
435 
436 		if (now > then + 3000)
437 		{
438 			info = 2;
439 		}
440 
441 		if (now > then + 4000)
442 		{
443 			info = 3;
444 		}
445 
446 		if (now > then + 5000)
447 		{
448 			break;
449 		}
450 
451 		if (info == 1)
452 		{
453 			graphics.setFontSize(4);
454 			graphics.drawString(400, 100, TXT_CENTERED, graphics.screen, "Round #%d Clear", gameData.level);
455 			graphics.setFontSize(2);
456 
457 			graphics.drawString(400, 200, TXT_RIGHT, graphics.screen, "Bonus");
458 			graphics.drawString(400, 250, TXT_RIGHT, graphics.screen, "Viruses Destroyed");
459 			graphics.drawString(400, 300, TXT_RIGHT, graphics.screen, "Files Lost");
460 			graphics.drawString(400, 350, TXT_RIGHT, graphics.screen, "Directories Lost");
461 			graphics.drawString(400, 400, TXT_RIGHT, graphics.screen, "Items Collected");
462 			graphics.drawString(400, 450, TXT_RIGHT, graphics.screen, "Biggest Chain");
463 
464 			if (bonus > 0)
465 			{
466 				graphics.drawString(430, 200, TXT_LEFT, graphics.screen, "%d", bonus);
467 			}
468 			else
469 			{
470 				graphics.drawString(430, 200, TXT_LEFT, graphics.screen, "None");
471 			}
472 
473 			graphics.drawString(430, 250, TXT_LEFT, graphics.screen, "%.4d", gameData.roundVirusesKilled);
474 			graphics.drawString(430, 300, TXT_LEFT, graphics.screen, "%.4d", gameData.roundFilesLost);
475 			graphics.drawString(430, 350, TXT_LEFT, graphics.screen, "%.4d", gameData.roundDirsLost);
476 			graphics.drawString(430, 400, TXT_LEFT, graphics.screen, "%.4d", gameData.roundItemsCollected);
477 			graphics.drawString(430, 450, TXT_LEFT, graphics.screen, "%.4d", gameData.roundBiggestChain);
478 		}
479 		else if (info == 3)
480 		{
481 			graphics.setFontSize(4);
482 			graphics.drawString(400, 270, TXT_CENTERED, graphics.screen, "Round #%d", (gameData.level + 1));
483 			graphics.drawString(400, 320, TXT_CENTERED, graphics.screen, "READY!");
484 		}
485 
486 		graphics.blit(targeter->getCurrentFrame(), engine.getMouseX(), engine.getMouseY(), graphics.screen, true);
487 
488 	}
489 
490 	engine.resetTimeDifference();
491 
492 	addScore(bonus);
493 }
494 
doGame()495 int doGame()
496 {
497 	graphics.clearScreen(graphics.black);
498 	graphics.delay(500);
499 
500 	if (gameData.skill != MODE_ULTIMATE)
501 	{
502 		audio.loadMusic("music/DCC_Psychedhelic.mod");
503 	}
504 	else
505 	{
506 		audio.loadMusic("music/DarkAngel.mod");
507 	}
508 
509 	loadRandomBackground();
510 
511 	Sprite *targeter = graphics.getSprite("Targeter", true);
512 
513 	gameData.clear();
514 
515 	setupActiveDirectories(4);
516 
517 	gameData.activeDirs = 4;
518 
519 	unsigned int gameOverWait = 0;
520 
521 	float virusSpawn = 100 * Math::rrand(2, 4);
522 	float itemSpawnTime = 100 * Math::rrand(ITEM_MINWAIT, ITEM_MAXWAIT);
523 
524 	unsigned int roundTime = 15;
525 	unsigned int minViruses = 1 + (1 * gameData.skill);
526 	unsigned int maxViruses = 2 + (2 * gameData.skill);
527 
528 	bool addMoreViruses = true;
529 
530 	audio.playMusic();
531 
532 	unsigned int green;
533 	float time = SDL_GetTicks();
534 	unsigned int lastTime = (int)time + (roundTime * 100);
535 	unsigned int now;
536 
537 	bool playingBeamSound = false;
538 
539 	engine.clearInput();
540 	engine.flushInput();
541 
542 	gameData.resetForNextRound();
543 
544 	doGameStuff();
545 	graphics.fade(210);
546 	graphics.setFontSize(4);
547 	graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
548 
549 	if (gameData.skill < 3)
550 	{
551 		graphics.drawString(400, 270, TXT_CENTERED, graphics.screen, "Round #%d", gameData.level);
552 		graphics.drawString(400, 320, TXT_CENTERED, graphics.screen, "READY!");
553 	}
554 	else if (gameData.skill == 3)
555 	{
556 		graphics.drawString(400, 270, TXT_CENTERED, graphics.screen, "Nightmare Mode");
557 		graphics.drawString(400, 320, TXT_CENTERED, graphics.screen, "Survive as long as you can!", gameData.level);
558 	}
559 	else
560 	{
561 		graphics.drawString(400, 270, TXT_CENTERED, graphics.screen, "The Ultimate Nightmare");
562 		graphics.drawString(400, 320, TXT_CENTERED, graphics.screen, "Good Luck!", gameData.level);
563 	}
564 
565 	graphics.delay(2000);
566 
567 	addViruses(minViruses);
568 
569 	engine.resetTimeDifference();
570 
571 	while (true)
572 	{
573 		now = SDL_GetTicks();
574 
575 		if (gameData.threadStopTimer != 0)
576 		{
577 			gameData.threadStopTimer -= (1 * engine.getTimeDifference());
578 
579 			if (gameData.threadStopTimer <= 0)
580 			{
581 				gameData.threadStopTimer = 0;
582 
583 				if (engine.useAudio)
584 				{
585 					Mix_HaltChannel(6);
586 					Mix_ResumeMusic();
587 				}
588 			}
589 		}
590 
591 		doGameStuff();
592 
593 		graphics.blit(targeter->getCurrentFrame(), engine.getMouseX(), engine.getMouseY(), graphics.screen, true);
594 
595 		if (engine.mouseLeft)
596 		{
597 			if (gameData.kernelPower > 0)
598 			{
599 				if (gameData.threadStopTimer == 0)
600 				{
601 					gameData.kernelPower -= (.4 * engine.getTimeDifference());
602 				}
603 
604 				green = SDL_MapRGB(graphics.screen->format, Math::rrand(0, 100), Math::rrand(0, 255), 0);
605 
606 				graphics.drawLine(0, 599, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
607 				graphics.drawLine(1, 598, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
608 				graphics.drawLine(2, 597, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
609 				graphics.drawLine(3, 596, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
610 
611 				graphics.drawLine(799, 599, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
612 				graphics.drawLine(798, 598, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
613 				graphics.drawLine(797, 597, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
614 				graphics.drawLine(796, 596, engine.getMouseX(), engine.getMouseY(), green, graphics.screen);
615 
616 				doVirusBulletCollisions();
617 				doBulletItemCollisions();
618 
619 				addBulletParticle();
620 
621 				Math::limitFloat(&gameData.kernelPower, 0, 300);
622 
623 				if (!playingBeamSound)
624 				{
625 					audio.playSound(SND_KERNALBEAM, 7, -1);
626 					playingBeamSound = true;
627 				}
628 			}
629 			else
630 			{
631 				if (engine.useAudio)
632 				{
633 					Mix_HaltChannel(7);
634 				}
635 			}
636 		}
637 		else
638 		{
639 			gameData.kernelPower += (.1 * engine.getTimeDifference());
640 			Math::limitFloat(&gameData.kernelPower, 0, 300);
641 
642 			if (engine.useAudio)
643 			{
644 				Mix_HaltChannel(7);
645 			}
646 
647 			playingBeamSound = false;
648 		}
649 
650 		if ((engine.mouseRight) && (gameData.threadStops > 0))
651 		{
652 			if (gameData.threadStopTimer == 0)
653 			{
654 				gameData.threadStopTimer = 600;
655 				engine.mouseRight = 0;
656 
657 				if (engine.useAudio)
658 				{
659 					Mix_PauseMusic();
660 				}
661 
662 				audio.playSound(SND_CLOCK, 6, 2);
663 				gameData.threadStops--;
664 			}
665 		}
666 
667 		if (addMoreViruses)
668 		{
669 			virusSpawn -= (1 * engine.getTimeDifference());
670 
671 			if ((virusSpawn <= 0) && (gameData.threadStopTimer == 0))
672 			{
673 				virusSpawn = 100 * Math::rrand(2, 4);
674 				virusSpawn -= (gameData.level * 5);
675 				Math::limitFloat(&virusSpawn, 25, 400);
676 				addViruses(Math::rrand(minViruses, maxViruses));
677 			}
678 		}
679 		else if ((gameData.activeViruses == 0) && (gameData.activeDirs > 0))
680 		{
681 			doRoundClear();
682 
683 			gameData.level++;
684 
685 			if ((gameData.level % 2) == 0)
686 			{
687 				roundTime += 5;
688 			}
689 			else
690 			{
691 				maxViruses += 2;
692 			}
693 
694 			lastTime = (int)time;
695 
696 			minViruses += 2;
697 
698 			time = lastTime = now;
699 			lastTime += (roundTime * 100);
700 
701 			gameData.resetForNextRound();
702 			addViruses(minViruses);
703 
704 			addMoreViruses = true;
705 		}
706 
707 		if (gameData.threadStopTimer == 0)
708 		{
709 			time += (1 * engine.getTimeDifference());
710 		}
711 
712 		itemSpawnTime -= (1 * engine.getTimeDifference());
713 
714 		if (itemSpawnTime <= 0)
715 		{
716 			addItem();
717 
718 			if (gameData.skill < 3)
719 			{
720 				itemSpawnTime = 100 * Math::rrand(ITEM_MINWAIT, ITEM_MAXWAIT);
721 			}
722 			else
723 			{
724 				itemSpawnTime = 100 * Math::rrand(ITEM_MINWAIT * 2, ITEM_MAXWAIT * 2);
725 			}
726 		}
727 
728 		#if !USEPAK
729 		//if (time < lastTime)
730 			//graphics.drawString(10, 50, TXT_LEFT, graphics.screen, "Round Time: %d ", (lastTime - time) / 100);
731 
732 		//if (now < gameData.itemSpawnTime)
733 			//graphics.drawString(10, 70, TXT_LEFT, graphics.screen, "Item Time: %d ", (gameData.itemSpawnTime - now) / 100);
734 		#endif
735 
736 		if (time >= lastTime)
737 		{
738 			if (gameData.skill < 3)
739 			{
740 				addMoreViruses = false;
741 			}
742 			else
743 			{
744 				gameData.level++;
745 
746 				maxViruses += 2 + (2 * gameData.skill);
747 
748 				lastTime = (int)time;
749 
750 				if ((gameData.level % 3) == 0)
751 				{
752 					minViruses += 2 + (2 * gameData.skill);
753 				}
754 
755 				time = lastTime = now;
756 				lastTime += (roundTime * 100);
757 			}
758 		}
759 
760 		if (gameData.activeDirs > 0)
761 		{
762 			if (gameData.skill >= 3)
763 			{
764 				gameData.score += (int)(50 * engine.getTimeDifference());
765 			}
766 		}
767 
768 		if (gameData.activeDirs == 0)
769 		{
770 			if (gameOverWait == 0)
771 				gameOverWait = SDL_GetTicks() + 3000;
772 
773 			if (now > gameOverWait)
774 				break;
775 		}
776 
777 		engine.doPause();
778 
779 		if ((engine.paused) && (gameData.activeDirs > 0))
780 		{
781 			graphics.fade(210);
782 			graphics.setFontSize(4);
783 			graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
784 			graphics.drawString(400, 300, TXT_CENTERED, graphics.screen, "PAUSED");
785 			audio.pause();
786 		}
787 
788 		while (engine.paused)
789 		{
790 			engine.getInput();
791 			engine.doPause();
792 			graphics.updateScreen();
793 
794 			if (!engine.paused)
795 			{
796 				audio.resume();
797 				engine.resetTimeDifference();
798 			}
799 		}
800 
801 		if (engine.keyState[SDLK_ESCAPE])
802 		{
803 			if (engine.useAudio)
804 			{
805 				for (int i = 0 ; i < 8 ; i++)
806 				{
807 					Mix_HaltChannel(i);
808 				}
809 			}
810 
811 			if (showInGameOptions())
812 			{
813 				if (engine.useAudio)
814 				{
815 					audio.stopMusic();
816 					for (int i = 0 ; i < 8 ; i++)
817 					{
818 						Mix_HaltChannel(i);
819 					}
820 				}
821 				graphics.clearScreen(graphics.black);
822 				graphics.delay(500);
823 				gameData.virusList.clear();
824 				return SECTION_TITLE;
825 			}
826 
827 			audio.resume();
828 			engine.resetTimeDifference();
829 		}
830 	}
831 
832 	if (gameData.score <= -100000)
833 	{
834 		presentPlayerMedal("VK_NegativeScore");
835 	}
836 
837 	GameOver();
838 
839 	if (gameData.skill == MODE_HARD)
840 	{
841 		if (gameData.nightmareCount > 0)
842 		{
843 			if (gameData.nightmareCount > 50)
844 			{
845 				gameData.nightmareCount -= gameData.level;
846 				Math::limitInt(&gameData.nightmareCount, 50, 100);
847 			}
848 			else
849 			{
850 				gameData.nightmareCount -= gameData.level;
851 				Math::limitInt(&gameData.nightmareCount, 0, 100);
852 			}
853 
854 			debug(("Nightmare Count is now %d\n", gameData.nightmareCount));
855 
856 			if (gameData.nightmareCount == 50)
857 			{
858 				presentPlayerMedal("VK_NightmareMode");
859 
860 				graphics.clearScreen(graphics.black);
861 				graphics.delay(500);
862 				graphics.setFontSize(4);
863 				graphics.setFontColor(0xff, 0xff, 0x00, 0x00, 0x00, 0x00);
864 				audio.playSound(SND_POWERUP, 0);
865 				graphics.drawString(400, 300, TXT_CENTERED, graphics.screen, "Nightmare Mode is now Available");
866 				graphics.delay(3000);
867 			}
868 			else if (gameData.nightmareCount == 0)
869 			{
870 				presentPlayerMedal("VK_UltimateNightmareMode");
871 
872 				graphics.clearScreen(graphics.black);
873 				graphics.delay(500);
874 				graphics.setFontSize(4);
875 				graphics.setFontColor(0x00, 0xff, 0xff, 0x00, 0x00, 0x00);
876 				audio.playSound(SND_POWERUP, 0);
877 				graphics.drawString(400, 300, TXT_CENTERED, graphics.screen, "Ultimate Nightmare Mode is now Available");
878 				graphics.delay(3000);
879 			}
880 		}
881 	}
882 
883 	graphics.clearScreen(graphics.black);
884 	graphics.delay(500);
885 
886 	gameData.virusList.clear();
887 
888 	return SECTION_HIGHSCORE;
889 }
890