#include "qedefs.h" @implementation Entity vec3_t bad_mins = {-8, -8, -8}; vec3_t bad_maxs = {8, 8, 8}; - createFixedBrush: (vec3_t)org { vec3_t emins, emaxs; float *v, *v2, *color; id new; texturedef_t td; // get class new = [entity_classes_i classForName: [self valueForQKey: "classname"]]; if (new) { v = [new mins]; v2 = [new maxs]; } else { v = bad_mins; v2 = bad_maxs; } color = [new drawColor]; modifiable = NO; memset(&td,0,sizeof(td)); strcpy (td.texture,"entity"); VectorAdd (org, v, emins); VectorAdd (org, v2, emaxs); new = [[SetBrush alloc] initOwner: self mins:emins maxs:emaxs texture: &td]; [new setEntityColor: color]; [self addObject: new]; return self; } - copyFromZone:(NSZone *)zone { id new, nb; epair_t *e; int i; new = [[Entity alloc] init]; [new setModifiable: modifiable]; for (e = epairs; e; e = e->next) { if (strncmp (e->key, "target", 6)) // don't copy target and targetname fields [new setKey: e->key toValue: e->value]; } for (i = 0; i < [self count]; i++) { nb = [[self objectAtIndex: i] copy]; [nb setParent: new]; [new addObject: nb]; } return new; } - initClass: (char *)classname { id new; esize_t esize; char value[80]; vec3_t min, max; float *v; [super init]; modifiable = YES; [self setKey: "classname" toValue:classname]; // get class new = [entity_classes_i classForName: [self valueForQKey: "classname"]]; if (!new) esize = esize_model; else esize = [new esize]; // create a brush if needed if (esize == esize_fixed) { v = [new mins]; [[map_i selectedBrush] getMins: min maxs: max]; VectorSubtract (min, v, min); sprintf (value, "%i %i %i",(int)min[0], (int)min[1], (int)min[2]); [self setKey:"origin" toValue: value]; [self createFixedBrush: min]; } else modifiable = YES; return self; } - (oneway void) release { epair_t *e, *n; for (e = epairs; e; e = n) { n = e->next; free (e); } [super release]; } - (BOOL) modifiable { return modifiable; } - setModifiable: (BOOL) m { modifiable = m; return self; } - (void) removeObject: (id) anObject { [super removeObject: anObject]; if ([self count]) return; // the entity is empty, so remove the entire thing if (self == [map_i objectAtIndex: 0]) // never remove the world return; [map_i removeObject: self]; [self release]; return; } - (char *)valueForQKey: (char *)k { epair_t *e; static char ret[64]; for (e=epairs ; e ; e=e->next) if (!strcmp(k,e->key)) { strcpy (ret, e->value); return ret; } return ""; } - getVector: (vec3_t)v forKey: (char *)k { char *c; c = [self valueForQKey: k]; v[0] = v[1] = v[2] = 0; sscanf (c, "%f %f %f", &v[0], &v[1], &v[2]); return self; } - print { epair_t *e; for (e=epairs ; e ; e=e->next) printf ("%20s : %20s\n",e->key, e->value); return self; } - setKey:(char *)k toValue:(char *)v { epair_t *e; if (strlen(k) > MAX_KEY) Error ("setKey: %s > MAX_KEY", k); if (strlen(v) > MAX_VALUE) Error ("setKey: %s > MAX_VALUE", v); while (*k && *k <= ' ') k++; if (!*k) return self; // don't set NULL values for (e=epairs ; e ; e=e->next) if (!strcmp(k,e->key)) { memset (e->value, 0, sizeof(e->value)); strcpy (e->value, v); return self; } e = malloc (sizeof(epair_t)); memset (e, 0, sizeof(epair_t)); strcpy (e->key, k); strcpy (e->value, v); e->next = epairs; epairs = e; return self; } - (int)numPairs { int i; epair_t *e; i=0; for (e=epairs ; e ; e=e->next) i++; return i; } - (epair_t *)epairs { return epairs; } - removeKeyPair: (char *)key { epair_t *e, *e2; if (!epairs) return self; e = epairs; if (!strcmp(e->key, key)) { epairs = e->next; free (e); return self; } for (; e ; e=e->next) { if (e->next && !strcmp(e->next->key, key)) { e2 = e->next; e->next = e2->next; free (e2); return self; } } printf ("WARNING: removeKeyPair: %s not found\n", key); return self; } /* ============= targetname If the entity does not have a "targetname" key, a unique one is generated ============= */ - (char *)targetname { char *t; int i, count; id ent; int tval, maxt; char name[20]; t = [self valueForQKey: "targetname"]; if (t && t[0]) return t; // make a unique name of the form t count = [map_i count]; maxt = 0; for (i=1 ; i maxt) maxt = tval; } sprintf (name,"t%i",maxt+1); [self setKey: "targetname" toValue: name]; return [self valueForQKey: "targetname"]; // so it's not on the stack } /* ============================================================================== FILE METHODS ============================================================================== */ int nument; - initFromTokens { char key[MAXTOKEN]; id eclass, brush; char *spawn; vec3_t emins, emaxs; vec3_t org; texturedef_t td; esize_t esize; int i, c; float *color; [self init]; if (!GetToken (true)) { [self release]; return nil; } if (strcmp (token, "{") ) Error ("initFromFileP: { not found"); do { if (!GetToken (true)) break; if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) { // read a brush brush = [[SetBrush alloc] initFromTokens: self]; [self addObject: brush]; } else { // read a key / value pair strcpy (key, token); GetToken (false); [self setKey: key toValue:token]; } } while (1); nument++; // get class spawn = [self valueForQKey: "classname"]; eclass = [entity_classes_i classForName: spawn]; esize = [eclass esize]; [self getVector: org forKey: "origin"]; if ([self count] && esize != esize_model) { printf ("WARNING:Entity with brushes and wrong model type\n"); [self removeAllObjects]; } if (![self count] && esize == esize_model) { printf ("WARNING:Entity with no brushes and esize_model\n"); [texturepalette_i getTextureDef: &td]; for (i=0 ; i<3 ; i++) { emins[i] = org[i] - 8; emaxs[i] = org[i] + 8; } brush = [[SetBrush alloc] initOwner: self mins:emins maxs:emaxs texture: &td]; [self addObject: brush]; } // create a brush if needed if (esize == esize_fixed) [self createFixedBrush: org]; else modifiable = YES; // set all the brush colors color = [eclass drawColor]; c = [self count]; for (i=0 ; inext) fprintf (f,"\"%s\"\t\"%s\"\n", e->key, e->value); // fixed size entities don't save out brushes if ( modifiable ) { for (i=0 ; i < [self count]; i++) [[self objectAtIndex: i] writeToFILE: f region: reg]; } fprintf (f,"}\n"); if (temporg) [self setKey: "angle" toValue: oldang]; return self; } /* ============================================================================== INTERACTION ============================================================================== */ @end