Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
aced358
Add additional setWeaponProperty customizations
DeValdi Feb 6, 2026
b19b1c5
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 9, 2026
b0542dc
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 10, 2026
b60aaec
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 11, 2026
3550dc8
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 11, 2026
31ef18d
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 11, 2026
fc608f6
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 11, 2026
8ffd23f
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 12, 2026
af434ce
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 12, 2026
0c49a3d
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 13, 2026
864d835
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 14, 2026
545e14f
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 15, 2026
7c46589
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 15, 2026
f7f0a51
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 16, 2026
946273b
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 17, 2026
766b1a6
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 18, 2026
6c636b1
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 18, 2026
f47c4c7
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 20, 2026
839382e
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 22, 2026
054d182
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 24, 2026
13c3794
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 25, 2026
2bd2cd6
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 26, 2026
ffe374a
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 27, 2026
4304f83
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 28, 2026
3bbaa70
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Feb 28, 2026
d44a500
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 1, 2026
f9076ad
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 3, 2026
ef16e12
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 4, 2026
a01692d
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 5, 2026
9412296
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 6, 2026
d857eab
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 9, 2026
3ea52e8
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 11, 2026
17aeb7a
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 12, 2026
18549ad
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 16, 2026
d2df313
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 21, 2026
a5b762b
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 23, 2026
c53a40c
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 26, 2026
25978c4
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Mar 28, 2026
24d1e52
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 1, 2026
71c7309
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 2, 2026
3492d5e
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 4, 2026
fb8963d
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 5, 2026
223ad28
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 6, 2026
223f195
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 8, 2026
6ac1995
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 9, 2026
fc404f1
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 12, 2026
6570d07
Merge branch 'master' into feature/additional-weapon-customization
DeValdi Apr 14, 2026
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
306 changes: 215 additions & 91 deletions Client/game_sa/CWeaponStatManagerSA.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Client/game_sa/CWeaponStatManagerSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,5 @@ class CWeaponStatManagerSA : public CWeaponStatManager
static sWeaponInfo OriginalPoorWeaponData[WEAPONTYPE_MAX + 1];
static sWeaponInfo OriginalNormalWeaponData[WEAPONTYPE_MAX + 1];
static sWeaponInfo OriginalHitmanWeaponData[WEAPONTYPE_MAX + 1];
static sWeaponInfo OriginalSpecialWeaponData[WEAPONTYPE_MAX + 1];
};
21 changes: 20 additions & 1 deletion Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2609,6 +2609,8 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
pWeaponInfo->SetWeaponAnim2LoopFireTime(weaponProperty.data.anim2_loop_bullet_fire);

pWeaponInfo->SetAnimBreakoutTime(weaponProperty.data.anim_breakout_time);

pWeaponInfo->SetAnimGroup(weaponProperty.data.anim_group);
}

