00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "server.h"
00025 #include "../game/botlib.h"
00026
00027 typedef struct bot_debugpoly_s
00028 {
00029 int inuse;
00030 int color;
00031 int numPoints;
00032 vec3_t points[128];
00033 } bot_debugpoly_t;
00034
00035 static bot_debugpoly_t *debugpolygons;
00036 int bot_maxdebugpolys;
00037
00038 extern botlib_export_t *botlib_export;
00039 int bot_enable;
00040
00041
00042
00043
00044
00045
00046
00047 int SV_BotAllocateClient(void) {
00048 int i;
00049 client_t *cl;
00050
00051
00052 for ( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) {
00053 if ( cl->state == CS_FREE ) {
00054 break;
00055 }
00056 }
00057
00058 if ( i == sv_maxclients->integer ) {
00059 return -1;
00060 }
00061
00062 cl->gentity = SV_GentityNum( i );
00063 cl->gentity->s.number = i;
00064 cl->state = CS_ACTIVE;
00065 cl->lastPacketTime = svs.time;
00066 cl->netchan.remoteAddress.type = NA_BOT;
00067 cl->rate = 16384;
00068
00069 return i;
00070 }
00071
00072
00073
00074
00075
00076
00077 void SV_BotFreeClient( int clientNum ) {
00078 client_t *cl;
00079
00080 if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) {
00081 Com_Error( ERR_DROP, "SV_BotFreeClient: bad clientNum: %i", clientNum );
00082 }
00083 cl = &svs.clients[clientNum];
00084 cl->state = CS_FREE;
00085 cl->name[0] = 0;
00086 if ( cl->gentity ) {
00087 cl->gentity->r.svFlags &= ~SVF_BOT;
00088 }
00089 }
00090
00091
00092
00093
00094
00095
00096 void BotDrawDebugPolygons(void (*drawPoly)(int color, int numPoints, float *points), int value) {
00097 static cvar_t *bot_debug, *bot_groundonly, *bot_reachability, *bot_highlightarea;
00098 bot_debugpoly_t *poly;
00099 int i, parm0;
00100
00101 if (!debugpolygons)
00102 return;
00103
00104 if (!bot_debug) bot_debug = Cvar_Get("bot_debug", "0", 0);
00105
00106 if (bot_enable && bot_debug->integer) {
00107
00108 if (!bot_reachability) bot_reachability = Cvar_Get("bot_reachability", "0", 0);
00109
00110 if (!bot_groundonly) bot_groundonly = Cvar_Get("bot_groundonly", "1", 0);
00111
00112 if (!bot_highlightarea) bot_highlightarea = Cvar_Get("bot_highlightarea", "0", 0);
00113
00114 parm0 = 0;
00115 if (svs.clients[0].lastUsercmd.buttons & BUTTON_ATTACK) parm0 |= 1;
00116 if (bot_reachability->integer) parm0 |= 2;
00117 if (bot_groundonly->integer) parm0 |= 4;
00118 botlib_export->BotLibVarSet("bot_highlightarea", bot_highlightarea->string);
00119 botlib_export->Test(parm0, NULL, svs.clients[0].gentity->r.currentOrigin,
00120 svs.clients[0].gentity->r.currentAngles);
00121 }
00122
00123 for (i = 0; i < bot_maxdebugpolys; i++) {
00124 poly = &debugpolygons[i];
00125 if (!poly->inuse) continue;
00126 drawPoly(poly->color, poly->numPoints, (float *) poly->points);
00127
00128 }
00129 }
00130
00131
00132
00133
00134
00135
00136 void QDECL BotImport_Print(int type, char *fmt, ...)
00137 {
00138 char str[2048];
00139 va_list ap;
00140
00141 va_start(ap, fmt);
00142 vsprintf(str, fmt, ap);
00143 va_end(ap);
00144
00145 switch(type) {
00146 case PRT_MESSAGE: {
00147 Com_Printf("%s", str);
00148 break;
00149 }
00150 case PRT_WARNING: {
00151 Com_Printf(S_COLOR_YELLOW "Warning: %s", str);
00152 break;
00153 }
00154 case PRT_ERROR: {
00155 Com_Printf(S_COLOR_RED "Error: %s", str);
00156 break;
00157 }
00158 case PRT_FATAL: {
00159 Com_Printf(S_COLOR_RED "Fatal: %s", str);
00160 break;
00161 }
00162 case PRT_EXIT: {
00163 Com_Error(ERR_DROP, S_COLOR_RED "Exit: %s", str);
00164 break;
00165 }
00166 default: {
00167 Com_Printf("unknown print type\n");
00168 break;
00169 }
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178 void BotImport_Trace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask) {
00179 trace_t trace;
00180
00181 SV_Trace(&trace, start, mins, maxs, end, passent, contentmask, qfalse);
00182
00183 bsptrace->allsolid = trace.allsolid;
00184 bsptrace->startsolid = trace.startsolid;
00185 bsptrace->fraction = trace.fraction;
00186 VectorCopy(trace.endpos, bsptrace->endpos);
00187 bsptrace->plane.dist = trace.plane.dist;
00188 VectorCopy(trace.plane.normal, bsptrace->plane.normal);
00189 bsptrace->plane.signbits = trace.plane.signbits;
00190 bsptrace->plane.type = trace.plane.type;
00191 bsptrace->surface.value = trace.surfaceFlags;
00192 bsptrace->ent = trace.entityNum;
00193 bsptrace->exp_dist = 0;
00194 bsptrace->sidenum = 0;
00195 bsptrace->contents = 0;
00196 }
00197
00198
00199
00200
00201
00202
00203 void BotImport_EntityTrace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int entnum, int contentmask) {
00204 trace_t trace;
00205
00206 SV_ClipToEntity(&trace, start, mins, maxs, end, entnum, contentmask, qfalse);
00207
00208 bsptrace->allsolid = trace.allsolid;
00209 bsptrace->startsolid = trace.startsolid;
00210 bsptrace->fraction = trace.fraction;
00211 VectorCopy(trace.endpos, bsptrace->endpos);
00212 bsptrace->plane.dist = trace.plane.dist;
00213 VectorCopy(trace.plane.normal, bsptrace->plane.normal);
00214 bsptrace->plane.signbits = trace.plane.signbits;
00215 bsptrace->plane.type = trace.plane.type;
00216 bsptrace->surface.value = trace.surfaceFlags;
00217 bsptrace->ent = trace.entityNum;
00218 bsptrace->exp_dist = 0;
00219 bsptrace->sidenum = 0;
00220 bsptrace->contents = 0;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 int BotImport_PointContents(vec3_t point) {
00230 return SV_PointContents(point, -1);
00231 }
00232
00233
00234
00235
00236
00237
00238 int BotImport_inPVS(vec3_t p1, vec3_t p2) {
00239 return SV_inPVS (p1, p2);
00240 }
00241
00242
00243
00244
00245
00246
00247 char *BotImport_BSPEntityData(void) {
00248 return CM_EntityString();
00249 }
00250
00251
00252
00253
00254
00255
00256 void BotImport_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t outmins, vec3_t outmaxs, vec3_t origin) {
00257 clipHandle_t h;
00258 vec3_t mins, maxs;
00259 float max;
00260 int i;
00261
00262 h = CM_InlineModel(modelnum);
00263 CM_ModelBounds(h, mins, maxs);
00264
00265 if ((angles[0] || angles[1] || angles[2])) {
00266
00267
00268 max = RadiusFromBounds(mins, maxs);
00269 for (i = 0; i < 3; i++) {
00270 mins[i] = -max;
00271 maxs[i] = max;
00272 }
00273 }
00274 if (outmins) VectorCopy(mins, outmins);
00275 if (outmaxs) VectorCopy(maxs, outmaxs);
00276 if (origin) VectorClear(origin);
00277 }
00278
00279
00280
00281
00282
00283
00284 void *BotImport_GetMemory(int size) {
00285 void *ptr;
00286
00287 ptr = Z_TagMalloc( size, TAG_BOTLIB );
00288 return ptr;
00289 }
00290
00291
00292
00293
00294
00295
00296 void BotImport_FreeMemory(void *ptr) {
00297 Z_Free(ptr);
00298 }
00299
00300
00301
00302
00303
00304
00305 void *BotImport_HunkAlloc( int size ) {
00306 if( Hunk_CheckMark() ) {
00307 Com_Error( ERR_DROP, "SV_Bot_HunkAlloc: Alloc with marks already set\n" );
00308 }
00309 return Hunk_Alloc( size, h_high );
00310 }
00311
00312
00313
00314
00315
00316
00317 int BotImport_DebugPolygonCreate(int color, int numPoints, vec3_t *points) {
00318 bot_debugpoly_t *poly;
00319 int i;
00320
00321 if (!debugpolygons)
00322 return 0;
00323
00324 for (i = 1; i < bot_maxdebugpolys; i++) {
00325 if (!debugpolygons[i].inuse)
00326 break;
00327 }
00328 if (i >= bot_maxdebugpolys)
00329 return 0;
00330 poly = &debugpolygons[i];
00331 poly->inuse = qtrue;
00332 poly->color = color;
00333 poly->numPoints = numPoints;
00334 Com_Memcpy(poly->points, points, numPoints * sizeof(vec3_t));
00335
00336 return i;
00337 }
00338
00339
00340
00341
00342
00343
00344 void BotImport_DebugPolygonShow(int id, int color, int numPoints, vec3_t *points) {
00345 bot_debugpoly_t *poly;
00346
00347 if (!debugpolygons) return;
00348 poly = &debugpolygons[id];
00349 poly->inuse = qtrue;
00350 poly->color = color;
00351 poly->numPoints = numPoints;
00352 Com_Memcpy(poly->points, points, numPoints * sizeof(vec3_t));
00353 }
00354
00355
00356
00357
00358
00359
00360 void BotImport_DebugPolygonDelete(int id)
00361 {
00362 if (!debugpolygons) return;
00363 debugpolygons[id].inuse = qfalse;
00364 }
00365
00366
00367
00368
00369
00370
00371 int BotImport_DebugLineCreate(void) {
00372 vec3_t points[1];
00373 return BotImport_DebugPolygonCreate(0, 0, points);
00374 }
00375
00376
00377
00378
00379
00380
00381 void BotImport_DebugLineDelete(int line) {
00382 BotImport_DebugPolygonDelete(line);
00383 }
00384
00385
00386
00387
00388
00389
00390 void BotImport_DebugLineShow(int line, vec3_t start, vec3_t end, int color) {
00391 vec3_t points[4], dir, cross, up = {0, 0, 1};
00392 float dot;
00393
00394 VectorCopy(start, points[0]);
00395 VectorCopy(start, points[1]);
00396
00397 VectorCopy(end, points[2]);
00398
00399 VectorCopy(end, points[3]);
00400
00401
00402 VectorSubtract(end, start, dir);
00403 VectorNormalize(dir);
00404 dot = DotProduct(dir, up);
00405 if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
00406 else CrossProduct(dir, up, cross);
00407
00408 VectorNormalize(cross);
00409
00410 VectorMA(points[0], 2, cross, points[0]);
00411 VectorMA(points[1], -2, cross, points[1]);
00412 VectorMA(points[2], -2, cross, points[2]);
00413 VectorMA(points[3], 2, cross, points[3]);
00414
00415 BotImport_DebugPolygonShow(line, color, 4, points);
00416 }
00417
00418
00419
00420
00421
00422
00423 void BotClientCommand( int client, char *command ) {
00424 SV_ExecuteClientCommand( &svs.clients[client], command, qtrue );
00425 }
00426
00427
00428
00429
00430
00431
00432 void SV_BotFrame( int time ) {
00433 if (!bot_enable) return;
00434
00435 if (!gvm) return;
00436 VM_Call( gvm, BOTAI_START_FRAME, time );
00437 }
00438
00439
00440
00441
00442
00443
00444 int SV_BotLibSetup( void ) {
00445 if (!bot_enable) {
00446 return 0;
00447 }
00448
00449 if ( !botlib_export ) {
00450 Com_Printf( S_COLOR_RED "Error: SV_BotLibSetup without SV_BotInitBotLib\n" );
00451 return -1;
00452 }
00453
00454 return botlib_export->BotLibSetup();
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 int SV_BotLibShutdown( void ) {
00466
00467 if ( !botlib_export ) {
00468 return -1;
00469 }
00470
00471 return botlib_export->BotLibShutdown();
00472 }
00473
00474
00475
00476
00477
00478
00479 void SV_BotInitCvars(void) {
00480
00481 Cvar_Get("bot_enable", "1", 0);
00482 Cvar_Get("bot_developer", "0", CVAR_CHEAT);
00483 Cvar_Get("bot_debug", "0", CVAR_CHEAT);
00484 Cvar_Get("bot_maxdebugpolys", "2", 0);
00485 Cvar_Get("bot_groundonly", "1", 0);
00486 Cvar_Get("bot_reachability", "0", 0);
00487 Cvar_Get("bot_visualizejumppads", "0", CVAR_CHEAT);
00488 Cvar_Get("bot_forceclustering", "0", 0);
00489 Cvar_Get("bot_forcereachability", "0", 0);
00490 Cvar_Get("bot_forcewrite", "0", 0);
00491 Cvar_Get("bot_aasoptimize", "0", 0);
00492 Cvar_Get("bot_saveroutingcache", "0", 0);
00493 Cvar_Get("bot_thinktime", "100", CVAR_CHEAT);
00494 Cvar_Get("bot_reloadcharacters", "0", 0);
00495 Cvar_Get("bot_testichat", "0", 0);
00496 Cvar_Get("bot_testrchat", "0", 0);
00497 Cvar_Get("bot_testsolid", "0", CVAR_CHEAT);
00498 Cvar_Get("bot_testclusters", "0", CVAR_CHEAT);
00499 Cvar_Get("bot_fastchat", "0", 0);
00500 Cvar_Get("bot_nochat", "0", 0);
00501 Cvar_Get("bot_pause", "0", CVAR_CHEAT);
00502 Cvar_Get("bot_report", "0", CVAR_CHEAT);
00503 Cvar_Get("bot_grapple", "0", 0);
00504 Cvar_Get("bot_rocketjump", "1", 0);
00505 Cvar_Get("bot_challenge", "0", 0);
00506 Cvar_Get("bot_minplayers", "0", 0);
00507 Cvar_Get("bot_interbreedchar", "", CVAR_CHEAT);
00508 Cvar_Get("bot_interbreedbots", "10", CVAR_CHEAT);
00509 Cvar_Get("bot_interbreedcycle", "20", CVAR_CHEAT);
00510 Cvar_Get("bot_interbreedwrite", "", CVAR_CHEAT);
00511 }
00512
00513
00514
00515
00516
00517
00518 void SV_BotInitBotLib(void) {
00519 botlib_import_t botlib_import;
00520
00521 if ( !Cvar_VariableValue("fs_restrict") && !Sys_CheckCD() ) {
00522 Com_Error( ERR_NEED_CD, "Game CD not in drive" );
00523 }
00524
00525 if (debugpolygons) Z_Free(debugpolygons);
00526 bot_maxdebugpolys = Cvar_VariableIntegerValue("bot_maxdebugpolys");
00527 debugpolygons = Z_Malloc(sizeof(bot_debugpoly_t) * bot_maxdebugpolys);
00528
00529 botlib_import.Print = BotImport_Print;
00530 botlib_import.Trace = BotImport_Trace;
00531 botlib_import.EntityTrace = BotImport_EntityTrace;
00532 botlib_import.PointContents = BotImport_PointContents;
00533 botlib_import.inPVS = BotImport_inPVS;
00534 botlib_import.BSPEntityData = BotImport_BSPEntityData;
00535 botlib_import.BSPModelMinsMaxsOrigin = BotImport_BSPModelMinsMaxsOrigin;
00536 botlib_import.BotClientCommand = BotClientCommand;
00537
00538
00539 botlib_import.GetMemory = BotImport_GetMemory;
00540 botlib_import.FreeMemory = BotImport_FreeMemory;
00541 botlib_import.AvailableMemory = Z_AvailableMemory;
00542 botlib_import.HunkAlloc = BotImport_HunkAlloc;
00543
00544
00545 botlib_import.FS_FOpenFile = FS_FOpenFileByMode;
00546 botlib_import.FS_Read = FS_Read2;
00547 botlib_import.FS_Write = FS_Write;
00548 botlib_import.FS_FCloseFile = FS_FCloseFile;
00549 botlib_import.FS_Seek = FS_Seek;
00550
00551
00552 botlib_import.DebugLineCreate = BotImport_DebugLineCreate;
00553 botlib_import.DebugLineDelete = BotImport_DebugLineDelete;
00554 botlib_import.DebugLineShow = BotImport_DebugLineShow;
00555
00556
00557 botlib_import.DebugPolygonCreate = BotImport_DebugPolygonCreate;
00558 botlib_import.DebugPolygonDelete = BotImport_DebugPolygonDelete;
00559
00560 botlib_export = (botlib_export_t *)GetBotLibAPI( BOTLIB_API_VERSION, &botlib_import );
00561 assert(botlib_export);
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 int SV_BotGetConsoleMessage( int client, char *buf, int size )
00575 {
00576 client_t *cl;
00577 int index;
00578
00579 cl = &svs.clients[client];
00580 cl->lastPacketTime = svs.time;
00581
00582 if ( cl->reliableAcknowledge == cl->reliableSequence ) {
00583 return qfalse;
00584 }
00585
00586 cl->reliableAcknowledge++;
00587 index = cl->reliableAcknowledge & ( MAX_RELIABLE_COMMANDS - 1 );
00588
00589 if ( !cl->reliableCommands[index][0] ) {
00590 return qfalse;
00591 }
00592
00593 Q_strncpyz( buf, cl->reliableCommands[index], size );
00594 return qtrue;
00595 }
00596
00597 #if 0
00598
00599
00600
00601
00602
00603 int EntityInPVS( int client, int entityNum ) {
00604 client_t *cl;
00605 clientSnapshot_t *frame;
00606 int i;
00607
00608 cl = &svs.clients[client];
00609 frame = &cl->frames[cl->netchan.outgoingSequence & PACKET_MASK];
00610 for ( i = 0; i < frame->num_entities; i++ ) {
00611 if ( svs.snapshotEntities[(frame->first_entity + i) % svs.numSnapshotEntities].number == entityNum ) {
00612 return qtrue;
00613 }
00614 }
00615 return qfalse;
00616 }
00617 #endif
00618
00619
00620
00621
00622
00623
00624 int SV_BotGetSnapshotEntity( int client, int sequence ) {
00625 client_t *cl;
00626 clientSnapshot_t *frame;
00627
00628 cl = &svs.clients[client];
00629 frame = &cl->frames[cl->netchan.outgoingSequence & PACKET_MASK];
00630 if (sequence < 0 || sequence >= frame->num_entities) {
00631 return -1;
00632 }
00633 return svs.snapshotEntities[(frame->first_entity + sequence) % svs.numSnapshotEntities].number;
00634 }
00635