/*** * * Copyright (c) 1999, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting * object code is restricted to non-commercial enhancements to products from * Valve LLC. All other use, distribution, or modification is prohibited * without written permission from Valve LLC. * ****/ // // HPB_bot - botman's High Ping Bastard bot // // (http://planethalflife.com/botman/) // // util.cpp // #include "extdll.h" #include "util.h" #include "HPB_bot/engine/engine.h" #include "dlls/cbase.h" #include "dlls/player.h" #include "bot.h" #include "bot_func.h" extern int mod_id; extern bot_t bots[32]; extern edict_t *pent_info_ctfdetect; extern char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH]; extern int num_teams; int gmsgTextMsg = 0; int gmsgSayText = 0; int gmsgShowMenu = 0; Vector UTIL_VecToAngles( const Vector &vec ) { float rgflVecOut[3]; VEC_TO_ANGLES(vec, rgflVecOut); return Vector(rgflVecOut); } // Overloaded to add IGNORE_GLASS void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr ) { TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE) | (ignoreGlass?0x100:0), pentIgnore, ptr ); } void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr ) { TRACE_LINE( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), pentIgnore, ptr ); } void UTIL_MakeVectors( const Vector &vecAngles ) { MAKE_VECTORS( vecAngles ); } edict_t *UTIL_FindEntityInSphere( edict_t *pentStart, const Vector &vecCenter, float flRadius ) { edict_t *pentEntity; pentEntity = FIND_ENTITY_IN_SPHERE( pentStart, vecCenter, flRadius); if (!FNullEnt(pentEntity)) return pentEntity; return NULL; } edict_t *UTIL_FindEntityByString( edict_t *pentStart, const char *szKeyword, const char *szValue ) { edict_t *pentEntity; pentEntity = FIND_ENTITY_BY_STRING( pentStart, szKeyword, szValue ); if (!FNullEnt(pentEntity)) return pentEntity; return NULL; } edict_t *UTIL_FindEntityByClassname( edict_t *pentStart, const char *szName ) { return UTIL_FindEntityByString( pentStart, "classname", szName ); } edict_t *UTIL_FindEntityByTargetname( edict_t *pentStart, const char *szName ) { return UTIL_FindEntityByString( pentStart, "targetname", szName ); } int UTIL_PointContents( const Vector &vec ) { return POINT_CONTENTS(vec); } void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ) { SET_SIZE( ENT(pev), vecMin, vecMax ); } void UTIL_SetOrigin( entvars_t *pev, const Vector &vecOrigin ) { SET_ORIGIN(ENT(pev), vecOrigin ); } void ClientPrint( edict_t *pEntity, int msg_dest, const char *msg_name) { // if (gmsgTextMsg == 0) // gmsgTextMsg = REG_USER_MSG( "TextMsg", -1 ); // // pfnMessageBegin( MSG_ONE, gmsgTextMsg, NULL, pEntity ); // // pfnWriteByte( msg_dest ); // pfnWriteString( msg_name ); // pfnMessageEnd(); } void UTIL_SayText( const char *pText, edict_t *pEdict ) { // if (gmsgSayText == 0) // gmsgSayText = REG_USER_MSG( "SayText", -1 ); // // pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEdict ); // pfnWriteByte( ENTINDEX(pEdict) ); // if (mod_id == FRONTLINE_DLL) // pfnWriteShort(0); // pfnWriteString( pText ); // pfnMessageEnd(); } void UTIL_HostSay( edict_t *pEntity, int teamonly, char *message ) { // int j; // char text[128]; // char *pc; // int sender_team, player_team; // edict_t *client; // // // make sure the text has content // for ( pc = message; pc != NULL && *pc != 0; pc++ ) // { // if ( isprint( *pc ) && !isspace( *pc ) ) // { // pc = NULL; // we've found an alphanumeric character, so text is valid // break; // } // } // // if ( pc != NULL ) // return; // no character found, so say nothing // // // turn on color set 2 (color on, no sound) // if ( teamonly ) // sprintf( text, "%c(TEAM) %s: ", 2, STRING( pEntity->v.netname ) ); // else // sprintf( text, "%c%s: ", 2, STRING( pEntity->v.netname ) ); // // j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator // if ( (int)strlen(message) > j ) // message[j] = 0; // // strcat( text, message ); // strcat( text, "\n" ); // // // loop through all players // // Start with the first player. // // This may return the world in single player if the client types something between levels or during spawn // // so check it, or it will infinite loop // // if (gmsgSayText == 0) // gmsgSayText = REG_USER_MSG( "SayText", -1 ); // // sender_team = UTIL_GetTeam(pEntity); // // client = NULL; // while ( ((client = UTIL_FindEntityByClassname( client, "player" )) != NULL) && // (!FNullEnt(client)) ) // { // if ( client == pEntity ) // skip sender of message // continue; // // player_team = UTIL_GetTeam(client); // // if ( teamonly && (sender_team != player_team) ) // continue; // // pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, client ); // pfnWriteByte( ENTINDEX(pEntity) ); // if (mod_id == FRONTLINE_DLL) // pfnWriteShort(0); // pfnWriteString( text ); // pfnMessageEnd(); // } // // // print to the sending client // pfnMessageBegin( MSG_ONE, gmsgSayText, NULL, pEntity ); // pfnWriteByte( ENTINDEX(pEntity) ); // if (mod_id == FRONTLINE_DLL) // pfnWriteShort(0); // pfnWriteString( text ); // pfnMessageEnd(); // // // echo to server console // g_engfuncs.pfnServerPrint( text ); } #ifdef DEBUG edict_t *DBG_EntOfVars( const entvars_t *pev ) { if (pev->pContainingEntity != NULL) return pev->pContainingEntity; ALERT(at_console, "entvars_t pContainingEntity is NULL, calling into engine"); edict_t* pent = (*g_engfuncs.pfnFindEntityByVars)((entvars_t*)pev); if (pent == NULL) ALERT(at_console, "DAMN! Even the engine couldn't FindEntityByVars!"); ((entvars_t *)pev)->pContainingEntity = pent; return pent; } #endif //DEBUG // return team number 0 through 3 based what MOD uses for team numbers int UTIL_GetTeam(edict_t *pEntity) { if (mod_id == TFC_DLL) { return pEntity->v.team - 1; // TFC teams are 1-4 based } else if (mod_id == CSTRIKE_DLL) { char *infobuffer; char model_name[32]; infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity ); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion (strcmp(model_name, "arab") == 0) || // old L337 Krew (strcmp(model_name, "leet") == 0) || // L337 Krew (strcmp(model_name, "artic") == 0) || // Artic Avenger (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare { return 0; } else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 (strcmp(model_name, "gsg9") == 0) || // German GSG-9 (strcmp(model_name, "sas") == 0) || // UK SAS (strcmp(model_name, "gign") == 0) || // French GIGN (strcmp(model_name, "vip") == 0)) // VIP { return 1; } return 0; // return zero if team is unknown } else if ((mod_id == GEARBOX_DLL) && (pent_info_ctfdetect != NULL)) { // OpFor CTF map... char *infobuffer; char model_name[32]; infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity ); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); if ((strcmp(model_name, "ctf_barney") == 0) || (strcmp(model_name, "cl_suit") == 0) || (strcmp(model_name, "ctf_gina") == 0) || (strcmp(model_name, "ctf_gordon") == 0) || (strcmp(model_name, "otis") == 0) || (strcmp(model_name, "ctf_scientist") == 0)) { return 0; } else if ((strcmp(model_name, "beret") == 0) || (strcmp(model_name, "drill") == 0) || (strcmp(model_name, "grunt") == 0) || (strcmp(model_name, "recruit") == 0) || (strcmp(model_name, "shephard") == 0) || (strcmp(model_name, "tower") == 0)) { return 1; } return 0; // return zero if team is unknown } else if (mod_id == FRONTLINE_DLL) { return pEntity->v.team - 1; // Front Line Force teams are 1-4 based } else if(mod_id == AVH_DLL) { return pEntity->v.team; } else // must be HL or OpFor deathmatch... { char *infobuffer; char model_name[32]; if (team_names[0][0] == 0) { char *pName; char teamlist[MAX_TEAMS*MAX_TEAMNAME_LENGTH]; int i; num_teams = 0; strcpy(teamlist, CVAR_GET_STRING("mp_teamlist")); pName = teamlist; pName = strtok(pName, ";"); while (pName != NULL && *pName) { // check that team isn't defined twice for (i=0; i < num_teams; i++) if (strcmp(pName, team_names[i]) == 0) break; if (i == num_teams) { strcpy(team_names[num_teams], pName); num_teams++; } pName = strtok(NULL, ";"); } } infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity ); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); for (int index=0; index < num_teams; index++) { if (strcmp(model_name, team_names[index]) == 0) return index; } return 0; } } // return class number 0 through N int UTIL_GetClass(edict_t *pEntity) { char *infobuffer; char model_name[32]; infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)( pEntity ); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); if (mod_id == FRONTLINE_DLL) { if ((strcmp(model_name, "natorecon") == 0) || (strcmp(model_name, "axisrecon") == 0)) { return 0; // recon } else if ((strcmp(model_name, "natoassault") == 0) || (strcmp(model_name, "axisassault") == 0)) { return 1; // assault } else if ((strcmp(model_name, "natosupport") == 0) || (strcmp(model_name, "axissupport") == 0)) { return 2; // support } } return 0; } int UTIL_GetBotIndex(edict_t *pEdict) { int index; for (index=0; index < 32; index++) { if (bots[index].pEdict == pEdict) { return index; } } return -1; // return -1 if edict is not a bot } bot_t *UTIL_GetBotPointer(edict_t *pEdict) { int index; for (index=0; index < 32; index++) { if (bots[index].pEdict == pEdict) { break; } } if (index < 32) return (&bots[index]); return NULL; // return NULL if edict is not a bot } bool IsAlive(edict_t *pEdict) { return ((pEdict->v.deadflag == DEAD_NO) && (pEdict->v.health > 0) && !(pEdict->v.flags & FL_NOTARGET)); } bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { Vector2D vec2LOS; float flDot; UTIL_MakeVectors ( pEdict->v.angles ); vec2LOS = ( *pOrigin - pEdict->v.origin ).Make2D(); vec2LOS = vec2LOS.Normalize(); flDot = DotProduct (vec2LOS , gpGlobals->v_forward.Make2D() ); if ( flDot > 0.50 ) // 60 degree field of view { return TRUE; } else { return FALSE; } } bool FVisible( const Vector &vecOrigin, edict_t *pEdict ) { TraceResult tr; Vector vecLookerOrigin; // look through caller's eyes vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; int bInWater = (UTIL_PointContents (vecOrigin) == CONTENTS_WATER); int bLookerInWater = (UTIL_PointContents (vecLookerOrigin) == CONTENTS_WATER); // don't look through water if (bInWater != bLookerInWater) return FALSE; UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, pEdict, &tr); if (tr.flFraction != 1.0) { return FALSE; // Line of sight is not established } else { return TRUE; // line of sight is valid. } } Vector GetGunPosition(edict_t *pEdict) { return (pEdict->v.origin + pEdict->v.view_ofs); } void UTIL_SelectItem(edict_t *pEdict, char *item_name) { FakeClientCommand(pEdict, item_name, NULL, NULL); } Vector VecBModelOrigin(edict_t *pEdict) { return pEdict->v.absmin + (pEdict->v.size * 0.5); } bool UpdateSounds(edict_t *pEdict, edict_t *pPlayer) { float distance; static bool check_footstep_sounds = TRUE; static float footstep_sounds_on; float sensitivity = 1.0; float volume; // update sounds made by this player, alert bots if they are nearby... if (check_footstep_sounds) { check_footstep_sounds = FALSE; footstep_sounds_on = CVAR_GET_FLOAT("mp_footsteps"); } if (footstep_sounds_on > 0.0) { CBasePlayer* thePlayer = (CBasePlayer*)CBaseEntity::Instance(pPlayer); // check if this player is moving fast enough to make sounds... if (pPlayer->v.velocity.Length2D() > thePlayer->GetMaxWalkSpeed()) { volume = 500.0; // volume of sound being made (just pick something) Vector v_sound = pPlayer->v.origin - pEdict->v.origin; distance = v_sound.Length(); // is the bot close enough to hear this sound? if (distance < (volume * sensitivity)) { Vector bot_angles = UTIL_VecToAngles( v_sound ); pEdict->v.ideal_yaw = bot_angles.y; BotFixIdealYaw(pEdict); return TRUE; } } } return FALSE; } void UTIL_ShowMenu( edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText ) { // if (gmsgShowMenu == 0) // gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 ); // // pfnMessageBegin( MSG_ONE, gmsgShowMenu, NULL, pEdict ); // // pfnWriteShort( slots ); // pfnWriteChar( displaytime ); // pfnWriteByte( needmore ); // pfnWriteString( pText ); // // pfnMessageEnd(); } void UTIL_BuildFileName(char *filename, char *arg1, char *arg2) { if (mod_id == VALVE_DLL) #ifndef __linux__ strcpy(filename, "valve\\"); #else strcpy(filename, "valve/"); #endif else if (mod_id == TFC_DLL) #ifndef __linux__ strcpy(filename, "tfc\\"); #else strcpy(filename, "tfc/"); #endif else if (mod_id == CSTRIKE_DLL) #ifndef __linux__ strcpy(filename, "cstrike\\"); #else strcpy(filename, "cstrike/"); #endif else if (mod_id == GEARBOX_DLL) #ifndef __linux__ strcpy(filename, "gearbox\\"); #else strcpy(filename, "gearbox/"); #endif else if (mod_id == FRONTLINE_DLL) #ifndef __linux__ strcpy(filename, "frontline\\"); #else strcpy(filename, "frontline/"); #endif else if (mod_id == AVH_DLL) { string filenameString = string(getModDirectory()); #ifndef __linux__ filenameString += "\\"; #else filenameString += '/'; #endif strcpy(filename,filenameString.c_str()); } else { filename[0] = 0; return; } if ((arg1) && (*arg1) && (arg2) && (*arg2)) { strcat(filename, arg1); #ifndef __linux__ strcat(filename, "\\"); #else strcat(filename, "/"); #endif strcat(filename, arg2); } else if ((arg1) && (*arg1)) { strcat(filename, arg1); } printf("UTIL_BuildFileName:"); printf(filename); printf("\n"); } //========================================================= // UTIL_LogPrintf - Prints a logged message to console. // Preceded by LOG: ( timestamp ) < message > //========================================================= void UTIL_LogPrintf( char *fmt, ... ) { va_list argptr; static char string[1024]; va_start ( argptr, fmt ); vsprintf ( string, fmt, argptr ); va_end ( argptr ); // Print to server console printf("UTIL_LogPrintf:"); printf(string); printf("\n"); ALERT( at_logged, "%s", string ); }