/* ================ ParseEntity ================ */ qboolean ParseEntity (void) { if (!GetToken (true)) return false; if (strcmp (token, "{") ) Error ("ParseEntity: { not found"); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); mapent = &entities[num_entities]; num_entities++; do { fflush(stdout); if (!GetToken (true)) Error ("ParseEntity: EOF without closing brace"); if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) ParseBrush (); else ParseEpair (); } while (1); // all fields have been parsed if (!strncmp (mapent->classname, "light", 5)) { if (!mapent->light) { mapent->color[0] = mapent->color[1] = mapent->color[2] = 1; mapent->light = DEFAULTLIGHTLEVEL; } // LordHavoc: added falloff and color if (!mapent->falloff) mapent->falloff = DEFAULTFALLOFF * DEFAULTFALLOFF; } if (!strcmp (mapent->classname, "light")) if (mapent->targetname[0] && !mapent->style) { char s[16]; mapent->style = LightStyleForTargetname (mapent->targetname, true); sprintf (s,"%i", mapent->style); SetKeyValue (mapent, "style", s); } GetVectorForKey (mapent, "origin", mapent->origin); return true; }
/* ================== ParseLightEntities ================== */ void ParseLightEntities( void ) { int i, j; entity_t *ent; char *value, *targetname, *style; directlight_t *l; double vec[4], color2[3]; qboolean isLight; num_directlights = 0; for( i = 0, ent = entities; i < num_entities; i++, ent++ ) { value = ValueForKey( ent, "classname" ); if( strncmp (value, "light", 5) ) continue; if( !strcmp (value, "light") ) isLight = true; else isLight = false; if( num_directlights == MAP_DIRECTLIGHTS ) Error( "numdirectlights == MAP_DIRECTLIGHTS" ); l = &directlights[num_directlights++]; memset( l, 0, sizeof (*l) ); color2[0] = color2[1] = color2[2] = 1.0f; l->color[0] = l->color[1] = l->color[2] = 1.0f; GetVectorForKey( ent, "origin", l->origin ); l->type = defaultlighttype; if (!overridelighttypes && (j = FloatForKey( ent, "delay" ))) { if (j < 0 || j >= LIGHTTYPE_TOTAL) Error("error in light at %.0f %.0f %.0f:\nunknown light type \"delay\" \"%s\"\n", l->origin[0], l->origin[1], l->origin[2], ValueForKey( ent, "delay" )); l->type = j; } l->style = FloatForKey( ent, "style" ); if( (unsigned)l->style > 254 ) Error( "error in light at %.0f %.0f %.0f:\nBad light style %i (must be 0-254)", l->origin[0], l->origin[1], l->origin[2], l->style ); l->angle = FloatForKey( ent, "angle" ); value = ValueForKey( ent, "color" ); if( !value[0] ) value = ValueForKey( ent, "_color" ); if( value[0] ) if( sscanf (value, "%lf %lf %lf", &color2[0], &color2[1], &color2[2]) != 3 ) Error( "error in light at %.0f %.0f %.0f:\ncolor must be given 3 values", l->origin[0], l->origin[1], l->origin[2] ); value = ValueForKey( ent, "light" ); if( !value[0] ) value = ValueForKey( ent, "_light" ); if( value[0] ) { j = sscanf ( value, "%lf %lf %lf %lf", &vec[0], &vec[1], &vec[2], &vec[3] ); switch( j ) { case 4:// HalfLife light l->color[0] = vec[0]; l->color[1] = vec[1]; l->color[2] = vec[2]; l->radius = vec[3]; break; case 1: // quake light l->radius = vec[0]; l->color[0] = vec[0]; l->color[1] = vec[0]; l->color[2] = vec[0]; break; default: Error( "error in light at %.0f %.0f %.0f:\n_light (or light) key must be 1 (Quake) or 4 (HalfLife) numbers, \"%s\" is not valid\n", l->origin[0], l->origin[1], l->origin[2], value ); } } if( !l->radius ) { l->radius = DEFAULTLIGHTLEVEL; l->color[0] = DEFAULTLIGHTLEVEL; l->color[1] = DEFAULTLIGHTLEVEL; l->color[2] = DEFAULTLIGHTLEVEL; } // for some reason this * 0.5 is needed to match quake light VectorScale(l->color, 0.5, l->color); // fix tyrlite darklight radius value (but color remains negative) l->radius = fabs(l->radius); // apply scaling to radius vec[0] = FloatForKey( ent, "wait" ); if( !vec[0] ) vec[0] = 1; if (vec[0] != 1) { if (vec[0] <= 0.0001) { l->type = LIGHTTYPE_NONE; l->radius = BOGUS_RANGE; VectorScale(l->color, 0.25, l->color); } else l->radius /= vec[0]; } l->radius *= globallightradiusscale; l->clampradius = l->radius; switch (l->type) { case LIGHTTYPE_RECIPX: l->clampradius = BOGUS_RANGE; break; case LIGHTTYPE_RECIPXX: l->clampradius = BOGUS_RANGE; break; default: break; } l->color[0] *= color2[0] * globallightscale; l->color[1] *= color2[1] * globallightscale; l->color[2] *= color2[2] * globallightscale; // this confines the light to a specified radius (typically used on RECIPX and RECIPXX) vec[0] = FloatForKey( ent, "_lightradius" ); if (vec[0]) l->clampradius = vec[0]; if( isLight ) { value = ValueForKey( ent, "targetname" ); if( value[0] && !l->style ) { char s[16]; l->style = LightStyleForTargetname( value ); memset( s, 0, sizeof(s) ); sprintf( s, "%i", l->style ); SetKeyValue( ent, "style", s ); } } value = ValueForKey( ent, "target" ); if( !value[0] ) { if (l->type == LIGHTTYPE_SUN) Error("error in light at %.0f %.0f %.0f:\nLIGHTTYPE_SUN (delay 4) requires a target for the sun direction\n", l->origin[0], l->origin[1], l->origin[2]); continue; } for( j = 0; j < num_entities; j++ ) { if( i == j ) continue; targetname = ValueForKey( &entities[j], "targetname" ); if( !strcmp (targetname, value) ) { vec3_t origin; GetVectorForKey( &entities[j], "origin", origin ); // set up spotlight values for lighting code to use VectorSubtract( origin, l->origin, l->spotdir ); VectorNormalize( l->spotdir ); if( !l->angle ) l->spotcone = -cos( 20 * Q_PI / 180 ); else l->spotcone = -cos( l->angle / 2 * Q_PI / 180 ); break; } } if( j == num_entities ) { printf( "warning in light at %.0f %.0f %.0f:\nunmatched spotlight target\n", l->origin[0], l->origin[1], l->origin[2]); if (l->type == LIGHTTYPE_SUN) Error("error in light at %.0f %.0f %.0f:\nLIGHTTYPE_SUN (delay 4) requires a target for the sun direction\n", l->origin[0], l->origin[1], l->origin[2]); continue; } // set the style on the source ent for switchable lights style = ValueForKey( &entities[j], "style" ); if( style[0] && atof (style) ) { char s[16]; l->style = atof( style ); if( (unsigned)l->style > 254 ) Error( "error in light at %.0f %.0f %.0f:\nBad target light style %i (must be 0-254)", l->origin[0], l->origin[1], l->origin[2], l->style ); memset( s, 0, sizeof(s) ); sprintf( s, "%i", l->style ); SetKeyValue( ent, "style", s ); } } }
/* ================== LoadEntities ================== */ void LoadEntities (void) { char *data; entity_t *entity; char key[64]; epair_t *epair; // jkrige double vec[3]; int i; int num_lights; // jkrige data = dentdata; // // start parsing // num_entities = 0; num_lights = 0; // jkrige // go through all the entities while (1) { // parse the opening brace data = COM_Parse (data); if (!data) break; if (com_token[0] != '{') logerror ("LoadEntities: found %s when expecting {",com_token); // jkrige - was Error() if (num_entities == MAX_MAP_ENTITIES) logerror ("LoadEntities: MAX_MAP_ENTITIES"); // jkrige - was Error() entity = &entities[num_entities]; num_entities++; // jkrige // flag to indicate use of mangle key entity->use_mangle = false; // jkrige // go through all the keys in this entity while (1) { int c; // parse key data = COM_Parse (data); if (!data) logerror ("LoadEntities: EOF without closing brace"); // jkrige - was Error() if (!strcmp(com_token,"}")) break; strcpy (key, com_token); // parse value data = COM_Parse (data); if (!data) logerror ("LoadEntities: EOF without closing brace"); // jkrige - was Error() c = com_token[0]; if (c == '}') logerror ("LoadEntities: closing brace without data"); // jkrige - was Error() epair = malloc (sizeof(epair_t)); memset (epair, 0, sizeof(epair)); strcpy (epair->key, key); strcpy (epair->value, com_token); epair->next = entity->epairs; entity->epairs = epair; if (!strcmp(key, "classname")) strcpy (entity->classname, com_token); else if (!strcmp(key, "target")) strcpy (entity->target, com_token); else if (!strcmp(key, "targetname")) strcpy (entity->targetname, com_token); else if (!strcmp(key, "origin")) { // jkrige //if (sscanf(com_token, "%lf %lf %lf", // &entity->origin[0], // &entity->origin[1], // &entity->origin[2]) != 3) // Error ("LoadEntities: not 3 values for origin"); if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) logerror ("LoadEntities: not 3 values for origin"); // jkrige - was Error() for (i=0 ; i<3 ; i++) entity->origin[i] = vec[i]; // jkrige } else if (!strncmp(key, "light", 5)) { entity->light = atoi(com_token); } else if (!strcmp(key, "style")) { entity->style = atoi(com_token); if ((unsigned)entity->style > 254) logerror ("Bad light style %i (must be 0-254)", entity->style); // jkrige - was Error() } else if (!strcmp(key, "angle")) { entity->angle = (float)atof(com_token); } // jkrige else if (!strcmp(key, "wait")) entity->atten = (float)atof(com_token); else if (!strcmp(key, "delay")) entity->formula = atoi(com_token); else if (!strcmp(key, "mangle")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) logerror ("LoadEntities: not 3 values for mangle"); // jkrige - was Error() // Precalculate the direction vector entity->use_mangle = true; //vec_from_mangle(entity->mangle, vec); entity->mangle[0] = cos(vec[0]*Q_PI/180)*cos(vec[1]*Q_PI/180); entity->mangle[1] = sin(vec[0]*Q_PI/180)*cos(vec[1]*Q_PI/180); entity->mangle[2] = sin(vec[1]*Q_PI/180); } #ifdef HX2COLOR else if (!strcmp(key, "_color") || !strcmp(key, "color")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) logerror ("LoadEntities: not 3 values for colour"); // jkrige - was Error() for (i=0 ; i<3 ; i++) //entity->lightcolor[i] = (int)vec[i]*255; // jkrige - added (int) entity->lightcolor[i] = (int)vec[i]; // jkrige - added (int) } else if (!strcmp(key, "_minlight_color") || !strcmp(key, "minlight_color")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) logerror ("LoadEntities: not 3 values for _minlight_color"); // jkrige - was Error() for (i=0 ; i<3 ; i++) //minlight_color[i] = vec[i]*255; minlight_color[i] = vec[i]; } #endif /*else if (!strcmp(key, "_sunlight")) sunlight = (int)atof(com_token); else if (!strcmp(key, "_sun_mangle")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) Error ("LoadEntities: not 3 values for _sun_mangle"); // Precalculate sun vector and // make it too large to fit into the map vec_from_mangle(sunmangle, vec); //sunmangle[0] = cos(vec[0]*Q_PI/180)*cos(vec[1]*Q_PI/180); //sunmangle[1] = sin(vec[0]*Q_PI/180)*cos(vec[1]*Q_PI/180); //sunmangle[2] = sin(vec[1]*Q_PI/180); VectorNormalize(sunmangle); VectorScale(sunmangle, -16384, sunmangle); } else if (!strcmp(key, "_sunlight_color")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) Error ("LoadEntities: not 3 values for _sunlight_color"); for (i=0 ; i<3 ; i++) sunlight_color[i] = vec[i]; }*/ // jkrige } // all fields have been parsed // jkrige //if (!strncmp (entity->classname, "light", 5) && !entity->light) // entity->light = DEFAULTLIGHTLEVEL; if (!strncmp (entity->classname, "light", 5)) { if (!entity->light) entity->light = DEFAULTLIGHTLEVEL; if (entity->atten <= 0.0) entity->atten = 1.0; if ((entity->formula < 0) || (entity->formula > 3)) entity->formula = 0; #ifdef HX2COLOR if (!entity->lightcolor[0] && !entity->lightcolor[1] && !entity->lightcolor[2]) { entity->lightcolor[0] = 255; entity->lightcolor[1] = 255; entity->lightcolor[2] = 255; } #endif num_lights++; } // jkrige //if (!strncmp (entity->classname, "light", 5)) if (!strcmp (entity->classname, "light")) // jkrige { if (entity->targetname[0] && !entity->style) { char s[16]; entity->style = LightStyleForTargetname (entity->targetname, true); sprintf (s,"%i", entity->style); SetKeyValue (entity, "style", s); } } // jkrige if (!strcmp (entity->classname, "worldspawn")) { if (entity->light > 0 && !worldminlight) { worldminlight = entity->light; logprint("Using minlight value %i from worldspawn.\n", worldminlight); } else if (worldminlight) { logprint("Using minlight value %i from command line.\n", worldminlight); } } // jkrige } //logprint ("%d entities read\n", num_entities); logprint ("%d entities read, %d are lights.\n", num_entities, num_lights); // jkrige MatchTargets (); }
/* ================== LoadEntities ================== */ void LoadEntities (void) { char *data; entity_t *entity; char key[64]; epair_t *epair; double vec[3]; int i; data = dentdata; // // start parsing // num_entities = 0; // go through all the entities while (1) { // parse the opening brace data = COM_Parse (data); if (!data) break; if (com_token[0] != '{') Error ("LoadEntities: found %s when expecting {",com_token); if (num_entities == MAX_MAP_ENTITIES) Error ("LoadEntities: MAX_MAP_ENTITIES"); entity = &entities[num_entities]; num_entities++; // go through all the keys in this entity while (1) { int c; // parse key data = COM_Parse (data); if (!data) Error ("LoadEntities: EOF without closing brace"); if (!strcmp(com_token,"}")) break; strcpy (key, com_token); // parse value data = COM_Parse (data); if (!data) Error ("LoadEntities: EOF without closing brace"); c = com_token[0]; if (c == '}') Error ("LoadEntities: closing brace without data"); epair = malloc (sizeof(epair_t)); memset (epair, 0, sizeof(epair)); strcpy (epair->key, key); strcpy (epair->value, com_token); epair->next = entity->epairs; entity->epairs = epair; if (!strcmp(key, "classname")) strcpy (entity->classname, com_token); else if (!strcmp(key, "target")) strcpy (entity->target, com_token); else if (!strcmp(key, "targetname")) strcpy (entity->targetname, com_token); else if (!strcmp(key, "origin")) { // scan into doubles, then assign // which makes it vec_t size independent if (sscanf(com_token, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]) != 3) Error ("LoadEntities: not 3 values for origin"); for (i=0 ; i<3 ; i++) entity->origin[i] = vec[i]; } else if (!strncmp(key, "light", 5) || !strcmp (key, "_light") ) { entity->light = atof(com_token); } else if (!strcmp(key, "style")) { entity->style = atof(com_token); if ((unsigned)entity->style > 254) Error ("Bad light style %i (must be 0-254)", entity->style); } else if (!strcmp(key, "angle")) { entity->angle = atof(com_token); } } // all fields have been parsed if (!strncmp (entity->classname, "light", 5) && !entity->light) entity->light = DEFAULTLIGHTLEVEL; if (!strcmp (entity->classname, "light")) { if (entity->targetname[0] && !entity->style) { char s[16]; entity->style = LightStyleForTargetname (entity->targetname, true); sprintf (s,"%i", entity->style); SetKeyValue (entity, "style", s); } } } printf ("%d entities read\n", num_entities); MatchTargets (); }