Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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