mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 17:09:39 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
835
tools/quake3/q3map2/bspfile_abstract.c
Normal file
835
tools/quake3/q3map2/bspfile_abstract.c
Normal file
@@ -0,0 +1,835 @@
|
||||
/* -------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||||
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
This code has been altered significantly from its original form, to support
|
||||
several games based on the Quake III Arena engine, in the form of "Q3Map2."
|
||||
|
||||
------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* marker */
|
||||
#define BSPFILE_ABSTRACT_C
|
||||
|
||||
|
||||
|
||||
/* dependencies */
|
||||
#include "q3map2.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------------
|
||||
|
||||
this file was copied out of the common directory in order to not break
|
||||
compatibility with the q3map 1.x tree. it was moved out in order to support
|
||||
the raven bsp format (RBSP) used in soldier of fortune 2 and jedi knight 2.
|
||||
|
||||
since each game has its own set of particular features, the data structures
|
||||
below no longer directly correspond to the binary format of a particular game.
|
||||
|
||||
the translation will be done at bsp load/save time to keep any sort of
|
||||
special-case code messiness out of the rest of the program.
|
||||
|
||||
------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* FIXME: remove the functions below that handle memory management of bsp file chunks */
|
||||
|
||||
int numBSPDrawVertsBuffer = 0;
|
||||
void IncDrawVerts()
|
||||
{
|
||||
numBSPDrawVerts++;
|
||||
|
||||
if(bspDrawVerts == 0)
|
||||
{
|
||||
numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
|
||||
|
||||
bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
|
||||
|
||||
}
|
||||
else if(numBSPDrawVerts > numBSPDrawVertsBuffer)
|
||||
{
|
||||
numBSPDrawVertsBuffer *= 3; // multiply by 1.5
|
||||
numBSPDrawVertsBuffer /= 2;
|
||||
|
||||
if(numBSPDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
|
||||
numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
|
||||
|
||||
bspDrawVerts = realloc(bspDrawVerts, sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer);
|
||||
|
||||
if(!bspDrawVerts)
|
||||
Error( "realloc() failed (IncDrawVerts)");
|
||||
}
|
||||
|
||||
memset(bspDrawVerts + (numBSPDrawVerts - 1), 0, sizeof(bspDrawVert_t));
|
||||
}
|
||||
|
||||
void SetDrawVerts(int n)
|
||||
{
|
||||
if(bspDrawVerts != 0)
|
||||
free(bspDrawVerts);
|
||||
|
||||
numBSPDrawVerts = n;
|
||||
numBSPDrawVertsBuffer = numBSPDrawVerts;
|
||||
|
||||
bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
|
||||
|
||||
memset(bspDrawVerts, 0, n * sizeof(bspDrawVert_t));
|
||||
}
|
||||
|
||||
int numBSPDrawSurfacesBuffer = 0;
|
||||
void SetDrawSurfacesBuffer()
|
||||
{
|
||||
if(bspDrawSurfaces != 0)
|
||||
free(bspDrawSurfaces);
|
||||
|
||||
numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
|
||||
|
||||
bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
|
||||
|
||||
memset(bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(bspDrawVert_t));
|
||||
}
|
||||
|
||||
void SetDrawSurfaces(int n)
|
||||
{
|
||||
if(bspDrawSurfaces != 0)
|
||||
free(bspDrawSurfaces);
|
||||
|
||||
numBSPDrawSurfaces = n;
|
||||
numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
|
||||
|
||||
bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
|
||||
|
||||
memset(bspDrawSurfaces, 0, n * sizeof(bspDrawVert_t));
|
||||
}
|
||||
|
||||
void BSPFilesCleanup()
|
||||
{
|
||||
if(bspDrawVerts != 0)
|
||||
free(bspDrawVerts);
|
||||
if(bspDrawSurfaces != 0)
|
||||
free(bspDrawSurfaces);
|
||||
if(bspLightBytes != 0)
|
||||
free(bspLightBytes);
|
||||
if(bspGridPoints != 0)
|
||||
free(bspGridPoints);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SwapBlock()
|
||||
if all values are 32 bits, this can be used to swap everything
|
||||
*/
|
||||
|
||||
void SwapBlock( int *block, int size )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
/* dummy check */
|
||||
if( block == NULL )
|
||||
return;
|
||||
|
||||
/* swap */
|
||||
size >>= 2;
|
||||
for( i = 0; i < size; i++ )
|
||||
block[ i ] = LittleLong( block[ i ] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SwapBSPFile()
|
||||
byte swaps all data in the abstract bsp
|
||||
*/
|
||||
|
||||
void SwapBSPFile( void )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
|
||||
/* models */
|
||||
SwapBlock( (int*) bspModels, numBSPModels * sizeof( bspModels[ 0 ] ) );
|
||||
|
||||
/* shaders (don't swap the name) */
|
||||
for( i = 0; i < numBSPShaders ; i++ )
|
||||
{
|
||||
bspShaders[ i ].contentFlags = LittleLong( bspShaders[ i ].contentFlags );
|
||||
bspShaders[ i ].surfaceFlags = LittleLong( bspShaders[ i ].surfaceFlags );
|
||||
}
|
||||
|
||||
/* planes */
|
||||
SwapBlock( (int*) bspPlanes, numBSPPlanes * sizeof( bspPlanes[ 0 ] ) );
|
||||
|
||||
/* nodes */
|
||||
SwapBlock( (int*) bspNodes, numBSPNodes * sizeof( bspNodes[ 0 ] ) );
|
||||
|
||||
/* leafs */
|
||||
SwapBlock( (int*) bspLeafs, numBSPLeafs * sizeof( bspLeafs[ 0 ] ) );
|
||||
|
||||
/* leaffaces */
|
||||
SwapBlock( (int*) bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
|
||||
|
||||
/* leafbrushes */
|
||||
SwapBlock( (int*) bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
|
||||
|
||||
// brushes
|
||||
SwapBlock( (int*) bspBrushes, numBSPBrushes * sizeof( bspBrushes[ 0 ] ) );
|
||||
|
||||
// brushsides
|
||||
SwapBlock( (int*) bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
|
||||
|
||||
// vis
|
||||
((int*) &bspVisBytes)[ 0 ] = LittleLong( ((int*) &bspVisBytes)[ 0 ] );
|
||||
((int*) &bspVisBytes)[ 1 ] = LittleLong( ((int*) &bspVisBytes)[ 1 ] );
|
||||
|
||||
/* drawverts (don't swap colors) */
|
||||
for( i = 0; i < numBSPDrawVerts; i++ )
|
||||
{
|
||||
bspDrawVerts[ i ].xyz[ 0 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 0 ] );
|
||||
bspDrawVerts[ i ].xyz[ 1 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 1 ] );
|
||||
bspDrawVerts[ i ].xyz[ 2 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 2 ] );
|
||||
bspDrawVerts[ i ].normal[ 0 ] = LittleFloat( bspDrawVerts[ i ].normal[ 0 ] );
|
||||
bspDrawVerts[ i ].normal[ 1 ] = LittleFloat( bspDrawVerts[ i ].normal[ 1 ] );
|
||||
bspDrawVerts[ i ].normal[ 2 ] = LittleFloat( bspDrawVerts[ i ].normal[ 2 ] );
|
||||
bspDrawVerts[ i ].st[ 0 ] = LittleFloat( bspDrawVerts[ i ].st[ 0 ] );
|
||||
bspDrawVerts[ i ].st[ 1 ] = LittleFloat( bspDrawVerts[ i ].st[ 1 ] );
|
||||
for( j = 0; j < MAX_LIGHTMAPS; j++ )
|
||||
{
|
||||
bspDrawVerts[ i ].lightmap[ j ][ 0 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 0 ] );
|
||||
bspDrawVerts[ i ].lightmap[ j ][ 1 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* drawindexes */
|
||||
SwapBlock( (int*) bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[0] ) );
|
||||
|
||||
/* drawsurfs */
|
||||
/* note: rbsp files (and hence q3map2 abstract bsp) have byte lightstyles index arrays, this follows sof2map convention */
|
||||
SwapBlock( (int*) bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
|
||||
|
||||
/* fogs */
|
||||
for( i = 0; i < numBSPFogs; i++ )
|
||||
{
|
||||
bspFogs[ i ].brushNum = LittleLong( bspFogs[ i ].brushNum );
|
||||
bspFogs[ i ].visibleSide = LittleLong( bspFogs[ i ].visibleSide );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
GetLumpElements()
|
||||
gets the number of elements in a bsp lump
|
||||
*/
|
||||
|
||||
int GetLumpElements( bspHeader_t *header, int lump, int size )
|
||||
{
|
||||
/* check for odd size */
|
||||
if( header->lumps[ lump ].length % size )
|
||||
{
|
||||
if( force )
|
||||
{
|
||||
Sys_Printf( "WARNING: GetLumpElements: odd lump size (%d) in lump %d\n", header->lumps[ lump ].length, lump );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
Error( "GetLumpElements: odd lump size (%d) in lump %d", header->lumps[ lump ].length, lump );
|
||||
}
|
||||
|
||||
/* return element count */
|
||||
return header->lumps[ lump ].length / size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
GetLump()
|
||||
returns a pointer to the specified lump
|
||||
*/
|
||||
|
||||
void *GetLump( bspHeader_t *header, int lump )
|
||||
{
|
||||
return (void*)( (byte*) header + header->lumps[ lump ].offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
CopyLump()
|
||||
copies a bsp file lump into a destination buffer
|
||||
*/
|
||||
|
||||
int CopyLump( bspHeader_t *header, int lump, void *dest, int size )
|
||||
{
|
||||
int length, offset;
|
||||
|
||||
|
||||
/* get lump length and offset */
|
||||
length = header->lumps[ lump ].length;
|
||||
offset = header->lumps[ lump ].offset;
|
||||
|
||||
/* handle erroneous cases */
|
||||
if( length == 0 )
|
||||
return 0;
|
||||
if( length % size )
|
||||
{
|
||||
if( force )
|
||||
{
|
||||
Sys_Printf( "WARNING: CopyLump: odd lump size (%d) in lump %d\n", length, lump );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
Error( "CopyLump: odd lump size (%d) in lump %d", length, lump );
|
||||
}
|
||||
|
||||
/* copy block of memory and return */
|
||||
memcpy( dest, (byte*) header + offset, length );
|
||||
return length / size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
AddLump()
|
||||
adds a lump to an outgoing bsp file
|
||||
*/
|
||||
|
||||
void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length )
|
||||
{
|
||||
bspLump_t *lump;
|
||||
|
||||
|
||||
/* add lump to bsp file header */
|
||||
lump = &header->lumps[ lumpNum ];
|
||||
lump->offset = LittleLong( ftell( file ) );
|
||||
lump->length = LittleLong( length );
|
||||
|
||||
/* write lump to file */
|
||||
SafeWrite( file, data, (length + 3) & ~3 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
LoadBSPFile()
|
||||
loads a bsp file into memory
|
||||
*/
|
||||
|
||||
void LoadBSPFile( const char *filename )
|
||||
{
|
||||
/* dummy check */
|
||||
if( game == NULL || game->load == NULL )
|
||||
Error( "LoadBSPFile: unsupported BSP file format" );
|
||||
|
||||
/* load it, then byte swap the in-memory version */
|
||||
game->load( filename );
|
||||
SwapBSPFile();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
WriteBSPFile()
|
||||
writes a bsp file
|
||||
*/
|
||||
|
||||
void WriteBSPFile( const char *filename )
|
||||
{
|
||||
char tempname[ 1024 ];
|
||||
time_t tm;
|
||||
|
||||
|
||||
/* dummy check */
|
||||
if( game == NULL || game->write == NULL )
|
||||
Error( "WriteBSPFile: unsupported BSP file format" );
|
||||
|
||||
/* make fake temp name so existing bsp file isn't damaged in case write process fails */
|
||||
time( &tm );
|
||||
sprintf( tempname, "%s.%08X", filename, (int) tm );
|
||||
|
||||
/* byteswap, write the bsp, then swap back so it can be manipulated further */
|
||||
SwapBSPFile();
|
||||
game->write( tempname );
|
||||
SwapBSPFile();
|
||||
|
||||
/* replace existing bsp file */
|
||||
remove( filename );
|
||||
rename( tempname, filename );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
PrintBSPFileSizes()
|
||||
dumps info about current file
|
||||
*/
|
||||
|
||||
void PrintBSPFileSizes( void )
|
||||
{
|
||||
/* parse entities first */
|
||||
if( numEntities <= 0 )
|
||||
ParseEntities();
|
||||
|
||||
/* note that this is abstracted */
|
||||
Sys_Printf( "Abstracted BSP file components (*actual sizes may differ)\n" );
|
||||
|
||||
/* print various and sundry bits */
|
||||
Sys_Printf( "%9d models %9d\n",
|
||||
numBSPModels, (int) (numBSPModels * sizeof( bspModel_t )) );
|
||||
Sys_Printf( "%9d shaders %9d\n",
|
||||
numBSPShaders, (int) (numBSPShaders * sizeof( bspShader_t )) );
|
||||
Sys_Printf( "%9d brushes %9d\n",
|
||||
numBSPBrushes, (int) (numBSPBrushes * sizeof( bspBrush_t )) );
|
||||
Sys_Printf( "%9d brushsides %9d *\n",
|
||||
numBSPBrushSides, (int) (numBSPBrushSides * sizeof( bspBrushSide_t )) );
|
||||
Sys_Printf( "%9d fogs %9d\n",
|
||||
numBSPFogs, (int) (numBSPFogs * sizeof( bspFog_t ) ) );
|
||||
Sys_Printf( "%9d planes %9d\n",
|
||||
numBSPPlanes, (int) (numBSPPlanes * sizeof( bspPlane_t )) );
|
||||
Sys_Printf( "%9d entdata %9d\n",
|
||||
numEntities, bspEntDataSize );
|
||||
Sys_Printf( "\n");
|
||||
|
||||
Sys_Printf( "%9d nodes %9d\n",
|
||||
numBSPNodes, (int) (numBSPNodes * sizeof( bspNode_t)) );
|
||||
Sys_Printf( "%9d leafs %9d\n",
|
||||
numBSPLeafs, (int) (numBSPLeafs * sizeof( bspLeaf_t )) );
|
||||
Sys_Printf( "%9d leafsurfaces %9d\n",
|
||||
numBSPLeafSurfaces, (int) (numBSPLeafSurfaces * sizeof( *bspLeafSurfaces )) );
|
||||
Sys_Printf( "%9d leafbrushes %9d\n",
|
||||
numBSPLeafBrushes, (int) (numBSPLeafBrushes * sizeof( *bspLeafBrushes )) );
|
||||
Sys_Printf( "\n");
|
||||
|
||||
Sys_Printf( "%9d drawsurfaces %9d *\n",
|
||||
numBSPDrawSurfaces, (int) (numBSPDrawSurfaces * sizeof( *bspDrawSurfaces )) );
|
||||
Sys_Printf( "%9d drawverts %9d *\n",
|
||||
numBSPDrawVerts, (int) (numBSPDrawVerts * sizeof( *bspDrawVerts )) );
|
||||
Sys_Printf( "%9d drawindexes %9d\n",
|
||||
numBSPDrawIndexes, (int) (numBSPDrawIndexes * sizeof( *bspDrawIndexes )) );
|
||||
Sys_Printf( "\n");
|
||||
|
||||
Sys_Printf( "%9d lightmaps %9d\n",
|
||||
numBSPLightBytes / (game->lightmapSize * game->lightmapSize * 3), numBSPLightBytes );
|
||||
Sys_Printf( "%9d lightgrid %9d *\n",
|
||||
numBSPGridPoints, (int) (numBSPGridPoints * sizeof( *bspGridPoints )) );
|
||||
Sys_Printf( " visibility %9d\n",
|
||||
numBSPVisBytes );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------------
|
||||
|
||||
entity data handling
|
||||
|
||||
------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/*
|
||||
StripTrailing()
|
||||
strips low byte chars off the end of a string
|
||||
*/
|
||||
|
||||
void StripTrailing( char *e )
|
||||
{
|
||||
char *s;
|
||||
|
||||
|
||||
s = e + strlen( e ) - 1;
|
||||
while( s >= e && *s <= 32 )
|
||||
{
|
||||
*s = 0;
|
||||
s--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ParseEpair()
|
||||
parses a single quoted "key" "value" pair into an epair struct
|
||||
*/
|
||||
|
||||
epair_t *ParseEPair( void )
|
||||
{
|
||||
epair_t *e;
|
||||
|
||||
|
||||
/* allocate and clear new epair */
|
||||
e = safe_malloc( sizeof( epair_t ) );
|
||||
memset( e, 0, sizeof( epair_t ) );
|
||||
|
||||
/* handle key */
|
||||
if( strlen( token ) >= (MAX_KEY - 1) )
|
||||
Error( "ParseEPair: token too long" );
|
||||
|
||||
e->key = copystring( token );
|
||||
GetToken( qfalse );
|
||||
|
||||
/* handle value */
|
||||
if( strlen( token ) >= MAX_VALUE - 1 )
|
||||
Error( "ParseEpar: token too long" );
|
||||
e->value = copystring( token );
|
||||
|
||||
/* strip trailing spaces that sometimes get accidentally added in the editor */
|
||||
StripTrailing( e->key );
|
||||
StripTrailing( e->value );
|
||||
|
||||
/* return it */
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ParseEntity()
|
||||
parses an entity's epairs
|
||||
*/
|
||||
|
||||
qboolean ParseEntity( void )
|
||||
{
|
||||
epair_t *e;
|
||||
|
||||
|
||||
/* dummy check */
|
||||
if( !GetToken( qtrue ) )
|
||||
return qfalse;
|
||||
if( strcmp( token, "{" ) )
|
||||
Error( "ParseEntity: { not found" );
|
||||
if( numEntities == MAX_MAP_ENTITIES )
|
||||
Error( "numEntities == MAX_MAP_ENTITIES" );
|
||||
|
||||
/* create new entity */
|
||||
mapEnt = &entities[ numEntities ];
|
||||
numEntities++;
|
||||
|
||||
/* parse */
|
||||
while( 1 )
|
||||
{
|
||||
if( !GetToken( qtrue ) )
|
||||
Error( "ParseEntity: EOF without closing brace" );
|
||||
if( !EPAIR_STRCMP( token, "}" ) )
|
||||
break;
|
||||
e = ParseEPair();
|
||||
e->next = mapEnt->epairs;
|
||||
mapEnt->epairs = e;
|
||||
}
|
||||
|
||||
/* return to sender */
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ParseEntities()
|
||||
parses the bsp entity data string into entities
|
||||
*/
|
||||
|
||||
void ParseEntities( void )
|
||||
{
|
||||
numEntities = 0;
|
||||
ParseFromMemory( bspEntData, bspEntDataSize );
|
||||
while( ParseEntity() );
|
||||
|
||||
/* ydnar: set number of bsp entities in case a map is loaded on top */
|
||||
numBSPEntities = numEntities;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
UnparseEntities()
|
||||
generates the dentdata string from all the entities.
|
||||
this allows the utilities to add or remove key/value
|
||||
pairs to the data created by the map editor
|
||||
*/
|
||||
|
||||
void UnparseEntities( void )
|
||||
{
|
||||
int i;
|
||||
char *buf, *end;
|
||||
epair_t *ep;
|
||||
char line[ 2048 ];
|
||||
char key[ 1024 ], value[ 1024 ];
|
||||
const char *value2;
|
||||
|
||||
|
||||
/* setup */
|
||||
buf = bspEntData;
|
||||
end = buf;
|
||||
*end = 0;
|
||||
|
||||
/* run through entity list */
|
||||
for( i = 0; i < numBSPEntities && i < numEntities; i++ )
|
||||
{
|
||||
/* get epair */
|
||||
ep = entities[ i ].epairs;
|
||||
if( ep == NULL )
|
||||
continue; /* ent got removed */
|
||||
|
||||
/* ydnar: certain entities get stripped from bsp file */
|
||||
value2 = ValueForKey( &entities[ i ], "classname" );
|
||||
if( !Q_stricmp( value2, "misc_model" ) ||
|
||||
!Q_stricmp( value2, "_decal" ) ||
|
||||
!Q_stricmp( value2, "_skybox" ) )
|
||||
continue;
|
||||
|
||||
/* add beginning brace */
|
||||
strcat( end, "{\n" );
|
||||
end += 2;
|
||||
|
||||
/* walk epair list */
|
||||
for( ep = entities[ i ].epairs; ep != NULL; ep = ep->next )
|
||||
{
|
||||
/* copy and clean */
|
||||
strcpy( key, ep->key );
|
||||
StripTrailing( key );
|
||||
strcpy( value, ep->value );
|
||||
StripTrailing( value );
|
||||
|
||||
/* add to buffer */
|
||||
sprintf( line, "\"%s\" \"%s\"\n", key, value );
|
||||
strcat( end, line );
|
||||
end += strlen( line );
|
||||
}
|
||||
|
||||
/* add trailing brace */
|
||||
strcat( end,"}\n" );
|
||||
end += 2;
|
||||
|
||||
/* check for overflow */
|
||||
if( end > buf + MAX_MAP_ENTSTRING )
|
||||
Error( "Entity text too long" );
|
||||
}
|
||||
|
||||
/* set size */
|
||||
bspEntDataSize = end - buf + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
PrintEntity()
|
||||
prints an entity's epairs to the console
|
||||
*/
|
||||
|
||||
void PrintEntity( const entity_t *ent )
|
||||
{
|
||||
epair_t *ep;
|
||||
|
||||
|
||||
Sys_Printf( "------- entity %p -------\n", ent );
|
||||
for( ep = ent->epairs; ep != NULL; ep = ep->next )
|
||||
Sys_Printf( "%s = %s\n", ep->key, ep->value );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SetKeyValue()
|
||||
sets an epair in an entity
|
||||
*/
|
||||
|
||||
void SetKeyValue( entity_t *ent, const char *key, const char *value )
|
||||
{
|
||||
epair_t *ep;
|
||||
|
||||
|
||||
/* check for existing epair */
|
||||
for( ep = ent->epairs; ep != NULL; ep = ep->next )
|
||||
{
|
||||
if( !EPAIR_STRCMP( ep->key, key ) )
|
||||
{
|
||||
free( ep->value );
|
||||
ep->value = copystring( value );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* create new epair */
|
||||
ep = safe_malloc( sizeof( *ep ) );
|
||||
ep->next = ent->epairs;
|
||||
ent->epairs = ep;
|
||||
ep->key = copystring( key );
|
||||
ep->value = copystring( value );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ValueForKey()
|
||||
gets the value for an entity key
|
||||
*/
|
||||
|
||||
const char *ValueForKey( const entity_t *ent, const char *key )
|
||||
{
|
||||
epair_t *ep;
|
||||
|
||||
|
||||
/* dummy check */
|
||||
if( ent == NULL )
|
||||
return "";
|
||||
|
||||
/* walk epair list */
|
||||
for( ep = ent->epairs; ep != NULL; ep = ep->next )
|
||||
{
|
||||
if( !EPAIR_STRCMP( ep->key, key ) )
|
||||
return ep->value;
|
||||
}
|
||||
|
||||
/* if no match, return empty string */
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
IntForKey()
|
||||
gets the integer point value for an entity key
|
||||
*/
|
||||
|
||||
int IntForKey( const entity_t *ent, const char *key )
|
||||
{
|
||||
const char *k;
|
||||
|
||||
|
||||
k = ValueForKey( ent, key );
|
||||
return atoi( k );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
FloatForKey()
|
||||
gets the floating point value for an entity key
|
||||
*/
|
||||
|
||||
vec_t FloatForKey( const entity_t *ent, const char *key )
|
||||
{
|
||||
const char *k;
|
||||
|
||||
|
||||
k = ValueForKey( ent, key );
|
||||
return atof( k );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
GetVectorForKey()
|
||||
gets a 3-element vector value for an entity key
|
||||
*/
|
||||
|
||||
void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec )
|
||||
{
|
||||
const char *k;
|
||||
double v1, v2, v3;
|
||||
|
||||
|
||||
/* get value */
|
||||
k = ValueForKey( ent, key );
|
||||
|
||||
/* scanf into doubles, then assign, so it is vec_t size independent */
|
||||
v1 = v2 = v3 = 0.0;
|
||||
sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
|
||||
vec[ 0 ] = v1;
|
||||
vec[ 1 ] = v2;
|
||||
vec[ 2 ] = v3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
FindTargetEntity()
|
||||
finds an entity target
|
||||
*/
|
||||
|
||||
entity_t *FindTargetEntity( const char *target )
|
||||
{
|
||||
int i;
|
||||
const char *n;
|
||||
|
||||
|
||||
/* walk entity list */
|
||||
for( i = 0; i < numEntities; i++ )
|
||||
{
|
||||
n = ValueForKey( &entities[ i ], "targetname" );
|
||||
if ( !strcmp( n, target ) )
|
||||
return &entities[ i ];
|
||||
}
|
||||
|
||||
/* nada */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
GetEntityShadowFlags() - ydnar
|
||||
gets an entity's shadow flags
|
||||
note: does not set them to defaults if the keys are not found!
|
||||
*/
|
||||
|
||||
void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows )
|
||||
{
|
||||
const char *value;
|
||||
|
||||
|
||||
/* get cast shadows */
|
||||
if( castShadows != NULL )
|
||||
{
|
||||
value = ValueForKey( ent, "_castShadows" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent, "_cs" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent2, "_castShadows" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent2, "_cs" );
|
||||
if( value[ 0 ] != '\0' )
|
||||
*castShadows = atoi( value );
|
||||
}
|
||||
|
||||
/* receive */
|
||||
if( recvShadows != NULL )
|
||||
{
|
||||
value = ValueForKey( ent, "_receiveShadows" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent, "_rs" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent2, "_receiveShadows" );
|
||||
if( value[ 0 ] == '\0' )
|
||||
value = ValueForKey( ent2, "_rs" );
|
||||
if( value[ 0 ] != '\0' )
|
||||
*recvShadows = atoi( value );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user