00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "common.h"
00027 #include "tracing.h"
00028 #include "routing.h"
00029 #include "../shared/parse.h"
00030
00032 static cBspSurface_t nullSurface;
00033
00034
00035
00036
00037
00038
00039
00048 static void CMod_LoadSubmodels (mapTile_t *tile, const byte *base, const lump_t * l, const vec3_t shift)
00049 {
00050 const dBspModel_t *in;
00051 cBspModel_t *out;
00052 int i, j, count;
00053
00054 if (!l)
00055 Com_Error(ERR_DROP, "CMod_LoadSubmodels: No lump given");
00056
00057 in = (const dBspModel_t *) (base + l->fileofs);
00058 if (l->filelen % sizeof(*in))
00059 Com_Error(ERR_DROP, "CMod_LoadSubmodels: funny lump size (%i => "UFO_SIZE_T")", l->filelen, sizeof(*in));
00060 count = l->filelen / sizeof(*in);
00061 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...submodels: %i\n", count);
00062
00063 if (count < 1)
00064 Com_Error(ERR_DROP, "Map with no models");
00065 if (count > MAX_MAP_MODELS)
00066 Com_Error(ERR_DROP, "Map has too many models: %i", count);
00067
00068 out = (cBspModel_t *)Mem_PoolAlloc((count + 6) * sizeof(*out), com_cmodelSysPool, 0);
00069 tile->models = out;
00070 tile->nummodels = count;
00071
00072 for (i = 0; i < count; i++, in++, out++) {
00073 out = &tile->models[i];
00074
00075
00076 VectorCopy(shift, out->shift);
00077
00078 for (j = 0; j < 3; j++) {
00079 out->mins[j] = LittleFloat(in->mins[j]) - 1 + shift[j];
00080 out->maxs[j] = LittleFloat(in->maxs[j]) + 1 + shift[j];
00081 }
00082 out->headnode = LittleLong(in->headnode);
00083 out->tile = tile->idx;
00084 }
00085 }
00086
00087
00092 static void CMod_LoadSurfaces (mapTile_t *tile, const byte *base, const lump_t * l)
00093 {
00094 const dBspTexinfo_t *in;
00095 cBspSurface_t *out;
00096 int i, count;
00097
00098 if (!l)
00099 Com_Error(ERR_DROP, "CMod_LoadSurfaces: No lump given");
00100
00101 in = (const dBspTexinfo_t *) (base + l->fileofs);
00102 if (l->filelen % sizeof(*in))
00103 Com_Error(ERR_DROP, "CMod_LoadSurfaces: funny lump size: %i", l->filelen);
00104 count = l->filelen / sizeof(*in);
00105 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...surfaces: %i\n", count);
00106
00107 if (count < 1)
00108 Com_Error(ERR_DROP, "Map with no surfaces");
00109 if (count > MAX_MAP_TEXINFO)
00110 Com_Error(ERR_DROP, "Map has too many surfaces");
00111
00112 out = (cBspSurface_t *)Mem_PoolAlloc(count * sizeof(*out), com_cmodelSysPool, 0);
00113
00114 tile->surfaces = out;
00115 tile->numtexinfo = count;
00116
00117 for (i = 0; i < count; i++, in++, out++) {
00118 Q_strncpyz(out->name, in->texture, sizeof(out->name));
00119 out->surfaceFlags = LittleLong(in->surfaceFlags);
00120 out->value = LittleLong(in->value);
00121 }
00122 }
00123
00124
00131 static void CMod_LoadNodes (mapTile_t *tile, const byte *base, const lump_t * l, const vec3_t shift)
00132 {
00133 const dBspNode_t *in;
00134 int child;
00135 cBspNode_t *out;
00136 int i, j, count;
00137
00138 if (!l)
00139 Com_Error(ERR_DROP, "CMod_LoadNodes: No lump given");
00140
00141 in = (const dBspNode_t *) (base + l->fileofs);
00142 if (l->filelen % sizeof(*in))
00143 Com_Error(ERR_DROP, "CMod_LoadNodes: funny lump size: %i", l->filelen);
00144 count = l->filelen / sizeof(*in);
00145 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...nodes: %i\n", count);
00146
00147 if (count < 1)
00148 Com_Error(ERR_DROP, "Map has no nodes");
00149 if (count > MAX_MAP_NODES)
00150 Com_Error(ERR_DROP, "Map has too many nodes");
00151
00152
00153 out = (cBspNode_t *)Mem_PoolAlloc((count + 6) * sizeof(*out), com_cmodelSysPool, 0);
00154
00155 tile->numnodes = count;
00156 tile->nodes = out;
00157
00158 for (i = 0; i < count; i++, out++, in++) {
00159 if (LittleLong(in->planenum) == PLANENUM_LEAF)
00160 out->plane = NULL;
00161 else
00162 out->plane = tile->planes + LittleLong(in->planenum);
00163
00164
00165 for (j = 0; j < 3; j++) {
00166 out->mins[j] = LittleShort(in->mins[j]) + shift[j];
00167 out->maxs[j] = LittleShort(in->maxs[j]) + shift[j];
00168 }
00169
00170 for (j = 0; j < 2; j++) {
00171 child = LittleLong(in->children[j]);
00172 out->children[j] = child;
00173 }
00174 }
00175 }
00176
00181 static void CMod_LoadBrushes (mapTile_t *tile, const byte *base, const lump_t * l)
00182 {
00183 const dBspBrush_t *in;
00184 cBspBrush_t *out;
00185 int i, count;
00186
00187 if (!l)
00188 Com_Error(ERR_DROP, "CMod_LoadBrushes: No lump given");
00189
00190 in = (const dBspBrush_t *) (base + l->fileofs);
00191 if (l->filelen % sizeof(*in))
00192 Com_Error(ERR_DROP, "CMod_LoadBrushes: funny lump size: %i", l->filelen);
00193 count = l->filelen / sizeof(*in);
00194 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...brushes: %i\n", count);
00195
00196 if (count > MAX_MAP_BRUSHES)
00197 Com_Error(ERR_DROP, "Map has too many brushes");
00198
00199
00200 out = (cBspBrush_t *)Mem_PoolAlloc((count + 1) * sizeof(*out), com_cmodelSysPool, 0);
00201
00202 tile->numbrushes = count;
00203 tile->brushes = out;
00204
00205 for (i = 0; i < count; i++, out++, in++) {
00206 out->firstbrushside = LittleLong(in->firstbrushside);
00207 out->numsides = LittleLong(in->numsides);
00208 out->contentFlags = LittleLong(in->contentFlags);
00209 }
00210 }
00211
00216 static void CMod_LoadLeafs (mapTile_t *tile, const byte *base, const lump_t * l)
00217 {
00218 int i;
00219 cBspLeaf_t *out;
00220 const dBspLeaf_t *in;
00221 int count;
00222
00223 if (!l)
00224 Com_Error(ERR_DROP, "CMod_LoadLeafs: No lump given");
00225
00226 in = (const dBspLeaf_t *) (base + l->fileofs);
00227 if (l->filelen % sizeof(*in))
00228 Com_Error(ERR_DROP, "CMod_LoadLeafs: funny lump size: %i", l->filelen);
00229 count = l->filelen / sizeof(*in);
00230 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...leafs: %i\n", count);
00231
00232 if (count < 1)
00233 Com_Error(ERR_DROP, "Map with no leafs");
00234
00235 if (count > MAX_MAP_LEAFS)
00236 Com_Error(ERR_DROP, "Map has too many leafs");
00237
00238
00239 out = (cBspLeaf_t *)Mem_PoolAlloc((count + 1) * sizeof(*out), com_cmodelSysPool, 0);
00240
00241 tile->numleafs = count;
00242 tile->leafs = out;
00243
00244 for (i = 0; i < count; i++, in++, out++) {
00245 out->contentFlags = LittleLong(in->contentFlags);
00246 out->firstleafbrush = LittleShort(in->firstleafbrush);
00247 out->numleafbrushes = LittleShort(in->numleafbrushes);
00248 }
00249
00250 if (tile->leafs[0].contentFlags != CONTENTS_SOLID)
00251 Com_Error(ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID");
00252 tile->emptyleaf = -1;
00253 for (i = 1; i < tile->numleafs; i++) {
00254 if (!tile->leafs[i].contentFlags) {
00255 tile->emptyleaf = i;
00256 break;
00257 }
00258 }
00259 if (tile->emptyleaf == -1)
00260 Com_Error(ERR_DROP, "Map does not have an empty leaf");
00261 }
00262
00269 static void CMod_LoadPlanes (mapTile_t *tile, const byte *base, const lump_t * l, const vec3_t shift)
00270 {
00271 int i, j;
00272 cBspPlane_t *out;
00273 const dBspPlane_t *in;
00274 int count;
00275
00276 if (!l)
00277 Com_Error(ERR_DROP, "CMod_LoadPlanes: No lump given");
00278
00279 in = (const dBspPlane_t *) (base + l->fileofs);
00280 if (l->filelen % sizeof(*in))
00281 Com_Error(ERR_DROP, "CMod_LoadPlanes: funny lump size: %i", l->filelen);
00282 count = l->filelen / sizeof(*in);
00283 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...planes: %i\n", count);
00284
00285 if (count < 1)
00286 Com_Error(ERR_DROP, "Map with no planes");
00287
00288 if (count > MAX_MAP_PLANES)
00289 Com_Error(ERR_DROP, "Map has too many planes");
00290
00291
00292 out = (cBspPlane_t *)Mem_PoolAlloc((count + 12) * sizeof(*out), com_cmodelSysPool, 0);
00293
00294 tile->numplanes = count;
00295 tile->planes = out;
00296
00297 for (i = 0; i < count; i++, in++, out++) {
00298 out->dist = LittleFloat(in->dist);
00299 out->type = LittleLong(in->type);
00300
00301
00302 for (j = 0; j < 3; j++) {
00303 out->normal[j] = LittleFloat(in->normal[j]);
00304 out->dist += out->normal[j] * shift[j];
00305 }
00306 }
00307 }
00308
00313 static void CMod_LoadLeafBrushes (mapTile_t *tile, const byte *base, const lump_t * l)
00314 {
00315 int i;
00316 unsigned short *out;
00317 const unsigned short *in;
00318 int count;
00319
00320 if (!l)
00321 Com_Error(ERR_DROP, "CMod_LoadLeafBrushes: No lump given");
00322
00323 in = (const unsigned short *) (base + l->fileofs);
00324 if (l->filelen % sizeof(unsigned short))
00325 Com_Error(ERR_DROP, "CMod_LoadLeafBrushes: funny lump size: %i", l->filelen);
00326 count = l->filelen / sizeof(unsigned short);
00327 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...leafbrushes: %i\n", count);
00328
00329
00330 out = (unsigned short *)Mem_PoolAlloc((count + 1) * sizeof(*out), com_cmodelSysPool, 0);
00331
00332 if (count < 1)
00333 Com_Error(ERR_DROP, "Map with no planes");
00334
00335 if (count >= MAX_MAP_LEAFBRUSHES)
00336 Com_Error(ERR_DROP, "Map has too many leafbrushes");
00337
00338 tile->numleafbrushes = count;
00339 tile->leafbrushes = out;
00340
00341 for (i = 0; i < count; i++, in++, out++)
00342 *out = LittleShort(*in);
00343 }
00344
00349 static void CMod_LoadBrushSides (mapTile_t *tile, const byte *base, const lump_t * l)
00350 {
00351 int i;
00352 cBspBrushSide_t *out;
00353 const dBspBrushSide_t *in;
00354 int count;
00355
00356 if (!l)
00357 Com_Error(ERR_DROP, "CMod_LoadBrushSides: No lump given");
00358
00359 in = (const dBspBrushSide_t *) (base + l->fileofs);
00360 if (l->filelen % sizeof(dBspBrushSide_t))
00361 Com_Error(ERR_DROP, "CMod_LoadBrushSides: funny lump size: %i", l->filelen);
00362 count = l->filelen / sizeof(dBspBrushSide_t);
00363 Com_DPrintf(DEBUG_ENGINE, COLORED_GREEN "...brushsides: %i\n", count);
00364
00365
00366 if (count > MAX_MAP_BRUSHSIDES)
00367 Com_Error(ERR_DROP, "Map has too many brushsides");
00368
00369
00370 out = (cBspBrushSide_t *)Mem_PoolAlloc((count + 6) * sizeof(*out), com_cmodelSysPool, 0);
00371
00372 tile->numbrushsides = count;
00373 tile->brushsides = out;
00374
00375 for (i = 0; i < count; i++, in++, out++) {
00376 const int num = LittleShort(in->planenum);
00377 const int j = LittleShort(in->texinfo);
00378 if (j >= tile->numtexinfo)
00379 Com_Error(ERR_DROP, "Bad brushside texinfo");
00380 out->plane = &tile->planes[num];
00381 out->surface = &tile->surfaces[j];
00382 }
00383 }
00384
00391 static int CMod_DeCompressRouting (const byte ** source, byte * dataStart)
00392 {
00393 int i, c;
00394 byte *data_p;
00395 const byte *src;
00396
00397 data_p = dataStart;
00398 src = *source;
00399
00400 while (*src) {
00401 if (*src & 0x80) {
00402
00403 c = *src++ & ~0x80;
00404
00405 for (i = 0; i < c + 2; i++)
00406 *data_p++ = *src;
00407 src++;
00408 } else {
00409
00410 c = *src++;
00411 for (i = 0; i < c; i++)
00412 *data_p++ = *src++;
00413 }
00414 }
00415
00416 src++;
00417 *source = src;
00418
00419 return data_p - dataStart;
00420 }
00421
00422
00423
00424
00425
00426
00427
00434 static void CM_MakeTracingNodes (mapTile_t *tile)
00435 {
00436 int i;
00437 tnode_t *tnode;
00438
00439 tnode = tile->tnodes = (tnode_t *)Mem_PoolAlloc((tile->numnodes + 6) * sizeof(*tnode), com_cmodelSysPool, 0);
00440
00441 tile->numtheads = 0;
00442 tile->numcheads = 0;
00443
00444 for (i = 0; i < tile->nummodels; i++) {
00445 if (tile->models[i].headnode == LEAFNODE || tile->models[i].headnode >= tile->numnodes + 6)
00446 continue;
00447
00448 tile->thead[tile->numtheads] = tnode - tile->tnodes;
00449 tile->theadlevel[tile->numtheads] = i;
00450 tile->numtheads++;
00451 assert(tile->numtheads < LEVEL_MAX);
00452
00453
00454
00455 if (i < NUM_REGULAR_MODELS)
00456 TR_BuildTracingNode_r(tile, &tnode, tile->models[i].headnode, i);
00457 }
00458 }
00459
00469 static void CMod_LoadRouting (mapTile_t *tile, mapData_t *mapData, const byte *base, const char *name, const lump_t * l, int sX, int sY, int sZ)
00470 {
00472 static routing_t tempMap[ACTOR_MAX_SIZE];
00473 const byte *source;
00474 int length;
00475 int x, y, z, size, dir;
00476 int minX, minY, minZ;
00477 int maxX, maxY, maxZ;
00478 unsigned int i;
00479 double start, end;
00480 const int targetLength = sizeof(tile->wpMins) + sizeof(tile->wpMaxs) + sizeof(tempMap);
00481
00482 start = time(NULL);
00483
00484 if (!l)
00485 Com_Error(ERR_DROP, "CMod_LoadRouting: No lump given");
00486
00487 if (!l->filelen)
00488 Com_Error(ERR_DROP, "CMod_LoadRouting: Map has NO routing lump");
00489
00490 assert((sX > -(PATHFINDING_WIDTH / 2)) && (sX < (PATHFINDING_WIDTH / 2)));
00491 assert((sY > -(PATHFINDING_WIDTH / 2)) && (sY < (PATHFINDING_WIDTH / 2)));
00492 assert((sZ >= 0) && (sZ < PATHFINDING_HEIGHT));
00493
00494 source = base + l->fileofs;
00495
00496 i = CMod_DeCompressRouting(&source, (byte*)tile->wpMins);
00497 length = i;
00498 i = CMod_DeCompressRouting(&source, (byte*)tile->wpMaxs);
00499 length += i;
00500 i = CMod_DeCompressRouting(&source, (byte*)tempMap);
00501 length += i;
00502
00503 if (length != targetLength)
00504 Com_Error(ERR_DROP, "CMod_LoadRouting: Map has BAD routing lump; expected %i got %i", targetLength, length);
00505
00506
00507 for (i = 0; i < 3; i++) {
00508 tile->wpMins[i] = LittleLong(tile->wpMins[i]);
00509 tile->wpMaxs[i] = LittleLong(tile->wpMaxs[i]);
00510 }
00511
00512 Com_DPrintf(DEBUG_ROUTING, "Map:%s Offset:(%i, %i, %i)\n", name, sX, sY, sZ);
00513 Com_DPrintf(DEBUG_ROUTING, "wpMins:(%i, %i, %i) wpMaxs:(%i, %i, %i)\n", tile->wpMins[0], tile->wpMins[1],
00514 tile->wpMins[2], tile->wpMaxs[0], tile->wpMaxs[1], tile->wpMaxs[2]);
00515
00516
00517
00518 tile->wpMins[0] += sX;
00519 tile->wpMins[1] += sY;
00520 tile->wpMins[2] += sZ;
00521 tile->wpMaxs[0] += sX;
00522 tile->wpMaxs[1] += sY;
00523 tile->wpMaxs[2] += sZ;
00524
00525 Com_DPrintf(DEBUG_ROUTING, "Shifted wpMins:(%i, %i, %i) wpMaxs:(%i, %i, %i)\n", tile->wpMins[0],
00526 tile->wpMins[1], tile->wpMins[2], tile->wpMaxs[0], tile->wpMaxs[1], tile->wpMaxs[2]);
00527
00528
00529
00530
00531
00532
00533
00534 minX = max(tile->wpMins[0], 0);
00535 minY = max(tile->wpMins[1], 0);
00536 minZ = max(tile->wpMins[2], 0);
00537 maxX = min(tile->wpMaxs[0], PATHFINDING_WIDTH - 1);
00538 maxY = min(tile->wpMaxs[1], PATHFINDING_WIDTH - 1);
00539 maxZ = min(tile->wpMaxs[2], PATHFINDING_HEIGHT - 1);
00540
00541 assert(minX <= maxX);
00542 assert(minY <= maxY);
00543 assert(minZ <= maxZ);
00544
00545 Com_DPrintf(DEBUG_ROUTING, "Tile bounds: (%i, %i, %i) to (%i, %i, %i)\n", minX, minY, minZ, maxX, maxY, maxZ);
00546 Com_DPrintf(DEBUG_ROUTING, "Source bounds: (%i, %i, %i) to (%i, %i, %i)\n", minX - sX, minY - sY, minZ - sZ,
00547 maxX - sX, maxY - sY, maxZ - sZ);
00548
00549 for (size = 0; size < ACTOR_MAX_SIZE; size++)
00550
00551 for (y = minY - size; y <= maxY; y++)
00552 for (x = minX - size; x <= maxX; x++) {
00553
00554 if (x < 0 || y < 0)
00555 continue;
00556 for (z = minZ; z <= maxZ; z++) {
00557 mapData->map[size].floor[z][y][x] = tempMap[size].floor[z - sZ][y - sY][x - sX];
00558 mapData->map[size].ceil[z][y][x] = tempMap[size].ceil[z - sZ][y - sY][x - sX];
00559 for (dir = 0; dir < CORE_DIRECTIONS; dir++) {
00560 mapData->map[size].route[z][y][x][dir] = tempMap[size].route[z - sZ][y - sY][x - sX][dir];
00561 mapData->map[size].stepup[z][y][x][dir] = tempMap[size].stepup[z - sZ][y - sY][x - sX][dir];
00562 }
00563 }
00564
00565 if (!mapData->reroute[size][y][x]) {
00566 mapData->reroute[size][y][x] = tile->idx + 1;
00567 } else {
00568 mapData->reroute[size][y][x] = ROUTING_NOT_REACHABLE;
00569 }
00570 }
00571
00572 Com_DPrintf(DEBUG_ROUTING, "Done copying data.\n");
00573
00574 end = time(NULL);
00575 Com_DPrintf(DEBUG_ROUTING, "Loaded routing for tile %s in %5.1fs\n", name, end - start);
00576 }
00577
00578
00586 static void CMod_LoadEntityString (mapTile_t *tile, mapData_t *mapData, const byte *base, const lump_t * l, const vec3_t shift)
00587 {
00588 const char *token;
00589 const char *es;
00590 char keyname[256];
00591 vec3_t v;
00592 cBspModel_t *model = NULL;
00593
00594 if (!l)
00595 Com_Error(ERR_DROP, "CMod_LoadEntityString: No lump given");
00596
00597 if (!l->filelen)
00598 Com_Error(ERR_DROP, "CMod_LoadEntityString: Map has NO entity lump");
00599
00600 if (l->filelen + 1 > MAX_MAP_ENTSTRING)
00601 Com_Error(ERR_DROP, "CMod_LoadEntityString: Map has too large entity lump");
00602
00603
00604 es = (const char *) (base + l->fileofs);
00605 while (1) {
00606
00607 token = Com_Parse(&es);
00608 if (!es)
00609 break;
00610 if (token[0] != '{')
00611 Com_Error(ERR_DROP, "CMod_LoadEntityString: found %s when expecting {", token);
00612
00613
00614 Q_strcat(mapData->mapEntityString, "{ ", MAX_MAP_ENTSTRING);
00615
00616
00617 while (1) {
00618
00619 token = Com_Parse(&es);
00620 if (token[0] == '}')
00621 break;
00622 if (!es)
00623 Com_Error(ERR_DROP, "CMod_LoadEntityString: EOF without closing brace");
00624
00625 Q_strncpyz(keyname, token, sizeof(keyname));
00626
00627
00628 token = Com_Parse(&es);
00629 if (!es)
00630 Com_Error(ERR_DROP, "CMod_LoadEntityString: EOF without closing brace");
00631
00632 if (token[0] == '}')
00633 Com_Error(ERR_DROP, "CMod_LoadEntityString: closing brace without data");
00634
00635
00636 if (!strcmp(keyname, "origin")) {
00637
00638 sscanf(token, "%f %f %f", &(v[0]), &(v[1]), &(v[2]));
00639 VectorAdd(v, shift, v);
00640 Q_strcat(mapData->mapEntityString, va("%s \"%f %f %f\" ", keyname, v[0], v[1], v[2]), MAX_MAP_ENTSTRING);
00641
00642 if (model) {
00643 VectorSubtract(model->mins, shift, model->mins);
00644 VectorSubtract(model->maxs, shift, model->maxs);
00645 model = NULL;
00646 }
00647 } else if (!strcmp(keyname, "model") && token[0] == '*') {
00648
00649 int num = atoi(token + 1);
00650
00651 model = &tile->models[NUM_REGULAR_MODELS + num - 1];
00652
00653 num += mapData->numInline;
00654 Q_strcat(mapData->mapEntityString, va("%s *%i ", keyname, num), MAX_MAP_ENTSTRING);
00655 } else if (!strcmp(keyname, "targetname") || !strcmp(keyname, "target")) {
00656 Q_strcat(mapData->mapEntityString, va("%s \"%s-%i\" ", keyname, token, tile->idx), MAX_MAP_ENTSTRING);
00657 } else {
00658
00659 Q_strcat(mapData->mapEntityString, va("%s \"%s\" ", keyname, token), MAX_MAP_ENTSTRING);
00660 }
00661 }
00662
00663
00664 Q_strcat(mapData->mapEntityString, "} ", MAX_MAP_ENTSTRING);
00665 }
00666 }
00667
00672 static void CMod_LoadLighting (mapTile_t *tile, const byte *base, const lump_t * l)
00673 {
00674 #if 0
00675 tile->lightdata = Mem_PoolAlloc(l->filelen, com_cmodelSysPool, 0);
00676 memcpy(tile->lightdata, base + l->fileofs, l->filelen);
00677 #endif
00678 }
00679
00684 static void CM_InitBoxHull (mapTile_t *tile)
00685 {
00686 int i;
00687
00688 tile->box_headnode = tile->numnodes;
00689 tile->box_planes = &tile->planes[tile->numplanes];
00690
00691 if (tile->idx == 1 && (tile->numnodes + 6 > MAX_MAP_NODES
00692 || tile->numbrushes + 1 > MAX_MAP_BRUSHES
00693 || tile->numleafbrushes + 1 > MAX_MAP_LEAFBRUSHES
00694 || tile->numbrushsides + 6 > MAX_MAP_BRUSHSIDES
00695 || tile->numplanes + 12 > MAX_MAP_PLANES))
00696 Com_Error(ERR_DROP, "Not enough room for box tree");
00697
00698 tile->box_brush = &tile->brushes[tile->numbrushes];
00699 tile->box_brush->numsides = 6;
00700 tile->box_brush->firstbrushside = tile->numbrushsides;
00701 tile->box_brush->contentFlags = CONTENTS_WEAPONCLIP;
00702
00703 tile->box_leaf = &tile->leafs[tile->numleafs];
00704 tile->box_leaf->contentFlags = CONTENTS_WEAPONCLIP;
00705 tile->box_leaf->firstleafbrush = tile->numleafbrushes;
00706 tile->box_leaf->numleafbrushes = 1;
00707
00708 tile->leafbrushes[tile->numleafbrushes] = tile->numbrushes;
00709
00710
00711 for (i = 0; i < 6; i++) {
00712 const int side = i & 1;
00713 cBspNode_t *c;
00714 cBspPlane_t *p;
00715 cBspBrushSide_t *s;
00716
00717
00718 s = &tile->brushsides[tile->numbrushsides + i];
00719 s->plane = tile->planes + (tile->numplanes + i * 2 + side);
00720 s->surface = &nullSurface;
00721
00722
00723 c = &tile->nodes[tile->box_headnode + i];
00724 c->plane = tile->planes + (tile->numplanes + i * 2);
00725 c->children[side] = -1 - tile->emptyleaf;
00726 if (i != 5)
00727 c->children[side ^ 1] = tile->box_headnode + i + 1;
00728 else
00729 c->children[side ^ 1] = LEAFNODE - tile->numleafs;
00730
00731
00732 p = &tile->box_planes[i * 2];
00733 p->type = i >> 1;
00734 VectorClear(p->normal);
00735 p->normal[i >> 1] = 1;
00736
00737 p = &tile->box_planes[i * 2 + 1];
00738 p->type = PLANE_ANYX + (i >> 1);
00739 VectorClear(p->normal);
00740 p->normal[i >> 1] = -1;
00741 }
00742 }
00743
00758 static void CM_AddMapTile (const char *name, qboolean day, int sX, int sY, byte sZ, mapData_t *mapData, mapTiles_t *mapTiles)
00759 {
00760 char filename[MAX_QPATH];
00761 unsigned checksum;
00762 byte *buf;
00763 unsigned int i;
00764 int length;
00765 dBspHeader_t header;
00766
00767 vec3_t shift;
00768 const byte *base;
00769 mapTile_t *tile;
00770
00771 Com_DPrintf(DEBUG_ENGINE, "CM_AddMapTile: %s at %i,%i,%i\n", name, sX, sY, sZ);
00772 assert(name);
00773 assert(name[0]);
00774 assert((sX > -(PATHFINDING_WIDTH / 2)) && (sX < (PATHFINDING_WIDTH / 2)));
00775 assert((sY > -(PATHFINDING_WIDTH / 2)) && (sY < (PATHFINDING_WIDTH / 2)));
00776 assert(sZ < PATHFINDING_HEIGHT);
00777
00778
00779 Com_sprintf(filename, sizeof(filename), "maps/%s.bsp", name);
00780 length = FS_LoadFile(filename, &buf);
00781 if (!buf)
00782 Com_Error(ERR_DROP, "Couldn't load %s", filename);
00783
00784 checksum = LittleLong(Com_BlockChecksum(buf, length));
00785
00786 header = *(dBspHeader_t *) buf;
00787 for (i = 0; i < sizeof(header) / 4; i++)
00788 ((int *) &header)[i] = LittleLong(((int *) &header)[i]);
00789
00790 if (header.version != BSPVERSION)
00791 Com_Error(ERR_DROP, "CM_AddMapTile: %s has wrong version number (%i should be %i)", name, header.version, BSPVERSION);
00792
00793 base = (const byte *) buf;
00794
00795
00796 if (mapTiles->numTiles >= MAX_MAPTILES)
00797 Com_Error(ERR_FATAL, "CM_AddMapTile: too many tiles loaded %i", mapTiles->numTiles);
00798
00799 tile = &(mapTiles->mapTiles[mapTiles->numTiles]);
00800 memset(tile, 0, sizeof(*tile));
00801 tile->idx = mapTiles->numTiles;
00802 Q_strncpyz(tile->name, name, sizeof(tile->name));
00803
00804
00805
00806 VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_HEIGHT);
00807
00808
00809 CMod_LoadSurfaces(tile, base, &header.lumps[LUMP_TEXINFO]);
00810 CMod_LoadLeafs(tile, base, &header.lumps[LUMP_LEAFS]);
00811 CMod_LoadLeafBrushes(tile, base, &header.lumps[LUMP_LEAFBRUSHES]);
00812 CMod_LoadPlanes(tile, base, &header.lumps[LUMP_PLANES], shift);
00813 CMod_LoadBrushes(tile, base, &header.lumps[LUMP_BRUSHES]);
00814 CMod_LoadBrushSides(tile, base, &header.lumps[LUMP_BRUSHSIDES]);
00815 CMod_LoadSubmodels(tile, base, &header.lumps[LUMP_MODELS], shift);
00816 CMod_LoadNodes(tile, base, &header.lumps[LUMP_NODES], shift);
00817 CMod_LoadEntityString(tile, mapData, base, &header.lumps[LUMP_ENTITIES], shift);
00818 if (day)
00819 CMod_LoadLighting(tile, base, &header.lumps[LUMP_LIGHTING_DAY]);
00820 else
00821 CMod_LoadLighting(tile, base, &header.lumps[LUMP_LIGHTING_NIGHT]);
00822
00823 CM_InitBoxHull(tile);
00824 CM_MakeTracingNodes(tile);
00825
00826 mapData->numInline += tile->nummodels - NUM_REGULAR_MODELS;
00827
00828 CMod_LoadRouting(tile, mapData, base, name, &header.lumps[LUMP_ROUTING], sX, sY, sZ);
00829
00830
00831 mapTiles->numTiles++;
00832
00833
00834
00835 RT_GetMapSize(mapTiles, mapData->mapMin, mapData->mapMax);
00836
00837 FS_FreeFile(buf);
00838
00839 mapData->mapChecksum += checksum;
00840 }
00841
00842 static void CMod_RerouteMap (mapTiles_t *mapTiles, mapData_t *mapData)
00843 {
00844 actorSizeEnum_t size;
00845 int x, y, z, dir;
00846 int i;
00847 pos3_t mins, maxs;
00848 double start, end;
00849
00850 start = time(NULL);
00851
00852 VecToPos(mapData->mapMin, mins);
00853 VecToPos(mapData->mapMax, maxs);
00854
00855
00856 maxs[0] = min(maxs[0], PATHFINDING_WIDTH - 1);
00857 maxs[1] = min(maxs[1], PATHFINDING_WIDTH - 1);
00858 maxs[2] = min(maxs[2], PATHFINDING_HEIGHT - 1);
00859 for (i = 0; i < 3; i++)
00860 mins[i] = max(mins[i], 0);
00861
00862 Com_DPrintf(DEBUG_PATHING, "rerouting (%i %i %i) (%i %i %i)\n",
00863 (int)mins[0], (int)mins[1], (int)mins[2],
00864 (int)maxs[0], (int)maxs[1], (int)maxs[2]);
00865
00866
00867 for (size = ACTOR_SIZE_INVALID; size < ACTOR_MAX_SIZE; size++) {
00868 for (y = mins[1]; y <= maxs[1]; y++) {
00869 for (x = mins[0]; x <= maxs[0]; x++) {
00870 if (mapData->reroute[size][y][x] == ROUTING_NOT_REACHABLE) {
00871
00872 for (z = maxs[2]; z >= mins[2]; z--) {
00873 const int newZ = RT_CheckCell(mapTiles, mapData->map, size + 1, x, y, z, NULL);
00874 assert(newZ <= z);
00875 z = newZ;
00876 }
00877 }
00878 }
00879 }
00880 }
00881
00882
00883 for (size = ACTOR_SIZE_INVALID; size < ACTOR_MAX_SIZE; size++) {
00884 for (y = mins[1]; y <= maxs[1]; y++) {
00885 for (x = mins[0]; x <= maxs[0]; x++) {
00886 const byte tile = mapData->reroute[size][y][x];
00887 if (tile) {
00890
00891
00892 for (dir = 0; dir < CORE_DIRECTIONS; dir++) {
00893 const int dx = x + dvecs[dir][0];
00894 const int dy = y + dvecs[dir][1];
00895 int tile2;
00896
00897 if (dx < 0 || dx >= PATHFINDING_WIDTH || dy < 0 || dy >= PATHFINDING_WIDTH)
00898 continue;
00899 tile2 = mapData->reroute[size][dy][dx];
00900
00901 if (tile2 && (tile2 == ROUTING_NOT_REACHABLE || tile2 != tile)) {
00904
00905 RT_UpdateConnectionColumn(mapTiles, mapData->map, size + 1, x, y, dir, NULL);
00906 }
00907 }
00908 }
00909 }
00910 }
00911 }
00912 end = time(NULL);
00913 Com_Printf("Rerouted for RMA in %5.1fs\n", end - start);
00914 }
00915
00928 void CM_LoadMap (const char *tiles, qboolean day, const char *pos, mapData_t *mapData, mapTiles_t *mapTiles)
00929 {
00930 const char *token;
00931 char name[MAX_VAR];
00932 char base[MAX_QPATH];
00933 int i;
00934
00935 Mem_FreePool(com_cmodelSysPool);
00936
00937
00938 base[0] = 0;
00939
00940
00941 memset(mapData, 0, sizeof(*mapData));
00942 memset(mapTiles, 0, sizeof(*mapTiles));
00943
00944 if (pos && *pos)
00945 Com_Printf("CM_LoadMap: \"%s\" \"%s\"\n", tiles, pos);
00946
00947
00948 while (tiles) {
00949
00950 token = Com_Parse(&tiles);
00951 if (!tiles) {
00952 CMod_RerouteMap(mapTiles, mapData);
00953 return;
00954 }
00955
00956
00957 if (token[0] == '-') {
00958 Q_strncpyz(base, token + 1, sizeof(base));
00959 continue;
00960 }
00961
00962
00963 Com_DPrintf(DEBUG_ENGINE, "CM_LoadMap: token: %s\n", token);
00964 if (token[0] == '+')
00965 Com_sprintf(name, sizeof(name), "%s%s", base, token + 1);
00966 else
00967 Q_strncpyz(name, token, sizeof(name));
00968
00969 if (pos && pos[0]) {
00970 ipos3_t sh;
00971
00972 for (i = 0; i < 3; i++) {
00973 token = Com_Parse(&pos);
00974 if (!pos)
00975 Com_Error(ERR_DROP, "CM_LoadMap: invalid positions");
00976 sh[i] = atoi(token);
00977 }
00978 if (sh[0] <= -(PATHFINDING_WIDTH / 2) || sh[0] >= PATHFINDING_WIDTH / 2)
00979 Com_Error(ERR_DROP, "CM_LoadMap: invalid x position given: %i\n", sh[0]);
00980 if (sh[1] <= -(PATHFINDING_WIDTH / 2) || sh[1] >= PATHFINDING_WIDTH / 2)
00981 Com_Error(ERR_DROP, "CM_LoadMap: invalid y position given: %i\n", sh[1]);
00982 if (sh[2] >= PATHFINDING_HEIGHT)
00983 Com_Error(ERR_DROP, "CM_LoadMap: invalid z position given: %i\n", sh[2]);
00984 CM_AddMapTile(name, day, sh[0], sh[1], sh[2], mapData, mapTiles);
00985 } else {
00986
00987 CM_AddMapTile(name, day, 0, 0, 0, mapData, mapTiles);
00988 return;
00989 }
00990 }
00991
00992 Com_Error(ERR_DROP, "CM_LoadMap: invalid tile names");
00993 }
00994
01001 cBspModel_t *CM_InlineModel (mapTiles_t *mapTiles, const char *name)
01002 {
01003 int i, num;
01004
01005
01006 if (!name || name[0] != '*')
01007 Com_Error(ERR_DROP, "CM_InlineModel: bad name: '%s'", name ? name : "");
01008
01009 num = atoi(name + 1) - 1;
01010 if (num < 0 || num >= MAX_MODELS)
01011 Com_Error(ERR_DROP, "CM_InlineModel: bad number %i - max inline models are %i", num, MAX_MODELS);
01012
01013
01014 for (i = 0; i < mapTiles->numTiles; i++) {
01015 const int models = mapTiles->mapTiles[i].nummodels - NUM_REGULAR_MODELS;
01016 assert(models >= 0);
01017
01018 if (num >= models)
01019 num -= models;
01020 else
01021 return &(mapTiles->mapTiles[i].models[NUM_REGULAR_MODELS + num]);
01022 }
01023
01024 Com_Error(ERR_DROP, "CM_InlineModel: Error cannot find model '%s'\n", name);
01025 }
01026
01036 void CM_SetInlineModelOrientation (mapTiles_t *mapTiles, const char *name, const vec3_t origin, const vec3_t angles)
01037 {
01038 cBspModel_t *model = CM_InlineModel(mapTiles, name);
01039 assert(model);
01040 VectorCopy(origin, model->origin);
01041 VectorCopy(angles, model->angles);
01042 }