2023-06-03 18:10:32 +02:00
|
|
|
|
//===== Copyright <20> 1996-2008, Valve Corporation, All rights reserved. ======//
|
|
|
|
|
//
|
|
|
|
|
// Purpose:
|
|
|
|
|
//
|
|
|
|
|
// $NoKeywords: $
|
|
|
|
|
//===========================================================================//
|
|
|
|
|
|
|
|
|
|
#include "clientstate.h"
|
|
|
|
|
#ifndef CL_SPLITSCREEN_H
|
|
|
|
|
#define CL_SPLITSCREEN_H
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#pragma once
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
class CNetChan;
|
|
|
|
|
class ISplitScreen
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
virtual bool Init() = 0;
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
virtual bool AddSplitScreenUser( int nSlot, int nPlayerIndex ) = 0;
|
|
|
|
|
virtual bool AddBaseUser( int nSlot, int nPlayerIndex ) = 0;
|
|
|
|
|
virtual bool RemoveSplitScreenUser( int nSlot, int nPlayerIndex ) = 0;
|
|
|
|
|
virtual int GetActiveSplitScreenPlayerSlot() = 0;
|
|
|
|
|
virtual int SetActiveSplitScreenPlayerSlot( int nSlot ) = 0;
|
|
|
|
|
|
|
|
|
|
virtual bool IsValidSplitScreenSlot( int nSlot ) = 0;
|
|
|
|
|
virtual int FirstValidSplitScreenSlot() = 0; // -1 == invalid
|
|
|
|
|
virtual int NextValidSplitScreenSlot( int nPreviousSlot ) = 0; // -1 == invalid
|
|
|
|
|
|
|
|
|
|
virtual int GetNumSplitScreenPlayers() = 0;
|
|
|
|
|
virtual int GetSplitScreenPlayerEntity( int nSlot ) = 0;
|
|
|
|
|
virtual CNetChan *GetSplitScreenPlayerNetChan( int nSlot ) = 0;
|
|
|
|
|
|
|
|
|
|
virtual bool IsDisconnecting( int nSlot ) = 0;
|
|
|
|
|
virtual void SetDisconnecting( int nSlot, bool bState ) = 0;
|
|
|
|
|
|
|
|
|
|
virtual bool SetLocalPlayerIsResolvable( char const *pchContext, int nLine, bool bResolvable ) = 0;
|
|
|
|
|
virtual bool IsLocalPlayerResolvable() = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CSplitScreen : public ISplitScreen
|
|
|
|
|
{
|
|
|
|
|
// Commented as 'CClientState' uses virtual functions,
|
|
|
|
|
// which are pure in the SDK since its implemented in
|
|
|
|
|
// shipped engine code, but this should be the struct:
|
|
|
|
|
//public:
|
|
|
|
|
// struct SplitPlayer_t
|
|
|
|
|
// {
|
|
|
|
|
// bool m_bActive;
|
|
|
|
|
// CClientState m_Client;
|
|
|
|
|
// };
|
|
|
|
|
//
|
|
|
|
|
// SplitPlayer_t m_SplitScreenPlayers[MAX_SPLITSCREEN_CLIENTS];
|
|
|
|
|
// int m_nActiveSplitScreenUserCount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifndef DEDICATED
|
|
|
|
|
extern CSplitScreen* g_pSplitScreenMgr;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
class CSetActiveSplitScreenPlayerGuard
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CSetActiveSplitScreenPlayerGuard( char const *pchContext, int nLine, int slot );
|
|
|
|
|
~CSetActiveSplitScreenPlayerGuard();
|
|
|
|
|
private:
|
|
|
|
|
char const *m_pchContext;
|
|
|
|
|
int m_nLine;
|
|
|
|
|
int m_nSaveSlot;
|
|
|
|
|
bool m_bResolvable;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// If this is defined, all of the scopeguard objects are NULL'd out to reduce overhead
|
|
|
|
|
#ifdef DEDICATED
|
|
|
|
|
#define SPLIT_SCREEN_STUBS
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined( CSTRIKE15 ) // && !defined( _GAMECONSOLE ) // Split screen removed from console.
|
|
|
|
|
#define SPLIT_SCREEN_STUBS
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined( SPLIT_SCREEN_STUBS )
|
|
|
|
|
#define IS_LOCAL_PLAYER_RESOLVABLE true
|
|
|
|
|
#define SET_LOCAL_PLAYER_RESOLVABLE( a, b, c ) true
|
|
|
|
|
#define SET_ACTIVE_SPLIT_SCREEN_PLAYER_SLOT( x )
|
|
|
|
|
|
|
|
|
|
#define ACTIVE_SPLITSCREEN_PLAYER_GUARD( slot )
|
|
|
|
|
#define FORCE_DEFAULT_SPLITSCREEN_PLAYER_GUARD
|
|
|
|
|
|
|
|
|
|
#define FOR_EACH_VALID_SPLITSCREEN_PLAYER( iteratorName ) for ( int iteratorName = 0; iteratorName == 0; ++iteratorName )
|
|
|
|
|
#define FOR_EACH_SPLITSCREEN_PLAYER FOR_EACH_VALID_SPLITSCREEN_PLAYER
|
|
|
|
|
|
|
|
|
|
#define ASSERT_LOCAL_PLAYER_RESOLVABLE()
|
|
|
|
|
#define GET_ACTIVE_SPLITSCREEN_SLOT() ( 0 )
|
|
|
|
|
#define GET_NUM_SPLIT_SCREEN_PLAYERS() 1
|
|
|
|
|
#define IS_VALID_SPLIT_SCREEN_SLOT( i ) ( ( i ) == 0 )
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
#define IS_LOCAL_PLAYER_RESOLVABLE ( g_pSplitScreenMgr->IsLocalPlayerResolvable() )
|
|
|
|
|
|
|
|
|
|
#define SET_LOCAL_PLAYER_RESOLVABLE( a, b, c ) ( g_pSplitScreenMgr->SetLocalPlayerIsResolvable( a, b, c ) )
|
|
|
|
|
|
|
|
|
|
#define ACTIVE_SPLITSCREEN_PLAYER_GUARD( slot ) CSetActiveSplitScreenPlayerGuard g_SSGuard( __FILE__, __LINE__, slot );
|
|
|
|
|
#define FORCE_DEFAULT_SPLITSCREEN_PLAYER_GUARD CSetActiveSplitScreenPlayerGuard g_SSGuard( __FILE__, __LINE__, 0 );
|
|
|
|
|
|
|
|
|
|
#define FOR_EACH_VALID_SPLITSCREEN_PLAYER( iteratorName ) \
|
|
|
|
|
for ( int iteratorName = g_pSplitScreenMgr->FirstValidSplitScreenSlot(); \
|
|
|
|
|
iteratorName != -1; \
|
|
|
|
|
iteratorName = g_pSplitScreenMgr->NextValidSplitScreenSlot( iteratorName ) )
|
|
|
|
|
#define FOR_EACH_SPLITSCREEN_PLAYER( iteratorName ) for ( int iteratorName = 0; iteratorName < MAX_SPLITSCREEN_CLIENTS; ++iteratorName )
|
|
|
|
|
|
|
|
|
|
#define ASSERT_LOCAL_PLAYER_RESOLVABLE() Assert( g_pSplitScreenMgr->IsLocalPlayerResolvable() );
|
|
|
|
|
#define GET_ACTIVE_SPLITSCREEN_SLOT() g_pSplitScreenMgr->GetActiveSplitScreenPlayerSlot()
|
|
|
|
|
#define SET_ACTIVE_SPLIT_SCREEN_PLAYER_SLOT( x ) g_pSplitScreenMgr->SetActiveSplitScreenPlayerSlot( x )
|
|
|
|
|
#define GET_NUM_SPLIT_SCREEN_PLAYERS() ( g_pSplitScreenMgr->GetNumSplitScreenPlayers() )
|
|
|
|
|
#define IS_VALID_SPLIT_SCREEN_SLOT( i ) ( g_pSplitScreenMgr->IsValidSplitScreenSlot( i ) )
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-06-03 21:20:23 +02:00
|
|
|
|
inline CClientState* GetBaseLocalClient()
|
|
|
|
|
{
|
|
|
|
|
return g_pClientState;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 18:10:32 +02:00
|
|
|
|
class VSplitScreen : public IDetour
|
|
|
|
|
{
|
|
|
|
|
virtual void GetAdr(void) const
|
|
|
|
|
{
|
|
|
|
|
LogVarAdr("g_SplitScreenMgr", reinterpret_cast<uintptr_t>(g_pSplitScreenMgr));
|
|
|
|
|
}
|
|
|
|
|
virtual void GetFun(void) const { }
|
|
|
|
|
virtual void GetVar(void) const
|
|
|
|
|
{
|
|
|
|
|
const char* pszPattern;
|
|
|
|
|
const char* pszInstruction;
|
|
|
|
|
|
|
|
|
|
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
|
|
|
|
pszPattern = "83 FA FF 75 22 48 8D 05 ?? ?? ?? ??";
|
|
|
|
|
pszInstruction = "4C 8D";
|
|
|
|
|
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
|
|
|
|
pszPattern = "40 53 48 83 EC 20 48 8D 1D ?? ?? ?? ?? 83 FA FF 75 12 48 8B 05 ?? ?? ?? ?? 48 8B CB FF 50 28 48 63 C8 EB 03 48 63 CA 48 69 C1 ?? ?? ?? ?? 66 C7 84 18 ?? ?? ?? ?? ?? ??";
|
|
|
|
|
pszInstruction = "48 8D";
|
|
|
|
|
#endif
|
|
|
|
|
g_pSplitScreenMgr = g_GameDll.FindPatternSIMD(pszPattern).FindPatternSelf(pszInstruction).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CSplitScreen*>();
|
|
|
|
|
}
|
|
|
|
|
virtual void GetCon(void) const { }
|
2023-11-26 13:21:20 +01:00
|
|
|
|
virtual void Detour(const bool bAttach) const { };
|
2023-06-03 18:10:32 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // CL_SPLITSCREEN_H
|