Skip to content

Commit

Permalink
feat: player physics simulate list shuffle (#318)
Browse files Browse the repository at this point in the history
* pickrandom by trigger

* fix decl

* fucking auto completion

* 😭

* :octocat: switch to VPhysics method

* Update signatures for 2024-10-28 CS2 update

* 👏 finished physics linkedlist shuffle

* Delete .clang-format

* revert something

* missing init

* 😢

* feat: default config

---------

Co-authored-by: Vauff <[email protected]>
  • Loading branch information
Kxnrl and Vauff authored Nov 16, 2024
1 parent 41f28b6 commit 223a007
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 8 deletions.
1 change: 1 addition & 0 deletions cfg/cs2fixes/cs2fixes.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ cs2f_disable_subtick_move 0 // Whether to disable subtick movement
cs2f_disable_subtick_shooting 0 // Whether to disable subtick shooting, experimental (WARNING: add "log_flags Shooting +DoNotEcho" to your cfg to prevent console spam on every shot fired)
cs2f_full_alltalk 0 // Whether to enforce sv_full_alltalk 1
cs2f_drop_map_weapons 0 // Whether to force drop map-spawned weapons on death
cs2f_shuffle_player_physics_sim 0 // Whether to enable shuffle player list in physics simulate
cs2f_prevent_using_players 0 // Whether to prevent +use from hitting players (0=can use players, 1=cannot use players)
cs2f_map_steamids_enable 0 // Whether to make Steam ID's available to maps
Expand Down
7 changes: 7 additions & 0 deletions gamedata/cs2fixes.games.txt
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,13 @@
"windows" "128"
"linux" "129"
}

// server.dll -> xref 'sv_phys_stop_at_collision' first __fastcall
"CVPhys2World::GetTouchingList"
{
"windows" "23"
"linux" "24"
}
}
"Patches"
{
Expand Down
1 change: 1 addition & 0 deletions src/addresses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ bool addresses::Initialize(CGameConfig *g_GameConfig)
modules::schemasystem = new CModule(ROOTBIN, "schemasystem");
modules::vscript = new CModule(ROOTBIN, "vscript");
modules::networksystem = new CModule(ROOTBIN, "networksystem");
modules::vphysics2 = new CModule(ROOTBIN, "vphysics2");
modules::client = nullptr;

if (!CommandLine()->HasParm("-dedicated"))
Expand Down
5 changes: 3 additions & 2 deletions src/addresses.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ namespace modules
inline CModule *vscript;
inline CModule *client;
inline CModule* networksystem;
inline CModule* vphysics2;
#ifdef _WIN32
inline CModule *hammer;
#endif
}
} // namespace modules

class CEntityInstance;
class CEntityIdentity;
Expand Down Expand Up @@ -91,4 +92,4 @@ namespace addresses
inline void(FASTCALL *CTakeDamageInfo_Constructor)(CTakeDamageInfo *pThis, CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pAbility,
const Vector *vecDamageForce, const Vector *vecDamagePosition, float flDamage, int bitsDamageType, int iCustomDamage, void *a10);
inline void(FASTCALL *CNetworkStringTable_DeleteAllStrings)(INetworkStringTable *pThis);
}
}
92 changes: 87 additions & 5 deletions src/cs2fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, bool, CTakeDamageInfoContainer
SH_DECL_MANUALHOOK1_void(CheckMovingGround, 0, 0, 0, double);
SH_DECL_HOOK2(IGameEventManager2, LoadEventsFromFile, SH_NOATTRIB, 0, int, const char *, bool);
SH_DECL_MANUALHOOK1_void(GoToIntermission, 0, 0, 0, bool);
SH_DECL_MANUALHOOK2_void(PhysicsTouchShuffle, 0, 0, 0, CUtlVector<TouchLinked_t>*, bool);

CS2Fixes g_CS2Fixes;

