Skip to content

Commit 1a41f4e

Browse files
authored
Merge branch 'master' into radar-jpg-update
2 parents 6b82b56 + a4b4318 commit 1a41f4e

33 files changed

+466
-113
lines changed

Client/game_sa/CGameSA.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,34 @@ void CGameSA::SetRoadSignsTextEnabled(bool isEnabled)
848848
m_isRoadSignsTextEnabled = isEnabled;
849849
}
850850

851+
void CGameSA::SetIgnoreFireStateEnabled(bool isEnabled)
852+
{
853+
if (isEnabled == m_isIgnoreFireStateEnabled)
854+
return;
855+
856+
if (isEnabled)
857+
{
858+
MemSet((void*)0x6511B9, 0x90, 10); // CCarEnterExit::IsVehicleStealable
859+
MemSet((void*)0x643A95, 0x90, 14); // CTaskComplexEnterCar::CreateFirstSubTask
860+
MemSet((void*)0x6900B5, 0x90, 14); // CTaskComplexCopInCar::ControlSubTask
861+
MemSet((void*)0x64F3DB, 0x90, 14); // CCarEnterExit::IsPlayerToQuitCarEnter
862+
863+
MemSet((void*)0x685A7F, 0x90, 14); // CTaskSimplePlayerOnFoot::ProcessPlayerWeapon
864+
}
865+
else
866+
{
867+
// Restore original bytes
868+
MemCpy((void*)0x6511B9, "\x88\x86\x90\x04\x00\x00\x85\xC0\x75\x3E", 10);
869+
MemCpy((void*)0x643A95, "\x8B\x88\x90\x04\x00\x00\x85\xC9\x0F\x85\x99\x01\x00\x00", 14);
870+
MemCpy((void*)0x6900B5, "\x8B\x81\x90\x04\x00\x00\x85\xC0\x0F\x85\x1A\x01\x00\x00", 14);
871+
MemCpy((void*)0x64F3DB, "\x8B\x85\x90\x04\x00\x00\x85\xC0\x0F\x85\x1B\x01\x00\x00", 14);
872+
873+
MemCpy((void*)0x685A7F, "\x8B\x86\x30\x07\x00\x00\x85\xC0\x0F\x85\x1D\x01\x00\x00", 14);
874+
}
875+
876+
m_isIgnoreFireStateEnabled = isEnabled;
877+
}
878+
851879
bool CGameSA::PerformChecks()
852880
{
853881
std::map<std::string, SCheatSA*>::iterator it;

Client/game_sa/CGameSA.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ class CGameSA : public CGame
249249
bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; }
250250
void SetTunnelWeatherBlendEnabled(bool isEnabled) override;
251251

252+
bool IsIgnoreFireStateEnabled() const noexcept override { return m_isIgnoreFireStateEnabled; }
253+
void SetIgnoreFireStateEnabled(bool isEnabled) override;
252254

253255
unsigned long GetMinuteDuration();
254256
void SetMinuteDuration(unsigned long ulTime);
@@ -378,6 +380,7 @@ class CGameSA : public CGame
378380
bool m_isRoadSignsTextEnabled{true};
379381
bool m_isBuildingsRemoved{false};
380382
bool m_isExtendedWaterCannonsEnabled{false};
383+
bool m_isIgnoreFireStateEnabled{false};
381384

382385
static unsigned int& ClumpOffset;
383386

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
135135
m_Glitches[GLITCH_BADDRIVEBYHITBOX] = false;
136136
m_Glitches[GLITCH_QUICKSTAND] = false;
137137
m_Glitches[GLITCH_KICKOUTOFVEHICLE_ONMODELREPLACE] = false;
138+
138139
g_pMultiplayer->DisableBadDrivebyHitboxes(true);
139140

