1 /**
2  * This is an example of program that uses cake library.
3  * In this file, the coder has to write the main function, create the window
4  * (for instance by using GLUT like here), define the keys, manage the mouse
5  * behaviour, order the map loading, and make the main loop for update and redraw.
6  */
7 
8 #ifdef WIN32
9 	#pragma comment(lib, "cake/glsetup/lib/glut32.lib")		// Link for GLUT 3.7.6
10 	#ifdef _DEBUG
11 		#pragma comment(lib, "obj_files/caked.lib")			// Link for cake library
12 	#else
13 		#pragma comment(lib, "obj_files/cake.lib")			// Link for cake library
14 	#endif
15 #endif
16 
17 #include "cake/alias.h"									// aliases
18 #include "cake/app.h"									// application
19 #include "cake/cake.h"									// main cake header
20 #include "cake/client.h"								// clients
21 #include "cake/commands.h"								// commands
22 #include "cake/console.h"								// console
23 #include "cake/definitions.h"							// cake definitions
24 #include "cake/demo.h"									// demo support
25 #include "cake/files.h"									// files support
26 #include "cake/framework.h"								// framework
27 #include "cake/logfile.h"								// logfile
28 #include "cake/math.h"									// math funcs
29 #include "cake/mem.h"									// memory
30 #include "cake/overlay.h"								// overlay
31 #include "cake/render.h"								// render
32 #include "cake/sound.h"									// sound/music support
33 #include "cake/system.h"								// exceptions
34 #include "cake/timer.h"									// timer
35 #include "cake/vars.h"									// variables
36 #include "cake/world.h"									// world
37 #include "cake/glsetup/glut.h"							// OpenGL + GLUT
38 
39 #define DEFAULT_MUSIC	"music/sonic1.wav"				// default music when no map is loaded
40 
41 //-----------------------------------------------------------------------------
42 // Variables
43 //-----------------------------------------------------------------------------
44 
45 // App and world stuff
46 App* app = NULL;										// main application
47 int preview = -1;										// map preview state
48 
49 // clients stuff
50 int nstartpos, currstartpos;							// client start pos
51 
52 // inputs
53 Var invertMouseX("invertMouseX", -1, VF_PERSISTENT);	// mouse x inversion
54 Var invertMouseY("invertMouseY", -1, VF_PERSISTENT);	// mouse y inversion
55 struct { int x, y; } mousepos;							// mouse x and y position
56 bool AutoCenterMouse = true;							// the mouse is always centered
57 bool lButton = false, mButton = false, rButton = false;	// mouse buttons state
58 int dx, dy;												// mouse rot backup
59 Var mouse_speed("mouse_speed", 0.5f, VF_PERSISTENT);	// camera rotation speed (if camera is rotated with mouse)
60 Var zoomspeed("zoomspeed", 300, VF_PERSISTENT);			// zoom speed
61 int lastkey;											// last key pressed backup
62 typedef enum { KEYUP = 0, KEYDOWN = 1 } key_state;		// keyboard key state
63 key_state up, down, left, right, pgnup, pgndown, zoom;	// keys that use keystate system (to avoid the dependance to keyboard repetition speed)
64 
65 // console
66 int histLine;											// commands history scrolling value
67 Var consoleKey("consoleKey", 96, VF_PERSISTENT);		// key used for console opening/closing
68 int tabmode = 1;										// console tabulation mode
69 
70 // window
71 int window_index;										// window index
72 int width, height;										// window width and height
73 int toppos, leftpos;									// window position (top and pos) - not used
74 int freq;												// window frequency
75 int colorbits;											// window color bits (8, 16, 24 or 32)
76 bool fullscr;											// is window in fullscreen mode
77 int backupWidth, backupHeight;							// backup used for maximisation/reduce
78 #define nwidths 17
79 #define nheights 17
80 #define ncolors 5
81 #define nfreqs 11
82 int widths[nwidths] = {320, 400, 480, 512, 640, 720, 768, 800, 856, 960, 1024, 1152, 1200, 1280, 1600, 1920, 2048};
83 int heights[nheights] = {200, 240, 300, 360, 384, 400, 480, 576, 600, 720, 768, 864, 900, 960, 1080, 1200, 1536};
84 int colors[ncolors] = {8, 15, 16, 24, 32};
85 int freqs[nfreqs] = {43, 50, 56, 60, 70, 72, 75, 85, 95, 100, 120};
86 
87 //-----------------------------------------------------------------------------
88 // Functions declarations
89 //-----------------------------------------------------------------------------
90 
91 void AddCommands(void);
92 void RegisterVariables(void);
93 void Keyboard(unsigned char key, int x, int y);
94 void KeyboardUp(unsigned char key, int x, int y);
95 void KeyboardSpec(int key, int x, int y);
96 void KeyboardSpecUp(int key, int x, int y);
97 void MouseClic(int button, int state, int x, int y);
98 void MouseMove(int x, int y);
99 void MouseMovePassive(int x, int y);
100 static void Draw(void);
101 void Reshape(int w, int h);
102 void Idle(void);
103 void Init();
104 void ParseArgs(int argc, char *argv[]);
105 void Shut(int status);
106 int ScreenShot(char *fName, int hideconsole = 1);
107 void CheckForAllAvailableResolutions(void);
108 void ToggleFullScreen(void);
109 
110 //-----------------------------------------------------------------------------
111 // Commands declarations
112 //-----------------------------------------------------------------------------
113 void cmd_quit(int argc, char *argv[]);
114 void cmd_load(int argc, char *argv[]);
115 void cmd_reload(int argc, char *argv[]);
116 void cmd_defineviewport(int argc, char *argv[]);
117 void cmd_noclip(int argc, char *argv[]);
118 void cmd_lockfrustum(int argc, char *argv[]);
119 void cmd_unload(int argc, char *argv[]);
120 void cmd_record(int argc, char *argv[]);
121 void cmd_stopdemo(int argc, char *argv[]);
122 void cmd_demo(int argc, char *argv[]);
123 void cmd_demodump(int argc, char *argv[]);
124 void cmd_shaderpreview(int argc, char *argv[]);
125 void cmd_resolutions(int argc, char *argv[]);
126 void cmd_screenshot(int argc, char *argv[]);
127 void cmd_fontsize (int argc, char *argv[]);
128 void cmd_tabmode (int argc, char *argv[]);
129 void cmd_togglemousecenter (int argc, char *argv[]);
130 void cmd_preview (int argc, char *argv[]);
131 void cmd_credits(int argc, char *argv[]);
132 void cmd_speed(int argc, char *argv[]);
133 void cmd_fov(int argc, char *argv[]);
134 void cmd_zoomlimit(int argc, char *argv[]);
135 void cmd_tpl(int argc, char *argv[]);
136 void cmd_acceleration(int argc, char *argv[]);
137 void cmd_friction(int argc, char *argv[]);
138 void cmd_getpos(int argc, char *argv[]);
139 void cmd_getrot(int argc, char *argv[]);
140 void cmd_setpos(int argc, char *argv[]);
141 void cmd_setrot(int argc, char *argv[]);
142 void cmd_addpos(int argc, char *argv[]);
143 void cmd_addangle(int argc, char *argv[]);
144 void cmd_getfps(int argc, char *argv[]);
145 void cmd_setnclients(int argc, char *argv[]);
146 void cmd_entityreport(int argc, char *argv[]);
147 void cmd_bspreport(int argc, char *argv[]);
148 void cmd_loadplayer(int argc, char *argv[]);
149 
150 // Save a screenshot in an output file
ScreenShot(char * fName,int hideconsole)151 int ScreenShot(char *fName, int hideconsole)
152 {
153 	unsigned char *fBuffer3 = (unsigned char*) cake_malloc(3*width*height*sizeof(unsigned char), "Main::ScreenShot.fBuffer3");
154 	if (!fBuffer3) return 0;								// no memory allocated for image data
155 
156 	memset(fBuffer3, 0, 3*width*height*sizeof(unsigned char));
157 
158 	char fBMPName[255];
159 	strncpy(fBMPName, fName, 255);
160 	_strlwr(fBMPName);										// makes the filename lowercase
161 	if (strcmp(&fBMPName[strlen(fBMPName)-4], ".bmp"))		// add a ".bmp" extension if not already present
162 		sprintf(fBMPName, "%s.bmp", fBMPName);
163 
164 	enum_ConsoleStates consolestate = gConsole->GetState();
165 	if (hideconsole) gConsole->SetState(CLOSED);
166 
167 	Draw();
168 	glutSwapBuffers();
169 
170 	// read our image data from the frame buffer
171 	glReadPixels(0, 0,
172 		width, height,
173 		GL_RGB,
174 		GL_UNSIGNED_BYTE,
175 		fBuffer3);
176 
177 	// write the image data to a .bmp file
178 	if (!WriteBitmapFile(fBMPName, width, height, 3, fBuffer3)) return 0;
179 
180 	cake_free(fBuffer3);
181 
182 	gConsole->SetState(consolestate);
183 
184 	return 1;
185 }
186 
187 // Displays a list of all available resolutions
CheckForAllAvailableResolutions(void)188 void CheckForAllAvailableResolutions(void)
189 {
190 	char resolution[128];
191 
192 	gConsole->Insertln("List of available resolutions :");
193 	gLogFile->OpenFile();
194 
195 	for (int i = 0; i < nwidths; ++i)
196 		for (int j = 0; j < nheights; ++j)
197 			for (int k = 0; k < ncolors; ++k)
198 				for (int l = 0; l < nfreqs; ++l)
199 				{
200 					sprintf(resolution, "%dx%d:%d@%d", widths[i], heights[j], colors[k], freqs[l]);
201 					glutGameModeString(resolution);
202 					if (glutGameModeGet(GLUT_GAME_MODE_POSSIBLE))
203 					{
204 						gConsole->Insertln("%s ", resolution);
205 					}
206 				}
207 	gLogFile->CloseFile();
208 }
209 
210 // Toggles the mode fullscreen/windowed
ToggleFullScreen(void)211 void ToggleFullScreen(void)
212 {
213 	fullscr = !fullscr;
214 	if (fullscr)
215 	{
216 		backupWidth = width;
217 		backupHeight = height;
218 		glutFullScreen();
219 	}
220 	else
221 	{
222 		width = backupWidth;
223 		height = backupHeight;
224 		glutReshapeWindow(width, height);
225 	}
226 }
227 
228 //-----------------------------------------------------------------------------
229 // Keyboard
230 // The following functions manage the keyboard.
231 //-----------------------------------------------------------------------------
Keyboard(unsigned char key,int x,int y)232 void Keyboard(unsigned char key, int x, int y)
233 {
234 	// Console opening/closing
235 	if (key == (unsigned char) consoleKey.ivalue)
236 	{
237 		if (!app->GetWorld()) { beep(); return; }
238 		if (gConsole->ToggleState() == OPENING) histLine = 0;
239 		lastkey = key;
240 		return;
241 	}
242 
243 	// if console is active and opened, keyboard actions are done in the console
244 	if ((gConsole->GetState() == OPEN || gConsole->GetState() == OPENING) && gConsole->isActive)
245 	{
246 		bool do_return = true;
247 		switch (key)
248 		{
249 			case 13:
250 				char ConsoleBufferCommand[CONSOLE_LINELENGTH];
251 				strncpy(ConsoleBufferCommand, gConsole->GetCurrentCommand(), CONSOLE_LINELENGTH);
252 				if (strlen(ConsoleBufferCommand) > 0)
253 				{
254 					histLine = 0;
255 
256 					if (!gCommands->ExecuteCommand(ConsoleBufferCommand))
257 						gConsole->Insertln("\"%s\" : ^5Command not found", ConsoleBufferCommand);
258 				}
259 				break;
260 			case 27:
261 				if (strlen(gConsole->GetCurrentCommand()))
262 					gConsole->ReInitCurrentCommand();
263 				else if (app->GetWorld())
264 				{
265 					gConsole->Close();
266 					gConsole->ReInitCurrentCommand();
267 				}
268 				else do_return = false;
269 				break;
270 			case 8: gConsole->DelChar(); break;
271 			case 9:
272 				if (tabmode)
273 				{
274 					if (lastkey == key)
275 					{
276 						if (glutGetModifiers() == GLUT_ACTIVE_SHIFT)
277 							gCommands->PrevSolution();
278 						else
279 							gCommands->NextSolution();
280 					}
281 					else
282 					{
283 						gCommands->FirstSolution(gConsole->GetCurrentCommand());
284 					}
285 				}
286 				else
287 				{
288 					gCommands->CompleteCommand(gConsole->GetCurrentCommand());
289 				}
290 				break;
291 			default:
292 				gConsole->AddChar((char) key);
293 				break;
294 		}
295 		lastkey = key;
296 		if (do_return) return;
297 	}
298 
299 	// if console is not active, keyboard is attached to engine (or clients camera)
300 	switch (key)
301 	{
302 		case 27:
303 			if (!app->StopDemo()) Shut(0);
304 			break;
305 		case 32:
306 			// zoom
307 			zoom = KEYDOWN;
308 			break;
309 		case 'a':
310 		case 'A':
311 			// move left
312 			left = KEYDOWN;
313 			break;
314 		case 'w':
315 		case 'W':
316 			// move forwards
317 			up = KEYDOWN;
318 			break;
319 		case 'd':
320 		case 'D':
321 			// move right
322 			right = KEYDOWN;
323 			break;
324 		case 's':
325 		case 'S':
326 			// move backwards
327 			down = KEYDOWN;
328 			break;
329 		case 'e':
330 		case 'E':
331 			// move up
332 			pgnup = KEYDOWN;
333 			break;
334 		case 'q':
335 		case 'Q':
336 			// move down
337 			pgndown = KEYDOWN;
338 			break;
339 		case 'f':
340 		case 'F':
341 			// toggle fps display
342 			gVars->SetKeyValue("cg_drawFPS", 1-gVars->IntForKey("cg_drawFPS"));
343 			break;
344 		case 't':
345 		case 'T':
346 			// toggle time display
347 			gVars->SetKeyValue("cg_drawtime", 1-gVars->IntForKey("cg_drawtime"));
348 			break;
349 		case 'G':
350 		case 'g':
351 			// changes wireframe mode
352 			gVars->SetKeyValue("r_grid", 1-gVars->IntForKey("r_grid"));
353 			break;
354 		case 'B':
355 		case 'b':
356 			gVars->SetKeyValue("r_showbbox", 1-gVars->IntForKey("r_showbbox"));
357 			break;
358 		case 'c':
359 		case 'C':
360 			// toggle clear mode
361 			gVars->SetKeyValue("r_clear", 1-gVars->IntForKey("r_clear"));
362 			gConsole->Insertln("r_clear value changed to %d", gVars->IntForKey("r_clear"));
363 			break;
364 		case 'n':
365 		case 'N':
366 			// change current client (has effect only if clients are unlinked)
367 			app->SetCurrentClient((app->GetCurrentClientIndex()+1)%app->GetNumClients());
368 			gConsole->Insertln("Current client : %d", app->GetCurrentClientIndex());
369 			break;
370 		case 'p':
371 		case 'P':
372 			// change start pos for current client
373 			if (!app->GetWorld()) break;
374 			if (app->GetWorld()->GetNumStartPos())
375 			{
376 				if (key == 'P')
377 				{
378 					currstartpos = (currstartpos-1)%app->GetWorld()->GetNumStartPos();
379 					if (currstartpos < 0) currstartpos = app->GetWorld()->GetNumStartPos()-1;
380 				}
381 				else currstartpos = (currstartpos+1)%app->GetWorld()->GetNumStartPos();
382 				app->GetWorld()->SetStartPos(app->GetCurrentClient(), currstartpos);
383 				gConsole->Insertln("using start pos %d/%d for client %d", currstartpos+1, app->GetWorld()->GetNumStartPos(), app->GetCurrentClientIndex());
384 			}
385 			break;
386 		case 'm':
387 		case 'M':
388 			{
389 				Client *client = app->GetCurrentClient();
390 				if (client)
391 				{
392 					client->flying = !client->flying;
393 					gConsole->Insertln("client flying state: %s", client->flying?"ON":"OFF");
394 				}
395 			}
396 			break;
397 		default:
398 			gConsole->Insertln("%d : invalid key", key);
399 			break;
400 	}
401 	lastkey = key;
402 }
403 
404 //-----------------------------------------------------------------------------
405 // KeyboardUp
406 //-----------------------------------------------------------------------------
KeyboardUp(unsigned char key,int x,int y)407 void KeyboardUp(unsigned char key, int x, int y)
408 {
409 	switch (key)
410 	{
411 		case 'a':
412 		case 'A':
413 			left = KEYUP;
414 			break;
415 		case 'w':
416 		case 'W':
417 			up = KEYUP;
418 			break;
419 		case 'd':
420 		case 'D':
421 			right = KEYUP;
422 			break;
423 		case 's':
424 		case 'S':
425 			down = KEYUP;
426 			break;
427 		case 'e':
428 		case 'E':
429 			pgnup = KEYUP;
430 			break;
431 		case 'q':
432 		case 'Q':
433 			pgndown = KEYUP;
434 			break;
435 		case 32:
436 			zoom = KEYUP;
437 			break;
438 		default:
439 			// should not happen
440 			break;
441 	}
442 }
443 
444 //-----------------------------------------------------------------------------
445 // KeyboardSpec
446 //-----------------------------------------------------------------------------
KeyboardSpec(int key,int x,int y)447 void KeyboardSpec(int key, int x, int y)
448 {
449 	// if console is active and onpened
450 	if ((gConsole->GetState() == OPEN ||
451 		 gConsole->GetState() == OPENING) &&
452 		gConsole->isActive)
453 	{
454 		switch (key)
455 		{
456 			case GLUT_KEY_UP:
457 				++histLine;
458 				if (histLine > gCommands->GetNbrCommHistLines())
459 				{
460 					histLine = gCommands->GetNbrCommHistLines();
461 					beep();
462 				}
463 				gConsole->SetCurrentCommand(gCommands->GetHistoryLine(histLine));
464 				break;
465 			case GLUT_KEY_DOWN:
466 				--histLine;
467 				if (histLine < 0)
468 				{
469 					histLine = 0;
470 					beep();
471 				}
472 				gConsole->SetCurrentCommand(gCommands->GetHistoryLine(histLine));
473 				break;
474 			case GLUT_KEY_LEFT:
475 				gConsole->MoveCursor(LEFT);
476 				break;
477 			case GLUT_KEY_RIGHT:
478 				gConsole->MoveCursor(RIGHT);
479 				break;
480 			case GLUT_KEY_HOME:
481 				if (glutGetModifiers() == GLUT_ACTIVE_CTRL) gConsole->ScrollConsole(TOP);
482 				else gConsole->MoveCursor(C_EXTREM_LEFT);
483 				break;
484 			case GLUT_KEY_END:
485 				if (glutGetModifiers() == GLUT_ACTIVE_CTRL) gConsole->ScrollConsole(BOTTOM);
486 				else gConsole->MoveCursor(C_EXTREM_RIGHT);
487 				break;
488 			case GLUT_KEY_PAGE_UP:
489 				gConsole->ScrollConsole(UP);
490 				break;
491 			case GLUT_KEY_PAGE_DOWN:
492 				gConsole->ScrollConsole(DOWN);
493 				break;
494 			default:
495 				// does nothing
496 				break;
497 		}
498 		lastkey = key;
499 		return;
500 	}
501 
502 	histLine = 0;
503 
504 	switch (key)
505 	{
506 		case GLUT_KEY_F4:
507 			gCommands->RepeatLastCommand();
508 			break;
509 		case 100:
510 			left = KEYDOWN;
511 			break;
512 		case 101:
513 			up = KEYDOWN;
514 			break;
515 		case 102:
516 			right = KEYDOWN;
517 			break;
518 		case 103:
519 			down = KEYDOWN;
520 			break;
521 		case 104:
522 			pgnup = KEYDOWN;
523 			break;
524 		case 105:
525 			pgndown = KEYDOWN;
526 			break;
527 		default:
528 			gConsole->Insertln("%d : invalid key", key);
529 			break;
530 	}
531 	lastkey = key;
532 }
533 
534 //-----------------------------------------------------------------------------
535 // KeyboardSpecUp
536 //-----------------------------------------------------------------------------
KeyboardSpecUp(int key,int x,int y)537 void KeyboardSpecUp(int key, int x, int y)
538 {
539 	switch (key)
540 	{
541 		case 100:
542 			left = KEYUP;
543 			break;
544 		case 101:
545 			up = KEYUP;
546 			break;
547 		case 102:
548 			right = KEYUP;
549 			break;
550 		case 103:
551 			down = KEYUP;
552 			break;
553 		case 104:
554 			pgnup = KEYUP;
555 			break;
556 		case 105:
557 			pgndown = KEYUP;
558 			break;
559 		default:
560 			break;
561 	}
562 }
563 
564 //-----------------------------------------------------------------------------
565 // MouseClic
566 // Manage the mouse clics.
567 //-----------------------------------------------------------------------------
MouseClic(int button,int state,int x,int y)568 void MouseClic(int button, int state, int x, int y)
569 {
570 	if (preview >= 0)
571 	{
572 		gFramework->shaders.DeleteShader(preview);
573 		preview = -1;
574 	}
575 
576     switch (button)
577     {
578 		case GLUT_LEFT_BUTTON:
579 			if (state == GLUT_DOWN)
580 			{
581 				lButton = true;
582 				dx = x;
583 				dy = y;
584 			}
585 			else if (state == GLUT_UP) lButton = false;
586 			break;
587 		case GLUT_RIGHT_BUTTON:
588 			if (state == GLUT_DOWN)
589 			{
590 				rButton = true;
591 				dx = x;
592 				dy = y;
593 
594 				Client *client = app->GetCurrentClient();
595 				if (client) client->Jump();
596 			}
597 			else if (state == GLUT_UP) rButton = false;
598 			break;
599 		default:
600 			break;
601 	}
602 }
603 
604 
605 //-----------------------------------------------------------------------------
606 // MouseMove
607 // Clients camera rotation following mouse
608 //-----------------------------------------------------------------------------
MouseMove(int x,int y)609 void MouseMove(int x, int y)
610 {
611 	if (lButton && !fullscr)
612 	{
613 		Client *client = app->GetCurrentClient();
614 		if (client) client->MoveMouseXY((float) (dx-x), (float) (dy-y));
615 
616 		dx = x;
617 		dy = y;
618 	}
619 	else
620 	{
621 		mousepos.x = x;
622 		mousepos.y = y;
623 	}
624 }
625 
626 //-----------------------------------------------------------------------------
627 // MouseMovePassive
628 // Updates the mouse x and y position
629 //-----------------------------------------------------------------------------
MouseMovePassive(int x,int y)630 void MouseMovePassive(int x, int y)
631 {
632 	mousepos.x = x;
633 	mousepos.y = y;
634 }
635 
636 //-----------------------------------------------------------------------------
637 // Draw
638 // Calls the display refresh.
639 //-----------------------------------------------------------------------------
Draw(void)640 static void Draw(void)
641 {
642 	if (!width || !height) return;
643 	gRender->BeginFrame();							// clears the screen and the z buffer
644 
645 	int numclients = app->GetNumClients();
646 
647 	app->DrawWorld();
648 	app->DrawInterface();
649 
650 	if (preview >= 0)
651 	{
652 		gOver->Quad(preview, width-196, height-156, 156, 128);
653 		gFramework->Render();	// used for displaying the gOver with framework shaders (quite tricky, I know !!)
654 	}
655 
656 	gRender->EndFrame();							// flips the screen and force the flushing
657 
658 	glutSwapBuffers();
659 }
660 
661 //-----------------------------------------------------------------------------
662 // Reshape
663 //-----------------------------------------------------------------------------
Reshape(int w,int h)664 void Reshape(int w, int h)
665 {
666 	if (gLogFile) gLogFile->Insert("reshaping to %dx%d\n", w, h);
667 	width = w;
668 	height = h;
669 	gRender->SetWindowSettings(w, h);
670 	if (gConsole) gConsole->Resize(-1, app->GetWorld()?h/2:h);
671 	app->InitClients();
672 
673 	Draw();
674 }
675 
676 //-----------------------------------------------------------------------------
677 // Idle
678 //-----------------------------------------------------------------------------
Idle(void)679 void Idle(void)
680 {
681 	Client *client = app->GetCurrentClient();
682 
683 	if (client)
684 	{
685 		// Updates camera rotation
686 		if (fullscr && AutoCenterMouse)
687 		{
688 			client->MoveMouseXY(invertMouseX.fvalue*(mousepos.x-(float)width /2.f)*mouse_speed.fvalue,
689 								invertMouseY.fvalue*(mousepos.y-(float)height/2.f)*mouse_speed.fvalue);
690 			glutWarpPointer((int)((float)width/2.f), (int)((float)height/2.f));
691 		}
692 
693 		// Updates camera position
694 		if (up == KEYDOWN && down == KEYUP) client->MoveForward();
695 		else if (up == KEYUP && down == KEYDOWN) client->MoveBackward();
696 		if (right == KEYDOWN && left == KEYUP) client->MoveRight();
697 		else if (right == KEYUP && left == KEYDOWN) client->MoveLeft();
698 		if (pgnup == KEYDOWN && pgndown == KEYUP) client->MoveUp();
699 		else if (pgnup == KEYUP && pgndown == KEYDOWN) client->MoveDown();
700 		if (zoom == KEYDOWN) client->Zoom(-zoomspeed.fvalue);
701 		else if (zoom == KEYUP) client->Zoom(zoomspeed.fvalue);
702 	}
703 
704 	glutPostRedisplay();
705 }
706 
707 //-----------------------------------------------------------------------------
708 // Init
709 //-----------------------------------------------------------------------------
Init()710 void Init()
711 {
712 	if (!gRender->Init(glutSwapBuffers)) ThrowException(FATAL_ERROR, "Couldn't initialize render !");
713 
714 	gConsole->Insertln("<br/><b>^6----- Application starts --------------------------------------</b>");
715 
716 	// Initialize the keys
717 	up = down = left = right = pgnup = pgndown = zoom = KEYUP;
718 
719 	// Set window settings
720 	gRender->SetWindowSettings(width, height, colorbits, freq);
721 
722 	// Load console shaders and intialize the console
723 	gConsole->SetFont(gConsole->shaders.AddShader("gfx/2d/bigchars", 0, 0, FACETYPE_MESH), 16, 16);
724 	gConsole->SetBack(gConsole->shaders.AddShader("console", 0, 0, FACETYPE_MESH));
725 	gConsole->Init();
726 
727 	// Load framework shaders
728 	gFramework->SetFont(gFramework->shaders.AddShader("gfx/2d/bigchars", 0, 0, FACETYPE_MESH), NORMAL_CHAR);
729 	gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font1_prop", 0, 0, FACETYPE_MESH), PROPFONT1_CHAR);
730 	gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font1_prop_glo", 0, 0, FACETYPE_MESH), PROPFONT1_GLOW_CHAR);
731 	gFramework->SetFont(gFramework->shaders.AddShader("menu/art/font2_prop", 0, 0, FACETYPE_MESH), PROPFONT2_CHAR);
732 	gFramework->Init();
733 
734 	if (fullscr) glutWarpPointer((int)((float)width/2.f), (int)((float) height/2.f));
735 }
736 
ParseArgs(int argc,char * argv[])737 void ParseArgs(int argc, char *argv[])
738 {
739 	bool displayinfos = true;
740 
741 	gConsole->Insertln("Parsing the command line...");
742 
743 	for (int i = 1; i < argc; ++i)
744 	{
745 		// +map <mapname>
746 		if (!stricmp(argv[i], "+map"))
747 		{
748 			if (++i >= argc)
749 			{
750 				gConsole->Insertln("^1Missing argument for \"+map\" command");
751 				displayinfos = true;
752 			}
753 			else if (argv[i][0] == '+')
754 			{
755 				gConsole->Insertln("^1Invalid argument for \"+map\" command");
756 				displayinfos = true;
757 			}
758 			else if (app->LoadMap(argv[i])) displayinfos = false;
759 			else displayinfos = true;
760 		}
761 
762     // +demo <demoname.demo>
763     if (!stricmp(argv[i], "+demo"))
764     {
765       int j;
766       for (j = 1; j < argc; ++j)
767       {
768         if (!stricmp(argv[j], "+map"))
769         {
770           gConsole->Insertln("^1You cannot use \"+demo\" and \"+map\" simultaneously; \"+demo\" argument ignored");
771 				  displayinfos = true;
772           break;
773         }
774       }
775 
776       if (j >= argc)  // if +map not found
777       {
778         if (++i >= argc)
779 			  {
780 				  gConsole->Insertln("^1Missing argument for \"+demo\" command");
781 				  displayinfos = true;
782 			  }
783 			  else if (argv[i][0] == '+')
784 			  {
785 				  gConsole->Insertln("^1Invalid argument for \"+demo\" command");
786 				  displayinfos = true;
787 			  }
788 			  else
789         {
790           // compute last argument for function
791           j = i+1;
792           while (j < argc && argv[j][0] != '+') ++j;
793           cmd_demo(j-i+1, argv+i-1);  // the keyword 'demo' must be included
794           displayinfos = false;
795         }
796       }
797     }
798 	}
799 
800 	if (displayinfos)
801 	{
802 		setBGMusic(DEFAULT_MUSIC);		// Load a default music
803 		gConsole->Insertln("^2You can get a list of available maps with command \"bsplist\".");
804 		gConsole->Insertln("^2Map can be loaded with command \"load mapname\".");
805 		gConsole->Insertln("^2Commands names are displayed with \"cmdlist\".");
806 		gConsole->Insertln("^2Variables names are displayed with \"varlist\".");
807 		gConsole->SetState(OPEN);
808 	}
809 }
810 
811 //-----------------------------------------------------------------------------
812 // Shut
813 //-----------------------------------------------------------------------------
Shut(int status)814 void Shut(int status)
815 {
816 	gConsole->Insertln("<br/><b>^6----- Application shuting down --------------------------------</b>");
817 
818 	// Unregistering variables
819 	gVars->UnregisterVar(invertMouseX);
820 	gVars->UnregisterVar(invertMouseY);
821 	gVars->UnregisterVar(mouse_speed);
822 	gVars->UnregisterVar(zoomspeed);
823 	gVars->UnregisterVar(consoleKey);
824 
825 	app->Shut();
826 	delete app;
827 
828 	if (fullscr)
829 		glutLeaveGameMode();
830 	else
831 		glutDestroyWindow(window_index);
832 
833 	exit(status);
834 }
835 
836 //-----------------------------------------------------------------------------
837 // main
838 // Creates the window and the application
839 //-----------------------------------------------------------------------------
main(int argc,char * argv[])840 int main(int argc, char *argv[])
841 {
842 	glutInit(&argc, argv);
843 
844 	// Creates the application. It is important to create it very early in the
845 	// code because it reads the "config.ini" file, register variables, read
846 	// available packages, etc.
847 	app = new App;
848 	if (!app) ThrowException(ALLOCATION_ERROR, "Couldn't create the application");
849 
850 	RegisterVariables();
851 	AddCommands();
852 
853 	app->Init();
854 
855 	// Get window sizes from variables (initialized with "config.ini" values)
856 	width     = gVars->IntForKey("v_width");
857 	height    = gVars->IntForKey("v_height");
858 	toppos    = gVars->IntForKey("v_top");
859 	leftpos   = gVars->IntForKey("v_left");
860 	freq      = gVars->IntForKey("v_hz");
861 	colorbits = gVars->IntForKey("v_colorBits");
862 	fullscr   = (gVars->IntForKey("v_fullscreen"))?true:false;
863 
864 	// Creates the window
865 	if (fullscr)
866 	{
867 		char resolution[128];
868 		sprintf(resolution,
869 			"%dx%d:%d@%d",
870 			width,
871 			height,
872 			colorbits,
873 			freq);
874 
875  		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
876 		glutGameModeString(resolution);
877 
878 		glutEnterGameMode();
879 		glutSetCursor(GLUT_CURSOR_NONE);
880 	}
881 	else
882 	{
883 		glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
884 		glutInitWindowSize(width, height);
885 		glutInitWindowPosition(leftpos, toppos);
886 		window_index = glutCreateWindow(_VERSION_);
887 	}
888 
889 	glutReshapeFunc(Reshape);
890 	glutDisplayFunc(Draw);
891 	glutKeyboardFunc(Keyboard);
892 	glutKeyboardUpFunc(KeyboardUp);
893 	glutSpecialUpFunc(KeyboardSpecUp);
894 	glutSpecialFunc(KeyboardSpec);
895 	glutMouseFunc(MouseClic);
896 	glutMotionFunc(MouseMove);
897 	glutPassiveMotionFunc(MouseMovePassive);
898 	glutIdleFunc(Idle);
899 
900 	// Initialize resting values
901 	Init();
902 
903 	// Change the engine mode from initialization to running mode
904 	app->Run();
905 
906 	// Parse the command arguments
907 	ParseArgs(argc, argv);
908 
909 	// runs the main loop
910 	glutMainLoop();
911 
912 	return 0;
913 }
914 
RegisterVariables(void)915 void RegisterVariables(void)
916 {
917 	gVars->RegisterVar(invertMouseX);
918 	gVars->RegisterVar(invertMouseY);
919 	gVars->RegisterVar(mouse_speed);
920 	gVars->RegisterVar(zoomspeed);
921 	gVars->RegisterVar(consoleKey);
922 }
923 
924 //-----------------------------------------------------------------------------
925 // Commands
926 // It is possible to set commands that can be executed from the console
927 // during engine running. It is very useful for debugging or setting
928 // evenments during execution. Commands have all the same prototype:
929 //     void commandname(int argc, char *argv[])
930 // like the main function.
931 //-----------------------------------------------------------------------------
932 
933 // Quit the application
cmd_quit(int argc,char * argv[])934 void cmd_quit(int argc, char *argv[])
935 {
936 	Shut(0);
937 }
938 
939 // Load a map
cmd_load(int argc,char * argv[])940 void cmd_load(int argc, char *argv[])
941 {
942 	if (argc > 1)
943 	{
944 		if (app->LoadMap(argv[1]))
945 		{
946 			gConsole->Resize(-1, height/2);
947 		}
948 		else
949 		{
950 			setBGMusic(DEFAULT_MUSIC);		// Load a default music
951 		}
952 	}
953 	else gConsole->Insertln("usage: %s <string>", argv[0]);
954 }
955 
956 // Reload the current map
cmd_reload(int argc,char * argv[])957 void cmd_reload(int argc, char *argv[])
958 {
959 	if (app->ReloadMap())
960 	{
961 		gConsole->Resize(-1, height/2);
962 	}
963 	else
964 	{
965 		setBGMusic(DEFAULT_MUSIC);		// Load a default music
966 	}
967 }
968 
cmd_defineviewport(int argc,char * argv[])969 void cmd_defineviewport(int argc, char *argv[])
970 {
971 	if (argc > 5)
972 	{
973 		Client *client = app->GetClient(atoi(argv[1]));
974 		if (client) client->Init(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
975 		else gConsole->Insertln("^1Invalid client index");
976 	}
977 	else gConsole->Insertln("usage: %s <client_index> <left_pos> <top_pos> <width> <height>");
978 }
979 
cmd_noclip(int argc,char * argv[])980 void cmd_noclip(int argc, char *argv[])
981 {
982 	int currclient = app->GetCurrentClientIndex();
983 	if (currclient < 0)
984 	{
985 		gConsole->Insert("^1No available client");
986 		return;
987 	}
988 
989 	app->GetClient(currclient)->noclip = !app->GetClient(currclient)->noclip;
990 	gConsole->Insertln("noclip %s for client %d", app->GetClient(currclient)->noclip?"ON":"OFF", currclient);
991 }
992 
cmd_lockfrustum(int argc,char * argv[])993 void cmd_lockfrustum(int argc, char *argv[])
994 {
995 	int currclient = app->GetCurrentClientIndex();
996 	if (currclient < 0)
997 	{
998 		gConsole->Insert("^1No available client");
999 		return;
1000 	}
1001 
1002 	app->GetClient(currclient)->cam.lockfrustum = !app->GetClient(currclient)->cam.lockfrustum;
1003 	gConsole->Insertln("frustum lock %s for client %d", app->GetClient(currclient)->cam.lockfrustum?"ON":"OFF", currclient);
1004 }
1005 
1006 // Unload the current map
cmd_unload(int argc,char * argv[])1007 void cmd_unload(int argc, char *argv[])
1008 {
1009 	app->UnloadMap();
1010 	setBGMusic(DEFAULT_MUSIC);		// Load a default music
1011 }
1012 
cmd_record(int argc,char * argv[])1013 void cmd_record(int argc, char *argv[])
1014 {
1015 	app->RecordDemo((argc>1)?(float)atof(argv[1]):0.1f);
1016 }
1017 
cmd_stopdemo(int argc,char * argv[])1018 void cmd_stopdemo(int argc, char *argv[])
1019 {
1020 	if (argc > 1) app->StopDemo(argv[1]);
1021 	else app->StopDemo();
1022 }
1023 
cmd_demo(int argc,char * argv[])1024 void cmd_demo(int argc, char *argv[])
1025 {
1026 	if (argc > 1)
1027 	{
1028 		int i;
1029 
1030 		bool looping = false;
1031 		for (i = 2; i < argc; ++i)
1032 		{
1033 			// get last valid value
1034 			if (!stricmp(argv[i], "loop")) looping = true;
1035 		}
1036 
1037 		enum_InterpolationMode mode = AUTO_INTERPOLATION;
1038 		for (i = 2; i < argc; ++i)
1039 		{
1040 			// get last valid value
1041 			if (!stricmp(argv[i], "linear")) mode = LINEAR_INTERPOLATION;
1042 			else if (!stricmp(argv[i], "spline")) mode = SPLINE_INTERPOLATION;
1043 		}
1044 
1045 		app->PlayDemo(argv[1], looping, mode);
1046 	}
1047 	else gConsole->Insertln("usage: %s <string> {\"loop\"} {\"linear\", \"spline\"}", argv[0]);
1048 }
1049 
cmd_demodump(int argc,char * argv[])1050 void cmd_demodump(int argc, char *argv[])
1051 {
1052 	if (argc > 1)
1053 	{
1054 		Demo demo;
1055 		demo.DemoDump(argv[1], (argc > 2)?atol(argv[2]):0);
1056 	}
1057 }
1058 
cmd_shaderpreview(int argc,char * argv[])1059 void cmd_shaderpreview(int argc, char *argv[])
1060 {
1061 	if (argc > 1)
1062 	{
1063 		if (app->GetWorld())
1064 		{
1065 			preview = gFramework->shaders.AddShader(argv[1], 0, 0, FACETYPE_MESH);
1066 			gFramework->Update();
1067 		}
1068 		else gConsole->Insertln("^6Some shaders require camera position. Camera is created when "
1069 							  "map is loaded, so load a map to be able to preview shaders.");
1070 	}
1071 }
1072 
1073 // Display available resolutions
cmd_resolutions(int argc,char * argv[])1074 void cmd_resolutions(int argc, char *argv[])
1075 {
1076 	CheckForAllAvailableResolutions();
1077 }
1078 
1079 // Save a screenshot of current scene (without console)
cmd_screenshot(int argc,char * argv[])1080 void cmd_screenshot(int argc, char *argv[])
1081 {
1082 	if (argc > 1)
1083 	{
1084 		if (!ScreenShot(argv[1]))
1085 			gConsole->Insertln("^5!! An error occured while trying to save screenshot bitmap.");
1086 	}
1087 	else gConsole->Insertln("usage: %s <filename>", argv[0]);
1088 }
1089 
1090 // Change the fontsize
cmd_fontsize(int argc,char * argv[])1091 void cmd_fontsize (int argc, char *argv[])
1092 {
1093 	if (argc < 3) return;
1094 
1095 	gConsole->SetFontSize(atol(argv[1]), atol(argv[2]));
1096 }
1097 
1098 // Sets the tabulation key mode for console
cmd_tabmode(int argc,char * argv[])1099 void cmd_tabmode (int argc, char *argv[])
1100 {
1101 	if (argc > 1)
1102 	{
1103 		if (!strcmp(argv[1], "0")) tabmode = 0;
1104 		else tabmode = 1;
1105 	}
1106 }
1107 
1108 // Toggles the mouse auto center mode
cmd_togglemousecenter(int argc,char * argv[])1109 void cmd_togglemousecenter (int argc, char *argv[])
1110 {
1111 	AutoCenterMouse = !AutoCenterMouse;
1112 }
1113 
1114 // Displays a preview (levelshot) of an available map
cmd_preview(int argc,char * argv[])1115 void cmd_preview (int argc, char *argv[])
1116 {
1117 	if (argc > 1)
1118 	{
1119 		char levelshot_name[256] = { '\0' };
1120 		sprintf(levelshot_name, "levelshots/%s", argv[1]);
1121 		preview = gFramework->shaders.AddShader(levelshot_name, 0, 0, FACETYPE_MESH);
1122 		gFramework->Update();
1123 	}
1124 }
1125 
1126 // Displays credits
cmd_credits(int argc,char * argv[])1127 void cmd_credits(int argc, char *argv[])
1128 {
1129 	gConsole->Insertln("^5Credits:");
1130 	gConsole->Insertln("^2Base engine: TITAN PROJECT - Ignacio Castano Aguado");
1131 	gConsole->Insertln("^2Addons and new elements: morbac");
1132 	gConsole->Insertln("^2With special thanks to: Kaspar, Max, and all cool guys who make demos and tutorials on the web :)");
1133 }
1134 
cmd_speed(int argc,char * argv[])1135 void cmd_speed(int argc, char *argv[])
1136 {
1137 	Client *client = app->GetCurrentClient();
1138 	if (!client)
1139 	{
1140 		gConsole->Insert("^1No available client");
1141 		return;
1142 	}
1143 	if (argc > 1) client->max_speed = (float) atof(argv[1]);
1144 	else gConsole->Insertln("Client speed: %f", app->GetCurrentClient()->max_speed);
1145 }
1146 
cmd_fov(int argc,char * argv[])1147 void cmd_fov(int argc, char *argv[])
1148 {
1149 	Client *client = app->GetCurrentClient();
1150 	if (!client)
1151 	{
1152 		gConsole->Insert("^1No available client");
1153 		return;
1154 	}
1155 
1156 	if (argc > 1)
1157 	{
1158 		client->fov = (float) atof(argv[1]);
1159 		client->UpdateCam();
1160 	}
1161 	else gConsole->Insertln("FOV : %f", client->fov);
1162 }
1163 
cmd_zoomlimit(int argc,char * argv[])1164 void cmd_zoomlimit(int argc, char *argv[])
1165 {
1166 	Client *client = app->GetCurrentClient();
1167 	if (!client)
1168 	{
1169 		gConsole->Insert("^1No available client");
1170 		return;
1171 	}
1172 
1173 	if (argc > 1)
1174 	{
1175 		client->zoomlimit = (float) atof(argv[1]);
1176 	}
1177 	else gConsole->Insertln("zoom limit : %f", client->zoomlimit);
1178 }
1179 
cmd_tpl(int argc,char * argv[])1180 void cmd_tpl(int argc, char *argv[])
1181 {
1182 	Client *client = app->GetCurrentClient();
1183 	if (!client)
1184 	{
1185 		gConsole->Insert("^1No available client");
1186 		return;
1187 	}
1188 
1189 	client->pitchLimit = !client->pitchLimit;
1190 }
1191 
cmd_acceleration(int argc,char * argv[])1192 void cmd_acceleration(int argc, char *argv[])
1193 {
1194 	Client *client = app->GetCurrentClient();
1195 	if (!client)
1196 	{
1197 		gConsole->Insert("^1No available client");
1198 		return;
1199 	}
1200 
1201 	if (argc > 1) client->acceleration = (float) atof(argv[1]);
1202 	else gConsole->Insertln("Client acceleration value: %f", client->acceleration);
1203 }
1204 
cmd_friction(int argc,char * argv[])1205 void cmd_friction(int argc, char *argv[])
1206 {
1207 	Client *client = app->GetCurrentClient();
1208 	if (!client)
1209 	{
1210 		gConsole->Insert("^1No available client");
1211 		return;
1212 	}
1213 
1214 	if (argc > 1) client->friction = (float) atof(argv[1]);
1215 	else gConsole->Insertln("Client friction value: %f", client->friction);
1216 }
1217 
cmd_getpos(int argc,char * argv[])1218 void cmd_getpos(int argc, char *argv[])
1219 {
1220 	Client *client = app->GetCurrentClient();
1221 	if (!client)
1222 	{
1223 		gConsole->Insert("^1No available client");
1224 		return;
1225 	}
1226 
1227 	gConsole->Insertln("Client position : [%f;%f;%f]",
1228 		client->cam.pos[0], client->cam.pos[1], client->cam.pos[2]);
1229 }
1230 
cmd_getrot(int argc,char * argv[])1231 void cmd_getrot(int argc, char *argv[])
1232 {
1233 	Client *client = app->GetCurrentClient();
1234 	if (!client)
1235 	{
1236 		gConsole->Insert("^1No available client");
1237 		return;
1238 	}
1239 
1240 	gConsole->Insertln("Client angle : [%f;%f;%f]",
1241 		client->cam.rot[PITCH], client->cam.rot[YAW], client->cam.rot[ROLL]);
1242 }
1243 
cmd_setpos(int argc,char * argv[])1244 void cmd_setpos(int argc, char *argv[])
1245 {
1246 	if (argc > 3)
1247 	{
1248 		Client *client = app->GetCurrentClient();
1249 		if (!client)
1250 		{
1251 			gConsole->Insert("^1No available client");
1252 			return;
1253 		}
1254 
1255 		client->SetPos((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
1256 	}
1257 	else gConsole->Insertln("usage: %s <value value value>", argv[0]);
1258 }
1259 
cmd_setrot(int argc,char * argv[])1260 void cmd_setrot(int argc, char *argv[])
1261 {
1262 	if (argc > 3)
1263 	{
1264 		Client *client = app->GetCurrentClient();
1265 		if (!client)
1266 		{
1267 			gConsole->Insert("^1No available client");
1268 			return;
1269 		}
1270 
1271 		client->SetAngle((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
1272 	}
1273 	else gConsole->Insertln("usage: %s <value value value>", argv[0]);
1274 }
1275 
cmd_addpos(int argc,char * argv[])1276 void cmd_addpos(int argc, char *argv[])
1277 {
1278 	if (argc > 3)
1279 	{
1280 		Client *client = app->GetCurrentClient();
1281 		if (!client)
1282 		{
1283 			gConsole->Insert("^1No available client");
1284 			return;
1285 		}
1286 		client->AddPos((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
1287 	}
1288 	else if (argc > 2)
1289 	{
1290 		Client *client = app->GetCurrentClient();
1291 		if (!client)
1292 		{
1293 			gConsole->Insert("^1No available client");
1294 			return;
1295 		}
1296 		client->AddPos((float) atof(argv[1]), (float) atof(argv[2]), 0);
1297 	}
1298 	else if (argc > 1)
1299 	{
1300 		Client *client = app->GetCurrentClient();
1301 		if (!client)
1302 		{
1303 			gConsole->Insert("^1No available client");
1304 			return;
1305 		}
1306 		client->AddPos((float) atof(argv[1]), 0, 0);
1307 	}
1308 	else gConsole->Insertln("usage: %s <value value value>", argv[0]);
1309 }
1310 
cmd_addangle(int argc,char * argv[])1311 void cmd_addangle(int argc, char *argv[])
1312 {
1313 	if (argc > 3)
1314 	{
1315 		Client *client = app->GetCurrentClient();
1316 		if (!client)
1317 		{
1318 			gConsole->Insert("^1No available client");
1319 			return;
1320 		}
1321 		client->AddAngle((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]));
1322 	}
1323 	if (argc > 2)
1324 	{
1325 		Client *client = app->GetCurrentClient();
1326 		if (!client)
1327 		{
1328 			gConsole->Insert("^1No available client");
1329 			return;
1330 		}
1331 		client->AddAngle((float) atof(argv[1]), (float) atof(argv[2]), 0);
1332 	}
1333 	if (argc > 1)
1334 	{
1335 		Client *client = app->GetCurrentClient();
1336 		if (!client)
1337 		{
1338 			gConsole->Insert("^1No available client");
1339 			return;
1340 		}
1341 		client->AddAngle((float) atof(argv[1]), 0, 0);
1342 	}
1343 	else gConsole->Insertln("usage: %s <value value value>", argv[0]);
1344 }
1345 
cmd_getfps(int argc,char * argv[])1346 void cmd_getfps(int argc, char *argv[])
1347 {
1348 	gConsole->Insertln("%4.2f fps", app->GetFPS());
1349 }
1350 
cmd_setnclients(int argc,char * argv[])1351 void cmd_setnclients(int argc, char *argv[])
1352 {
1353 	if (argc > 1)
1354 	{
1355 		int numclients = atol(argv[1]);
1356 
1357 		// Create the clients
1358 		if (numclients <= 0) numclients = 1;
1359 		app->CreateClients(numclients);
1360 
1361 		if ((nstartpos = app->GetWorld()->GetNumStartPos()))
1362 		{
1363 			currstartpos = 0;
1364 			for (int i = 0; i < numclients; ++i)
1365 			{
1366 				app->GetWorld()->SetStartPos(app->GetClient(i), currstartpos);
1367 				currstartpos = (currstartpos+1)%nstartpos;
1368 			}
1369 		}
1370 	}
1371 	else gConsole->Insertln("usage: %s <value>", argv[0]);
1372 }
1373 
cmd_entityreport(int argc,char * argv[])1374 void cmd_entityreport(int argc, char *argv[])
1375 {
1376 	if (app->GetWorld()) app->GetWorld()->GetBSP()->GetEntities()->Report();
1377 	else gConsole->Insertln("^1No world !");
1378 }
1379 
cmd_bspreport(int argc,char * argv[])1380 void cmd_bspreport(int argc, char *argv[])
1381 {
1382 	if (app->GetWorld()) app->GetWorld()->GetBSP()->Report();
1383 	else gConsole->Insertln("^1No world !");
1384 }
1385 
cmd_loadplayer(int argc,char * argv[])1386 void cmd_loadplayer(int argc, char *argv[])
1387 {
1388 	if (!app->GetNumClients())
1389 	{
1390 		gConsole->Insertln("^5WARNING: No available client !");
1391 		return;
1392 	}
1393 
1394 	if (argc > 1)
1395 	{
1396 		app->GetCurrentClient()->LoadPlayer(argv[1]);
1397 	}
1398 	else gConsole->Insertln("usage: %s <playername>", argv[0]);
1399 }
1400 
1401 // Add the commands to the engine commands list
AddCommands(void)1402 void AddCommands(void)
1403 {
1404 	gCommands->AddCommand("quit", cmd_quit, "exit the application");
1405 	gAlias->SetAlias("exit", "quit");
1406 	gCommands->AddCommand("map", cmd_load, "load a bsp map");
1407 	gAlias->SetAlias("load", "map");
1408 	gCommands->AddCommand("map_restart", cmd_reload, "reload the current map");
1409 	gAlias->SetAlias("reload", "map_restart");
1410 	gCommands->AddCommand("unload", cmd_unload, "unload the current map");
1411 	gCommands->AddCommand("noclip", cmd_noclip, "toggle the collisions for clients");
1412 	gCommands->AddCommand("lockfrustum", cmd_lockfrustum, "loks the frustum for clients");
1413 	gCommands->AddCommand("record", cmd_record, "start recording a demo");
1414 	gCommands->AddCommand("stopdemo", cmd_stopdemo, "stop recording a demo");
1415 	gCommands->AddCommand("demo", cmd_demo, "play recorded demo");
1416 	gCommands->AddCommand("demodump", cmd_demodump, "dump demo file content");
1417 	gCommands->AddCommand("preview", cmd_preview, "displays the levelshot of a map (if it exists)");
1418 	gCommands->AddCommand("shaderpreview", cmd_shaderpreview, "display a sample of shader");
1419 	gCommands->AddCommand("fontsize", cmd_fontsize, "sets the font size");
1420 	gCommands->AddCommand("tabmode", cmd_tabmode, "sets the current tabulation key comportement");
1421 	gCommands->AddCommand("togglemousecenter", cmd_togglemousecenter, "toggles the mouse autocentering");
1422 	gAlias->SetAlias("tmc", "togglemousecenter");
1423 	gCommands->AddCommand("credits", cmd_credits, "displays the engine and test program credits");
1424 	gCommands->AddCommand("speed", cmd_speed, "defines the moving speed of camera");
1425 	gCommands->AddCommand("fov", cmd_fov, "defines the camera fov");
1426 	gCommands->AddCommand("zoomlimit", cmd_zoomlimit, "defines the camera zoom limit");
1427 	gCommands->AddCommand("togglepitchlimit", cmd_tpl, "toggles the camera rotation limitation on Ox axis");
1428 	gAlias->SetAlias("tpl", "togglepitchlimit");
1429 	gCommands->AddCommand("accel", cmd_acceleration, "defines the acceleration value of client");
1430 	gCommands->AddCommand("friction", cmd_friction, "defines the friction value of client");
1431 	gCommands->AddCommand("getpos", cmd_getpos, "gets the current camera position");
1432 	gCommands->AddCommand("setpos", cmd_setpos, "sets the current camera position");
1433 	gCommands->AddCommand("addpos", cmd_addpos, "increments the current client camera position");
1434 	gCommands->AddCommand("getrot", cmd_getrot, "gets the current rotation angle");
1435 	gCommands->AddCommand("setrot", cmd_setrot, "sets the current rotation angle");
1436 	gCommands->AddCommand("addangle", cmd_addangle, "increments the current client camera angle");
1437 	gCommands->AddCommand("getfps", cmd_getfps, "returns the current fps rate");
1438 	gCommands->AddCommand("setnclients", cmd_setnclients, "sets the number of clients");
1439 	gCommands->AddCommand("resolutions", cmd_resolutions, "displays a list of all available screen resolution");
1440 	gCommands->AddCommand("screenshot", cmd_screenshot, "takes a screenshot of current window");
1441 	gCommands->AddCommand("entityreport", cmd_entityreport, "writes a report on entities in logfile");
1442 	gCommands->AddCommand("bspreport", cmd_bspreport, "writes a report on bsp in logfile");
1443 	gCommands->AddCommand("defineviewport", cmd_defineviewport, "define the viewport for a client");
1444 	gCommands->AddCommand("loadplayer", cmd_loadplayer, "load player skin, sounds, etc.");
1445 }
1446