From 8a0a29c64e5ebdfa71fe2d2a6a6e64c756a99961 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 31 Aug 2020 21:09:48 +0300 Subject: [PATCH 1/5] Stinger done --- src/objects/Stinger.cpp | 239 ++++++++++++++++++++++++++++++++++++++++ src/objects/Stinger.h | 41 +++++++ src/peds/CopPed.cpp | 4 + src/peds/CopPed.h | 1 + 4 files changed, 285 insertions(+) create mode 100644 src/objects/Stinger.cpp create mode 100644 src/objects/Stinger.h diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp new file mode 100644 index 00000000..86b44b57 --- /dev/null +++ b/src/objects/Stinger.cpp @@ -0,0 +1,239 @@ +#include "common.h" +#include "Stinger.h" +#include "CopPed.h" +#include "ModelIndices.h" +#include "RpAnimBlend.h" +#include "World.h" +#include "Automobile.h" +#include "Bike.h" +#include "Particle.h" +#include "AnimBlendAssociation.h" +#include "General.h" + +uint32 NumOfStingerSegments; + +/* -- CStingerSegment -- */ + +CStingerSegment::CStingerSegment() +{ + m_fMass = 1.0f; + m_fTurnMass = 1.0f; + m_fAirResistance = 0.99999f; + m_fElasticity = 0.75f; + m_fBuoyancy = GRAVITY * m_fMass * 0.1f; + bExplosionProof = true; + SetModelIndex(MI_PLC_STINGER); + ObjectCreatedBy = ESCALATOR_OBJECT; + NumOfStingerSegments++; +} + +CStingerSegment::~CStingerSegment() +{ + NumOfStingerSegments--; +} + +/* -- CStinger -- */ + +CStinger::CStinger() +{ + bIsDeployed = false; +} + +void +CStinger::Init(CPed *pPed) +{ + int32 i; + + pOwner = pPed; + for (i = 0; i < NUM_STINGER_SEGMENTS; i++) { + pSpikes[i] = new CStingerSegment; + pSpikes[i]->bUsesCollision = false; + } + bIsDeployed = true; + m_vPos = pPed->GetPosition(); + m_fMax_Z = Atan2(-pPed->GetForward().x, pPed->GetForward().y) + HALFPI; + + for (i = 0; i < NUM_STINGER_SEGMENTS; i++) { + // shouldn't this be some inlined method? guh... + CVector pos = pSpikes[i]->GetPosition(); + pSpikes[i]->GetMatrix().SetRotate(0.0f, 0.0f, Atan2(-pPed->GetForward().x, pPed->GetForward().y)); + pSpikes[i]->GetMatrix().Translate(pos); + pSpikes[i]->SetPosition(m_vPos); + } + + CVector2D fwd2d(pPed->GetForward().x, pPed->GetForward().y); + + for (i = 0; i < ARRAY_SIZE(m_vPositions); i++) + m_vPositions[i] = fwd2d * Sin(DEGTORAD(i)); + + m_nSpikeState = STINGERSTATE_NONE; + m_nTimeOfDeploy = CTimer::GetTimeInMilliseconds(); +} + +void +CStinger::Remove() +{ + if (!bIsDeployed) return; + + for (int32 i = 0; i < NUM_STINGER_SEGMENTS; i++) { + CStingerSegment *spikeSegment = pSpikes[i]; + if (spikeSegment->m_entryInfoList.first != nil) + spikeSegment->bRemoveFromWorld = true; + else + delete spikeSegment; + } + bIsDeployed = false; +} + +void +CStinger::Deploy(CPed *pPed) +{ + if (NumOfStingerSegments < NUM_STINGER_SEGMENTS*2 && !pPed->bInVehicle && pPed->IsPedInControl()) { + if (!bIsDeployed && RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_WEAPON_THROWU) == nil) { + Init(pPed); + pPed->SetPedState(PED_DEPLOY_STINGER); + CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU); + } + } +} + +void +CStinger::CheckForBurstTyres() +{ + const CVector firstPos = pSpikes[0]->GetPosition(); + const CVector lastPos = pSpikes[NUM_STINGER_SEGMENTS - 1]->GetPosition(); + float dist = (lastPos - firstPos).Magnitude(); + if (dist > 0.1f) return; + + CVehicle *vehsInRange[16]; + int16 numObjects; + CEntity someEntity; + + CWorld::FindObjectsInRange((lastPos + firstPos) / 2.0f, + dist, true, &numObjects, 15, (CEntity**)vehsInRange, + false, true, false, false, false); + + for (int32 i = 0; i < numObjects; i++) { + CAutomobile *pAutomobile = nil; + CBike *pBike = nil; + + if (vehsInRange[i]->IsCar()) + pAutomobile = (CAutomobile*)vehsInRange[i]; + else if (vehsInRange[i]->IsBike()) + pBike = (CBike*)vehsInRange[i]; + + if (pAutomobile == nil && pBike == nil) continue; + + int wheelId = 0; + float someWheelDist = sq(((CVehicleModelInfo*)CModelInfo::GetModelInfo(vehsInRange[i]->GetModelIndex()))->m_wheelScale); + + for (; wheelId < 4; wheelId++) { + if ((pAutomobile != nil && pAutomobile->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f) || + (pBike != nil && pBike->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f)) + break; + } + + if (wheelId >= 4) continue; + + CVector vecWheelPos; + if (pAutomobile != nil) + vecWheelPos = pAutomobile->m_aWheelColPoints[wheelId].point; + else if (pBike != nil) + vecWheelPos = pBike->m_aWheelColPoints[wheelId].point; + + for (int32 spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { + if ((pSpikes[spike]->GetPosition() - vecWheelPos).Magnitude() < someWheelDist) { + if (pBike) { + if (wheelId < 2) + vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); + else + vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true); + } else { + switch (wheelId) { + case 0: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); break; + case 1: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true); break; + case 2: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RF, true); break; + case 3: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RR, true); break; + } + } + vecWheelPos.z += 0.15f; // BUG? doesn't that break the burst of other tires? + for (int j = 0; j < 4; j++) + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, vecWheelPos, vehsInRange[i]->GetRight() * 0.1f); + } + } + } +} + +void +CStinger::Process() +{ + switch (m_nSpikeState) + { + case STINGERSTATE_NONE: + if (pOwner != nil + && !pOwner->bInVehicle + && pOwner->GetPedState() == PED_DEPLOY_STINGER + && RpAnimBlendClumpGetAssociation(pOwner->GetClump(), ANIM_WEAPON_THROWU)->currentTime > 0.39f) + { + m_nSpikeState = STINGERSTATE_STATE1; + for (int i = 0; i < NUM_STINGER_SEGMENTS; i++) + CWorld::Add(pSpikes[i]); + pOwner->SetIdle(); + } + break; + case STINGERSTATE_STATE2: + if (pOwner != nil && pOwner->m_nPedType == PEDTYPE_COP) + ((CCopPed*)pOwner)->m_bThrowsSpikeTrap = false; + break; + case STINGERSTATE_STATE3: + if (CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500) + m_nSpikeState = STINGERSTATE_REMOVE; + // no break + case STINGERSTATE_STATE1: + if (m_nSpikeState != STINGERSTATE_STATE1 || CTimer::GetTimeInMilliseconds() <= m_nTimeOfDeploy + 2500) { + float something = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f; + if (m_nSpikeState != STINGERSTATE_STATE1) + something = 1.0f - something; + + float radangle = something * ARRAY_SIZE(m_vPositions); + float angle1 = m_fMax_Z + DEGTORAD(radangle); + float angle2 = m_fMax_Z - DEGTORAD(radangle); + int pos = clamp(radangle, 0, ARRAY_SIZE(m_vPositions)-1); + + CVector2D pos2d = m_vPositions[pos]; + CVector pos3d = m_vPos; + CColPoint colPoint; + CEntity *pEntity; + if (CWorld::ProcessVerticalLine(CVector(pos3d.x, pos3d.y, pos3d.z - 10.0f), pos3d.z, colPoint, pEntity, true, false, false, false, true, false, nil)) + pos3d.z = colPoint.point.z + 0.15f; + + angle1 = CGeneral::LimitRadianAngle(angle1); + angle2 = CGeneral::LimitRadianAngle(angle2); + + for (int spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { + CVector somePosAgain = pos3d + CVector(pos2d.x, pos2d.y, 0.6f); + if (CWorld::TestSphereAgainstWorld(somePosAgain, 0.3f, nil, true, false, false, true, false, false)) + pos2d = CVector2D(0.0f, 0.0f); + + if (spike % 2 == 0) { + CVector pos = pSpikes[spike]->GetPosition(); + pSpikes[spike]->GetMatrix().SetRotate(0.0f, 0.0f, angle1); + pSpikes[spike]->GetMatrix().Translate(pos); + pos3d.x += pos2d.x; + pos3d.y += pos2d.y; + } else { + CVector pos = pSpikes[spike]->GetPosition(); + pSpikes[spike]->GetMatrix().SetRotate(0.0f, 0.0f, angle2); + pSpikes[spike]->GetMatrix().Translate(pos); + } + pSpikes[spike]->SetPosition(pos3d); + } + } else + m_nSpikeState = STINGERSTATE_STATE2; + break; + case STINGERSTATE_REMOVE: + Remove(); + break; + } + CheckForBurstTyres(); +} \ No newline at end of file diff --git a/src/objects/Stinger.h b/src/objects/Stinger.h new file mode 100644 index 00000000..80ac3d1e --- /dev/null +++ b/src/objects/Stinger.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Object.h" + +class CStingerSegment : public CObject +{ +public: + CStingerSegment(); + ~CStingerSegment(); +}; + +#define NUM_STINGER_SEGMENTS (12) + +class CStinger +{ + // TODO: better names + enum { + STINGERSTATE_NONE = 0, + STINGERSTATE_STATE1, + STINGERSTATE_STATE2, + STINGERSTATE_STATE3, + STINGERSTATE_REMOVE, + }; + + bool bIsDeployed; + uint32 m_nTimeOfDeploy; + CVector m_vPos; + float m_fMax_Z; + float m_fMin_Z; + CVector2D m_vPositions[60]; + CStingerSegment *pSpikes[NUM_STINGER_SEGMENTS]; + class CPed *pOwner; + uint8 m_nSpikeState; +public: + CStinger(); + void Init(CPed *pPed); + void Remove(); + void Deploy(CPed *pPed); + void CheckForBurstTyres(); + void Process(); +}; \ No newline at end of file diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 6c9eb276..8dd517a2 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -18,6 +18,7 @@ #include "Camera.h" #include "PedPlacement.h" #include "Ropes.h" +#include "Stinger.h" CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) { @@ -92,6 +93,7 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) m_nHassleTimer = 0; field_61C = 0; field_624 = 0; + m_pStinger = new CStinger; if (m_pPointGunAt) m_pPointGunAt->CleanUpOldReference((CEntity**)&m_pPointGunAt); m_pPointGunAt = nil; @@ -100,6 +102,8 @@ CCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP) CCopPed::~CCopPed() { ClearPursuit(); + m_pStinger->Remove(); + delete m_pStinger; } // --MIAMI: Done diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h index edec145e..35244bed 100644 --- a/src/peds/CopPed.h +++ b/src/peds/CopPed.h @@ -30,6 +30,7 @@ public: uintptr m_nRopeID; uint32 m_nHassleTimer; uint32 field_61C; + class CStinger *m_pStinger; int32 field_624; int8 field_628; From 024f0a5027829fb7af962b59e996553ed3e78eb6 Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 31 Aug 2020 21:15:04 +0300 Subject: [PATCH 2/5] use SetOrientation --- src/objects/Stinger.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp index 86b44b57..7a84edac 100644 --- a/src/objects/Stinger.cpp +++ b/src/objects/Stinger.cpp @@ -54,10 +54,7 @@ CStinger::Init(CPed *pPed) m_fMax_Z = Atan2(-pPed->GetForward().x, pPed->GetForward().y) + HALFPI; for (i = 0; i < NUM_STINGER_SEGMENTS; i++) { - // shouldn't this be some inlined method? guh... - CVector pos = pSpikes[i]->GetPosition(); - pSpikes[i]->GetMatrix().SetRotate(0.0f, 0.0f, Atan2(-pPed->GetForward().x, pPed->GetForward().y)); - pSpikes[i]->GetMatrix().Translate(pos); + pSpikes[i]->SetOrientation(0.0f, 0.0f, Atan2(-pPed->GetForward().x, pPed->GetForward().y)); pSpikes[i]->SetPosition(m_vPos); } @@ -216,15 +213,11 @@ CStinger::Process() pos2d = CVector2D(0.0f, 0.0f); if (spike % 2 == 0) { - CVector pos = pSpikes[spike]->GetPosition(); - pSpikes[spike]->GetMatrix().SetRotate(0.0f, 0.0f, angle1); - pSpikes[spike]->GetMatrix().Translate(pos); + pSpikes[spike]->SetOrientation(0.0f, 0.0f, angle1); pos3d.x += pos2d.x; pos3d.y += pos2d.y; } else { - CVector pos = pSpikes[spike]->GetPosition(); - pSpikes[spike]->GetMatrix().SetRotate(0.0f, 0.0f, angle2); - pSpikes[spike]->GetMatrix().Translate(pos); + pSpikes[spike]->SetOrientation(0.0f, 0.0f, angle2); } pSpikes[spike]->SetPosition(pos3d); } From df67c73d81c6ce9f6922b7fad23d69232b9e19fd Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 31 Aug 2020 21:21:50 +0300 Subject: [PATCH 3/5] vars rename --- src/objects/Stinger.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp index 7a84edac..61424885 100644 --- a/src/objects/Stinger.cpp +++ b/src/objects/Stinger.cpp @@ -188,14 +188,14 @@ CStinger::Process() // no break case STINGERSTATE_STATE1: if (m_nSpikeState != STINGERSTATE_STATE1 || CTimer::GetTimeInMilliseconds() <= m_nTimeOfDeploy + 2500) { - float something = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f; + float progress = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f; if (m_nSpikeState != STINGERSTATE_STATE1) - something = 1.0f - something; + progress = 1.0f - progress; - float radangle = something * ARRAY_SIZE(m_vPositions); - float angle1 = m_fMax_Z + DEGTORAD(radangle); - float angle2 = m_fMax_Z - DEGTORAD(radangle); - int pos = clamp(radangle, 0, ARRAY_SIZE(m_vPositions)-1); + float degangle = progress * ARRAY_SIZE(m_vPositions); + float angle1 = m_fMax_Z + DEGTORAD(degangle); + float angle2 = m_fMax_Z - DEGTORAD(degangle); + int pos = clamp(degangle, 0, ARRAY_SIZE(m_vPositions)-1); CVector2D pos2d = m_vPositions[pos]; CVector pos3d = m_vPos; From 6778640b52b474e0d06f09c3fdfdb15138936b6b Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Mon, 31 Aug 2020 21:35:05 +0300 Subject: [PATCH 4/5] Rename states --- src/objects/Stinger.cpp | 17 +++++++++-------- src/objects/Stinger.h | 7 +++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp index 61424885..0b96322b 100644 --- a/src/objects/Stinger.cpp +++ b/src/objects/Stinger.cpp @@ -172,24 +172,26 @@ CStinger::Process() && pOwner->GetPedState() == PED_DEPLOY_STINGER && RpAnimBlendClumpGetAssociation(pOwner->GetClump(), ANIM_WEAPON_THROWU)->currentTime > 0.39f) { - m_nSpikeState = STINGERSTATE_STATE1; + m_nSpikeState = STINGERSTATE_DEPLOYING; for (int i = 0; i < NUM_STINGER_SEGMENTS; i++) CWorld::Add(pSpikes[i]); pOwner->SetIdle(); } break; - case STINGERSTATE_STATE2: + case STINGERSTATE_DEPLOYED: if (pOwner != nil && pOwner->m_nPedType == PEDTYPE_COP) ((CCopPed*)pOwner)->m_bThrowsSpikeTrap = false; break; - case STINGERSTATE_STATE3: + case STINGERSTATE_UNDEPLOYING: if (CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500) m_nSpikeState = STINGERSTATE_REMOVE; // no break - case STINGERSTATE_STATE1: - if (m_nSpikeState != STINGERSTATE_STATE1 || CTimer::GetTimeInMilliseconds() <= m_nTimeOfDeploy + 2500) { + case STINGERSTATE_DEPLOYING: + if (m_nSpikeState == STINGERSTATE_DEPLOYING && CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500) + m_nSpikeState = STINGERSTATE_DEPLOYED; + else { float progress = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f; - if (m_nSpikeState != STINGERSTATE_STATE1) + if (m_nSpikeState != STINGERSTATE_DEPLOYING) progress = 1.0f - progress; float degangle = progress * ARRAY_SIZE(m_vPositions); @@ -221,8 +223,7 @@ CStinger::Process() } pSpikes[spike]->SetPosition(pos3d); } - } else - m_nSpikeState = STINGERSTATE_STATE2; + } break; case STINGERSTATE_REMOVE: Remove(); diff --git a/src/objects/Stinger.h b/src/objects/Stinger.h index 80ac3d1e..d1b57ce7 100644 --- a/src/objects/Stinger.h +++ b/src/objects/Stinger.h @@ -13,12 +13,11 @@ public: class CStinger { - // TODO: better names enum { STINGERSTATE_NONE = 0, - STINGERSTATE_STATE1, - STINGERSTATE_STATE2, - STINGERSTATE_STATE3, + STINGERSTATE_DEPLOYING, + STINGERSTATE_DEPLOYED, + STINGERSTATE_UNDEPLOYING, STINGERSTATE_REMOVE, }; From 3bb0e78e1c9efec3c5e7ade14271550ea2e8cf7e Mon Sep 17 00:00:00 2001 From: Sergeanur Date: Tue, 1 Sep 2020 12:35:59 +0300 Subject: [PATCH 5/5] Rename vars --- src/objects/Stinger.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/objects/Stinger.cpp b/src/objects/Stinger.cpp index 0b96322b..d0e6919f 100644 --- a/src/objects/Stinger.cpp +++ b/src/objects/Stinger.cpp @@ -104,7 +104,7 @@ CStinger::CheckForBurstTyres() CVehicle *vehsInRange[16]; int16 numObjects; - CEntity someEntity; + CEntity entity; CWorld::FindObjectsInRange((lastPos + firstPos) / 2.0f, dist, true, &numObjects, 15, (CEntity**)vehsInRange, @@ -122,7 +122,7 @@ CStinger::CheckForBurstTyres() if (pAutomobile == nil && pBike == nil) continue; int wheelId = 0; - float someWheelDist = sq(((CVehicleModelInfo*)CModelInfo::GetModelInfo(vehsInRange[i]->GetModelIndex()))->m_wheelScale); + float wheelScaleSq = sq(((CVehicleModelInfo*)CModelInfo::GetModelInfo(vehsInRange[i]->GetModelIndex()))->m_wheelScale); for (; wheelId < 4; wheelId++) { if ((pAutomobile != nil && pAutomobile->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f) || @@ -139,7 +139,7 @@ CStinger::CheckForBurstTyres() vecWheelPos = pBike->m_aWheelColPoints[wheelId].point; for (int32 spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { - if ((pSpikes[spike]->GetPosition() - vecWheelPos).Magnitude() < someWheelDist) { + if ((pSpikes[spike]->GetPosition() - vecWheelPos).Magnitude() < wheelScaleSq) { if (pBike) { if (wheelId < 2) vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); @@ -210,8 +210,7 @@ CStinger::Process() angle2 = CGeneral::LimitRadianAngle(angle2); for (int spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) { - CVector somePosAgain = pos3d + CVector(pos2d.x, pos2d.y, 0.6f); - if (CWorld::TestSphereAgainstWorld(somePosAgain, 0.3f, nil, true, false, false, true, false, false)) + if (CWorld::TestSphereAgainstWorld(pos3d + CVector(pos2d.x, pos2d.y, 0.6f), 0.3f, nil, true, false, false, true, false, false)) pos2d = CVector2D(0.0f, 0.0f); if (spike % 2 == 0) {