]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/main.c
Merge commit 'eef39952025db1375e33b6e314692ac76badb93c' into garux-merge
[xonotic/netradiant.git] / tools / quake3 / q3map2 / main.c
1 /* -------------------------------------------------------------------------------
2
3    Copyright (C) 1999-2007 id Software, Inc. and contributors.
4    For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6    This file is part of GtkRadiant.
7
8    GtkRadiant is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    GtkRadiant is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GtkRadiant; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22    -------------------------------------------------------------------------------
23
24    This code has been altered significantly from its original form, to support
25    several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27    ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define MAIN_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38 #include <glib.h>
39
40 /*
41    Random()
42    returns a pseudorandom number between 0 and 1
43  */
44
45 vec_t Random( void ){
46         return (vec_t) rand() / RAND_MAX;
47 }
48
49
50 char *Q_strncpyz( char *dst, const char *src, size_t len ) {
51         if ( len == 0 ) {
52                 abort();
53         }
54
55         strncpy( dst, src, len );
56         dst[ len - 1 ] = '\0';
57         return dst;
58 }
59
60
61 char *Q_strcat( char *dst, size_t dlen, const char *src ) {
62         size_t n = strlen( dst );
63
64         if ( n > dlen ) {
65                 abort(); /* buffer overflow */
66         }
67
68         return Q_strncpyz( dst + n, src, dlen - n );
69 }
70
71
72 char *Q_strncat( char *dst, size_t dlen, const char *src, size_t slen ) {
73         size_t n = strlen( dst );
74
75         if ( n > dlen ) {
76                 abort(); /* buffer overflow */
77         }
78
79         return Q_strncpyz( dst + n, src, MIN( slen, dlen - n ) );
80 }
81
82
83 /*
84    ExitQ3Map()
85    cleanup routine
86  */
87
88 static void ExitQ3Map( void ){
89         BSPFilesCleanup();
90         if ( mapDrawSurfs != NULL ) {
91                 free( mapDrawSurfs );
92         }
93 }
94
95
96 /*
97    ShiftBSPMain()
98    shifts a map: for testing physics with huge coordinates
99  */
100
101 int ShiftBSPMain( int argc, char **argv ){
102         int i, j;
103         float f, a;
104         vec3_t scale;
105         vec3_t vec;
106         char str[ 1024 ];
107         int uniform, axis;
108         qboolean texscale;
109         float *old_xyzst = NULL;
110         float spawn_ref = 0;
111
112
113         /* arg checking */
114         if ( argc < 3 ) {
115                 Sys_Printf( "Usage: q3map [-v] -shift [-tex] [-spawn_ref <value>] <value> <mapname>\n" );
116                 return 0;
117         }
118
119         texscale = qfalse;
120         for ( i = 1; i < argc - 2; ++i )
121         {
122                 if ( !strcmp( argv[i], "-tex" ) ) {
123                         texscale = qtrue;
124                 }
125                 else if ( !strcmp( argv[i], "-spawn_ref" ) ) {
126                         spawn_ref = atof( argv[i + 1] );
127                         ++i;
128                 }
129                 else{
130                         break;
131                 }
132         }
133
134         /* get shift */
135         // if(argc-2 >= i) // always true
136         scale[2] = scale[1] = scale[0] = atof( argv[ argc - 2 ] );
137         if ( argc - 3 >= i ) {
138                 scale[1] = scale[0] = atof( argv[ argc - 3 ] );
139         }
140         if ( argc - 4 >= i ) {
141                 scale[0] = atof( argv[ argc - 4 ] );
142         }
143
144         uniform = ( ( scale[0] == scale[1] ) && ( scale[1] == scale[2] ) );
145
146
147         /* do some path mangling */
148         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
149         StripExtension( source );
150         DefaultExtension( source, ".bsp" );
151
152         /* load the bsp */
153         Sys_Printf( "Loading %s\n", source );
154         LoadBSPFile( source );
155         ParseEntities();
156
157         /* note it */
158         Sys_Printf( "--- ShiftBSP ---\n" );
159         Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
160
161         /* shift entity keys */
162         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
163         {
164                 /* shift origin */
165                 GetVectorForKey( &entities[ i ], "origin", vec );
166                 if ( ( vec[ 0 ] || vec[ 1 ] || vec[ 2 ] ) ) {
167                         if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
168                                 vec[2] += spawn_ref;
169                         }
170                         vec[0] += scale[0];
171                         vec[1] += scale[1];
172                         vec[2] += scale[2];
173                         if ( !strncmp( ValueForKey( &entities[i], "classname" ), "info_player_", 12 ) ) {
174                                 vec[2] -= spawn_ref;
175                         }
176                         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
177                         SetKeyValue( &entities[ i ], "origin", str );
178                 }
179
180         }
181
182         /* shift models */
183         for ( i = 0; i < numBSPModels; i++ )
184         {
185                 bspModels[ i ].mins[0] += scale[0];
186                 bspModels[ i ].mins[1] += scale[1];
187                 bspModels[ i ].mins[2] += scale[2];
188                 bspModels[ i ].maxs[0] += scale[0];
189                 bspModels[ i ].maxs[1] += scale[1];
190                 bspModels[ i ].maxs[2] += scale[2];
191         }
192
193         /* shift nodes */
194         for ( i = 0; i < numBSPNodes; i++ )
195         {
196                 bspNodes[ i ].mins[0] += scale[0];
197                 bspNodes[ i ].mins[1] += scale[1];
198                 bspNodes[ i ].mins[2] += scale[2];
199                 bspNodes[ i ].maxs[0] += scale[0];
200                 bspNodes[ i ].maxs[1] += scale[1];
201                 bspNodes[ i ].maxs[2] += scale[2];
202         }
203
204         /* shift leafs */
205         for ( i = 0; i < numBSPLeafs; i++ )
206         {
207                 bspLeafs[ i ].mins[0] += scale[0];
208                 bspLeafs[ i ].mins[1] += scale[1];
209                 bspLeafs[ i ].mins[2] += scale[2];
210                 bspLeafs[ i ].maxs[0] += scale[0];
211                 bspLeafs[ i ].maxs[1] += scale[1];
212                 bspLeafs[ i ].maxs[2] += scale[2];
213         }
214
215         /* shift drawverts */
216         for ( i = 0; i < numBSPDrawVerts; i++ )
217         {
218                 bspDrawVerts[i].xyz[0] += scale[0];
219                 bspDrawVerts[i].xyz[1] += scale[1];
220                 bspDrawVerts[i].xyz[2] += scale[2];
221         }
222
223         /* shift planes */
224
225         vec3_t point;
226
227         for ( i = 0; i < numBSPPlanes; i++ )
228         {
229                 //find point on plane
230                 for ( j=0; j<3; j++ ){
231                         if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
232                                 point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
233                                 point[(j+1)%3] = point[(j+2)%3] = 0;
234                                 break;
235                         }
236                 }
237                 //shift point
238                 for ( j=0; j<3; j++ ){
239                         point[j] += scale[j];
240                 }
241                 //calc new plane dist
242                 bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
243         }
244
245         /* scale gridsize */
246         /*
247         GetVectorForKey( &entities[ 0 ], "gridsize", vec );
248         if ( ( vec[ 0 ] + vec[ 1 ] + vec[ 2 ] ) == 0.0f ) {
249                 VectorCopy( gridSize, vec );
250         }
251         vec[0] *= scale[0];
252         vec[1] *= scale[1];
253         vec[2] *= scale[2];
254         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
255         SetKeyValue( &entities[ 0 ], "gridsize", str );
256 */
257         /* inject command line parameters */
258         InjectCommandLine( argv, 0, argc - 1 );
259
260         /* write the bsp */
261         UnparseEntities();
262         StripExtension( source );
263         DefaultExtension( source, "_sh.bsp" );
264         Sys_Printf( "Writing %s\n", source );
265         WriteBSPFile( source );
266
267         /* return to sender */
268         return 0;
269 }
270
271
272 void FixDOSName( char *src ){
273         if ( src == NULL ) {
274                 return;
275         }
276
277         while ( *src )
278         {
279                 if ( *src == '\\' ) {
280                         *src = '/';
281                 }
282                 src++;
283         }
284 }
285
286 /*
287         Check if newcoming texture is unique and not excluded
288 */
289 void tex2list( char texlist[512][MAX_QPATH], int *texnum, char EXtex[2048][MAX_QPATH], int *EXtexnum ){
290         int i;
291         if ( token[0] == '\0') return;
292         StripExtension( token );
293         FixDOSName( token );
294         for ( i = 0; i < *texnum; i++ ){
295                 if ( !stricmp( texlist[i], token ) ) return;
296         }
297         for ( i = 0; i < *EXtexnum; i++ ){
298                 if ( !stricmp( EXtex[i], token ) ) return;
299         }
300         strcpy ( texlist[*texnum], token );
301         (*texnum)++;
302         return;
303 }
304
305
306 /*
307         Check if newcoming res is unique
308 */
309 void res2list( char data[512][MAX_QPATH], int *num ){
310         int i;
311         if ( data[*num][0] == '\0') return;
312         for ( i = 0; i < *num; i++ ){
313                 if ( !stricmp( data[i], data[*num] ) ) return;
314         }
315         (*num)++;
316         return;
317 }
318
319 void parseEXblock ( char data[512][MAX_QPATH], int *num, const char *exName ){
320         if ( !GetToken( qtrue ) || strcmp( token, "{" ) ) {
321                 Error( "ReadExclusionsFile: %s, line %d: { not found", exName, scriptline );
322         }
323         while ( 1 )
324         {
325                 if ( !GetToken( qtrue ) ) {
326                         break;
327                 }
328                 if ( !strcmp( token, "}" ) ) {
329                         break;
330                 }
331                 if ( token[0] == '{' ) {
332                         Error( "ReadExclusionsFile: %s, line %d: brace, opening twice in a row.", exName, scriptline );
333                 }
334
335                 /* add to list */
336                 strcpy( data[*num], token );
337                 (*num)++;
338         }
339         return;
340 }
341
342 char q3map2path[1024];
343 /*
344    pk3BSPMain()
345    map autopackager, works for Q3 type of shaders and ents
346  */
347
348 int pk3BSPMain( int argc, char **argv ){
349         int i, j;
350         qboolean dbg = qfalse, png = qfalse;
351
352         /* process arguments */
353         for ( i = 1; i < ( argc - 1 ); i++ ){
354                 if ( !strcmp( argv[ i ],  "-dbg" ) ) {
355                         dbg = qtrue;
356                 }
357                 else if ( !strcmp( argv[ i ],  "-png" ) ) {
358                         png = qtrue;
359                 }
360         }
361
362
363
364         /* do some path mangling */
365         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
366         StripExtension( source );
367         DefaultExtension( source, ".bsp" );
368
369         /* load the bsp */
370         Sys_Printf( "Loading %s\n", source );
371         LoadBSPFile( source );
372         ParseEntities();
373
374
375         char packname[ 1024 ], base[ 1024 ], nameOFmap[ 1024 ];
376         int len;
377         strcpy( packname, EnginePath );
378
379
380         /* copy map name */
381         strcpy( base, source );
382         StripExtension( base );
383
384         /* extract map name */
385         len = strlen( base ) - 1;
386         while ( len > 0 && base[ len ] != '/' && base[ len ] != '\\' )
387                 len--;
388         strcpy( nameOFmap, &base[ len + 1 ] );
389
390
391         qboolean dsSHs[512] = {qfalse};
392
393         for ( i = 0; i < numBSPDrawSurfaces; i++ ){
394                 /* can't exclude nodraw patches here (they want shaders :0!) */
395                 //if ( !( bspDrawSurfaces[i].surfaceType == 2 && bspDrawSurfaces[i].numIndexes == 0 ) ) dsSHs[bspDrawSurfaces[i].shaderNum] = qtrue;
396                 dsSHs[bspDrawSurfaces[i].shaderNum] = qtrue;
397                 //Sys_Printf( "%s\n", bspShaders[bspDrawSurfaces[i].shaderNum].shader );
398         }
399
400         int pk3ShadersN = 0;
401         char pk3Shaders[512][MAX_QPATH];
402         int pk3SoundsN = 0;
403         char pk3Sounds[512][MAX_QPATH];
404         int pk3ShaderfilesN = 0;
405         char pk3Shaderfiles[512][MAX_QPATH];
406         int pk3TexturesN = 0;
407         char pk3Textures[512][MAX_QPATH];
408         int pk3VideosN = 0;
409         char pk3Videos[512][MAX_QPATH];
410
411
412
413         for ( i = 0; i < numBSPShaders; i++ ){
414                 if ( dsSHs[i] ){
415                         strcpy( pk3Shaders[pk3ShadersN], bspShaders[i].shader );
416                         res2list( pk3Shaders, &pk3ShadersN );
417                         //pk3ShadersN++;
418                         //Sys_Printf( "%s\n", bspShaders[i].shader );
419                 }
420         }
421
422         //ent keys
423         epair_t *ep;
424         for ( ep = entities[0].epairs; ep != NULL; ep = ep->next )
425         {
426                 if ( !strnicmp( ep->key, "vertexremapshader", 17 ) ) {
427                         sscanf( ep->value, "%*[^;] %*[;] %s", pk3Shaders[pk3ShadersN] );
428                         res2list( pk3Shaders, &pk3ShadersN );
429                 }
430         }
431         strcpy( pk3Sounds[pk3SoundsN], ValueForKey( &entities[0], "music" ) );
432         res2list( pk3Sounds, &pk3SoundsN );
433
434         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
435         {
436                 strcpy( pk3Sounds[pk3SoundsN], ValueForKey( &entities[i], "noise" ) );
437                 if ( pk3Sounds[pk3SoundsN][0] != '*' ) res2list( pk3Sounds, &pk3SoundsN );
438
439                 if ( !stricmp( ValueForKey( &entities[i], "classname" ), "func_plat" ) ){
440                         strcpy( pk3Sounds[pk3SoundsN], "sound/movers/plats/pt1_strt.wav");
441                         res2list( pk3Sounds, &pk3SoundsN );
442                         strcpy( pk3Sounds[pk3SoundsN], "sound/movers/plats/pt1_end.wav");
443                         res2list( pk3Sounds, &pk3SoundsN );
444                 }
445                 if ( !stricmp( ValueForKey( &entities[i], "classname" ), "target_push" ) ){
446                         if ( !(IntForKey( &entities[i], "spawnflags") & 1) ){
447                                 strcpy( pk3Sounds[pk3SoundsN], "sound/misc/windfly.wav");
448                                 res2list( pk3Sounds, &pk3SoundsN );
449                         }
450                 }
451                 strcpy( pk3Shaders[pk3ShadersN], ValueForKey( &entities[i], "targetShaderNewName" ) );
452                 res2list( pk3Shaders, &pk3ShadersN );
453         }
454
455         //levelshot
456         sprintf( pk3Shaders[ pk3ShadersN ], "levelshots/%s", nameOFmap );
457         res2list( pk3Shaders, &pk3ShadersN );
458
459
460         if( dbg ){
461                 Sys_Printf( "\tDrawsurface+ent calls....%i\n", pk3ShadersN );
462                 for ( i = 0; i < pk3ShadersN; i++ ){
463                         Sys_Printf( "%s\n", pk3Shaders[i] );
464                 }
465                 Sys_Printf( "\tSounds....%i\n", pk3SoundsN );
466                 for ( i = 0; i < pk3SoundsN; i++ ){
467                         Sys_Printf( "%s\n", pk3Sounds[i] );
468                 }
469         }
470
471         vfsListShaderFiles( pk3Shaderfiles, &pk3ShaderfilesN );
472
473         if( dbg ){
474                 Sys_Printf( "\tSchroider fileses.....%i\n", pk3ShaderfilesN );
475                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
476                         Sys_Printf( "%s\n", pk3Shaderfiles[i] );
477                 }
478         }
479
480
481         /* load exclusions file */
482         int EXpk3TexturesN = 0;
483         char EXpk3Textures[2048][MAX_QPATH];
484         int EXpk3ShadersN = 0;
485         char EXpk3Shaders[2048][MAX_QPATH];
486         int EXpk3SoundsN = 0;
487         char EXpk3Sounds[2048][MAX_QPATH];
488         int EXpk3ShaderfilesN = 0;
489         char EXpk3Shaderfiles[512][MAX_QPATH];
490         int EXpk3VideosN = 0;
491         char EXpk3Videos[512][MAX_QPATH];
492
493         char exName[ 1024 ];
494         byte *buffer;
495         int size;
496
497         strcpy( exName, q3map2path );
498         char *cut = strrchr( exName, '\\' );
499         char *cut2 = strrchr( exName, '/' );
500         if ( cut == NULL && cut2 == NULL ){
501                 Sys_Printf( "WARNING: Unable to load exclusions file.\n" );
502                 goto skipEXfile;
503         }
504         if ( cut2 > cut ) cut = cut2;
505         //cut++;
506         cut[1] = '\0';
507         strcat( exName, game->arg );
508         strcat( exName, ".exclude" );
509
510         Sys_Printf( "Loading %s\n", exName );
511         size = TryLoadFile( exName, (void**) &buffer );
512         if ( size <= 0 ) {
513                 Sys_Printf( "WARNING: Unable to find exclusions file %s.\n", exName );
514                 goto skipEXfile;
515         }
516
517         /* parse the file */
518         ParseFromMemory( (char *) buffer, size );
519
520         /* blocks pointers */
521         //int *exptrN;
522         //char *exptr[512][64];
523
524
525         /* tokenize it */
526         while ( 1 )
527         {
528                 /* test for end of file */
529                 if ( !GetToken( qtrue ) ) {
530                         break;
531                 }
532
533                 /* blocks */
534                 if ( !stricmp( token, "textures" ) ){
535                         parseEXblock ( EXpk3Textures, &EXpk3TexturesN, exName );
536                 }
537                 else if ( !stricmp( token, "shaders" ) ){
538                         parseEXblock ( EXpk3Shaders, &EXpk3ShadersN, exName );
539                 }
540                 else if ( !stricmp( token, "shaderfiles" ) ){
541                         parseEXblock ( EXpk3Shaderfiles, &EXpk3ShaderfilesN, exName );
542                 }
543                 else if ( !stricmp( token, "sounds" ) ){
544                         parseEXblock ( EXpk3Sounds, &EXpk3SoundsN, exName );
545                 }
546                 else if ( !stricmp( token, "videos" ) ){
547                         parseEXblock ( EXpk3Videos, &EXpk3VideosN, exName );
548                 }
549                 else{
550                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
551                 }
552         }
553
554         /* free the buffer */
555         free( buffer );
556
557 skipEXfile:
558
559         if( dbg ){
560                 Sys_Printf( "\tEXpk3Textures....%i\n", EXpk3TexturesN );
561                 for ( i = 0; i < EXpk3TexturesN; i++ ) Sys_Printf( "%s\n", EXpk3Textures[i] );
562                 Sys_Printf( "\tEXpk3Shaders....%i\n", EXpk3ShadersN );
563                 for ( i = 0; i < EXpk3ShadersN; i++ ) Sys_Printf( "%s\n", EXpk3Shaders[i] );
564                 Sys_Printf( "\tEXpk3Shaderfiles....%i\n", EXpk3ShaderfilesN );
565                 for ( i = 0; i < EXpk3ShaderfilesN; i++ ) Sys_Printf( "%s\n", EXpk3Shaderfiles[i] );
566                 Sys_Printf( "\tEXpk3Sounds....%i\n", EXpk3SoundsN );
567                 for ( i = 0; i < EXpk3SoundsN; i++ ) Sys_Printf( "%s\n", EXpk3Sounds[i] );
568                 Sys_Printf( "\tEXpk3Videos....%i\n", EXpk3VideosN );
569                 for ( i = 0; i < EXpk3VideosN; i++ ) Sys_Printf( "%s\n", EXpk3Videos[i] );
570         }
571
572         char temp[ 1024 ];
573
574         //Parse Shader Files
575         for ( i = 0; i < pk3ShaderfilesN; i++ ){
576                 qboolean wantShader = qfalse;
577                 qboolean wantShaderFile = qfalse;
578                 char shadername[ 1024 ];
579                 char lastwantedShader[ 1024 ];
580
581
582                 /* load the shader */
583                 sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles[ i ] );
584                 LoadScriptFile( temp, 0 );
585
586                 /* tokenize it */
587                 while ( 1 )
588                 {
589                         /* test for end of file */
590                         if ( !GetToken( qtrue ) ) {
591                                 break;
592                         }
593                         //dump shader names
594                         if( dbg ) Sys_Printf( "%s\n", token );
595
596                         /* do wanna le shader? */
597                         wantShader = qfalse;
598                         for ( j = 0; j < pk3ShadersN; j++ ){
599                                 if ( !stricmp( pk3Shaders[j], token) ){
600                                         strcpy ( shadername, pk3Shaders[j] );
601                                         pk3Shaders[j][0] = '\0';
602                                         wantShader = qtrue;
603                                         break;
604                                 }
605                         }
606
607                         /* handle { } section */
608                         if ( !GetToken( qtrue ) ) {
609                                 break;
610                         }
611                         if ( strcmp( token, "{" ) ) {
612                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
613                                                 temp, scriptline, token );
614                         }
615
616                         while ( 1 )
617                         {
618                                 /* get the next token */
619                                 if ( !GetToken( qtrue ) ) {
620                                         break;
621                                 }
622                                 if ( !strcmp( token, "}" ) ) {
623                                         break;
624                                 }
625
626
627                                 /* -----------------------------------------------------------------
628                                 shader stages (passes)
629                                 ----------------------------------------------------------------- */
630
631                                 /* parse stage directives */
632                                 if ( !strcmp( token, "{" ) ) {
633                                         while ( 1 )
634                                         {
635                                                 if ( !GetToken( qtrue ) ) {
636                                                         break;
637                                                 }
638                                                 if ( !strcmp( token, "}" ) ) {
639                                                         break;
640                                                 }
641                                                 if ( !wantShader ) continue;
642
643                                                 /* digest any images */
644                                                 if ( !stricmp( token, "map" ) ||
645                                                         !stricmp( token, "clampMap" ) ) {
646
647                                                         /* get an image */
648                                                         GetToken( qfalse );
649                                                         if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) {
650                                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
651                                                         }
652                                                 }
653                                                 else if ( !stricmp( token, "animMap" ) ||
654                                                         !stricmp( token, "clampAnimMap" ) ) {
655                                                         GetToken( qfalse );// skip num
656                                                         while ( TokenAvailable() ){
657                                                                 GetToken( qfalse );
658                                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
659                                                         }
660                                                 }
661                                                 else if ( !stricmp( token, "videoMap" ) ){
662                                                         GetToken( qfalse );
663                                                         FixDOSName( token );
664                                                         if ( strchr( token, "/" ) == NULL ){
665                                                                 sprintf( temp, "video/%s", token );
666                                                                 strcpy( token, temp );
667                                                         }
668                                                         for ( j = 0; j < pk3VideosN; j++ ){
669                                                                 if ( !stricmp( pk3Videos[j], token ) ){
670                                                                         goto away;
671                                                                 }
672                                                         }
673                                                         for ( j = 0; j < EXpk3VideosN; j++ ){
674                                                                 if ( !stricmp( EXpk3Videos[j], token ) ){
675                                                                         goto away;
676                                                                 }
677                                                         }
678                                                         strcpy ( pk3Videos[pk3VideosN], token );
679                                                         pk3VideosN++;
680                                                         away:
681                                                         j = 0;
682                                                 }
683                                         }
684                                 }
685                                 /* skip to the next shader */
686                                 else if ( !wantShader ) continue;
687
688                                 /* -----------------------------------------------------------------
689                                 surfaceparm * directives
690                                 ----------------------------------------------------------------- */
691
692                                 /* match surfaceparm */
693                                 else if ( !stricmp( token, "surfaceparm" ) ) {
694                                         GetToken( qfalse );
695                                         if ( !stricmp( token, "nodraw" ) ) {
696                                                 wantShader = qfalse;
697                                         }
698                                 }
699
700                                 /* skyparms <outer image> <cloud height> <inner image> */
701                                 else if ( !stricmp( token, "skyParms" ) ) {
702                                         /* get image base */
703                                         GetToken( qfalse );
704
705                                         /* ignore bogus paths */
706                                         if ( stricmp( token, "-" ) && stricmp( token, "full" ) ) {
707                                                 strcpy ( temp, token );
708                                                 sprintf( token, "%s_up", temp );
709                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
710                                                 sprintf( token, "%s_dn", temp );
711                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
712                                                 sprintf( token, "%s_lf", temp );
713                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
714                                                 sprintf( token, "%s_rt", temp );
715                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
716                                                 sprintf( token, "%s_bk", temp );
717                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
718                                                 sprintf( token, "%s_ft", temp );
719                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
720                                         }
721                                         /* skip rest of line */
722                                         GetToken( qfalse );
723                                         GetToken( qfalse );
724                                 }
725                         }
726                         //exclude shader
727                         if ( wantShader ){
728                                 for ( j = 0; j < EXpk3ShadersN; j++ ){
729                                         if ( !stricmp( EXpk3Shaders[j], shadername ) ){
730                                                 wantShader = qfalse;
731                                                 break;
732                                         }
733                                 }
734                                 /* shouldnt make shaders for shipped with the game textures aswell */
735                                 if ( wantShader ){
736                                         for ( j = 0; j < EXpk3TexturesN; j++ ){
737                                                 if ( !stricmp( EXpk3Textures[j], shadername ) ){
738                                                         wantShader = qfalse;
739                                                         break;
740                                                 }
741                                         }
742                                 }
743                                 if ( wantShader ){
744                                         wantShaderFile = qtrue;
745                                         strcpy( lastwantedShader, shadername );
746                                 }
747                         }
748                 }
749                 //exclude shader file
750                 if ( wantShaderFile ){
751                         for ( j = 0; j < EXpk3ShaderfilesN; j++ ){
752                                 if ( !stricmp( EXpk3Shaderfiles[j], pk3Shaderfiles[ i ] ) ){
753                                         Sys_Printf( "WARNING: excluded shader %s, since it was located in restricted shader file: %s\n", lastwantedShader, pk3Shaderfiles[i] );
754                                         pk3Shaderfiles[ i ][0] = '\0';
755                                         break;
756                                 }
757                         }
758                 }
759                 else {
760                         pk3Shaderfiles[ i ][0] = '\0';
761                 }
762
763         }
764
765
766
767 /* exclude stuff */
768 //pure textures (shader ones are done)
769         for ( i = 0; i < pk3ShadersN; i++ ){
770                 if ( pk3Shaders[i][0] != '\0' ){
771                         FixDOSName( pk3Shaders[i] );
772                         for ( j = 0; j < pk3TexturesN; j++ ){
773                                 if ( !stricmp( pk3Shaders[i], pk3Textures[j] ) ){
774                                         pk3Shaders[i][0] = '\0';
775                                         break;
776                                 }
777                         }
778                         if ( pk3Shaders[i][0] == '\0' ) continue;
779                         for ( j = 0; j < EXpk3TexturesN; j++ ){
780                                 if ( !stricmp( pk3Shaders[i], EXpk3Textures[j] ) ){
781                                         pk3Shaders[i][0] = '\0';
782                                         break;
783                                 }
784                         }
785                 }
786         }
787
788 //snds
789         for ( i = 0; i < pk3SoundsN; i++ ){
790                 FixDOSName( pk3Sounds[i] );
791                 for ( j = 0; j < EXpk3SoundsN; j++ ){
792                         if ( !stricmp( pk3Sounds[i], EXpk3Sounds[j] ) ){
793                                 pk3Sounds[i][0] = '\0';
794                                 break;
795                         }
796                 }
797         }
798
799         if( dbg ){
800                 Sys_Printf( "\tShader referenced textures....%i\n", pk3TexturesN );
801                 for ( i = 0; i < pk3TexturesN; i++ ){
802                         Sys_Printf( "%s\n", pk3Textures[i] );
803                 }
804                 Sys_Printf( "\tShader files....\n" );
805                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
806                         if ( pk3Shaderfiles[i][0] != '\0' ) Sys_Printf( "%s\n", pk3Shaderfiles[i] );
807                 }
808                 Sys_Printf( "\tPure textures....\n" );
809                 for ( i = 0; i < pk3ShadersN; i++ ){
810                         if ( pk3Shaders[i][0] != '\0' ) Sys_Printf( "%s\n", pk3Shaders[i] );
811                 }
812         }
813
814
815
816         sprintf( packname, "%s/%s_autopacked.pk3", EnginePath, nameOFmap );
817         remove( packname );
818
819         Sys_Printf( "--- ZipZip ---\n" );
820
821         Sys_Printf( "\n\tShader referenced textures....\n" );
822
823         for ( i = 0; i < pk3TexturesN; i++ ){
824                 if ( png ){
825                         sprintf( temp, "%s.png", pk3Textures[i] );
826                         if ( vfsPackFile( temp, packname ) ){
827                                 Sys_Printf( "++%s\n", temp );
828                                 continue;
829                         }
830                 }
831                 sprintf( temp, "%s.tga", pk3Textures[i] );
832                 if ( vfsPackFile( temp, packname ) ){
833                         Sys_Printf( "++%s\n", temp );
834                         continue;
835                 }
836                 sprintf( temp, "%s.jpg", pk3Textures[i] );
837                 if ( vfsPackFile( temp, packname ) ){
838                         Sys_Printf( "++%s\n", temp );
839                         continue;
840                 }
841                 Sys_Printf( "  !FAIL! %s\n", pk3Textures[i] );
842         }
843
844         Sys_Printf( "\n\tPure textures....\n" );
845
846         for ( i = 0; i < pk3ShadersN; i++ ){
847                 if ( pk3Shaders[i][0] != '\0' ){
848                         if ( png ){
849                                 sprintf( temp, "%s.png", pk3Shaders[i] );
850                                 if ( vfsPackFile( temp, packname ) ){
851                                         Sys_Printf( "++%s\n", temp );
852                                         continue;
853                                 }
854                         }
855                         sprintf( temp, "%s.tga", pk3Shaders[i] );
856                         if ( vfsPackFile( temp, packname ) ){
857                                 Sys_Printf( "++%s\n", temp );
858                                 continue;
859                         }
860                         sprintf( temp, "%s.jpg", pk3Shaders[i] );
861                         if ( vfsPackFile( temp, packname ) ){
862                                 Sys_Printf( "++%s\n", temp );
863                                 continue;
864                         }
865                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders[i] );
866                 }
867         }
868
869         Sys_Printf( "\n\tShaizers....\n" );
870
871         for ( i = 0; i < pk3ShaderfilesN; i++ ){
872                 if ( pk3Shaderfiles[i][0] != '\0' ){
873                         sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles[ i ] );
874                         if ( vfsPackFile( temp, packname ) ){
875                                 Sys_Printf( "++%s\n", temp );
876                                 continue;
877                         }
878                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders[i] );
879                 }
880         }
881
882         Sys_Printf( "\n\tSounds....\n" );
883
884         for ( i = 0; i < pk3SoundsN; i++ ){
885                 if ( pk3Sounds[i][0] != '\0' ){
886                         if ( vfsPackFile( pk3Sounds[ i ], packname ) ){
887                                 Sys_Printf( "++%s\n", pk3Sounds[ i ] );
888                                 continue;
889                         }
890                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds[i] );
891                 }
892         }
893
894         Sys_Printf( "\n\tVideos....\n" );
895
896         for ( i = 0; i < pk3VideosN; i++ ){
897                 if ( vfsPackFile( pk3Videos[i], packname ) ){
898                         Sys_Printf( "++%s\n", pk3Videos[i] );
899                         continue;
900                 }
901                 Sys_Printf( "  !FAIL! %s\n", pk3Videos[i] );
902         }
903
904         Sys_Printf( "\n\t.\n" );
905
906         sprintf( temp, "maps/%s.bsp", nameOFmap );
907         if ( vfsPackFile( temp, packname ) ){
908                         Sys_Printf( "++%s\n", temp );
909                 }
910         else{
911                 Sys_Printf( "  !FAIL! %s\n", temp );
912         }
913
914         sprintf( temp, "maps/%s.aas", nameOFmap );
915         if ( vfsPackFile( temp, packname ) ){
916                         Sys_Printf( "++%s\n", temp );
917                 }
918         else{
919                 Sys_Printf( "  !FAIL! %s\n", temp );
920         }
921
922         sprintf( temp, "scripts/%s.arena", nameOFmap );
923         if ( vfsPackFile( temp, packname ) ){
924                         Sys_Printf( "++%s\n", temp );
925                 }
926         else{
927                 Sys_Printf( "  !FAIL! %s\n", temp );
928         }
929
930         sprintf( temp, "scripts/%s.defi", nameOFmap );
931         if ( vfsPackFile( temp, packname ) ){
932                         Sys_Printf( "++%s\n", temp );
933                 }
934         else{
935                 Sys_Printf( "  !FAIL! %s\n", temp );
936         }
937
938         Sys_Printf( "\nSaved to %s\n", packname );
939         /* return to sender */
940         return 0;
941 }
942
943
944 /*
945    main()
946    q3map mojo...
947  */
948
949 int main( int argc, char **argv ){
950         int i, r;
951         double start, end;
952         extern qboolean werror;
953
954
955         /* we want consistent 'randomness' */
956         srand( 0 );
957
958         /* start timer */
959         start = I_FloatTime();
960
961         /* this was changed to emit version number over the network */
962         printf( Q3MAP_VERSION "\n" );
963
964         /* set exit call */
965         atexit( ExitQ3Map );
966
967         /* read general options first */
968         for ( i = 1; i < argc; i++ )
969         {
970                 /* -help */
971                 if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
972                         || !strcmp( argv[ i ], "-help" ) ) {
973                         HelpMain(argv[i+1]);
974                         return 0;
975                 }
976
977                 /* -connect */
978                 if ( !strcmp( argv[ i ], "-connect" ) ) {
979                         argv[ i ] = NULL;
980                         i++;
981                         Broadcast_Setup( argv[ i ] );
982                         argv[ i ] = NULL;
983                 }
984
985                 /* verbose */
986                 else if ( !strcmp( argv[ i ], "-v" ) ) {
987                         if ( !verbose ) {
988                                 verbose = qtrue;
989                                 argv[ i ] = NULL;
990                         }
991                 }
992
993                 /* force */
994                 else if ( !strcmp( argv[ i ], "-force" ) ) {
995                         force = qtrue;
996                         argv[ i ] = NULL;
997                 }
998
999                 /* make all warnings into errors */
1000                 else if ( !strcmp( argv[ i ], "-werror" ) ) {
1001                         werror = qtrue;
1002                         argv[ i ] = NULL;
1003                 }
1004
1005                 /* patch subdivisions */
1006                 else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
1007                         argv[ i ] = NULL;
1008                         i++;
1009                         patchSubdivisions = atoi( argv[ i ] );
1010                         argv[ i ] = NULL;
1011                         if ( patchSubdivisions <= 0 ) {
1012                                 patchSubdivisions = 1;
1013                         }
1014                 }
1015
1016                 /* threads */
1017                 else if ( !strcmp( argv[ i ], "-threads" ) ) {
1018                         argv[ i ] = NULL;
1019                         i++;
1020                         numthreads = atoi( argv[ i ] );
1021                         argv[ i ] = NULL;
1022                 }
1023
1024                 else if( !strcmp( argv[ i ], "-nocmdline" ) )
1025                 {
1026                         Sys_Printf( "noCmdLine\n" );
1027                         nocmdline = qtrue;
1028                         argv[ i ] = NULL;
1029                 }
1030
1031         }
1032
1033         /* init model library */
1034         PicoInit();
1035         PicoSetMallocFunc( safe_malloc );
1036         PicoSetFreeFunc( free );
1037         PicoSetPrintFunc( PicoPrintFunc );
1038         PicoSetLoadFileFunc( PicoLoadFileFunc );
1039         PicoSetFreeFileFunc( free );
1040
1041         /* set number of threads */
1042         ThreadSetDefault();
1043
1044         /* generate sinusoid jitter table */
1045         for ( i = 0; i < MAX_JITTERS; i++ )
1046         {
1047                 jitters[ i ] = sin( i * 139.54152147 );
1048                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
1049         }
1050
1051         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
1052            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
1053
1054         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
1055         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
1056         Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
1057         Sys_Printf( "%s\n", Q3MAP_MOTD );
1058         Sys_Printf( "%s\n", argv[0] );
1059
1060         strcpy( q3map2path, argv[0] );//fuer autoPack func
1061
1062         /* ydnar: new path initialization */
1063         InitPaths( &argc, argv );
1064
1065         /* set game options */
1066         if ( !patchSubdivisions ) {
1067                 patchSubdivisions = game->patchSubdivisions;
1068         }
1069
1070         /* check if we have enough options left to attempt something */
1071         if ( argc < 2 ) {
1072                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
1073         }
1074
1075         /* fixaas */
1076         if ( !strcmp( argv[ 1 ], "-fixaas" ) ) {
1077                 r = FixAASMain( argc - 1, argv + 1 );
1078         }
1079
1080         /* analyze */
1081         else if ( !strcmp( argv[ 1 ], "-analyze" ) ) {
1082                 r = AnalyzeBSPMain( argc - 1, argv + 1 );
1083         }
1084
1085         /* info */
1086         else if ( !strcmp( argv[ 1 ], "-info" ) ) {
1087                 r = BSPInfoMain( argc - 2, argv + 2 );
1088         }
1089
1090         /* vis */
1091         else if ( !strcmp( argv[ 1 ], "-vis" ) ) {
1092                 r = VisMain( argc - 1, argv + 1 );
1093         }
1094
1095         /* light */
1096         else if ( !strcmp( argv[ 1 ], "-light" ) ) {
1097                 r = LightMain( argc - 1, argv + 1 );
1098         }
1099
1100         /* vlight */
1101         else if ( !strcmp( argv[ 1 ], "-vlight" ) ) {
1102                 Sys_FPrintf( SYS_WRN, "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
1103                 argv[ 1 ] = "-fast";    /* eek a hack */
1104                 r = LightMain( argc, argv );
1105         }
1106
1107         /* QBall: export entities */
1108         else if ( !strcmp( argv[ 1 ], "-exportents" ) ) {
1109                 r = ExportEntitiesMain( argc - 1, argv + 1 );
1110         }
1111
1112         /* ydnar: lightmap export */
1113         else if ( !strcmp( argv[ 1 ], "-export" ) ) {
1114                 r = ExportLightmapsMain( argc - 1, argv + 1 );
1115         }
1116
1117         /* ydnar: lightmap import */
1118         else if ( !strcmp( argv[ 1 ], "-import" ) ) {
1119                 r = ImportLightmapsMain( argc - 1, argv + 1 );
1120         }
1121
1122         /* ydnar: bsp scaling */
1123         else if ( !strcmp( argv[ 1 ], "-scale" ) ) {
1124                 r = ScaleBSPMain( argc - 1, argv + 1 );
1125         }
1126
1127         /* bsp shifting */
1128         else if ( !strcmp( argv[ 1 ], "-shift" ) ) {
1129                 r = ShiftBSPMain( argc - 1, argv + 1 );
1130         }
1131
1132         /* autopacking */
1133         else if ( !strcmp( argv[ 1 ], "-pk3" ) ) {
1134                 r = pk3BSPMain( argc - 1, argv + 1 );
1135         }
1136
1137         /* ydnar: bsp conversion */
1138         else if ( !strcmp( argv[ 1 ], "-convert" ) ) {
1139                 r = ConvertBSPMain( argc - 1, argv + 1 );
1140         }
1141
1142         /* div0: minimap */
1143         else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
1144                 r = MiniMapBSPMain( argc - 1, argv + 1 );
1145         }
1146
1147         /* ydnar: otherwise create a bsp */
1148         else{
1149                 r = BSPMain( argc, argv );
1150         }
1151
1152         /* emit time */
1153         end = I_FloatTime();
1154         Sys_Printf( "%9.0f seconds elapsed\n", end - start );
1155
1156         /* shut down connection */
1157         Broadcast_Shutdown();
1158
1159         /* return any error code */
1160         return r;
1161 }