summaryrefslogtreecommitdiffstats
path: root/src/control/Cranes.cpp
diff options
context:
space:
mode:
authorNikolay Korolev <nickvnuk@gmail.com>2020-04-05 11:35:51 +0200
committerNikolay Korolev <nickvnuk@gmail.com>2020-04-05 11:35:51 +0200
commit057b28e39b2e58aae1f47d44bd1ce6222a781978 (patch)
treef9f207d74461f98f46baf184d01e56d2fb8fd76b /src/control/Cranes.cpp
parentMerge remote-tracking branch 'upstream/master' (diff)
downloadre3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar.gz
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar.bz2
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar.lz
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar.xz
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.tar.zst
re3-057b28e39b2e58aae1f47d44bd1ce6222a781978.zip
Diffstat (limited to 'src/control/Cranes.cpp')
-rw-r--r--src/control/Cranes.cpp235
1 files changed, 230 insertions, 5 deletions
diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp
index 4c1bf2c8..96c41f45 100644
--- a/src/control/Cranes.cpp
+++ b/src/control/Cranes.cpp
@@ -2,13 +2,238 @@
#include "patcher.h"
#include "Cranes.h"
+#include "Camera.h"
+#include "DMAudio.h"
+#include "Entity.h"
+#include "ModelIndices.h"
+#include "Replay.h"
+#include "Object.h"
+#include "World.h"
+
+#define MAX_DISTANCE_TO_FIND_CRANE (10.0f)
+#define CRANE_UPDATE_RADIUS (300.0f)
+#define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f)
+#define CRUSHER_Z (-0.951f)
+#define MILITARY_Z (10.7862f)
+
+void CCranes::InitCranes(void)
+{
+ CarsCollectedMilitaryCrane = 0;
+ NumCranes = 0;
+ for (int i = 0; i < NUMSECTORS_X; i++) {
+ for (int j = 0; j < NUMSECTORS_Y; j++) {
+ for (CPtrNode* pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {
+ CEntity* pEntity = (CEntity*)pNode->item;
+ if (MODELID_CRANE_1 == pEntity->GetModelIndex() ||
+ MODELID_CRANE_2 == pEntity->GetModelIndex() ||
+ MODELID_CRANE_3 == pEntity->GetModelIndex())
+ AddThisOneCrane(pEntity);
+ }
+ }
+ }
+ for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode->next) {
+ CEntity* pEntity = (CEntity*)pNode->item;
+ if (MODELID_CRANE_1 == pEntity->GetModelIndex() ||
+ MODELID_CRANE_2 == pEntity->GetModelIndex() ||
+ MODELID_CRANE_3 == pEntity->GetModelIndex())
+ AddThisOneCrane(pEntity);
+ }
+}
+
+void CCranes::AddThisOneCrane(CEntity* pEntity)
+{
+ pEntity->GetMatrix().ResetOrientation();
+ if (NumCranes >= NUM_CRANES)
+ return;
+ CCrane* pCrane = &aCranes[NumCranes];
+ pCrane->Init();
+ pCrane->m_pObject = pEntity;
+ pCrane->m_bCraneStatus = CCrane::NONE;
+ pCrane->m_fHeight = NumCranes; // lol wtf
+ while (pCrane->m_fHeight > TWOPI)
+ pCrane->m_fHeight -= TWOPI;
+ pCrane->m_fHookOffset = 20.0f;
+ pCrane->m_fHookHeight = 20.0f;
+ pCrane->m_nUpdateTimer = 0;
+ pCrane->m_bCraneState = CCrane::IDLE;
+ pCrane->m_bWasMilitaryCrane = 0;
+ pCrane->m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[NumCranes]);
+ if (pCrane->m_nAudioEntity >= 0)
+ DMAudio.SetEntityStatus(pCrane->m_nAudioEntity, 1);
+ pCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex());
+ // W T F ? ? ?
+ // Is this used to avoid military crane?
+ if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) {
+ CObject* pMagnet = new CObject(MI_MAGNET, false);
+ pMagnet->ObjectCreatedBy = MISSION_OBJECT;
+ pMagnet->bUsesCollision = false;
+ pMagnet->bExplosionProof = true;
+ pMagnet->bAffectedByGravity = false;
+ pCrane->m_pMagnet = pMagnet;
+ pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z);
+ pCrane->SetHookMatrix();
+ }
+ else
+ pCrane->m_pMagnet = nil;
+ NumCranes++;
+}
+
+void CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY)
+{
+ float fMinDistance = 99999.9f;
+ float X = fPosX, Y = fPosY;
+ if (X <= -10000.0f || Y <= -10000.0f) {
+ X = fDropOffX;
+ Y = fDropOffY;
+ }
+ int index = 0;
+ for (int i = 0; i < NumCranes; i++) {
+ float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude();
+ if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
+ fMinDistance = distance;
+ index = i;
+ }
+ }
+#ifdef FIX_BUGS // classic
+ if (fMinDistance == 99999.9f)
+ return;
+#endif
+ CCrane* pCrane = &aCranes[NumCranes];
+ pCrane->m_fPickupX1 = fInfX;
+ pCrane->m_fPickupX2 = fSupX;
+ pCrane->m_fPickupY1 = fInfY;
+ pCrane->m_fPickupY2 = fSupY;
+ pCrane->m_vecDropoffTarget.x = fDropOffX;
+ pCrane->m_vecDropoffTarget.y = fDropOffY;
+ pCrane->m_vecDropoffTarget.z = fDropOffZ;
+ pCrane->m_bCraneStatus = CCrane::ACTIVATED;
+ pCrane->m_pVehiclePickedUp = nil;
+ pCrane->m_bVehiclesCollected = 0;
+ pCrane->m_bIsCrusher = bIsCrusher;
+ pCrane->m_bIsMilitaryCrane = bIsMilitary;
+ bool military = true;
+ if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane)
+ military = false;
+ pCrane->m_bWasMilitaryCrane = military;
+ pCrane->m_nUpdateTimer = 0;
+ pCrane->m_bCraneState = CCrane::IDLE;
+ float Z;
+ if (bIsCrusher)
+ Z = CRUSHER_Z;
+ else if (bIsMilitary)
+ Z = MILITARY_Z;
+ else
+ Z = CWorld::FindGroundZForCoord((fInfX + fSupY) / 2, (fInfY + fSupY) / 2);
+ pCrane->FindParametersForTarget((fInfX + fSupY) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fAngle);
+ pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDistance);
+}
+
+void CCranes::DeActivateCrane(float X, float Y)
+{
+ float fMinDistance = 99999.9f;
+ int index = 0;
+ for (int i = 0; i < NumCranes; i++) {
+ float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude();
+ if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
+ fMinDistance = distance;
+ index = i;
+ }
+ }
+#ifdef FIX_BUGS // classic
+ if (fMinDistance == 99999.9f)
+ return;
+#endif
+ aCranes[index].m_bCraneStatus = CCrane::DEACTIVATED;
+ aCranes[index].m_bCraneState = CCrane::IDLE;
+}
+
+bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle)
+{
+ int index = 0;
+ bool result = false;
+ for (int i = 0; i < NumCranes; i++) {
+ float distance = (CVector2D(X, Y) - aCranes[i].m_pObject->GetPosition()).Magnitude();
+ if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) {
+ if (aCranes[i].m_bCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_bCraneStatus == CCrane::ROTATING_TARGET)
+ result = true;
+ }
+ }
+ return true;
+}
+
+void CCranes::UpdateCranes(void)
+{
+ for (int i = 0; i < NumCranes; i++) {
+ if (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher ||
+ (TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().x &&
+ TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().x &&
+ TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pObject->GetPosition().y &&
+ TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pObject->GetPosition().y))
+ aCranes[i].Update();
+ }
+}
+
+void CCrane::Update(void)
+{
+ if (CReplay::IsPlayingBack())
+ return;
+ if ((m_bCraneStatus == ACTIVATED || m_bCraneStatus == DEACTIVATED) &&
+ Abs(TheCamera.GetGameCamPosition().x - m_pObject->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS &&
+ Abs(TheCamera.GetGameCamPosition().y - m_pObject->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) {
+ switch (m_bCraneState) {
+ case IDLE:
+ if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, 4.0f + m_fAngle + m_bIsCrusher ? 4.5f : 0.0f, 1.0f) &&
+ CTimer::GetTimeInMilliseconds() > m_nUpdateTimer) {
+ CWorld::AdvanceCurrentScanCode();
+#ifdef FIX_BUGS
+ int xstart = max(0, CWorld::GetSectorIndexX(m_fPickupX1));
+ int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2));
+ int ystart = max(0, CWorld::GetSectorIndexY(m_fPickupY1));
+ int yend = min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2));
+#else
+ int xstart = CWorld::GetSectorIndexX(m_fPickupX1);
+ int xend = CWorld::GetSectorIndexX(m_fPickupX2);
+ int ystart = CWorld::GetSectorIndexY(m_fPickupY1);
+ int yend = CWorld::GetSectorIndexY(m_fPickupY1);
+#endif
+ assert(xstart <= xend);
+ assert(ystart <= yend);
+ for (int i = xstart; i <= xend; i++) {
+ for (int j = ystart; j <= yend; j++) {
+ FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES]);
+ FindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
+ }
+ }
+ }
+ break;
+ case GOING_TOWARDS_TARGET:
+ if (!m_pVehiclePickedUp) {
+ m_bCraneState = IDLE;
+ break;
+ }
+ if (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 ||
+ m_pVehiclePickedUp->GetPosition().x > m_fPickupX2 ||
+ m_pVehiclePickedUp->GetPosition().y > m_fPickupY1 ||
+ m_pVehiclePickedUp->GetPosition().y > m_fPickupY2 ||
+ m_pVehiclePickedUp->pDriver ||
+ Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > 0.01f ||
+ Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > 0.01f ||
+ Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > 0.01f ||
+ FindPlayerPed()->GetPedState() == PED_ENTER_CAR &&
+ FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) {
+ m_pVehiclePickedUp = nil;
+ m_bCraneState = IDLE;
+ break;
+ }
+
+ }
+ }
+}
+
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }
-WRAPPER bool CCranes::IsThisCarPickedUp(float, float, CVehicle*) { EAXJMP(0x543940); }
WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); }
-WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); }
-WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); }
-WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); }
-WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); }
+
+
WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); }
WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); }