00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "../game/q_shared.h"
00033 #include "l_memory.h"
00034 #include "l_script.h"
00035 #include "l_precomp.h"
00036 #include "l_struct.h"
00037 #include "aasfile.h"
00038 #include "../game/botlib.h"
00039 #include "../game/be_aas.h"
00040 #include "be_aas_funcs.h"
00041 #include "be_aas_def.h"
00042
00043 extern botlib_import_t botimport;
00044
00045
00046
00047 #define ON_EPSILON 0.005
00048
00049
00050 #define MAX_BSPENTITIES 2048
00051
00052 typedef struct rgb_s
00053 {
00054 int red;
00055 int green;
00056 int blue;
00057 } rgb_t;
00058
00059
00060 typedef struct bsp_epair_s
00061 {
00062 char *key;
00063 char *value;
00064 struct bsp_epair_s *next;
00065 } bsp_epair_t;
00066
00067
00068 typedef struct bsp_entity_s
00069 {
00070 bsp_epair_t *epairs;
00071 } bsp_entity_t;
00072
00073
00074 typedef struct bsp_s
00075 {
00076
00077 int loaded;
00078
00079 int entdatasize;
00080 char *dentdata;
00081
00082 int numentities;
00083 bsp_entity_t entities[MAX_BSPENTITIES];
00084 } bsp_t;
00085
00086
00087 bsp_t bspworld;
00088
00089
00090 #ifdef BSP_DEBUG
00091 typedef struct cname_s
00092 {
00093 int value;
00094 char *name;
00095 } cname_t;
00096
00097 cname_t contentnames[] =
00098 {
00099 {CONTENTS_SOLID,"CONTENTS_SOLID"},
00100 {CONTENTS_WINDOW,"CONTENTS_WINDOW"},
00101 {CONTENTS_AUX,"CONTENTS_AUX"},
00102 {CONTENTS_LAVA,"CONTENTS_LAVA"},
00103 {CONTENTS_SLIME,"CONTENTS_SLIME"},
00104 {CONTENTS_WATER,"CONTENTS_WATER"},
00105 {CONTENTS_MIST,"CONTENTS_MIST"},
00106 {LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
00107
00108 {CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
00109 {CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
00110 {CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
00111 {CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
00112 {CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
00113 {CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
00114 {CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
00115 {CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
00116 {CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
00117 {CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
00118 {CONTENTS_MONSTER,"CONTENTS_MONSTER"},
00119 {CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
00120 {CONTENTS_DETAIL,"CONTENTS_DETAIL"},
00121 {CONTENTS_TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
00122 {CONTENTS_LADDER,"CONTENTS_LADDER"},
00123 {0, 0}
00124 };
00125
00126 void PrintContents(int contents)
00127 {
00128 int i;
00129
00130 for (i = 0; contentnames[i].value; i++)
00131 {
00132 if (contents & contentnames[i].value)
00133 {
00134 botimport.Print(PRT_MESSAGE, "%s\n", contentnames[i].name);
00135 }
00136 }
00137 }
00138
00139 #endif // BSP_DEBUG
00140
00141
00142
00143
00144
00145
00146
00147 bsp_trace_t AAS_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
00148 {
00149 bsp_trace_t bsptrace;
00150 botimport.Trace(&bsptrace, start, mins, maxs, end, passent, contentmask);
00151 return bsptrace;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 int AAS_PointContents(vec3_t point)
00161 {
00162 return botimport.PointContents(point);
00163 }
00164
00165
00166
00167
00168
00169
00170 qboolean AAS_EntityCollision(int entnum,
00171 vec3_t start, vec3_t boxmins, vec3_t boxmaxs, vec3_t end,
00172 int contentmask, bsp_trace_t *trace)
00173 {
00174 bsp_trace_t enttrace;
00175
00176 botimport.EntityTrace(&enttrace, start, boxmins, boxmaxs, end, entnum, contentmask);
00177 if (enttrace.fraction < trace->fraction)
00178 {
00179 Com_Memcpy(trace, &enttrace, sizeof(bsp_trace_t));
00180 return qtrue;
00181 }
00182 return qfalse;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 qboolean AAS_inPVS(vec3_t p1, vec3_t p2)
00192 {
00193 return botimport.inPVS(p1, p2);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 qboolean AAS_inPHS(vec3_t p1, vec3_t p2)
00203 {
00204 return qtrue;
00205 }
00206
00207
00208
00209
00210
00211
00212 void AAS_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin)
00213 {
00214 botimport.BSPModelMinsMaxsOrigin(modelnum, angles, mins, maxs, origin);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 void AAS_UnlinkFromBSPLeaves(bsp_link_t *leaves)
00224 {
00225 }
00226
00227
00228
00229
00230
00231
00232 bsp_link_t *AAS_BSPLinkEntity(vec3_t absmins, vec3_t absmaxs, int entnum, int modelnum)
00233 {
00234 return NULL;
00235 }
00236
00237
00238
00239
00240
00241
00242 int AAS_BoxEntities(vec3_t absmins, vec3_t absmaxs, int *list, int maxcount)
00243 {
00244 return 0;
00245 }
00246
00247
00248
00249
00250
00251
00252 int AAS_NextBSPEntity(int ent)
00253 {
00254 ent++;
00255 if (ent >= 1 && ent < bspworld.numentities) return ent;
00256 return 0;
00257 }
00258
00259
00260
00261
00262
00263
00264 int AAS_BSPEntityInRange(int ent)
00265 {
00266 if (ent <= 0 || ent >= bspworld.numentities)
00267 {
00268 botimport.Print(PRT_MESSAGE, "bsp entity out of range\n");
00269 return qfalse;
00270 }
00271 return qtrue;
00272 }
00273
00274
00275
00276
00277
00278
00279 int AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size)
00280 {
00281 bsp_epair_t *epair;
00282
00283 value[0] = '\0';
00284 if (!AAS_BSPEntityInRange(ent)) return qfalse;
00285 for (epair = bspworld.entities[ent].epairs; epair; epair = epair->next)
00286 {
00287 if (!strcmp(epair->key, key))
00288 {
00289 strncpy(value, epair->value, size-1);
00290 value[size-1] = '\0';
00291 return qtrue;
00292 }
00293 }
00294 return qfalse;
00295 }
00296
00297
00298
00299
00300
00301
00302 int AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v)
00303 {
00304 char buf[MAX_EPAIRKEY];
00305 double v1, v2, v3;
00306
00307 VectorClear(v);
00308 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
00309
00310 v1 = v2 = v3 = 0;
00311 sscanf(buf, "%lf %lf %lf", &v1, &v2, &v3);
00312 v[0] = v1;
00313 v[1] = v2;
00314 v[2] = v3;
00315 return qtrue;
00316 }
00317
00318
00319
00320
00321
00322
00323 int AAS_FloatForBSPEpairKey(int ent, char *key, float *value)
00324 {
00325 char buf[MAX_EPAIRKEY];
00326
00327 *value = 0;
00328 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
00329 *value = atof(buf);
00330 return qtrue;
00331 }
00332
00333
00334
00335
00336
00337
00338 int AAS_IntForBSPEpairKey(int ent, char *key, int *value)
00339 {
00340 char buf[MAX_EPAIRKEY];
00341
00342 *value = 0;
00343 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
00344 *value = atoi(buf);
00345 return qtrue;
00346 }
00347
00348
00349
00350
00351
00352
00353 void AAS_FreeBSPEntities(void)
00354 {
00355 int i;
00356 bsp_entity_t *ent;
00357 bsp_epair_t *epair, *nextepair;
00358
00359 for (i = 1; i < bspworld.numentities; i++)
00360 {
00361 ent = &bspworld.entities[i];
00362 for (epair = ent->epairs; epair; epair = nextepair)
00363 {
00364 nextepair = epair->next;
00365
00366 if (epair->key) FreeMemory(epair->key);
00367 if (epair->value) FreeMemory(epair->value);
00368 FreeMemory(epair);
00369 }
00370 }
00371 bspworld.numentities = 0;
00372 }
00373
00374
00375
00376
00377
00378
00379 void AAS_ParseBSPEntities(void)
00380 {
00381 script_t *script;
00382 token_t token;
00383 bsp_entity_t *ent;
00384 bsp_epair_t *epair;
00385
00386 script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
00387 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);
00388
00389 bspworld.numentities = 1;
00390
00391 while(PS_ReadToken(script, &token))
00392 {
00393 if (strcmp(token.string, "{"))
00394 {
00395 ScriptError(script, "invalid %s\n", token.string);
00396 AAS_FreeBSPEntities();
00397 FreeScript(script);
00398 return;
00399 }
00400 if (bspworld.numentities >= MAX_BSPENTITIES)
00401 {
00402 botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n");
00403 break;
00404 }
00405 ent = &bspworld.entities[bspworld.numentities];
00406 bspworld.numentities++;
00407 ent->epairs = NULL;
00408 while(PS_ReadToken(script, &token))
00409 {
00410 if (!strcmp(token.string, "}")) break;
00411 epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t));
00412 epair->next = ent->epairs;
00413 ent->epairs = epair;
00414 if (token.type != TT_STRING)
00415 {
00416 ScriptError(script, "invalid %s\n", token.string);
00417 AAS_FreeBSPEntities();
00418 FreeScript(script);
00419 return;
00420 }
00421 StripDoubleQuotes(token.string);
00422 epair->key = (char *) GetHunkMemory(strlen(token.string) + 1);
00423 strcpy(epair->key, token.string);
00424 if (!PS_ExpectTokenType(script, TT_STRING, 0, &token))
00425 {
00426 AAS_FreeBSPEntities();
00427 FreeScript(script);
00428 return;
00429 }
00430 StripDoubleQuotes(token.string);
00431 epair->value = (char *) GetHunkMemory(strlen(token.string) + 1);
00432 strcpy(epair->value, token.string);
00433 }
00434 if (strcmp(token.string, "}"))
00435 {
00436 ScriptError(script, "missing }\n");
00437 AAS_FreeBSPEntities();
00438 FreeScript(script);
00439 return;
00440 }
00441 }
00442 FreeScript(script);
00443 }
00444
00445
00446
00447
00448
00449
00450 int AAS_BSPTraceLight(vec3_t start, vec3_t end, vec3_t endpos, int *red, int *green, int *blue)
00451 {
00452 return 0;
00453 }
00454
00455
00456
00457
00458
00459
00460 void AAS_DumpBSPData(void)
00461 {
00462 AAS_FreeBSPEntities();
00463
00464 if (bspworld.dentdata) FreeMemory(bspworld.dentdata);
00465 bspworld.dentdata = NULL;
00466 bspworld.entdatasize = 0;
00467
00468 bspworld.loaded = qfalse;
00469 Com_Memset( &bspworld, 0, sizeof(bspworld) );
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 int AAS_LoadBSPFile(void)
00479 {
00480 AAS_DumpBSPData();
00481 bspworld.entdatasize = strlen(botimport.BSPEntityData()) + 1;
00482 bspworld.dentdata = (char *) GetClearedHunkMemory(bspworld.entdatasize);
00483 Com_Memcpy(bspworld.dentdata, botimport.BSPEntityData(), bspworld.entdatasize);
00484 AAS_ParseBSPEntities();
00485 bspworld.loaded = qtrue;
00486 return BLERR_NOERROR;
00487 }