sv_game.c (28027B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // sv_game.c -- interface to the game dll 23 24 #include "server.h" 25 26 #include "../game/botlib.h" 27 28 botlib_export_t *botlib_export; 29 30 void SV_GameError( const char *string ) { 31 Com_Error( ERR_DROP, "%s", string ); 32 } 33 34 void SV_GamePrint( const char *string ) { 35 Com_Printf( "%s", string ); 36 } 37 38 // these functions must be used instead of pointer arithmetic, because 39 // the game allocates gentities with private information after the server shared part 40 int SV_NumForGentity( sharedEntity_t *ent ) { 41 int num; 42 43 num = ( (byte *)ent - (byte *)sv.gentities ) / sv.gentitySize; 44 45 return num; 46 } 47 48 sharedEntity_t *SV_GentityNum( int num ) { 49 sharedEntity_t *ent; 50 51 ent = (sharedEntity_t *)((byte *)sv.gentities + sv.gentitySize*(num)); 52 53 return ent; 54 } 55 56 playerState_t *SV_GameClientNum( int num ) { 57 playerState_t *ps; 58 59 ps = (playerState_t *)((byte *)sv.gameClients + sv.gameClientSize*(num)); 60 61 return ps; 62 } 63 64 svEntity_t *SV_SvEntityForGentity( sharedEntity_t *gEnt ) { 65 if ( !gEnt || gEnt->s.number < 0 || gEnt->s.number >= MAX_GENTITIES ) { 66 Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" ); 67 } 68 return &sv.svEntities[ gEnt->s.number ]; 69 } 70 71 sharedEntity_t *SV_GEntityForSvEntity( svEntity_t *svEnt ) { 72 int num; 73 74 num = svEnt - sv.svEntities; 75 return SV_GentityNum( num ); 76 } 77 78 /* 79 =============== 80 SV_GameSendServerCommand 81 82 Sends a command string to a client 83 =============== 84 */ 85 void SV_GameSendServerCommand( int clientNum, const char *text ) { 86 if ( clientNum == -1 ) { 87 SV_SendServerCommand( NULL, "%s", text ); 88 } else { 89 if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) { 90 return; 91 } 92 SV_SendServerCommand( svs.clients + clientNum, "%s", text ); 93 } 94 } 95 96 97 /* 98 =============== 99 SV_GameDropClient 100 101 Disconnects the client with a message 102 =============== 103 */ 104 void SV_GameDropClient( int clientNum, const char *reason ) { 105 if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) { 106 return; 107 } 108 SV_DropClient( svs.clients + clientNum, reason ); 109 } 110 111 112 /* 113 ================= 114 SV_SetBrushModel 115 116 sets mins and maxs for inline bmodels 117 ================= 118 */ 119 void SV_SetBrushModel( sharedEntity_t *ent, const char *name ) { 120 clipHandle_t h; 121 vec3_t mins, maxs; 122 123 if (!name) { 124 Com_Error( ERR_DROP, "SV_SetBrushModel: NULL" ); 125 } 126 127 if (name[0] != '*') { 128 Com_Error( ERR_DROP, "SV_SetBrushModel: %s isn't a brush model", name ); 129 } 130 131 132 ent->s.modelindex = atoi( name + 1 ); 133 134 h = CM_InlineModel( ent->s.modelindex ); 135 CM_ModelBounds( h, mins, maxs ); 136 VectorCopy (mins, ent->r.mins); 137 VectorCopy (maxs, ent->r.maxs); 138 ent->r.bmodel = qtrue; 139 140 ent->r.contents = -1; // we don't know exactly what is in the brushes 141 142 SV_LinkEntity( ent ); // FIXME: remove 143 } 144 145 146 147 /* 148 ================= 149 SV_inPVS 150 151 Also checks portalareas so that doors block sight 152 ================= 153 */ 154 qboolean SV_inPVS (const vec3_t p1, const vec3_t p2) 155 { 156 int leafnum; 157 int cluster; 158 int area1, area2; 159 byte *mask; 160 161 leafnum = CM_PointLeafnum (p1); 162 cluster = CM_LeafCluster (leafnum); 163 area1 = CM_LeafArea (leafnum); 164 mask = CM_ClusterPVS (cluster); 165 166 leafnum = CM_PointLeafnum (p2); 167 cluster = CM_LeafCluster (leafnum); 168 area2 = CM_LeafArea (leafnum); 169 if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) ) 170 return qfalse; 171 if (!CM_AreasConnected (area1, area2)) 172 return qfalse; // a door blocks sight 173 return qtrue; 174 } 175 176 177 /* 178 ================= 179 SV_inPVSIgnorePortals 180 181 Does NOT check portalareas 182 ================= 183 */ 184 qboolean SV_inPVSIgnorePortals( const vec3_t p1, const vec3_t p2) 185 { 186 int leafnum; 187 int cluster; 188 int area1, area2; 189 byte *mask; 190 191 leafnum = CM_PointLeafnum (p1); 192 cluster = CM_LeafCluster (leafnum); 193 area1 = CM_LeafArea (leafnum); 194 mask = CM_ClusterPVS (cluster); 195 196 leafnum = CM_PointLeafnum (p2); 197 cluster = CM_LeafCluster (leafnum); 198 area2 = CM_LeafArea (leafnum); 199 200 if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) ) 201 return qfalse; 202 203 return qtrue; 204 } 205 206 207 /* 208 ======================== 209 SV_AdjustAreaPortalState 210 ======================== 211 */ 212 void SV_AdjustAreaPortalState( sharedEntity_t *ent, qboolean open ) { 213 svEntity_t *svEnt; 214 215 svEnt = SV_SvEntityForGentity( ent ); 216 if ( svEnt->areanum2 == -1 ) { 217 return; 218 } 219 CM_AdjustAreaPortalState( svEnt->areanum, svEnt->areanum2, open ); 220 } 221 222 223 /* 224 ================== 225 SV_GameAreaEntities 226 ================== 227 */ 228 qboolean SV_EntityContact( vec3_t mins, vec3_t maxs, const sharedEntity_t *gEnt, int capsule ) { 229 const float *origin, *angles; 230 clipHandle_t ch; 231 trace_t trace; 232 233 // check for exact collision 234 origin = gEnt->r.currentOrigin; 235 angles = gEnt->r.currentAngles; 236 237 ch = SV_ClipHandleForEntity( gEnt ); 238 CM_TransformedBoxTrace ( &trace, vec3_origin, vec3_origin, mins, maxs, 239 ch, -1, origin, angles, capsule ); 240 241 return trace.startsolid; 242 } 243 244 245 /* 246 =============== 247 SV_GetServerinfo 248 249 =============== 250 */ 251 void SV_GetServerinfo( char *buffer, int bufferSize ) { 252 if ( bufferSize < 1 ) { 253 Com_Error( ERR_DROP, "SV_GetServerinfo: bufferSize == %i", bufferSize ); 254 } 255 Q_strncpyz( buffer, Cvar_InfoString( CVAR_SERVERINFO ), bufferSize ); 256 } 257 258 /* 259 =============== 260 SV_LocateGameData 261 262 =============== 263 */ 264 void SV_LocateGameData( sharedEntity_t *gEnts, int numGEntities, int sizeofGEntity_t, 265 playerState_t *clients, int sizeofGameClient ) { 266 sv.gentities = gEnts; 267 sv.gentitySize = sizeofGEntity_t; 268 sv.num_entities = numGEntities; 269 270 sv.gameClients = clients; 271 sv.gameClientSize = sizeofGameClient; 272 } 273 274 275 /* 276 =============== 277 SV_GetUsercmd 278 279 =============== 280 */ 281 void SV_GetUsercmd( int clientNum, usercmd_t *cmd ) { 282 if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) { 283 Com_Error( ERR_DROP, "SV_GetUsercmd: bad clientNum:%i", clientNum ); 284 } 285 *cmd = svs.clients[clientNum].lastUsercmd; 286 } 287 288 //============================================== 289 290 static int FloatAsInt( float f ) { 291 union 292 { 293 int i; 294 float f; 295 } temp; 296 297 temp.f = f; 298 return temp.i; 299 } 300 301 /* 302 ==================== 303 SV_GameSystemCalls 304 305 The module is making a system call 306 ==================== 307 */ 308 //rcg010207 - see my comments in VM_DllSyscall(), in qcommon/vm.c ... 309 #if ((defined __linux__) && (defined __powerpc__)) 310 #define VMA(x) ((void *) args[x]) 311 #else 312 #define VMA(x) VM_ArgPtr(args[x]) 313 #endif 314 315 #define VMF(x) ((float *)args)[x] 316 317 int SV_GameSystemCalls( int *args ) { 318 switch( args[0] ) { 319 case G_PRINT: 320 Com_Printf( "%s", VMA(1) ); 321 return 0; 322 case G_ERROR: 323 Com_Error( ERR_DROP, "%s", VMA(1) ); 324 return 0; 325 case G_MILLISECONDS: 326 return Sys_Milliseconds(); 327 case G_CVAR_REGISTER: 328 Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); 329 return 0; 330 case G_CVAR_UPDATE: 331 Cvar_Update( VMA(1) ); 332 return 0; 333 case G_CVAR_SET: 334 Cvar_Set( (const char *)VMA(1), (const char *)VMA(2) ); 335 return 0; 336 case G_CVAR_VARIABLE_INTEGER_VALUE: 337 return Cvar_VariableIntegerValue( (const char *)VMA(1) ); 338 case G_CVAR_VARIABLE_STRING_BUFFER: 339 Cvar_VariableStringBuffer( VMA(1), VMA(2), args[3] ); 340 return 0; 341 case G_ARGC: 342 return Cmd_Argc(); 343 case G_ARGV: 344 Cmd_ArgvBuffer( args[1], VMA(2), args[3] ); 345 return 0; 346 case G_SEND_CONSOLE_COMMAND: 347 Cbuf_ExecuteText( args[1], VMA(2) ); 348 return 0; 349 350 case G_FS_FOPEN_FILE: 351 return FS_FOpenFileByMode( VMA(1), VMA(2), args[3] ); 352 case G_FS_READ: 353 FS_Read2( VMA(1), args[2], args[3] ); 354 return 0; 355 case G_FS_WRITE: 356 FS_Write( VMA(1), args[2], args[3] ); 357 return 0; 358 case G_FS_FCLOSE_FILE: 359 FS_FCloseFile( args[1] ); 360 return 0; 361 case G_FS_GETFILELIST: 362 return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] ); 363 case G_FS_SEEK: 364 return FS_Seek( args[1], args[2], args[3] ); 365 366 case G_LOCATE_GAME_DATA: 367 SV_LocateGameData( VMA(1), args[2], args[3], VMA(4), args[5] ); 368 return 0; 369 case G_DROP_CLIENT: 370 SV_GameDropClient( args[1], VMA(2) ); 371 return 0; 372 case G_SEND_SERVER_COMMAND: 373 SV_GameSendServerCommand( args[1], VMA(2) ); 374 return 0; 375 case G_LINKENTITY: 376 SV_LinkEntity( VMA(1) ); 377 return 0; 378 case G_UNLINKENTITY: 379 SV_UnlinkEntity( VMA(1) ); 380 return 0; 381 case G_ENTITIES_IN_BOX: 382 return SV_AreaEntities( VMA(1), VMA(2), VMA(3), args[4] ); 383 case G_ENTITY_CONTACT: 384 return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qfalse ); 385 case G_ENTITY_CONTACTCAPSULE: 386 return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qtrue ); 387 case G_TRACE: 388 SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse ); 389 return 0; 390 case G_TRACECAPSULE: 391 SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue ); 392 return 0; 393 case G_POINT_CONTENTS: 394 return SV_PointContents( VMA(1), args[2] ); 395 case G_SET_BRUSH_MODEL: 396 SV_SetBrushModel( VMA(1), VMA(2) ); 397 return 0; 398 case G_IN_PVS: 399 return SV_inPVS( VMA(1), VMA(2) ); 400 case G_IN_PVS_IGNORE_PORTALS: 401 return SV_inPVSIgnorePortals( VMA(1), VMA(2) ); 402 403 case G_SET_CONFIGSTRING: 404 SV_SetConfigstring( args[1], VMA(2) ); 405 return 0; 406 case G_GET_CONFIGSTRING: 407 SV_GetConfigstring( args[1], VMA(2), args[3] ); 408 return 0; 409 case G_SET_USERINFO: 410 SV_SetUserinfo( args[1], VMA(2) ); 411 return 0; 412 case G_GET_USERINFO: 413 SV_GetUserinfo( args[1], VMA(2), args[3] ); 414 return 0; 415 case G_GET_SERVERINFO: 416 SV_GetServerinfo( VMA(1), args[2] ); 417 return 0; 418 case G_ADJUST_AREA_PORTAL_STATE: 419 SV_AdjustAreaPortalState( VMA(1), args[2] ); 420 return 0; 421 case G_AREAS_CONNECTED: 422 return CM_AreasConnected( args[1], args[2] ); 423 424 case G_BOT_ALLOCATE_CLIENT: 425 return SV_BotAllocateClient(); 426 case G_BOT_FREE_CLIENT: 427 SV_BotFreeClient( args[1] ); 428 return 0; 429 430 case G_GET_USERCMD: 431 SV_GetUsercmd( args[1], VMA(2) ); 432 return 0; 433 case G_GET_ENTITY_TOKEN: 434 { 435 const char *s; 436 437 s = COM_Parse( &sv.entityParsePoint ); 438 Q_strncpyz( VMA(1), s, args[2] ); 439 if ( !sv.entityParsePoint && !s[0] ) { 440 return qfalse; 441 } else { 442 return qtrue; 443 } 444 } 445 446 case G_DEBUG_POLYGON_CREATE: 447 return BotImport_DebugPolygonCreate( args[1], args[2], VMA(3) ); 448 case G_DEBUG_POLYGON_DELETE: 449 BotImport_DebugPolygonDelete( args[1] ); 450 return 0; 451 case G_REAL_TIME: 452 return Com_RealTime( VMA(1) ); 453 case G_SNAPVECTOR: 454 Sys_SnapVector( VMA(1) ); 455 return 0; 456 457 //==================================== 458 459 case BOTLIB_SETUP: 460 return SV_BotLibSetup(); 461 case BOTLIB_SHUTDOWN: 462 return SV_BotLibShutdown(); 463 case BOTLIB_LIBVAR_SET: 464 return botlib_export->BotLibVarSet( VMA(1), VMA(2) ); 465 case BOTLIB_LIBVAR_GET: 466 return botlib_export->BotLibVarGet( VMA(1), VMA(2), args[3] ); 467 468 case BOTLIB_PC_ADD_GLOBAL_DEFINE: 469 return botlib_export->PC_AddGlobalDefine( VMA(1) ); 470 case BOTLIB_PC_LOAD_SOURCE: 471 return botlib_export->PC_LoadSourceHandle( VMA(1) ); 472 case BOTLIB_PC_FREE_SOURCE: 473 return botlib_export->PC_FreeSourceHandle( args[1] ); 474 case BOTLIB_PC_READ_TOKEN: 475 return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) ); 476 case BOTLIB_PC_SOURCE_FILE_AND_LINE: 477 return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) ); 478 479 case BOTLIB_START_FRAME: 480 return botlib_export->BotLibStartFrame( VMF(1) ); 481 case BOTLIB_LOAD_MAP: 482 return botlib_export->BotLibLoadMap( VMA(1) ); 483 case BOTLIB_UPDATENTITY: 484 return botlib_export->BotLibUpdateEntity( args[1], VMA(2) ); 485 case BOTLIB_TEST: 486 return botlib_export->Test( args[1], VMA(2), VMA(3), VMA(4) ); 487 488 case BOTLIB_GET_SNAPSHOT_ENTITY: 489 return SV_BotGetSnapshotEntity( args[1], args[2] ); 490 case BOTLIB_GET_CONSOLE_MESSAGE: 491 return SV_BotGetConsoleMessage( args[1], VMA(2), args[3] ); 492 case BOTLIB_USER_COMMAND: 493 SV_ClientThink( &svs.clients[args[1]], VMA(2) ); 494 return 0; 495 496 case BOTLIB_AAS_BBOX_AREAS: 497 return botlib_export->aas.AAS_BBoxAreas( VMA(1), VMA(2), VMA(3), args[4] ); 498 case BOTLIB_AAS_AREA_INFO: 499 return botlib_export->aas.AAS_AreaInfo( args[1], VMA(2) ); 500 case BOTLIB_AAS_ALTERNATIVE_ROUTE_GOAL: 501 return botlib_export->aas.AAS_AlternativeRouteGoals( VMA(1), args[2], VMA(3), args[4], args[5], VMA(6), args[7], args[8] ); 502 case BOTLIB_AAS_ENTITY_INFO: 503 botlib_export->aas.AAS_EntityInfo( args[1], VMA(2) ); 504 return 0; 505 506 case BOTLIB_AAS_INITIALIZED: 507 return botlib_export->aas.AAS_Initialized(); 508 case BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX: 509 botlib_export->aas.AAS_PresenceTypeBoundingBox( args[1], VMA(2), VMA(3) ); 510 return 0; 511 case BOTLIB_AAS_TIME: 512 return FloatAsInt( botlib_export->aas.AAS_Time() ); 513 514 case BOTLIB_AAS_POINT_AREA_NUM: 515 return botlib_export->aas.AAS_PointAreaNum( VMA(1) ); 516 case BOTLIB_AAS_POINT_REACHABILITY_AREA_INDEX: 517 return botlib_export->aas.AAS_PointReachabilityAreaIndex( VMA(1) ); 518 case BOTLIB_AAS_TRACE_AREAS: 519 return botlib_export->aas.AAS_TraceAreas( VMA(1), VMA(2), VMA(3), VMA(4), args[5] ); 520 521 case BOTLIB_AAS_POINT_CONTENTS: 522 return botlib_export->aas.AAS_PointContents( VMA(1) ); 523 case BOTLIB_AAS_NEXT_BSP_ENTITY: 524 return botlib_export->aas.AAS_NextBSPEntity( args[1] ); 525 case BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY: 526 return botlib_export->aas.AAS_ValueForBSPEpairKey( args[1], VMA(2), VMA(3), args[4] ); 527 case BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY: 528 return botlib_export->aas.AAS_VectorForBSPEpairKey( args[1], VMA(2), VMA(3) ); 529 case BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY: 530 return botlib_export->aas.AAS_FloatForBSPEpairKey( args[1], VMA(2), VMA(3) ); 531 case BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY: 532 return botlib_export->aas.AAS_IntForBSPEpairKey( args[1], VMA(2), VMA(3) ); 533 534 case BOTLIB_AAS_AREA_REACHABILITY: 535 return botlib_export->aas.AAS_AreaReachability( args[1] ); 536 537 case BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA: 538 return botlib_export->aas.AAS_AreaTravelTimeToGoalArea( args[1], VMA(2), args[3], args[4] ); 539 case BOTLIB_AAS_ENABLE_ROUTING_AREA: 540 return botlib_export->aas.AAS_EnableRoutingArea( args[1], args[2] ); 541 case BOTLIB_AAS_PREDICT_ROUTE: 542 return botlib_export->aas.AAS_PredictRoute( VMA(1), args[2], VMA(3), args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11] ); 543 544 case BOTLIB_AAS_SWIMMING: 545 return botlib_export->aas.AAS_Swimming( VMA(1) ); 546 case BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT: 547 return botlib_export->aas.AAS_PredictClientMovement( VMA(1), args[2], VMA(3), args[4], args[5], 548 VMA(6), VMA(7), args[8], args[9], VMF(10), args[11], args[12], args[13] ); 549 550 case BOTLIB_EA_SAY: 551 botlib_export->ea.EA_Say( args[1], VMA(2) ); 552 return 0; 553 case BOTLIB_EA_SAY_TEAM: 554 botlib_export->ea.EA_SayTeam( args[1], VMA(2) ); 555 return 0; 556 case BOTLIB_EA_COMMAND: 557 botlib_export->ea.EA_Command( args[1], VMA(2) ); 558 return 0; 559 560 case BOTLIB_EA_ACTION: 561 botlib_export->ea.EA_Action( args[1], args[2] ); 562 break; 563 case BOTLIB_EA_GESTURE: 564 botlib_export->ea.EA_Gesture( args[1] ); 565 return 0; 566 case BOTLIB_EA_TALK: 567 botlib_export->ea.EA_Talk( args[1] ); 568 return 0; 569 case BOTLIB_EA_ATTACK: 570 botlib_export->ea.EA_Attack( args[1] ); 571 return 0; 572 case BOTLIB_EA_USE: 573 botlib_export->ea.EA_Use( args[1] ); 574 return 0; 575 case BOTLIB_EA_RESPAWN: 576 botlib_export->ea.EA_Respawn( args[1] ); 577 return 0; 578 case BOTLIB_EA_CROUCH: 579 botlib_export->ea.EA_Crouch( args[1] ); 580 return 0; 581 case BOTLIB_EA_MOVE_UP: 582 botlib_export->ea.EA_MoveUp( args[1] ); 583 return 0; 584 case BOTLIB_EA_MOVE_DOWN: 585 botlib_export->ea.EA_MoveDown( args[1] ); 586 return 0; 587 case BOTLIB_EA_MOVE_FORWARD: 588 botlib_export->ea.EA_MoveForward( args[1] ); 589 return 0; 590 case BOTLIB_EA_MOVE_BACK: 591 botlib_export->ea.EA_MoveBack( args[1] ); 592 return 0; 593 case BOTLIB_EA_MOVE_LEFT: 594 botlib_export->ea.EA_MoveLeft( args[1] ); 595 return 0; 596 case BOTLIB_EA_MOVE_RIGHT: 597 botlib_export->ea.EA_MoveRight( args[1] ); 598 return 0; 599 600 case BOTLIB_EA_SELECT_WEAPON: 601 botlib_export->ea.EA_SelectWeapon( args[1], args[2] ); 602 return 0; 603 case BOTLIB_EA_JUMP: 604 botlib_export->ea.EA_Jump( args[1] ); 605 return 0; 606 case BOTLIB_EA_DELAYED_JUMP: 607 botlib_export->ea.EA_DelayedJump( args[1] ); 608 return 0; 609 case BOTLIB_EA_MOVE: 610 botlib_export->ea.EA_Move( args[1], VMA(2), VMF(3) ); 611 return 0; 612 case BOTLIB_EA_VIEW: 613 botlib_export->ea.EA_View( args[1], VMA(2) ); 614 return 0; 615 616 case BOTLIB_EA_END_REGULAR: 617 botlib_export->ea.EA_EndRegular( args[1], VMF(2) ); 618 return 0; 619 case BOTLIB_EA_GET_INPUT: 620 botlib_export->ea.EA_GetInput( args[1], VMF(2), VMA(3) ); 621 return 0; 622 case BOTLIB_EA_RESET_INPUT: 623 botlib_export->ea.EA_ResetInput( args[1] ); 624 return 0; 625 626 case BOTLIB_AI_LOAD_CHARACTER: 627 return botlib_export->ai.BotLoadCharacter( VMA(1), VMF(2) ); 628 case BOTLIB_AI_FREE_CHARACTER: 629 botlib_export->ai.BotFreeCharacter( args[1] ); 630 return 0; 631 case BOTLIB_AI_CHARACTERISTIC_FLOAT: 632 return FloatAsInt( botlib_export->ai.Characteristic_Float( args[1], args[2] ) ); 633 case BOTLIB_AI_CHARACTERISTIC_BFLOAT: 634 return FloatAsInt( botlib_export->ai.Characteristic_BFloat( args[1], args[2], VMF(3), VMF(4) ) ); 635 case BOTLIB_AI_CHARACTERISTIC_INTEGER: 636 return botlib_export->ai.Characteristic_Integer( args[1], args[2] ); 637 case BOTLIB_AI_CHARACTERISTIC_BINTEGER: 638 return botlib_export->ai.Characteristic_BInteger( args[1], args[2], args[3], args[4] ); 639 case BOTLIB_AI_CHARACTERISTIC_STRING: 640 botlib_export->ai.Characteristic_String( args[1], args[2], VMA(3), args[4] ); 641 return 0; 642 643 case BOTLIB_AI_ALLOC_CHAT_STATE: 644 return botlib_export->ai.BotAllocChatState(); 645 case BOTLIB_AI_FREE_CHAT_STATE: 646 botlib_export->ai.BotFreeChatState( args[1] ); 647 return 0; 648 case BOTLIB_AI_QUEUE_CONSOLE_MESSAGE: 649 botlib_export->ai.BotQueueConsoleMessage( args[1], args[2], VMA(3) ); 650 return 0; 651 case BOTLIB_AI_REMOVE_CONSOLE_MESSAGE: 652 botlib_export->ai.BotRemoveConsoleMessage( args[1], args[2] ); 653 return 0; 654 case BOTLIB_AI_NEXT_CONSOLE_MESSAGE: 655 return botlib_export->ai.BotNextConsoleMessage( args[1], VMA(2) ); 656 case BOTLIB_AI_NUM_CONSOLE_MESSAGE: 657 return botlib_export->ai.BotNumConsoleMessages( args[1] ); 658 case BOTLIB_AI_INITIAL_CHAT: 659 botlib_export->ai.BotInitialChat( args[1], VMA(2), args[3], VMA(4), VMA(5), VMA(6), VMA(7), VMA(8), VMA(9), VMA(10), VMA(11) ); 660 return 0; 661 case BOTLIB_AI_NUM_INITIAL_CHATS: 662 return botlib_export->ai.BotNumInitialChats( args[1], VMA(2) ); 663 case BOTLIB_AI_REPLY_CHAT: 664 return botlib_export->ai.BotReplyChat( args[1], VMA(2), args[3], args[4], VMA(5), VMA(6), VMA(7), VMA(8), VMA(9), VMA(10), VMA(11), VMA(12) ); 665 case BOTLIB_AI_CHAT_LENGTH: 666 return botlib_export->ai.BotChatLength( args[1] ); 667 case BOTLIB_AI_ENTER_CHAT: 668 botlib_export->ai.BotEnterChat( args[1], args[2], args[3] ); 669 return 0; 670 case BOTLIB_AI_GET_CHAT_MESSAGE: 671 botlib_export->ai.BotGetChatMessage( args[1], VMA(2), args[3] ); 672 return 0; 673 case BOTLIB_AI_STRING_CONTAINS: 674 return botlib_export->ai.StringContains( VMA(1), VMA(2), args[3] ); 675 case BOTLIB_AI_FIND_MATCH: 676 return botlib_export->ai.BotFindMatch( VMA(1), VMA(2), args[3] ); 677 case BOTLIB_AI_MATCH_VARIABLE: 678 botlib_export->ai.BotMatchVariable( VMA(1), args[2], VMA(3), args[4] ); 679 return 0; 680 case BOTLIB_AI_UNIFY_WHITE_SPACES: 681 botlib_export->ai.UnifyWhiteSpaces( VMA(1) ); 682 return 0; 683 case BOTLIB_AI_REPLACE_SYNONYMS: 684 botlib_export->ai.BotReplaceSynonyms( VMA(1), args[2] ); 685 return 0; 686 case BOTLIB_AI_LOAD_CHAT_FILE: 687 return botlib_export->ai.BotLoadChatFile( args[1], VMA(2), VMA(3) ); 688 case BOTLIB_AI_SET_CHAT_GENDER: 689 botlib_export->ai.BotSetChatGender( args[1], args[2] ); 690 return 0; 691 case BOTLIB_AI_SET_CHAT_NAME: 692 botlib_export->ai.BotSetChatName( args[1], VMA(2), args[3] ); 693 return 0; 694 695 case BOTLIB_AI_RESET_GOAL_STATE: 696 botlib_export->ai.BotResetGoalState( args[1] ); 697 return 0; 698 case BOTLIB_AI_RESET_AVOID_GOALS: 699 botlib_export->ai.BotResetAvoidGoals( args[1] ); 700 return 0; 701 case BOTLIB_AI_REMOVE_FROM_AVOID_GOALS: 702 botlib_export->ai.BotRemoveFromAvoidGoals( args[1], args[2] ); 703 return 0; 704 case BOTLIB_AI_PUSH_GOAL: 705 botlib_export->ai.BotPushGoal( args[1], VMA(2) ); 706 return 0; 707 case BOTLIB_AI_POP_GOAL: 708 botlib_export->ai.BotPopGoal( args[1] ); 709 return 0; 710 case BOTLIB_AI_EMPTY_GOAL_STACK: 711 botlib_export->ai.BotEmptyGoalStack( args[1] ); 712 return 0; 713 case BOTLIB_AI_DUMP_AVOID_GOALS: 714 botlib_export->ai.BotDumpAvoidGoals( args[1] ); 715 return 0; 716 case BOTLIB_AI_DUMP_GOAL_STACK: 717 botlib_export->ai.BotDumpGoalStack( args[1] ); 718 return 0; 719 case BOTLIB_AI_GOAL_NAME: 720 botlib_export->ai.BotGoalName( args[1], VMA(2), args[3] ); 721 return 0; 722 case BOTLIB_AI_GET_TOP_GOAL: 723 return botlib_export->ai.BotGetTopGoal( args[1], VMA(2) ); 724 case BOTLIB_AI_GET_SECOND_GOAL: 725 return botlib_export->ai.BotGetSecondGoal( args[1], VMA(2) ); 726 case BOTLIB_AI_CHOOSE_LTG_ITEM: 727 return botlib_export->ai.BotChooseLTGItem( args[1], VMA(2), VMA(3), args[4] ); 728 case BOTLIB_AI_CHOOSE_NBG_ITEM: 729 return botlib_export->ai.BotChooseNBGItem( args[1], VMA(2), VMA(3), args[4], VMA(5), VMF(6) ); 730 case BOTLIB_AI_TOUCHING_GOAL: 731 return botlib_export->ai.BotTouchingGoal( VMA(1), VMA(2) ); 732 case BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE: 733 return botlib_export->ai.BotItemGoalInVisButNotVisible( args[1], VMA(2), VMA(3), VMA(4) ); 734 case BOTLIB_AI_GET_LEVEL_ITEM_GOAL: 735 return botlib_export->ai.BotGetLevelItemGoal( args[1], VMA(2), VMA(3) ); 736 case BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL: 737 return botlib_export->ai.BotGetNextCampSpotGoal( args[1], VMA(2) ); 738 case BOTLIB_AI_GET_MAP_LOCATION_GOAL: 739 return botlib_export->ai.BotGetMapLocationGoal( VMA(1), VMA(2) ); 740 case BOTLIB_AI_AVOID_GOAL_TIME: 741 return FloatAsInt( botlib_export->ai.BotAvoidGoalTime( args[1], args[2] ) ); 742 case BOTLIB_AI_SET_AVOID_GOAL_TIME: 743 botlib_export->ai.BotSetAvoidGoalTime( args[1], args[2], VMF(3)); 744 return 0; 745 case BOTLIB_AI_INIT_LEVEL_ITEMS: 746 botlib_export->ai.BotInitLevelItems(); 747 return 0; 748 case BOTLIB_AI_UPDATE_ENTITY_ITEMS: 749 botlib_export->ai.BotUpdateEntityItems(); 750 return 0; 751 case BOTLIB_AI_LOAD_ITEM_WEIGHTS: 752 return botlib_export->ai.BotLoadItemWeights( args[1], VMA(2) ); 753 case BOTLIB_AI_FREE_ITEM_WEIGHTS: 754 botlib_export->ai.BotFreeItemWeights( args[1] ); 755 return 0; 756 case BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC: 757 botlib_export->ai.BotInterbreedGoalFuzzyLogic( args[1], args[2], args[3] ); 758 return 0; 759 case BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC: 760 botlib_export->ai.BotSaveGoalFuzzyLogic( args[1], VMA(2) ); 761 return 0; 762 case BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC: 763 botlib_export->ai.BotMutateGoalFuzzyLogic( args[1], VMF(2) ); 764 return 0; 765 case BOTLIB_AI_ALLOC_GOAL_STATE: 766 return botlib_export->ai.BotAllocGoalState( args[1] ); 767 case BOTLIB_AI_FREE_GOAL_STATE: 768 botlib_export->ai.BotFreeGoalState( args[1] ); 769 return 0; 770 771 case BOTLIB_AI_RESET_MOVE_STATE: 772 botlib_export->ai.BotResetMoveState( args[1] ); 773 return 0; 774 case BOTLIB_AI_ADD_AVOID_SPOT: 775 botlib_export->ai.BotAddAvoidSpot( args[1], VMA(2), VMF(3), args[4] ); 776 return 0; 777 case BOTLIB_AI_MOVE_TO_GOAL: 778 botlib_export->ai.BotMoveToGoal( VMA(1), args[2], VMA(3), args[4] ); 779 return 0; 780 case BOTLIB_AI_MOVE_IN_DIRECTION: 781 return botlib_export->ai.BotMoveInDirection( args[1], VMA(2), VMF(3), args[4] ); 782 case BOTLIB_AI_RESET_AVOID_REACH: 783 botlib_export->ai.BotResetAvoidReach( args[1] ); 784 return 0; 785 case BOTLIB_AI_RESET_LAST_AVOID_REACH: 786 botlib_export->ai.BotResetLastAvoidReach( args[1] ); 787 return 0; 788 case BOTLIB_AI_REACHABILITY_AREA: 789 return botlib_export->ai.BotReachabilityArea( VMA(1), args[2] ); 790 case BOTLIB_AI_MOVEMENT_VIEW_TARGET: 791 return botlib_export->ai.BotMovementViewTarget( args[1], VMA(2), args[3], VMF(4), VMA(5) ); 792 case BOTLIB_AI_PREDICT_VISIBLE_POSITION: 793 return botlib_export->ai.BotPredictVisiblePosition( VMA(1), args[2], VMA(3), args[4], VMA(5) ); 794 case BOTLIB_AI_ALLOC_MOVE_STATE: 795 return botlib_export->ai.BotAllocMoveState(); 796 case BOTLIB_AI_FREE_MOVE_STATE: 797 botlib_export->ai.BotFreeMoveState( args[1] ); 798 return 0; 799 case BOTLIB_AI_INIT_MOVE_STATE: 800 botlib_export->ai.BotInitMoveState( args[1], VMA(2) ); 801 return 0; 802 803 case BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON: 804 return botlib_export->ai.BotChooseBestFightWeapon( args[1], VMA(2) ); 805 case BOTLIB_AI_GET_WEAPON_INFO: 806 botlib_export->ai.BotGetWeaponInfo( args[1], args[2], VMA(3) ); 807 return 0; 808 case BOTLIB_AI_LOAD_WEAPON_WEIGHTS: 809 return botlib_export->ai.BotLoadWeaponWeights( args[1], VMA(2) ); 810 case BOTLIB_AI_ALLOC_WEAPON_STATE: 811 return botlib_export->ai.BotAllocWeaponState(); 812 case BOTLIB_AI_FREE_WEAPON_STATE: 813 botlib_export->ai.BotFreeWeaponState( args[1] ); 814 return 0; 815 case BOTLIB_AI_RESET_WEAPON_STATE: 816 botlib_export->ai.BotResetWeaponState( args[1] ); 817 return 0; 818 819 case BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION: 820 return botlib_export->ai.GeneticParentsAndChildSelection(args[1], VMA(2), VMA(3), VMA(4), VMA(5)); 821 822 case TRAP_MEMSET: 823 Com_Memset( VMA(1), args[2], args[3] ); 824 return 0; 825 826 case TRAP_MEMCPY: 827 Com_Memcpy( VMA(1), VMA(2), args[3] ); 828 return 0; 829 830 case TRAP_STRNCPY: 831 return (int)strncpy( VMA(1), VMA(2), args[3] ); 832 833 case TRAP_SIN: 834 return FloatAsInt( sin( VMF(1) ) ); 835 836 case TRAP_COS: 837 return FloatAsInt( cos( VMF(1) ) ); 838 839 case TRAP_ATAN2: 840 return FloatAsInt( atan2( VMF(1), VMF(2) ) ); 841 842 case TRAP_SQRT: 843 return FloatAsInt( sqrt( VMF(1) ) ); 844 845 case TRAP_MATRIXMULTIPLY: 846 MatrixMultiply( VMA(1), VMA(2), VMA(3) ); 847 return 0; 848 849 case TRAP_ANGLEVECTORS: 850 AngleVectors( VMA(1), VMA(2), VMA(3), VMA(4) ); 851 return 0; 852 853 case TRAP_PERPENDICULARVECTOR: 854 PerpendicularVector( VMA(1), VMA(2) ); 855 return 0; 856 857 case TRAP_FLOOR: 858 return FloatAsInt( floor( VMF(1) ) ); 859 860 case TRAP_CEIL: 861 return FloatAsInt( ceil( VMF(1) ) ); 862 863 864 default: 865 Com_Error( ERR_DROP, "Bad game system trap: %i", args[0] ); 866 } 867 return -1; 868 } 869 870 /* 871 =============== 872 SV_ShutdownGameProgs 873 874 Called every time a map changes 875 =============== 876 */ 877 void SV_ShutdownGameProgs( void ) { 878 if ( !gvm ) { 879 return; 880 } 881 VM_Call( gvm, GAME_SHUTDOWN, qfalse ); 882 VM_Free( gvm ); 883 gvm = NULL; 884 } 885 886 /* 887 ================== 888 SV_InitGameVM 889 890 Called for both a full init and a restart 891 ================== 892 */ 893 static void SV_InitGameVM( qboolean restart ) { 894 int i; 895 896 // start the entity parsing at the beginning 897 sv.entityParsePoint = CM_EntityString(); 898 899 // clear all gentity pointers that might still be set from 900 // a previous level 901 // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=522 902 // now done before GAME_INIT call 903 for ( i = 0 ; i < sv_maxclients->integer ; i++ ) { 904 svs.clients[i].gentity = NULL; 905 } 906 907 // use the current msec count for a random seed 908 // init for this gamestate 909 VM_Call( gvm, GAME_INIT, svs.time, Com_Milliseconds(), restart ); 910 } 911 912 913 914 /* 915 =================== 916 SV_RestartGameProgs 917 918 Called on a map_restart, but not on a normal map change 919 =================== 920 */ 921 void SV_RestartGameProgs( void ) { 922 if ( !gvm ) { 923 return; 924 } 925 VM_Call( gvm, GAME_SHUTDOWN, qtrue ); 926 927 // do a restart instead of a free 928 gvm = VM_Restart( gvm ); 929 if ( !gvm ) { // bk001212 - as done below 930 Com_Error( ERR_FATAL, "VM_Restart on game failed" ); 931 } 932 933 SV_InitGameVM( qtrue ); 934 } 935 936 937 /* 938 =============== 939 SV_InitGameProgs 940 941 Called on a normal map change, not on a map_restart 942 =============== 943 */ 944 void SV_InitGameProgs( void ) { 945 cvar_t *var; 946 //FIXME these are temp while I make bots run in vm 947 extern int bot_enable; 948 949 var = Cvar_Get( "bot_enable", "1", CVAR_LATCH ); 950 if ( var ) { 951 bot_enable = var->integer; 952 } 953 else { 954 bot_enable = 0; 955 } 956 957 // load the dll or bytecode 958 gvm = VM_Create( "qagame", SV_GameSystemCalls, Cvar_VariableValue( "vm_game" ) ); 959 if ( !gvm ) { 960 Com_Error( ERR_FATAL, "VM_Create on game failed" ); 961 } 962 963 SV_InitGameVM( qfalse ); 964 } 965 966 967 /* 968 ==================== 969 SV_GameCommand 970 971 See if the current console command is claimed by the game 972 ==================== 973 */ 974 qboolean SV_GameCommand( void ) { 975 if ( sv.state != SS_GAME ) { 976 return qfalse; 977 } 978 979 return VM_Call( gvm, GAME_CONSOLE_COMMAND ); 980 } 981