Expand All @@ -139,6 +140,7 @@ int g_iOnTakeDamageAliveId = -1;
int g_iCheckMovingGroundId = -1;
int g_iLoadEventsFromFileId = -1;
int g_iGoToIntermissionId = -1;
int g_iPhysicsTouchShuffle = -1;

CGameEntitySystem *GameEntitySystem()
{
Expand Down Expand Up @@ -266,6 +268,17 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
SH_MANUALHOOK_RECONFIGURE(CheckMovingGround, offset, 0, 0);
g_iCheckMovingGroundId = SH_ADD_MANUALDVPHOOK(CheckMovingGround, pCCSPlayer_MovementServicesVTable, SH_MEMBER(this, &CS2Fixes::Hook_CheckMovingGround), false);

auto pCVPhys2WorldVTable = modules::vphysics2->FindVirtualTable("CVPhys2World");

offset = g_GameConfig->GetOffset("CVPhys2World::GetTouchingList");
if (offset == -1)
{
snprintf(error, maxlen, "Failed to find CVPhys2World::GetTouchingList\n");
bRequiredInitLoaded = false;
}
SH_MANUALHOOK_RECONFIGURE(PhysicsTouchShuffle, offset, 0, 0);
g_iPhysicsTouchShuffle = SH_ADD_MANUALDVPHOOK(PhysicsTouchShuffle, pCVPhys2WorldVTable, SH_MEMBER(this, &CS2Fixes::Hook_PhysicsTouchShuffle), true);

auto pCGameEventManagerVTable = (IGameEventManager2*)modules::server->FindVirtualTable("CGameEventManager");

g_iLoadEventsFromFileId = SH_ADD_DVPHOOK(IGameEventManager2, LoadEventsFromFile, pCGameEventManagerVTable, SH_MEMBER(this, &CS2Fixes::Hook_LoadEventsFromFile), false);
Expand Down Expand Up @@ -368,6 +381,7 @@ bool CS2Fixes::Unload(char *error, size_t maxlen)
SH_REMOVE_HOOK_ID(g_iCreateWorkshopMapGroupId);
SH_REMOVE_HOOK_ID(g_iOnTakeDamageAliveId);
SH_REMOVE_HOOK_ID(g_iCheckMovingGroundId);
SH_REMOVE_HOOK_ID(g_iPhysicsTouchShuffle);

if (g_iGoToIntermissionId != -1)
SH_REMOVE_HOOK_ID(g_iGoToIntermissionId);
Expand Down Expand Up @@ -547,7 +561,7 @@ void CS2Fixes::Hook_GameServerSteamAPIActivated()
g_http = g_steamAPI.SteamHTTP();

g_playerManager->OnSteamAPIActivated();

if (g_bVoteManagerEnable && !g_pMapVoteSystem->IsMapListLoaded())
g_pMapVoteSystem->LoadMapList();

Expand Down Expand Up @@ -622,7 +636,7 @@ void CS2Fixes::Hook_PostEvent(CSplitScreenSlot nSlot, bool bLocalOnly, int nClie
if (g_bEnableNoShake)
*(uint64 *)clients &= ~g_playerManager->GetNoShakeMask();
}

}

void CS2Fixes::AllPluginsLoaded()
Expand Down Expand Up @@ -843,7 +857,6 @@ void CS2Fixes::Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount
for (int j = 0; j < gpGlobals->maxClients; j++)
{
CCSPlayerController* pController = CCSPlayerController::FromSlot(j);

// Always transmit to themselves
if (!pController || pController->m_bIsHLTV || j == iPlayerSlot)
continue;
Expand All @@ -856,7 +869,6 @@ void CS2Fixes::Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount
{
pInfo->m_pTransmitEntity->Clear(pFlashLight->entindex());
}

// Always transmit other players if spectating
if (!g_bEnableHide || pSelfController->GetPawnState() == STATE_OBSERVER_MODE)
continue;
Expand Down Expand Up @@ -929,6 +941,76 @@ bool CS2Fixes::Hook_OnTakeDamage_Alive(CTakeDamageInfoContainer *pInfoContainer)
RETURN_META_VALUE(MRES_IGNORED, true);
}

