2015-06-30 12:46:07 +03:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Globals initialization
|
|
|
|
*/
|
|
|
|
#ifndef HOOK_GAMEDLL
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
short s_iBeamSprite = 0;
|
2015-07-09 03:22:48 +03:00
|
|
|
float cosTable[ COS_TABLE_SIZE ];
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2016-02-23 02:13:52 +03:00
|
|
|
#endif
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2015-08-02 20:45:57 +03:00
|
|
|
bool UTIL_IsNameTaken(const char *name, bool ignoreHumans)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; ++i)
|
|
|
|
{
|
|
|
|
CBaseEntity *player = UTIL_PlayerByIndex(i);
|
|
|
|
|
|
|
|
if (player == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(player->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(player->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
2016-02-23 02:13:52 +03:00
|
|
|
if (player->IsPlayer() && ((CBasePlayer *)player)->IsBot())
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2015-08-02 20:45:57 +03:00
|
|
|
// bots can have prefixes so we need to check the name
|
|
|
|
// against the profile name instead.
|
2016-02-04 03:18:26 +03:00
|
|
|
CBot *bot = static_cast<CBot *>(player);
|
2015-06-30 12:46:07 +03:00
|
|
|
if (FStrEq(name, bot->GetProfile()->GetName()))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!ignoreHumans)
|
|
|
|
{
|
|
|
|
if (FStrEq(name, STRING(player->pev->netname)))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-04 03:18:26 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
int UTIL_ClientsInGame()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int iCount = 0;
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBaseEntity *pPlayer = UTIL_PlayerByIndex(iIndex);
|
|
|
|
|
|
|
|
if (pPlayer == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(pPlayer->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(pPlayer->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
++iCount;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-12-22 21:07:49 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return iCount;
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
int UTIL_ActivePlayersInGame()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int iCount = 0;
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
|
|
|
|
|
|
|
|
if (entity == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(entity->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(entity->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(entity);
|
|
|
|
|
|
|
|
// ignore spectators
|
|
|
|
if (player->m_iTeam != TERRORIST && player->m_iTeam != CT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iJoiningState != JOINED)
|
|
|
|
continue;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
++iCount;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-08-20 13:35:01 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return iCount;
|
|
|
|
}
|
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
int UTIL_HumansInGame(bool ignoreSpectators)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int iCount = 0;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
|
|
|
|
|
|
|
|
if (entity == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(entity->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(entity->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(entity);
|
|
|
|
|
|
|
|
if (player->IsBot())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ignoreSpectators && player->m_iTeam != TERRORIST && player->m_iTeam != CT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ignoreSpectators && player->m_iJoiningState != JOINED)
|
|
|
|
continue;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
++iCount;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-08-20 13:35:01 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return iCount;
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
int UTIL_HumansOnTeam(int teamID, bool isAlive)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int iCount = 0;
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBaseEntity *entity = UTIL_PlayerByIndex(iIndex);
|
|
|
|
|
|
|
|
if (entity == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(entity->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(entity->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(entity);
|
|
|
|
|
|
|
|
if (player->IsBot())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iTeam != teamID)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (isAlive && !player->IsAlive())
|
|
|
|
continue;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
++iCount;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-09-27 16:59:44 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return iCount;
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
int UTIL_BotsInGame()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int iCount = 0;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *pPlayer = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(iIndex));
|
|
|
|
|
|
|
|
if (pPlayer == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(pPlayer->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(pPlayer->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!pPlayer->IsBot())
|
|
|
|
continue;
|
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
++iCount;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-09-27 16:59:44 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return iCount;
|
|
|
|
}
|
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
bool UTIL_KickBotFromTeam(TeamName kickTeam)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int i;
|
2015-08-20 13:35:01 +03:00
|
|
|
|
|
|
|
// try to kick a dead bot first
|
2015-06-30 12:46:07 +03:00
|
|
|
for (i = 1; i <= gpGlobals->maxClients; ++i)
|
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
2015-08-20 13:35:01 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
if (player == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(player->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const char *name = STRING(player->pev->netname);
|
|
|
|
if (FStrEq(name, ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsBot())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsAlive() && player->m_iTeam == kickTeam)
|
|
|
|
{
|
2015-08-20 13:35:01 +03:00
|
|
|
// its a bot on the right team - kick it
|
2015-06-30 12:46:07 +03:00
|
|
|
SERVER_COMMAND(UTIL_VarArgs("kick \"%s\"\n", STRING(player->pev->netname)));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2015-08-20 13:35:01 +03:00
|
|
|
|
|
|
|
// no dead bots, kick any bot on the given team
|
2015-06-30 12:46:07 +03:00
|
|
|
for (i = 1; i <= gpGlobals->maxClients; ++i)
|
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
|
|
|
|
|
|
|
if (player == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(player->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const char *name = STRING(player->pev->netname);
|
|
|
|
if (FStrEq(name, ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsBot())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iTeam == kickTeam)
|
|
|
|
{
|
2015-08-20 13:35:01 +03:00
|
|
|
// its a bot on the right team - kick it
|
2015-06-30 12:46:07 +03:00
|
|
|
SERVER_COMMAND(UTIL_VarArgs("kick \"%s\"\n", STRING(player->pev->netname)));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2015-09-27 16:59:44 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
bool UTIL_IsTeamAllBots(int team)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
int botCount = 0;
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; ++i)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
|
|
|
|
|
|
|
if (player == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iTeam != team)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(player->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(player->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
2015-08-02 20:45:57 +03:00
|
|
|
if (!(player->pev->flags & FL_FAKECLIENT))
|
2015-06-30 12:46:07 +03:00
|
|
|
return false;
|
|
|
|
|
|
|
|
++botCount;
|
|
|
|
}
|
2015-09-27 16:59:44 +03:00
|
|
|
|
2016-02-23 02:13:52 +03:00
|
|
|
return botCount ? true : false;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
|
|
|
|
2015-12-05 22:40:30 +03:00
|
|
|
// Return the closest active player to the given position.
|
|
|
|
// If 'distance' is non-NULL, the distance to the closest player is returned in it.
|
2016-02-23 02:13:52 +03:00
|
|
|
extern CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, float *distance)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *closePlayer = NULL;
|
2015-12-05 22:40:30 +03:00
|
|
|
float closeDistSq = 1.0e12f; // 999999999999.9f
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; ++i)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
|
|
|
|
|
|
|
if (!IsEntityValid(player))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsAlive())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
float distSq = (player->pev->origin - *pos).LengthSquared();
|
|
|
|
if (distSq < closeDistSq)
|
|
|
|
{
|
|
|
|
closeDistSq = distSq;
|
2015-12-05 22:40:30 +03:00
|
|
|
closePlayer = player;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (distance)
|
2016-02-23 02:13:52 +03:00
|
|
|
*distance = Q_sqrt(closeDistSq);
|
2015-06-30 12:46:07 +03:00
|
|
|
|
|
|
|
return closePlayer;
|
|
|
|
}
|
|
|
|
|
2015-12-05 22:40:30 +03:00
|
|
|
// Return the closest active player on the given team to the given position.
|
|
|
|
// If 'distance' is non-NULL, the distance to the closest player is returned in it.
|
2016-02-23 02:13:52 +03:00
|
|
|
extern CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team, float *distance)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *closePlayer = NULL;
|
2015-12-09 01:39:54 +03:00
|
|
|
float closeDistSq = 1.0e12f; // 999999999999.9f
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; ++i)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
|
|
|
|
|
|
|
if (!IsEntityValid(player))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsAlive())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iTeam != team)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
float distSq = (player->pev->origin - *pos).LengthSquared();
|
|
|
|
if (distSq < closeDistSq)
|
|
|
|
{
|
|
|
|
closeDistSq = distSq;
|
2015-12-05 22:40:30 +03:00
|
|
|
closePlayer = player;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (distance)
|
2016-02-23 02:13:52 +03:00
|
|
|
*distance = Q_sqrt(closeDistSq);
|
2015-06-30 12:46:07 +03:00
|
|
|
|
|
|
|
return closePlayer;
|
|
|
|
}
|
|
|
|
|
2015-08-02 20:45:57 +03:00
|
|
|
const char *UTIL_GetBotPrefix()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
return cv_bot_prefix.string;
|
|
|
|
}
|
|
|
|
|
2015-08-02 20:45:57 +03:00
|
|
|
void UTIL_ConstructBotNetName(char *name, int nameLength, const BotProfile *profile)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
if (profile == NULL)
|
|
|
|
{
|
2015-12-05 22:40:30 +03:00
|
|
|
name[0] = '\0';
|
2015-06-30 12:46:07 +03:00
|
|
|
return;
|
|
|
|
}
|
2015-08-02 20:45:57 +03:00
|
|
|
|
|
|
|
// if there is no bot prefix just use the profile name.
|
2015-06-30 12:46:07 +03:00
|
|
|
if ((UTIL_GetBotPrefix() == NULL) || (Q_strlen(UTIL_GetBotPrefix()) == 0))
|
|
|
|
{
|
|
|
|
Q_strncpy(name, profile->GetName(), nameLength);
|
|
|
|
return;
|
|
|
|
}
|
2015-08-02 20:45:57 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
Q_snprintf(name, nameLength, "%s %s", UTIL_GetBotPrefix(), profile->GetName());
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
bool UTIL_IsVisibleToTeam(const Vector &spot, int team, float maxRange)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2015-07-12 23:32:09 +03:00
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; ++i)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
|
|
|
|
|
|
|
|
if (player == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FNullEnt(player->pev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FStrEq(STRING(player->pev->netname), ""))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!player->IsAlive())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (player->m_iTeam != team)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (maxRange > 0.0f && (spot - player->Center()).IsLengthGreaterThan(maxRange))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
TraceResult result;
|
|
|
|
UTIL_TraceLine(player->EyePosition(), spot, ignore_monsters, ignore_glass, ENT(player->pev), &result);
|
|
|
|
|
|
|
|
if (result.flFraction == 1.0f)
|
|
|
|
return true;
|
|
|
|
}
|
2015-09-27 16:59:44 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
CBasePlayer *UTIL_GetLocalPlayer()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
if (!IS_DEDICATED_SERVER())
|
|
|
|
return static_cast<CBasePlayer *>(UTIL_PlayerByIndex(1));
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
NOXREF Vector UTIL_ComputeOrigin(entvars_t *pevVars)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2016-01-19 14:54:31 +03:00
|
|
|
if (pevVars->origin.x == 0.0f && pevVars->origin.y == 0.0f && pevVars->origin.z == 0.0f)
|
|
|
|
return (pevVars->absmax + pevVars->absmin) * 0.5f;
|
2015-06-30 12:46:07 +03:00
|
|
|
else
|
|
|
|
return pevVars->origin;
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
NOXREF Vector UTIL_ComputeOrigin(CBaseEntity *pEntity)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
return UTIL_ComputeOrigin(pEntity->pev);
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
NOXREF Vector UTIL_ComputeOrigin(edict_t *pentEdict)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
return UTIL_ComputeOrigin(VARS(pentEdict));
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
NOXREF void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecEnd);
|
|
|
|
WRITE_BYTE(TE_BEAMENTPOINT);
|
|
|
|
WRITE_SHORT(iIndex);
|
|
|
|
WRITE_COORD(vecEnd.x);
|
|
|
|
WRITE_COORD(vecEnd.y);
|
|
|
|
WRITE_COORD(vecEnd.z);
|
|
|
|
WRITE_SHORT(s_iBeamSprite);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(iLifetime);
|
|
|
|
WRITE_BYTE(10);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(bRed);
|
|
|
|
WRITE_BYTE(bGreen);
|
|
|
|
WRITE_BYTE(bBlue);
|
|
|
|
WRITE_BYTE(255);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
|
2016-01-19 14:54:31 +03:00
|
|
|
void UTIL_DrawBeamPoints(Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecStart);
|
|
|
|
WRITE_BYTE(TE_BEAMPOINTS);
|
|
|
|
WRITE_COORD(vecStart.x);
|
|
|
|
WRITE_COORD(vecStart.y);
|
|
|
|
WRITE_COORD(vecStart.z);
|
|
|
|
WRITE_COORD(vecEnd.x);
|
|
|
|
WRITE_COORD(vecEnd.y);
|
|
|
|
WRITE_COORD(vecEnd.z);
|
|
|
|
WRITE_SHORT(s_iBeamSprite);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(iLifetime);
|
|
|
|
WRITE_BYTE(10);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
WRITE_BYTE(bRed);
|
|
|
|
WRITE_BYTE(bGreen);
|
|
|
|
WRITE_BYTE(bBlue);
|
|
|
|
WRITE_BYTE(255);
|
|
|
|
WRITE_BYTE(0);
|
|
|
|
MESSAGE_END();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_ECHO(char *pszMsg, ...)
|
|
|
|
{
|
|
|
|
va_list argptr;
|
|
|
|
static char szStr[1024];
|
|
|
|
|
|
|
|
va_start(argptr, pszMsg);
|
|
|
|
vsprintf(szStr, pszMsg, argptr);
|
|
|
|
va_end(argptr);
|
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
SERVER_PRINT(szStr);
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_ECHO_LOGGED(char *pszMsg, ...)
|
|
|
|
{
|
|
|
|
va_list argptr;
|
|
|
|
static char szStr[1024];
|
|
|
|
|
|
|
|
va_start(argptr, pszMsg);
|
|
|
|
vsprintf(szStr, pszMsg, argptr);
|
|
|
|
va_end(argptr);
|
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
SERVER_PRINT(szStr);
|
2015-06-30 12:46:07 +03:00
|
|
|
UTIL_LogPrintf(szStr);
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
void BotPrecache()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
s_iBeamSprite = PRECACHE_MODEL("sprites/smoke.spr");
|
|
|
|
|
|
|
|
PRECACHE_SOUND("buttons/bell1.wav");
|
|
|
|
PRECACHE_SOUND("buttons/blip1.wav");
|
|
|
|
PRECACHE_SOUND("buttons/blip2.wav");
|
|
|
|
PRECACHE_SOUND("buttons/button11.wav");
|
|
|
|
PRECACHE_SOUND("buttons/latchunlocked2.wav");
|
|
|
|
PRECACHE_SOUND("buttons/lightswitch2.wav");
|
|
|
|
PRECACHE_SOUND("ambience/quail1.wav");
|
|
|
|
|
|
|
|
PRECACHE_SOUND("events/tutor_msg.wav");
|
|
|
|
PRECACHE_SOUND("events/enemy_died.wav");
|
|
|
|
PRECACHE_SOUND("events/friend_died.wav");
|
|
|
|
PRECACHE_SOUND("events/task_complete.wav");
|
|
|
|
}
|
|
|
|
|
2016-02-04 03:18:26 +03:00
|
|
|
void InitBotTrig()
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2015-12-22 21:07:49 +03:00
|
|
|
for (int i = 0; i < COS_TABLE_SIZE; ++i)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2016-02-23 02:13:52 +03:00
|
|
|
float_precision angle = 2.0f * M_PI * float(i) / float(COS_TABLE_SIZE - 1);
|
|
|
|
cosTable[i] = Q_cos(angle);
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float BotCOS(float angle)
|
|
|
|
{
|
|
|
|
angle = NormalizeAnglePositive(angle);
|
|
|
|
int i = angle * ((COS_TABLE_SIZE - 1) / 360.0f);
|
|
|
|
return cosTable[ i ];
|
|
|
|
}
|
|
|
|
|
|
|
|
float BotSIN(float angle)
|
|
|
|
{
|
|
|
|
angle = NormalizeAnglePositive(angle - 90);
|
|
|
|
int i = angle * ((COS_TABLE_SIZE - 1) / 360.0f);
|
|
|
|
return cosTable[ i ];
|
|
|
|
}
|
|
|
|
|
2015-12-05 22:40:30 +03:00
|
|
|
// Determine if this event is audible, and if so, return its audible range and priority
|
|
|
|
bool IsGameEventAudible(GameEventType event, CBaseEntity *entity, CBaseEntity *other, float *range, PriorityType *priority, bool *isHostile)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
CBasePlayer *player = static_cast<CBasePlayer *>(entity);
|
2015-12-05 22:40:30 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
if (entity == NULL || !player->IsPlayer())
|
|
|
|
player = NULL;
|
|
|
|
|
|
|
|
const float ShortRange = 1000.0f;
|
|
|
|
const float NormalRange = 2000.0f;
|
2015-12-05 22:40:30 +03:00
|
|
|
|
2015-09-16 23:19:21 +03:00
|
|
|
switch (event)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
2016-01-19 14:54:31 +03:00
|
|
|
// TODO: Check weapon type (knives are pretty quiet)
|
|
|
|
// TODO: Use actual volume, account for silencers, etc.
|
2015-12-05 22:40:30 +03:00
|
|
|
case EVENT_WEAPON_FIRED:
|
|
|
|
{
|
|
|
|
if (player->m_pActiveItem == NULL)
|
|
|
|
return false;
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2015-12-05 22:40:30 +03:00
|
|
|
switch (player->m_pActiveItem->m_iId)
|
|
|
|
{
|
|
|
|
// silent "firing"
|
|
|
|
case WEAPON_HEGRENADE:
|
|
|
|
case WEAPON_SMOKEGRENADE:
|
|
|
|
case WEAPON_FLASHBANG:
|
|
|
|
case WEAPON_SHIELDGUN:
|
|
|
|
case WEAPON_C4:
|
|
|
|
return false;
|
|
|
|
// quiet
|
|
|
|
case WEAPON_KNIFE:
|
|
|
|
case WEAPON_TMP:
|
|
|
|
*range = ShortRange;
|
|
|
|
break;
|
|
|
|
// M4A1 - check for silencer
|
|
|
|
case WEAPON_M4A1:
|
|
|
|
{
|
|
|
|
CBasePlayerWeapon *pWeapon = static_cast<CBasePlayerWeapon *>(player->m_pActiveItem);
|
|
|
|
if (pWeapon->m_iWeaponState & WPNSTATE_M4A1_SILENCED)
|
|
|
|
*range = ShortRange;
|
|
|
|
else
|
|
|
|
*range = NormalRange;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// USP - check for silencer
|
|
|
|
case WEAPON_USP:
|
|
|
|
{
|
|
|
|
CBasePlayerWeapon *pWeapon = static_cast<CBasePlayerWeapon *>(player->m_pActiveItem);
|
|
|
|
if (pWeapon->m_iWeaponState & WPNSTATE_USP_SILENCED)
|
|
|
|
*range = ShortRange;
|
|
|
|
else
|
|
|
|
*range = NormalRange;
|
|
|
|
break;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-12-05 22:40:30 +03:00
|
|
|
// loud
|
|
|
|
case WEAPON_AWP:
|
2015-06-30 12:46:07 +03:00
|
|
|
*range = 99999.0f;
|
2015-12-05 22:40:30 +03:00
|
|
|
break;
|
|
|
|
// normal
|
|
|
|
default:
|
|
|
|
*range = NormalRange;
|
|
|
|
break;
|
|
|
|
}
|
2015-06-30 12:46:07 +03:00
|
|
|
|
2015-12-05 22:40:30 +03:00
|
|
|
*priority = PRIORITY_HIGH;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
2015-06-30 12:46:07 +03:00
|
|
|
}
|
2015-12-05 22:40:30 +03:00
|
|
|
case EVENT_HE_GRENADE_EXPLODED:
|
|
|
|
*range = 99999.0f;
|
|
|
|
*priority = PRIORITY_HIGH;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_FLASHBANG_GRENADE_EXPLODED:
|
|
|
|
*range = 1000.0f;
|
|
|
|
*priority = PRIORITY_LOW;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_SMOKE_GRENADE_EXPLODED:
|
|
|
|
*range = 1000.0f;
|
|
|
|
*priority = PRIORITY_LOW;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_GRENADE_BOUNCED:
|
|
|
|
*range = 500.0f;
|
|
|
|
*priority = PRIORITY_LOW;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_BREAK_GLASS:
|
|
|
|
case EVENT_BREAK_WOOD:
|
|
|
|
case EVENT_BREAK_METAL:
|
|
|
|
case EVENT_BREAK_FLESH:
|
|
|
|
case EVENT_BREAK_CONCRETE:
|
|
|
|
*range = 1100.0f;
|
|
|
|
*priority = PRIORITY_MEDIUM;
|
|
|
|
*isHostile = true;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_DOOR:
|
|
|
|
*range = 1100.0f;
|
|
|
|
*priority = PRIORITY_MEDIUM;
|
|
|
|
*isHostile = false;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_WEAPON_FIRED_ON_EMPTY:
|
|
|
|
case EVENT_PLAYER_FOOTSTEP:
|
|
|
|
case EVENT_WEAPON_RELOADED:
|
|
|
|
case EVENT_WEAPON_ZOOMED:
|
|
|
|
case EVENT_PLAYER_LANDED_FROM_HEIGHT:
|
|
|
|
*range = 1100.0f;
|
|
|
|
*priority = PRIORITY_LOW;
|
|
|
|
*isHostile = false;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case EVENT_HOSTAGE_USED:
|
|
|
|
case EVENT_HOSTAGE_CALLED_FOR_HELP:
|
|
|
|
*range = 1200.0f;
|
|
|
|
*priority = PRIORITY_MEDIUM;
|
|
|
|
*isHostile = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-02 20:45:57 +03:00
|
|
|
void HintMessageToAllPlayers(const char *message)
|
2015-06-30 12:46:07 +03:00
|
|
|
{
|
|
|
|
hudtextparms_t textParms;
|
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
textParms.x = -1.0f;
|
|
|
|
textParms.y = -1.0f;
|
2015-08-02 20:45:57 +03:00
|
|
|
textParms.effect = 0;
|
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
textParms.r1 = 100;
|
2015-08-20 13:35:01 +03:00
|
|
|
textParms.g1 = 255;
|
2015-06-30 12:46:07 +03:00
|
|
|
textParms.b1 = 100;
|
2015-08-02 20:45:57 +03:00
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
textParms.r2 = 255;
|
|
|
|
textParms.g2 = 255;
|
|
|
|
textParms.b2 = 255;
|
2015-08-02 20:45:57 +03:00
|
|
|
|
2015-08-20 13:35:01 +03:00
|
|
|
textParms.fadeinTime = 1.0f;
|
|
|
|
textParms.fadeoutTime = 5.0f;
|
|
|
|
textParms.holdTime = 5.0f;
|
|
|
|
textParms.fxTime = 0.0f;
|
2015-08-02 20:45:57 +03:00
|
|
|
|
2015-06-30 12:46:07 +03:00
|
|
|
textParms.channel = 0;
|
|
|
|
|
|
|
|
UTIL_HudMessageAll(textParms, message);
|
|
|
|
}
|