From cc2805f9ab7909cbd2e0a4364444736494bbe41d Mon Sep 17 00:00:00 2001 From: Sergei Marochkin Date: Sun, 18 Dec 2016 00:14:21 +0300 Subject: [PATCH] Add FCNPC_OnWeaponStateChange callback Updated README --- README.md | 3 + pawn/FCNPC.inc.in | 1 + src/CCallbackManager.cpp | 15 ++++ src/CCallbackManager.hpp | 1 + src/CPlayerData.cpp | 172 +++++++++++++++++++++------------------ src/CPlayerData.hpp | 1 + 6 files changed, 115 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 5322e52..94d5ee7 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ forward FCNPC_OnFinishPlayback(npcid); forward FCNPC_OnTakeDamage(npcid, damagerid, weaponid, bodypart, Float:health_loss); forward FCNPC_OnGiveDamage(npcid, issuerid, weaponid, bodypart, Float:health_loss); forward FCNPC_OnVehicleTakeDamage(npcid, damagerid, vehicleid, weaponid, Float:x, Float:y, Float:z); +forward FCNPC_OnWeaponShot(npcid, weaponid, hittype, hitid, Float:x, Float:y, Float:z); +forward FCNPC_OnWeaponStateChange(npcid, weapon_state); forward FCNPC_OnFinishNodePoint(npcid, point); forward FCNPC_OnChangeNode(npcid, nodeid); @@ -197,6 +199,7 @@ native FCNPC_IsAimingAtPlayer(npcid, playerid); native FCNPC_GetAimingPlayer(npcid); native FCNPC_IsShooting(npcid); native FCNPC_IsReloading(npcid); +native FCNPC_TriggerWeaponShot(npcid, weaponid, hittype, hitid, Float:x, Float:y, Float:z, bool:ishit = true); native FCNPC_EnterVehicle(npcid, vehicleid, seatid, type = MOVE_TYPE_WALK); native FCNPC_ExitVehicle(npcid); diff --git a/pawn/FCNPC.inc.in b/pawn/FCNPC.inc.in index 193a7aa..f43eb67 100644 --- a/pawn/FCNPC.inc.in +++ b/pawn/FCNPC.inc.in @@ -53,6 +53,7 @@ forward FCNPC_OnTakeDamage(npcid, damagerid, weaponid, bodypart, Float:health_lo forward FCNPC_OnGiveDamage(npcid, issuerid, weaponid, bodypart, Float:health_loss); forward FCNPC_OnVehicleTakeDamage(npcid, damagerid, vehicleid, weaponid, Float:x, Float:y, Float:z); forward FCNPC_OnWeaponShot(npcid, weaponid, hittype, hitid, Float:x, Float:y, Float:z); +forward FCNPC_OnWeaponStateChange(npcid, weapon_state); forward FCNPC_OnFinishNodePoint(npcid, point); forward FCNPC_OnChangeNode(npcid, nodeid); diff --git a/src/CCallbackManager.cpp b/src/CCallbackManager.cpp index b11525c..b43eb31 100644 --- a/src/CCallbackManager.cpp +++ b/src/CCallbackManager.cpp @@ -203,6 +203,21 @@ int CCallbackManager::OnWeaponShot(WORD wPlayerId, WORD wHitId, BYTE byteHitType return cReturn; } +void CCallbackManager::OnWeaponStateChange(WORD wPlayerId, int iWeaponState) +{ + int iIndex; + for (auto &amx : m_vAMX) { + // Get the function index + if (!amx_FindPublic(amx, "FCNPC_OnWeaponStateChange", &iIndex)) { + // Push the parameters + amx_Push(amx, iWeaponState); + amx_Push(amx, wPlayerId); + // Execute the callback + amx_Exec(amx, NULL, iIndex); + } + } +} + int CCallbackManager::OnVehicleTakeDamage(WORD wPlayerId, WORD wDamagerId, WORD wVehicleId, BYTE byteWeaponId, CVector vecHit) { cell cReturn = 1; diff --git a/src/CCallbackManager.hpp b/src/CCallbackManager.hpp index 62bcb24..c878a36 100644 --- a/src/CCallbackManager.hpp +++ b/src/CCallbackManager.hpp @@ -30,6 +30,7 @@ class CCallbackManager static int OnTakeDamage(WORD wPlayerId, WORD wDamagerId, BYTE byteWeaponId, int iBodyPart, float fHealthLoss); static void OnGiveDamage(WORD wPlayerId, WORD wIssuerId, BYTE byteWeaponId, int iBodyPart, float fHealthLoss); static int OnWeaponShot(WORD wPlayerId, WORD wHitId, BYTE byteHitType, BYTE byteWeaponId, CVector vecPoint); + static void OnWeaponStateChange(WORD wPlayerId, int iWeaponState); static int OnVehicleTakeDamage(WORD wPlayerId, WORD wDamagerId, WORD wVehicleId, BYTE byteWeaponId, CVector vecHit); static void OnFinishPlayback(WORD wPlayerId); static int OnChangeNode(WORD wPlayerId, WORD wNodeId); diff --git a/src/CPlayerData.cpp b/src/CPlayerData.cpp index 4a6ccdf..d35db14 100644 --- a/src/CPlayerData.cpp +++ b/src/CPlayerData.cpp @@ -426,91 +426,97 @@ void CPlayerData::UpdateAim() } else { m_pPlayer->aimSyncData.byteCameraMode = 53; } - - // Set the weapon state - switch (byteWeaponId) { - case 0: - case WEAPON_BRASSKNUCKLE: - case WEAPON_GOLFCLUB: - case WEAPON_NITESTICK: - case WEAPON_KNIFE: - case WEAPON_BAT: - case WEAPON_SHOVEL: - case WEAPON_POOLSTICK: - case WEAPON_KATANA: - case WEAPON_CHAINSAW: - case WEAPON_DILDO: - case WEAPON_DILDO2: - case WEAPON_VIBRATOR: - case WEAPON_VIBRATOR2: - case WEAPON_FLOWER: - case WEAPON_CANE: - case WEAPON_BOMB: - case WEAPON_CAMERA: - case WEAPON_NIGHTVISION: - case WEAPON_INFRARED: - case WEAPON_PARACHUTE: - SetWeaponState(WEAPONSTATE_NO_BULLETS); - break; - - case WEAPON_GRENADE: - case WEAPON_TEARGAS: - case WEAPON_MOLTOV: - case WEAPON_SHOTGUN: - case WEAPON_SAWEDOFF: - case WEAPON_SHOTGSPA: - case WEAPON_RIFLE: - case WEAPON_SNIPER: - case WEAPON_ROCKETLAUNCHER: - case WEAPON_HEATSEEKER: - case WEAPON_SATCHEL: - SetWeaponState(WEAPONSTATE_LAST_BULLET); - break; - - case WEAPON_COLT45: - case WEAPON_SILENCED: - case WEAPON_DEAGLE: - case WEAPON_UZI: - case WEAPON_MP5: - case WEAPON_AK47: - case WEAPON_M4: - case WEAPON_TEC9: - case WEAPON_FLAMETHROWER: - case WEAPON_MINIGUN: - case WEAPON_SPRAYCAN: - case WEAPON_FIREEXTINGUISHER: - if (m_bReloading) { - SetWeaponState(WEAPONSTATE_RELOADING); - } else if (m_wAmmo == 1) { - SetWeaponState(WEAPONSTATE_LAST_BULLET); - } else if (m_wAmmo == 0) { - SetWeaponState(WEAPONSTATE_NO_BULLETS); - } else { - SetWeaponState(WEAPONSTATE_MORE_BULLETS); - } - break; - - default: - SetWeaponState(WEAPONSTATE_NO_BULLETS); - break; - } } else { // Set the camera mode and weapon state m_pPlayer->aimSyncData.byteCameraMode = 0; - SetWeaponState(WEAPONSTATE_NO_BULLETS); // Convert the player angle to radians float fAngle = CMath::DegreeToRadians(GetAngle()); // Calculate the camera target CVector vecTarget(m_pPlayer->aimSyncData.vecPosition.fX - sin(fAngle) * 0.2f, - m_pPlayer->aimSyncData.vecPosition.fY + cos(fAngle) * 0.2f, m_pPlayer->aimSyncData.vecPosition.fZ); + m_pPlayer->aimSyncData.vecPosition.fY + cos(fAngle) * 0.2f, + m_pPlayer->aimSyncData.vecPosition.fZ); // Calculate the camera front vector m_pPlayer->aimSyncData.vecFront = vecTarget - m_pPlayer->aimSyncData.vecPosition; } + + // Update the weapon state + UpdateWeaponState(); // Set the aim sync flag m_pPlayer->bHasAimSync = true; } +void CPlayerData::UpdateWeaponState() +{ + BYTE byteWeaponId = m_pPlayer->syncData.byteWeapon; + switch (byteWeaponId) { + case 0: + case WEAPON_BRASSKNUCKLE: + case WEAPON_GOLFCLUB: + case WEAPON_NITESTICK: + case WEAPON_KNIFE: + case WEAPON_BAT: + case WEAPON_SHOVEL: + case WEAPON_POOLSTICK: + case WEAPON_KATANA: + case WEAPON_CHAINSAW: + case WEAPON_DILDO: + case WEAPON_DILDO2: + case WEAPON_VIBRATOR: + case WEAPON_VIBRATOR2: + case WEAPON_FLOWER: + case WEAPON_CANE: + case WEAPON_BOMB: + case WEAPON_CAMERA: + case WEAPON_NIGHTVISION: + case WEAPON_INFRARED: + case WEAPON_PARACHUTE: + SetWeaponState(WEAPONSTATE_NO_BULLETS); + break; + + case WEAPON_GRENADE: + case WEAPON_TEARGAS: + case WEAPON_MOLTOV: + case WEAPON_SHOTGUN: + case WEAPON_SAWEDOFF: + case WEAPON_SHOTGSPA: + case WEAPON_RIFLE: + case WEAPON_SNIPER: + case WEAPON_ROCKETLAUNCHER: + case WEAPON_HEATSEEKER: + case WEAPON_SATCHEL: + SetWeaponState(WEAPONSTATE_LAST_BULLET); + break; + + case WEAPON_COLT45: + case WEAPON_SILENCED: + case WEAPON_DEAGLE: + case WEAPON_UZI: + case WEAPON_MP5: + case WEAPON_AK47: + case WEAPON_M4: + case WEAPON_TEC9: + case WEAPON_FLAMETHROWER: + case WEAPON_MINIGUN: + case WEAPON_SPRAYCAN: + case WEAPON_FIREEXTINGUISHER: + if (m_bReloading) { + SetWeaponState(WEAPONSTATE_RELOADING); + } else if (m_wAmmo == 1) { + SetWeaponState(WEAPONSTATE_LAST_BULLET); + } else if (m_wAmmo == 0) { + SetWeaponState(WEAPONSTATE_NO_BULLETS); + } else { + SetWeaponState(WEAPONSTATE_MORE_BULLETS); + } + break; + + default: + SetWeaponState(WEAPONSTATE_NO_BULLETS); + break; + } +} + bool CPlayerData::IsSpawned() { return m_bSpawned; @@ -823,15 +829,13 @@ void CPlayerData::Process() SetKeys(m_pPlayer->wUDAnalog, m_pPlayer->wLRAnalog, KEY_AIM); } } else if (m_bShooting) { - if (m_wAmmo == 0) { - if (!m_bHasInfiniteAmmo) { - m_bShooting = false; - SetKeys(m_pPlayer->wUDAnalog, m_pPlayer->wLRAnalog, KEY_AIM); - } else { - m_wAmmo = 500; - } + if (m_bHasInfiniteAmmo) { + m_wAmmo = 500; } - if (m_wAmmo > 0) { + if (m_wAmmo == 0) { + m_bShooting = false; + SetKeys(m_pPlayer->wUDAnalog, m_pPlayer->wLRAnalog, KEY_AIM); + } else { // Get the shoot time int iShootTime = GetWeaponShootTime(m_byteWeaponId); @@ -1121,7 +1125,16 @@ WORD CPlayerData::GetWeaponSkill(DWORD dwSkill) void CPlayerData::SetWeaponState(int iState) { + if (iState == WEAPONSTATE_UNKNOWN) { + return; + } + + int iOldState = m_pPlayer->aimSyncData.byteWeaponState; m_pPlayer->aimSyncData.byteWeaponState = iState; + + if (iOldState != iState) { + CCallbackManager::OnWeaponStateChange(m_wPlayerId, iState); + } } int CPlayerData::GetWeaponState() @@ -1905,6 +1918,9 @@ void CPlayerData::SetVehicle(WORD wVehicleId, BYTE byteSeatId) m_pPlayer->wVehicleId = wVehicleId; m_pPlayer->byteSeatId = byteSeatId; m_dwVehicleDeadTick = 0; + if (byteSeatId == 0) { + SetWeaponState(WEAPONSTATE_UNKNOWN); + } if (wVehicleId == INVALID_VEHICLE_ID && m_pPlayer->wVehicleId != INVALID_VEHICLE_ID) { CVehicle *pVehicle = GetVehicle(); diff --git a/src/CPlayerData.hpp b/src/CPlayerData.hpp index 42c5996..3ea5232 100644 --- a/src/CPlayerData.hpp +++ b/src/CPlayerData.hpp @@ -85,6 +85,7 @@ class CPlayerData WORD GetWeaponSkill(DWORD dwSkill); void SetWeaponState(int iState); int GetWeaponState(); + void UpdateWeaponState(); int GetWeaponType(BYTE byteWeaponId); bool SetWeaponReloadTime(BYTE byteWeaponId, int iTime);