]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/main.c
Merge commit '66d12fc2373b05233aa29ee097efe820f05a8520' 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, int *texnum, char* EXtex, 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 ( !Q_stricmp( texlist[i], token ) ) return;
296         }
297         for ( i = 0; i < *EXtexnum; i++ ){
298                 if ( !Q_stricmp( EXtex[i], token ) ) return;
299         }
300         strcpy ( texlist + (*texnum)*65, token );
301         (*texnum)++;
302         return;
303 }
304
305
306 /*
307         Check if newcoming res is unique
308 */
309 void res2list( char* data, int *num ){
310         int i;
311         if ( *( data + (*num)*65 ) == '\0') return;
312         for ( i = 0; i < *num; i++ ){
313                 if ( !Q_stricmp( data[i], data[*num] ) ) return;
314         }
315         (*num)++;
316         return;
317 }
318
319 void parseEXblock ( char* data, 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)*65, 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, len;
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         /* do some path mangling */
363         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
364         StripExtension( source );
365         DefaultExtension( source, ".bsp" );
366
367         /* load the bsp */
368         Sys_Printf( "Loading %s\n", source );
369         LoadBSPFile( source );
370         ParseEntities();
371
372
373         char packname[ 1024 ], base[ 1024 ], nameOFmap[ 1024 ], temp[ 1024 ];
374
375         /* copy map name */
376         strcpy( base, source );
377         StripExtension( base );
378
379         /* extract map name */
380         len = strlen( base ) - 1;
381         while ( len > 0 && base[ len ] != '/' && base[ len ] != '\\' )
382                 len--;
383         strcpy( nameOFmap, &base[ len + 1 ] );
384
385
386         qboolean drawsurfSHs[1024] = { qfalse };
387
388         for ( i = 0; i < numBSPDrawSurfaces; i++ ){
389                 /* can't exclude nodraw patches here (they want shaders :0!) */
390                 //if ( !( bspDrawSurfaces[i].surfaceType == 2 && bspDrawSurfaces[i].numIndexes == 0 ) ) drawsurfSHs[bspDrawSurfaces[i].shaderNum] = qtrue;
391                 drawsurfSHs[ bspDrawSurfaces[i].shaderNum ] = qtrue;
392                 //Sys_Printf( "%s\n", bspShaders[bspDrawSurfaces[i].shaderNum].shader );
393         }
394
395         int pk3ShadersN = 0;
396         char* pk3Shaders;
397         pk3Shaders = (char *)calloc( 1024*65, sizeof( char ) );
398         int pk3SoundsN = 0;
399         char* pk3Sounds;
400         pk3Sounds = (char *)calloc( 1024*65, sizeof( char ) );
401         int pk3ShaderfilesN = 0;
402         char* pk3Shaderfiles;
403         pk3Shaderfiles = (char *)calloc( 1024*65, sizeof( char ) );
404         int pk3TexturesN = 0;
405         char* pk3Textures;
406         pk3Textures = (char *)calloc( 1024*65, sizeof( char ) );
407         int pk3VideosN = 0;
408         char* pk3Videos;
409         pk3Videos = (char *)calloc( 1024*65, sizeof( char ) );
410
411
412
413         for ( i = 0; i < numBSPShaders; i++ ){
414                 if ( drawsurfSHs[i] ){
415                         strcpy( pk3Shaders + pk3ShadersN*65, 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 ( !Q_strncasecmp( ep->key, "vertexremapshader", 17 ) ) {
427                         sscanf( ep->value, "%*[^;] %*[;] %s", pk3Shaders + pk3ShadersN*65 );
428                         res2list( pk3Shaders, &pk3ShadersN );
429                 }
430         }
431         strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[0], "music" ) );
432         if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' ){
433                 FixDOSName( pk3Sounds + pk3SoundsN*65 );
434                 DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
435                 res2list( pk3Sounds, &pk3SoundsN );
436         }
437
438         for ( i = 0; i < numBSPEntities && i < numEntities; i++ )
439         {
440                 strcpy( pk3Sounds + pk3SoundsN*65, ValueForKey( &entities[i], "noise" ) );
441                 if ( *( pk3Sounds + pk3SoundsN*65 ) != '\0' && *( pk3Sounds + pk3SoundsN*65 ) != '*' ){
442                         FixDOSName( pk3Sounds + pk3SoundsN*65 );
443                         DefaultExtension( pk3Sounds + pk3SoundsN*65, ".wav" );
444                         res2list( pk3Sounds, &pk3SoundsN );
445                 }
446
447                 if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "func_plat" ) ){
448                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_strt.wav");
449                         res2list( pk3Sounds, &pk3SoundsN );
450                         strcpy( pk3Sounds + pk3SoundsN*65, "sound/movers/plats/pt1_end.wav");
451                         res2list( pk3Sounds, &pk3SoundsN );
452                 }
453                 if ( !Q_stricmp( ValueForKey( &entities[i], "classname" ), "target_push" ) ){
454                         if ( !(IntForKey( &entities[i], "spawnflags") & 1) ){
455                                 strcpy( pk3Sounds + pk3SoundsN*65, "sound/misc/windfly.wav");
456                                 res2list( pk3Sounds, &pk3SoundsN );
457                         }
458                 }
459                 strcpy( pk3Shaders + pk3ShadersN*65, ValueForKey( &entities[i], "targetShaderNewName" ) );
460                 res2list( pk3Shaders, &pk3ShadersN );
461         }
462
463         //levelshot
464         sprintf( pk3Shaders + pk3ShadersN*65, "levelshots/%s", nameOFmap );
465         res2list( pk3Shaders, &pk3ShadersN );
466
467
468         if( dbg ){
469                 Sys_Printf( "\tDrawsurface+ent calls....%i\n", pk3ShadersN );
470                 for ( i = 0; i < pk3ShadersN; i++ ){
471                         Sys_Printf( "%s\n", pk3Shaders + i*65 );
472                 }
473                 Sys_Printf( "\tSounds....%i\n", pk3SoundsN );
474                 for ( i = 0; i < pk3SoundsN; i++ ){
475                         Sys_Printf( "%s\n", pk3Sounds + i*65 );
476                 }
477         }
478
479         vfsListShaderFiles( pk3Shaderfiles, &pk3ShaderfilesN );
480
481         if( dbg ){
482                 Sys_Printf( "\tSchroider fileses.....%i\n", pk3ShaderfilesN );
483                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
484                         Sys_Printf( "%s\n", pk3Shaderfiles + i*65 );
485                 }
486         }
487
488
489         /* load exclusions file */
490         int EXpk3TexturesN = 0;
491         char* EXpk3Textures;
492         EXpk3Textures = (char *)calloc( 4096*65, sizeof( char ) );
493         int EXpk3ShadersN = 0;
494         char* EXpk3Shaders;
495         EXpk3Shaders = (char *)calloc( 4096*65, sizeof( char ) );
496         int EXpk3SoundsN = 0;
497         char* EXpk3Sounds;
498         EXpk3Sounds = (char *)calloc( 4096*65, sizeof( char ) );
499         int EXpk3ShaderfilesN = 0;
500         char* EXpk3Shaderfiles;
501         EXpk3Shaderfiles = (char *)calloc( 4096*65, sizeof( char ) );
502         int EXpk3VideosN = 0;
503         char* EXpk3Videos;
504         EXpk3Videos = (char *)calloc( 4096*65, sizeof( char ) );
505
506         char exName[ 1024 ];
507         byte *buffer;
508         int size;
509
510         strcpy( exName, q3map2path );
511         char *cut = strrchr( exName, '\\' );
512         char *cut2 = strrchr( exName, '/' );
513         if ( cut == NULL && cut2 == NULL ){
514                 Sys_Printf( "WARNING: Unable to load exclusions file.\n" );
515                 goto skipEXfile;
516         }
517         if ( cut2 > cut ) cut = cut2;
518         cut[1] = '\0';
519         strcat( exName, game->arg );
520         strcat( exName, ".exclude" );
521
522         Sys_Printf( "Loading %s\n", exName );
523         size = TryLoadFile( exName, (void**) &buffer );
524         if ( size <= 0 ) {
525                 Sys_Printf( "WARNING: Unable to find exclusions file %s.\n", exName );
526                 goto skipEXfile;
527         }
528
529         /* parse the file */
530         ParseFromMemory( (char *) buffer, size );
531
532         /* tokenize it */
533         while ( 1 )
534         {
535                 /* test for end of file */
536                 if ( !GetToken( qtrue ) ) {
537                         break;
538                 }
539
540                 /* blocks */
541                 if ( !Q_stricmp( token, "textures" ) ){
542                         parseEXblock ( EXpk3Textures, &EXpk3TexturesN, exName );
543                 }
544                 else if ( !Q_stricmp( token, "shaders" ) ){
545                         parseEXblock ( EXpk3Shaders, &EXpk3ShadersN, exName );
546                 }
547                 else if ( !Q_stricmp( token, "shaderfiles" ) ){
548                         parseEXblock ( EXpk3Shaderfiles, &EXpk3ShaderfilesN, exName );
549                 }
550                 else if ( !Q_stricmp( token, "sounds" ) ){
551                         parseEXblock ( EXpk3Sounds, &EXpk3SoundsN, exName );
552                 }
553                 else if ( !Q_stricmp( token, "videos" ) ){
554                         parseEXblock ( EXpk3Videos, &EXpk3VideosN, exName );
555                 }
556                 else{
557                         Error( "ReadExclusionsFile: %s, line %d: unknown block name!\nValid ones are: textures, shaders, shaderfiles, sounds, videos.", exName, scriptline );
558                 }
559         }
560
561         /* free the buffer */
562         free( buffer );
563
564 skipEXfile:
565
566         if( dbg ){
567                 Sys_Printf( "\tEXpk3Textures....%i\n", EXpk3TexturesN );
568                 for ( i = 0; i < EXpk3TexturesN; i++ ) Sys_Printf( "%s\n", EXpk3Textures + i*65 );
569                 Sys_Printf( "\tEXpk3Shaders....%i\n", EXpk3ShadersN );
570                 for ( i = 0; i < EXpk3ShadersN; i++ ) Sys_Printf( "%s\n", EXpk3Shaders + i*65 );
571                 Sys_Printf( "\tEXpk3Shaderfiles....%i\n", EXpk3ShaderfilesN );
572                 for ( i = 0; i < EXpk3ShaderfilesN; i++ ) Sys_Printf( "%s\n", EXpk3Shaderfiles + i*65 );
573                 Sys_Printf( "\tEXpk3Sounds....%i\n", EXpk3SoundsN );
574                 for ( i = 0; i < EXpk3SoundsN; i++ ) Sys_Printf( "%s\n", EXpk3Sounds + i*65 );
575                 Sys_Printf( "\tEXpk3Videos....%i\n", EXpk3VideosN );
576                 for ( i = 0; i < EXpk3VideosN; i++ ) Sys_Printf( "%s\n", EXpk3Videos + i*65 );
577         }
578
579
580         //Parse Shader Files
581         for ( i = 0; i < pk3ShaderfilesN; i++ ){
582                 qboolean wantShader = qfalse, wantShaderFile = qfalse;
583                 char shadername[ 1024 ], lastwantedShader[ 1024 ];
584
585                 /* load the shader */
586                 sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
587                 LoadScriptFile( temp, 0 );
588
589                 /* tokenize it */
590                 while ( 1 )
591                 {
592                         /* test for end of file */
593                         if ( !GetToken( qtrue ) ) {
594                                 break;
595                         }
596                         //dump shader names
597                         if( dbg ) Sys_Printf( "%s\n", token );
598
599                         /* do wanna le shader? */
600                         wantShader = qfalse;
601                         for ( j = 0; j < pk3ShadersN; j++ ){
602                                 if ( !Q_stricmp( pk3Shaders + j*65, token) ){
603                                         strcpy ( shadername, pk3Shaders + j*65 );
604                                         *(pk3Shaders + j*65) = '\0';
605                                         wantShader = qtrue;
606                                         break;
607                                 }
608                         }
609
610                         /* handle { } section */
611                         if ( !GetToken( qtrue ) ) {
612                                 break;
613                         }
614                         if ( strcmp( token, "{" ) ) {
615                                         Error( "ParseShaderFile: %s, line %d: { not found!\nFound instead: %s",
616                                                 temp, scriptline, token );
617                         }
618
619                         while ( 1 )
620                         {
621                                 /* get the next token */
622                                 if ( !GetToken( qtrue ) ) {
623                                         break;
624                                 }
625                                 if ( !strcmp( token, "}" ) ) {
626                                         break;
627                                 }
628
629
630                                 /* -----------------------------------------------------------------
631                                 shader stages (passes)
632                                 ----------------------------------------------------------------- */
633
634                                 /* parse stage directives */
635                                 if ( !strcmp( token, "{" ) ) {
636                                         while ( 1 )
637                                         {
638                                                 if ( !GetToken( qtrue ) ) {
639                                                         break;
640                                                 }
641                                                 if ( !strcmp( token, "}" ) ) {
642                                                         break;
643                                                 }
644                                                 /* skip the shader */
645                                                 if ( !wantShader ) continue;
646
647                                                 /* digest any images */
648                                                 if ( !Q_stricmp( token, "map" ) ||
649                                                         !Q_stricmp( token, "clampMap" ) ) {
650
651                                                         /* get an image */
652                                                         GetToken( qfalse );
653                                                         if ( token[ 0 ] != '*' && token[ 0 ] != '$' ) {
654                                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
655                                                         }
656                                                 }
657                                                 else if ( !Q_stricmp( token, "animMap" ) ||
658                                                         !Q_stricmp( token, "clampAnimMap" ) ) {
659                                                         GetToken( qfalse );// skip num
660                                                         while ( TokenAvailable() ){
661                                                                 GetToken( qfalse );
662                                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
663                                                         }
664                                                 }
665                                                 else if ( !Q_stricmp( token, "videoMap" ) ){
666                                                         GetToken( qfalse );
667                                                         FixDOSName( token );
668                                                         if ( strchr( token, "/" ) == NULL ){
669                                                                 sprintf( temp, "video/%s", token );
670                                                                 strcpy( token, temp );
671                                                         }
672                                                         for ( j = 0; j < pk3VideosN; j++ ){
673                                                                 if ( !Q_stricmp( pk3Videos + j*65, token ) ){
674                                                                         goto away;
675                                                                 }
676                                                         }
677                                                         for ( j = 0; j < EXpk3VideosN; j++ ){
678                                                                 if ( !Q_stricmp( EXpk3Videos + j*65, token ) ){
679                                                                         goto away;
680                                                                 }
681                                                         }
682                                                         strcpy ( pk3Videos + pk3VideosN*65, token );
683                                                         pk3VideosN++;
684                                                         away:
685                                                         j = 0;
686                                                 }
687                                         }
688                                 }
689                                 /* skip the shader */
690                                 else if ( !wantShader ) continue;
691
692                                 /* -----------------------------------------------------------------
693                                 surfaceparm * directives
694                                 ----------------------------------------------------------------- */
695
696                                 /* match surfaceparm */
697                                 else if ( !Q_stricmp( token, "surfaceparm" ) ) {
698                                         GetToken( qfalse );
699                                         if ( !Q_stricmp( token, "nodraw" ) ) {
700                                                 wantShader = qfalse;
701                                         }
702                                 }
703
704                                 /* skyparms <outer image> <cloud height> <inner image> */
705                                 else if ( !Q_stricmp( token, "skyParms" ) ) {
706                                         /* get image base */
707                                         GetToken( qfalse );
708
709                                         /* ignore bogus paths */
710                                         if ( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) ) {
711                                                 strcpy ( temp, token );
712                                                 sprintf( token, "%s_up", temp );
713                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
714                                                 sprintf( token, "%s_dn", temp );
715                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
716                                                 sprintf( token, "%s_lf", temp );
717                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
718                                                 sprintf( token, "%s_rt", temp );
719                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
720                                                 sprintf( token, "%s_bk", temp );
721                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
722                                                 sprintf( token, "%s_ft", temp );
723                                                 tex2list( pk3Textures, &pk3TexturesN, EXpk3Textures, &EXpk3TexturesN );
724                                         }
725                                         /* skip rest of line */
726                                         GetToken( qfalse );
727                                         GetToken( qfalse );
728                                 }
729                         }
730                         //exclude shader
731                         if ( wantShader ){
732                                 for ( j = 0; j < EXpk3ShadersN; j++ ){
733                                         if ( !Q_stricmp( EXpk3Shaders + j*65, shadername ) ){
734                                                 wantShader = qfalse;
735                                                 break;
736                                         }
737                                 }
738                                 /* shouldnt make shaders for shipped with the game textures aswell */
739                                 if ( wantShader ){
740                                         for ( j = 0; j < EXpk3TexturesN; j++ ){
741                                                 if ( !Q_stricmp( EXpk3Textures + j*65, shadername ) ){
742                                                         wantShader = qfalse;
743                                                         break;
744                                                 }
745                                         }
746                                 }
747                                 if ( wantShader ){
748                                         wantShaderFile = qtrue;
749                                         strcpy( lastwantedShader, shadername );
750                                 }
751                         }
752                 }
753                 //exclude shader file
754                 if ( wantShaderFile ){
755                         for ( j = 0; j < EXpk3ShaderfilesN; j++ ){
756                                 if ( !Q_stricmp( EXpk3Shaderfiles + j*65, pk3Shaderfiles + i*65 ) ){
757                                         Sys_Printf( "WARNING: excluded shader %s, since it was located in restricted shader file: %s\n", lastwantedShader, pk3Shaderfiles + i*65 );
758                                         *( pk3Shaderfiles + i*65 ) = '\0';
759                                         break;
760                                 }
761                         }
762                 }
763                 else {
764                         *( pk3Shaderfiles + i*65 ) = '\0';
765                 }
766
767         }
768
769
770
771 /* exclude stuff */
772 //pure textures (shader ones are done)
773         for ( i = 0; i < pk3ShadersN; i++ ){
774                 if ( *( pk3Shaders + i*65 ) != '\0' ){
775                         FixDOSName( pk3Shaders + i*65 );
776                         for ( j = 0; j < pk3TexturesN; j++ ){
777                                 if ( !Q_stricmp( pk3Shaders + i*65, pk3Textures + j*65 ) ){
778                                         *( pk3Shaders + i*65 ) = '\0';
779                                         break;
780                                 }
781                         }
782                         if ( *( pk3Shaders + i*65 ) == '\0' ) continue;
783                         for ( j = 0; j < EXpk3TexturesN; j++ ){
784                                 if ( !Q_stricmp( pk3Shaders + i*65, EXpk3Textures + j*65 ) ){
785                                         *( pk3Shaders + i*65 ) = '\0';
786                                         break;
787                                 }
788                         }
789                 }
790         }
791
792 //snds
793         for ( i = 0; i < pk3SoundsN; i++ ){
794                 for ( j = 0; j < EXpk3SoundsN; j++ ){
795                         if ( !Q_stricmp( pk3Sounds + i*65, EXpk3Sounds + j*65 ) ){
796                                 *( pk3Sounds + i*65 ) = '\0';
797                                 break;
798                         }
799                 }
800         }
801
802         if( dbg ){
803                 Sys_Printf( "\tShader referenced textures....%i\n", pk3TexturesN );
804                 for ( i = 0; i < pk3TexturesN; i++ ){
805                         Sys_Printf( "%s\n", pk3Textures + i*65 );
806                 }
807                 Sys_Printf( "\tShader files....\n" );
808                 for ( i = 0; i < pk3ShaderfilesN; i++ ){
809                         if ( *( pk3Shaderfiles + i*65 ) != '\0' ) Sys_Printf( "%s\n", pk3Shaderfiles + i*65 );
810                 }
811                 Sys_Printf( "\tPure textures....\n" );
812                 for ( i = 0; i < pk3ShadersN; i++ ){
813                         if ( *( pk3Shaders + i*65 ) != '\0' ) Sys_Printf( "%s\n", pk3Shaders + i*65 );
814                 }
815         }
816
817
818         sprintf( packname, "%s/%s_autopacked.pk3", EnginePath, nameOFmap );
819         remove( packname );
820
821         Sys_Printf( "--- ZipZip ---\n" );
822
823         Sys_Printf( "\n\tShader referenced textures....\n" );
824
825         for ( i = 0; i < pk3TexturesN; i++ ){
826                 if ( png ){
827                         sprintf( temp, "%s.png", pk3Textures + i*65 );
828                         if ( vfsPackFile( temp, packname ) ){
829                                 Sys_Printf( "++%s\n", temp );
830                                 continue;
831                         }
832                 }
833                 sprintf( temp, "%s.tga", pk3Textures + i*65 );
834                 if ( vfsPackFile( temp, packname ) ){
835                         Sys_Printf( "++%s\n", temp );
836                         continue;
837                 }
838                 sprintf( temp, "%s.jpg", pk3Textures + i*65 );
839                 if ( vfsPackFile( temp, packname ) ){
840                         Sys_Printf( "++%s\n", temp );
841                         continue;
842                 }
843                 Sys_Printf( "  !FAIL! %s\n", pk3Textures + i*65 );
844         }
845
846         Sys_Printf( "\n\tPure textures....\n" );
847
848         for ( i = 0; i < pk3ShadersN; i++ ){
849                 if ( *( pk3Shaders + i*65 ) != '\0' ){
850                         if ( png ){
851                                 sprintf( temp, "%s.png", pk3Shaders + i*65 );
852                                 if ( vfsPackFile( temp, packname ) ){
853                                         Sys_Printf( "++%s\n", temp );
854                                         continue;
855                                 }
856                         }
857                         sprintf( temp, "%s.tga", pk3Shaders + i*65 );
858                         if ( vfsPackFile( temp, packname ) ){
859                                 Sys_Printf( "++%s\n", temp );
860                                 continue;
861                         }
862                         sprintf( temp, "%s.jpg", pk3Shaders + i*65 );
863                         if ( vfsPackFile( temp, packname ) ){
864                                 Sys_Printf( "++%s\n", temp );
865                                 continue;
866                         }
867                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
868                 }
869         }
870
871         Sys_Printf( "\n\tShaizers....\n" );
872
873         for ( i = 0; i < pk3ShaderfilesN; i++ ){
874                 if ( *( pk3Shaderfiles + i*65 ) != '\0' ){
875                         sprintf( temp, "%s/%s", game->shaderPath, pk3Shaderfiles + i*65 );
876                         if ( vfsPackFile( temp, packname ) ){
877                                 Sys_Printf( "++%s\n", temp );
878                                 continue;
879                         }
880                         Sys_Printf( "  !FAIL! %s\n", pk3Shaders + i*65 );
881                 }
882         }
883
884         Sys_Printf( "\n\tSounds....\n" );
885
886         for ( i = 0; i < pk3SoundsN; i++ ){
887                 if ( *( pk3Sounds + i*65 ) != '\0' ){
888                         if ( vfsPackFile( pk3Sounds + i*65, packname ) ){
889                                 Sys_Printf( "++%s\n", pk3Sounds + i*65 );
890                                 continue;
891                         }
892                         Sys_Printf( "  !FAIL! %s\n", pk3Sounds + i*65 );
893                 }
894         }
895
896         Sys_Printf( "\n\tVideos....\n" );
897
898         for ( i = 0; i < pk3VideosN; i++ ){
899                 if ( vfsPackFile( pk3Videos + i*65, packname ) ){
900                         Sys_Printf( "++%s\n", pk3Videos + i*65 );
901                         continue;
902                 }
903                 Sys_Printf( "  !FAIL! %s\n", pk3Videos + i*65 );
904         }
905
906         Sys_Printf( "\n\t.\n" );
907
908         sprintf( temp, "maps/%s.bsp", nameOFmap );
909         if ( vfsPackFile( temp, packname ) ){
910                         Sys_Printf( "++%s\n", temp );
911                 }
912         else{
913                 Sys_Printf( "  !FAIL! %s\n", temp );
914         }
915
916         sprintf( temp, "maps/%s.aas", nameOFmap );
917         if ( vfsPackFile( temp, packname ) ){
918                         Sys_Printf( "++%s\n", temp );
919                 }
920         else{
921                 Sys_Printf( "  !FAIL! %s\n", temp );
922         }
923
924         sprintf( temp, "scripts/%s.arena", nameOFmap );
925         if ( vfsPackFile( temp, packname ) ){
926                         Sys_Printf( "++%s\n", temp );
927                 }
928         else{
929                 Sys_Printf( "  !FAIL! %s\n", temp );
930         }
931
932         sprintf( temp, "scripts/%s.defi", nameOFmap );
933         if ( vfsPackFile( temp, packname ) ){
934                         Sys_Printf( "++%s\n", temp );
935                 }
936         else{
937                 Sys_Printf( "  !FAIL! %s\n", temp );
938         }
939
940         Sys_Printf( "\nSaved to %s\n", packname );
941         /* return to sender */
942         return 0;
943 }
944
945
946 /*
947    main()
948    q3map mojo...
949  */
950
951 int main( int argc, char **argv ){
952         int i, r;
953         double start, end;
954         extern qboolean werror;
955
956
957         /* we want consistent 'randomness' */
958         srand( 0 );
959
960         /* start timer */
961         start = I_FloatTime();
962
963         /* this was changed to emit version number over the network */
964         printf( Q3MAP_VERSION "\n" );
965
966         /* set exit call */
967         atexit( ExitQ3Map );
968
969         /* read general options first */
970         for ( i = 1; i < argc; i++ )
971         {
972                 /* -help */
973                 if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
974                         || !strcmp( argv[ i ], "-help" ) ) {
975                         HelpMain(argv[i+1]);
976                         return 0;
977                 }
978
979                 /* -connect */
980                 if ( !strcmp( argv[ i ], "-connect" ) ) {
981                         argv[ i ] = NULL;
982                         i++;
983                         Broadcast_Setup( argv[ i ] );
984                         argv[ i ] = NULL;
985                 }
986
987                 /* verbose */
988                 else if ( !strcmp( argv[ i ], "-v" ) ) {
989                         if ( !verbose ) {
990                                 verbose = qtrue;
991                                 argv[ i ] = NULL;
992                         }
993                 }
994
995                 /* force */
996                 else if ( !strcmp( argv[ i ], "-force" ) ) {
997                         force = qtrue;
998                         argv[ i ] = NULL;
999                 }
1000
1001                 /* make all warnings into errors */
1002                 else if ( !strcmp( argv[ i ], "-werror" ) ) {
1003                         werror = qtrue;
1004                         argv[ i ] = NULL;
1005                 }
1006
1007                 /* patch subdivisions */
1008                 else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
1009                         argv[ i ] = NULL;
1010                         i++;
1011                         patchSubdivisions = atoi( argv[ i ] );
1012                         argv[ i ] = NULL;
1013                         if ( patchSubdivisions <= 0 ) {
1014                                 patchSubdivisions = 1;
1015                         }
1016                 }
1017
1018                 /* threads */
1019                 else if ( !strcmp( argv[ i ], "-threads" ) ) {
1020                         argv[ i ] = NULL;
1021                         i++;
1022                         numthreads = atoi( argv[ i ] );
1023                         argv[ i ] = NULL;
1024                 }
1025
1026                 else if( !strcmp( argv[ i ], "-nocmdline" ) )
1027                 {
1028                         Sys_Printf( "noCmdLine\n" );
1029                         nocmdline = qtrue;
1030                         argv[ i ] = NULL;
1031                 }
1032
1033         }
1034
1035         /* init model library */
1036         PicoInit();
1037         PicoSetMallocFunc( safe_malloc );
1038         PicoSetFreeFunc( free );
1039         PicoSetPrintFunc( PicoPrintFunc );
1040         PicoSetLoadFileFunc( PicoLoadFileFunc );
1041         PicoSetFreeFileFunc( free );
1042
1043         /* set number of threads */
1044         ThreadSetDefault();
1045
1046         /* generate sinusoid jitter table */
1047         for ( i = 0; i < MAX_JITTERS; i++ )
1048         {
1049                 jitters[ i ] = sin( i * 139.54152147 );
1050                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
1051         }
1052
1053         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
1054            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
1055
1056         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
1057         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
1058         Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
1059         Sys_Printf( "%s\n", Q3MAP_MOTD );
1060         Sys_Printf( "%s\n", argv[0] );
1061
1062         strcpy( q3map2path, argv[0] );//fuer autoPack func
1063
1064         /* ydnar: new path initialization */
1065         InitPaths( &argc, argv );
1066
1067         /* set game options */
1068         if ( !patchSubdivisions ) {
1069                 patchSubdivisions = game->patchSubdivisions;
1070         }
1071
1072         /* check if we have enough options left to attempt something */
1073         if ( argc < 2 ) {
1074                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
1075         }
1076
1077         /* fixaas */
1078         if ( !strcmp( argv[ 1 ], "-fixaas" ) ) {
1079                 r = FixAASMain( argc - 1, argv + 1 );
1080         }
1081
1082         /* analyze */
1083         else if ( !strcmp( argv[ 1 ], "-analyze" ) ) {
1084                 r = AnalyzeBSPMain( argc - 1, argv + 1 );
1085         }
1086
1087         /* info */
1088         else if ( !strcmp( argv[ 1 ], "-info" ) ) {
1089                 r = BSPInfoMain( argc - 2, argv + 2 );
1090         }
1091
1092         /* vis */
1093         else if ( !strcmp( argv[ 1 ], "-vis" ) ) {
1094                 r = VisMain( argc - 1, argv + 1 );
1095         }
1096
1097         /* light */
1098         else if ( !strcmp( argv[ 1 ], "-light" ) ) {
1099                 r = LightMain( argc - 1, argv + 1 );
1100         }
1101
1102         /* vlight */
1103         else if ( !strcmp( argv[ 1 ], "-vlight" ) ) {
1104                 Sys_FPrintf( SYS_WRN, "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
1105                 argv[ 1 ] = "-fast";    /* eek a hack */
1106                 r = LightMain( argc, argv );
1107         }
1108
1109         /* QBall: export entities */
1110         else if ( !strcmp( argv[ 1 ], "-exportents" ) ) {
1111                 r = ExportEntitiesMain( argc - 1, argv + 1 );
1112         }
1113
1114         /* ydnar: lightmap export */
1115         else if ( !strcmp( argv[ 1 ], "-export" ) ) {
1116                 r = ExportLightmapsMain( argc - 1, argv + 1 );
1117         }
1118
1119         /* ydnar: lightmap import */
1120         else if ( !strcmp( argv[ 1 ], "-import" ) ) {
1121                 r = ImportLightmapsMain( argc - 1, argv + 1 );
1122         }
1123
1124         /* ydnar: bsp scaling */
1125         else if ( !strcmp( argv[ 1 ], "-scale" ) ) {
1126                 r = ScaleBSPMain( argc - 1, argv + 1 );
1127         }
1128
1129         /* bsp shifting */
1130         else if ( !strcmp( argv[ 1 ], "-shift" ) ) {
1131                 r = ShiftBSPMain( argc - 1, argv + 1 );
1132         }
1133
1134         /* autopacking */
1135         else if ( !strcmp( argv[ 1 ], "-pk3" ) ) {
1136                 r = pk3BSPMain( argc - 1, argv + 1 );
1137         }
1138
1139         /* ydnar: bsp conversion */
1140         else if ( !strcmp( argv[ 1 ], "-convert" ) ) {
1141                 r = ConvertBSPMain( argc - 1, argv + 1 );
1142         }
1143
1144         /* div0: minimap */
1145         else if ( !strcmp( argv[ 1 ], "-minimap" ) ) {
1146                 r = MiniMapBSPMain( argc - 1, argv + 1 );
1147         }
1148
1149         /* ydnar: otherwise create a bsp */
1150         else{
1151                 r = BSPMain( argc, argv );
1152         }
1153
1154         /* emit time */
1155         end = I_FloatTime();
1156         Sys_Printf( "%9.0f seconds elapsed\n", end - start );
1157
1158         /* shut down connection */
1159         Broadcast_Shutdown();
1160
1161         /* return any error code */
1162         return r;
1163 }