Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions Client/game_sa/CPedSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ void CPedSA::ClearWeapons()

void CPedSA::RemoveWeaponModel(std::uint32_t model)
{
// void __thiscall CPed::RemoveWeaponModel(CPed *this, int modelID)
((void(__thiscall*)(CEntitySAInterface*, std::uint32_t))FUNC_RemoveWeaponModel)(m_pInterface, model);
if (auto* pedInterface = GetPedInterface())
pedInterface->RemoveWeaponModel(model);
}

void CPedSA::ClearWeapon(eWeaponType weaponType)
Expand Down Expand Up @@ -598,6 +598,73 @@ void CPedSA::SetInWaterFlags(bool inWater)
physicalInterface->bSubmergedInWater = inWater;
}

void __fastcall CPedSA::RemoveWeaponWhenEnteringVehicle(CPedSAInterface* pedInterface, void*, int jetpack)
{
if (!pedInterface)
return;

pedInterface->RemoveWeaponWhenEnteringVehicle(jetpack == 1);
}

void CPedSAInterface::RemoveWeaponWhenEnteringVehicle(bool jetpack)
{
// Bugfix #3659 (allow switch weapons while using jetpack - see PR #3573)
if (!jetpack)
{
if (auto* playerData = pPlayerData)
playerData->m_bInVehicleDontAllowWeaponChange = true;
}

if (savedWeapon != eWeaponType::WEAPONTYPE_UNIDENTIFIED)
return;

eWeaponSlot newSlot = WEAPONSLOT_MAX;

if (IsPlayer())
{
auto* playerInfo = pGame->GetPlayerInfo();
if (playerInfo && playerInfo->CanDoDriveBy())
{
const auto& smg = Weapons[WEAPONSLOT_TYPE_SMG];
const auto& shotgun = Weapons[WEAPONSLOT_TYPE_SHOTGUN];
const auto& pistol = Weapons[WEAPONSLOT_TYPE_HANDGUN];

const bool hasSMG = (smg.m_eWeaponType == eWeaponType::WEAPONTYPE_MICRO_UZI || smg.m_eWeaponType == eWeaponType::WEAPONTYPE_TEC9 ||
(jetpack && smg.m_eWeaponType == eWeaponType::WEAPONTYPE_MP5)) &&
smg.m_ammoTotal > 0;

const bool hasSawnoff = jetpack && shotgun.m_eWeaponType == eWeaponType::WEAPONTYPE_SAWNOFF_SHOTGUN && shotgun.m_ammoTotal > 0;

const bool hasPistol = jetpack && pistol.m_eWeaponType == eWeaponType::WEAPONTYPE_PISTOL && pistol.m_ammoTotal > 0;

if (hasSMG)
{
newSlot = WEAPONSLOT_TYPE_SMG;
}
else if (hasSawnoff) // Bugfix - the default here was WEAPONSLOT_TYPE_HANDGUN
{
newSlot = WEAPONSLOT_TYPE_SHOTGUN;
}
else if (hasPistol)
{
newSlot = WEAPONSLOT_TYPE_HANDGUN;
}
}
}

if (newSlot != WEAPONSLOT_MAX)
{
savedWeapon = Weapons[bCurrentWeaponSlot].m_eWeaponType;
SetCurrentWeapon(newSlot);
}
else if (!jetpack) // Bugfix #508 (weapons are invisible when wearing jetpack - see PR #3559)
{
auto weaponType = Weapons[bCurrentWeaponSlot].m_eWeaponType;
auto model = pGame->GetWeaponInfo(weaponType, eWeaponSkill::WEAPONSKILL_STD)->GetModel();
RemoveWeaponModel(model);
}
}

