mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2024-12-27 07:05:38 +03:00
19714af6e6
minor refactor
1875 lines
40 KiB
C++
1875 lines
40 KiB
C++
#include "precompiled.h"
|
|
|
|
unsigned int glSeed;
|
|
CUtlVector<hash_item_t> stringsHashTable;
|
|
|
|
unsigned int seed_table[256] =
|
|
{
|
|
28985U, 27138U, 26457U, 9451U, 17764U, 10909U, 28790U, 8716U, 6361U, 4853U, 17798U, 21977U, 19643U, 20662U, 10834U, 20103,
|
|
27067U, 28634U, 18623U, 25849U, 8576U, 26234U, 23887U, 18228U, 32587U, 4836U, 3306U, 1811U, 3035U, 24559U, 18399U, 315,
|
|
26766U, 907U, 24102U, 12370U, 9674U, 2972U, 10472U, 16492U, 22683U, 11529U, 27968U, 30406U, 13213U, 2319U, 23620U, 16823,
|
|
10013U, 23772U, 21567U, 1251U, 19579U, 20313U, 18241U, 30130U, 8402U, 20807U, 27354U, 7169U, 21211U, 17293U, 5410U, 19223,
|
|
10255U, 22480U, 27388U, 9946U, 15628U, 24389U, 17308U, 2370U, 9530U, 31683U, 25927U, 23567U, 11694U, 26397U, 32602U, 15031,
|
|
18255U, 17582U, 1422U, 28835U, 23607U, 12597U, 20602U, 10138U, 5212U, 1252U, 10074U, 23166U, 19823U, 31667U, 5902U, 24630,
|
|
18948U, 14330U, 14950U, 8939U, 23540U, 21311U, 22428U, 22391U, 3583U, 29004U, 30498U, 18714U, 4278U, 2437U, 22430U, 3439,
|
|
28313U, 23161U, 25396U, 13471U, 19324U, 15287U, 2563U, 18901U, 13103U, 16867U, 9714U, 14322U, 15197U, 26889U, 19372U, 26241,
|
|
31925U, 14640U, 11497U, 8941U, 10056U, 6451U, 28656U, 10737U, 13874U, 17356U, 8281U, 25937U, 1661U, 4850U, 7448U, 12744,
|
|
21826U, 5477U, 10167U, 16705U, 26897U, 8839U, 30947U, 27978U, 27283U, 24685U, 32298U, 3525U, 12398U, 28726U, 9475U, 10208,
|
|
617U, 13467U, 22287U, 2376U, 6097U, 26312U, 2974U, 9114U, 21787U, 28010U, 4725U, 15387U, 3274U, 10762U, 31695U, 17320,
|
|
18324U, 12441U, 16801U, 27376U, 22464U, 7500U, 5666U, 18144U, 15314U, 31914U, 31627U, 6495U, 5226U, 31203U, 2331U, 4668,
|
|
12650U, 18275U, 351U, 7268U, 31319U, 30119U, 7600U, 2905U, 13826U, 11343U, 13053U, 15583U, 30055U, 31093U, 5067U, 761,
|
|
9685U, 11070U, 21369U, 27155U, 3663U, 26542U, 20169U, 12161U, 15411U, 30401U, 7580U, 31784U, 8985U, 29367U, 20989U, 14203,
|
|
29694U, 21167U, 10337U, 1706U, 28578U, 887U, 3373U, 19477U, 14382U, 675U, 7033U, 15111U, 26138U, 12252U, 30996U, 21409,
|
|
25678U, 18555U, 13256U, 23316U, 22407U, 16727U, 991U, 9236U, 5373U, 29402U, 6117U, 15241U, 27715U, 19291U, 19888U, 19847U
|
|
};
|
|
|
|
int g_groupmask = 0;
|
|
int g_groupop = 0;
|
|
|
|
float UTIL_WeaponTimeBase()
|
|
{
|
|
#ifdef CLIENT_WEAPONS
|
|
return 0.0;
|
|
#else
|
|
return gpGlobals->time;
|
|
#endif
|
|
}
|
|
|
|
unsigned int U_Random()
|
|
{
|
|
glSeed *= 69069;
|
|
glSeed += seed_table[glSeed & 0xFF] + 1;
|
|
return (glSeed & 0xFFFFFFF);
|
|
}
|
|
|
|
void U_Srand(unsigned int seed)
|
|
{
|
|
glSeed = seed_table[seed & 0xFF];
|
|
}
|
|
|
|
int UTIL_SharedRandomLong(unsigned int seed, int low, int high)
|
|
{
|
|
unsigned int range = high - low + 1;
|
|
U_Srand((unsigned int)(high + low + seed));
|
|
if (range != 1)
|
|
{
|
|
int rnum = U_Random();
|
|
int offset = rnum % range;
|
|
return (low + offset);
|
|
}
|
|
|
|
return low;
|
|
}
|
|
|
|
float UTIL_SharedRandomFloat(unsigned int seed, float low, float high)
|
|
{
|
|
unsigned int range = high - low;
|
|
U_Srand((unsigned int)seed + *(unsigned int *)&low + *(unsigned int *)&high);
|
|
|
|
U_Random();
|
|
U_Random();
|
|
|
|
if (range)
|
|
{
|
|
int tensixrand = U_Random() & 0xFFFFu;
|
|
float offset = float(tensixrand) / 0x10000u;
|
|
return (low + offset * range);
|
|
}
|
|
|
|
return low;
|
|
}
|
|
|
|
NOXREF void UTIL_ParametricRocket(entvars_t *pev, Vector p_vecOrigin, Vector vecAngles, edict_t *owner)
|
|
{
|
|
TraceResult tr;
|
|
Vector vecTravel;
|
|
float travelTime;
|
|
|
|
pev->startpos = p_vecOrigin;
|
|
UTIL_MakeVectors(vecAngles);
|
|
UTIL_TraceLine(pev->startpos, gpGlobals->v_forward * 8192.0f + pev->startpos, ignore_monsters, owner, &tr);
|
|
pev->endpos = tr.vecEndPos;
|
|
|
|
vecTravel = pev->endpos - pev->startpos;
|
|
if (pev->velocity.Length() > 0.0f)
|
|
travelTime = vecTravel.Length() / pev->velocity.Length();
|
|
else
|
|
travelTime = 0.0f;
|
|
|
|
pev->starttime = gpGlobals->time;
|
|
pev->impacttime = travelTime + gpGlobals->time;
|
|
}
|
|
|
|
void UTIL_SetGroupTrace(int groupmask, int op)
|
|
{
|
|
g_groupmask = groupmask;
|
|
g_groupop = op;
|
|
|
|
ENGINE_SETGROUPMASK(groupmask, op);
|
|
}
|
|
|
|
void UTIL_UnsetGroupTrace()
|
|
{
|
|
g_groupmask = 0;
|
|
g_groupop = 0;
|
|
|
|
ENGINE_SETGROUPMASK(0, 0);
|
|
}
|
|
|
|
NOXREF UTIL_GroupTrace::UTIL_GroupTrace(int groupmask, int op)
|
|
{
|
|
m_oldgroupmask = g_groupmask;
|
|
m_oldgroupop = g_groupop;
|
|
|
|
g_groupmask = groupmask;
|
|
g_groupop = op;
|
|
|
|
ENGINE_SETGROUPMASK(groupmask, op);
|
|
}
|
|
|
|
NOXREF UTIL_GroupTrace::~UTIL_GroupTrace()
|
|
{
|
|
g_groupmask = m_oldgroupmask;
|
|
g_groupop = m_oldgroupop;
|
|
|
|
ENGINE_SETGROUPMASK(g_groupmask, g_groupop);
|
|
}
|
|
|
|
NOXREF BOOL UTIL_GetNextBestWeapon(CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon)
|
|
{
|
|
return g_pGameRules->GetNextBestWeapon(pPlayer,pCurrentWeapon);
|
|
}
|
|
|
|
float UTIL_AngleMod(float a)
|
|
{
|
|
if (a < 0.0f)
|
|
a = a + 360.0f * (int(a / 360.0f) + 1);
|
|
else if (a >= 360.0f)
|
|
a = a - 360.0f * int(a / 360.0f);
|
|
return a;
|
|
}
|
|
|
|
NOXREF float UTIL_AngleDiff(float destAngle, float srcAngle)
|
|
{
|
|
float delta = destAngle - srcAngle;
|
|
if (destAngle > srcAngle)
|
|
{
|
|
if (delta >= 180.0f)
|
|
delta -= 360.0f;
|
|
}
|
|
else
|
|
{
|
|
if (delta <= -180.0f)
|
|
delta += 360.0f;
|
|
}
|
|
|
|
return delta;
|
|
}
|
|
|
|
Vector UTIL_VecToAngles(const Vector &vec)
|
|
{
|
|
float rgflVecOut[3];
|
|
VEC_TO_ANGLES(vec, rgflVecOut);
|
|
return Vector(rgflVecOut);
|
|
}
|
|
|
|
NOXREF void UTIL_MoveToOrigin(edict_t *pent, const Vector &vecGoal, float flDist, int iMoveType)
|
|
{
|
|
float rgfl[3];
|
|
vecGoal.CopyToArray(rgfl);
|
|
MOVE_TO_ORIGIN(pent, rgfl, flDist, iMoveType);
|
|
}
|
|
|
|
int UTIL_EntitiesInBox(CBaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask)
|
|
{
|
|
edict_t *pEdict = INDEXENT(1);
|
|
int count = 0;
|
|
|
|
if (!pEdict)
|
|
return 0;
|
|
|
|
for (int i = 1; i < gpGlobals->maxEntities; i++, pEdict++)
|
|
{
|
|
if (pEdict->free)
|
|
continue;
|
|
|
|
if (flagMask && !(pEdict->v.flags & flagMask))
|
|
continue;
|
|
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(pEdict);
|
|
if (!pEntity)
|
|
continue;
|
|
|
|
if (!pEntity->Intersects(mins, maxs))
|
|
continue;
|
|
|
|
pList[count++] = pEntity;
|
|
|
|
if (count >= listMax)
|
|
break;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
NOXREF int UTIL_MonstersInSphere(CBaseEntity ** pList, int listMax, const Vector ¢er, float radius)
|
|
{
|
|
edict_t *pEdict;
|
|
CBaseEntity *pEntity;
|
|
int count = 0;
|
|
float distance;
|
|
float delta;
|
|
|
|
float radiusSquared = radius * radius;
|
|
pEdict = INDEXENT(1);
|
|
|
|
if (!pEdict)
|
|
return count;
|
|
|
|
for (int i = 1; i < gpGlobals->maxEntities; i++, pEdict++)
|
|
{
|
|
if (pEdict->free)
|
|
continue;
|
|
|
|
if (!(pEdict->v.flags & (FL_CLIENT | FL_MONSTER)))
|
|
continue;
|
|
|
|
delta = center.x - pEdict->v.origin.x;
|
|
delta *= delta;
|
|
|
|
if (delta > radiusSquared)
|
|
continue;
|
|
|
|
distance = delta;
|
|
|
|
delta = center.y - pEdict->v.origin.y;
|
|
delta *= delta;
|
|
|
|
distance += delta;
|
|
if (distance > radiusSquared)
|
|
continue;
|
|
|
|
delta = center.z - (pEdict->v.absmin.z + pEdict->v.absmax.z) * 0.5;
|
|
delta *= delta;
|
|
|
|
distance += delta;
|
|
if (distance > radiusSquared)
|
|
continue;
|
|
|
|
pEntity = CBaseEntity::Instance(pEdict);
|
|
if (!pEntity)
|
|
continue;
|
|
|
|
pList[count++] = pEntity;
|
|
|
|
if (count >= listMax)
|
|
return count;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
CBaseEntity *UTIL_FindEntityInSphere(CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius)
|
|
{
|
|
edict_t *pentEntity;
|
|
if (pStartEntity)
|
|
pentEntity = pStartEntity->edict();
|
|
else
|
|
pentEntity = nullptr;
|
|
|
|
pentEntity = FIND_ENTITY_IN_SPHERE(pentEntity, vecCenter, flRadius);
|
|
if (!FNullEnt(pentEntity))
|
|
{
|
|
return CBaseEntity::Instance(pentEntity);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CBaseEntity *UTIL_FindEntityByString_Old(CBaseEntity *pStartEntity, const char *szKeyword, const char *szValue)
|
|
{
|
|
edict_t *pentEntity;
|
|
if (pStartEntity)
|
|
pentEntity = pStartEntity->edict();
|
|
else
|
|
pentEntity = nullptr;
|
|
|
|
pentEntity = FIND_ENTITY_BY_STRING(pentEntity, szKeyword, szValue);
|
|
if (!FNullEnt(pentEntity))
|
|
{
|
|
return CBaseEntity::Instance(pentEntity);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CBaseEntity *EXT_FUNC UTIL_FindEntityByString(CBaseEntity *pStartEntity, const char *szKeyword, const char *szValue)
|
|
{
|
|
edict_t *pentEntity;
|
|
int startEntityIndex;
|
|
|
|
if (pStartEntity)
|
|
pentEntity = pStartEntity->edict();
|
|
else
|
|
pentEntity = nullptr;
|
|
|
|
startEntityIndex = ENTINDEX(pentEntity);
|
|
|
|
// it best each entity list
|
|
if (*szKeyword == 'c')
|
|
{
|
|
int hash;
|
|
hash_item_t *item;
|
|
int count;
|
|
|
|
hash = CaseInsensitiveHash(szValue, stringsHashTable.Count());
|
|
count = stringsHashTable.Count();
|
|
item = &stringsHashTable[hash];
|
|
|
|
if (!item->pev)
|
|
{
|
|
item->lastHash = nullptr;
|
|
return nullptr;
|
|
}
|
|
|
|
while (item->pev)
|
|
{
|
|
if (!Q_strcmp(STRING(item->pev->classname), szValue))
|
|
break;
|
|
|
|
hash = (hash + 1) % count;
|
|
item = &stringsHashTable[hash];
|
|
}
|
|
|
|
if (!item->pev)
|
|
{
|
|
item->lastHash = nullptr;
|
|
return nullptr;
|
|
}
|
|
|
|
if (pStartEntity)
|
|
{
|
|
if (item->lastHash && item->lastHash->pevIndex <= startEntityIndex)
|
|
item = item->lastHash;
|
|
|
|
if (item->pevIndex <= startEntityIndex)
|
|
{
|
|
while (item->pevIndex <= startEntityIndex)
|
|
{
|
|
if (!item->next)
|
|
break;
|
|
|
|
item = item->next;
|
|
}
|
|
|
|
if (item->pevIndex == startEntityIndex)
|
|
{
|
|
stringsHashTable[hash].lastHash = nullptr;
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
stringsHashTable[hash].lastHash = item;
|
|
pentEntity = ENT(item->pev);
|
|
}
|
|
else
|
|
pentEntity = FIND_ENTITY_BY_STRING(pentEntity, szKeyword, szValue);
|
|
|
|
if (!FNullEnt(pentEntity))
|
|
{
|
|
return CBaseEntity::Instance(pentEntity);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
CBaseEntity *UTIL_FindEntityByClassname(CBaseEntity *pStartEntity, const char *szName)
|
|
{
|
|
return UTIL_FindEntityByString(pStartEntity, "classname", szName);
|
|
}
|
|
|
|
CBaseEntity *UTIL_FindEntityByTargetname(CBaseEntity *pStartEntity, const char *szName)
|
|
{
|
|
return UTIL_FindEntityByString(pStartEntity, "targetname", szName);
|
|
}
|
|
|
|
CBaseEntity *UTIL_FindEntityGeneric(const char *szWhatever, const Vector &vecSrc, float flRadius)
|
|
{
|
|
CBaseEntity *pSearch = nullptr;
|
|
CBaseEntity *pEntity = UTIL_FindEntityByTargetname(nullptr, szWhatever);
|
|
if (pEntity)
|
|
return pEntity;
|
|
|
|
float flMaxDist2 = flRadius * flRadius;
|
|
while ((pSearch = UTIL_FindEntityByClassname(pSearch, szWhatever)))
|
|
{
|
|
float flDist2 = (pSearch->pev->origin - vecSrc).Length();
|
|
flDist2 = flDist2 * flDist2;
|
|
if (flMaxDist2 > flDist2)
|
|
{
|
|
pEntity = pSearch;
|
|
flMaxDist2 = flDist2;
|
|
}
|
|
}
|
|
|
|
return pEntity;
|
|
}
|
|
|
|
#ifndef REGAMEDLL_FIXES
|
|
CBasePlayer *EXT_FUNC UTIL_PlayerByIndex(int playerIndex)
|
|
{
|
|
CBasePlayer *pPlayer = nullptr;
|
|
if (playerIndex > 0 && playerIndex <= gpGlobals->maxClients)
|
|
{
|
|
edict_t *pPlayerEdict = INDEXENT(playerIndex);
|
|
if (pPlayerEdict && !pPlayerEdict->free)
|
|
pPlayer = CBasePlayer::Instance(pPlayerEdict);
|
|
}
|
|
|
|
return pPlayer;
|
|
}
|
|
#endif
|
|
|
|
void UTIL_MakeVectors(const Vector &vecAngles)
|
|
{
|
|
MAKE_VECTORS(vecAngles);
|
|
}
|
|
|
|
void UTIL_MakeAimVectors(const Vector &vecAngles)
|
|
{
|
|
float rgflVec[3];
|
|
vecAngles.CopyToArray(rgflVec);
|
|
rgflVec[0] = -rgflVec[0];
|
|
MAKE_VECTORS(rgflVec);
|
|
}
|
|
|
|
void UTIL_MakeInvVectors(const Vector &vec, globalvars_t *pgv)
|
|
{
|
|
MAKE_VECTORS(vec);
|
|
|
|
pgv->v_right = pgv->v_right * -1;
|
|
|
|
SWAP(pgv->v_forward.y, pgv->v_right.x);
|
|
SWAP(pgv->v_forward.z, pgv->v_up.x);
|
|
SWAP(pgv->v_right.z, pgv->v_up.y);
|
|
}
|
|
|
|
void UTIL_EmitAmbientSound(edict_t *entity, const Vector &vecOrigin, const char *samp, float vol, float attenuation, int fFlags, int pitch)
|
|
{
|
|
float rgfl[3];
|
|
vecOrigin.CopyToArray(rgfl);
|
|
|
|
if (samp && *samp == '!')
|
|
{
|
|
char name[32];
|
|
if (SENTENCEG_Lookup(samp, name) >= 0)
|
|
EMIT_AMBIENT_SOUND(entity, rgfl, name, vol, attenuation, fFlags, pitch);
|
|
}
|
|
else
|
|
EMIT_AMBIENT_SOUND(entity, rgfl, samp, vol, attenuation, fFlags, pitch);
|
|
}
|
|
|
|
unsigned short FixedUnsigned16(float value, float scale)
|
|
{
|
|
int output = value * scale;
|
|
if (output < 0)
|
|
output = 0;
|
|
|
|
if (output > USHRT_MAX)
|
|
output = USHRT_MAX;
|
|
|
|
return (unsigned short)output;
|
|
}
|
|
|
|
short FixedSigned16(float value, float scale)
|
|
{
|
|
int output = value * scale;
|
|
if (output > SHRT_MAX)
|
|
output = SHRT_MAX;
|
|
|
|
if (output < SHRT_MIN)
|
|
output = SHRT_MIN;
|
|
|
|
return (short)output;
|
|
}
|
|
|
|
void UTIL_ScreenShake(const Vector ¢er, float amplitude, float frequency, float duration, float radius)
|
|
{
|
|
int i;
|
|
float localAmplitude;
|
|
ScreenShake shake;
|
|
|
|
shake.duration = FixedUnsigned16(duration, (1<<12));
|
|
shake.frequency = FixedUnsigned16(frequency, (1<<8));
|
|
|
|
for (i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBaseEntity *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
if (!(pPlayer->pev->flags & FL_ONGROUND))
|
|
continue;
|
|
|
|
localAmplitude = 0;
|
|
if (radius > 0)
|
|
{
|
|
Vector delta = center - pPlayer->pev->origin;
|
|
float distance = delta.Length();
|
|
|
|
if (distance < radius)
|
|
localAmplitude = amplitude;
|
|
}
|
|
else
|
|
localAmplitude = amplitude;
|
|
|
|
if (localAmplitude)
|
|
{
|
|
shake.amplitude = FixedUnsigned16(localAmplitude, 1<<12);
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgShake, nullptr, pPlayer->edict());
|
|
WRITE_SHORT(shake.amplitude);
|
|
WRITE_SHORT(shake.duration);
|
|
WRITE_SHORT(shake.frequency);
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
}
|
|
|
|
NOXREF void UTIL_ScreenShakeAll(const Vector ¢er, float amplitude, float frequency, float duration)
|
|
{
|
|
UTIL_ScreenShake(center, amplitude, frequency, duration, 0);
|
|
}
|
|
|
|
void UTIL_ScreenFadeBuild(ScreenFade &fade, const Vector &color, float fadeTime, float fadeHold, int alpha, int flags)
|
|
{
|
|
fade.duration = FixedUnsigned16(fadeTime, 1<<12);
|
|
fade.holdTime = FixedUnsigned16(fadeHold, 1<<12);
|
|
fade.r = int(color.x);
|
|
fade.g = int(color.y);
|
|
fade.b = int(color.z);
|
|
fade.a = alpha;
|
|
fade.fadeFlags = flags;
|
|
}
|
|
|
|
void UTIL_ScreenFadeWrite(const ScreenFade &fade, CBaseEntity *pEntity)
|
|
{
|
|
if (!UTIL_IsValidPlayer(pEntity))
|
|
return;
|
|
|
|
if (!pEntity->IsNetClient())
|
|
return;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgFade, nullptr, pEntity->edict());
|
|
WRITE_SHORT(fade.duration);
|
|
WRITE_SHORT(fade.holdTime);
|
|
WRITE_SHORT(fade.fadeFlags);
|
|
WRITE_BYTE(fade.r);
|
|
WRITE_BYTE(fade.g);
|
|
WRITE_BYTE(fade.b);
|
|
WRITE_BYTE(fade.a);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_ScreenFadeAll(const Vector &color, float fadeTime, float fadeHold, int alpha, int flags)
|
|
{
|
|
int i;
|
|
ScreenFade fade;
|
|
UTIL_ScreenFadeBuild(fade, color, fadeTime, fadeHold, alpha, flags);
|
|
for (i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBaseEntity *pPlayer = UTIL_PlayerByIndex(i);
|
|
UTIL_ScreenFadeWrite(fade, pPlayer);
|
|
}
|
|
}
|
|
|
|
void UTIL_ScreenFade(CBaseEntity *pEntity, const Vector &color, float fadeTime, float fadeHold, int alpha, int flags)
|
|
{
|
|
ScreenFade fade;
|
|
UTIL_ScreenFadeBuild(fade, color, fadeTime, fadeHold, alpha, flags);
|
|
UTIL_ScreenFadeWrite(fade, pEntity);
|
|
}
|
|
|
|
void UTIL_HudMessage(CBaseEntity *pEntity, const hudtextparms_t &textparms, const char *pMessage)
|
|
{
|
|
if (!pEntity || !pEntity->IsNetClient())
|
|
return;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, pEntity->edict());
|
|
WRITE_BYTE(TE_TEXTMESSAGE);
|
|
WRITE_BYTE(textparms.channel & 0xFF);
|
|
WRITE_SHORT(FixedSigned16(textparms.x, (1<<13)));
|
|
WRITE_SHORT(FixedSigned16(textparms.y, (1<<13)));
|
|
WRITE_BYTE(textparms.effect);
|
|
WRITE_BYTE(textparms.r1);
|
|
WRITE_BYTE(textparms.g1);
|
|
WRITE_BYTE(textparms.b1);
|
|
WRITE_BYTE(textparms.a1);
|
|
WRITE_BYTE(textparms.r2);
|
|
WRITE_BYTE(textparms.g2);
|
|
WRITE_BYTE(textparms.b2);
|
|
WRITE_BYTE(textparms.a2);
|
|
WRITE_SHORT(FixedUnsigned16(textparms.fadeinTime, (1<<8)));
|
|
WRITE_SHORT(FixedUnsigned16(textparms.fadeoutTime, (1<<8)));
|
|
WRITE_SHORT(FixedUnsigned16(textparms.holdTime, (1<<8)));
|
|
|
|
if (textparms.effect == 2)
|
|
WRITE_SHORT(FixedUnsigned16(textparms.fxTime, (1<<8)));
|
|
|
|
if (!pMessage)
|
|
WRITE_STRING(" ");
|
|
else
|
|
{
|
|
if (Q_strlen(pMessage) >= 512)
|
|
{
|
|
char tmp[512];
|
|
Q_strlcpy(tmp, pMessage);
|
|
WRITE_STRING(tmp);
|
|
}
|
|
else
|
|
{
|
|
WRITE_STRING(pMessage);
|
|
}
|
|
}
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_HudMessageAll(const hudtextparms_t &textparms, const char *pMessage)
|
|
{
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBaseEntity *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
UTIL_HudMessage(pPlayer, textparms, pMessage);
|
|
}
|
|
}
|
|
|
|
void UTIL_ClientPrintAll(int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgTextMsg);
|
|
WRITE_BYTE(msg_dest);
|
|
WRITE_STRING(msg_name);
|
|
if (param1)
|
|
WRITE_STRING(param1);
|
|
if (param2)
|
|
WRITE_STRING(param2);
|
|
if (param3)
|
|
WRITE_STRING(param3);
|
|
if (param4)
|
|
WRITE_STRING(param4);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void ClientPrint(entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgTextMsg, nullptr, client);
|
|
WRITE_BYTE(msg_dest);
|
|
WRITE_STRING(msg_name);
|
|
if (param1)
|
|
WRITE_STRING(param1);
|
|
if (param2)
|
|
WRITE_STRING(param2);
|
|
if (param3)
|
|
WRITE_STRING(param3);
|
|
if (param4)
|
|
WRITE_STRING(param4);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_Log(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
static char string[1024];
|
|
|
|
va_start(ap, fmt);
|
|
Q_vsnprintf(string, sizeof(string), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Q_strlcat(string, "\n");
|
|
|
|
FILE *fp = fopen("regamedll.log", "at");
|
|
if (fp)
|
|
{
|
|
fprintf(fp, "%s", string);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void UTIL_ServerPrint(const char *fmt, ...)
|
|
{
|
|
#ifdef PLAY_GAMEDLL
|
|
// Check is null, test the demo started before than searches pointer to refs
|
|
if (&g_engfuncs == nullptr || g_engfuncs.pfnServerPrint == nullptr)
|
|
return;
|
|
#endif
|
|
|
|
static char string[1024];
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
Q_vsnprintf(string, sizeof(string), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Q_strlcat(string, "\n");
|
|
|
|
SERVER_PRINT(string);
|
|
}
|
|
|
|
void UTIL_PrintConsole(edict_t *pEdict, const char *fmt, ...)
|
|
{
|
|
CBaseEntity *pEntity = GET_PRIVATE<CBaseEntity>(pEdict);
|
|
if (!pEntity || !pEntity->IsNetClient())
|
|
return;
|
|
|
|
static char string[1024];
|
|
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
Q_vsnprintf(string, sizeof(string), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Q_strlcat(string, "\n");
|
|
|
|
ClientPrint(pEntity->pev, HUD_PRINTCONSOLE, string);
|
|
}
|
|
|
|
void UTIL_SayText(edict_t *pEdict, const char *fmt, ...)
|
|
{
|
|
CBaseEntity *pEntity = GET_PRIVATE<CBaseEntity>(pEdict);
|
|
if (!pEntity || !pEntity->IsNetClient())
|
|
return;
|
|
|
|
static char string[1024];
|
|
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
Q_vsnprintf(string, sizeof(string), fmt, ap);
|
|
va_end(ap);
|
|
|
|
Q_strlcat(string, "\n");
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEntity->edict());
|
|
WRITE_BYTE(pEntity->entindex());
|
|
WRITE_STRING(string);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_SayTextAll(const char *pText, CBaseEntity *pEntity)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgSayText);
|
|
WRITE_BYTE(pEntity->entindex());
|
|
WRITE_STRING(pText);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
char *UTIL_dtos1(int d)
|
|
{
|
|
static char buf[12];
|
|
Q_snprintf(buf, sizeof(buf), "%d", d);
|
|
return buf;
|
|
}
|
|
|
|
char *UTIL_dtos2(int d)
|
|
{
|
|
static char buf[12];
|
|
Q_snprintf(buf, sizeof(buf), "%d", d);
|
|
return buf;
|
|
}
|
|
|
|
NOXREF char *UTIL_dtos3(int d)
|
|
{
|
|
static char buf[12];
|
|
Q_snprintf(buf, sizeof(buf), "%d", d);
|
|
return buf;
|
|
}
|
|
|
|
NOXREF char *UTIL_dtos4(int d)
|
|
{
|
|
static char buf[12];
|
|
Q_snprintf(buf, sizeof(buf), "%d", d);
|
|
return buf;
|
|
}
|
|
|
|
void UTIL_ShowMessageArgs(const char *pString, CBaseEntity *pPlayer, CUtlVector<char *> *args, bool isHint)
|
|
{
|
|
if (!pPlayer)
|
|
return;
|
|
|
|
if (!pPlayer->IsNetClient())
|
|
return;
|
|
|
|
if (args)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgHudTextArgs, nullptr, pPlayer->pev);
|
|
WRITE_STRING(pString);
|
|
WRITE_BYTE(isHint);
|
|
WRITE_BYTE(args->Count());
|
|
|
|
for (int i = 0; i < args->Count(); i++)
|
|
WRITE_STRING((*args)[i]);
|
|
|
|
MESSAGE_END();
|
|
}
|
|
else
|
|
{
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgHudTextPro, nullptr, pPlayer->pev);
|
|
WRITE_STRING(pString);
|
|
WRITE_BYTE(isHint);
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
void UTIL_ShowMessage(const char *pString, CBaseEntity *pEntity, bool isHint)
|
|
{
|
|
if (!pEntity || !pEntity->IsNetClient())
|
|
return;
|
|
|
|
MESSAGE_BEGIN(MSG_ONE, gmsgHudTextPro, nullptr, pEntity->edict());
|
|
WRITE_STRING(pString);
|
|
WRITE_BYTE(int(isHint));
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_ShowMessageAll(const char *pString, bool isHint)
|
|
{
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBaseEntity *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
UTIL_ShowMessage(pString, pPlayer, isHint);
|
|
}
|
|
}
|
|
|
|
void UTIL_TraceLine(const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr)
|
|
{
|
|
TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters), pentIgnore, ptr);
|
|
}
|
|
|
|
// OVERLOAD
|
|
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) | (ignoreGlass ? 0x100 : 0), pentIgnore, ptr);
|
|
}
|
|
|
|
void UTIL_TraceHull(const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr)
|
|
{
|
|
TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters), hullNumber, pentIgnore, ptr);
|
|
}
|
|
|
|
void UTIL_TraceModel(const Vector &vecStart, const Vector &vecEnd, int hullNumber, edict_t *pentModel, TraceResult *ptr)
|
|
{
|
|
TRACE_MODEL(vecStart, vecEnd, hullNumber, pentModel, ptr);
|
|
}
|
|
|
|
NOXREF TraceResult UTIL_GetGlobalTrace()
|
|
{
|
|
TraceResult tr;
|
|
|
|
tr.flFraction = gpGlobals->trace_fraction;
|
|
tr.fInWater = int(gpGlobals->trace_inwater);
|
|
tr.fAllSolid = int(gpGlobals->trace_allsolid);
|
|
tr.fStartSolid = int(gpGlobals->trace_startsolid);
|
|
tr.fInOpen = int(gpGlobals->trace_inopen);
|
|
tr.vecEndPos = gpGlobals->trace_endpos;
|
|
tr.flPlaneDist = gpGlobals->trace_plane_dist;
|
|
tr.vecPlaneNormal = gpGlobals->trace_plane_normal;
|
|
tr.iHitgroup = gpGlobals->trace_hitgroup;
|
|
tr.pHit = gpGlobals->trace_ent;
|
|
|
|
return tr;
|
|
}
|
|
|
|
void UTIL_SetSize(entvars_t *pev, const Vector &vecMin, const Vector &vecMax)
|
|
{
|
|
SET_SIZE(ENT(pev), vecMin, vecMax);
|
|
}
|
|
|
|
float UTIL_VecToYaw(const Vector &vec)
|
|
{
|
|
return VEC_TO_YAW(vec);
|
|
}
|
|
|
|
void UTIL_SetOrigin(entvars_t *pev, const Vector &vecOrigin)
|
|
{
|
|
edict_t *pEdict = ENT(pev);
|
|
if (pEdict)
|
|
{
|
|
SET_ORIGIN(pEdict, vecOrigin);
|
|
}
|
|
}
|
|
|
|
NOXREF void UTIL_ParticleEffect(const Vector &vecOrigin, const Vector &vecDirection, ULONG ulColor, ULONG ulCount)
|
|
{
|
|
PARTICLE_EFFECT(vecOrigin, vecDirection, float(ulColor), float(ulCount));
|
|
}
|
|
|
|
float UTIL_Approach(float target, float value, float speed)
|
|
{
|
|
float delta = target - value;
|
|
if (delta > speed)
|
|
value += speed;
|
|
else if (delta < -speed)
|
|
value -= speed;
|
|
else
|
|
value = target;
|
|
|
|
return value;
|
|
}
|
|
|
|
real_t UTIL_ApproachAngle(float target, float value, float speed)
|
|
{
|
|
target = UTIL_AngleMod(target);
|
|
|
|
#ifdef REGAMEDLL_FIXES
|
|
value = UTIL_AngleMod(value);
|
|
#else
|
|
value = UTIL_AngleMod(target);
|
|
#endif
|
|
|
|
float delta = target - value;
|
|
if (speed < 0.0f)
|
|
speed = -speed;
|
|
|
|
if (delta < -180.0f)
|
|
delta += 360.0f;
|
|
else if (delta > 180.0f)
|
|
delta -= 360.0f;
|
|
|
|
if (delta > speed)
|
|
value += speed;
|
|
else if (delta < -speed)
|
|
value -= speed;
|
|
else
|
|
value = target;
|
|
|
|
return value;
|
|
}
|
|
|
|
real_t UTIL_AngleDistance(float next, float cur)
|
|
{
|
|
real_t delta;
|
|
|
|
delta = next - cur;
|
|
|
|
if (delta < -180.0f)
|
|
delta += 360.0f;
|
|
|
|
else if (delta > 180.0f)
|
|
delta -= 360.0f;
|
|
|
|
return delta;
|
|
}
|
|
|
|
float UTIL_SplineFraction(float value, float scale)
|
|
{
|
|
float valueSquared = value * scale;
|
|
return 3.0f * (valueSquared * valueSquared) - (valueSquared * valueSquared * valueSquared + valueSquared * valueSquared * valueSquared);
|
|
}
|
|
|
|
char *UTIL_VarArgs(char *format, ...)
|
|
{
|
|
va_list argptr;
|
|
static char string[1024];
|
|
|
|
va_start(argptr, format);
|
|
Q_vsnprintf(string, sizeof(string), format, argptr);
|
|
va_end(argptr);
|
|
|
|
return string;
|
|
}
|
|
|
|
NOXREF Vector UTIL_GetAimVector(edict_t *pent, float flSpeed)
|
|
{
|
|
Vector tmp;
|
|
GET_AIM_VECTOR(pent, flSpeed, tmp);
|
|
return tmp;
|
|
}
|
|
|
|
bool UTIL_IsMasterTriggered(string_t sMaster, CBaseEntity *pActivator)
|
|
{
|
|
if (sMaster)
|
|
{
|
|
edict_t *pentTarget = FIND_ENTITY_BY_TARGETNAME(nullptr, STRING(sMaster));
|
|
if (!FNullEnt(pentTarget))
|
|
{
|
|
CBaseEntity *pMaster = CBaseEntity::Instance(pentTarget);
|
|
if (pMaster && (pMaster->ObjectCaps() & FCAP_MASTER))
|
|
return pMaster->IsTriggered(pActivator) != FALSE;
|
|
}
|
|
|
|
ALERT(at_console, "Master was null or not a master!\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL UTIL_ShouldShowBlood(int color)
|
|
{
|
|
if (color != DONT_BLEED)
|
|
{
|
|
if (color == BLOOD_COLOR_RED)
|
|
{
|
|
if (CVAR_GET_FLOAT("violence_hblood") != 0.0f)
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (CVAR_GET_FLOAT("violence_ablood") != 0.0f)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int UTIL_PointContents(const Vector &vec)
|
|
{
|
|
return POINT_CONTENTS(vec);
|
|
}
|
|
|
|
void UTIL_BloodStream(const Vector &origin, const Vector &direction, int color, int amount)
|
|
{
|
|
if (!UTIL_ShouldShowBlood(color))
|
|
return;
|
|
|
|
if (g_Language == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED)
|
|
color = 0;
|
|
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, origin);
|
|
WRITE_BYTE(TE_BLOODSTREAM);
|
|
WRITE_COORD(origin.x);
|
|
WRITE_COORD(origin.y);
|
|
WRITE_COORD(origin.z);
|
|
WRITE_COORD(direction.x);
|
|
WRITE_COORD(direction.y);
|
|
WRITE_COORD(direction.z);
|
|
WRITE_BYTE(color);
|
|
WRITE_BYTE(Q_min(amount, 255));
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_BloodDrips(const Vector &origin, int color, int amount)
|
|
{
|
|
if (!UTIL_ShouldShowBlood(color))
|
|
return;
|
|
|
|
if (color == DONT_BLEED || amount == 0)
|
|
return;
|
|
|
|
if (g_Language == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED)
|
|
color = 0;
|
|
|
|
if (g_pGameRules->IsMultiplayer())
|
|
amount *= 2;
|
|
|
|
if (amount > 255)
|
|
amount = 255;
|
|
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, origin);
|
|
WRITE_BYTE(TE_BLOODSPRITE);
|
|
WRITE_COORD(origin.x);
|
|
WRITE_COORD(origin.y);
|
|
WRITE_COORD(origin.z);
|
|
WRITE_SHORT(g_sModelIndexBloodSpray);
|
|
WRITE_SHORT(g_sModelIndexBloodDrop);
|
|
WRITE_BYTE(color);
|
|
WRITE_BYTE(clamp(amount / 10, 3, 16));
|
|
MESSAGE_END();
|
|
}
|
|
|
|
Vector UTIL_RandomBloodVector()
|
|
{
|
|
Vector direction;
|
|
direction.x = RANDOM_FLOAT(-1, 1);
|
|
direction.y = RANDOM_FLOAT(-1, 1);
|
|
direction.z = RANDOM_FLOAT(0, 1);
|
|
return direction;
|
|
}
|
|
|
|
void UTIL_BloodDecalTrace(TraceResult *pTrace, int bloodColor)
|
|
{
|
|
if (UTIL_ShouldShowBlood(bloodColor))
|
|
{
|
|
if (bloodColor == BLOOD_COLOR_RED)
|
|
UTIL_DecalTrace(pTrace, DECAL_BLOOD1 + RANDOM_LONG(0, 5));
|
|
else
|
|
UTIL_DecalTrace(pTrace, DECAL_YBLOOD1 + RANDOM_LONG(0, 5));
|
|
}
|
|
}
|
|
|
|
void UTIL_DecalTrace(TraceResult *pTrace, int decalNumber)
|
|
{
|
|
short entityIndex;
|
|
int index;
|
|
int message;
|
|
|
|
if (decalNumber < 0)
|
|
return;
|
|
|
|
index = gDecals[decalNumber].index;
|
|
if (index < 0 || pTrace->flFraction == 1.0f)
|
|
return;
|
|
|
|
if (pTrace->pHit)
|
|
{
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(pTrace->pHit);
|
|
if (pEntity && !pEntity->IsBSPModel())
|
|
return;
|
|
|
|
entityIndex = ENTINDEX(pTrace->pHit);
|
|
}
|
|
else
|
|
entityIndex = 0;
|
|
|
|
message = TE_DECAL;
|
|
if (entityIndex)
|
|
{
|
|
if (index > 255)
|
|
{
|
|
message = TE_DECALHIGH;
|
|
index -= 256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
message = TE_WORLDDECAL;
|
|
if (index > 255)
|
|
{
|
|
message = TE_WORLDDECALHIGH;
|
|
index -= 256;
|
|
}
|
|
}
|
|
|
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WRITE_BYTE(message);
|
|
WRITE_COORD(pTrace->vecEndPos.x);
|
|
WRITE_COORD(pTrace->vecEndPos.y);
|
|
WRITE_COORD(pTrace->vecEndPos.z);
|
|
WRITE_BYTE(index);
|
|
if (entityIndex)
|
|
WRITE_SHORT(entityIndex);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_PlayerDecalTrace(TraceResult *pTrace, int playernum, int decalNumber, BOOL bIsCustom)
|
|
{
|
|
int index;
|
|
if (!bIsCustom)
|
|
{
|
|
if (decalNumber < 0)
|
|
return;
|
|
|
|
index = gDecals[decalNumber].index;
|
|
if (index < 0)
|
|
return;
|
|
}
|
|
else
|
|
index = decalNumber;
|
|
|
|
if (pTrace->flFraction != 1.0f)
|
|
{
|
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WRITE_BYTE(TE_PLAYERDECAL);
|
|
WRITE_BYTE(playernum);
|
|
WRITE_COORD(pTrace->vecEndPos.x);
|
|
WRITE_COORD(pTrace->vecEndPos.y);
|
|
WRITE_COORD(pTrace->vecEndPos.z);
|
|
WRITE_SHORT(int(ENTINDEX(pTrace->pHit)));
|
|
WRITE_BYTE(index);
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
void UTIL_GunshotDecalTrace(TraceResult *pTrace, int decalNumber, bool ClientOnly, entvars_t *pShooter)
|
|
{
|
|
if (decalNumber < 0)
|
|
return;
|
|
|
|
int index = gDecals[decalNumber].index;
|
|
if (index < 0 || pTrace->flFraction == 1.0f)
|
|
return;
|
|
|
|
if (ClientOnly)
|
|
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, pTrace->vecEndPos, pShooter);
|
|
else
|
|
MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pTrace->vecEndPos);
|
|
|
|
WRITE_BYTE(TE_GUNSHOTDECAL);
|
|
WRITE_COORD(pTrace->vecEndPos.x);
|
|
WRITE_COORD(pTrace->vecEndPos.y);
|
|
WRITE_COORD(pTrace->vecEndPos.z);
|
|
WRITE_SHORT(int(ENTINDEX(pTrace->pHit)));
|
|
WRITE_BYTE(index);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_Sparks(const Vector &position)
|
|
{
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, position);
|
|
WRITE_BYTE(TE_SPARKS);
|
|
WRITE_COORD(position.x);
|
|
WRITE_COORD(position.y);
|
|
WRITE_COORD(position.z);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_Ricochet(const Vector &position, float scale)
|
|
{
|
|
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, position);
|
|
WRITE_BYTE(TE_ARMOR_RICOCHET);
|
|
WRITE_COORD(position.x);
|
|
WRITE_COORD(position.y);
|
|
WRITE_COORD(position.z);
|
|
WRITE_BYTE(int(scale * 10.0f));
|
|
MESSAGE_END();
|
|
}
|
|
|
|
bool UTIL_TeamsMatch(const char *pTeamName1, const char *pTeamName2)
|
|
{
|
|
if (!g_pGameRules->IsTeamplay())
|
|
return true;
|
|
|
|
if (*pTeamName1 != '\0' && *pTeamName2 != '\0')
|
|
{
|
|
if (!Q_stricmp(pTeamName1, pTeamName2))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UTIL_StringToVector(float *pVector, const char *pString)
|
|
{
|
|
char *pstr;
|
|
char *pfront;
|
|
char tempString[128];
|
|
int j;
|
|
|
|
Q_strlcpy(tempString, pString);
|
|
|
|
pstr = tempString;
|
|
pfront = tempString;
|
|
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
pVector[j] = Q_atof(pfront);
|
|
|
|
while (*pstr && *pstr != ' ')
|
|
pstr++;
|
|
|
|
if (!*pstr)
|
|
break;
|
|
|
|
pstr++;
|
|
pfront = pstr;
|
|
}
|
|
|
|
for (j++; j < 3; j++)
|
|
pVector[j] = 0;
|
|
}
|
|
|
|
void UTIL_StringToVector(Vector &vecIn, const char *pString, char cSeparator)
|
|
{
|
|
return UTIL_StringToVectorND(vecIn, 3, pString, cSeparator);
|
|
}
|
|
|
|
void UTIL_StringToVectorND(Vector &vecIn, int nCount, const char *pString, char cSeparator)
|
|
{
|
|
int i;
|
|
char *pstr;
|
|
char *pfront;
|
|
char tempString[128];
|
|
|
|
Q_strlcpy(tempString, pString);
|
|
|
|
pstr = tempString;
|
|
pfront = tempString;
|
|
|
|
for (i = 0; i < nCount; i++)
|
|
{
|
|
vecIn[i] = Q_atof(pfront);
|
|
|
|
while (*pstr && *pstr != cSeparator)
|
|
pstr++;
|
|
|
|
if (!*pstr)
|
|
break;
|
|
|
|
pstr++;
|
|
pfront = pstr;
|
|
}
|
|
|
|
if (++i < nCount)
|
|
{
|
|
Q_memset(&vecIn[i], 0, sizeof(float) * (nCount - i));
|
|
}
|
|
}
|
|
|
|
void UTIL_StringToIntArray(int *pVector, int count, const char *pString)
|
|
{
|
|
char *pstr;
|
|
char *pfront;
|
|
char tempString[128];
|
|
int j;
|
|
|
|
Q_strlcpy(tempString, pString);
|
|
|
|
pstr = tempString;
|
|
pfront = tempString;
|
|
|
|
for (j = 0; j < count; j++)
|
|
{
|
|
pVector[j] = Q_atoi(pfront);
|
|
|
|
while (*pstr && *pstr != ' ')
|
|
pstr++;
|
|
|
|
if (!*pstr)
|
|
break;
|
|
|
|
pstr++;
|
|
pfront = pstr;
|
|
}
|
|
|
|
for (j++; j < count; j++)
|
|
pVector[j] = 0;
|
|
}
|
|
|
|
Vector UTIL_ClampVectorToBox(const Vector &input, const Vector &clampSize)
|
|
{
|
|
Vector sourceVector = input;
|
|
if (sourceVector.x > clampSize.x)
|
|
sourceVector.x -= clampSize.x;
|
|
else if (sourceVector.x < -clampSize.x)
|
|
sourceVector.x += clampSize.x;
|
|
else
|
|
sourceVector.x = 0;
|
|
if (sourceVector.y > clampSize.y)
|
|
sourceVector.y -= clampSize.y;
|
|
else if (sourceVector.y < -clampSize.y)
|
|
sourceVector.y += clampSize.y;
|
|
else
|
|
sourceVector.y = 0;
|
|
if (sourceVector.z > clampSize.z)
|
|
sourceVector.z -= clampSize.z;
|
|
else if (sourceVector.z < -clampSize.z)
|
|
sourceVector.z += clampSize.z;
|
|
else
|
|
sourceVector.z = 0;
|
|
return sourceVector.Normalize();
|
|
}
|
|
|
|
float UTIL_WaterLevel(const Vector &position, float minz, float maxz)
|
|
{
|
|
Vector midUp;
|
|
float diff;
|
|
|
|
midUp = position;
|
|
midUp.z = minz;
|
|
|
|
if (UTIL_PointContents(midUp) != CONTENTS_WATER)
|
|
return minz;
|
|
|
|
midUp.z = maxz;
|
|
if (UTIL_PointContents(midUp) == CONTENTS_WATER)
|
|
return maxz;
|
|
|
|
diff = maxz - minz;
|
|
while (diff > 1)
|
|
{
|
|
midUp.z = minz + diff / 2;
|
|
if (UTIL_PointContents(midUp) == CONTENTS_WATER)
|
|
minz = midUp.z;
|
|
else
|
|
maxz = midUp.z;
|
|
|
|
diff = maxz - minz;
|
|
}
|
|
|
|
return midUp.z;
|
|
}
|
|
|
|
void UTIL_Bubbles(Vector mins, Vector maxs, int count)
|
|
{
|
|
Vector mid = (mins + maxs) * 0.5f;
|
|
float flHeight = UTIL_WaterLevel(mid, mid.z, mid.z + 1024.0f) - mins.z;
|
|
|
|
MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, mid);
|
|
WRITE_BYTE(TE_BUBBLES);
|
|
WRITE_COORD(mins.x);
|
|
WRITE_COORD(mins.y);
|
|
WRITE_COORD(mins.z);
|
|
WRITE_COORD(maxs.x);
|
|
WRITE_COORD(maxs.y);
|
|
WRITE_COORD(maxs.z);
|
|
WRITE_COORD(flHeight);
|
|
WRITE_SHORT(g_sModelIndexBubbles);
|
|
WRITE_BYTE(count);
|
|
WRITE_COORD(8);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_BubbleTrail(Vector from, Vector to, int count)
|
|
{
|
|
float flHeight = UTIL_WaterLevel(from, from.z, from.z + 256.0f) - from.z;
|
|
if (flHeight < 8.0f)
|
|
{
|
|
flHeight = UTIL_WaterLevel(to, to.z, to.z + 256.0f) - to.z;
|
|
|
|
if (flHeight < 8.0f)
|
|
return;
|
|
|
|
flHeight = flHeight + to.z - from.z;
|
|
}
|
|
|
|
if (count > 255)
|
|
count = 255;
|
|
|
|
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WRITE_BYTE(TE_BUBBLETRAIL);
|
|
WRITE_COORD(from.x);
|
|
WRITE_COORD(from.y);
|
|
WRITE_COORD(from.z);
|
|
WRITE_COORD(to.x);
|
|
WRITE_COORD(to.y);
|
|
WRITE_COORD(to.z);
|
|
WRITE_COORD(flHeight);
|
|
WRITE_SHORT(g_sModelIndexBubbles);
|
|
WRITE_BYTE(count);
|
|
WRITE_COORD(8);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void UTIL_Remove(CBaseEntity *pEntity)
|
|
{
|
|
if (!pEntity)
|
|
return;
|
|
|
|
#ifdef REGAMEDLL_FIXES
|
|
if (pEntity->pev == VARS(eoNullEntity) || pEntity->IsPlayer() || (pEntity->pev->flags & FL_KILLME) == FL_KILLME)
|
|
return;
|
|
#endif
|
|
|
|
pEntity->UpdateOnRemove();
|
|
|
|
pEntity->pev->solid = SOLID_NOT;
|
|
pEntity->pev->flags |= FL_KILLME;
|
|
pEntity->pev->targetname = 0;
|
|
}
|
|
|
|
NOXREF BOOL UTIL_IsValidEntity(edict_t *pent)
|
|
{
|
|
if (!pent || pent->free || (pent->v.flags & FL_KILLME))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void UTIL_PrecacheOther(const char *szClassname)
|
|
{
|
|
edict_t *pent = CREATE_NAMED_ENTITY(MAKE_STRING(szClassname));
|
|
if (FNullEnt(pent))
|
|
{
|
|
ALERT(at_console, "NULL Ent in UTIL_PrecacheOther classname `%s`\n", szClassname);
|
|
return;
|
|
}
|
|
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(VARS(pent));
|
|
if (pEntity)
|
|
{
|
|
pEntity->Precache();
|
|
}
|
|
|
|
REMOVE_ENTITY(pent);
|
|
}
|
|
|
|
void UTIL_RestartOther(const char *szClassname)
|
|
{
|
|
CBaseEntity *pEntity = nullptr;
|
|
while ((pEntity = UTIL_FindEntityByClassname(pEntity, szClassname)))
|
|
{
|
|
pEntity->Restart();
|
|
|
|
#ifdef REGAMEDLL_ADD
|
|
FireTargets("game_entity_restart", pEntity, nullptr, USE_TOGGLE, 0.0);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void UTIL_ResetEntities()
|
|
{
|
|
for (int i = 1; i < gpGlobals->maxEntities; i++)
|
|
{
|
|
edict_t *pEdict = INDEXENT(i);
|
|
if (!pEdict || pEdict->free)
|
|
continue;
|
|
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(pEdict);
|
|
if (!pEntity)
|
|
continue;
|
|
|
|
// only non-player entities
|
|
if (pEntity->IsPlayer())
|
|
continue;
|
|
|
|
int caps = pEntity->ObjectCaps();
|
|
if ((caps & FCAP_MUST_RELEASE) == FCAP_MUST_RELEASE)
|
|
UTIL_Remove(pEntity);
|
|
|
|
else if ((caps & FCAP_MUST_RESET) == FCAP_MUST_RESET)
|
|
pEntity->Restart();
|
|
}
|
|
}
|
|
|
|
void UTIL_RemoveOther(const char *szClassname, int nRemoveCount)
|
|
{
|
|
int num = 0;
|
|
CBaseEntity *pEntity = nullptr;
|
|
while ((pEntity = UTIL_FindEntityByClassname(pEntity, szClassname)))
|
|
{
|
|
#ifndef REGAMEDLL_FIXES
|
|
if (nRemoveCount > 0 && num++ >= nRemoveCount)
|
|
break;
|
|
#endif
|
|
|
|
UTIL_Remove(pEntity);
|
|
}
|
|
}
|
|
|
|
void UTIL_LogPrintf(const char *fmt, ...)
|
|
{
|
|
va_list argptr;
|
|
static char string[1024];
|
|
|
|
va_start(argptr, fmt);
|
|
Q_vsnprintf(string, sizeof(string), fmt, argptr);
|
|
va_end(argptr);
|
|
|
|
ALERT(at_logged, "%s", string);
|
|
}
|
|
|
|
NOXREF float UTIL_DotPoints(const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir)
|
|
{
|
|
Vector2D vec2LOS = (vecCheck - vecSrc).Make2D();
|
|
vec2LOS = vec2LOS.Normalize();
|
|
return DotProduct(vec2LOS, (vecDir.Make2D()));
|
|
}
|
|
|
|
char UTIL_TextureHit(TraceResult *ptr, Vector vecSrc, Vector vecEnd)
|
|
{
|
|
char chTextureType;
|
|
float rgfl1[3];
|
|
float rgfl2[3];
|
|
const char *pTextureName;
|
|
char szbuffer[MAX_TEXTURENAME_LENGHT];
|
|
CBaseEntity *pEntity = CBaseEntity::Instance(ptr->pHit);
|
|
|
|
#ifdef REGAMEDLL_FIXES
|
|
if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE && pEntity->Classify() != CLASS_VEHICLE)
|
|
#else
|
|
if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
|
|
#endif
|
|
return CHAR_TEX_FLESH;
|
|
|
|
vecSrc.CopyToArray(rgfl1);
|
|
vecEnd.CopyToArray(rgfl2);
|
|
|
|
if (pEntity)
|
|
pTextureName = TRACE_TEXTURE(ENT(pEntity->pev), rgfl1, rgfl2);
|
|
else
|
|
pTextureName = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2);
|
|
|
|
if (pTextureName)
|
|
{
|
|
if (*pTextureName == '-' || *pTextureName == '+')
|
|
pTextureName += 2;
|
|
|
|
if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
|
|
pTextureName++;
|
|
|
|
Q_strlcpy(szbuffer, pTextureName);
|
|
|
|
chTextureType = TEXTURETYPE_Find(szbuffer);
|
|
}
|
|
else
|
|
chTextureType = '\0';
|
|
|
|
return chTextureType;
|
|
}
|
|
|
|
NOXREF int GetPlayerTeam(int index)
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndexSafe(index);
|
|
if (pPlayer)
|
|
{
|
|
return pPlayer->m_iTeam;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool UTIL_IsGame(const char *pszGameName)
|
|
{
|
|
#ifndef CSTRIKE
|
|
if (pszGameName)
|
|
{
|
|
char szGameDir[256];
|
|
GET_GAME_DIR(szGameDir);
|
|
return (Q_stricmp(szGameDir, pszGameName) == 0);
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
real_t UTIL_GetPlayerGaitYaw(int playerIndex)
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(playerIndex);
|
|
if (pPlayer)
|
|
{
|
|
return pPlayer->m_flGaityaw;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int UTIL_ReadFlags(const char *c)
|
|
{
|
|
int flags = 0;
|
|
|
|
while (*c)
|
|
{
|
|
if (*c >= 'a' && *c <= 'z')
|
|
{
|
|
flags |= (1 << (*c - 'a'));
|
|
}
|
|
|
|
c++;
|
|
}
|
|
|
|
return flags;
|
|
}
|
|
|
|
// Determine whether bots can be used or not
|
|
bool UTIL_AreBotsAllowed()
|
|
{
|
|
#ifdef REGAMEDLL_ADD
|
|
if (g_engfuncs.pfnEngCheckParm == nullptr)
|
|
return false;
|
|
#endif
|
|
|
|
if (AreRunningCZero())
|
|
{
|
|
#ifdef REGAMEDLL_ADD
|
|
// If they pass in -nobots, don't allow bots. This is for people who host servers, to
|
|
// allow them to disallow bots to enforce CPU limits.
|
|
int nobots = ENG_CHECK_PARM("-nobots", nullptr);
|
|
if (nobots)
|
|
{
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef REGAMEDLL_ADD
|
|
// let enables zBot by default from listen server?
|
|
if (!IS_DEDICATED_SERVER())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// allow the using of bots for CS 1.6
|
|
int bots = ENG_CHECK_PARM("-bots", nullptr);
|
|
if (bots)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UTIL_IsBeta()
|
|
{
|
|
#ifdef BUILD_LATEST
|
|
if (g_engfuncs.pfnEngCheckParm == nullptr)
|
|
return false;
|
|
|
|
// always beta from listen server
|
|
if (!IS_DEDICATED_SERVER())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
int beta = ENG_CHECK_PARM("-beta", nullptr);
|
|
if (beta)
|
|
{
|
|
return true;
|
|
}
|
|
#endif // #ifdef BUILD_LATEST
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UTIL_AreHostagesImprov()
|
|
{
|
|
if (AreRunningCZero())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#ifdef REGAMEDLL_ADD
|
|
if (g_engfuncs.pfnEngCheckParm == nullptr)
|
|
return false;
|
|
|
|
// someday in CS 1.6
|
|
int improv = ENG_CHECK_PARM("-host-improv", nullptr);
|
|
if (improv)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
int UTIL_GetNumPlayers()
|
|
{
|
|
int nNumPlayers = 0;
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
nNumPlayers++;
|
|
}
|
|
|
|
return nNumPlayers;
|
|
}
|
|
|
|
int UTIL_CountEntities(const char *szName)
|
|
{
|
|
int count = 0;
|
|
CBaseEntity *pEnt = nullptr;
|
|
|
|
while ((pEnt = UTIL_FindEntityByClassname(pEnt, szName)))
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
bool UTIL_IsSpawnPointOccupied(CBaseEntity *pSpot)
|
|
{
|
|
if (!pSpot)
|
|
return false;
|
|
|
|
const int maxList = 8;
|
|
CBaseEntity *pList[maxList];
|
|
|
|
Vector mins(pSpot->pev->origin + VEC_SPOT_HULL_MIN - 8.0);
|
|
Vector maxs(pSpot->pev->origin + VEC_SPOT_HULL_MAX + 8.0);
|
|
|
|
int nCount = UTIL_EntitiesInBox(pList, maxList, mins, maxs, FL_MONSTER | FL_CLIENT);
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
if (pList[i]->pev->solid != SOLID_NOT)
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void MAKE_STRING_CLASS(const char *str, entvars_t *pev)
|
|
{
|
|
if (!FStringNull(pev->classname))
|
|
{
|
|
RemoveEntityHashValue(pev, STRING(pev->classname), CLASSNAME);
|
|
}
|
|
|
|
pev->classname = MAKE_STRING(str);
|
|
AddEntityHashValue(pev, STRING(pev->classname), CLASSNAME);
|
|
}
|
|
|
|
void NORETURN Sys_Error(const char *error, ...)
|
|
{
|
|
va_list argptr;
|
|
static char text[1024];
|
|
|
|
va_start(argptr, error);
|
|
vsnprintf(text, sizeof(text), error, argptr);
|
|
va_end(argptr);
|
|
|
|
FILE *fl = fopen("regamedll_error.txt", "w");
|
|
if (fl)
|
|
{
|
|
fprintf(fl, "%s\n", text);
|
|
fclose(fl);
|
|
}
|
|
|
|
CONSOLE_ECHO("FATAL ERROR (shutting down): %s\n", text);
|
|
|
|
#if defined(_WIN32)
|
|
MessageBoxA(NULL, text, "Fatal error", MB_ICONERROR | MB_OK);
|
|
#endif
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int UTIL_CountPlayersInBrushVolume(bool bOnlyAlive, CBaseEntity *pBrushEntity, int &playersInCount, int &playersOutCount, CPlayerInVolumeAdapter *pAdapter)
|
|
{
|
|
playersInCount = 0;
|
|
playersOutCount = 0;
|
|
|
|
if (pBrushEntity)
|
|
{
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
if (!pPlayer->IsInWorld())
|
|
continue;
|
|
|
|
if (bOnlyAlive && !pPlayer->IsAlive())
|
|
continue;
|
|
|
|
TraceResult trace;
|
|
int hullNumber = (pPlayer->pev->flags & FL_DUCKING) ? head_hull : human_hull;
|
|
UTIL_TraceModel(pPlayer->pev->origin, pPlayer->pev->origin, hullNumber, pBrushEntity->edict(), &trace);
|
|
|
|
bool fInVolume = trace.fStartSolid > 0.0f;
|
|
if (fInVolume)
|
|
{
|
|
playersInCount++;
|
|
}
|
|
else
|
|
{
|
|
playersOutCount++;
|
|
}
|
|
|
|
if (pAdapter) {
|
|
pAdapter->PlayerDetected(fInVolume, pPlayer);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
playersOutCount = UTIL_GetNumPlayers();
|
|
}
|
|
|
|
return playersInCount + playersOutCount;
|
|
}
|