From 0d1f42add1abbe729d52292d3e7b06a575b2506b Mon Sep 17 00:00:00 2001
From: Filip Gawin <filip.gawin@zoho.com>
Date: Mon, 24 Feb 2020 20:40:39 +0100
Subject: [PATCH] Implement ProcessCrane

---
 src/audio/AudioManager.cpp | 52 ++++++++++++++++++++++++++++++++++++--
 src/control/Cranes.h       | 41 ++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index 7f7af157..eafd1c9a 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -9,6 +9,7 @@
 #include "Boat.h"
 #include "Bridge.h"
 #include "Camera.h"
+#include "Cranes.h"
 #include "DMAudio.h"
 #include "Entity.h"
 #include "Explosion.h"
@@ -3293,11 +3294,58 @@ cAudioManager::ProcessCinemaScriptObject(uint8 sound)
 	}
 }
 
-WRAPPER
 void
 cAudioManager::ProcessCrane()
 {
-	EAXJMP(0x578910);
+	CCrane *crane = (CCrane *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity;
+	float distSquared;
+
+	bool distCalculated = false;
+
+	if(crane) {
+		if(crane->m_bCraneActive == 1) {
+			if(crane->m_bCraneStatus) {
+				m_sQueueSample.m_vecPos = crane->m_pObject->GetPosition();
+				distSquared = GetDistanceSquared(&this->m_sQueueSample.m_vecPos);
+				if(distSquared < 6400.f) {
+					CalculateDistance(distCalculated, distSquared);
+					m_sQueueSample.m_bVolume = ComputeVolume(100, 80.f, m_sQueueSample.m_fDistance);
+					if(m_sQueueSample.m_bVolume) {
+						m_sQueueSample.m_counter = 0;
+						m_sQueueSample.m_nSampleIndex = SFX_CRANE_MAGNET;
+						m_sQueueSample.m_bBankIndex = 0;
+						m_sQueueSample.m_bIsDistant = 0;
+						m_sQueueSample.field_16 = 2;
+						m_sQueueSample.m_nFrequency = 6000;
+						m_sQueueSample.m_nLoopCount = 0;
+						m_sQueueSample.m_bEmittingVolume = 100;
+						m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(
+						    m_sQueueSample.m_nSampleIndex);
+						m_sQueueSample.m_nLoopEnd =
+						    SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
+						m_sQueueSample.field_48 = 4.0f;
+						m_sQueueSample.m_fSoundIntensity = 80.0f;
+						m_sQueueSample.field_56 = 0;
+						m_sQueueSample.field_76 = 3;
+						m_sQueueSample.m_bReverbFlag = 1;
+						m_sQueueSample.m_bRequireReflection = 0;
+						AddSampleToRequestedQueue();
+					}
+					if(m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents) {
+						m_sQueueSample.m_counter = 1;
+						m_sQueueSample.m_nSampleIndex = SFX_COL_CAR_2;
+						m_sQueueSample.m_nFrequency =
+						    SampleManager.GetSampleBaseFrequency(SFX_COL_CAR_2);
+						m_sQueueSample.m_nLoopCount = 1;
+						m_sQueueSample.field_56 = 1;
+						m_sQueueSample.m_bReverbFlag = 1;
+						m_sQueueSample.m_bRequireReflection = 1;
+						AddSampleToRequestedQueue();
+					}
+				}
+			}
+		}
+	}
 }
 
 void
diff --git a/src/control/Cranes.h b/src/control/Cranes.h
index 9f606c9f..b40454ea 100644
--- a/src/control/Cranes.h
+++ b/src/control/Cranes.h
@@ -2,6 +2,47 @@
 #include "common.h"
 
 class CVehicle;
+class CEntity;
+class CObject;
+
+class CCrane
+{
+public:
+	CEntity *m_pObject;
+	CObject *m_pMagnet;
+	int m_nAudioEntity;
+	float m_fPickupX1;
+	float m_fPickupX2;
+	float m_fPickupY1;
+	float m_fPickupY2;
+	CVector m_vecDropoffTarget;
+	float m_fDropoffHeading;
+	float m_fPickupAngle;
+	float m_fDropoffAngle;
+	float m_fPickupDistance;
+	float m_fDropoffDistance;
+	float m_fAngle;
+	float m_fDistance;
+	float m_fHeight;
+	float m_fHookOffset;
+	float m_fHookHeight;
+	CVector m_vecHookInitPos;
+	CVector m_vecHookCurPos;
+	float m_fHookVelocityX;
+	float m_fHookVelocityY;
+	CVehicle *m_pVehiclePickedUp;
+	int m_nUpdateTimer;
+	char m_bCraneActive;
+	char m_bCraneStatus;
+	char m_bVehiclesCollected;
+	char m_bIsCrusher;
+	char m_bIsMilitaryCrane;
+	char field_125;
+	char m_bNotMilitaryCrane;
+	char gap_127[1];
+};
+
+static_assert(sizeof(CCrane) == 128, "CCrane: error");
 
 class CCranes
 {