/* ================ ParseEntity ================ */ qboolean ParseEntity(script_t *script) { epair_t *e; entity_t *mapent; token_t token; if (!PS_ReadToken(script, &token)) return false; if (strcmp(token.string, "{")) Error ("ParseEntity: { not found"); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); mapent = &entities[num_entities]; num_entities++; do { if (!PS_ReadToken(script, &token)) Error ("ParseEntity: EOF without closing brace"); if (!strcmp(token.string, "}") ) break; PS_UnreadLastToken(script); e = ParseEpair(script); e->next = mapent->epairs; mapent->epairs = e; } while (1); return true; } //end of the function ParseEntity
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_SkipUntilString(script_t* script, char* string) { token_t token; while (PS_ReadToken(script, &token)) { if (!strcmp(token.string, string)) return 1; } //end while return 0; } //end of the function PS_SkipUntilString
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ExpectAnyToken(script_t* script, token_t* token) { if (!PS_ReadToken(script, token)) { ScriptError(script, "couldn't read expected token"); return 0; } //end if else { return 1; } //end else } //end of the function PS_ExpectAnyToken
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_CheckTokenString(script_t* script, char* string) { token_t tok; if (!PS_ReadToken(script, &tok)) return 0; //if the token is available if (!strcmp(tok.string, string)) return 1; //token not available script->script_p = script->lastscript_p; return 0; } //end of the function PS_CheckTokenString
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token) { char str[MAX_TOKEN]; if (!PS_ReadToken(script, token)) { ScriptError(script, "couldn't read expected token"); return 0; } //end if if (token->type != type) { strcpy(str, ""); if (type == TT_STRING) strcpy(str, "string"); if (type == TT_LITERAL) strcpy(str, "literal"); if (type == TT_NUMBER) strcpy(str, "number"); if (type == TT_NAME) strcpy(str, "name"); if (type == TT_PUNCTUATION) strcpy(str, "punctuation"); ScriptError(script, "expected a %s, found %s", str, token->string); return 0; } //end if if (token->type == TT_NUMBER) { if ((token->subtype & subtype) != subtype) { strcpy(str, ""); if (subtype & TT_DECIMAL) strcpy(str, "decimal"); if (subtype & TT_HEX) strcpy(str, "hex"); if (subtype & TT_OCTAL) strcpy(str, "octal"); if (subtype & TT_BINARY) strcpy(str, "binary"); if (subtype & TT_LONG) strcat(str, " long"); if (subtype & TT_UNSIGNED) strcat(str, " unsigned"); if (subtype & TT_FLOAT) strcat(str, " float"); if (subtype & TT_INTEGER) strcat(str, " integer"); ScriptError(script, "expected %s, found %s", str, token->string); return 0; } //end if } //end if else if (token->type == TT_PUNCTUATION) { if (subtype < 0) { ScriptError(script, "BUG: wrong punctuation subtype"); return 0; } //end if if (token->subtype != subtype) { ScriptError(script, "expected %s, found %s", script->punctuations[subtype].p, token->string); return 0; } //end if } //end else if return 1; } //end of the function PS_ExpectTokenType
int PS_ExpectAnyToken(script_t *script, token_t *token) { if (!PS_ReadToken(script, token)) { ScriptError(script, "couldn't read expected token"); return 0; } else { return 1; } }
int PS_SkipUntilString(script_t *script, char *string) { token_t token; while (PS_ReadToken(script, &token)) { if (!strcmp(token.string, string)) { return 1; } } return 0; }
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ExpectTokenString( script_t *script, char *string ) { token_t token; if ( !PS_ReadToken( script, &token ) ) { ScriptError( script, "couldn't find expected %s", string ); return 0; } //end if if ( strcmp( token.string, string ) ) { ScriptError( script, "expected %s, found %s", string, token.string ); return 0; } //end if return 1; } //end of the function PS_ExpectToken
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_CheckTokenType(script_t* script, int type, int subtype, token_t* token) { token_t tok; if (!PS_ReadToken(script, &tok)) return 0; //if the type matches if (tok.type == type && (tok.subtype & subtype) == subtype) { Com_Memcpy(token, &tok, sizeof(token_t)); return 1; } //end if //token is not available script->script_p = script->lastscript_p; return 0; } //end of the function PS_CheckTokenType
/* ================= ScrewUpFile ================= */ void ScrewUpFile (char *oldfile, char *newfile) { FILE *fp; script_t *script; token_t token; replacefunc_t *f; char *ptr; printf( "screwing up file %s\n", oldfile ); script = LoadScriptFile( oldfile ); if ( !script ) { Error( "error opening %s\n", oldfile ); } fp = fopen( newfile, "wb" ); if ( !fp ) { Error( "error opening %s\n", newfile ); } // while ( PS_ReadToken( script, &token ) ) { WriteWhiteSpace( fp, script ); if ( token.type == TT_NAME ) { f = FindFunctionName( token.string ); if ( f ) { ptr = f->newname; } else { ptr = token.string;} while ( *ptr ) { fputc( *ptr, fp ); ptr++; } //end while } //end if else { WriteString( fp, script ); } //end else } //end while WriteWhiteSpace( fp, script ); FreeMemory( script ); fclose( fp ); } //end of the function ScrewUpFile
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ParseBSPEntities( void ) { script_t *script; token_t token; bsp_entity_t *ent; bsp_epair_t *epair; byte *buffer, *buftrav; int bufsize; // RF, modified this, so that it first gathers up memory requirements, then allocates a single chunk, // and places the strings all in there bspworld.ebuffer = NULL; script = LoadScriptMemory( bspworld.dentdata, bspworld.entdatasize, "entdata" ); SetScriptFlags( script, SCFL_NOSTRINGWHITESPACES | SCFL_NOSTRINGESCAPECHARS ); //SCFL_PRIMITIVE); bufsize = 0; while ( PS_ReadToken( script, &token ) ) { if ( strcmp( token.string, "{" ) ) { ScriptError( script, "invalid %s\n", token.string ); AAS_FreeBSPEntities(); FreeScript( script ); return; } //end if if ( bspworld.numentities >= MAX_BSPENTITIES ) { botimport.Print( PRT_MESSAGE, "too many entities in BSP file\n" ); break; } //end if while ( PS_ReadToken( script, &token ) ) { if ( !strcmp( token.string, "}" ) ) { break; } bufsize += sizeof( bsp_epair_t ); if ( token.type != TT_STRING ) { ScriptError( script, "invalid %s\n", token.string ); AAS_FreeBSPEntities(); FreeScript( script ); return; } //end if StripDoubleQuotes( token.string ); bufsize += strlen( token.string ) + 1; if ( !PS_ExpectTokenType( script, TT_STRING, 0, &token ) ) { AAS_FreeBSPEntities(); FreeScript( script ); return; } //end if StripDoubleQuotes( token.string ); bufsize += strlen( token.string ) + 1; } //end while if ( strcmp( token.string, "}" ) ) { ScriptError( script, "missing }\n" ); AAS_FreeBSPEntities(); FreeScript( script ); return; } //end if } //end while FreeScript( script ); buffer = (byte *)GetClearedHunkMemory( bufsize ); buftrav = buffer; bspworld.ebuffer = buffer; // RF, now parse the entities into memory // RF, NOTE: removed error checks for speed, no need to do them twice script = LoadScriptMemory( bspworld.dentdata, bspworld.entdatasize, "entdata" ); SetScriptFlags( script, SCFL_NOSTRINGWHITESPACES | SCFL_NOSTRINGESCAPECHARS ); //SCFL_PRIMITIVE); bspworld.numentities = 1; while ( PS_ReadToken( script, &token ) ) { ent = &bspworld.entities[bspworld.numentities]; bspworld.numentities++; ent->epairs = NULL; while ( PS_ReadToken( script, &token ) ) { if ( !strcmp( token.string, "}" ) ) { break; } epair = (bsp_epair_t *) buftrav; buftrav += sizeof( bsp_epair_t ); epair->next = ent->epairs; ent->epairs = epair; StripDoubleQuotes( token.string ); epair->key = (char *) buftrav; buftrav += ( strlen( token.string ) + 1 ); strcpy( epair->key, token.string ); if ( !PS_ExpectTokenType( script, TT_STRING, 0, &token ) ) { AAS_FreeBSPEntities(); FreeScript( script ); return; } //end if StripDoubleQuotes( token.string ); epair->value = (char *) buftrav; buftrav += ( strlen( token.string ) + 1 ); strcpy( epair->value, token.string ); } //end while } //end while FreeScript( script ); } //end of the function AAS_ParseBSPEntities
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ParseBSPEntities(void) { script_t *script; token_t token; bsp_entity_t *ent; bsp_epair_t *epair; script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata"); SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE); bspworld.numentities = 1; while(PS_ReadToken(script, &token)) { if (strcmp(token.string, "{")) { ScriptError(script, "invalid %s", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if if (bspworld.numentities >= MAX_BSPENTITIES) { botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n"); break; } //end if ent = &bspworld.entities[bspworld.numentities]; bspworld.numentities++; ent->epairs = NULL; while(PS_ReadToken(script, &token)) { if (!strcmp(token.string, "}")) break; epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t)); epair->next = ent->epairs; ent->epairs = epair; if (token.type != TT_STRING) { ScriptError(script, "invalid %s", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if StripDoubleQuotes(token.string); epair->key = (char *) GetHunkMemory(strlen(token.string) + 1); strcpy(epair->key, token.string); if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) { AAS_FreeBSPEntities(); FreeScript(script); return; } //end if StripDoubleQuotes(token.string); epair->value = (char *) GetHunkMemory(strlen(token.string) + 1); strcpy(epair->value, token.string); } //end while if (strcmp(token.string, "}")) { ScriptError(script, "missing }"); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if } //end while FreeScript(script); } //end of the function AAS_ParseBSPEntities
/* ================ Q2_ParseMapEntity ================ */ qboolean Q2_ParseMapEntity(script_t *script) { entity_t *mapent; epair_t *e; side_t *s; int i, j; int startbrush, startsides; vec_t newdist; mapbrush_t *b; token_t token; if (!PS_ReadToken(script, &token)) { return false; } if (strcmp(token.string, "{")) { Error("ParseEntity: { not found"); } if (num_entities == MAX_MAP_ENTITIES) { Error("num_entities == MAX_MAP_ENTITIES"); } startbrush = nummapbrushes; startsides = nummapbrushsides; mapent = &entities[num_entities]; num_entities++; memset(mapent, 0, sizeof(*mapent)); mapent->firstbrush = nummapbrushes; mapent->numbrushes = 0; // mapent->portalareas[0] = -1; // mapent->portalareas[1] = -1; do { if (!PS_ReadToken(script, &token)) { Error("ParseEntity: EOF without closing brace"); } //end if if (!strcmp(token.string, "}")) { break; } if (!strcmp(token.string, "{")) { Q2_ParseBrush(script, mapent); } //end if else { PS_UnreadLastToken(script); e = ParseEpair(script); e->next = mapent->epairs; mapent->epairs = e; } //end else } while (1); GetVectorForKey(mapent, "origin", mapent->origin); // // if there was an origin brush, offset all of the planes and texinfo // if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { for (i = 0 ; i < mapent->numbrushes ; i++) { b = &mapbrushes[mapent->firstbrush + i]; for (j = 0 ; j < b->numsides ; j++) { s = &b->original_sides[j]; newdist = mapplanes[s->planenum].dist - DotProduct(mapplanes[s->planenum].normal, mapent->origin); s->planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist, 0, NULL); s->texinfo = TexinfoForBrushTexture(&mapplanes[s->planenum], &side_brushtextures[s - brushsides], mapent->origin); } MakeBrushWindings(b); } } // group entities are just for editor convenience // toss all brushes into the world entity if (!strcmp("func_group", ValueForKey(mapent, "classname"))) { Q2_MoveBrushesToWorld(mapent); mapent->numbrushes = 0; return true; } // areaportal entities move their brushes, but don't eliminate // the entity if (!strcmp("func_areaportal", ValueForKey(mapent, "classname"))) { char str[128]; if (mapent->numbrushes != 1) { Error("Entity %i: func_areaportal can only be a single brush", num_entities - 1); } b = &mapbrushes[nummapbrushes - 1]; b->contents = CONTENTS_AREAPORTAL; c_areaportals++; mapent->areaportalnum = c_areaportals; // set the portal number as "style" sprintf(str, "%i", c_areaportals); SetKeyValue(mapent, "style", str); Q2_MoveBrushesToWorld(mapent); return true; } return true; }
/* ================= Q2_ParseBrush ================= */ void Q2_ParseBrush(script_t *script, entity_t *mapent) { mapbrush_t *b; int i, j, k; int mt; side_t *side, *s2; int planenum; brush_texture_t td; int planepts[3][3]; token_t token; if (nummapbrushes >= MAX_MAPFILE_BRUSHES) { Error("nummapbrushes == MAX_MAPFILE_BRUSHES"); } b = &mapbrushes[nummapbrushes]; b->original_sides = &brushsides[nummapbrushsides]; b->entitynum = num_entities - 1; b->brushnum = nummapbrushes - mapent->firstbrush; b->leafnum = -1; do { if (!PS_ReadToken(script, &token)) { break; } if (!strcmp(token.string, "}")) { break; } //IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could // lead to out of bound indexing of the arrays if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES) { Error("MAX_MAPFILE_BRUSHSIDES"); } side = &brushsides[nummapbrushsides]; //read the three point plane definition for (i = 0; i < 3; i++) { if (i != 0) { PS_ExpectTokenString(script, "("); } for (j = 0; j < 3; j++) { PS_ExpectAnyToken(script, &token); planepts[i][j] = atof(token.string); } //end for PS_ExpectTokenString(script, ")"); } //end for // //read the texturedef // PS_ExpectAnyToken(script, &token); strcpy(td.name, token.string); PS_ExpectAnyToken(script, &token); td.shift[0] = atol(token.string); PS_ExpectAnyToken(script, &token); td.shift[1] = atol(token.string); PS_ExpectAnyToken(script, &token); td.rotate = atol(token.string); PS_ExpectAnyToken(script, &token); td.scale[0] = atof(token.string); PS_ExpectAnyToken(script, &token); td.scale[1] = atof(token.string); //find default flags and values mt = FindMiptex(td.name); td.flags = textureref[mt].flags; td.value = textureref[mt].value; side->contents = textureref[mt].contents; side->surf = td.flags = textureref[mt].flags; //check if there's a number available if (PS_CheckTokenType(script, TT_NUMBER, 0, &token)) { side->contents = token.intvalue; PS_ExpectTokenType(script, TT_NUMBER, 0, &token); side->surf = td.flags = token.intvalue; PS_ExpectTokenType(script, TT_NUMBER, 0, &token); td.value = token.intvalue; } // translucent objects are automatically classified as detail // if (side->surf & (SURF_TRANS33|SURF_TRANS66) ) // side->contents |= CONTENTS_DETAIL; if (side->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP)) { side->contents |= CONTENTS_DETAIL; } if (fulldetail) { side->contents &= ~CONTENTS_DETAIL; } if (!(side->contents & ((LAST_VISIBLE_CONTENTS - 1) | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP | CONTENTS_MIST))) { side->contents |= CONTENTS_SOLID; } // hints and skips are never detail, and have no content // if (side->surf & (SURF_HINT|SURF_SKIP) ) // { // side->contents = 0; // side->surf &= ~CONTENTS_DETAIL; // } #ifdef ME //for creating AAS... this side is textured side->flags |= SFL_TEXTURED; #endif //ME // // find the plane number // planenum = PlaneFromPoints(planepts[0], planepts[1], planepts[2]); if (planenum == -1) { Log_Print("Entity %i, Brush %i: plane with no normal\n" , b->entitynum, b->brushnum); continue; } // // see if the plane has been used already // for (k = 0 ; k < b->numsides ; k++) { s2 = b->original_sides + k; if (s2->planenum == planenum) { Log_Print("Entity %i, Brush %i: duplicate plane\n" , b->entitynum, b->brushnum); break; } if (s2->planenum == (planenum ^ 1)) { Log_Print("Entity %i, Brush %i: mirrored plane\n" , b->entitynum, b->brushnum); break; } } if (k != b->numsides) { continue; // duplicated } // // keep this side // side = b->original_sides + b->numsides; side->planenum = planenum; side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum], &td, vec3_origin); // save the td off in case there is an origin brush and we // have to recalculate the texinfo side_brushtextures[nummapbrushsides] = td; nummapbrushsides++; b->numsides++; } while (1); // get the content for the entire brush b->contents = Q2_BrushContents(b); #ifdef ME if (BrushExists(b)) { c_squattbrushes++; b->numsides = 0; return; } //end if if (create_aas) { //create AAS brushes, and add brush bevels AAS_CreateMapBrushes(b, mapent, true); //NOTE: if we return here then duplicate plane errors occur for the non world entities return; } //end if #endif //ME // allow detail brushes to be removed if (nodetail && (b->contents & CONTENTS_DETAIL)) { b->numsides = 0; return; } // allow water brushes to be removed if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER))) { b->numsides = 0; return; } // create windings for sides and bounds for brush MakeBrushWindings(b); // brushes that will not be visible at all will never be // used as bsp splitters if (b->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP)) { c_clipbrushes++; for (i = 0 ; i < b->numsides ; i++) b->original_sides[i].texinfo = TEXINFO_NODE; } // // origin brushes are removed, but they set // the rotation origin for the rest of the brushes // in the entity. After the entire entity is parsed, // the planenums and texinfos will be adjusted for // the origin brush // if (b->contents & CONTENTS_ORIGIN) { char string[32]; vec3_t origin; if (num_entities == 1) { Error("Entity %i, Brush %i: origin brushes not allowed in world" , b->entitynum, b->brushnum); return; } VectorAdd(b->mins, b->maxs, origin); VectorScale(origin, 0.5, origin); sprintf(string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); SetKeyValue(&entities[b->entitynum], "origin", string); VectorCopy(origin, entities[b->entitynum].origin); // don't keep this brush b->numsides = 0; return; } AddBrushBevels(b); nummapbrushes++; mapent->numbrushes++; }
bool PS_ExpectTokenType( script_t* script, int type, int subtype, token_t* token ) { if ( !PS_ReadToken( script, token ) ) { ScriptError( script, "couldn't read expected token" ); return false; } if ( token->type != type ) { char str[ MAX_TOKEN ]; if ( type == TT_STRING ) { String::Cpy( str, "string" ); } if ( type == TT_LITERAL ) { String::Cpy( str, "literal" ); } if ( type == TT_NUMBER ) { String::Cpy( str, "number" ); } if ( type == TT_NAME ) { String::Cpy( str, "name" ); } if ( type == TT_PUNCTUATION ) { String::Cpy( str, "punctuation" ); } ScriptError( script, "expected a %s, found %s", str, token->string ); return false; } if ( token->type == TT_NUMBER ) { if ( ( token->subtype & subtype ) != subtype ) { char str[ MAX_TOKEN ]; if ( subtype & TT_DECIMAL ) { String::Cpy( str, "decimal" ); } if ( subtype & TT_HEX ) { String::Cpy( str, "hex" ); } if ( subtype & TT_OCTAL ) { String::Cpy( str, "octal" ); } if ( subtype & TT_BINARY ) { String::Cpy( str, "binary" ); } if ( subtype & TT_LONG ) { String::Cat( str, sizeof ( str ), " long" ); } if ( subtype & TT_UNSIGNED ) { String::Cat( str, sizeof ( str ), " unsigned" ); } if ( subtype & TT_FLOAT ) { String::Cat( str, sizeof ( str ), " float" ); } if ( subtype & TT_INTEGER ) { String::Cat( str, sizeof ( str ), " integer" ); } ScriptError( script, "expected %s, found %s", str, token->string ); return false; } } else if ( token->type == TT_PUNCTUATION ) { if ( subtype < 0 ) { ScriptError( script, "BUG: wrong punctuation subtype" ); return false; } if ( token->subtype != subtype ) { ScriptError( script, "expected %s, found %s", script->punctuations[ subtype ].p, token->string ); return false; } } return true; }