Added cvar bot_deathmatch #39

Added checks for null pointers into GetPlayerGaitsequence
Fixed mp_nadedrops: If pressed a the button attack before player death, then not drop nades to ground.
Compiler: remove rrti, added -ipo
Refactoring
This commit is contained in:
s1lentq 2016-06-14 05:13:13 +07:00
parent 4f1ca61628
commit d6b59dc0c3
34 changed files with 390 additions and 263 deletions

View File

@ -24,11 +24,12 @@ Archive's bin directory contains 2 subdirectories, 'bugfixed' and 'pure'
| mp_friendlyfire | 0 | 0 | 2 | Allow inflict damage to teammates<br/>`0` disabled <br/>`1` enabled <br/>`2` FFA mode |
| mp_maxmoney | 16000 | 0 | `0x7FFFFFFF` | The maximum allowable amount of money in the game
| mp_round_infinite | 0 | 0 | 1 | Flags for fine grained control (choose as many as needed)<br/>`0` disabled<br/>`1` enabled<br/><br/>or flags<br/>`a` block round time round end check<br/>`b` block needed players round end check<br/>`c` block VIP assassination/success round end check<br/>`d` block prison escape round end check<br/>`e` block bomb round end check<br/>`f` block team extermination round end check<br/>`g` block hostage rescue round end check<br/><br/>`Example setting:` "ae" blocks round time and bomb round end checks |
| mp_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls<br>`0` disabled<br>`1` enabled |
| mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death<br>`0` disabled<br>`1` drop one the grenade<br>`2` drop a everyone grenades |
| mp_hegrenade_penetration | 0 | 0 | 1 | Disable grenade damage through walls<br/>`0` disabled<br/>`1` enabled |
| mp_nadedrops | 0 | 0 | 2 | Drop a grenade after player death<br/>`0` disabled<br/>`1` drop one the grenade<br/>`2` drop a everyone grenades |
| mp_roundrespawn_time | 20 | 0 | - | Player cannot respawn until next round if more than N seconds has elapsed since the beginning round |
| mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn<br>`0` disabled<br>`1` enabled |
| mp_auto_reload_weapons | 0 | 0 | 1 | Automatically reload each weapon on player spawn<br/>`0` disabled<br/>`1` enabled |
| mp_refill_bpammo_weapons | 0 | 0 | 2 | Refill amount of backpack ammo up to the max <br/>`0` disabled<br/>`1` refill backpack ammo on player spawn<br/>`2` refill backpack ammo on each weapon reload |
| bot_deathmatch | 0 | 0 | 2 | Set's the mode for the zBot <br/>`0` disabled<br/>`1` enable mode Deathmatch and not allow to do the scenario<br/>`2` enable Deathmatch and FFA mode |
## How to install zBot for CS 1.6?
* Extract all the files from an [archive](regamedll/extra/zBot/bot_profiles.zip?raw=true)

8
dist/game.cfg vendored
View File

@ -64,3 +64,11 @@ mp_auto_reload_weapons "0"
//
// Default value: "0"
mp_refill_bpammo_weapons 0
// Set's the mode for the zBot
// 0 - disabled
// 1 - enable mode Deathmatch and not allow to do the scenario
// 2 - enable Deathmatch and FFA mode (Free for all)
//
// Default value: "0"
bot_deathmatch 0

View File

@ -121,7 +121,7 @@ void setupToolchain(NativeBinarySpec b)
cfg.compilerOptions.enhancedInstructionsSet = EnhancedInstructionsSet.DISABLED
}
else {
cfg.compilerOptions.args '/Oi', '/GF', '/GS-'
cfg.compilerOptions.args '/Oi', '/GF', '/GS-', '/GR-'
}
if (mpLib)
@ -151,7 +151,7 @@ void setupToolchain(NativeBinarySpec b)
])
cfg.linkerOptions.args '-no-opt-class-analysis'
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-g'
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-g0', '-fno-rtti'
cfg.extraLibs 'dl', 'm', 'stdc++'
}

View File

@ -11,12 +11,11 @@ LINK_ENTITY_TO_CLASS(bot, CCSBot, CAPI_CSBot);
int GetBotFollowCount(CBasePlayer *leader)
{
int count = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBasePlayer *player = UTIL_PlayerByIndex(i);
if (player == NULL)
if (!player)
continue;
if (FNullEnt(player->pev))
@ -31,8 +30,8 @@ int GetBotFollowCount(CBasePlayer *leader)
if (!player->IsAlive())
continue;
CCSBot *bot = dynamic_cast<CCSBot *>(player);
if (bot != NULL && bot->GetFollowLeader() == leader)
CCSBot *bot = reinterpret_cast<CCSBot *>(player);
if (bot->IsBot() && bot->GetFollowLeader() == leader)
++count;
}
@ -79,8 +78,7 @@ int CCSBot::__MAKE_VHOOK(TakeDamage)(entvars_t *pevInflictor, entvars_t *pevAtta
if (attacker->IsPlayer())
{
CBasePlayer *player = static_cast<CBasePlayer *>(attacker);
if (player->m_iTeam == m_iTeam && !player->IsBot())
if (BotRelationship(player) == BOT_TEAMMATE && !player->IsBot())
{
GetChatter()->FriendlyFire();
}
@ -453,7 +451,7 @@ bool CCSBot::IsDoingScenario() const
if (cv_bot_defer_to_human.value <= 0.0f)
return true;
return !UTIL_HumansOnTeam(m_iTeam, true);
return !UTIL_HumansOnTeam(m_iTeam, IS_ALIVE);
}
// Return true if we noticed the bomb on the ground or on the radar (for T's only)
@ -650,7 +648,7 @@ CBasePlayer *CCSBot::GetImportantEnemy(bool checkVisibility) const
continue;
// skip friends
if (player->m_iTeam == m_iTeam)
if (BotRelationship(player) == BOT_TEAMMATE)
continue;
// is it "important"

View File

@ -50,7 +50,7 @@ void BotMeme::Transmit(CCSBot *sender) const
{
CBasePlayer *player = UTIL_PlayerByIndex(i);
if (player == NULL)
if (!player)
continue;
if (FNullEnt(player->pev))
@ -68,20 +68,15 @@ void BotMeme::Transmit(CCSBot *sender) const
continue;
// ignore enemies, since we can't hear them talk
if (sender->m_iTeam != player->m_iTeam)
if (sender->BotRelationship(player) == CCSBot::BOT_ENEMY)
continue;
// if not a bot, fail the test
if (!player->IsBot())
continue;
CCSBot *bot = dynamic_cast<CCSBot *>(player);
if (!bot)
continue;
// allow bot to interpret our meme
Interpret(sender, bot);
Interpret(sender, (CCSBot *)player);
}
}
@ -1523,14 +1518,14 @@ void BotChatterInterface::Update()
BotStatement *BotChatterInterface::GetActiveStatement()
{
// keep track of statement waiting longest to be spoken - it is next
BotStatement *earliest = NULL;
BotStatement *earliest = nullptr;
float earlyTime = 999999999.9f;
for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBasePlayer *player = UTIL_PlayerByIndex(i);
if (player == NULL)
if (!player)
continue;
if (FNullEnt(player->pev))
@ -1544,17 +1539,17 @@ BotStatement *BotChatterInterface::GetActiveStatement()
continue;
// ignore enemies, since we can't hear them talk
if (m_me->m_iTeam != player->m_iTeam)
if (m_me->BotRelationship(player) == CCSBot::BOT_ENEMY)
continue;
CCSBot *bot = dynamic_cast<CCSBot *>(player);
// if not a bot, fail the test
// TODO: Check if human is currently talking
if (!bot)
if (!player->IsBot())
continue;
for (BotStatement *say = bot->GetChatter()->m_statementList; say != NULL; say = say->m_next)
CCSBot *bot = reinterpret_cast<CCSBot *>(player);
auto say = bot->GetChatter()->m_statementList;
while (say)
{
// if this statement is currently being spoken, return it
if (say->IsSpeaking())
@ -1566,12 +1561,14 @@ BotStatement *BotChatterInterface::GetActiveStatement()
earlyTime = say->GetTimestamp();
earliest = say;
}
say = say->m_next;
}
}
// make sure it is time to start this statement
if (earliest != NULL && earliest->GetStartTime() > gpGlobals->time)
return NULL;
if (earliest && earliest->GetStartTime() > gpGlobals->time)
return nullptr;
return earliest;
}