////////////////////////////////////////////////////////////////
//
// CPed_PreRenderAfterTest
Expand Down Expand Up @@ -686,4 +753,9 @@ void CPedSA::StaticSetHooks()
{
EZHookInstall(CPed_PreRenderAfterTest);
EZHookInstall(CPed_PreRenderAfterTest_Mid);

HookInstallCall(0x68025A, (DWORD)CPedSA::RemoveWeaponWhenEnteringVehicle); // CTaskSimpleJetPack::ProcessPed
HookInstallCall(0x64DB4D, (DWORD)CPedSA::RemoveWeaponWhenEnteringVehicle); // CTaskSimpleCarGetIn::ProcessPed
HookInstallCall(0x64BCA3, (DWORD)CPedSA::RemoveWeaponWhenEnteringVehicle); // CTaskSimpleCarSetPedInAsDriver::ProcessPed
HookInstallCall(0x64B876, (DWORD)CPedSA::RemoveWeaponWhenEnteringVehicle); // CTaskSimpleCarSetPedInAsPassenger::ProcessPed
}
14 changes: 12 additions & 2 deletions Client/game_sa/CPedSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ static_assert(sizeof(CPedStatSAInterface) == 0x34, "Invalid size for CPedStatSAI

class CPedSAInterface : public CPhysicalSAInterface
{
public:
bool IsPlayer() const noexcept { return bPedType < 2; }

void SetCurrentWeapon(eWeaponSlot slot) { ((void(__thiscall*)(CPedSAInterface*, eWeaponSlot))FUNC_SetCurrentWeapon)(this, slot); }

void RemoveWeaponModel(std::uint32_t model) { ((void(__thiscall*)(CEntitySAInterface*, std::uint32_t))FUNC_RemoveWeaponModel)(this, model); }

void RemoveWeaponWhenEnteringVehicle(bool jetpack);

public:
CPedSoundEntitySAInterface pedAudio; // CAEPedAudioEntity
CPedSoundSAInterface pedSound; // CAEPedSpeechAudioEntity
Expand Down Expand Up @@ -286,7 +295,7 @@ class CPedSAInterface : public CPhysicalSAInterface
CVehicleSAInterface* vehicleDeadInFrontOf;

int unk_594;
int bPedType; // ped type? 0 = player, >1 = ped?
int bPedType; // 0 = player, 1 = player2, > 1 = ped
CPedStatSAInterface* pPedStats;
CWeaponSAInterface Weapons[WEAPONSLOT_MAX];
eWeaponType savedWeapon;
Expand Down Expand Up @@ -477,7 +486,8 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA

void SetInWaterFlags(bool inWater) override;

static void StaticSetHooks();
static void __fastcall RemoveWeaponWhenEnteringVehicle(CPedSAInterface* pedInterface, void*, int jetpack);
static void StaticSetHooks();

private:
void ApplySwimAndSlopeRotations();
Expand Down
2 changes: 2 additions & 0 deletions Client/game_sa/CPlayerInfoSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,6 @@ class CPlayerInfoSA : public CPlayerInfo
float GetBikeFrontWheelDist() { return internalInterface->fBikeFrontWheelDist; }
std::uint8_t GetMaxHealth() const { return internalInterface->MaxHealth; }
std::uint8_t GetMaxArmor() const { return internalInterface->MaxArmour; }

bool CanDoDriveBy() const override { return internalInterface->bCanDoDriveBy; }
};
56 changes: 0 additions & 56 deletions Client/multiplayer_sa/CMultiplayerSA_1.3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ DWORD RETURN_CProjectile_FixTearGasCrash_Cont = 0x4C0409;
#define HOOKPOS_CProjectile_FixExplosionLocation 0x738A77
DWORD RETURN_CProjectile_FixExplosionLocation = 0x738A86;

#define HOOKPOS_CPed_RemoveWeaponWhenEnteringVehicle 0x5E6370
DWORD RETURN_CPed_RemoveWeaponWhenEnteringVehicle = 0x5E6379;

void HOOK_CVehicle_ProcessStuff_TestSirenTypeSingle();
void HOOK_CVehicle_ProcessStuff_PostPushSirenPositionSingle();
void HOOK_CVehicle_ProcessStuff_TestSirenTypeDual();
Expand All @@ -140,7 +137,6 @@ void HOOK_CVehicleModelInterface_SetClump();
void HOOK_CBoat_ApplyDamage();
void HOOK_CProjectile_FixTearGasCrash();
void HOOK_CProjectile_FixExplosionLocation();
void HOOK_CPed_RemoveWeaponWhenEnteringVehicle();
void* __cdecl HOOK_CMemoryMgr_MallocAlign(int size, int alignment, int nHint);
void __cdecl HOOK_CMemoryMgr_FreeAlign(void* ptr);

Expand Down Expand Up @@ -198,9 +194,6 @@ void CMultiplayerSA::InitHooks_13()

HookInstall(HOOKPOS_CProjectile_FixExplosionLocation, (DWORD)HOOK_CProjectile_FixExplosionLocation, 12);

// Fix invisible weapons during jetpack task
HookInstall(HOOKPOS_CPed_RemoveWeaponWhenEnteringVehicle, (DWORD)HOOK_CPed_RemoveWeaponWhenEnteringVehicle, 9);

InitHooks_ClothesSpeedUp();
EnableHooks_ClothesMemFix(true);
InitHooks_FixBadAnimId();
Expand Down Expand Up @@ -1872,52 +1865,3 @@ static void __declspec(naked) HOOK_CProjectile_FixExplosionLocation()
}
// clang-format on
}