bool bEnabled;
Expand All @@ -2623,7 +2625,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
bitStream.ReadBit(bReadWeaponInfo);
if (bReadWeaponInfo)
{
for (int j = 0; j <= 2; j++)
for (int j = 0; j <= 3; j++)
{
bitStream.Read(&weaponProperty);
CWeaponStat* pWeaponInfo = g_pGame->GetWeaponStatManager()->GetWeaponStats((eWeaponType)weaponProperty.data.weaponType, (eWeaponSkill)j);
Expand All @@ -2644,6 +2646,23 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
pWeaponInfo->SetWeaponAnim2LoopFireTime(weaponProperty.data.anim2_loop_bullet_fire);

pWeaponInfo->SetAnimBreakoutTime(weaponProperty.data.anim_breakout_time);

pWeaponInfo->SetAnimGroup(weaponProperty.data.anim_group);
pWeaponInfo->SetAnimGroup(weaponProperty.data.anim_group);
pWeaponInfo->SetFireType((eFireType)weaponProperty.data.fire_type);
pWeaponInfo->SetModel(weaponProperty.data.model);
pWeaponInfo->SetModel2( weaponProperty.data.model2);
pWeaponInfo->SetSlot((eWeaponSlot)weaponProperty.data.weapon_slot);
pWeaponInfo->SetFireOffset(&weaponProperty.data.fire_offset);
pWeaponInfo->SetSkill((eWeaponSkill)weaponProperty.data.skill_level);
pWeaponInfo->SetRequiredStatLevel(weaponProperty.data.required_skill_level);
pWeaponInfo->SetFiringSpeed(weaponProperty.data.firing_speed);
pWeaponInfo->SetRadius(weaponProperty.data.radius);
pWeaponInfo->SetLifeSpan(weaponProperty.data.life_span);
pWeaponInfo->SetSpread(weaponProperty.data.spread);
pWeaponInfo->SetAimOffsetIndex(weaponProperty.data.aim_offset);
pWeaponInfo->SetDefaultCombo(weaponProperty.data.default_combo);
pWeaponInfo->SetCombosAvailable(weaponProperty.data.combos_available);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ IMPLEMENT_ENUM_BEGIN(eWeaponSkill)
ADD_ENUM(WEAPONSKILL_POOR, "poor")
ADD_ENUM(WEAPONSKILL_STD, "std")
ADD_ENUM(WEAPONSKILL_PRO, "pro")
ADD_ENUM(WEAPONSKILL_SPECIAL, "special")
IMPLEMENT_ENUM_END("weapon-skill")

IMPLEMENT_ENUM_BEGIN(ERenderFormat)
Expand Down
18 changes: 16 additions & 2 deletions Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2119,8 +2119,22 @@ int CLuaPedDefs::SetPedStat(lua_State* luaVM)
if (!argStream.HasErrors())
{
// Check the stat and value
if (usStat > NUM_PLAYER_STATS - 1 || fValue < 0.0f || fValue > 1000.0f)
argStream.SetCustomError("Stat must be 0 to 342 and value must be 0 to 1000.");
if (usStat > NUM_PLAYER_STATS - 1)
{
argStream.SetCustomError("Stat must be 0 to 342 and value must be 0 to 5000.");
}
else if (fValue < 0.0f)
{
argStream.SetCustomError("Value must be greater than 0.");
}
else if ((usStat >= WEAPONTYPE_PISTOL_SKILL && usStat <= WEAPONTYPE_SNIPERRIFLE_SKILL) && fValue > 5000.0f)
{
argStream.SetCustomError("Value must be at most 5000 (for weapon stats).");
}
else if ((usStat < WEAPONTYPE_PISTOL_SKILL || usStat > WEAPONTYPE_SNIPERRIFLE_SKILL) && fValue > 1000.0f)
{
argStream.SetCustomError("Value must be at most 1000 (for non-weapon stats).");
}
else if (CStaticFunctionDefinitions::SetPedStat(*pEntity, usStat, fValue))
{
lua_pushboolean(luaVM, true);
Expand Down
72 changes: 43 additions & 29 deletions Client/multiplayer_sa/CMultiplayerSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6260,40 +6260,54 @@ eWeaponType weaponSkillWeapon;
BYTE weaponSkill;
bool CPed_GetWeaponSkill()
{
if (weaponSkillWeapon < WEAPONTYPE_PISTOL || weaponSkillWeapon > WEAPONTYPE_TEC9)
{
return false;
}

SClientEntity<CPedSA>* pPedClientEntity = pGameInterface->GetPools()->GetPed((DWORD*)weaponSkillPed);
CPed* pPed = pPedClientEntity ? pPedClientEntity->pEntity : nullptr;
if (pPed)
if (!pPed)
{
return false;
}

CPlayerPed* playerPed = dynamic_cast<CPlayerPed*>(pPed);
if (!playerPed)
{
return false;
}

unsigned short skillStatIdx = pGameInterface->GetStats()->GetSkillStatIndex(weaponSkillWeapon);
float stat;
CPed* pLocalPlayerPed = pGameInterface->GetPools()->GetPedFromRef((DWORD)1);
if (pPed == pLocalPlayerPed)
{
CPed* pLocalPlayerPed = pGameInterface->GetPools()->GetPedFromRef((DWORD)1);
if (pPed != pLocalPlayerPed)
stat = pGameInterface->GetStats()->GetStatValue(skillStatIdx);
}
else
{
CRemoteDataStorageSA* data = CRemoteDataSA::GetRemoteDataStorage(playerPed);
if (!data)
{
if (weaponSkillWeapon >= WEAPONTYPE_PISTOL && weaponSkillWeapon <= WEAPONTYPE_TEC9)
{
CPlayerPed* playerPed = dynamic_cast<CPlayerPed*>(pPed);
if (playerPed)
{
CRemoteDataStorageSA* data = CRemoteDataSA::GetRemoteDataStorage(playerPed);
if (data)
{
float stat = data->m_stats.StatTypesFloat[pGameInterface->GetStats()->GetSkillStatIndex(weaponSkillWeapon)];

CWeaponInfo* pPoor = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_POOR);
CWeaponInfo* pStd = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_STD);
CWeaponInfo* pPro = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_PRO);

if (stat >= pPro->GetRequiredStatLevel())
weaponSkill = WEAPONSKILL_PRO;
else if (stat >= pStd->GetRequiredStatLevel())
weaponSkill = WEAPONSKILL_STD;
else
weaponSkill = WEAPONSKILL_POOR;
return true;
}
}
}
return false;
}
}
return false;
stat = data->m_stats.StatTypesFloat[skillStatIdx];
}

CWeaponInfo* pPoor = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_POOR);
CWeaponInfo* pStd = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_STD);
CWeaponInfo* pPro = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_PRO);
CWeaponInfo* pSpec = pGameInterface->GetWeaponInfo(weaponSkillWeapon, WEAPONSKILL_SPECIAL);
if (stat >= pSpec->GetRequiredStatLevel())
weaponSkill = WEAPONSKILL_SPECIAL;
else if (stat >= pPro->GetRequiredStatLevel())
weaponSkill = WEAPONSKILL_PRO;
else if (stat >= pStd->GetRequiredStatLevel())
weaponSkill = WEAPONSKILL_STD;
else
weaponSkill = WEAPONSKILL_POOR;
return true;
}