bool g_bFixPhysicsPlayerShuffle = false;
FAKE_BOOL_CVAR(cs2f_shuffle_player_physics_sim, "Whether to enable shuffle player list in physics simulate", g_bFixPhysicsPlayerShuffle, false, false);

struct TouchLinked_t
{
uint32_t TouchFlags;

private:
uint8_t padding_0[20];

public:
CBaseHandle SourceHandle;
CBaseHandle TargetHandle;

private:
uint8_t padding_1[208];

public:
[[nodiscard]] bool IsUnTouching() const
{
return !!(TouchFlags & 0x10);
}

[[nodiscard]] bool IsTouching() const
{
return (!!(TouchFlags & 4)) || (!!(TouchFlags & 8));
}
};
static_assert(sizeof(TouchLinked_t) == 240, "Touch_t size mismatch");
void CS2Fixes::Hook_PhysicsTouchShuffle(CUtlVector<TouchLinked_t>* pList, bool unknown)
{
if (!g_bFixPhysicsPlayerShuffle || g_SHPtr->GetStatus() == MRES_SUPERCEDE || pList->Count() <= 1)
return;

// [Kxnrl]
// seems it sorted by flags?

std::srand(gpGlobals->tickcount);

// Fisher-Yates shuffle

std::vector<TouchLinked_t> touchingLinks;
std::vector<TouchLinked_t> unTouchLinks;

FOR_EACH_VEC(*pList, i)
{
const auto& link = pList->Element(i);
if (link.IsUnTouching())
unTouchLinks.push_back(link);
else
touchingLinks.push_back(link);
}

if (touchingLinks.size() <= 1)
return;

for (size_t i = touchingLinks.size() - 1; i > 0; --i)
{
const auto j = std::rand() % (i + 1);
std::swap(touchingLinks[i], touchingLinks[j]);
}

pList->Purge();

for (const auto link : touchingLinks)
pList->AddToTail(link);
for (const auto link : unTouchLinks)
pList->AddToTail(link);
}

void CS2Fixes::Hook_CheckMovingGround(double frametime)
{
CCSPlayer_MovementServices *pMove = META_IFACEPTR(CCSPlayer_MovementServices);
Expand Down Expand Up @@ -1046,4 +1128,4 @@ const char *CS2Fixes::GetName()
const char *CS2Fixes::GetURL()
{
return "https://github.com/Source2ZE/CS2Fixes";
}
}
2 changes: 2 additions & 0 deletions src/cs2fixes.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
struct CTakeDamageInfoContainer;
class CCSPlayer_MovementServices;
class CServerSideClient;
struct TouchLinked_t;

class CS2Fixes : public ISmmPlugin, public IMetamodListener
{
Expand Down Expand Up @@ -67,6 +68,7 @@ class CS2Fixes : public ISmmPlugin, public IMetamodListener
void Hook_CreateWorkshopMapGroup(const char* name, const CUtlStringList& mapList);
void Hook_GoToIntermission(bool bAbortedMatch);
bool Hook_OnTakeDamage_Alive(CTakeDamageInfoContainer *pInfoContainer);
void Hook_PhysicsTouchShuffle(CUtlVector<TouchLinked_t>* pList, bool unknown);
#ifdef PLATFORM_WINDOWS
Vector* Hook_GetEyePosition(Vector*);
QAngle* Hook_GetEyeAngles(QAngle*);
Expand Down
2 changes: 1 addition & 1 deletion src/detours.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,4 +696,4 @@ bool InitDetours(CGameConfig *gameConfig)
void FlushAllDetours()
{
g_vecDetours.Purge();
}
}

0 comments on commit 223a007

Please sign in to comment.