/* ======================================================================================================================================= SV_PointContents ======================================================================================================================================= */ int SV_PointContents(const vec3_t p, int passEntityNum) { int touch[MAX_GENTITIES]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; // get base contents from world contents = CM_PointContents(p, 0); // or in contents from all the other entities num = SV_AreaEntities(p, p, touch, MAX_GENTITIES); for (i = 0; i < num; i++) { if (touch[i] == passEntityNum) { continue; } hit = SV_GentityNum(touch[i]); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity(hit); // non - worldspawn entities must not use world as clip model! if (clipHandle == 0) { continue; } c2 = CM_TransformedPointContents(p, clipHandle, hit->r.currentOrigin, hit->r.currentAngles); // s.origin/angles is base origin/angles, need to use the current origin/angles for moving entity based water, or water locks in movement start position. //c2 = CM_TransformedPointContents(p, clipHandle, hit->s.origin, hit->s.angles); contents |= c2; } return contents; }
/* ============= SV_PointContents ============= */ int SV_PointContents( const vec3_t p, int passEntityNum ) { int touch[MAX_GENTITIES]; sharedEntity_t *hit; int i, num; int contents, c2; clipHandle_t clipHandle; float *angles; // get base contents from world contents = CM_PointContents( p, 0 ); // or in contents from all the other entities num = SV_AreaEntities( p, p, touch, MAX_GENTITIES ); for ( i=0 ; i<num ; i++ ) { if ( touch[i] == passEntityNum ) { continue; } hit = SV_GentityNum( touch[i] ); // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity( hit ); angles = hit->r.currentAngles; if ( !hit->r.bmodel ) { angles = vec3_origin; // boxes don't rotate } c2 = CM_TransformedPointContents (p, clipHandle, hit->r.currentOrigin, angles); contents |= c2; } return contents; }
/* * SV_PointContents */ int SV_PointContents(const Vec3 p, int passEntityNum) { int touch[MAX_GENTITIES]; Sharedent *hit; int i, num; int contents, c2; Cliphandle clipHandle; float *angles; /* get base contents from world */ contents = CM_PointContents(p, 0); /* or in contents from all the other entities */ num = SV_AreaEntities(p, p, touch, MAX_GENTITIES); for(i=0; i<num; i++){ if(touch[i] == passEntityNum) continue; hit = SV_GentityNum(touch[i]); /* might intersect, so do an exact clip */ clipHandle = SV_ClipHandleForEntity(hit); angles = hit->r.currentAngles; if(!hit->r.bmodel) angles = vec3_origin; /* boxes don't rotate */ c2 = CM_TransformedPointContents (p, clipHandle, hit->r.currentOrigin, angles); contents |= c2; } return contents; }
/* ==================== SV_GameSystemCalls The module is making a system call ==================== */ intptr_t SV_GameSystemCalls(intptr_t * args) { switch (args[0]) { case G_PRINT: Com_Printf("%s", (char *)VMA(1)); return 0; case G_ERROR: Com_Error(ERR_DROP, "%s", (char *)VMA(1)); return 0; case G_MILLISECONDS: return Sys_Milliseconds(); case G_CVAR_REGISTER: Cvar_Register((vmCvar_t*)VMA(1), (char*)VMA(2), (char*)VMA(3), args[4]); return 0; case G_CVAR_UPDATE: Cvar_Update((vmCvar_t*)VMA(1)); return 0; case G_CVAR_SET: Cvar_Set((const char *)VMA(1), (const char *)VMA(2)); return 0; case G_CVAR_VARIABLE_INTEGER_VALUE: return Cvar_VariableIntegerValue((const char *)VMA(1)); case G_CVAR_VARIABLE_STRING_BUFFER: Cvar_VariableStringBuffer((char *)VMA(1), (char*)VMA(2), args[3]); return 0; case G_CVAR_LATCHEDVARIABLESTRINGBUFFER: Cvar_LatchedVariableStringBuffer((char *)VMA(1), (char*)VMA(2), args[3]); return 0; case G_ARGC: return Cmd_Argc(); case G_ARGV: Cmd_ArgvBuffer(args[1], (char*)VMA(2), args[3]); return 0; case G_SEND_CONSOLE_COMMAND: Cbuf_ExecuteText(args[1], (char *)VMA(2)); return 0; case G_FS_FOPEN_FILE: return FS_FOpenFileByMode((char *)VMA(1), (fileHandle_t*)VMA(2), (fsMode_t)args[3]); case G_FS_READ: FS_Read2(VMA(1), args[2], args[3]); return 0; case G_FS_WRITE: return FS_Write(VMA(1), args[2], args[3]); case G_FS_RENAME: FS_Rename((char *)VMA(1), (char *)VMA(2)); return 0; case G_FS_FCLOSE_FILE: FS_FCloseFile(args[1]); return 0; case G_FS_GETFILELIST: return FS_GetFileList((char *)VMA(1), (char *)VMA(2), (char*)VMA(3), args[4]); case G_LOCATE_GAME_DATA: SV_LocateGameData((sharedEntity_t*)VMA(1), args[2], args[3], (playerState_t*)VMA(4), args[5]); return 0; case G_DROP_CLIENT: SV_GameDropClient(args[1], (char*)VMA(2), args[3]); return 0; case G_SEND_SERVER_COMMAND: SV_GameSendServerCommand(args[1], (char*)VMA(2)); return 0; case G_LINKENTITY: SV_LinkEntity((sharedEntity_t*)VMA(1)); return 0; case G_UNLINKENTITY: SV_UnlinkEntity((sharedEntity_t*)VMA(1)); return 0; case G_ENTITIES_IN_BOX: return SV_AreaEntities((float*)VMA(1), (float*)VMA(2), (int*)VMA(3), args[4]); case G_ENTITY_CONTACT: return SV_EntityContact((float*)VMA(1), (float*)VMA(2), (sharedEntity_t*)VMA(3), TT_AABB); case G_ENTITY_CONTACTCAPSULE: return SV_EntityContact((float*)VMA(1), (float*)VMA(2), (sharedEntity_t*)VMA(3), TT_CAPSULE); case G_TRACE: SV_Trace((trace_t*)VMA(1), (float*)VMA(2), (float*)VMA(3), (float*)VMA(4), (float*)VMA(5), args[6], args[7], TT_AABB); return 0; case G_TRACECAPSULE: SV_Trace((trace_t*)VMA(1), (float*)VMA(2), (float*)VMA(3), (float*)VMA(4), (float*)VMA(5), args[6], args[7], TT_CAPSULE); return 0; case G_POINT_CONTENTS: return SV_PointContents((float*)VMA(1), args[2]); case G_SET_BRUSH_MODEL: SV_SetBrushModel((sharedEntity_t*)VMA(1), (char*)VMA(2)); return 0; case G_IN_PVS: return SV_inPVS((float*)VMA(1), (float*)VMA(2)); case G_IN_PVS_IGNORE_PORTALS: return SV_inPVSIgnorePortals((float*)VMA(1), (float*)VMA(2)); case G_SET_CONFIGSTRING: SV_SetConfigstring(args[1], (char*)VMA(2)); return 0; case G_GET_CONFIGSTRING: SV_GetConfigstring(args[1], (char*)VMA(2), args[3]); return 0; case G_SET_CONFIGSTRING_RESTRICTIONS: SV_SetConfigstringRestrictions( args[1], (clientList_t*)VMA(2) ); return 0; case G_SET_USERINFO: SV_SetUserinfo(args[1], (char*)VMA(2)); return 0; case G_GET_USERINFO: SV_GetUserinfo(args[1], (char*)VMA(2), args[3]); return 0; case G_GET_SERVERINFO: SV_GetServerinfo((char*)VMA(1), args[2]); return 0; case G_ADJUST_AREA_PORTAL_STATE: SV_AdjustAreaPortalState((sharedEntity_t*)VMA(1),(bool)args[2]); return 0; case G_AREAS_CONNECTED: return CM_AreasConnected(args[1], args[2]); case G_UPDATE_SHARED_CONFIG: SV_UpdateSharedConfig( args[1], (char*)VMA(2) ); return 0; case G_BOT_ALLOCATE_CLIENT: return SV_BotAllocateClient(args[1]); case G_BOT_FREE_CLIENT: SV_BotFreeClient(args[1]); return 0; case G_GET_USERCMD: SV_GetUsercmd(args[1], (usercmd_t*)VMA(2)); return 0; case G_GET_ENTITY_TOKEN: { const char *s; s = COM_Parse(&sv.entityParsePoint); Q_strncpyz((char*)VMA(1), s, args[2]); if(!sv.entityParsePoint && !s[0]) { return false; } else { return true; } } case G_DEBUG_POLYGON_CREATE: return BotImport_DebugPolygonCreate(args[1], args[2], (vec3_t*)VMA(3)); case G_DEBUG_POLYGON_DELETE: BotImport_DebugPolygonDelete(args[1]); return 0; case G_REAL_TIME: return Com_RealTime((qtime_t*)VMA(1)); case G_SNAPVECTOR: Q_SnapVector((float*)VMA(1)); return 0; case G_SEND_GAMESTAT: SV_MasterGameStat( (char*)VMA(1) ); return 0; case G_ADDCOMMAND: Cmd_AddCommand( (char*)VMA(1), NULL, (char*)VMA(3) ); return 0; case G_REMOVECOMMAND: Cmd_RemoveCommand( (char*)VMA(1) ); return 0; case G_GETTAG: return SV_GetTag(args[1], args[2], (char*)VMA(3), (orientation_t*)VMA(4)); case G_REGISTERTAG: return SV_LoadTag((char*)VMA(1)); case G_REGISTERSOUND: return S_RegisterSound((char*)VMA(1), (bool)args[2]); case G_GET_SOUND_LENGTH: return S_GetSoundLength(args[1]); case G_PARSE_ADD_GLOBAL_DEFINE: return Parse_AddGlobalDefine( (char*)VMA(1) ); case G_PARSE_LOAD_SOURCE: return Parse_LoadSourceHandle( (char*)VMA(1) ); case G_PARSE_FREE_SOURCE: return Parse_FreeSourceHandle( args[1] ); case G_PARSE_READ_TOKEN: return Parse_ReadTokenHandle( args[1], (pc_token_t*)VMA(2) ); case G_PARSE_SOURCE_FILE_AND_LINE: return Parse_SourceFileAndLine( args[1], (char*)VMA(2), (int*)VMA(3) ); case BOTLIB_SETUP: return SV_BotLibSetup(); case BOTLIB_SHUTDOWN: return SV_BotLibShutdown(); case BOTLIB_LIBVAR_SET: return botlib_export->BotLibVarSet((char*)VMA(1), (char*)VMA(2)); case BOTLIB_LIBVAR_GET: return botlib_export->BotLibVarGet((char*)VMA(1), (char*)VMA(2), args[3]); case BOTLIB_PC_ADD_GLOBAL_DEFINE: return Parse_AddGlobalDefine( (char*)VMA(1) ); case BOTLIB_PC_LOAD_SOURCE: return Parse_LoadSourceHandle((char*)VMA(1)); case BOTLIB_PC_FREE_SOURCE: return Parse_FreeSourceHandle(args[1]); case BOTLIB_PC_READ_TOKEN: return Parse_ReadTokenHandle(args[1], (pc_token_t*)VMA(2)); case BOTLIB_PC_SOURCE_FILE_AND_LINE: return Parse_SourceFileAndLine(args[1], (char*)VMA(2), (int*)VMA(3)); case BOTLIB_PC_UNREAD_TOKEN: Parse_UnreadLastTokenHandle(args[1]); return 0; case BOTLIB_START_FRAME: return botlib_export->BotLibStartFrame(VMF(1)); case BOTLIB_LOAD_MAP: return botlib_export->BotLibLoadMap((char*)VMA(1)); case BOTLIB_UPDATENTITY: return botlib_export->BotLibUpdateEntity(args[1], (bot_entitystate_t*)VMA(2)); case BOTLIB_TEST: return botlib_export->Test( args[1], (char*)VMA(2), (float*)VMA(3), (float*)VMA(4) ); case BOTLIB_GET_SNAPSHOT_ENTITY: return SV_BotGetSnapshotEntity(args[1], args[2]); case BOTLIB_GET_CONSOLE_MESSAGE: return SV_BotGetConsoleMessage(args[1], (char*)VMA(2), args[3]); case BOTLIB_USER_COMMAND: SV_ClientThink(&svs.clients[args[1]], (usercmd_t*)VMA(2)); return 0; case BOTLIB_AAS_ENTITY_INFO: botlib_export->aas.AAS_EntityInfo(args[1], (aas_entityinfo_s*)VMA(2)); return 0; case BOTLIB_AAS_INITIALIZED: return botlib_export->aas.AAS_Initialized(); case BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX: botlib_export->aas.AAS_PresenceTypeBoundingBox( args[1], (float*)VMA(2), (float*)VMA(3) ); return 0; case BOTLIB_AAS_TIME: return FloatAsInt(botlib_export->aas.AAS_Time()); case BOTLIB_AAS_SETCURRENTWORLD: botlib_export->aas.AAS_SetCurrentWorld(args[1]); return 0; case BOTLIB_AAS_POINT_AREA_NUM: return botlib_export->aas.AAS_PointAreaNum( (float*)VMA(1) ); case BOTLIB_AAS_TRACE_AREAS: return botlib_export->aas.AAS_TraceAreas( (float*)VMA(1), (float*)VMA(2), (int*)VMA(3), (vec3_t*)VMA(4), args[5] ); case BOTLIB_AAS_BBOX_AREAS: return botlib_export->aas.AAS_BBoxAreas( (float*)VMA(1), (float*)VMA(2), (int*)VMA(3), args[4] ); case BOTLIB_AAS_AREA_CENTER: botlib_export->aas.AAS_AreaCenter(args[1], (float*)VMA(2)); return 0; case BOTLIB_AAS_AREA_WAYPOINT: return botlib_export->aas.AAS_AreaWaypoint(args[1], (float*)VMA(2)); case BOTLIB_AAS_POINT_CONTENTS: return botlib_export->aas.AAS_PointContents((float*)VMA(1)); case BOTLIB_AAS_NEXT_BSP_ENTITY: return botlib_export->aas.AAS_NextBSPEntity(args[1]); case BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY: return botlib_export->aas.AAS_ValueForBSPEpairKey(args[1], (char*)VMA(2), (char*)VMA(3), args[4]); case BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY: return botlib_export->aas.AAS_VectorForBSPEpairKey(args[1], (char*)VMA(2), (float*)VMA(3)); case BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY: return botlib_export->aas.AAS_FloatForBSPEpairKey(args[1], (char*)VMA(2), (float*)VMA(3)); case BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY: return botlib_export->aas.AAS_IntForBSPEpairKey(args[1], (char*)VMA(2), (int*)VMA(3)); case BOTLIB_AAS_AREA_REACHABILITY: return botlib_export->aas.AAS_AreaReachability(args[1]); case BOTLIB_AAS_AREA_LADDER: return botlib_export->aas.AAS_AreaLadder(args[1]); case BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA: return botlib_export->aas.AAS_AreaTravelTimeToGoalArea(args[1], (float*)VMA(2), args[3], args[4]); case BOTLIB_AAS_SWIMMING: return botlib_export->aas.AAS_Swimming((float*)VMA(1)); case BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT: return botlib_export->aas.AAS_PredictClientMovement((aas_clientmove_s*)VMA(1), args[2], (float*)VMA(3), args[4], args[5], (float*)VMA(6), (float*)VMA(7), args[8], args[9], VMF(10), args[11], args[12], args[13]); case BOTLIB_AAS_RT_SHOWROUTE: botlib_export->aas.AAS_RT_ShowRoute((float*)VMA(1), args[2], args[3]); return 0; case BOTLIB_AAS_NEARESTHIDEAREA: return botlib_export->aas.AAS_NearestHideArea(args[1], (float*)VMA(2), args[3], args[4], (float*)VMA(5), args[6], args[7], VMF(8), (float*)VMA(9)); case BOTLIB_AAS_LISTAREASINRANGE: return botlib_export->aas.AAS_ListAreasInRange((float*)VMA(1), args[2], VMF(3), args[4], (vec3_t*)VMA(5), args[6]); case BOTLIB_AAS_AVOIDDANGERAREA: return botlib_export->aas.AAS_AvoidDangerArea((float*)VMA(1), args[2], (float*)VMA(3), args[4], VMF(5), args[6]); case BOTLIB_AAS_RETREAT: return botlib_export->aas.AAS_Retreat((int*)VMA(1), args[2], (float*)VMA(3), args[4], (float*)VMA(5), args[6], VMF(7), VMF(8), args[9]); case BOTLIB_AAS_ALTROUTEGOALS: return botlib_export->aas.AAS_AlternativeRouteGoals((float*)VMA(1), (float*)VMA(2), args[3], (aas_altroutegoal_t*)VMA(4), args[5], args[6]); case BOTLIB_AAS_SETAASBLOCKINGENTITY: botlib_export->aas.AAS_SetAASBlockingEntity((float*)VMA(1), (float*)VMA(2), args[3]); return 0; case BOTLIB_AAS_RECORDTEAMDEATHAREA: botlib_export->aas.AAS_RecordTeamDeathArea((float*)VMA(1), args[2], args[3], args[4], args[5]); return 0; case BOTLIB_EA_SAY: botlib_export->ea.EA_Say(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_SAY_TEAM: botlib_export->ea.EA_SayTeam(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_USE_ITEM: botlib_export->ea.EA_UseItem(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_DROP_ITEM: botlib_export->ea.EA_DropItem(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_USE_INV: botlib_export->ea.EA_UseInv(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_DROP_INV: botlib_export->ea.EA_DropInv(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_GESTURE: botlib_export->ea.EA_Gesture(args[1]); return 0; case BOTLIB_EA_COMMAND: botlib_export->ea.EA_Command(args[1], (char*)VMA(2)); return 0; case BOTLIB_EA_SELECT_WEAPON: botlib_export->ea.EA_SelectWeapon(args[1], args[2]); return 0; case BOTLIB_EA_TALK: botlib_export->ea.EA_Talk(args[1]); return 0; case BOTLIB_EA_ATTACK: botlib_export->ea.EA_Attack(args[1]); return 0; case BOTLIB_EA_RELOAD: botlib_export->ea.EA_Reload(args[1]); return 0; case BOTLIB_EA_USE: botlib_export->ea.EA_Use(args[1]); return 0; case BOTLIB_EA_RESPAWN: botlib_export->ea.EA_Respawn(args[1]); return 0; case BOTLIB_EA_JUMP: botlib_export->ea.EA_Jump(args[1]); return 0; case BOTLIB_EA_DELAYED_JUMP: botlib_export->ea.EA_DelayedJump(args[1]); return 0; case BOTLIB_EA_CROUCH: botlib_export->ea.EA_Crouch(args[1]); return 0; case BOTLIB_EA_WALK: botlib_export->ea.EA_Walk(args[1]); return 0; case BOTLIB_EA_MOVE_UP: botlib_export->ea.EA_MoveUp(args[1]); return 0; case BOTLIB_EA_MOVE_DOWN: botlib_export->ea.EA_MoveDown(args[1]); return 0; case BOTLIB_EA_MOVE_FORWARD: botlib_export->ea.EA_MoveForward(args[1]); return 0; case BOTLIB_EA_MOVE_BACK: botlib_export->ea.EA_MoveBack(args[1]); return 0; case BOTLIB_EA_MOVE_LEFT: botlib_export->ea.EA_MoveLeft(args[1]); return 0; case BOTLIB_EA_MOVE_RIGHT: botlib_export->ea.EA_MoveRight(args[1]); return 0; case BOTLIB_EA_MOVE: botlib_export->ea.EA_Move(args[1], (float*)VMA(2), VMF(3)); return 0; case BOTLIB_EA_VIEW: botlib_export->ea.EA_View(args[1], (float*)VMA(2)); return 0; case BOTLIB_EA_PRONE: botlib_export->ea.EA_Prone(args[1]); return 0; case BOTLIB_EA_END_REGULAR: botlib_export->ea.EA_EndRegular(args[1], VMF(2)); return 0; case BOTLIB_EA_GET_INPUT: botlib_export->ea.EA_GetInput(args[1], VMF(2), (bot_input_t*)VMA(3)); return 0; case BOTLIB_EA_RESET_INPUT: botlib_export->ea.EA_ResetInput(args[1], (bot_input_t*)VMA(2)); return 0; case BOTLIB_AI_LOAD_CHARACTER: return botlib_export->ai.BotLoadCharacter((char*)VMA(1), args[2]); case BOTLIB_AI_FREE_CHARACTER: botlib_export->ai.BotFreeCharacter(args[1]); return 0; case BOTLIB_AI_CHARACTERISTIC_FLOAT: return FloatAsInt(botlib_export->ai.Characteristic_Float(args[1], args[2])); case BOTLIB_AI_CHARACTERISTIC_BFLOAT: return FloatAsInt(botlib_export->ai.Characteristic_BFloat(args[1], args[2], VMF(3), VMF(4))); case BOTLIB_AI_CHARACTERISTIC_INTEGER: return botlib_export->ai.Characteristic_Integer(args[1], args[2]); case BOTLIB_AI_CHARACTERISTIC_BINTEGER: return botlib_export->ai.Characteristic_BInteger(args[1], args[2], args[3], args[4]); case BOTLIB_AI_CHARACTERISTIC_STRING: botlib_export->ai.Characteristic_String(args[1], args[2], (char*)VMA(3), args[4]); return 0; case BOTLIB_AI_ALLOC_CHAT_STATE: return botlib_export->ai.BotAllocChatState(); case BOTLIB_AI_FREE_CHAT_STATE: botlib_export->ai.BotFreeChatState(args[1]); return 0; case BOTLIB_AI_QUEUE_CONSOLE_MESSAGE: botlib_export->ai.BotQueueConsoleMessage(args[1], args[2], (char*)VMA(3)); return 0; case BOTLIB_AI_REMOVE_CONSOLE_MESSAGE: botlib_export->ai.BotRemoveConsoleMessage(args[1], args[2]); return 0; case BOTLIB_AI_NEXT_CONSOLE_MESSAGE: return botlib_export->ai.BotNextConsoleMessage(args[1], (bot_consolemessage_s*)VMA(2)); case BOTLIB_AI_NUM_CONSOLE_MESSAGE: return botlib_export->ai.BotNumConsoleMessages(args[1]); case BOTLIB_AI_INITIAL_CHAT: botlib_export->ai.BotInitialChat(args[1], (char*)VMA(2), args[3], (char*)VMA(4), (char*)VMA(5), (char*)VMA(6), (char*)VMA(7), (char*)VMA(8), (char*)VMA(9), (char*)VMA(10), (char*)VMA(11)); return 0; case BOTLIB_AI_NUM_INITIAL_CHATS: return botlib_export->ai.BotNumInitialChats(args[1], (char*)VMA(2)); case BOTLIB_AI_REPLY_CHAT: return botlib_export->ai.BotReplyChat(args[1], (char*)VMA(2), args[3], args[4], (char*)VMA(5), (char*)VMA(6), (char*)VMA(7), (char*)VMA(8), (char*)VMA(9), (char*)VMA(10), (char*)VMA(11), (char*)VMA(12)); case BOTLIB_AI_CHAT_LENGTH: return botlib_export->ai.BotChatLength(args[1]); case BOTLIB_AI_ENTER_CHAT: botlib_export->ai.BotEnterChat(args[1], args[2], args[3]); return 0; case BOTLIB_AI_GET_CHAT_MESSAGE: botlib_export->ai.BotGetChatMessage(args[1], (char*)VMA(2), args[3]); return 0; case BOTLIB_AI_STRING_CONTAINS: return botlib_export->ai.StringContains((char*)VMA(1), (char*)VMA(2), args[3]); case BOTLIB_AI_FIND_MATCH: return botlib_export->ai.BotFindMatch((char*)VMA(1), (bot_match_s*)VMA(2), args[3]); case BOTLIB_AI_MATCH_VARIABLE: botlib_export->ai.BotMatchVariable((bot_match_s*)VMA(1), args[2], (char*)VMA(3), args[4]); return 0; case BOTLIB_AI_UNIFY_WHITE_SPACES: botlib_export->ai.UnifyWhiteSpaces((char*)VMA(1)); return 0; case BOTLIB_AI_REPLACE_SYNONYMS: botlib_export->ai.BotReplaceSynonyms((char*)VMA(1), args[2]); return 0; case BOTLIB_AI_LOAD_CHAT_FILE: return botlib_export->ai.BotLoadChatFile(args[1], (char*)VMA(2), (char*)VMA(3)); case BOTLIB_AI_SET_CHAT_GENDER: botlib_export->ai.BotSetChatGender(args[1], args[2]); return 0; case BOTLIB_AI_SET_CHAT_NAME: botlib_export->ai.BotSetChatName(args[1], (char*)VMA(2)); return 0; case BOTLIB_AI_RESET_GOAL_STATE: botlib_export->ai.BotResetGoalState(args[1]); return 0; case BOTLIB_AI_RESET_AVOID_GOALS: botlib_export->ai.BotResetAvoidGoals(args[1]); return 0; case BOTLIB_AI_REMOVE_FROM_AVOID_GOALS: botlib_export->ai.BotRemoveFromAvoidGoals(args[1], args[2]); return 0; case BOTLIB_AI_PUSH_GOAL: botlib_export->ai.BotPushGoal(args[1], (bot_goal_s*)VMA(2)); return 0; case BOTLIB_AI_POP_GOAL: botlib_export->ai.BotPopGoal(args[1]); return 0; case BOTLIB_AI_EMPTY_GOAL_STACK: botlib_export->ai.BotEmptyGoalStack(args[1]); return 0; case BOTLIB_AI_DUMP_AVOID_GOALS: botlib_export->ai.BotDumpAvoidGoals(args[1]); return 0; case BOTLIB_AI_DUMP_GOAL_STACK: botlib_export->ai.BotDumpGoalStack(args[1]); return 0; case BOTLIB_AI_GOAL_NAME: botlib_export->ai.BotGoalName(args[1], (char*)VMA(2), args[3]); return 0; case BOTLIB_AI_GET_TOP_GOAL: return botlib_export->ai.BotGetTopGoal(args[1], (bot_goal_s*)VMA(2)); case BOTLIB_AI_GET_SECOND_GOAL: return botlib_export->ai.BotGetSecondGoal(args[1], (bot_goal_s*)VMA(2)); case BOTLIB_AI_CHOOSE_LTG_ITEM: return botlib_export->ai.BotChooseLTGItem(args[1], (float*)VMA(2), (int*)VMA(3), args[4]); case BOTLIB_AI_CHOOSE_NBG_ITEM: return botlib_export->ai.BotChooseNBGItem(args[1], (float*)VMA(2), (int*)VMA(3), args[4], (bot_goal_s*)VMA(5), VMF(6)); case BOTLIB_AI_TOUCHING_GOAL: return botlib_export->ai.BotTouchingGoal((float*)VMA(1), (bot_goal_s*)VMA(2)); case BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE: return botlib_export->ai.BotItemGoalInVisButNotVisible(args[1], (float*)VMA(2), (float*)VMA(3), (bot_goal_s*)VMA(4)); case BOTLIB_AI_GET_LEVEL_ITEM_GOAL: return botlib_export->ai.BotGetLevelItemGoal(args[1], (char*)VMA(2), (bot_goal_s*)VMA(3)); case BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL: return botlib_export->ai.BotGetNextCampSpotGoal(args[1], (bot_goal_s*)VMA(2)); case BOTLIB_AI_GET_MAP_LOCATION_GOAL: return botlib_export->ai.BotGetMapLocationGoal((char*)VMA(1), (bot_goal_s*)VMA(2)); case BOTLIB_AI_AVOID_GOAL_TIME: return FloatAsInt(botlib_export->ai.BotAvoidGoalTime(args[1], args[2])); case BOTLIB_AI_INIT_LEVEL_ITEMS: botlib_export->ai.BotInitLevelItems(); return 0; case BOTLIB_AI_UPDATE_ENTITY_ITEMS: botlib_export->ai.BotUpdateEntityItems(); return 0; case BOTLIB_AI_LOAD_ITEM_WEIGHTS: return botlib_export->ai.BotLoadItemWeights(args[1], (char*)VMA(2)); case BOTLIB_AI_FREE_ITEM_WEIGHTS: botlib_export->ai.BotFreeItemWeights(args[1]); return 0; case BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC: botlib_export->ai.BotInterbreedGoalFuzzyLogic(args[1], args[2], args[3]); return 0; case BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC: botlib_export->ai.BotSaveGoalFuzzyLogic(args[1], (char*)VMA(2)); return 0; case BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC: botlib_export->ai.BotMutateGoalFuzzyLogic(args[1], VMF(2)); return 0; case BOTLIB_AI_ALLOC_GOAL_STATE: return botlib_export->ai.BotAllocGoalState(args[1]); case BOTLIB_AI_FREE_GOAL_STATE: botlib_export->ai.BotFreeGoalState(args[1]); return 0; case BOTLIB_AI_RESET_MOVE_STATE: botlib_export->ai.BotResetMoveState(args[1]); return 0; case BOTLIB_AI_MOVE_TO_GOAL: botlib_export->ai.BotMoveToGoal((bot_moveresult_s*)VMA(1), args[2], (bot_goal_s*)VMA(3), args[4]); return 0; case BOTLIB_AI_MOVE_IN_DIRECTION: return botlib_export->ai.BotMoveInDirection(args[1], (float*)VMA(2), VMF(3), args[4]); case BOTLIB_AI_RESET_AVOID_REACH: botlib_export->ai.BotResetAvoidReach(args[1]); return 0; case BOTLIB_AI_RESET_LAST_AVOID_REACH: botlib_export->ai.BotResetLastAvoidReach(args[1]); return 0; case BOTLIB_AI_REACHABILITY_AREA: return botlib_export->ai.BotReachabilityArea((float*)VMA(1), args[2]); case BOTLIB_AI_MOVEMENT_VIEW_TARGET: return botlib_export->ai.BotMovementViewTarget(args[1], (bot_goal_s*)VMA(2), args[3], VMF(4), (float*)VMA(5)); case BOTLIB_AI_PREDICT_VISIBLE_POSITION: return botlib_export->ai.BotPredictVisiblePosition((float*)VMA(1), args[2], (bot_goal_s*)VMA(3), args[4], (vec_t*)VMA(5)); case BOTLIB_AI_ALLOC_MOVE_STATE: return botlib_export->ai.BotAllocMoveState(); case BOTLIB_AI_FREE_MOVE_STATE: botlib_export->ai.BotFreeMoveState(args[1]); return 0; case BOTLIB_AI_INIT_MOVE_STATE: botlib_export->ai.BotInitMoveState(args[1], (bot_initmove_s*)VMA(2)); return 0; case BOTLIB_AI_INIT_AVOID_REACH: botlib_export->ai.BotInitAvoidReach(args[1]); return 0; case BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON: return botlib_export->ai.BotChooseBestFightWeapon(args[1], (int*)VMA(2)); case BOTLIB_AI_GET_WEAPON_INFO: botlib_export->ai.BotGetWeaponInfo(args[1], args[2], (weaponinfo_s*)VMA(3)); return 0; case BOTLIB_AI_LOAD_WEAPON_WEIGHTS: return botlib_export->ai.BotLoadWeaponWeights(args[1], (char*)VMA(2)); case BOTLIB_AI_ALLOC_WEAPON_STATE: return botlib_export->ai.BotAllocWeaponState(); case BOTLIB_AI_FREE_WEAPON_STATE: botlib_export->ai.BotFreeWeaponState(args[1]); return 0; case BOTLIB_AI_RESET_WEAPON_STATE: botlib_export->ai.BotResetWeaponState(args[1]); return 0; case BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION: return botlib_export->ai.GeneticParentsAndChildSelection(args[1], (float*)VMA(2), (int*)VMA(3), (int*)VMA(4), (int*)VMA(5)); case G_ADD_PHYSICS_ENTITY: #ifdef USE_PHYSICS CMod_PhysicsAddEntity((sharedEntity_t*)VMA(1)); #endif return 0; case G_ADD_PHYSICS_STATIC: #ifdef USE_PHYSICS CMod_PhysicsAddStatic((sharedEntity_t*)VMA(1)); #endif return 0; case TRAP_MEMSET: memset(VMA(1), args[2], args[3]); return 0; case TRAP_MEMCPY: memcpy(VMA(1), VMA(2), args[3]); return 0; case TRAP_STRNCPY: return (intptr_t)strncpy( (char*)VMA( 1 ), (char*)VMA( 2 ), args[3] ); case TRAP_SIN: return FloatAsInt(sin(VMF(1))); case TRAP_COS: return FloatAsInt(cos(VMF(1))); case TRAP_ATAN2: return FloatAsInt(atan2(VMF(1), VMF(2))); case TRAP_SQRT: return FloatAsInt(sqrt(VMF(1))); case TRAP_MATRIXMULTIPLY: AxisMultiply((vec3_t*)VMA(1), (vec3_t*)VMA(2), (vec3_t*)VMA(3)); return 0; case TRAP_ANGLEVECTORS: AngleVectors((vec_t*)VMA(1), (vec_t*)VMA(2), (vec_t*)VMA(3), (vec_t*)VMA(4)); return 0; case TRAP_PERPENDICULARVECTOR: PerpendicularVector((vec_t*)VMA(1), (vec_t*)VMA(2)); return 0; case TRAP_FLOOR: return FloatAsInt(floor(VMF(1))); case TRAP_CEIL: return FloatAsInt(ceil(VMF(1))); case G_SENDMESSAGE: SV_SendBinaryMessage(args[1], (char*)VMA(2), args[3]); return 0; case G_MESSAGESTATUS: return SV_BinaryMessageStatus(args[1]); #if defined(ET_MYSQL) case G_SQL_RUNQUERY: return OW_RunQuery( (char*)VMA(1) ); case G_SQL_FINISHQUERY: OW_FinishQuery( args[1] ); return 0; case G_SQL_NEXTROW: return OW_NextRow( args[1] ); case G_SQL_ROWCOUNT: return OW_RowCount( args[1] ); case G_SQL_GETFIELDBYID: OW_GetFieldByID( args[1], args[2], (char*)VMA(3), args[4] ); return 0; case G_SQL_GETFIELDBYNAME: OW_GetFieldByName( args[1], (char*)VMA(2), (char*)VMA(3), args[4] ); return 0; case G_SQL_GETFIELDBYID_INT: return OW_GetFieldByID_int( args[1], args[2] ); case G_SQL_GETFIELDBYNAME_INT: return OW_GetFieldByName_int( args[1], (char*)VMA(2) ); case G_SQL_FIELDCOUNT: return OW_FieldCount( args[1] ); case G_SQL_CLEANSTRING: OW_CleanString( (char*)VMA(1), (char*)VMA(2), args[3] ); return 0; #endif case G_RSA_GENMSG: return SV_RSAGenMsg( (char*)VMA(1), (char*)VMA(2), (char*)VMA(3) ); default: Com_Error( ERR_DROP, "Bad game system trap: %ld", (long int) args[0] ); } return -1; }
/* ==================== SV_ClipMoveToEntities ==================== */ static void SV_ClipMoveToEntities( moveclip_t *clip ) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; float *origin, *angles; num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES); if ( clip->passEntityNum != ENTITYNUM_NONE ) { passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum; if ( passOwnerNum == ENTITYNUM_NONE ) { passOwnerNum = -1; } } else { passOwnerNum = -1; } for ( i=0 ; i<num ; i++ ) { if ( clip->trace.allsolid ) { return; } touch = SV_GentityNum( touchlist[i] ); // see if we should ignore this entity if ( clip->passEntityNum != ENTITYNUM_NONE ) { if ( touchlist[i] == clip->passEntityNum ) { continue; // don't clip against the pass entity } if ( !(touch->r.svFlags & SVF_OWNERNOTSHARED) && touch->r.ownerNum == clip->passEntityNum ) { continue; // don't clip against own missiles } if ( !(touch->r.svFlags & SVF_OWNERNOTSHARED) && touch->r.ownerNum == passOwnerNum ) { continue; // don't clip against other missiles from our owner } } // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( clip->contentmask & touch->r.contents ) ) { continue; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity (touch); if ( clipHandle == 0 ) { continue; } origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if ( !touch->r.bmodel ) { angles = vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); if ( trace.allsolid ) { clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; } else if ( trace.startsolid ) { clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; } if ( trace.fraction < clip->trace.fraction ) { qboolean oldStart; // make sure we keep a startsolid from a previous trace oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid |= oldStart; } } }
/* ======================================================================================================================================= SV_ClipMoveToEntities ======================================================================================================================================= */ void SV_ClipMoveToEntities(moveclip_t *clip) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; float *origin, *angles; num = SV_AreaEntities(clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES); if (clip->passEntityNum != ENTITYNUM_NONE) { passOwnerNum = (SV_GentityNum(clip->passEntityNum))->r.ownerNum; if (passOwnerNum == ENTITYNUM_NONE) { passOwnerNum = -1; } } else { passOwnerNum = -1; } for (i = 0; i < num; i++) { if (clip->trace.allsolid) { return; } touch = SV_GentityNum(touchlist[i]); // see if we should ignore this entity if (clip->passEntityNum != ENTITYNUM_NONE) { if (touchlist[i] == clip->passEntityNum) { continue; // don't clip against the pass entity } if (touch->r.ownerNum == clip->passEntityNum) { continue; // don't clip against own missiles } if (touch->r.ownerNum == passOwnerNum) { continue; // don't clip against other missiles from our owner } } // if it doesn't have any brushes of a type we are looking for, ignore it if (!(clip->contentmask & touch->r.contents)) { continue; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity(touch); // non-worldspawn entities must not use world as clip model! if (clipHandle == 0) { continue; } // if clipping against BBOX, set to correct contents if (clipHandle == BOX_MODEL_HANDLE) { CM_SetTempBoxModelContents(touch->r.contents); } origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if (!touch->r.bmodel) { angles = vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace(&trace, clip->start, clip->end, clip->mins, clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); if (trace.allsolid) { clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; } else if (trace.startsolid) { clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; } if (trace.fraction < clip->trace.fraction) { // make sure we keep a startsolid from a previous trace qboolean oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid |= oldStart; } // reset contents to default if (clipHandle == BOX_MODEL_HANDLE) { CM_SetTempBoxModelContents(CONTENTS_BODY); } } }
/* ==================== SV_ClipMoveToEntities ==================== */ void SV_ClipMoveToEntities( moveclip_t *clip ) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace, oldTrace; clipHandle_t clipHandle; float *origin, *angles; int thisOwnerShared = 1; num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES); if ( clip->passEntityNum != ENTITYNUM_NONE ) { passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum; if ( passOwnerNum == ENTITYNUM_NONE ) { passOwnerNum = -1; } } else { passOwnerNum = -1; } if ( SV_GentityNum(clip->passEntityNum)->r.svFlags & SVF_OWNERNOTSHARED ) { thisOwnerShared = 0; } for ( i=0 ; i<num ; i++ ) { if ( clip->trace.allsolid ) { return; } touch = SV_GentityNum( touchlist[i] ); // see if we should ignore this entity if ( clip->passEntityNum != ENTITYNUM_NONE ) { if ( touchlist[i] == clip->passEntityNum ) { continue; // don't clip against the pass entity } if ( touch->r.ownerNum == clip->passEntityNum) { if (touch->r.svFlags & SVF_OWNERNOTSHARED) { if ( clip->contentmask != (MASK_SHOT | CONTENTS_LIGHTSABER) && clip->contentmask != (MASK_SHOT)) { //it's not a laser hitting the other "missile", don't care then continue; } } else { continue; // don't clip against own missiles } } if ( touch->r.ownerNum == passOwnerNum && !(touch->r.svFlags & SVF_OWNERNOTSHARED) && !thisOwnerShared ) { continue; // don't clip against other missiles from our owner } } // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( clip->contentmask & touch->r.contents ) ) { continue; } if ((clip->contentmask == (MASK_SHOT|CONTENTS_LIGHTSABER) || clip->contentmask == MASK_SHOT) && (touch->r.contents > 0 && (touch->r.contents & CONTENTS_NOSHOT))) { continue; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity (touch); origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if ( !touch->r.bmodel ) { angles = vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); /* Ghoul2 Insert Start */ // keep these older variables around for a bit, incase we need to replace them in the Ghoul2 Collision check oldTrace = clip->trace; /* Ghoul2 Insert End */ if ( trace.allsolid ) { clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; } else if ( trace.startsolid ) { clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; } if ( trace.fraction < clip->trace.fraction ) { qboolean oldStart; // make sure we keep a startsolid from a previous trace oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid = (qboolean)((unsigned)clip->trace.startsolid | (unsigned)oldStart); } /* Ghoul2 Insert Start */ #if 0 // decide if we should do the ghoul2 collision detection right here if ((trace.entityNum == touch->s.number) && (clip->traceFlags)) { // do we actually have a ghoul2 model here? if (touch->s.ghoul2) { int oldTraceRecSize = 0; int newTraceRecSize = 0; int z; // we have to do this because sometimes you may hit a model's bounding box, but not actually penetrate the Ghoul2 Models polygons // this is, needless to say, not good. So we must check to see if we did actually hit the model, and if not, reset the trace stuff // to what it was to begin with // set our trace record size for (z=0;z<MAX_G2_COLLISIONS;z++) { if (clip->trace.G2CollisionMap[z].mEntityNum != -1) { oldTraceRecSize++; } } G2API_CollisionDetect(&clip->trace.G2CollisionMap[0], *((CGhoul2Info_v *)touch->s.ghoul2), touch->s.angles, touch->s.origin, svs.time, touch->s.number, clip->start, clip->end, touch->s.modelScale, G2VertSpaceServer, clip->traceFlags, clip->useLod); // set our new trace record size for (z=0;z<MAX_G2_COLLISIONS;z++) { if (clip->trace.G2CollisionMap[z].mEntityNum != -1) { newTraceRecSize++; } } // did we actually touch this model? If not, lets reset this ent as being hit.. if (newTraceRecSize == oldTraceRecSize) { clip->trace = oldTrace; } } } #endif /* Ghoul2 Insert End */ } }
static void SV_ClipMoveToEntities( moveclip_t *clip ) { int i, num; int touchlist[MAX_GENTITIES]; sharedEntity_t *touch; int passOwnerNum; trace_t trace; clipHandle_t clipHandle; vector3 *origin, *angles; num = SV_AreaEntities( &clip->boxmins, &clip->boxmaxs, touchlist, MAX_GENTITIES); if ( clip->passEntityNum != ENTITYNUM_NONE ) { passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum; if ( passOwnerNum == ENTITYNUM_NONE ) { passOwnerNum = -1; } } else { passOwnerNum = -1; } for ( i=0 ; i<num ; i++ ) { if ( clip->trace.allsolid ) { return; } touch = SV_GentityNum( touchlist[i] ); // see if we should ignore this entity if ( clip->passEntityNum != ENTITYNUM_NONE ) { if ( touchlist[i] == clip->passEntityNum ) { continue; // don't clip against the pass entity } //QTZTODO: Missiles colliding with eachother from https://github.com/dmead/jkaq3/commit/1d1e1fefb04fab8ceb42537702d946c1a75f4812 if ( touch->r.ownerNum == clip->passEntityNum // don't clip against own missiles || touch->r.ownerNum == passOwnerNum ) // don't clip against other missiles from our owner continue; } // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( clip->contentmask & touch->r.contents ) ) { continue; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity (touch); origin = &touch->r.currentOrigin; angles = &touch->r.currentAngles; if ( !touch->r.bmodel ) { angles = &vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace( &trace, (vector3 *)clip->start, &clip->end, (vector3 *)clip->mins, (vector3 *)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule ); if ( trace.allsolid ) { clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; } else if ( trace.startsolid ) { clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; } if ( trace.fraction < clip->trace.fraction ) { qboolean oldStart; // make sure we keep a startsolid from a previous trace oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid |= oldStart; } } }
static void SV_ClipMoveToEntities( moveclip_t *clip ) { static int touchlist[MAX_GENTITIES]; int i, num; sharedEntity_t *touch; int passOwnerNum; trace_t trace, oldTrace= {0}; clipHandle_t clipHandle; float *origin, *angles; int thisOwnerShared = 1; num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES); if ( clip->passEntityNum != ENTITYNUM_NONE ) { passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum; if ( passOwnerNum == ENTITYNUM_NONE ) { passOwnerNum = -1; } } else { passOwnerNum = -1; } if ( SV_GentityNum(clip->passEntityNum)->r.svFlags & SVF_OWNERNOTSHARED ) { thisOwnerShared = 0; } for ( i=0 ; i<num ; i++ ) { if ( clip->trace.allsolid ) { return; } touch = SV_GentityNum( touchlist[i] ); // see if we should ignore this entity if ( clip->passEntityNum != ENTITYNUM_NONE ) { if ( touchlist[i] == clip->passEntityNum ) { continue; // don't clip against the pass entity } if ( touch->r.ownerNum == clip->passEntityNum) { if (touch->r.svFlags & SVF_OWNERNOTSHARED) { if ( clip->contentmask != (MASK_SHOT | CONTENTS_LIGHTSABER) && clip->contentmask != (MASK_SHOT)) { //it's not a laser hitting the other "missile", don't care then continue; } } else { continue; // don't clip against own missiles } } if ( touch->r.ownerNum == passOwnerNum && !(touch->r.svFlags & SVF_OWNERNOTSHARED) && thisOwnerShared ) { continue; // don't clip against other missiles from our owner } if (touch->s.eType == ET_MISSILE && !(touch->r.svFlags & SVF_OWNERNOTSHARED) && touch->r.ownerNum == passOwnerNum) { //blah, hack continue; } } // if it doesn't have any brushes of a type we // are looking for, ignore it if ( ! ( clip->contentmask & touch->r.contents ) ) { continue; } if ((clip->contentmask == (MASK_SHOT|CONTENTS_LIGHTSABER) || clip->contentmask == MASK_SHOT) && (touch->r.contents > 0 && (touch->r.contents & CONTENTS_NOSHOT))) { continue; } // might intersect, so do an exact clip clipHandle = SV_ClipHandleForEntity (touch); origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if ( !touch->r.bmodel ) { angles = vec3_origin; // boxes don't rotate } CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); if (clip->traceFlags & G2TRFLAG_DOGHOULTRACE) { // keep these older variables around for a bit, incase we need to replace them in the Ghoul2 Collision check oldTrace = clip->trace; } if ( trace.allsolid ) { clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; } else if ( trace.startsolid ) { clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; //rww - added this because we want to get the number of an ent even if our trace starts inside it. clip->trace.entityNum = touch->s.number; } if ( trace.fraction < clip->trace.fraction ) { byte oldStart; // make sure we keep a startsolid from a previous trace oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid = (qboolean)((unsigned)clip->trace.startsolid | (unsigned)oldStart); } /* Ghoul2 Insert Start */ #if 0 // decide if we should do the ghoul2 collision detection right here if ((trace.entityNum == touch->s.number) && (clip->traceFlags)) { // do we actually have a ghoul2 model here? if (touch->s.ghoul2) { int oldTraceRecSize = 0; int newTraceRecSize = 0; int z; // we have to do this because sometimes you may hit a model's bounding box, but not actually penetrate the Ghoul2 Models polygons // this is, needless to say, not good. So we must check to see if we did actually hit the model, and if not, reset the trace stuff // to what it was to begin with // set our trace record size for (z=0;z<MAX_G2_COLLISIONS;z++) { if (clip->trace.G2CollisionMap[z].mEntityNum != -1) { oldTraceRecSize++; } } G2API_CollisionDetect(&clip->trace.G2CollisionMap[0], *((CGhoul2Info_v *)touch->s.ghoul2), touch->s.angles, touch->s.origin, svs.time, touch->s.number, clip->start, clip->end, touch->s.modelScale, G2VertSpaceServer, clip->traceFlags, clip->useLod); // set our new trace record size for (z=0;z<MAX_G2_COLLISIONS;z++) { if (clip->trace.G2CollisionMap[z].mEntityNum != -1) { newTraceRecSize++; } } // did we actually touch this model? If not, lets reset this ent as being hit.. if (newTraceRecSize == oldTraceRecSize) { clip->trace = oldTrace; } } } #else //rww - since this is multiplayer and we don't have the luxury of violating networking rules in horrible ways, //this must be done somewhat differently. if ((clip->traceFlags & G2TRFLAG_DOGHOULTRACE) && trace.entityNum == touch->s.number && touch->ghoul2 && ((clip->traceFlags & G2TRFLAG_HITCORPSES) || !(touch->s.eFlags & EF_DEAD))) { //standard behavior will be to ignore g2 col on dead ents, but if traceFlags is set to allow, then we'll try g2 col on EF_DEAD people too. static G2Trace_t G2Trace; vec3_t angles; float fRadius = 0.0f; int tN = 0; int bestTr = -1; if (clip->mins[0] || clip->maxs[0]) { fRadius=(clip->maxs[0]-clip->mins[0])/2.0f; } if (clip->traceFlags & G2TRFLAG_THICK) { //if using this flag, make sure it's at least 1.0f if (fRadius < 1.0f) { fRadius = 1.0f; } } memset (&G2Trace, 0, sizeof(G2Trace)); while (tN < MAX_G2_COLLISIONS) { G2Trace[tN].mEntityNum = -1; tN++; } if (touch->s.number < MAX_CLIENTS) { VectorCopy(touch->s.apos.trBase, angles); } else { VectorCopy(touch->r.currentAngles, angles); } angles[ROLL] = angles[PITCH] = 0; //I would think that you could trace from trace.endpos instead of clip->start, but that causes it to miss sometimes.. Not sure what it's off, but if it could be done like that, it would probably //be faster. #ifndef FINAL_BUILD if (sv_showghoultraces->integer) { Com_Printf( "Ghoul2 trace lod=%1d length=%6.0f to %s\n",clip->useLod,VectorDistance(clip->start, clip->end), re->G2API_GetModelName (*(CGhoul2Info_v *)touch->ghoul2, 0)); } #endif if (com_optvehtrace && com_optvehtrace->integer && touch->s.eType == ET_NPC && touch->s.NPC_class == CLASS_VEHICLE && touch->m_pVehicle) { //for vehicles cache the transform data. re->G2API_CollisionDetectCache(G2Trace, *((CGhoul2Info_v *)touch->ghoul2), angles, touch->r.currentOrigin, svs.time, touch->s.number, clip->start, clip->end, touch->modelScale, G2VertSpaceServer, 0, clip->useLod, fRadius); } else { re->G2API_CollisionDetect(G2Trace, *((CGhoul2Info_v *)touch->ghoul2), angles, touch->r.currentOrigin, svs.time, touch->s.number, clip->start, clip->end, touch->modelScale, G2VertSpaceServer, 0, clip->useLod, fRadius); } tN = 0; while (tN < MAX_G2_COLLISIONS) { if (G2Trace[tN].mEntityNum == touch->s.number) { //ok, valid bestTr = tN; break; } else if (G2Trace[tN].mEntityNum == -1) { //there should not be any after the first -1 break; } tN++; } if (bestTr == -1) { //Well then, put the trace back to the old one. clip->trace = oldTrace; } else { //Otherwise, set the endpos/normal/etc. to the model location hit instead of leaving it out in space. VectorCopy(G2Trace[bestTr].mCollisionPosition, clip->trace.endpos); VectorCopy(G2Trace[bestTr].mCollisionNormal, clip->trace.plane.normal); if (clip->traceFlags & G2TRFLAG_GETSURFINDEX) { //we have requested that surfaceFlags be stomped over with the g2 hit surface index. if (clip->trace.entityNum == G2Trace[bestTr].mEntityNum) { clip->trace.surfaceFlags = G2Trace[bestTr].mSurfaceIndex; } } } } #endif /* Ghoul2 Insert End */ } }
/* * SV_ClipMoveToEntities * */ static void SV_ClipMoveToEntities(moveclip_t *clip) { int i, num; int touchlist[MAX_GENTITIES]; Sharedent *touch; int passOwnerNum; Trace trace; Cliphandle clipHandle; float *origin, *angles; num = SV_AreaEntities(clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES); if(clip->passEntityNum != ENTITYNUM_NONE){ passOwnerNum = (SV_GentityNum(clip->passEntityNum))->r.ownerNum; if(passOwnerNum == ENTITYNUM_NONE) passOwnerNum = -1; }else passOwnerNum = -1; for(i=0; i<num; i++){ if(clip->trace.allsolid) return; touch = SV_GentityNum(touchlist[i]); /* see if we should ignore this entity */ if(clip->passEntityNum != ENTITYNUM_NONE){ if(touchlist[i] == clip->passEntityNum) continue; /* don't clip against the pass entity */ if(touch->r.ownerNum == clip->passEntityNum) continue; /* don't clip against own missiles */ if(touch->r.ownerNum == passOwnerNum) continue; /* don't clip against other missiles from our owner */ } /* if it doesn't have any brushes of a type we * are looking for, ignore it */ if(!(clip->contentmask & touch->r.contents)) continue; /* might intersect, so do an exact clip */ clipHandle = SV_ClipHandleForEntity (touch); origin = touch->r.currentOrigin; angles = touch->r.currentAngles; if(!touch->r.bmodel) angles = vec3_origin; /* boxes don't rotate */ CM_TransformedBoxTrace (&trace, (float*)clip->start, (float*)clip->end, (float*)clip->mins, (float*)clip->maxs, clipHandle, clip->contentmask, origin, angles, clip->capsule); if(trace.allsolid){ clip->trace.allsolid = qtrue; trace.entityNum = touch->s.number; }else if(trace.startsolid){ clip->trace.startsolid = qtrue; trace.entityNum = touch->s.number; } if(trace.fraction < clip->trace.fraction){ qbool oldStart; /* make sure we keep a startsolid from a previous trace */ oldStart = clip->trace.startsolid; trace.entityNum = touch->s.number; clip->trace = trace; clip->trace.startsolid |= oldStart; } } }