yapb-noob-edition/source/support.cpp

1022 lines
29 KiB
C++
Raw Normal View History

2015-06-04 11:52:48 +03:00
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
2014-07-30 14:17:46 +04:00
//
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// http://yapb.jeefo.net/license
2014-07-30 14:17:46 +04:00
//
#include <core.h>
ConVar yb_display_menu_text ("yb_display_menu_text", "1");
2014-07-30 14:17:46 +04:00
ConVar mp_roundtime ("mp_roundtime", NULL, VT_NOREGISTER);
#ifndef XASH_CSDM
2014-07-30 14:17:46 +04:00
ConVar mp_freezetime ("mp_freezetime", NULL, VT_NOREGISTER);
#else
ConVar mp_freezetime ("mp_freezetime", "0", VT_NOSERVER);
#endif
2014-07-30 14:17:46 +04:00
uint16 FixedUnsigned16 (float value, float scale)
{
int output = (static_cast <int> (value * scale));
if (output < 0)
output = 0;
if (output > 0xffff)
output = 0xffff;
return static_cast <uint16> (output);
}
short FixedSigned16 (float value, float scale)
{
int output = (static_cast <int> (value * scale));
if (output > 32767)
output = 32767;
if (output < -32768)
output = -32768;
return static_cast <short> (output);
}
const char *FormatBuffer (const char *format, ...)
2014-07-30 14:17:46 +04:00
{
va_list ap;
static char staticBuffer[3072];
va_start (ap, format);
vsprintf (staticBuffer, format, ap);
va_end (ap);
return &staticBuffer[0];
}
bool IsAlive (edict_t *ent)
{
if (IsNullEntity (ent))
2015-06-04 11:52:48 +03:00
return false;
2014-07-30 14:17:46 +04:00
2015-06-04 11:52:48 +03:00
return ent->v.deadflag == DEAD_NO && ent->v.health > 0 && ent->v.movetype != MOVETYPE_NOCLIP;
2014-07-30 14:17:46 +04:00
}
float GetShootingConeDeviation (edict_t *ent, Vector *position)
{
const Vector &dir = (*position - (ent->v.origin + ent->v.view_ofs)).Normalize ();
MakeVectors (ent->v.v_angle);
// he's facing it, he meant it
return g_pGlobals->v_forward | dir;
}
bool IsInViewCone (const Vector &origin, edict_t *ent)
2014-07-30 14:17:46 +04:00
{
MakeVectors (ent->v.v_angle);
if (((origin - (ent->v.origin + ent->v.view_ofs)).Normalize () | g_pGlobals->v_forward) >= cosf (((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f) * MATH_D2R))
2014-07-30 14:17:46 +04:00
return true;
return false;
}
bool IsVisible (const Vector &origin, edict_t *ent)
{
if (IsNullEntity (ent))
2014-07-30 14:17:46 +04:00
return false;
TraceResult tr;
2016-03-01 13:37:10 +03:00
engine.TestLine (ent->v.origin + ent->v.view_ofs, origin, TRACE_IGNORE_EVERYTHING, ent, &tr);
2014-07-30 14:17:46 +04:00
if (tr.flFraction != 1.0f)
return false;
2014-07-30 14:17:46 +04:00
return true;
2014-07-30 14:17:46 +04:00
}
void DisplayMenuToClient (edict_t *ent, MenuText *menu)
{
if (!IsValidPlayer (ent))
return;
2014-09-17 20:36:42 +04:00
int clientIndex = IndexOfEntity (ent) - 1;
2014-07-30 14:17:46 +04:00
if (menu != NULL)
{
String tempText = String (menu->menuText);
tempText.Replace ("\v", "\n");
2015-07-24 14:39:11 +03:00
char *text = locale.TranslateInput (tempText.GetBuffer ());
2014-07-30 14:17:46 +04:00
tempText = String (text);
// make menu looks best
for (int i = 0; i <= 9; i++)
tempText.Replace (FormatBuffer ("%d.", i), FormatBuffer ("\\r%d.\\w", i));
if ((g_gameFlags & (GAME_XASH | GAME_MOBILITY)) && !yb_display_menu_text.GetBool ())
text = " ";
else
text = (char *) tempText.GetBuffer ();
2014-07-30 14:17:46 +04:00
while (strlen (text) >= 64)
{
2015-07-24 14:39:11 +03:00
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, netmsg.GetId (NETMSG_SHOWMENU), NULL, ent);
2014-07-30 14:17:46 +04:00
WRITE_SHORT (menu->validSlots);
WRITE_CHAR (-1);
WRITE_BYTE (1);
for (int i = 0; i <= 63; i++)
WRITE_CHAR (text[i]);
MESSAGE_END ();
text += 64;
}
2015-07-24 14:39:11 +03:00
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, netmsg.GetId (NETMSG_SHOWMENU), NULL, ent);
2014-07-30 14:17:46 +04:00
WRITE_SHORT (menu->validSlots);
WRITE_CHAR (-1);
WRITE_BYTE (0);
WRITE_STRING (text);
MESSAGE_END();
g_clients[clientIndex].menu = menu;
}
else
{
2015-07-24 14:39:11 +03:00
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, netmsg.GetId (NETMSG_SHOWMENU), NULL, ent);
2014-07-30 14:17:46 +04:00
WRITE_SHORT (0);
WRITE_CHAR (0);
WRITE_BYTE (0);
WRITE_STRING ("");
MESSAGE_END();
g_clients[clientIndex].menu = NULL;
}
CLIENT_COMMAND (ent, "speak \"player/geiger1\"\n"); // Stops others from hearing menu sounds..
}
void DecalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex)
{
// this function draw spraypaint depending on the tracing results.
static Array <String> logotypes;
if (logotypes.IsEmpty ())
2015-06-14 23:13:09 +03:00
logotypes = String ("{biohaz;{graf003;{graf004;{graf005;{lambda06;{target;{hand1;{spit2;{bloodhand6;{foot_l;{foot_r").Split (";");
2014-07-30 14:17:46 +04:00
int entityIndex = -1, message = TE_DECAL;
2015-06-04 11:52:48 +03:00
int decalIndex = (*g_engfuncs.pfnDecalIndex) (logotypes[logotypeIndex].GetBuffer ());
2014-07-30 14:17:46 +04:00
if (decalIndex < 0)
decalIndex = (*g_engfuncs.pfnDecalIndex) ("{lambda06");
if (trace->flFraction == 1.0f)
2014-07-30 14:17:46 +04:00
return;
if (!IsNullEntity (trace->pHit))
2014-07-30 14:17:46 +04:00
{
if (trace->pHit->v.solid == SOLID_BSP || trace->pHit->v.movetype == MOVETYPE_PUSHSTEP)
2014-09-17 20:36:42 +04:00
entityIndex = IndexOfEntity (trace->pHit);
2014-07-30 14:17:46 +04:00
else
return;
}
else
entityIndex = 0;
if (entityIndex != 0)
{
if (decalIndex > 255)
{
message = TE_DECALHIGH;
decalIndex -= 256;
}
}
else
{
message = TE_WORLDDECAL;
if (decalIndex > 255)
{
message = TE_WORLDDECALHIGH;
decalIndex -= 256;
}
}
if (logotypes[logotypeIndex].Contains ("{"))
{
MESSAGE_BEGIN (MSG_BROADCAST, SVC_TEMPENTITY);
WRITE_BYTE (TE_PLAYERDECAL);
2014-09-17 20:36:42 +04:00
WRITE_BYTE (IndexOfEntity (ENT (pev)));
2014-07-30 14:17:46 +04:00
WRITE_COORD (trace->vecEndPos.x);
WRITE_COORD (trace->vecEndPos.y);
WRITE_COORD (trace->vecEndPos.z);
2014-09-17 20:36:42 +04:00
WRITE_SHORT (static_cast <short> (IndexOfEntity (trace->pHit)));
2014-07-30 14:17:46 +04:00
WRITE_BYTE (decalIndex);
MESSAGE_END ();
}
else
{
MESSAGE_BEGIN (MSG_BROADCAST, SVC_TEMPENTITY);
WRITE_BYTE (message);
WRITE_COORD (trace->vecEndPos.x);
WRITE_COORD (trace->vecEndPos.y);
WRITE_COORD (trace->vecEndPos.z);
WRITE_BYTE (decalIndex);
if (entityIndex)
WRITE_SHORT (entityIndex);
MESSAGE_END();
}
}
void FreeLibraryMemory (void)
{
// this function free's all allocated memory
2015-07-24 15:10:51 +03:00
waypoints.Init (); // frees waypoint data
2015-07-24 14:39:11 +03:00
locale.Destroy (); // clear language
2015-06-04 11:52:48 +03:00
delete [] g_experienceData;
2014-07-30 14:17:46 +04:00
g_experienceData = NULL;
}
void UpdateGlobalExperienceData (void)
{
// this function called after each end of the round to update knowledge about most dangerous waypoints for each team.
// no waypoints, no experience used or waypoints edited or being edited?
if (g_numWaypoints < 1 || g_waypointsChanged)
2014-07-30 14:17:46 +04:00
return; // no action
unsigned short maxDamage; // maximum damage
unsigned short actDamage; // actual damage
int bestIndex; // best index to store
bool recalcKills = false;
// get the most dangerous waypoint for this position for terrorist team
for (int i = 0; i < g_numWaypoints; i++)
{
maxDamage = 0;
bestIndex = -1;
for (int j = 0; j < g_numWaypoints; j++)
{
if (i == j)
continue;
actDamage = (g_experienceData + (i * g_numWaypoints) + j)->team0Damage;
if (actDamage > maxDamage)
{
maxDamage = actDamage;
bestIndex = j;
}
}
if (maxDamage > MAX_DAMAGE_VALUE)
recalcKills = true;
(g_experienceData + (i * g_numWaypoints) + i)->team0DangerIndex = static_cast <short> (bestIndex);
}
// get the most dangerous waypoint for this position for counter-terrorist team
for (int i = 0; i < g_numWaypoints; i++)
{
maxDamage = 0;
bestIndex = -1;
for (int j = 0; j < g_numWaypoints; j++)
{
if (i == j)
continue;
actDamage = (g_experienceData + (i * g_numWaypoints) + j)->team1Damage;
if (actDamage > maxDamage)
{
maxDamage = actDamage;
bestIndex = j;
}
}
if (maxDamage > MAX_DAMAGE_VALUE)
recalcKills = true;
(g_experienceData + (i * g_numWaypoints) + i)->team1DangerIndex = static_cast <short> (bestIndex);
}
// adjust values if overflow is about to happen
if (recalcKills)
{
for (int i = 0; i < g_numWaypoints; i++)
{
for (int j = 0; j < g_numWaypoints; j++)
{
if (i == j)
continue;
int clip = (g_experienceData + (i * g_numWaypoints) + j)->team0Damage;
clip -= static_cast <int> (MAX_DAMAGE_VALUE * 0.5);
if (clip < 0)
clip = 0;
(g_experienceData + (i * g_numWaypoints) + j)->team0Damage = static_cast <unsigned short> (clip);
clip = (g_experienceData + (i * g_numWaypoints) + j)->team1Damage;
clip -= static_cast <int> (MAX_DAMAGE_VALUE * 0.5);
if (clip < 0)
clip = 0;
(g_experienceData + (i * g_numWaypoints) + j)->team1Damage = static_cast <unsigned short> (clip);
}
}
}
g_highestKills++;
2014-07-30 14:17:46 +04:00
int clip = g_highestDamageT - static_cast <int> (MAX_DAMAGE_VALUE * 0.5);
if (clip < 1)
clip = 1;
g_highestDamageT = clip;
clip = (int) g_highestDamageCT - static_cast <int> (MAX_DAMAGE_VALUE * 0.5);
if (clip < 1)
clip = 1;
g_highestDamageCT = clip;
if (g_highestKills == MAX_KILL_HISTORY)
2014-07-30 14:17:46 +04:00
{
for (int i = 0; i < g_numWaypoints; i++)
{
2016-03-01 13:37:10 +03:00
(g_experienceData + (i * g_numWaypoints) + i)->team0Damage /= static_cast <unsigned short> (engine.MaxClients () * 0.5);
(g_experienceData + (i * g_numWaypoints) + i)->team1Damage /= static_cast <unsigned short> (engine.MaxClients () * 0.5);
2014-07-30 14:17:46 +04:00
}
g_highestKills = 1;
2014-07-30 14:17:46 +04:00
}
}
void RoundInit (void)
{
// this is called at the start of each round
g_roundEnded = false;
// check team economics
bots.CheckTeamEconomics (TERRORIST);
bots.CheckTeamEconomics (CT);
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
for (int i = 0; i < engine.MaxClients (); i++)
2014-07-30 14:17:46 +04:00
{
2015-07-24 15:10:51 +03:00
if (bots.GetBot (i))
bots.GetBot (i)->NewRound ();
2014-07-30 14:17:46 +04:00
g_radioSelect[i] = 0;
}
2015-07-24 15:10:51 +03:00
waypoints.SetBombPosition (true);
waypoints.ClearVisitedGoals ();
2014-07-30 14:17:46 +04:00
g_bombSayString = false;
g_timeBombPlanted = 0.0f;
g_timeNextBombUpdate = 0.0f;
2014-07-30 14:17:46 +04:00
g_leaderChoosen[CT] = false;
g_leaderChoosen[TERRORIST] = false;
2014-07-30 14:17:46 +04:00
g_lastRadioTime[0] = 0.0f;
g_lastRadioTime[1] = 0.0f;
2014-07-30 14:17:46 +04:00
g_botsCanPause = false;
2015-06-04 11:52:48 +03:00
for (int i = 0; i < TASK_MAX; i++)
g_taskFilters[i].time = 0.0f;
2014-07-30 14:17:46 +04:00
UpdateGlobalExperienceData (); // update experience data on round start
// calculate the round mid/end in world time
2016-03-01 13:37:10 +03:00
g_timeRoundStart = engine.Time () + mp_freezetime.GetFloat ();
g_timeRoundMid = g_timeRoundStart + mp_roundtime.GetFloat () * 60.0f * 0.5f;
g_timeRoundEnd = g_timeRoundStart + mp_roundtime.GetFloat () * 60.0f;
2014-07-30 14:17:46 +04:00
}
2015-06-04 11:52:48 +03:00
int GetWeaponPenetrationPower (int id)
2014-07-30 14:17:46 +04:00
{
// returns if weapon can pierce through a wall
int i = 0;
while (g_weaponSelect[i].id)
{
if (g_weaponSelect[i].id == id)
2015-06-04 11:52:48 +03:00
return g_weaponSelect[i].penetratePower;
2014-07-30 14:17:46 +04:00
i++;
}
2015-06-04 11:52:48 +03:00
return 0;
2014-07-30 14:17:46 +04:00
}
bool IsValidPlayer (edict_t *ent)
{
if (IsNullEntity (ent))
2014-07-30 14:17:46 +04:00
return false;
if (ent->v.flags & FL_PROXY)
return false;
2015-07-24 15:10:51 +03:00
if ((ent->v.flags & (FL_CLIENT | FL_FAKECLIENT)) || bots.GetBot (ent) != NULL)
2014-07-30 14:17:46 +04:00
return !IsNullString (STRING (ent->v.netname));
return false;
}
bool IsPlayerVIP (edict_t *ent)
{
if (!(g_mapType & MAP_AS))
return false;
if (!IsValidPlayer (ent))
return false;
return *(INFOKEY_VALUE (GET_INFOKEYBUFFER (ent), "model")) == 'v';
}
2014-07-30 14:17:46 +04:00
bool IsValidBot (edict_t *ent)
{
if (bots.GetBot (ent) != NULL || (!IsNullEntity (ent) && (ent->v.flags & FL_FAKECLIENT)))
2014-07-30 14:17:46 +04:00
return true;
return false;
}
2016-03-01 13:37:10 +03:00
bool OpenConfig (const char *fileName, const char *errorIfNotExists, File *outFile, bool languageDependant /*= false*/)
2014-07-30 14:17:46 +04:00
{
if (outFile->IsValid ())
outFile->Close ();
if (languageDependant)
{
2016-03-01 13:37:10 +03:00
const char *mod = engine.GetModName ();
2014-07-30 14:17:46 +04:00
extern ConVar yb_language;
if (strcmp (fileName, "lang.cfg") == 0 && strcmp (yb_language.GetString (), "en") == 0)
return false;
2016-03-01 13:37:10 +03:00
const char *languageDependantConfigFile = FormatBuffer ("%s/addons/yapb/conf/lang/%s_%s", mod, yb_language.GetString (), fileName);
2014-07-30 14:17:46 +04:00
// check is file is exists for this language
2015-07-11 19:54:46 +03:00
if (File::Accessible (languageDependantConfigFile))
2014-07-30 14:17:46 +04:00
outFile->Open (languageDependantConfigFile, "rt");
else
2016-03-01 13:37:10 +03:00
outFile->Open (FormatBuffer ("%s/addons/yapb/conf/lang/en_%s", mod, fileName), "rt");
2014-07-30 14:17:46 +04:00
}
else
2016-03-01 13:37:10 +03:00
outFile->Open (FormatBuffer ("%s/addons/yapb/conf/%s", engine.GetModName (), fileName), "rt");
2014-07-30 14:17:46 +04:00
if (!outFile->IsValid ())
{
AddLogEntry (true, LL_ERROR, errorIfNotExists);
return false;
}
return true;
}
void CheckWelcomeMessage (void)
{
// the purpose of this function, is to send quick welcome message, to the listenserver entity.
static bool alreadyReceived = false;
static float receiveTime = 0.0f;
2014-07-30 14:17:46 +04:00
if (alreadyReceived)
2014-07-30 14:17:46 +04:00
return;
Array <String> sentences;
if (!(g_gameFlags & (GAME_MOBILITY | GAME_XASH)))
{
// add default messages
sentences.Push ("hello user,communication is acquired");
sentences.Push ("your presence is acknowledged");
sentences.Push ("high man, your in command now");
sentences.Push ("blast your hostile for good");
sentences.Push ("high man, kill some idiot here");
sentences.Push ("is there a doctor in the area");
sentences.Push ("warning, experimental materials detected");
sentences.Push ("high amigo, shoot some but");
sentences.Push ("attention, hours of work software, detected");
sentences.Push ("time for some bad ass explosion");
sentences.Push ("bad ass son of a breach device activated");
sentences.Push ("high, do not question this great service");
sentences.Push ("engine is operative, hello and goodbye");
sentences.Push ("high amigo, your administration has been great last day");
sentences.Push ("attention, expect experimental armed hostile presence");
sentences.Push ("warning, medical attention required");
}
2014-07-30 14:17:46 +04:00
if (IsAlive (g_hostEntity) && !alreadyReceived && receiveTime < 1.0 && (g_numWaypoints > 0 ? g_isCommencing : true))
2016-03-01 13:37:10 +03:00
receiveTime = engine.Time () + 4.0f; // receive welcome message in four seconds after game has commencing
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
if (receiveTime > 0.0f && receiveTime < engine.Time () && !alreadyReceived && (g_numWaypoints > 0 ? g_isCommencing : true))
2014-07-30 14:17:46 +04:00
{
if (!(g_gameFlags & (GAME_MOBILITY | GAME_XASH)))
2016-03-01 13:37:10 +03:00
engine.IssueCmd ("speak \"%s\"", const_cast <char *> (sentences.GetRandomElement ().GetBuffer ()));
2016-03-01 13:37:10 +03:00
engine.ChatPrintf ("----- %s v%s (Build: %u), {%s}, (c) 2016, by %s (%s)-----", PRODUCT_NAME, PRODUCT_VERSION, GenerateBuildNumber (), PRODUCT_DATE, PRODUCT_AUTHOR, PRODUCT_URL);
MESSAGE_BEGIN (MSG_ONE, SVC_TEMPENTITY, NULL, g_hostEntity);
WRITE_BYTE (TE_TEXTMESSAGE);
WRITE_BYTE (1);
WRITE_SHORT (FixedSigned16 (-1, 1 << 13));
WRITE_SHORT (FixedSigned16 (-1, 1 << 13));
WRITE_BYTE (2);
WRITE_BYTE (Random.Long (33, 255));
WRITE_BYTE (Random.Long (33, 255));
WRITE_BYTE (Random.Long (33, 255));
WRITE_BYTE (0);
WRITE_BYTE (Random.Long (230, 255));
WRITE_BYTE (Random.Long (230, 255));
WRITE_BYTE (Random.Long (230, 255));
WRITE_BYTE (200);
WRITE_SHORT (FixedUnsigned16 (0.0078125f, 1 << 8));
WRITE_SHORT (FixedUnsigned16 (2.0f, 1 << 8));
WRITE_SHORT (FixedUnsigned16 (6.0f, 1 << 8));
WRITE_SHORT (FixedUnsigned16 (0.1f, 1 << 8));
2015-07-24 15:10:51 +03:00
WRITE_STRING (FormatBuffer ("\nServer is running YaPB v%s (Build: %u)\nDeveloped by %s\n\n%s", PRODUCT_VERSION, GenerateBuildNumber (), PRODUCT_AUTHOR, waypoints.GetInfo ()));
MESSAGE_END ();
2014-07-30 14:17:46 +04:00
receiveTime = 0.0;
alreadyReceived = true;
2014-07-30 14:17:46 +04:00
}
}
void DetectCSVersion (void)
{
if (g_gameFlags & GAME_CZERO)
return;
2014-07-30 14:17:46 +04:00
// detect xash engine
if (g_engfuncs.pfnCVarGetPointer ("build") != NULL)
{
g_gameFlags |= (GAME_LEGACY | GAME_XASH);
return;
}
2014-07-30 14:17:46 +04:00
// counter-strike 1.6 or higher (plus detects for non-steam versions of 1.5)
byte *detection = (*g_engfuncs.pfnLoadFileForMe) ("events/galil.sc", NULL);
2014-07-30 14:17:46 +04:00
if (detection != NULL)
g_gameFlags |= GAME_CSTRIKE16; // just to be sure
else if (detection == NULL)
g_gameFlags |= GAME_LEGACY; // reset it to WON
2014-07-30 14:17:46 +04:00
// if we have loaded the file free it
if (detection != NULL)
(*g_engfuncs.pfnFreeFile) (detection);
2014-07-30 14:17:46 +04:00
}
void AddLogEntry (bool outputToConsole, int logLevel, const char *format, ...)
{
// this function logs a message to the message log file root directory.
va_list ap;
char buffer[512] = {0, }, levelString[32] = {0, }, logLine[1024] = {0, };
va_start (ap, format);
2015-07-24 14:39:11 +03:00
vsprintf (buffer, locale.TranslateInput (format), ap);
2014-07-30 14:17:46 +04:00
va_end (ap);
switch (logLevel)
{
case LL_DEFAULT:
strcpy (levelString, "Log: ");
break;
case LL_WARNING:
strcpy (levelString, "Warning: ");
break;
case LL_ERROR:
strcpy (levelString, "Error: ");
break;
case LL_FATAL:
strcpy (levelString, "Critical: ");
break;
}
if (outputToConsole)
2016-03-01 13:37:10 +03:00
engine.Printf ("%s%s", levelString, buffer);
2014-07-30 14:17:46 +04:00
// now check if logging disabled
if (!(logLevel & LL_IGNORE))
{
extern ConVar yb_debug;
if (logLevel == LL_DEFAULT && yb_debug.GetInt () < 3)
return; // no log, default logging is disabled
if (logLevel == LL_WARNING && yb_debug.GetInt () < 2)
return; // no log, warning logging is disabled
if (logLevel == LL_ERROR && yb_debug.GetInt () < 1)
return; // no log, error logging is disabled
}
// open file in a standard stream
File fp ("yapb.txt", "at");
// check if we got a valid handle
if (!fp.IsValid ())
return;
time_t tickTime = time (&tickTime);
tm *time = localtime (&tickTime);
sprintf (logLine, "[%02d:%02d:%02d] %s%s", time->tm_hour, time->tm_min, time->tm_sec, levelString, buffer);
fp.Printf ("%s\n", logLine);
fp.Close ();
if (logLevel == LL_FATAL)
{
bots.RemoveAll ();
FreeLibraryMemory ();
2014-07-30 14:17:46 +04:00
#if defined (PLATFORM_WIN32)
DestroyWindow (GetForegroundWindow ());
2014-07-30 14:17:46 +04:00
MessageBoxA (GetActiveWindow (), buffer, "YaPB Error", MB_ICONSTOP);
#else
2015-06-06 16:37:15 +03:00
printf ("%s", buffer);
2014-07-30 14:17:46 +04:00
#endif
2014-07-30 14:17:46 +04:00
#if defined (PLATFORM_WIN32)
_exit (1);
#else
exit (1);
#endif
}
}
char *Localizer::TranslateInput (const char *input)
{
2016-03-01 13:37:10 +03:00
if (engine.IsDedicatedServer ())
2014-07-30 14:17:46 +04:00
return const_cast <char *> (&input[0]);
static char string[1024];
const char *ptr = input + strlen (input) - 1;
while (ptr > input && *ptr == '\n')
ptr--;
if (ptr != input)
ptr++;
2015-06-29 22:06:55 +03:00
strncpy (string, input, SIZEOF_CHAR (string));
String::TrimExternalBuffer (string);
2014-07-30 14:17:46 +04:00
FOR_EACH_AE (m_langTab, i)
2014-07-30 14:17:46 +04:00
{
if (strcmp (string, m_langTab[i].original) == 0)
{
strncpy (string, m_langTab[i].translated, SIZEOF_CHAR (string));
2014-07-30 14:17:46 +04:00
if (ptr != input)
strncat (string, ptr, 1024 - 1 - strlen (string));
return &string[0];
}
}
return const_cast <char *> (&input[0]); // nothing found
}
2015-07-24 14:39:11 +03:00
void Localizer::Destroy (void)
{
FOR_EACH_AE (m_langTab, it)
{
delete[] m_langTab[it].original;
delete[] m_langTab[it].translated;
}
m_langTab.RemoveAll ();
}
2014-07-30 14:17:46 +04:00
bool FindNearestPlayer (void **pvHolder, edict_t *to, float searchDistance, bool sameTeam, bool needBot, bool isAlive, bool needDrawn)
{
// this function finds nearest to to, player with set of parameters, like his
// team, live status, search distance etc. if needBot is true, then pvHolder, will
// be filled with bot pointer, else with edict pointer(!).
edict_t *survive = NULL; // pointer to temporaly & survive entity
float nearestPlayer = 4096.0f; // nearest player
2014-07-30 14:17:46 +04:00
int toTeam = GetTeam (to);
2016-03-01 13:37:10 +03:00
for (int i = 0; i < engine.MaxClients (); i++)
2014-07-30 14:17:46 +04:00
{
edict_t *ent = g_clients[i].ent;
if (!(g_clients[i].flags & CF_USED) || ent == to)
continue;
2014-07-30 14:17:46 +04:00
if ((sameTeam && g_clients[i].team != toTeam) || (isAlive && !(g_clients[i].flags & CF_ALIVE)) || (needBot && !IsValidBot (ent)) || (needDrawn && (ent->v.effects & EF_NODRAW)))
2014-07-30 14:17:46 +04:00
continue; // filter players with parameters
float distance = (ent->v.origin - to->v.origin).GetLength ();
2014-07-30 14:17:46 +04:00
if (distance < nearestPlayer && distance < searchDistance)
2014-07-30 14:17:46 +04:00
{
nearestPlayer = distance;
survive = ent;
}
}
if (IsNullEntity (survive))
2014-07-30 14:17:46 +04:00
return false; // nothing found
// fill the holder
if (needBot)
2015-07-24 15:10:51 +03:00
*pvHolder = reinterpret_cast <void *> (bots.GetBot (survive));
2014-07-30 14:17:46 +04:00
else
*pvHolder = reinterpret_cast <void *> (survive);
return true;
}
void SoundAttachToClients (edict_t *ent, const char *sample, float volume)
2014-07-30 14:17:46 +04:00
{
// this function called by the sound hooking code (in emit_sound) enters the played sound into
// the array associated with the entity
if (IsNullEntity (ent) || IsNullString (sample))
2014-07-30 14:17:46 +04:00
return; // reliability check
2016-03-01 13:37:10 +03:00
const Vector &origin = engine.GetAbsOrigin (ent);
2014-09-17 20:36:42 +04:00
int index = IndexOfEntity (ent) - 1;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
if (index < 0 || index >= engine.MaxClients ())
2014-07-30 14:17:46 +04:00
{
float nearestDistance = 99999.0f;
2014-07-30 14:17:46 +04:00
// loop through all players
2016-03-01 13:37:10 +03:00
for (int i = 0; i < engine.MaxClients (); i++)
2014-07-30 14:17:46 +04:00
{
if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE))
continue;
float distance = (g_clients[i].ent->v.origin - origin).GetLengthSquared ();
// now find nearest player
if (distance < nearestDistance)
{
index = i;
nearestDistance = distance;
}
}
}
Client *client = &g_clients[index];
2014-07-30 14:17:46 +04:00
if (client == NULL)
return;
2014-07-30 14:17:46 +04:00
if (strncmp ("player/bhit_flesh", sample, 17) == 0 || strncmp ("player/headshot", sample, 15) == 0)
{
// hit/fall sound?
client->hearingDistance = 768.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 0.5f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("items/gunpickup", sample, 15) == 0)
{
// weapon pickup?
client->hearingDistance = 768.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 0.5f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("weapons/zoom", sample, 12) == 0)
{
// sniper zooming?
client->hearingDistance = 512.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 0.1f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("items/9mmclip", sample, 13) == 0)
{
// ammo pickup?
client->hearingDistance = 512.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 0.1f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("hostage/hos", sample, 11) == 0)
{
// CT used hostage?
client->hearingDistance = 1024.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 5.0f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("debris/bustmetal", sample, 16) == 0 || strncmp ("debris/bustglass", sample, 16) == 0)
{
// broke something?
client->hearingDistance = 1024.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 2.0f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
else if (strncmp ("doors/doormove", sample, 14) == 0)
{
// someone opened a door
client->hearingDistance = 1024.0f * volume;
2016-03-01 13:37:10 +03:00
client->timeSoundLasting = engine.Time () + 3.0f;
client->soundPosition = origin;
2014-07-30 14:17:46 +04:00
}
}
void SoundSimulateUpdate (int playerIndex)
{
// this function tries to simulate playing of sounds to let the bots hear sounds which aren't
// captured through server sound hooking
2016-03-01 13:37:10 +03:00
if (playerIndex < 0 || playerIndex >= engine.MaxClients ())
2014-07-30 14:17:46 +04:00
return; // reliability check
Client *client = &g_clients[playerIndex];
2014-07-30 14:17:46 +04:00
float hearDistance = 0.0f;
float timeSound = 0.0f;
2014-07-30 14:17:46 +04:00
if (client->ent->v.oldbuttons & IN_ATTACK) // pressed attack button?
2014-07-30 14:17:46 +04:00
{
hearDistance = 2048.0f;
2016-03-01 13:37:10 +03:00
timeSound = engine.Time () + 0.3f;
2014-07-30 14:17:46 +04:00
}
else if (client->ent->v.oldbuttons & IN_USE) // pressed used button?
2014-07-30 14:17:46 +04:00
{
hearDistance = 512.0f;
2016-03-01 13:37:10 +03:00
timeSound = engine.Time () + 0.5f;
2014-07-30 14:17:46 +04:00
}
else if (client->ent->v.oldbuttons & IN_RELOAD) // pressed reload button?
2014-07-30 14:17:46 +04:00
{
hearDistance = 512.0f;
2016-03-01 13:37:10 +03:00
timeSound = engine.Time () + 0.5f;
2014-07-30 14:17:46 +04:00
}
else if (client->ent->v.movetype == MOVETYPE_FLY) // uses ladder?
2014-07-30 14:17:46 +04:00
{
if (fabsf (client->ent->v.velocity.z) > 50.0f)
2014-07-30 14:17:46 +04:00
{
hearDistance = 1024.0f;
2016-03-01 13:37:10 +03:00
timeSound = engine.Time () + 0.3f;
2014-07-30 14:17:46 +04:00
}
}
else
{
extern ConVar mp_footsteps;
if (mp_footsteps.GetBool ())
{
// moves fast enough?
hearDistance = 1280.0f * (client->ent->v.velocity.GetLength2D () / 260.0f);
2016-03-01 13:37:10 +03:00
timeSound = engine.Time () + 0.3f;
2014-07-30 14:17:46 +04:00
}
}
if (hearDistance <= 0.0)
return; // didn't issue sound?
// some sound already associated
2016-03-01 13:37:10 +03:00
if (client->timeSoundLasting > engine.Time ())
2014-07-30 14:17:46 +04:00
{
if (client->hearingDistance <= hearDistance)
2014-07-30 14:17:46 +04:00
{
// override it with new
client->hearingDistance = hearDistance;
client->timeSoundLasting = timeSound;
client->soundPosition = client->ent->v.origin;
2014-07-30 14:17:46 +04:00
}
}
else
{
// just remember it
client->hearingDistance = hearDistance;
client->timeSoundLasting = timeSound;
client->soundPosition = client->ent->v.origin;
2014-07-30 14:17:46 +04:00
}
}
int GenerateBuildNumber (void)
2014-07-30 14:17:46 +04:00
{
// this function generates build number from the compiler date macros
static int buildNumber = 0;
2015-07-05 21:32:56 +03:00
if (buildNumber != 0)
return buildNumber;
2014-07-30 14:17:46 +04:00
// get compiling date using compiler macros
const char *date = __DATE__;
// array of the month names
const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
// array of the month days
byte monthDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int day = 0; // day of the year
int year = 0; // year
int i = 0;
2015-07-05 21:32:56 +03:00
// go through all months, and calculate, days since year start
2014-07-30 14:17:46 +04:00
for (i = 0; i < 11; i++)
{
if (strncmp (&date[0], months[i], 3) == 0)
break; // found current month break
day += monthDays[i]; // add month days
}
day += atoi (&date[4]) - 1; // finally calculate day
year = atoi (&date[7]) - 2000; // get years since year 2000
2015-07-05 21:32:56 +03:00
buildNumber = day + static_cast <int> ((year - 1) * 365.25);
2014-07-30 14:17:46 +04:00
// if the year is a leap year?
if ((year % 4) == 0 && i > 1)
buildNumber += 1; // add one year more
2015-07-05 21:32:56 +03:00
buildNumber -= 1114;
return buildNumber;
2014-07-30 14:17:46 +04:00
}
int GetWeaponReturn (bool needString, const char *weaponAlias, int weaponIndex)
{
// this function returning weapon id from the weapon alias and vice versa.
// structure definition for weapon tab
struct WeaponTab_t
{
Weapon weaponIndex; // weapon id
const char *alias; // weapon alias
};
// weapon enumeration
WeaponTab_t weaponTab[] =
{
{WEAPON_USP, "usp"}, // HK USP .45 Tactical
{WEAPON_GLOCK, "glock"}, // Glock18 Select Fire
{WEAPON_DEAGLE, "deagle"}, // Desert Eagle .50AE
{WEAPON_P228, "p228"}, // SIG P228
{WEAPON_ELITE, "elite"}, // Dual Beretta 96G Elite
{WEAPON_FIVESEVEN, "fn57"}, // FN Five-Seven
{WEAPON_M3, "m3"}, // Benelli M3 Super90
{WEAPON_XM1014, "xm1014"}, // Benelli XM1014
{WEAPON_MP5, "mp5"}, // HK MP5-Navy
{WEAPON_TMP, "tmp"}, // Steyr Tactical Machine Pistol
{WEAPON_P90, "p90"}, // FN P90
{WEAPON_MAC10, "mac10"}, // Ingram MAC-10
{WEAPON_UMP45, "ump45"}, // HK UMP45
{WEAPON_AK47, "ak47"}, // Automat Kalashnikov AK-47
{WEAPON_GALIL, "galil"}, // IMI Galil
{WEAPON_FAMAS, "famas"}, // GIAT FAMAS
{WEAPON_SG552, "sg552"}, // Sig SG-552 Commando
{WEAPON_M4A1, "m4a1"}, // Colt M4A1 Carbine
{WEAPON_AUG, "aug"}, // Steyr Aug
{WEAPON_SCOUT, "scout"}, // Steyr Scout
{WEAPON_AWP, "awp"}, // AI Arctic Warfare/Magnum
{WEAPON_G3SG1, "g3sg1"}, // HK G3/SG-1 Sniper Rifle
{WEAPON_SG550, "sg550"}, // Sig SG-550 Sniper
{WEAPON_M249, "m249"}, // FN M249 Para
{WEAPON_FLASHBANG, "flash"}, // Concussion Grenade
{WEAPON_EXPLOSIVE, "hegren"}, // High-Explosive Grenade
{WEAPON_SMOKE, "sgren"}, // Smoke Grenade
{WEAPON_ARMOR, "vest"}, // Kevlar Vest
{WEAPON_ARMORHELM, "vesthelm"}, // Kevlar Vest and Helmet
{WEAPON_DEFUSER, "defuser"}, // Defuser Kit
{WEAPON_SHIELD, "shield"}, // Tactical Shield
};
// if we need to return the string, find by weapon id
if (needString && weaponIndex != -1)
{
for (int i = 0; i < ARRAYSIZE_HLSDK (weaponTab); i++)
{
if (weaponTab[i].weaponIndex == weaponIndex) // is weapon id found?
return MAKE_STRING (weaponTab[i].alias);
}
return MAKE_STRING ("(none)"); // return none
}
// else search weapon by name and return weapon id
for (int i = 0; i < ARRAYSIZE_HLSDK (weaponTab); i++)
{
if (strncmp (weaponTab[i].alias, weaponAlias, strlen (weaponTab[i].alias)) == 0)
return weaponTab[i].weaponIndex;
}
return -1; // no weapon was found return -1
}