DWORD CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom = 0;
static void __declspec(naked) HOOK_CPed_RemoveWeaponWhenEnteringVehicle()
{
MTA_VERIFY_HOOK_LOCAL_SIZE;

// clang-format off
__asm
{
push eax
mov eax, [esp+4]
mov CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom, eax
pop eax

push esi
mov esi, ecx
mov eax, [esi+480h]
}
// clang-format on

// Called from CTaskSimpleJetPack::ProcessPed
if (CPed_RemoveWeaponWhenEnteringVehicle_CalledFrom == 0x68025F)
{
// clang-format off
__asm
{
mov pPedUsingJetpack, esi
}
// clang-format on

if (AllowJetPack())
{
// clang-format off
__asm
{
pop esi
retn 4
}
// clang-format on
}
}

// clang-format off
__asm
{
jmp RETURN_CPed_RemoveWeaponWhenEnteringVehicle
}
// clang-format on
}
2 changes: 2 additions & 0 deletions Client/sdk/game/CPlayerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ class CPlayerInfo
virtual float GetBikeFrontWheelDist() = 0;
virtual std::uint8_t GetMaxHealth() const = 0;
virtual std::uint8_t GetMaxArmor() const = 0;

virtual bool CanDoDriveBy() const = 0;
};
1 change: 1 addition & 0 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connections per 30
m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true;
m_JetpackWeapons[WEAPONTYPE_TEC9] = true;
m_JetpackWeapons[WEAPONTYPE_PISTOL] = true;
m_JetpackWeapons[WEAPONTYPE_SAWNOFF_SHOTGUN] = true;
// Glitch names (for Lua interface)
m_GlitchNames["quickreload"] = GLITCH_QUICKRELOAD;
m_GlitchNames["fastfire"] = GLITCH_FASTFIRE;
Expand Down
22 changes: 0 additions & 22 deletions Server/mods/deathmatch/logic/CPed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,25 +538,3 @@ void CPed::SetJackingVehicle(CVehicle* pVehicle)
if (m_pJackingVehicle)
m_pJackingVehicle->SetJackingPed(this);
}

void CPed::SetHasJetPack(bool bHasJetPack)
{
if (m_bHasJetPack == bHasJetPack)
return;

m_bHasJetPack = bHasJetPack;

if (!bHasJetPack)
return;

// Set weapon slot to 0 if weapon is disabled with jetpack to avoid HUD and audio bugs
eWeaponType weaponType = static_cast<eWeaponType>(GetWeaponType(GetWeaponSlot()));
if (weaponType <= WEAPONTYPE_UNARMED)
return;

bool weaponEnabled;
CStaticFunctionDefinitions::GetJetpackWeaponEnabled(weaponType, weaponEnabled);

if (!weaponEnabled)
CStaticFunctionDefinitions::SetPedWeaponSlot(this, 0);
}
2 changes: 1 addition & 1 deletion Server/mods/deathmatch/logic/CPed.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class CPed : public CElement
static const char* GetBodyPartName(unsigned char ucID);

bool HasJetPack() { return m_bHasJetPack; }
void SetHasJetPack(bool bHasJetPack);
void SetHasJetPack(bool bHasJetPack) { m_bHasJetPack = bHasJetPack; }

bool IsInWater() { return m_bInWater; }
void SetInWater(bool bInWater) { m_bInWater = bInWater; }
Expand Down
Loading