140141
// Remove Night & Thermal vision view (if enabled).
@@ -6025,6 +6026,9 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is
60256026
case WorldSpecialProperty::TUNNELWEATHERBLEND:
60266027
g_pGame->SetTunnelWeatherBlendEnabled(isEnabled);
60276028
return true;
6029+
case WorldSpecialProperty::IGNOREFIRESTATE:
6030+
g_pGame->SetIgnoreFireStateEnabled(isEnabled);
6031+
return true;
60286032
}
60296033
return false;
60306034
}
@@ -6062,6 +6066,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property)
60626066
return g_pGame->IsRoadSignsTextEnabled();
60636067
case WorldSpecialProperty::TUNNELWEATHERBLEND:
60646068
return g_pGame->IsTunnelWeatherBlendEnabled();
6069+
case WorldSpecialProperty::IGNOREFIRESTATE:
6070+
return g_pGame->IsIgnoreFireStateEnabled();
60656071
}
60666072
return false;
60676073
}
@@ -6475,7 +6481,7 @@ void CClientGame::OutputServerInfo()
64756481
{
64766482
SString strEnabledGlitches;
64776483
const char* szGlitchNames[] = {"Quick reload", "Fast fire", "Fast move", "Crouch bug", "Close damage", "Hit anim", "Fast sprint",
6478-
"Bad driveby hitboxes", "Quick stand"};
6484+
"Bad driveby hitboxes", "Quick stand", "Kickout of vehicle on model replace"};
64796485
for (uint i = 0; i < NUM_GLITCHES; i++)
64806486
{
64816487
if (IsGlitchEnabled(i))

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,10 @@ void CPacketHandler::Packet_ServerDisconnected(NetBitStreamInterface& bitStream)
572572
strReason = _("Disconnected: Serial verification failed");
573573
strErrorCode = _E("CD44");
574574
break;
575+
case ePlayerDisconnectType::SERIAL_DUPLICATE:
576+
strReason = _("Disconnected: Serial already in use");
577+
strErrorCode = _E("CD50");
578+
break;
575579
case ePlayerDisconnectType::CONNECTION_DESYNC:
576580
strReason = _("Disconnected: Connection desync %s");
577581
strErrorCode = _E("CD45");
@@ -2393,6 +2397,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
23932397
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext);
23942398
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons);
23952399
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend);
2400+
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState);
23962401

23972402
float fJetpackMaxHeight = 100;
23982403
if (!bitStream.Read(fJetpackMaxHeight))

Client/mods/deathmatch/logic/CPacketHandler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class CPacketHandler
4242
BAN,
4343
KICK,
4444
CUSTOM,
45-
SHUTDOWN
45+
SHUTDOWN,
46+
SERIAL_DUPLICATE
4647
};
4748

4849
struct SEntityDependantStuff

Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,8 @@ void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream)
619619
bitStream.Read(g_TickRateSettings.iObjectSync);
620620
bitStream.Read(g_TickRateSettings.iKeySyncRotation);
621621
bitStream.Read(g_TickRateSettings.iKeySyncAnalogMove);
622+
bitStream.Read(g_TickRateSettings.iPedSyncerDistance);
623+
bitStream.Read(g_TickRateSettings.iUnoccupiedVehicleSyncerDistance);
622624
}
623625

624626
void CWorldRPCs::SetMoonSize(NetBitStreamInterface& bitStream)

Client/multiplayer_sa/CMultiplayerSA.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ void CMultiplayerSA::InitHooks()
15741574
MemSet((void*)0x6C4453, 0x90, 0x68);
15751575

15761576
InitHooks_CrashFixHacks();
1577+
InitHooks_DeviceSelection();
15771578