View File

@ -41,7 +41,7 @@ void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBa
{
if (event == EVENT_PLAYER_DIED)
{
if (player->m_iTeam == m_iTeam)
if (BotRelationship(player) == BOT_TEAMMATE)
{
CBasePlayer *killer = static_cast<CBasePlayer *>(other);
@ -77,7 +77,7 @@ void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBa
CBasePlayer *killer = (other != NULL && other->IsPlayer()) ? static_cast<CBasePlayer *>(other) : NULL;
// if the human player died in the single player game, tell the team
if (CSGameRules()->IsCareer() && !victim->IsBot() && victim->m_iTeam == m_iTeam)
if (CSGameRules()->IsCareer() && !victim->IsBot() && BotRelationship(victim) == BOT_TEAMMATE)
{
GetChatter()->Say("CommanderDown", 20.0f);
}
@ -89,10 +89,10 @@ void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBa
}
// react to teammate death
if (victim->m_iTeam == m_iTeam)
if (BotRelationship(victim) == BOT_TEAMMATE)
{
// chastise friendly fire from humans
if (killer != NULL && !killer->IsBot() && killer->m_iTeam == m_iTeam && killer != this)
if (killer != NULL && !killer->IsBot() && BotRelationship(killer) == BOT_TEAMMATE && killer != this)
{
GetChatter()->KilledFriend();
}
@ -124,7 +124,7 @@ void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBa
// an enemy was killed
else
{
if (killer != NULL && killer->m_iTeam == m_iTeam)
if (killer != NULL && BotRelationship(killer) == BOT_TEAMMATE)
{
// only chatter about enemy kills if we see them occur, and they were the last one we see
if (GetNearbyEnemyCount() <= 1)
@ -240,7 +240,7 @@ void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBa
}
// Process radio events from our team
if (player != NULL && player->m_iTeam == m_iTeam && event > EVENT_START_RADIO_1 && event < EVENT_END_RADIO)
if (player != NULL && BotRelationship(player) == BOT_TEAMMATE && event > EVENT_START_RADIO_1 && event < EVENT_END_RADIO)
{
// TODO: Distinguish between radio commands and responses
if (event != EVENT_RADIO_AFFIRMATIVE && event != EVENT_RADIO_NEGATIVE && event != EVENT_RADIO_REPORTING_IN)

View File

@ -37,6 +37,10 @@ cvar_t cv_bot_profile_db = { "bot_profile_db", "BotProfile.db", FCVAR_SERVER, 0.
#endif
#ifdef REGAMEDLL_ADD
cvar_t cv_bot_deathmatch = { "bot_deathmatch", "0", FCVAR_SERVER, 0.0f, NULL };
#endif
void InstallBotControl()
{
if (TheBots != NULL)
@ -91,6 +95,11 @@ void Bot_RegisterCvars()
CVAR_REGISTER(&cv_bot_defer_to_human);
CVAR_REGISTER(&cv_bot_chatter);
CVAR_REGISTER(&cv_bot_profile_db);
#ifdef REGAMEDLL_ADD
CVAR_REGISTER(&cv_bot_deathmatch);
#endif
}
// Constructor

View File

@ -330,27 +330,24 @@ void CCSBotManager::__MAKE_VHOOK(ServerDeactivate)()
void CCSBotManager::__MAKE_VHOOK(ClientDisconnect)(CBasePlayer *pPlayer)
{
if (pPlayer != NULL && pPlayer->IsBot())
if (!pPlayer || !pPlayer->IsBot())
return;
auto pevTemp = VARS(pPlayer->edict());
CCSBot *bot = reinterpret_cast<CCSBot *>(pPlayer);
bot->Disconnect();
if (!FStringNull(pPlayer->pev->classname))
{
entvars_t *temp = VARS(pPlayer->edict());
CCSBot *pBot = dynamic_cast<CCSBot *>(pPlayer);
if (pBot != NULL)
{
pBot->Disconnect();
}
if (!FStringNull(pPlayer->pev->classname))
{
RemoveEntityHashValue(pPlayer->pev, STRING(pPlayer->pev->classname), CLASSNAME);
}
FREE_PRIVATE(pPlayer->edict());
CBasePlayer *player = GetClassPtr<CCSPlayer>((CBasePlayer *)temp);
AddEntityHashValue(player->pev, STRING(player->pev->classname), CLASSNAME);
player->pev->flags = FL_DORMANT;
RemoveEntityHashValue(pPlayer->pev, STRING(pPlayer->pev->classname), CLASSNAME);
}
FREE_PRIVATE(pPlayer->edict());
auto player = GetClassPtr<CCSPlayer>((CBasePlayer *)pevTemp);
AddEntityHashValue(player->pev, STRING(player->pev->classname), CLASSNAME);
player->pev->flags = FL_DORMANT;
}
void PrintAllEntities()
@ -1029,9 +1026,13 @@ void CCSBotManager::ValidateMapData()
m_zoneCount = 0;
m_gameScenario = SCENARIO_DEATHMATCH;
// Search all entities in the map and set the game type and
// store all zones (bomb target, etc).
#ifdef REGAMEDLL_ADD
// if we have included deathmatch mode, so set the game type like SCENARIO_DEATHMATCH
if (cv_bot_deathmatch.value > 0.0f)
return;
#endif
// Search all entities in the map and set the game type and store all zones (bomb target, etc).
CBaseEntity *entity = NULL;
int i;
for (i = 1; i < gpGlobals->maxEntities; ++i)
@ -1410,10 +1411,7 @@ unsigned int CCSBotManager::__MAKE_VHOOK(GetPlayerPriority)(CBasePlayer *player)
if (!player->IsBot())
return 0;
CCSBot *bot = dynamic_cast<CCSBot *>(player);
if (!bot)
return 0;
CCSBot *bot = reinterpret_cast<CCSBot *>(player);
// bots doing something important for the current scenario have high priority
switch (GetScenario())

View File

@ -1094,7 +1094,8 @@ bool CCSBot::IsFriendInTheWay(const Vector *goalPos) const
if (!player->IsAlive())
continue;
if (player->m_iTeam != m_iTeam)
// ignore enemies
if (BotRelationship(player) == BOT_ENEMY)
continue;
if (player == this)

View File

@ -678,7 +678,7 @@ CBasePlayer *CCSBot::FindMostDangerousThreat()
continue;
// is it an enemy?
if (player->m_iTeam == m_iTeam)
if (BotRelationship(player) == BOT_TEAMMATE)
{
TraceResult result;
UTIL_TraceLine(GetEyePosition(), player->pev->origin, ignore_monsters, ignore_glass, edict(), &result);
@ -810,8 +810,9 @@ CBasePlayer *CCSBot::FindMostDangerousThreat()
{
// find the area the player/bot is standing on
CNavArea *area;
CCSBot *bot = dynamic_cast<CCSBot *>(threat[i].enemy);
if (bot != NULL && bot->IsBot())
CCSBot *bot = reinterpret_cast<CCSBot *>(threat[i].enemy);
if (bot->IsBot())
{
area = bot->GetLastKnownArea();
}

View File

@ -795,15 +795,15 @@ void CCSBot::SilencerCheck()
// Invoked when in contact with a CWeaponBox
void CCSBot::__MAKE_VHOOK(OnTouchingWeapon)(CWeaponBox *box)
{
CBasePlayerItem *droppedGun = dynamic_cast<CBasePlayerItem *>(box->m_rgpPlayerItems[ PRIMARY_WEAPON_SLOT ]);
auto pDroppedWeapon = box->m_rgpPlayerItems[ PRIMARY_WEAPON_SLOT ];
// right now we only care about primary weapons on the ground
if (droppedGun != NULL)
if (pDroppedWeapon)
{
CBasePlayerWeapon *myGun = dynamic_cast<CBasePlayerWeapon *>(m_rgpPlayerItems[ PRIMARY_WEAPON_SLOT ]);
CBasePlayerWeapon *pWeapon = (CBasePlayerWeapon *)m_rgpPlayerItems[ PRIMARY_WEAPON_SLOT ];
// if the gun on the ground is the same one we have, dont bother
if (myGun != NULL && droppedGun->m_iId != myGun->m_iId)
if (pWeapon && pWeapon->IsWeapon() && pDroppedWeapon->m_iId != pWeapon->m_iId)
{
// if we don't have a weapon preference, give up
if (GetProfile()->HasPrimaryPreference())
@ -816,15 +816,14 @@ void CCSBot::__MAKE_VHOOK(OnTouchingWeapon)(CWeaponBox *box)
for (int i = 0; i < GetProfile()->GetWeaponPreferenceCount(); ++i)
{
int prefID = GetProfile()->GetWeaponPreference(i);
if (!IsPrimaryWeapon(prefID))
continue;
// if the gun we are using is more desirable, give up
if (prefID == myGun->m_iId)
if (prefID == pWeapon->m_iId)
break;
if (prefID == droppedGun->m_iId)
if (prefID == pDroppedWeapon->m_iId)
{
// the gun on the ground is better than the one we have - drop our gun
DropPrimary(this);
@ -859,7 +858,7 @@ bool CCSBot::IsFriendInLineOfFire()
{
CBasePlayer *player = static_cast<CBasePlayer *>(victim);
if (player->m_iTeam == m_iTeam)
if (BotRelationship(player) == BOT_TEAMMATE)
return true;
}
}

View File

@ -127,7 +127,7 @@ BOOL EXT_FUNC ClientConnect(edict_t *pEntity, const char *pszName, const char *p
void EXT_FUNC ClientDisconnect(edict_t *pEntity)
{
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pEntity));
CBasePlayer *pPlayer = CBasePlayer::Instance(pEntity);
if (!g_fGameOver)
{
@ -135,21 +135,26 @@ void EXT_FUNC ClientDisconnect(edict_t *pEntity)
#ifndef REGAMEDLL_FIXES
CSound *pSound = CSoundEnt::SoundPointerForIndex(CSoundEnt::ClientSoundIndex(pEntity));
if (pSound != NULL)
if (pSound)
pSound->Reset();
#endif
pEntity->v.takedamage = DAMAGE_NO;
pEntity->v.solid = SOLID_NOT;
pEntity->v.flags = FL_DORMANT;
if (pPlayer != NULL)
pPlayer->SetThink(NULL);
if (pPlayer)
pPlayer->SetThink(nullptr);
UTIL_SetOrigin(&pEntity->v, pEntity->v.origin);
g_pGameRules->ClientDisconnected(pEntity);
}
if (TheBots != NULL && pPlayer != NULL && pPlayer->IsBot())
#ifndef REGAMEDLL_FIXES
if (TheBots && pPlayer && pPlayer->IsBot())
#else
// These checks are already inside into this CCSBotManager::ClientDisconnect
if (TheBots)
#endif
{
TheBots->ClientDisconnect(pPlayer);
}
@ -180,28 +185,28 @@ void respawn(entvars_t *pev, BOOL fCopyCorpse)
void EXT_FUNC ClientKill(edict_t *pEntity)
{
entvars_t *pev = &pEntity->v;
CBasePlayer *pl = (CBasePlayer *)CBasePlayer::Instance(pev);
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (pl->IsObserver())
if (pPlayer->IsObserver())
return;
if (pl->m_iJoiningState != JOINED)
if (pPlayer->m_iJoiningState != JOINED)
return;
// prevent suiciding too often
if (pl->m_fNextSuicideTime > gpGlobals->time)
if (pPlayer->m_fNextSuicideTime > gpGlobals->time)
return;
pl->m_LastHitGroup = 0;
pPlayer->m_LastHitGroup = 0;
// don't let them suicide for 5 seconds after suiciding
pl->m_fNextSuicideTime = gpGlobals->time + 1;
pPlayer->m_fNextSuicideTime = gpGlobals->time + 1.0f;
// have the player kill themself
pEntity->v.health = 0;
pl->Killed(pev, GIB_NEVER);
pPlayer->Killed(pev, GIB_NEVER);
if (CSGameRules()->m_pVIP == pl)
if (CSGameRules()->m_pVIP == pPlayer)
{
CSGameRules()->m_iConsecutiveVIP = 10;
}
@ -219,18 +224,18 @@ void __API_HOOK(ShowMenu)(CBasePlayer *pPlayer, int bitsValidSlots, int nDisplay
MESSAGE_END();
}
LINK_HOOK_VOID_CHAIN(ShowVGUIMenu, (CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu), pPlayer, MenuType, BitMask, szOldMenu);
LINK_HOOK_VOID_CHAIN(ShowVGUIMenu, (CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu, bool bForceOldMenu), pPlayer, MenuType, BitMask, szOldMenu, bForceOldMenu);
void __API_HOOK(ShowVGUIMenu)(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu)
void __API_HOOK(ShowVGUIMenu)(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu, bool bForceOldMenu)
{
if (pPlayer->m_bVGUIMenus || MenuType > VGUI_Menu_Buy_Item)
if (!bForceOldMenu && (pPlayer->m_bVGUIMenus || MenuType > VGUI_Menu_Buy_Item))
{
MESSAGE_BEGIN(MSG_ONE, gmsgVGUIMenu, NULL, pPlayer->pev);
WRITE_BYTE(MenuType);
WRITE_SHORT(BitMask);
WRITE_CHAR(-1);
WRITE_BYTE(0);
WRITE_STRING(" ");
WRITE_BYTE(MenuType);
WRITE_SHORT(BitMask);
WRITE_CHAR(-1);
WRITE_BYTE(0);
WRITE_STRING(" ");
MESSAGE_END();
}
else
@ -669,7 +674,7 @@ void Host_Say(edict_t *pEntity, int teamonly)
Place playerPlace = TheNavAreaGrid.GetPlace(&player->pev->origin);
const BotPhraseList *placeList = TheBotPhrases->GetPlaceList();
for (auto& it : *placeList)
for (auto it : *placeList)
{
if (it->GetID() == playerPlace)
{
@ -3244,13 +3249,14 @@ void EXT_FUNC ClientCommand(edict_t *pEntity)
}
}
// called after the player changes userinfo - gives dll a chance to modify it before it gets sent into the rest of the engine.
void EXT_FUNC ClientUserInfoChanged(edict_t *pEntity, char *infobuffer)
{
// Is the client spawned yet?
if (!pEntity->pvPrivateData)
return;
CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance(pEntity);
CBasePlayer *pPlayer = CBasePlayer::Instance(pEntity);
char *szBufferName = GET_KEY_VALUE(infobuffer, "name");
// msg everyone if someone changes their name, and it isn't the first time (changing no name to current name)
@ -3270,6 +3276,7 @@ void EXT_FUNC ClientUserInfoChanged(edict_t *pEntity, char *infobuffer)
if (szName[0] == '#')
szName[0] = '*';
// Set the name
pPlayer->SetClientUserInfoName(infobuffer, szName);
}
@ -3857,7 +3864,16 @@ void ClientPrecache()
const char *EXT_FUNC GetGameDescription()
{
return g_bIsCzeroGame ? "Condition Zero" : "Counter-Strike";
#ifdef REGAMEDLL_ADD
if (CSGameRules()) {
return CSGameRules()->GetGameDescription();
}
#else
if (g_bIsCzeroGame) {
return "Condition Zero";
}
#endif
return "Counter-Strike";
}
void EXT_FUNC Sys_Error(const char *error_string)
@ -3938,14 +3954,13 @@ void EXT_FUNC SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned c
if (pClient->v.flags & FL_PROXY)
{
*pvs = NULL; // the spectator proxy sees
*pas = NULL; // and hears everything
*pvs = nullptr; // the spectator proxy sees
*pas = nullptr; // and hears everything
return;
}
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pClient));
if (pPlayer != NULL && pPlayer->pev->iuser2 && pPlayer->m_hObserverTarget)
CBasePlayer *pPlayer = CBasePlayer::Instance(pClient);
if (pPlayer && pPlayer->pev->iuser2 && pPlayer->m_hObserverTarget)
{
if (pPlayer->m_afPhysicsFlags & PFLAG_OBSERVER)
{
@ -4131,7 +4146,6 @@ int EXT_FUNC AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, ed
if (ent->v.owner)
{
int owner = ENTINDEX(ent->v.owner);
if (owner >= 1 && owner <= gpGlobals->maxClients)
state->owner = owner;
}
@ -4368,6 +4382,7 @@ void Custom_Encode(struct delta_s *pFields, const unsigned char *from, const uns
}
}
// Allows game .dll to override network encoding of certain types of entities and tweak values, etc.
void EXT_FUNC RegisterEncoders()
{
DELTA_ADDENCODER("Entity_Encode", Entity_Encode);
@ -4375,76 +4390,79 @@ void EXT_FUNC RegisterEncoders()
DELTA_ADDENCODER("Player_Encode", Player_Encode);
}
int EXT_FUNC GetWeaponData(edict_s *player, struct weapon_data_s *info)
int EXT_FUNC GetWeaponData(edict_t *player, struct weapon_data_s *info)
{
#ifdef CLIENT_WEAPONS
entvars_t *pev = &player->v;
CBasePlayer *pl = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
Q_memset(info, 0, sizeof(weapon_data_t) * MAX_WEAPONS);
if (!pl)
{
if (!pPlayer)
return 1;
}
// go through all of the weapons and make a list of the ones to pack
for (int i = 0; i < MAX_ITEM_TYPES; ++i)
{
CBasePlayerItem *pPlayerItem = pl->m_rgpPlayerItems[i];
while (pPlayerItem != NULL)
auto pPlayerItem = pPlayer->m_rgpPlayerItems[i];
while (pPlayerItem != nullptr)
{
CBasePlayerWeapon *gun = dynamic_cast<CBasePlayerWeapon *>(pPlayerItem->GetWeaponPtr());
if (gun != NULL && gun->UseDecrement())
// there's a weapon here. Should I pack it?
auto weapon = (CBasePlayerWeapon *)pPlayerItem->GetWeaponPtr();
if (weapon && weapon->UseDecrement())
{
// Get The ID
ItemInfo II;
Q_memset(&II, 0, sizeof(II));
gun->GetItemInfo(&II);
weapon->GetItemInfo(&II);
if (II.iId >= 0 && II.iId < MAX_WEAPONS)
{
weapon_data_t *item = &info[II.iId];
auto item = &info[II.iId];
item->m_iId = II.iId;
item->m_iClip = gun->m_iClip;
item->m_flTimeWeaponIdle = Q_max(gun->m_flTimeWeaponIdle, -0.001f);
item->m_flNextPrimaryAttack = Q_max(gun->m_flNextPrimaryAttack, -0.001f);
item->m_flNextSecondaryAttack = Q_max(gun->m_flNextSecondaryAttack, -0.001f);
item->m_flNextReload = Q_max(gun->m_flNextReload, -0.001f);
item->m_fInReload = gun->m_fInReload;
item->m_fInSpecialReload = gun->m_fInSpecialReload;
item->m_fInZoom = gun->m_iShotsFired;
item->m_fAimedDamage = gun->m_flLastFire;
item->m_iWeaponState = gun->m_iWeaponState;
item->fuser2 = gun->m_flStartThrow;
item->fuser3 = gun->m_flReleaseThrow;
item->iuser1 = gun->m_iSwing;
item->m_iClip = weapon->m_iClip;
item->m_flTimeWeaponIdle = Q_max(weapon->m_flTimeWeaponIdle, -0.001f);
item->m_flNextPrimaryAttack = Q_max(weapon->m_flNextPrimaryAttack, -0.001f);
item->m_flNextSecondaryAttack = Q_max(weapon->m_flNextSecondaryAttack, -0.001f);
item->m_flNextReload = Q_max(weapon->m_flNextReload, -0.001f);
item->m_fInReload = weapon->m_fInReload;
item->m_fInSpecialReload = weapon->m_fInSpecialReload;
item->m_fInZoom = weapon->m_iShotsFired;
item->m_fAimedDamage = weapon->m_flLastFire;
item->m_iWeaponState = weapon->m_iWeaponState;
item->fuser2 = weapon->m_flStartThrow;
item->fuser3 = weapon->m_flReleaseThrow;
item->iuser1 = weapon->m_iSwing;
}
}
pPlayerItem = pPlayerItem->m_pNext;
}
}
#else
Q_memset(info, 0, sizeof(weapon_data_t) * MAX_WEAPONS);
#endif
return 1;
}
// Data sent to current client only engine sets cd to 0 before calling.
void EXT_FUNC UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd)
{
if (!ent || !ent->pvPrivateData)
{
return;
}
entvars_t *pevOrg = NULL;
entvars_t *pevOrg = nullptr;
entvars_t *pev = const_cast<entvars_t *>(&ent->v);
CBasePlayer *pl = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (pl != NULL && pl->pev->iuser1 == OBS_IN_EYE && pl->m_hObserverTarget)
// if user is spectating different player in First person, override some vars
if (pPlayer && pPlayer->pev->iuser1 == OBS_IN_EYE && pPlayer->m_hObserverTarget)
{
pevOrg = pev;
pev = pl->m_hObserverTarget->pev;
pl = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
pev = pPlayer->m_hObserverTarget->pev;
pPlayer = CBasePlayer::Instance(pev);
}
cd->flags = pev->flags;
@ -4487,34 +4505,34 @@ void EXT_FUNC UpdateClientData(const struct edict_s *ent, int sendweapons, struc
cd->fuser3 = pev->fuser3;
cd->fuser2 = pev->fuser2;
if (sendweapons && pl != NULL)
if (sendweapons && pPlayer)
{
cd->ammo_shells = pl->ammo_buckshot;
cd->ammo_nails = pl->ammo_9mm;
cd->ammo_cells = pl->ammo_556nato;
cd->ammo_rockets = pl->ammo_556natobox;
cd->vuser2.x = pl->ammo_762nato;
cd->vuser2.y = pl->ammo_45acp;
cd->vuser2.z = pl->ammo_50ae;
cd->vuser3.x = pl->ammo_338mag;
cd->vuser3.y = pl->ammo_57mm;
cd->vuser3.z = pl->ammo_357sig;
cd->m_flNextAttack = pl->m_flNextAttack;
cd->ammo_shells = pPlayer->ammo_buckshot;
cd->ammo_nails = pPlayer->ammo_9mm;
cd->ammo_cells = pPlayer->ammo_556nato;
cd->ammo_rockets = pPlayer->ammo_556natobox;
cd->vuser2.x = pPlayer->ammo_762nato;
cd->vuser2.y = pPlayer->ammo_45acp;
cd->vuser2.z = pPlayer->ammo_50ae;
cd->vuser3.x = pPlayer->ammo_338mag;
cd->vuser3.y = pPlayer->ammo_57mm;
cd->vuser3.z = pPlayer->ammo_357sig;
cd->m_flNextAttack = pPlayer->m_flNextAttack;
int iUser3 = 0;
if (pl->m_bCanShoot && !pl->m_bIsDefusing)
if (pPlayer->m_bCanShoot && !pPlayer->m_bIsDefusing)
iUser3 |= DATA_IUSER3_CANSHOOT;
if (g_pGameRules->IsFreezePeriod())
iUser3 |= DATA_IUSER3_FREEZETIMEOVER;
if (pl->m_signals.GetState() & SIGNAL_BOMB)
if (pPlayer->m_signals.GetState() & SIGNAL_BOMB)
iUser3 |= DATA_IUSER3_INBOMBZONE;
if (pl->HasShield())
if (pPlayer->HasShield())
iUser3 |= DATA_IUSER3_HOLDINGSHIELD;
if (!pl->pev->iuser1 && !pevOrg)
if (pPlayer->pev->iuser1 == OBS_NONE && !pevOrg)
{
#ifdef REGAMEDLL_ADD
// useful for mods
@ -4523,21 +4541,20 @@ void EXT_FUNC UpdateClientData(const struct edict_s *ent, int sendweapons, struc
cd->iuser3 = iUser3;
}
if (pl->m_pActiveItem != NULL)
if (pPlayer->m_pActiveItem)
{
ItemInfo II;
Q_memset(&II, 0, sizeof(II));
CBasePlayerWeapon *gun = dynamic_cast<CBasePlayerWeapon *>(pl->m_pActiveItem->GetWeaponPtr());
if (gun != NULL && gun->UseDecrement() && gun->GetItemInfo(&II))
CBasePlayerWeapon *weapon = (CBasePlayerWeapon *)pPlayer->m_pActiveItem->GetWeaponPtr();
if (weapon && weapon->UseDecrement() && weapon->GetItemInfo(&II))
{
cd->m_iId = II.iId;
if ((unsigned int)gun->m_iPrimaryAmmoType < MAX_AMMO_TYPES)
if ((unsigned int)weapon->m_iPrimaryAmmoType < MAX_AMMO_TYPES)
{
cd->vuser4.x = gun->m_iPrimaryAmmoType;
cd->vuser4.y = pl->m_rgAmmo[ gun->m_iPrimaryAmmoType ];
cd->vuser4.x = weapon->m_iPrimaryAmmoType;
cd->vuser4.y = pPlayer->m_rgAmmo[ weapon->m_iPrimaryAmmoType ];
}
else
{
@ -4552,32 +4569,30 @@ void EXT_FUNC UpdateClientData(const struct edict_s *ent, int sendweapons, struc
void EXT_FUNC CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed)
{
entvars_t *pev = const_cast<entvars_t *>(&player->v);
CBasePlayer *pl = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (pl != NULL)
{
if (pl->pev->groupinfo)
{
UTIL_SetGroupTrace(pl->pev->groupinfo, GROUP_OP_AND);
}
if (!pPlayer)
return;
pl->random_seed = random_seed;
}
if (pPlayer->pev->groupinfo)
UTIL_SetGroupTrace(pPlayer->pev->groupinfo, GROUP_OP_AND);
pPlayer->random_seed = random_seed;
}
void EXT_FUNC CmdEnd(const edict_t *player)
{
entvars_t *pev = const_cast<entvars_t *>(&player->v);
CBasePlayer *pl = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (pl != NULL)
{
if (pl->pev->groupinfo)
UTIL_UnsetGroupTrace();
if (!pPlayer)
return;
if (pev->flags & FL_DUCKING)
UTIL_SetSize(pev, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX);
}
if (pPlayer->pev->groupinfo)
UTIL_UnsetGroupTrace();
if (pev->flags & FL_DUCKING)
UTIL_SetSize(pev, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX);
}
int EXT_FUNC ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size)

View File

@ -122,8 +122,8 @@ void respawn(entvars_t *pev, BOOL fCopyCorpse = FALSE);
void ClientKill(edict_t *pEntity);
void ShowMenu(CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText);
void ShowMenu_(CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText);
void ShowVGUIMenu(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu);
void ShowVGUIMenu_(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu);
void ShowVGUIMenu(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu, bool bForceOldMenu = false);
void ShowVGUIMenu_(CBasePlayer *pPlayer, int MenuType, int BitMask, char *szOldMenu, bool bForceOldMenu = false);
void ListPlayers(CBasePlayer *current);
void ProcessKickVote(CBasePlayer *pVotingPlayer, CBasePlayer *pKickPlayer);
TeamName SelectDefaultTeam();

View File

@ -102,7 +102,7 @@ cvar_t hegrenade_penetration = { "mp_hegrenade_penetration", "0", 0, 0.0f, nullp
cvar_t nadedrops = { "mp_nadedrops", "0", 0, 0.0f, nullptr };
cvar_t roundrespawn_time = { "mp_roundrespawn_time", "20", 0, 20.0f, nullptr };
cvar_t auto_reload_weapons = { "mp_auto_reload_weapons", "0", 0, 0.0f, nullptr };
cvar_t refill_bpammo_weapons = { "mp_refill_bpammo_weapons", "0", 0, 0.0f, nullptr }; // Useful for mods like CSDM, GunGame, ZombieMod etc
cvar_t refill_bpammo_weapons = { "mp_refill_bpammo_weapons", "0", 0, 0.0f, nullptr }; // Useful for mods like DeathMatch, GunGame, ZombieMod etc
void GameDLL_Version_f()
{

View File

@ -9,6 +9,29 @@ CGameRules *g_pGameRules = NULL;
#endif
CGameRules::CGameRules()
: m_GameDesc()
{
m_GameDesc = new char[sizeof("Counter-Strike")];
Q_strcpy(m_GameDesc, AreRunningCZero() ? "Condition Zero" : "Counter-Strike");
}
CGameRules::~CGameRules()
{
delete[] m_GameDesc;
m_GameDesc = nullptr;
}
// this is the game name that gets seen in the server browser
const char *CGameRules::GetGameDescription()
{
#ifdef REGAMEDLL_ADD
return m_GameDesc;
#else
return "Counter-Strike";
#endif
}
BOOL CGameRules::__MAKE_VHOOK(CanHaveAmmo)(CBasePlayer *pPlayer, const char *pszAmmoName, int iMaxCarry)
{
int iAmmoIndex;

View File

@ -218,6 +218,8 @@ class CItem;
class CGameRules
{
public:
CGameRules();
virtual ~CGameRules();
virtual void RefreshSkillData();
virtual void Think() = 0;
virtual BOOL IsAllowedToSpawn(CBaseEntity *pEntity) = 0;
@ -228,7 +230,7 @@ public:
virtual BOOL IsDeathmatch() = 0;
virtual BOOL IsTeamplay() { return FALSE; }
virtual BOOL IsCoOp() = 0;
virtual const char *GetGameDescription() { return "Counter-Strike"; } // this is the game name that gets seen in the server browser
virtual const char *GetGameDescription(); // this is the game name that gets seen in the server browser
virtual BOOL ClientConnected(edict_t *pEntity, const char *pszName, const char *pszAddress, char *szRejectReason) = 0;
virtual void InitHUD(CBasePlayer *pl) = 0;
virtual void ClientDisconnected(edict_t *pClient) = 0;
@ -296,12 +298,16 @@ public:
public:
BOOL m_bFreezePeriod;
BOOL m_bBombDropped;
// custom
char *m_GameDesc;
};
class CHalfLifeRules: public CGameRules
{
public:
CHalfLifeRules();
virtual ~CHalfLifeRules() {};
virtual void Think();
virtual BOOL IsAllowedToSpawn(CBaseEntity *pEntity);
@ -400,7 +406,8 @@ class CHalfLifeMultiplay: public CGameRules
{
public:
CHalfLifeMultiplay();
public:
virtual ~CHalfLifeMultiplay() {};
virtual void RefreshSkillData();
virtual void Think();
virtual BOOL IsAllowedToSpawn(CBaseEntity *pEntity);
@ -614,6 +621,7 @@ public:
VFUNC void UpdateTeamScores();
VFUNC void EndRoundMessage(const char *sentence, int event);
VFUNC void SetAccountRules(RewardRules rules, int amount) { m_rgRewardAccountRules[rules] = static_cast<RewardAccount>(amount); }
VFUNC RewardAccount GetAccountRules(RewardRules rules) const { return m_rgRewardAccountRules[rules]; }
void DisplayMaps(CBasePlayer *player, int iVote);
void ResetAllMapVotes();

View File

@ -1059,11 +1059,10 @@ CGrenade *CGrenade::ShootSatchelCharge(entvars_t *pevOwner, Vector vecStart, Vec
pGrenade->pev->friction = 0.9f;
pGrenade->m_bJustBlew = false;
CBasePlayer *owner = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pevOwner));
if (owner != NULL && owner->IsPlayer())
CBasePlayer *pOwner = CBasePlayer::Instance(pevOwner);
if (pOwner && pOwner->IsPlayer())
{
pGrenade->m_pentCurBombTarget = owner->m_pentCurBombTarget;
pGrenade->m_pentCurBombTarget = pOwner->m_pentCurBombTarget;
}
else
pGrenade->m_pentCurBombTarget = NULL;
@ -1217,15 +1216,14 @@ void CGrenade::C4Think()
if (m_pentCurBombTarget)
{
CBaseEntity *pBombTarget = CBaseEntity::Instance(m_pentCurBombTarget);
if (pBombTarget)
{
pBombTarget->Use(CBaseEntity::Instance(pev->owner), this, USE_TOGGLE, 0);
}
}
CBasePlayer *pBombOwner = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pev->owner));
if (pBombOwner != NULL)
CBasePlayer *pBombOwner = CBasePlayer::Instance(pev->owner);
if (pBombOwner)
{
pBombOwner->pev->frags += 3.0f;
}

View File

@ -33,7 +33,7 @@ RewardAccount CHalfLifeMultiplay::m_rgRewardAccountRules[] = {
REWARD_LOSER_BONUS_MAX, // RR_LOSER_BONUS_MAX
REWARD_LOSER_BONUS_ADD, // RR_LOSER_BONUS_ADD
REWARD_RESCUED_HOSTAGE, // RR_RESCUED_HOSTAGE
REWARD_TOOK_HOSTAGE_ACC, // RR_TOOK_HOSTAGE_ACC
REWARD_TOOK_HOSTAGE_ACC, // RR_TOOK_HOSTAGE_ACC
REWARD_TOOK_HOSTAGE, // RR_TOOK_HOSTAGE
};
@ -3807,11 +3807,11 @@ void CHalfLifeMultiplay::__API_VHOOK(DeathNotice)(CBasePlayer *pVictim, entvars_
if (pevInflictor == pKiller)
{
// If the inflictor is the killer, then it must be their current weapon doing the damage
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pKiller));
if (pPlayer != NULL && pPlayer->m_pActiveItem != NULL)
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
if (pAttacker && pAttacker->IsPlayer())
{
killer_weapon_name = pPlayer->m_pActiveItem->pszName();
if (pAttacker->m_pActiveItem)
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
}
}
else
@ -3825,29 +3825,30 @@ void CHalfLifeMultiplay::__API_VHOOK(DeathNotice)(CBasePlayer *pVictim, entvars_
#ifdef REGAMEDLL_FIXES
if (pevInflictor)
#endif
{
killer_weapon_name = STRING(pevInflictor->classname);
}
// strip the monster_* or weapon_* from the inflictor's classname
if (!Q_strncmp(killer_weapon_name, "weapon_", 7))
killer_weapon_name += 7;
const char cut_weapon[] = "weapon_";
const char cut_monster[] = "monster_";
const char cut_func[] = "func_";
else if (!Q_strncmp(killer_weapon_name, "monster_", 8))
killer_weapon_name += 8;
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
killer_weapon_name += sizeof(cut_weapon) - 1;
else if (!Q_strncmp(killer_weapon_name, "func_", 5))
killer_weapon_name += 5;
else if (!Q_strncmp(killer_weapon_name, cut_monster, sizeof(cut_monster) - 1))
killer_weapon_name += sizeof(cut_monster) - 1;
int iGotHeadshot = 0;
else if (!Q_strncmp(killer_weapon_name, cut_func, sizeof(cut_func) - 1))
killer_weapon_name += sizeof(cut_func) - 1;
if (pVictim->m_bHeadshotKilled)
iGotHeadshot = 1;
if (TheTutor == NULL)
if (TheTutor == nullptr)
{
MESSAGE_BEGIN(MSG_ALL, gmsgDeathMsg);
WRITE_BYTE(killer_index); // the killer
WRITE_BYTE(ENTINDEX(pVictim->edict())); // the victim
WRITE_BYTE(iGotHeadshot); // is killed headshot
WRITE_BYTE(pVictim->m_bHeadshotKilled); // is killed headshot
WRITE_STRING(killer_weapon_name); // what they were killed by (should this be a string?)
MESSAGE_END();
}
@ -3872,10 +3873,10 @@ void CHalfLifeMultiplay::__API_VHOOK(DeathNotice)(CBasePlayer *pVictim, entvars_
}
else if (pKiller->flags & FL_CLIENT)
{
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pKiller));
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
const char *VictimTeam = GetTeam(pVictim->m_iTeam);
const char *KillerTeam = (pPlayer != NULL) ? GetTeam(pPlayer->m_iTeam) : "";
const char *KillerTeam = (pAttacker && pAttacker->IsPlayer()) ? GetTeam(pAttacker->m_iTeam) : "";
UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", STRING(pKiller->netname), GETPLAYERUSERID(ENT(pKiller)), GETPLAYERAUTHID(ENT(pKiller)),
KillerTeam, STRING(pVictim->pev->netname), GETPLAYERUSERID(pVictim->edict()), GETPLAYERAUTHID(pVictim->edict()), VictimTeam, killer_weapon_name);
@ -3900,7 +3901,7 @@ void CHalfLifeMultiplay::__API_VHOOK(DeathNotice)(CBasePlayer *pVictim, entvars_
else
WRITE_SHORT(ENTINDEX(ENT(pKiller))); // index number of secondary entity
if (iGotHeadshot)
if (pVictim->m_bHeadshotKilled)
WRITE_LONG(9 | DRC_FLAG_DRAMATIC | DRC_FLAG_SLOWMOTION);
else
WRITE_LONG(7 | DRC_FLAG_DRAMATIC); // eventflags (priority and flags)

View File

@ -508,8 +508,7 @@ CBasePlayer *CBasePlayer::GetNextRadioRecipient(CBasePlayer *pStartPlayer)
if (!FNullEnt(m_hObserverTarget))
continue;
CBasePlayer *pTarget = (CBasePlayer *)CBaseEntity::Instance(pPlayer->m_hObserverTarget->pev);
CBasePlayer *pTarget = CBasePlayer::Instance(pPlayer->m_hObserverTarget->pev);
if (pTarget != NULL && pTarget->m_iTeam == m_iTeam)
{
bSend = true;
@ -759,9 +758,8 @@ void CBasePlayer::__API_VHOOK(TraceAttack)(entvars_t *pevAttacker, float flDamag
bool bShouldSpark = false;
bool bHitShield = IsHittingShield(vecDir, ptr);
CBasePlayer *pAttacker = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pevAttacker));
if (pAttacker != NULL && m_iTeam == pAttacker->m_iTeam && CVAR_GET_FLOAT("mp_friendlyfire") == 0)
CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
if (pAttacker && pAttacker->IsPlayer() && m_iTeam == pAttacker->m_iTeam && CVAR_GET_FLOAT("mp_friendlyfire") == 0)
bShouldBleed = false;
if (pev->takedamage == DAMAGE_NO)
@ -904,36 +902,52 @@ void CBasePlayer::__API_VHOOK(TraceAttack)(entvars_t *pevAttacker, float flDamag
const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller)
{
// by default, the player is killed by the world
const char *killer_weapon_name = "world";
// Is the killer a client?
if (pKiller->flags & FL_CLIENT)
{
if (pevInflictor)
{
if (pevInflictor == pKiller)
{
CBasePlayer *pAttacker = dynamic_cast<CBasePlayer *>(CBaseEntity::Instance(pKiller));
if (pAttacker != NULL)
// If the inflictor is the killer, then it must be their current weapon doing the damage
CBasePlayer *pAttacker = CBasePlayer::Instance(pKiller);
if (pAttacker && pAttacker->IsPlayer())
{
if (pAttacker->m_pActiveItem != NULL)
if (pAttacker->m_pActiveItem)
killer_weapon_name = pAttacker->m_pActiveItem->pszName();
}
}
else
{
// it's just that easy
killer_weapon_name = STRING(pevInflictor->classname);
}
}
}
else
#ifdef REGAMEDLL_FIXES
if (pevInflictor)
#endif
{
killer_weapon_name = STRING(pevInflictor->classname);
}
if (!Q_strncmp(killer_weapon_name, "weapon_", 7))
killer_weapon_name += 7;
// strip the monster_* or weapon_* from the inflictor's classname
const char cut_weapon[] = "weapon_";
const char cut_monster[] = "monster_";
const char cut_func[] = "func_";
else if (!Q_strncmp(killer_weapon_name, "monster_", 8))
killer_weapon_name += 8;
if (!Q_strncmp(killer_weapon_name, cut_weapon, sizeof(cut_weapon) - 1))
killer_weapon_name += sizeof(cut_weapon) - 1;
else if (Q_strncmp(killer_weapon_name, "func_", 5) != 0)
killer_weapon_name += 5;
else if (!Q_strncmp(killer_weapon_name, cut_monster, sizeof(cut_monster) - 1))
killer_weapon_name += sizeof(cut_monster) - 1;
else if (!Q_strncmp(killer_weapon_name, cut_func, sizeof(cut_func) - 1))
killer_weapon_name += sizeof(cut_func) - 1;
return killer_weapon_name;
}
@ -972,8 +986,8 @@ int CBasePlayer::__API_VHOOK(TakeDamage)(entvars_t *pevInflictor, entvars_t *pev
float flShieldRatio = 0;
BOOL bTeamAttack = FALSE;
int armorHit = 0;
CBasePlayer *pAttack = NULL;
CBaseEntity *pAttacker = NULL;
CBasePlayer *pAttack = nullptr;
CBaseEntity *pAttacker = nullptr;
if (bitsDamageType & (DMG_EXPLOSION | DMG_BLAST | DMG_FALL))
m_LastHitGroup = HITGROUP_GENERIC;
@ -1005,7 +1019,7 @@ int CBasePlayer::__API_VHOOK(TakeDamage)(entvars_t *pevInflictor, entvars_t *pev
if (!CSGameRules()->IsFriendlyFireAttack() && pGrenade->m_iTeam == m_iTeam)
bTeamAttack = TRUE;
pAttack = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pevAttacker));
pAttack = CBasePlayer::Instance(pevAttacker);
}
else if (pGrenade->m_iTeam == m_iTeam && (&edict()->v != pevAttacker))
{
@ -1415,11 +1429,11 @@ void packPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
#ifdef REGAMEDLL_ADD
void packPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
{
if (pItem == NULL)
if (!pItem)
return;
const char *modelName = GetCSModelName(pItem->m_iId);
if (modelName != NULL)
if (modelName)
{
float flOffset = 0.0f;
switch (pItem->m_iId)
@ -1435,6 +1449,15 @@ void packPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo)
break;
}
if (pItem->m_flStartThrow != 0.0f)
{
auto& ammoNades = pPlayer->m_rgAmmo[ pItem->PrimaryAmmoIndex() ];
if (ammoNades < 2)
return;
ammoNades--;
}
Vector vecAngles = pPlayer->pev->angles;
Vector dir(Q_cos(vecAngles.y) * flOffset, Q_sin(vecAngles.y) * flOffset, 0.0f);
@ -1515,7 +1538,7 @@ void CBasePlayer::PackDeadPlayerItems()
switch ((int)nadedrops.value)
{
case 1:
packPlayerItem(this, pPlayerItem, true);
packPlayerNade(this, pPlayerItem, true);
break;
case 2:
{
@ -1962,14 +1985,12 @@ void CBasePlayer::__API_VHOOK(Killed)(entvars_t *pevAttacker, int iGib)
if (!m_bKilledByBomb)
{
CBasePlayer *pAttacker = (CBasePlayer *)CBaseEntity::Instance(pevAttacker);
CBasePlayer *pAttacker = CBasePlayer::Instance(pevAttacker);
if (pAttacker->HasShield())
killerHasShield = true;
CCSBot *pBot = static_cast<CCSBot *>(this);
if (pBot->IsBot() && pBot->IsBlind())
if (IsBot() && IsBlind())
{
wasBlind = true;
}
@ -1982,7 +2003,6 @@ void CBasePlayer::__API_VHOOK(Killed)(entvars_t *pevAttacker, int iGib)
continue;
bool killedByHumanPlayer = (!pPlayer->IsBot() && pPlayer->pev == pevAttacker && pPlayer->m_iTeam != m_iTeam);
if (killedByHumanPlayer)
{
if (TheCareerTasks != NULL)
@ -2038,7 +2058,7 @@ void CBasePlayer::__API_VHOOK(Killed)(entvars_t *pevAttacker, int iGib)
#endif
SetAnimation(PLAYER_DIE);
if (m_pActiveItem != NULL && m_pActiveItem->m_pPlayer != NULL)
if (m_pActiveItem && m_pActiveItem->m_pPlayer)
{
switch (m_pActiveItem->m_iId)
{
@ -8030,13 +8050,13 @@ void CBasePlayer::ResetStamina()
float_precision GetPlayerPitch(const edict_t *pEdict)
{
if( !pEdict )
if (!pEdict)
return 0.0f;
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
if (!pPlayer)
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (!pPlayer || !pPlayer->IsPlayer())
return 0.0f;
return pPlayer->m_flPitch;
@ -8044,13 +8064,13 @@ float_precision GetPlayerPitch(const edict_t *pEdict)
float_precision GetPlayerYaw(const edict_t *pEdict)
{
if( !pEdict )
if (!pEdict)
return 0.0f;
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
if (!pPlayer)
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (!pPlayer || !pPlayer->IsPlayer())
return 0.0f;
return pPlayer->m_flYaw;
@ -8058,10 +8078,13 @@ float_precision GetPlayerYaw(const edict_t *pEdict)
int GetPlayerGaitsequence(const edict_t *pEdict)
{
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = dynamic_cast<CBasePlayer *>(CBasePlayer::Instance(pev));
if (!pEdict)
return 1;
if (!pPlayer)
entvars_t *pev = VARS(const_cast<edict_t *>(pEdict));
CBasePlayer *pPlayer = CBasePlayer::Instance(pev);
if (!pPlayer || !pPlayer->IsPlayer())
return 1;
return pPlayer->m_iGaitsequence;

View File

@ -420,6 +420,10 @@ public:
#endif
public:
static CBasePlayer *Instance(edict_t *pent) { return (CBasePlayer *)GET_PRIVATE(pent ? pent : ENT(0)); }
static CBasePlayer *Instance(entvars_t *pev) { return Instance(ENT(pev)); }
static CBasePlayer *Instance(int offset) { return Instance(ENT(offset)); }
void SpawnClientSideCorpse();
void Observer_FindNextPlayer(bool bReverse, const char *name = NULL);
CBasePlayer *Observer_IsValidTarget(int iPlayerIndex, bool bSameTeam);

View File

@ -36,6 +36,8 @@ class CHalfLifeTraining: public CHalfLifeMultiplay
{
public:
CHalfLifeTraining();
virtual ~CHalfLifeTraining() {};
virtual BOOL IsMultiplayer() { return FALSE; }
virtual BOOL IsDeathmatch();
virtual void InitHUD(CBasePlayer *pl);

View File

@ -212,7 +212,7 @@ void UTIL_UnsetGroupTrace()
g_groupmask = 0;
g_groupop = 0;
ENGINE_SETGROUPMASK(0,0);
ENGINE_SETGROUPMASK(0, 0);
}
NOXREF UTIL_GroupTrace::UTIL_GroupTrace(int groupmask, int op)
@ -524,12 +524,12 @@ CBaseEntity *UTIL_FindEntityGeneric(const char *szWhatever, const Vector &vecSrc
CBasePlayer *EXT_FUNC UTIL_PlayerByIndex(int playerIndex)
{
CBasePlayer *pPlayer = NULL;
CBasePlayer *pPlayer = nullptr;
if (playerIndex > 0 && playerIndex <= gpGlobals->maxClients)
{
edict_t *pPlayerEdict = INDEXENT(playerIndex);
if (pPlayerEdict != NULL && !pPlayerEdict->free)
pPlayer = (CBasePlayer *)CBaseEntity::Instance(pPlayerEdict);
if (pPlayerEdict && !pPlayerEdict->free)
pPlayer = CBasePlayer::Instance(pPlayerEdict);
}
return pPlayer;

View File

@ -209,6 +209,8 @@ enum
class CItem;
class CGameRules {
protected:
virtual ~CGameRules() {};
public:
virtual void RefreshSkillData() = 0;
virtual void Think() = 0;
@ -280,9 +282,14 @@ public:
public:
BOOL m_bFreezePeriod;
BOOL m_bBombDropped;
// custom
char *m_GameDesc;
};
class CHalfLifeRules: public CGameRules {
protected:
virtual ~CHalfLifeRules() {};
public:
virtual void Think() = 0;
virtual BOOL IsAllowedToSpawn(CBaseEntity *pEntity) = 0;
@ -328,6 +335,8 @@ public:
};
class CHalfLifeMultiplay: public CGameRules {
protected:
virtual ~CHalfLifeMultiplay() {};
public:
virtual void RefreshSkillData() = 0;
virtual void Think() = 0;
@ -407,6 +416,7 @@ public:
virtual void UpdateTeamScores() = 0;
virtual void EndRoundMessage(const char *sentence, int event) = 0;
virtual void SetAccountRules(RewardRules rules, int amount) = 0;
virtual RewardAccount GetAccountRules(RewardRules rules) const = 0;
// BOMB MAP FUNCTIONS
virtual BOOL IsThereABomber() = 0;

View File

@ -342,6 +342,10 @@ public:
virtual void Blind(float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha) = 0;
virtual void OnTouchingWeapon(CWeaponBox *pWeapon) = 0;
public:
static CBasePlayer *Instance(edict_t *pent) { return (CBasePlayer *)GET_PRIVATE(pent ? pent : ENT(0)); }
static CBasePlayer *Instance(entvars_t *pev) { return Instance(ENT(pev)); }
static CBasePlayer *Instance(int offset) { return Instance(ENT(offset)); }
int IsObserver() { return pev->iuser1; }
void SetWeaponAnimType(const char *szExtention) { strcpy(m_szAnimExtention, szExtention); }
bool IsProtectedByShield() { return m_bOwnsShield && m_bShieldDrawn; }

View File

@ -210,8 +210,8 @@ typedef IVoidHookChain<class CBasePlayer *, int, int, BOOL, char *> IReGameHook_
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, BOOL, char *> IReGameHookRegistry_ShowMenu;
// ShowVGUIMenu hook
typedef IVoidHookChain<class CBasePlayer *, int, int, char *> IReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, char *> IReGameHookRegistry_ShowVGUIMenu;
typedef IVoidHookChain<class CBasePlayer *, int, int, char *, bool> IReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, char *, bool> IReGameHookRegistry_ShowVGUIMenu;
// CHalfLifeMultiplay::FShouldSwitchWeapon hook
typedef IHookChain<BOOL, class CBasePlayer *, class CBasePlayerItem *> IReGameHook_CSGameRules_FShouldSwitchWeapon;

View File

@ -28,6 +28,8 @@
#pragma once
class CHalfLifeTraining: public CHalfLifeMultiplay {
protected:
virtual ~CHalfLifeTraining() {};
public:
virtual BOOL IsMultiplayer() = 0;
virtual BOOL IsDeathmatch() = 0;

View File

@ -346,7 +346,7 @@ bool CBot::IsEnemy(CBaseEntity *ent) const
CBasePlayer *player = static_cast<CBasePlayer *>(ent);
// if they are on our team, they are our friends
if (player->m_iTeam == m_iTeam)
if (BotRelationship(player) == BOT_TEAMMATE)
return false;
// yep, we hate 'em

View File

@ -84,10 +84,13 @@ public:
CBasePlayer::Killed(pevAttacker, iGib);
}
virtual void Think() {};
virtual BOOL IsBot() { return true; }
virtual BOOL IsBot() { return TRUE; }
virtual Vector GetAutoaimVector(float flDelta);
// invoked when in contact with a CWeaponBox
virtual void OnTouchingWeapon(CWeaponBox *box) {}
// prepare bot for action
virtual bool Initialize(const BotProfile *profile);
virtual void SpawnBot() = 0;
@ -179,6 +182,7 @@ public:
#endif
public:
// return bot's unique ID
unsigned int GetID() const { return m_id; }
bool IsRunning() const { return m_isRunning; }
bool IsCrouching() const { return m_isCrouching; }
@ -239,6 +243,13 @@ public:
// return our personality profile
const BotProfile *GetProfile() const { return m_profile; }
enum BotRelationshipTeam: uint8
{
BOT_TEAMMATE = 0,
BOT_ENEMY
};
BotRelationshipTeam BotRelationship(CBasePlayer *pTarget) const;
#ifndef HOOK_GAMEDLL
protected:
#endif
@ -408,6 +419,16 @@ inline bool CBot::__MAKE_VHOOK(IsPlayerLookingAtMe)(CBasePlayer *other) const
return false;
}
inline CBot::BotRelationshipTeam CBot::BotRelationship(CBasePlayer *pTarget) const
{
#ifdef REGAMEDLL_ADD
if (cv_bot_deathmatch.value > 1.0f)
return BOT_ENEMY;
#endif
return pTarget->m_iTeam == m_iTeam ? BOT_TEAMMATE : BOT_ENEMY;
}
extern float g_flBotCommandInterval;
extern float g_flBotFullThinkInterval;

View File

@ -208,6 +208,10 @@ extern cvar_t cv_bot_defer_to_human;
extern cvar_t cv_bot_chatter;
extern cvar_t cv_bot_profile_db;
#ifdef REGAMEDLL_ADD
extern cvar_t cv_bot_deathmatch;
#endif
#define IS_ALIVE true
int UTIL_HumansOnTeam(int teamID, bool isAlive = false);

View File

@ -267,7 +267,7 @@ FunctionHook g_FunctionHooks[] =
{ 0x01D63E50, "_Z7respawnP9entvars_si", (size_t)&respawn },
{ 0x01D63F60, "_Z10ClientKillP7edict_s", (size_t)&ClientKill },
{ 0x01D64010, "_Z8ShowMenuP11CBasePlayeriiiPc_constprop_32", (size_t)&ShowMenu },
{ 0x01D64070, "_Z12ShowVGUIMenuP11CBasePlayeriiPc", (size_t)&ShowVGUIMenu },
//{ 0x01D64070, "_Z12ShowVGUIMenuP11CBasePlayeriiPc", (size_t)&ShowVGUIMenu },
{ 0x01D64130, "CountTeams", (size_t)&CountTeams }, //extern c func
{ 0x01D64260, "_Z11ListPlayersP11CBasePlayer", (size_t)&ListPlayers },
{ 0x01D64460, "CountTeamPlayers", (size_t)&CountTeamPlayers }, //extern c func

View File

@ -210,8 +210,8 @@ typedef IVoidHookChain<class CBasePlayer *, int, int, BOOL, char *> IReGameHook_
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, BOOL, char *> IReGameHookRegistry_ShowMenu;
// ShowVGUIMenu hook
typedef IVoidHookChain<class CBasePlayer *, int, int, char *> IReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, char *> IReGameHookRegistry_ShowVGUIMenu;
typedef IVoidHookChain<class CBasePlayer *, int, int, char *, bool> IReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistry<class CBasePlayer *, int, int, char *, bool> IReGameHookRegistry_ShowVGUIMenu;
// CHalfLifeMultiplay::FShouldSwitchWeapon hook
typedef IHookChain<BOOL, class CBasePlayer *, class CBasePlayerItem *> IReGameHook_CSGameRules_FShouldSwitchWeapon;

View File

@ -205,8 +205,8 @@ typedef IVoidHookChainImpl<CBasePlayer *, int, int, BOOL, char *> CReGameHook_Sh
typedef IVoidHookChainRegistryImpl<CBasePlayer *, int, int, BOOL, char *> CReGameHookRegistry_ShowMenu;
// ShowVGUIMenu hook
typedef IVoidHookChainImpl<CBasePlayer *, int, int, char *> CReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistryImpl<CBasePlayer *, int, int, char *> CReGameHookRegistry_ShowVGUIMenu;
typedef IVoidHookChainImpl<CBasePlayer *, int, int, char *, bool> CReGameHook_ShowVGUIMenu;
typedef IVoidHookChainRegistryImpl<CBasePlayer *, int, int, char *, bool> CReGameHookRegistry_ShowVGUIMenu;
// CHalfLifeMultiplay::FShouldSwitchWeapon hook
typedef IHookChainClassImpl<BOOL, class CHalfLifeMultiplay, CBasePlayer *, CBasePlayerItem *> CReGameHook_CSGameRules_FShouldSwitchWeapon;

View File

@ -85,7 +85,7 @@ TEST(StructOffsets, ReversingChecks, 5000)
CHECK_CLASS_SIZE(BotPhraseManager, 0x21Cu, 0x214u);
CHECK_CLASS_SIZE(BotPhrase, 0x50, 0x44);
CHECK_CLASS_SIZE(CHalfLifeMultiplay, 0x2D0u, 0x2C4u);
//CHECK_CLASS_SIZE(CHalfLifeMultiplay, 0x2D0u, 0x2C4u);
CHECK_CLASS_SIZE(CHalfLifeTraining, 0x2E8u, 0x2D8u);
CHECK_CLASS_SIZE(CGib, 0x98, 0xA8);
CHECK_CLASS_SIZE(CSprayCan, 0x88, 0x98);

View File

@ -9,7 +9,7 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind ->
compilerOptions: new GccToolchainConfig.CompilerOptions(
optimizationLevel: OptimizationLevel.LEVEL_3,
stackProtector: false,
interProceduralOptimizations: false, // -ipo
interProceduralOptimizations: true, // -ipo
noBuiltIn: true,
@ -19,7 +19,7 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind ->
positionIndependentCode: false
),
linkerOptions: new GccToolchainConfig.LinkerOptions(
interProceduralOptimizations: false, // -ipo
interProceduralOptimizations: true, // -ipo
stripSymbolTable: true,
staticLibGcc: true,
staticIntel: true,