static void __declspec(naked) HOOK_CPed_GetWeaponSkill()
Expand Down
83 changes: 51 additions & 32 deletions Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,11 @@ bool CStaticFunctionDefinitions::SetWeaponProperty(eWeaponProperty eProperty, eW
pWeaponInfo->ToggleFlagBits(sData);
break;
}
case WEAPON_ANIM_GROUP:
{
pWeaponInfo->SetAnimGroup(sData);
break;
}
default:
return false;
}
Expand Down Expand Up @@ -3948,47 +3953,61 @@ bool CStaticFunctionDefinitions::SetPedStat(CElement* pElement, unsigned short u
assert(pElement);

// Check the stat
if (usStat < NUM_PLAYER_STATS && fValue >= 0.0f && fValue <= 1000.0f)
if (usStat > NUM_PLAYER_STATS - 1)
{
return false;
}
if (fValue < 0.0f)
{
return false;
}
if ((usStat >= 69 /* WEAPONTYPE_PISTOL_SKILL */ && usStat <= 79 /* WEAPONTYPE_SNIPERRIFLE_SKILL */) && fValue > 5000.0f)
{
return false;
}
if ((usStat < 69 /* WEAPONTYPE_PISTOL_SKILL */ || usStat > 79 /* WEAPONTYPE_SNIPERRIFLE_SKILL */) && fValue > 1000.0f)
{
RUN_CHILDREN(SetPedStat(*iter, usStat, fValue))
return false;
}

if (IS_PLAYER(pElement))
{
CPlayer* pPlayer = static_cast<CPlayer*>(pElement);
RUN_CHILDREN(SetPedStat(*iter, usStat, fValue))

// Dont let them set visual stats if they dont have the CJ model
if ((usStat != 21 /* FAT */ && usStat != 23 /* BODY_MUSCLE */) || pPlayer->GetModel() == 0)
{
// Save the stat
pPlayer->SetPlayerStat(usStat, fValue);
if (IS_PLAYER(pElement))
{
CPlayer* pPlayer = static_cast<CPlayer*>(pElement);

// Notify everyone
CPlayerStatsPacket Packet;
Packet.SetSourceElement(pPlayer);
Packet.Add(usStat, fValue);
m_pPlayerManager->BroadcastOnlyJoined(Packet);
// Dont let them set visual stats if they dont have the CJ model
if ((usStat != 21 /* FAT */ && usStat != 23 /* BODY_MUSCLE */) || pPlayer->GetModel() == 0)
{
// Save the stat
pPlayer->SetPlayerStat(usStat, fValue);

return true;
}
// Notify everyone
CPlayerStatsPacket Packet;
Packet.SetSourceElement(pPlayer);
Packet.Add(usStat, fValue);
m_pPlayerManager->BroadcastOnlyJoined(Packet);

return true;
}
else if (IS_PED(pElement))
{
CPed* pPed = static_cast<CPed*>(pElement);
}
else if (IS_PED(pElement))
{
CPed* pPed = static_cast<CPed*>(pElement);

// Dont let them set visual stats if they dont have the CJ model
if ((usStat != 21 /* FAT */ && usStat != 23 /* BODY_MUSCLE */) || pPed->GetModel() == 0)
{
// Save the stat
pPed->SetPlayerStat(usStat, fValue);
// Dont let them set visual stats if they dont have the CJ model
if ((usStat != 21 /* FAT */ && usStat != 23 /* BODY_MUSCLE */) || pPed->GetModel() == 0)
{
// Save the stat
pPed->SetPlayerStat(usStat, fValue);

// Notify everyone
CPlayerStatsPacket Packet;
Packet.SetSourceElement(pPed);
Packet.Add(usStat, fValue);
m_pPlayerManager->BroadcastOnlyJoined(Packet);
// Notify everyone
CPlayerStatsPacket Packet;
Packet.SetSourceElement(pPed);
Packet.Add(usStat, fValue);
m_pPlayerManager->BroadcastOnlyJoined(Packet);

return true;
}
return true;
}
}

Expand Down
Loading