📄 map.c
字号:
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteOriginBrush(FILE *fp, vec3_t origin)
{
vec3_t normal;
float dist;
int i, s;
winding_t *w;
if (fprintf(fp, " {\n") < 0) return false;
//
for (i = 0; i < 3; i++)
{
for (s = -1; s <= 1; s += 2)
{
//
VectorClear(normal);
normal[i] = s;
dist = origin[i] * s + 16;
//
w = BaseWindingForPlane(normal, dist);
//three non-colinear points to define the plane
if (fprintf(fp," ( %5i %5i %5i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]) < 0) return false;
if (fprintf(fp,"( %5i %5i %5i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]) < 0) return false;
if (fprintf(fp,"( %5i %5i %5i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]) < 0) return false;
//free the winding
FreeWinding(w);
//write origin texture:
// CONTENTS_ORIGIN = 16777216
// SURF_NODRAW = 128
if (loadedmaptype == MAPTYPE_SIN)
{
if (fprintf(fp, "generic/misc/origin 0 0 0 1 1") < 0) return false;
} //end if
else if (loadedmaptype == MAPTYPE_HALFLIFE)
{
if (fprintf(fp, "origin 0 0 0 1 1") < 0) return false;
} //end if
else
{
if (fprintf(fp, "e1u1/origin 0 0 0 1 1") < 0) return false;
} //end else
//Quake2 extra brush side info
if (loadedmaptype == MAPTYPE_QUAKE2)
{
//if (fprintf(fp, " 16777216 128 0") < 0) return false;
} //end if
if (fprintf(fp, "\n") < 0) return false;
} //end for
} //end for
if (fprintf(fp, " }\n") < 0) return false;
c_writtenbrushes++;
return true;
} //end of the function WriteOriginBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
mapbrush_t *GetAreaPortalBrush(entity_t *mapent)
{
int portalnum, bn;
mapbrush_t *brush;
//the area portal number
portalnum = mapent->areaportalnum;
//find the area portal brush in the world brushes
for (bn = 0; bn < nummapbrushes && portalnum; bn++)
{
brush = &mapbrushes[bn];
//must be in world entity
if (brush->entitynum == 0)
{
if (brush->contents & CONTENTS_AREAPORTAL)
{
portalnum--;
} //end if
} //end if
} //end for
if (bn < nummapbrushes)
{
return brush;
} //end if
else
{
Log_Print("area portal %d brush not found\n", mapent->areaportalnum);
return NULL;
} //end else
} //end of the function GetAreaPortalBrush
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
qboolean WriteMapFileSafe(FILE *fp)
{
char key[1024], value[1024];
int i, bn, entitybrushes;
epair_t *ep;
mapbrush_t *brush;
entity_t *mapent;
//vec3_t vec_origin = {0, 0, 0};
//
if (fprintf(fp,"//=====================================================\n"
"//\n"
"// map file created with BSPC "BSPC_VERSION"\n"
"//\n"
"// BSPC is designed to decompile material in which you own the copyright\n"
"// or have obtained permission to decompile from the copyright owner. Unless\n"
"// you own the copyright or have permission to decompile from the copyright\n"
"// owner, you may be violating copyright law and be subject to payment of\n"
"// damages and other remedies. If you are uncertain about your rights, contact\n"
"// your legal advisor.\n"
"//\n") < 0) return false;
if (loadedmaptype == MAPTYPE_SIN)
{
if (fprintf(fp,
"// generic/misc/red is used for unknown textures\n") < 0) return false;
} //end if
if (fprintf(fp,"//\n"
"//=====================================================\n") < 0) return false;
//write out all the entities
for (i = 0; i < num_entities; i++)
{
mapent = &entities[i];
if (!mapent->epairs)
{
continue;
} //end if
if (fprintf(fp, "{\n") < 0) return false;
//
if (loadedmaptype == MAPTYPE_QUAKE3)
{
if (!stricmp(ValueForKey(mapent, "classname"), "light"))
{
SetKeyValue(mapent, "light", "10000");
} //end if
} //end if
//write epairs
for (ep = mapent->epairs; ep; ep = ep->next)
{
strcpy(key, ep->key);
StripTrailing (key);
strcpy(value, ep->value);
StripTrailing(value);
//
if (loadedmaptype == MAPTYPE_QUAKE2 ||
loadedmaptype == MAPTYPE_SIN)
{
//don't write an origin for BSP models
if (mapent->modelnum >= 0 && !strcmp(key, "origin")) continue;
} //end if
//don't write BSP model numbers
if (mapent->modelnum >= 0 && !strcmp(key, "model") && value[0] == '*') continue;
//
if (fprintf(fp, " \"%s\" \"%s\"\n", key, value) < 0) return false;
} //end for
//
if (ValueForKey(mapent, "origin")) GetVectorForKey(mapent, "origin", mapent->origin);
else mapent->origin[0] = mapent->origin[1] = mapent->origin[2] = 0;
//if this is an area portal entity
if (!strcmp("func_areaportal", ValueForKey(mapent, "classname")))
{
brush = GetAreaPortalBrush(mapent);
if (!brush) return false;
if (!WriteMapBrush(fp, brush, mapent->origin)) return false;
} //end if
else
{
entitybrushes = false;
//write brushes
for (bn = 0; bn < nummapbrushes; bn++)
{
brush = &mapbrushes[bn];
//if the brush is part of this entity
if (brush->entitynum == i)
{
//don't write out area portal brushes in the world
if (!((brush->contents & CONTENTS_AREAPORTAL) && brush->entitynum == 0))
{
/*
if (!strcmp("func_door_rotating", ValueForKey(mapent, "classname")))
{
AAS_PositionFuncRotatingBrush(mapent, brush);
if (!WriteMapBrush(fp, brush, vec_origin)) return false;
} //end if
else //*/
{
if (!WriteMapBrush(fp, brush, mapent->origin)) return false;
} //end else
entitybrushes = true;
} //end if
} //end if
} //end for
//if the entity had brushes
if (entitybrushes)
{
//if the entity has an origin set
if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
{
if (!WriteOriginBrush(fp, mapent->origin)) return false;
} //end if
} //end if
} //end else
if (fprintf(fp, "}\n") < 0) return false;
} //end for
if (fprintf(fp, "//total of %d brushes\n", c_writtenbrushes) < 0) return false;
return true;
} //end of the function WriteMapFileSafe
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void WriteMapFile(char *filename)
{
FILE *fp;
double start_time;
c_writtenbrushes = 0;
//the time started
start_time = I_FloatTime();
//
Log_Print("writing %s\n", filename);
fp = fopen(filename, "wb");
if (!fp)
{
Log_Print("can't open %s\n", filename);
return;
} //end if
if (!WriteMapFileSafe(fp))
{
fclose(fp);
Log_Print("error writing map file %s\n", filename);
return;
} //end if
fclose(fp);
//display creation time
Log_Print("written %d brushes\n", c_writtenbrushes);
Log_Print("map file written in %5.0f seconds\n", I_FloatTime() - start_time);
} //end of the function WriteMapFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void PrintMapInfo(void)
{
Log_Print("\n");
Log_Print("%6i brushes\n", nummapbrushes);
Log_Print("%6i brush sides\n", nummapbrushsides);
// Log_Print("%6i clipbrushes\n", c_clipbrushes);
// Log_Print("%6i total sides\n", nummapbrushsides);
// Log_Print("%6i boxbevels\n", c_boxbevels);
// Log_Print("%6i edgebevels\n", c_edgebevels);
// Log_Print("%6i entities\n", num_entities);
// Log_Print("%6i planes\n", nummapplanes);
// Log_Print("%6i areaportals\n", c_areaportals);
// Log_Print("%6i squatt brushes\n", c_squattbrushes);
// Log_Print("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
// map_maxs[0],map_maxs[1],map_maxs[2]);
} //end of the function PrintMapInfo
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ResetMapLoading(void)
{
int i;
epair_t *ep, *nextep;
Q2_ResetMapLoading();
Sin_ResetMapLoading();
//free all map brush side windings
for (i = 0; i < nummapbrushsides; i++)
{
if (brushsides[i].winding)
{
FreeWinding(brushsides[i].winding);
} //end for
} //end for
//reset regular stuff
nummapbrushes = 0;
memset(mapbrushes, 0, MAX_MAPFILE_BRUSHES * sizeof(mapbrush_t));
//
nummapbrushsides = 0;
memset(brushsides, 0, MAX_MAPFILE_BRUSHSIDES * sizeof(side_t));
memset(side_brushtextures, 0, MAX_MAPFILE_BRUSHSIDES * sizeof(brush_texture_t));
//
nummapplanes = 0;
memset(mapplanes, 0, MAX_MAPFILE_PLANES * sizeof(plane_t));
//
memset(planehash, 0, PLANE_HASHES * sizeof(plane_t *));
//
memset(map_texinfo, 0, MAX_MAPFILE_TEXINFO * sizeof(map_texinfo_t));
map_numtexinfo = 0;
//
VectorClear(map_mins);
VectorClear(map_maxs);
//
c_boxbevels = 0;
c_edgebevels = 0;
c_areaportals = 0;
c_clipbrushes = 0;
c_writtenbrushes = 0;
//clear the entities
for (i = 0; i < num_entities; i++)
{
for (ep = entities[i].epairs; ep; ep = nextep)
{
nextep = ep->next;
FreeMemory(ep->key);
FreeMemory(ep->value);
FreeMemory(ep);
} //end for
} //end for
num_entities = 0;
memset(entities, 0, MAX_MAP_ENTITIES * sizeof(entity_t));
} //end of the function ResetMapLoading
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
#ifndef Q1_BSPVERSION
#define Q1_BSPVERSION 29
#endif
#ifndef HL_BSPVERSION
#define HL_BSPVERSION 30
#endif
#define Q2_BSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') //IBSP
#define Q2_BSPVERSION 38
#define SINGAME_BSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'R') //RBSP
#define SINGAME_BSPVERSION 1
#define SIN_BSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') //IBSP
#define SIN_BSPVERSION 41
typedef struct
{
int ident;
int version;
} idheader_t;
int LoadMapFromBSP(struct quakefile_s *qf)
{
idheader_t idheader;
if (ReadQuakeFile(qf, &idheader, 0, sizeof(idheader_t)) != sizeof(idheader_t))
{
return false;
} //end if
idheader.ident = LittleLong(idheader.ident);
idheader.version = LittleLong(idheader.version);
//Quake3 BSP file
if (idheader.ident == Q3_BSP_IDENT && idheader.version == Q3_BSP_VERSION)
{
ResetMapLoading();
Q3_LoadMapFromBSP(qf);
Q3_FreeMaxBSP();
} //end if
//Quake2 BSP file
else if (idheader.ident == Q2_BSPHEADER && idheader.version == Q2_BSPVERSION)
{
ResetMapLoading();
Q2_AllocMaxBSP();
Q2_LoadMapFromBSP(qf->filename, qf->offset, qf->length);
Q2_FreeMaxBSP();
} //endif
//Sin BSP file
else if ((idheader.ident == SIN_BSPHEADER && idheader.version == SIN_BSPVERSION) ||
//the dorks gave the same format another ident and verions
(idheader.ident == SINGAME_BSPHEADER && idheader.version == SINGAME_BSPVERSION))
{
ResetMapLoading();
Sin_AllocMaxBSP();
Sin_LoadMapFromBSP(qf->filename, qf->offset, qf->length);
Sin_FreeMaxBSP();
} //end if
//the Quake1 bsp files don't have a ident only a version
else if (idheader.ident == Q1_BSPVERSION)
{
ResetMapLoading();
Q1_AllocMaxBSP();
Q1_LoadMapFromBSP(qf->filename, qf->offset, qf->length);
Q1_FreeMaxBSP();
} //end if
//Half-Life also only uses a version number
else if (idheader.ident == HL_BSPVERSION)
{
ResetMapLoading();
HL_AllocMaxBSP();
HL_LoadMapFromBSP(qf->filename, qf->offset, qf->length);
HL_FreeMaxBSP();
} //end if
else
{
Error("unknown BSP format %c%c%c%c, version %d\n",
(idheader.ident & 0xFF),
((idheader.ident >> 8) & 0xFF),
((idheader.ident >> 16) & 0xFF),
((idheader.ident >> 24) & 0xFF), idheader.version);
return false;
} //end if
//
return true;
} //end of the function LoadMapFromBSP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -