1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 #include "cmdlib.h"
24 #include "mathlib.h"
25 #include "inout.h"
26 #include "bspfile.h"
27 #include "scriplib.h"
28
29 void GetLeafNums( void );
30
31 //=============================================================================
32
33 int bsp_version = Q3_BSP_VERSION;
34
35 int nummodels;
36 dmodel_t dmodels[MAX_MAP_MODELS];
37
38 int numShaders;
39 dshader_t dshaders[MAX_MAP_SHADERS];
40
41 int entdatasize;
42 char dentdata[MAX_MAP_ENTSTRING];
43
44 int numleafs;
45 dleaf_t dleafs[MAX_MAP_LEAFS];
46
47 int numplanes;
48 dplane_t dplanes[MAX_MAP_PLANES];
49
50 int numnodes;
51 dnode_t dnodes[MAX_MAP_NODES];
52
53 int numleafsurfaces;
54 int dleafsurfaces[MAX_MAP_LEAFFACES];
55
56 int numleafbrushes;
57 int dleafbrushes[MAX_MAP_LEAFBRUSHES];
58
59 int numbrushes;
60 dbrush_t dbrushes[MAX_MAP_BRUSHES];
61
62 int numbrushsides;
63 dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
64
65 int numLightBytes;
66 byte *lightBytes;
67
68 int numGridPoints;
69 byte *gridData;
70
71 int numVisBytes;
72 byte visBytes[MAX_MAP_VISIBILITY];
73
74 int numDrawVerts = 0;
75 int numDrawVertsBuffer = 0;
76 drawVert_t *drawVerts = NULL;
77
78 int numDrawIndexes;
79 int drawIndexes[MAX_MAP_DRAW_INDEXES];
80
81 int numDrawSurfaces;
82 int numDrawSurfacesBuffer = 0;
83 dsurface_t *drawSurfaces = NULL;
84
85 int numFogs;
86 dfog_t dfogs[MAX_MAP_FOGS];
87
SetLightBytes(int n)88 void SetLightBytes( int n ){
89 if ( lightBytes != 0 ) {
90 free( lightBytes );
91 }
92
93 numLightBytes = n;
94
95 if ( n == 0 ) {
96 return;
97 }
98
99 lightBytes = safe_malloc_info( numLightBytes, "SetLightBytes" );
100
101 memset( lightBytes, 0, numLightBytes );
102 }
103
SetGridPoints(int n)104 void SetGridPoints( int n ){
105 if ( gridData != 0 ) {
106 free( gridData );
107 }
108
109 numGridPoints = n;
110
111 if ( n == 0 ) {
112 return;
113 }
114
115 gridData = safe_malloc_info( numGridPoints * 8, "SetGridPoints" );
116
117 memset( gridData, 0, numGridPoints * 8 );
118 }
119
IncDrawVerts()120 void IncDrawVerts(){
121 numDrawVerts++;
122
123 if ( drawVerts == 0 ) {
124 numDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
125
126 drawVerts = safe_malloc_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
127
128 }
129 else if ( numDrawVerts > numDrawVertsBuffer ) {
130 numDrawVertsBuffer *= 3; // multiply by 1.5
131 numDrawVertsBuffer /= 2;
132
133 if ( numDrawVertsBuffer > MAX_MAP_DRAW_VERTS ) {
134 numDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
135 }
136
137 drawVerts = realloc( drawVerts, sizeof( drawVert_t ) * numDrawVertsBuffer );
138
139 if ( !drawVerts ) {
140 Error( "realloc() failed (IncDrawVerts)" );
141 }
142 }
143
144 memset( drawVerts + ( numDrawVerts - 1 ), 0, sizeof( drawVert_t ) );
145 }
146
SetDrawVerts(int n)147 void SetDrawVerts( int n ){
148 if ( drawVerts != 0 ) {
149 free( drawVerts );
150 }
151
152 numDrawVerts = n;
153 numDrawVertsBuffer = numDrawVerts;
154
155 drawVerts = safe_malloc_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
156
157 memset( drawVerts, 0, n * sizeof( drawVert_t ) );
158 }
159
SetDrawSurfacesBuffer()160 void SetDrawSurfacesBuffer(){
161 if ( drawSurfaces != 0 ) {
162 free( drawSurfaces );
163 }
164
165 numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
166
167 drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
168
169 memset( drawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( drawVert_t ) );
170 }
171
SetDrawSurfaces(int n)172 void SetDrawSurfaces( int n ){
173 if ( drawSurfaces != 0 ) {
174 free( drawSurfaces );
175 }
176
177 numDrawSurfaces = n;
178 numDrawSurfacesBuffer = numDrawSurfaces;
179
180 drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
181
182 memset( drawSurfaces, 0, n * sizeof( drawVert_t ) );
183 }
184
BspFilesCleanup()185 void BspFilesCleanup(){
186 if ( drawVerts != 0 ) {
187 free( drawVerts );
188 }
189 if ( drawSurfaces != 0 ) {
190 free( drawSurfaces );
191 }
192 if ( lightBytes != 0 ) {
193 free( lightBytes );
194 }
195 if ( gridData != 0 ) {
196 free( gridData );
197 }
198 }
199
200 //=============================================================================
201
202 /*
203 =============
204 SwapBlock
205
206 If all values are 32 bits, this can be used to swap everything
207 =============
208 */
SwapBlock(int * block,int sizeOfBlock)209 void SwapBlock( int *block, int sizeOfBlock ) {
210 int i;
211
212 sizeOfBlock >>= 2;
213 for ( i = 0 ; i < sizeOfBlock ; i++ ) {
214 block[i] = LittleLong( block[i] );
215 }
216 }
217
218 /*
219 =============
220 SwapBSPFile
221
222 Byte swaps all data in a bsp file.
223 =============
224 */
SwapBSPFile(void)225 void SwapBSPFile( void ) {
226 int i;
227
228 // models
229 SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) );
230
231 // shaders (don't swap the name)
232 for ( i = 0 ; i < numShaders ; i++ ) {
233 dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags );
234 dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags );
235 }
236
237 // planes
238 SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) );
239
240 // nodes
241 SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) );
242
243 // leafs
244 SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) );
245
246 // leaffaces
247 SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
248
249 // leafbrushes
250 SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
251
252 // brushes
253 SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) );
254
255 // brushsides
256 SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) );
257
258 // vis
259 ( (int *)&visBytes )[0] = LittleLong( ( (int *)&visBytes )[0] );
260 ( (int *)&visBytes )[1] = LittleLong( ( (int *)&visBytes )[1] );
261
262 // drawverts (don't swap colors )
263 for ( i = 0 ; i < numDrawVerts ; i++ ) {
264 drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] );
265 drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] );
266 drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] );
267 drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] );
268 drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] );
269 drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] );
270 drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] );
271 drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] );
272 drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] );
273 drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] );
274 }
275
276 // drawindexes
277 SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
278
279 // drawsurfs
280 SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) );
281
282 // fogs
283 for ( i = 0 ; i < numFogs ; i++ ) {
284 dfogs[i].brushNum = LittleLong( dfogs[i].brushNum );
285 dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide );
286 }
287 }
288
289
290
291 /*
292 =============
293 GetLumpElements
294 =============
295 */
GetLumpElements(dheader_t * header,int lump,int size)296 int GetLumpElements( dheader_t *header, int lump, int size ) {
297 int length, ofs;
298
299 length = header->lumps[lump].filelen;
300 ofs = header->lumps[lump].fileofs;
301
302 if ( length % size ) {
303 Error( "LoadBSPFile: odd lump size" );
304 }
305
306 return length / size;
307 }
308
309 /*
310 =============
311 CopyLump
312 =============
313 */
CopyLump(dheader_t * header,int lump,void * dest,int size)314 int CopyLump( dheader_t *header, int lump, void *dest, int size ) {
315 int length, ofs;
316
317 length = header->lumps[lump].filelen;
318 ofs = header->lumps[lump].fileofs;
319
320 if ( length == 0 ) {
321 return 0;
322 }
323
324 if ( length % size ) {
325 Error( "LoadBSPFile: odd lump size" );
326 }
327
328 memcpy( dest, (byte *)header + ofs, length );
329
330 return length / size;
331 }
332
333 /*
334 =============
335 LoadBSPFile
336 =============
337 */
LoadBSPFile(const char * filename)338 void LoadBSPFile( const char *filename ) {
339 dheader_t *header;
340
341 // load the file header
342 LoadFile( filename, (void **)&header );
343
344 // swap the header
345 SwapBlock( (int *)header, sizeof( *header ) );
346
347 if ( header->ident != BSP_IDENT ) {
348 Error( "%s is not a IBSP file", filename );
349 }
350 if ( header->version != bsp_version ) {
351 Error( "%s is version %i, not %i", filename, header->version, bsp_version );
352 }
353
354 numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof( dshader_t ) );
355 nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof( dmodel_t ) );
356 numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof( dplane_t ) );
357 numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof( dleaf_t ) );
358 numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof( dnode_t ) );
359 numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof( dleafsurfaces[0] ) );
360 numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof( dleafbrushes[0] ) );
361 numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof( dbrush_t ) );
362 numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof( dbrushside_t ) );
363 numDrawVerts = GetLumpElements( header, LUMP_DRAWVERTS, sizeof( drawVert_t ) );
364 SetDrawVerts( numDrawVerts );
365 CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof( drawVert_t ) );
366 numDrawSurfaces = GetLumpElements( header, LUMP_SURFACES, sizeof( dsurface_t ) );
367 SetDrawSurfaces( numDrawSurfaces );
368 numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof( dsurface_t ) );
369 numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof( dfog_t ) );
370 numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof( drawIndexes[0] ) );
371
372 numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 );
373 numLightBytes = GetLumpElements( header, LUMP_LIGHTMAPS, 1 );
374 SetLightBytes( numLightBytes );
375 CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 );
376 entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1 );
377
378 numGridPoints = GetLumpElements( header, LUMP_LIGHTGRID, 8 );
379 SetGridPoints( numGridPoints );
380 CopyLump( header, LUMP_LIGHTGRID, gridData, 8 );
381
382
383 free( header ); // everything has been copied out
384
385 // swap everything
386 SwapBSPFile();
387 }
388
389
390 //============================================================================
391
392 /*
393 =============
394 AddLump
395 =============
396 */
AddLump(FILE * bspfile,dheader_t * header,int lumpnum,const void * data,int len)397 void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) {
398 lump_t *lump;
399
400 lump = &header->lumps[lumpnum];
401
402 lump->fileofs = LittleLong( ftell( bspfile ) );
403 lump->filelen = LittleLong( len );
404 SafeWrite( bspfile, data, ( len + 3 ) & ~3 );
405 }
406
407 /*
408 =============
409 WriteBSPFile
410
411 Swaps the bsp file in place, so it should not be referenced again
412 =============
413 */
WriteBSPFile(const char * filename)414 void WriteBSPFile( const char *filename ) {
415 dheader_t outheader, *header;
416 FILE *bspfile;
417
418 header = &outheader;
419 memset( header, 0, sizeof( dheader_t ) );
420
421 SwapBSPFile();
422
423 header->ident = LittleLong( BSP_IDENT );
424 header->version = LittleLong( bsp_version );
425
426 bspfile = SafeOpenWrite( filename );
427 SafeWrite( bspfile, header, sizeof( dheader_t ) ); // overwritten later
428
429 AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders * sizeof( dshader_t ) );
430 AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes * sizeof( dplane_t ) );
431 AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs * sizeof( dleaf_t ) );
432 AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes * sizeof( dnode_t ) );
433 AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes * sizeof( dbrush_t ) );
434 AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides * sizeof( dbrushside_t ) );
435 AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
436 AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
437 AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels * sizeof( dmodel_t ) );
438 AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts * sizeof( drawVert_t ) );
439 AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces * sizeof( dsurface_t ) );
440 AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes );
441 AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes );
442 AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints );
443 AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize );
444 AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof( dfog_t ) );
445 AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
446
447 fseek( bspfile, 0, SEEK_SET );
448 SafeWrite( bspfile, header, sizeof( dheader_t ) );
449 fclose( bspfile );
450 }
451
452 //============================================================================
453
454 /*
455 =============
456 PrintBSPFileSizes
457
458 Dumps info about current file
459 =============
460 */
PrintBSPFileSizes(void)461 void PrintBSPFileSizes( void ) {
462 if ( !num_entities ) {
463 ParseEntities();
464 }
465
466 Sys_Printf( "%6i models %7i\n"
467 ,nummodels, (int)( nummodels * sizeof( dmodel_t ) ) );
468 Sys_Printf( "%6i shaders %7i\n"
469 ,numShaders, (int)( numShaders * sizeof( dshader_t ) ) );
470 Sys_Printf( "%6i brushes %7i\n"
471 ,numbrushes, (int)( numbrushes * sizeof( dbrush_t ) ) );
472 Sys_Printf( "%6i brushsides %7i\n"
473 ,numbrushsides, (int)( numbrushsides * sizeof( dbrushside_t ) ) );
474 Sys_Printf( "%6i fogs %7i\n"
475 ,numFogs, (int)( numFogs * sizeof( dfog_t ) ) );
476 Sys_Printf( "%6i planes %7i\n"
477 ,numplanes, (int)( numplanes * sizeof( dplane_t ) ) );
478 Sys_Printf( "%6i entdata %7i\n", num_entities, entdatasize );
479
480 Sys_Printf( "\n" );
481
482 Sys_Printf( "%6i nodes %7i\n"
483 ,numnodes, (int)( numnodes * sizeof( dnode_t ) ) );
484 Sys_Printf( "%6i leafs %7i\n"
485 ,numleafs, (int)( numleafs * sizeof( dleaf_t ) ) );
486 Sys_Printf( "%6i leafsurfaces %7i\n"
487 ,numleafsurfaces, (int)( numleafsurfaces * sizeof( dleafsurfaces[0] ) ) );
488 Sys_Printf( "%6i leafbrushes %7i\n"
489 ,numleafbrushes, (int)( numleafbrushes * sizeof( dleafbrushes[0] ) ) );
490 Sys_Printf( "%6i drawverts %7i\n"
491 ,numDrawVerts, (int)( numDrawVerts * sizeof( drawVerts[0] ) ) );
492 Sys_Printf( "%6i drawindexes %7i\n"
493 ,numDrawIndexes, (int)( numDrawIndexes * sizeof( drawIndexes[0] ) ) );
494 Sys_Printf( "%6i drawsurfaces %7i\n"
495 ,numDrawSurfaces, (int)( numDrawSurfaces * sizeof( drawSurfaces[0] ) ) );
496
497 Sys_Printf( "%6i lightmaps %7i\n"
498 ,numLightBytes / ( LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3 ), numLightBytes );
499 Sys_Printf( " visibility %7i\n"
500 , numVisBytes );
501 }
502
503
504 //============================================
505
506 int num_entities;
507 entity_t entities[MAX_MAP_ENTITIES];
508
StripTrailing(char * e)509 void StripTrailing( char *e ) {
510 char *s;
511
512 s = e + strlen( e ) - 1;
513 while ( s >= e && *s <= 32 )
514 {
515 *s = 0;
516 s--;
517 }
518 }
519
520 /*
521 =================
522 ParseEpair
523 =================
524 */
ParseEpair(void)525 epair_t *ParseEpair( void ) {
526 epair_t *e;
527
528 e = safe_malloc( sizeof( epair_t ) );
529 memset( e, 0, sizeof( epair_t ) );
530
531 if ( strlen( token ) >= MAX_KEY - 1 ) {
532 Error( "ParseEpar: token too long" );
533 }
534 e->key = copystring( token );
535 GetToken( qfalse );
536 if ( strlen( token ) >= MAX_VALUE - 1 ) {
537 Error( "ParseEpar: token too long" );
538 }
539 e->value = copystring( token );
540
541 // strip trailing spaces that sometimes get accidentally
542 // added in the editor
543 StripTrailing( e->key );
544 StripTrailing( e->value );
545
546 return e;
547 }
548
549
550 /*
551 ================
552 ParseEntity
553 ================
554 */
ParseEntity(void)555 qboolean ParseEntity( void ) {
556 epair_t *e;
557 entity_t *mapent;
558
559 if ( !GetToken( qtrue ) ) {
560 return qfalse;
561 }
562
563 if ( strcmp( token, "{" ) ) {
564 Error( "ParseEntity: { not found" );
565 }
566 if ( num_entities == MAX_MAP_ENTITIES ) {
567 Error( "num_entities == MAX_MAP_ENTITIES" );
568 }
569 mapent = &entities[num_entities];
570 num_entities++;
571
572 do {
573 if ( !GetToken( qtrue ) ) {
574 Error( "ParseEntity: EOF without closing brace" );
575 }
576 if ( !strcmp( token, "}" ) ) {
577 break;
578 }
579 e = ParseEpair();
580 e->next = mapent->epairs;
581 mapent->epairs = e;
582 } while ( 1 );
583
584 return qtrue;
585 }
586
587 /*
588 ================
589 ParseEntities
590
591 Parses the dentdata string into entities
592 ================
593 */
ParseEntities(void)594 void ParseEntities( void ) {
595 num_entities = 0;
596 ParseFromMemory( dentdata, entdatasize );
597
598 while ( ParseEntity() ) {
599 }
600 }
601
602
603 /*
604 ================
605 UnparseEntities
606
607 Generates the dentdata string from all the entities
608 This allows the utilities to add or remove key/value pairs
609 to the data created by the map editor.
610 ================
611 */
UnparseEntities(void)612 void UnparseEntities( void ) {
613 char *buf, *end;
614 epair_t *ep;
615 char line[2048];
616 int i;
617 char key[1024], value[1024];
618
619 buf = dentdata;
620 end = buf;
621 *end = 0;
622
623 for ( i = 0 ; i < num_entities ; i++ ) {
624 ep = entities[i].epairs;
625 if ( !ep ) {
626 continue; // ent got removed
627 }
628
629 strcat( end,"{\n" );
630 end += 2;
631
632 for ( ep = entities[i].epairs ; ep ; ep = ep->next ) {
633 strcpy( key, ep->key );
634 StripTrailing( key );
635 strcpy( value, ep->value );
636 StripTrailing( value );
637
638 sprintf( line, "\"%s\" \"%s\"\n", key, value );
639 strcat( end, line );
640 end += strlen( line );
641 }
642 strcat( end,"}\n" );
643 end += 2;
644
645 if ( end > buf + MAX_MAP_ENTSTRING ) {
646 Error( "Entity text too long" );
647 }
648 }
649 entdatasize = end - buf + 1;
650 }
651
PrintEntity(const entity_t * ent)652 void PrintEntity( const entity_t *ent ) {
653 epair_t *ep;
654
655 Sys_Printf( "------- entity %p -------\n", ent );
656 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
657 Sys_Printf( "%s = %s\n", ep->key, ep->value );
658 }
659
660 }
661
SetKeyValue(entity_t * ent,const char * key,const char * value)662 void SetKeyValue( entity_t *ent, const char *key, const char *value ) {
663 epair_t *ep;
664
665 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
666 if ( !strcmp( ep->key, key ) ) {
667 free( ep->value );
668 ep->value = copystring( value );
669 return;
670 }
671 }
672 ep = safe_malloc( sizeof( *ep ) );
673 ep->next = ent->epairs;
674 ent->epairs = ep;
675 ep->key = copystring( key );
676 ep->value = copystring( value );
677 }
678
ValueForKey(const entity_t * ent,const char * key)679 const char *ValueForKey( const entity_t *ent, const char *key ) {
680 epair_t *ep;
681
682 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
683 if ( !strcmp( ep->key, key ) ) {
684 return ep->value;
685 }
686 }
687 return "";
688 }
689
FloatForKey(const entity_t * ent,const char * key)690 vec_t FloatForKey( const entity_t *ent, const char *key ) {
691 const char *k;
692
693 k = ValueForKey( ent, key );
694 return atof( k );
695 }
696
GetVectorForKey(const entity_t * ent,const char * key,vec3_t vec)697 void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) {
698 const char *k;
699 double v1, v2, v3;
700
701 k = ValueForKey( ent, key );
702
703 // scanf into doubles, then assign, so it is vec_t size independent
704 v1 = v2 = v3 = 0;
705 sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
706 vec[0] = v1;
707 vec[1] = v2;
708 vec[2] = v3;
709 }
710