15781579
// Init our 1.3 hooks.
15791580
Init_13();
@@ -1861,6 +1862,7 @@ void CMultiplayerSA::DisableCloseRangeDamage(bool bDisabled)
18611862
MemPut<BYTE>(0x73BA00, 0x86);
18621863
}
18631864
}
1865+
18641866
bool CMultiplayerSA::GetInteriorSoundsEnabled()
18651867
{
18661868
return bInteriorSoundsEnabled;

Client/multiplayer_sa/CMultiplayerSA.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class CMultiplayerSA : public CMultiplayer
8080
void InitHooks_ProjectileCollisionFix();
8181
void InitHooks_ObjectStreamerOptimization();
8282
void InitHooks_Postprocess();
83+
void InitHooks_DeviceSelection();
8384
CRemoteDataStorage* CreateRemoteDataStorage();
8485
void DestroyRemoteDataStorage(CRemoteDataStorage* pData);
8586
void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData);
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*****************************************************************************
2+
*
3+
* PROJECT: Multi Theft Auto v1.0
4+
* LICENSE: See LICENSE in the top level directory
5+
* FILE: multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp
6+
*
7+
* Multi Theft Auto is available from http://www.multitheftauto.com/
8+
*
9+
*****************************************************************************/
10+
11+
#include "StdInc.h"
12+
#define FUNC_rwDeviceSystemRequest 0x7F2AB0
13+
#define FUNC_DialogFunc 0x745E50
14+
#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30
15+
#define CLASS_RwGlobals 0xC97B24
16+
#define CLASS_IDirect3D9 0xC97C20
17+
#define NUM_DialogFuncStackPushAddress 0x746239
18+
19+
// This is copied from SilentPatch:
20+
// https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp
21+
std::unordered_map<std::string, std::string> GetFriendlyMonitorNamesForDevicePaths()
22+
{
23+
std::unordered_map<std::string, std::string> monitorNames;
24+
25+
HMODULE user32Lib = LoadLibrary(TEXT("user32"));
26+
if (!user32Lib)
27+
return monitorNames;
28+
29+
auto* getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes");
30+
auto* queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig");
31+
auto* displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo");
32+
if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo)
33+
{
34+
FreeLibrary(user32Lib);
35+
return monitorNames;
36+
}
37+
38+
UINT32 pathCount, modeCount;
39+
std::unique_ptr<DISPLAYCONFIG_PATH_INFO[]> paths;
40+
std::unique_ptr<DISPLAYCONFIG_MODE_INFO[]> modes;
41+
42+
LONG result = ERROR_SUCCESS;
43+
do
44+
{
45+
result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount);
46+
if (result != ERROR_SUCCESS)
47+
{
48+
break;
49+
}
50+
paths = std::make_unique<DISPLAYCONFIG_PATH_INFO[]>(pathCount);
51+
modes = std::make_unique<DISPLAYCONFIG_MODE_INFO[]>(modeCount);
52+
result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr);
53+
} while (result == ERROR_INSUFFICIENT_BUFFER);
54+
55+
if (result != ERROR_SUCCESS)
56+
{
57+
FreeLibrary(user32Lib);
58+
return monitorNames;
59+
}
60+
61+
for (size_t i = 0; i < pathCount; i++)
62+
{
63+
DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
64+
targetName.header.adapterId = paths[i].targetInfo.adapterId;
65+
targetName.header.id = paths[i].targetInfo.id;
66+
targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
67+
targetName.header.size = sizeof(targetName);
68+
const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header);
69+
70+
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {};
71+
sourceName.header.adapterId = paths[i].sourceInfo.adapterId;
72+
sourceName.header.id = paths[i].sourceInfo.id;
73+
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
74+
sourceName.header.size = sizeof(sourceName);
75+
const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header);
76+
if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0')
77+
{
78+
char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)];
79+
char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)];
80+
WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast<int>(std::size(gdiDeviceName)), nullptr, nullptr);
81+
WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName,
82+
static_cast<int>(std::size(monitorFriendlyDeviceName)), nullptr, nullptr);
83+
84+
monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName);
85+
}
86+
}
87+
88+
FreeLibrary(user32Lib);
89+
return monitorNames;
90+
}
91+
92+
struct RwSubSystemInfo
93+
{
94+
char name[80];
95+
};
96+
97+
using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn);
98+
static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex)
99+
{
100+
auto* rwGlobals = *(RwGlobals**)CLASS_RwGlobals;
101+
auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest);
102+
if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex))
103+
return nullptr;
104+
105+
auto* pDxDevice = *(IDirect3D9**)CLASS_IDirect3D9;
106+
if (!pDxDevice)
107+
return subSystemInfo;
108+
109+
D3DADAPTER_IDENTIFIER9 identifier;
110+
if (FAILED(pDxDevice->GetAdapterIdentifier(subSystemIndex, 0, &identifier)))
111+
return subSystemInfo;
112+
113+
static const auto friendlyNames = GetFriendlyMonitorNamesForDevicePaths();
114+
115+
// If we can't find the friendly name, either because it doesn't exist or we're on an ancient Windows, fall back to the device name
116+
auto it = friendlyNames.find(identifier.DeviceName);
117+
if (it != friendlyNames.end())
118+
{
119+
strncpy_s(subSystemInfo->name, it->second.c_str(), _TRUNCATE);
120+
}
121+
else
122+
{
123+
strncpy_s(subSystemInfo->name, identifier.Description, _TRUNCATE);
124+
}
125+
126+
return subSystemInfo;
127+
}
128+
129+
INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
130+
{
131+
auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc;
132+
if (msg != WM_INITDIALOG)
133+
return orgDialogFunc(window, msg, wParam, lParam);
134+
135+
orgDialogFunc(window, msg, wParam, lParam);
136+
137+
// Set Icon
138+
HMODULE hGameModule = GetModuleHandle(nullptr);
139+
SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(LoadIcon(hGameModule, MAKEINTRESOURCE(100))));
140+
141+
// Make the dialog visible in the task bar
142+
// https://stackoverflow.com/a/1462811
143+
SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW);
144+
ShowWindow(window, SW_HIDE);
145+
ShowWindow(window, SW_SHOW);
146+
return FALSE;
147+
}
148+
149+
void CMultiplayerSA::InitHooks_DeviceSelection()
150+
{
151+
// 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(),
152+
// we're replacing it with out own proxy function
153+
MemPut<DLGPROC>(NUM_DialogFuncStackPushAddress, (DLGPROC)&CustomDlgProc);
154+
HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6);
155+
}

Client/sdk/game/CGame.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ class __declspec(novtable) CGame
230230
virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0;
231231
virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0;
232232

233+
virtual bool IsIgnoreFireStateEnabled() const noexcept = 0;
234+
virtual void SetIgnoreFireStateEnabled(bool isEnabled) = 0;
235+
233236
virtual CWeapon* CreateWeapon() = 0;
234237
virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0;
235238

0 commit comments

Comments
 (0)