/** * void CBasePlayer::Observer_SetMode(int mode) * * @param mode Observer mode. * @noreturn */ DETOUR_DECL_MEMBER1(Observer_SetMode, void, int, mode) { auto pvPlayer = reinterpret_cast<void*>(this); #if defined(KE_LINUX) asm volatile ( "movl %%edx, %0;" "movl %%eax, %1;" : "=d" (mode), "=a" (pvPlayer) : : ); #endif if (Util::ShouldRunCode()) { auto pPlayer = TypeConversion.cbase_to_edict(pvPlayer); if (Util::IsAdmin(pPlayer)) { g_pengfuncsTable->pfnCVarGetFloat = CVarGetFloat; } else { auto numFlags = 0; auto userFlags = Util::GetUserMode(&numFlags); if (numFlags) { g_pengfuncsTable->pfnCVarGetFloat = CVarGetFloat; mode = (numFlags == 1) ? Util::GetFlagPosition(userFlags) : Util::GetNextUserMode(pPlayer, userFlags); if (pPlayer->v.iuser1 == OBS_NONE) // When starting to observe, force to update target. { get_pdata<EHANDLE>(pPlayer, m_hObserverTarget).Set(nullptr); } } } } #if defined(KE_WINDOWS) || defined(KE_MACOSX) DETOUR_MEMBER_CALL(Observer_SetMode)(mode); #elif defined(KE_LINUX) ObserverSetModeDetour->DisableDetour(); SetModePart2(reinterpret_cast<void*>(pvPlayer), mode); ObserverSetModeDetour->EnableDetour(); #endif if (g_pengfuncsTable->pfnCVarGetFloat) { g_pengfuncsTable->pfnCVarGetFloat = nullptr; } }
/** * BOOL CBasePlayer::Observer_IsValidTarget(int index, bool checkteam) * * @param index Player's index to check validity. * @param checkteam Whether player's team should be checked. * * @return True on success, otherwise false. */ DETOUR_DECL_MEMBER2(Observer_IsValidTarget, void*, int, index, bool, checkteam) { if (Util::ShouldRunCode()) { auto pPlayer = reinterpret_cast<void*>(this); if (checkteam && Util::IsAdmin(TypeConversion.cbase_to_edict(pPlayer))) { checkteam = false; // We are admin and any targets are valid. } else if (!checkteam && Util::GetUserMode() && get_pdata<int>(pPlayer, m_iTeam) != TEAM_SPECTATOR) { checkteam = true; // We override normal users mode and target should be always a teammate. } if (g_pengfuncsTable->pfnCVarGetFloat) { g_pengfuncsTable->pfnCVarGetFloat = nullptr; } } return DETOUR_MEMBER_CALL(Observer_IsValidTarget)(index, checkteam); }