mirror of https://github.com/Nofated095/re-GTA.git
commit
81d945488d
|
@ -3515,9 +3515,9 @@ cAudioManager::ProcessCrane()
|
||||||
static const int intensity = 80;
|
static const int intensity = 80;
|
||||||
|
|
||||||
if(crane) {
|
if(crane) {
|
||||||
if(crane->m_bCraneActive == 1) {
|
if(crane->m_nCraneStatus == CCrane::ACTIVATED) {
|
||||||
if(crane->m_bCraneStatus) {
|
if(crane->m_nCraneState != CCrane::IDLE) {
|
||||||
m_sQueueSample.m_vecPos = crane->m_pObject->GetPosition();
|
m_sQueueSample.m_vecPos = crane->m_pCraneEntity->GetPosition();
|
||||||
distSquared = GetDistanceSquared(&this->m_sQueueSample.m_vecPos);
|
distSquared = GetDistanceSquared(&this->m_sQueueSample.m_vecPos);
|
||||||
if(distSquared < SQR(intensity)) {
|
if(distSquared < SQR(intensity)) {
|
||||||
CalculateDistance(distCalculated, distSquared);
|
CalculateDistance(distCalculated, distSquared);
|
||||||
|
|
|
@ -61,7 +61,7 @@ cAudioScriptObject::SaveAllAudioScriptObjects(uint8 *buf, uint32 *size)
|
||||||
INITSAVEBUF
|
INITSAVEBUF
|
||||||
|
|
||||||
int32 pool_size = CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces();
|
int32 pool_size = CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces();
|
||||||
*size = SAVE_HEADER_SIZE + pool_size * (sizeof(cAudioScriptObject) + sizeof(int32));
|
*size = SAVE_HEADER_SIZE + sizeof(int32) + pool_size * (sizeof(cAudioScriptObject) + sizeof(int32));
|
||||||
WriteSaveHeader(buf, 'A', 'U', 'D', '\0', *size - SAVE_HEADER_SIZE);
|
WriteSaveHeader(buf, 'A', 'U', 'D', '\0', *size - SAVE_HEADER_SIZE);
|
||||||
WriteSaveBuf(buf, pool_size);
|
WriteSaveBuf(buf, pool_size);
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,676 @@
|
||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "Cranes.h"
|
#include "Cranes.h"
|
||||||
|
|
||||||
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
|
#include "Camera.h"
|
||||||
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }
|
#include "DMAudio.h"
|
||||||
WRAPPER bool CCranes::IsThisCarPickedUp(float, float, CVehicle*) { EAXJMP(0x543940); }
|
#include "Garages.h"
|
||||||
WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); }
|
#include "General.h"
|
||||||
WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); }
|
#include "Entity.h"
|
||||||
WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); }
|
#include "ModelIndices.h"
|
||||||
WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); }
|
#include "Replay.h"
|
||||||
WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); }
|
#include "Object.h"
|
||||||
WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); }
|
#include "World.h"
|
||||||
WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); }
|
|
||||||
|
#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)
|
||||||
|
#define DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE (5.0f)
|
||||||
|
#define DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT (0.5f)
|
||||||
|
#define CAR_REWARD_MILITARY_CRANE (1500)
|
||||||
|
#define CAR_MOVING_SPEED_THRESHOLD (0.01f)
|
||||||
|
#define CRANE_SLOWDOWN_MULTIPLIER (0.3f)
|
||||||
|
|
||||||
|
#define OSCILLATION_SPEED (0.002f)
|
||||||
|
#define CAR_ROTATION_SPEED (0.0035f)
|
||||||
|
#define CRANE_MOVEMENT_SPEED (0.001f)
|
||||||
|
#define HOOK_ANGLE_MOVEMENT_SPEED (0.004f)
|
||||||
|
#define HOOK_OFFSET_MOVEMENT_SPEED (0.1f)
|
||||||
|
#define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f)
|
||||||
|
|
||||||
|
#define MESSAGE_SHOW_DURATION (4000)
|
||||||
|
|
||||||
|
#define MAX_DISTANCE (99999.9f)
|
||||||
|
#define MIN_VALID_POSITION (-10000.0f)
|
||||||
|
#define DEFAULT_OFFSET (20.0f)
|
||||||
|
|
||||||
|
uint32 TimerForCamInterpolation;
|
||||||
|
|
||||||
|
uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248;
|
||||||
|
int32& CCranes::NumCranes = *(int32*)0x8E28AC;
|
||||||
|
CCrane(&CCranes::aCranes)[NUM_CRANES] = *(CCrane(*)[NUM_CRANES])*(uintptr*)0x6FA4E0;
|
||||||
|
|
||||||
|
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 = 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_pCraneEntity = (CBuilding*)pEntity;
|
||||||
|
pCrane->m_nCraneStatus = CCrane::NONE;
|
||||||
|
pCrane->m_fHookAngle = NumCranes; // lol wtf
|
||||||
|
while (pCrane->m_fHookAngle > TWOPI)
|
||||||
|
pCrane->m_fHookAngle -= TWOPI;
|
||||||
|
pCrane->m_fHookOffset = DEFAULT_OFFSET;
|
||||||
|
pCrane->m_fHookHeight = DEFAULT_OFFSET;
|
||||||
|
pCrane->m_nTimeForNextCheck = 0;
|
||||||
|
pCrane->m_nCraneState = CCrane::IDLE;
|
||||||
|
pCrane->m_bWasMilitaryCrane = false;
|
||||||
|
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());
|
||||||
|
// Is this used to avoid military crane?
|
||||||
|
if (pCrane->m_bIsTop || pEntity->GetPosition().y > 0.0f) {
|
||||||
|
CObject* pHook = new CObject(MI_MAGNET, false);
|
||||||
|
pHook->ObjectCreatedBy = MISSION_OBJECT;
|
||||||
|
pHook->bUsesCollision = false;
|
||||||
|
pHook->bExplosionProof = true;
|
||||||
|
pHook->bAffectedByGravity = false;
|
||||||
|
pCrane->m_pHook = pHook;
|
||||||
|
pCrane->CalcHookCoordinates(&pCrane->m_vecHookCurPos.x, &pCrane->m_vecHookCurPos.y, &pCrane->m_vecHookCurPos.z);
|
||||||
|
pCrane->SetHookMatrix();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pCrane->m_pHook = 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 = MAX_DISTANCE;
|
||||||
|
float X = fPosX, Y = fPosY;
|
||||||
|
if (X <= MIN_VALID_POSITION || Y <= MIN_VALID_POSITION) {
|
||||||
|
X = fDropOffX;
|
||||||
|
Y = fDropOffY;
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < NumCranes; i++) {
|
||||||
|
float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();
|
||||||
|
if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
|
||||||
|
fMinDistance = distance;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef FIX_BUGS // classic
|
||||||
|
if (fMinDistance == MAX_DISTANCE)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
CCrane* pCrane = &aCranes[index];
|
||||||
|
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_nCraneStatus = CCrane::ACTIVATED;
|
||||||
|
pCrane->m_pVehiclePickedUp = nil;
|
||||||
|
pCrane->m_nVehiclesCollected = 0;
|
||||||
|
pCrane->m_fDropoffHeading = fHeading;
|
||||||
|
pCrane->m_bIsCrusher = bIsCrusher;
|
||||||
|
pCrane->m_bIsMilitaryCrane = bIsMilitary;
|
||||||
|
bool military = true;
|
||||||
|
if (!bIsMilitary && !pCrane->m_bWasMilitaryCrane)
|
||||||
|
military = false;
|
||||||
|
pCrane->m_bWasMilitaryCrane = military;
|
||||||
|
pCrane->m_nTimeForNextCheck = 0;
|
||||||
|
pCrane->m_nCraneState = CCrane::IDLE;
|
||||||
|
float Z;
|
||||||
|
if (bIsCrusher)
|
||||||
|
Z = CRUSHER_Z;
|
||||||
|
else if (bIsMilitary)
|
||||||
|
Z = MILITARY_Z;
|
||||||
|
else
|
||||||
|
Z = CWorld::FindGroundZForCoord((fInfX + fSupX) / 2, (fInfY + fSupY) / 2);
|
||||||
|
pCrane->FindParametersForTarget((fInfX + fSupX) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fPickupHeight);
|
||||||
|
pCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDropoffHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCranes::DeActivateCrane(float X, float Y)
|
||||||
|
{
|
||||||
|
float fMinDistance = MAX_DISTANCE;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < NumCranes; i++) {
|
||||||
|
float distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();
|
||||||
|
if (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {
|
||||||
|
fMinDistance = distance;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef FIX_BUGS // classic
|
||||||
|
if (fMinDistance == MAX_DISTANCE)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
aCranes[index].m_nCraneStatus = CCrane::DEACTIVATED;
|
||||||
|
aCranes[index].m_nCraneState = 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_pCraneEntity->GetPosition()).Magnitude();
|
||||||
|
if (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) {
|
||||||
|
if (aCranes[i].m_nCraneStatus == CCrane::LIFTING_TARGET || aCranes[i].m_nCraneStatus == 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_pCraneEntity->GetPosition().x &&
|
||||||
|
TheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().x &&
|
||||||
|
TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().y &&
|
||||||
|
TheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().y))
|
||||||
|
aCranes[i].Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCrane::Update(void)
|
||||||
|
{
|
||||||
|
if (CReplay::IsPlayingBack())
|
||||||
|
return;
|
||||||
|
if (((m_nCraneStatus == ACTIVATED || m_nCraneStatus == DEACTIVATED) &&
|
||||||
|
Abs(TheCamera.GetGameCamPosition().x - m_pCraneEntity->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS &&
|
||||||
|
Abs(TheCamera.GetGameCamPosition().y - m_pCraneEntity->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) ||
|
||||||
|
m_nCraneState != IDLE) {
|
||||||
|
switch (m_nCraneState) {
|
||||||
|
case IDLE:
|
||||||
|
if (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, GetHeightToPickup()) &&
|
||||||
|
CTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) {
|
||||||
|
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){
|
||||||
|
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) > CAR_MOVING_SPEED_THRESHOLD ||
|
||||||
|
Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > CAR_MOVING_SPEED_THRESHOLD ||
|
||||||
|
Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > CAR_MOVING_SPEED_THRESHOLD ||
|
||||||
|
FindPlayerPed()->GetPedState() == PED_ENTER_CAR && // TODO: fix carjack bug
|
||||||
|
FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) {
|
||||||
|
m_pVehiclePickedUp = nil;
|
||||||
|
m_nCraneState = IDLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float fAngle, fOffset, fHeight;
|
||||||
|
FindParametersForTarget(
|
||||||
|
m_pVehiclePickedUp->GetPosition().x,
|
||||||
|
m_pVehiclePickedUp->GetPosition().y,
|
||||||
|
m_pVehiclePickedUp->GetPosition().z + m_pVehiclePickedUp->GetColModel()->boundingBox.max.z,
|
||||||
|
&fAngle, &fOffset, &fHeight);
|
||||||
|
if (GoTowardsTarget(fAngle, fOffset, fHeight)) {
|
||||||
|
CVector distance = m_pVehiclePickedUp->GetPosition() - m_vecHookCurPos;
|
||||||
|
distance.z += m_pVehiclePickedUp->GetColModel()->boundingBox.max.z;
|
||||||
|
if (distance.MagnitudeSqr() < SQR(DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT)) {
|
||||||
|
m_nCraneState = GOING_TOWARDS_TARGET_ONLY_HEIGHT;
|
||||||
|
m_vecHookVelocity *= 0.4f;
|
||||||
|
m_pVehiclePickedUp->bLightsOn = false;
|
||||||
|
m_pVehiclePickedUp->bUsesCollision = false;
|
||||||
|
if (m_bIsCrusher)
|
||||||
|
m_pVehiclePickedUp->bCollisionProof = true;
|
||||||
|
DMAudio.PlayOneShot(m_nAudioEntity, SOUND_CRANE_PICKUP, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_nCraneState = IDLE;
|
||||||
|
break;
|
||||||
|
case LIFTING_TARGET:
|
||||||
|
RotateCarriedCarProperly();
|
||||||
|
if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), CRANE_SLOWDOWN_MULTIPLIER))
|
||||||
|
m_nCraneState = ROTATING_TARGET;
|
||||||
|
if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {
|
||||||
|
m_pVehiclePickedUp = nil;
|
||||||
|
m_nCraneState = IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GOING_TOWARDS_TARGET_ONLY_HEIGHT:
|
||||||
|
RotateCarriedCarProperly();
|
||||||
|
if (GoTowardsHeightTarget(GetHeightToPickupHeight(), CRANE_SLOWDOWN_MULTIPLIER))
|
||||||
|
m_nCraneState = LIFTING_TARGET;
|
||||||
|
TimerForCamInterpolation = CTimer::GetTimeInMilliseconds();
|
||||||
|
if (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {
|
||||||
|
m_pVehiclePickedUp = nil;
|
||||||
|
m_nCraneState = IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ROTATING_TARGET:
|
||||||
|
{
|
||||||
|
bool bRotateFinished = RotateCarriedCarProperly();
|
||||||
|
bool bMovementFinished = GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, m_fDropoffHeight, 0.3f);
|
||||||
|
if (bMovementFinished && bRotateFinished) {
|
||||||
|
float fDistanceFromPlayer = m_pVehiclePickedUp ? ((CVector2D)FindPlayerCoors() - (CVector2D)m_pVehiclePickedUp->GetPosition()).Magnitude() : 0.0f;
|
||||||
|
if (fDistanceFromPlayer > DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE || !m_bWasMilitaryCrane) {
|
||||||
|
m_nCraneState = DROPPING_TARGET;
|
||||||
|
if (m_pVehiclePickedUp) {
|
||||||
|
m_pVehiclePickedUp->bUsesCollision = true;
|
||||||
|
m_pVehiclePickedUp->m_nStaticFrames = 0;
|
||||||
|
++m_nVehiclesCollected;
|
||||||
|
if (m_bIsMilitaryCrane) {
|
||||||
|
CCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex());
|
||||||
|
if (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) {
|
||||||
|
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE;
|
||||||
|
CGarages::TriggerMessage("GA_10", CAR_REWARD_MILITARY_CRANE, MESSAGE_SHOW_DURATION, -1);
|
||||||
|
}
|
||||||
|
CWorld::Remove(m_pVehiclePickedUp);
|
||||||
|
delete m_pVehiclePickedUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_pVehiclePickedUp = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DROPPING_TARGET:
|
||||||
|
if (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoffHeight(), CRANE_SLOWDOWN_MULTIPLIER)) {
|
||||||
|
m_nCraneState = IDLE;
|
||||||
|
m_nTimeForNextCheck = CTimer::GetTimeInMilliseconds() + 10000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CVector vecHook;
|
||||||
|
CalcHookCoordinates(&vecHook.x, &vecHook.y, &vecHook.z);
|
||||||
|
m_vecHookVelocity += ((CVector2D)vecHook - (CVector2D)m_vecHookCurPos) * CTimer::GetTimeStep() * CRANE_MOVEMENT_SPEED;
|
||||||
|
m_vecHookVelocity *= Pow(0.98f, CTimer::GetTimeStep());
|
||||||
|
m_vecHookCurPos.x += m_vecHookVelocity.x * CTimer::GetTimeStep();
|
||||||
|
m_vecHookCurPos.y += m_vecHookVelocity.y * CTimer::GetTimeStep();
|
||||||
|
m_vecHookCurPos.z = vecHook.z;
|
||||||
|
switch (m_nCraneState) {
|
||||||
|
case LIFTING_TARGET:
|
||||||
|
case GOING_TOWARDS_TARGET_ONLY_HEIGHT:
|
||||||
|
case ROTATING_TARGET:
|
||||||
|
if (m_pVehiclePickedUp) {
|
||||||
|
m_pVehiclePickedUp->GetPosition() = CVector(m_vecHookCurPos.x, m_vecHookCurPos.y, m_vecHookCurPos.z - m_pVehiclePickedUp->GetColModel()->boundingBox.max.z);
|
||||||
|
m_pVehiclePickedUp->SetMoveSpeed(0.0f, 0.0f, 0.0f);
|
||||||
|
CVector up(vecHook.x - m_vecHookCurPos.x, vecHook.y - m_vecHookCurPos.y, 20.0f);
|
||||||
|
up.Normalise();
|
||||||
|
m_pVehiclePickedUp->GetRight() = CrossProduct(m_pVehiclePickedUp->GetForward(), up);
|
||||||
|
m_pVehiclePickedUp->GetForward() = CrossProduct(up, m_pVehiclePickedUp->GetRight());
|
||||||
|
m_pVehiclePickedUp->GetUp() = up;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int16 rnd = (m_pCraneEntity->m_randomSeed + (CTimer::GetTimeInMilliseconds() >> 11)) & 0xF;
|
||||||
|
// 16 options, lasting 2048 ms each
|
||||||
|
// a bit awkward: why there are 4 periods for -= and 6 for +=? is it a bug?
|
||||||
|
if (rnd < 4) {
|
||||||
|
m_fHookAngle -= OSCILLATION_SPEED * CTimer::GetTimeStep();
|
||||||
|
if (m_fHookAngle < 0.0f)
|
||||||
|
m_fHookAngle += TWOPI;
|
||||||
|
}
|
||||||
|
else if (rnd > 5 && rnd < 12) {
|
||||||
|
m_fHookAngle += OSCILLATION_SPEED * CTimer::GetTimeStep();
|
||||||
|
if (m_fHookAngle > TWOPI)
|
||||||
|
m_fHookAngle -= TWOPI;
|
||||||
|
}
|
||||||
|
CalcHookCoordinates(&m_vecHookCurPos.x, &m_vecHookCurPos.y, &m_vecHookCurPos.z);
|
||||||
|
m_vecHookVelocity.x = m_vecHookVelocity.y = 0.0f;
|
||||||
|
}
|
||||||
|
float fCos = Cos(m_fHookAngle);
|
||||||
|
float fSin = Sin(m_fHookAngle);
|
||||||
|
m_pCraneEntity->GetRight().x = fCos;
|
||||||
|
m_pCraneEntity->GetForward().y = fCos;
|
||||||
|
m_pCraneEntity->GetRight().y = fSin;
|
||||||
|
m_pCraneEntity->GetForward().x = -fSin;
|
||||||
|
m_pCraneEntity->GetMatrix().UpdateRW();
|
||||||
|
m_pCraneEntity->UpdateRwFrame();
|
||||||
|
SetHookMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrane::RotateCarriedCarProperly()
|
||||||
|
{
|
||||||
|
if (m_fDropoffHeading <= 0.0f)
|
||||||
|
return true;
|
||||||
|
if (!m_pVehiclePickedUp)
|
||||||
|
return true;
|
||||||
|
float fAngleDelta = m_fDropoffHeading - CGeneral::GetATanOfXY(m_pVehiclePickedUp->GetForward().x, m_pVehiclePickedUp->GetForward().y);
|
||||||
|
while (fAngleDelta < -HALFPI)
|
||||||
|
fAngleDelta += PI;
|
||||||
|
while (fAngleDelta > HALFPI)
|
||||||
|
fAngleDelta -= PI;
|
||||||
|
float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep();
|
||||||
|
if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied?
|
||||||
|
return true;
|
||||||
|
m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCrane::FindCarInSectorList(CPtrList* pList)
|
||||||
|
{
|
||||||
|
CPtrNode* node;
|
||||||
|
for (node = pList->first; node; node = node->next) {
|
||||||
|
CVehicle* pVehicle = (CVehicle*)node->item;
|
||||||
|
if (pVehicle->m_scanCode == CWorld::GetCurrentScanCode())
|
||||||
|
continue;
|
||||||
|
pVehicle->m_scanCode = CWorld::GetCurrentScanCode();
|
||||||
|
if (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 ||
|
||||||
|
pVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2)
|
||||||
|
continue;
|
||||||
|
if (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD ||
|
||||||
|
Abs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD ||
|
||||||
|
Abs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD)
|
||||||
|
continue;
|
||||||
|
if (!pVehicle->IsCar() || pVehicle->m_status == STATUS_WRECKED || pVehicle->m_fHealth < 250.0f)
|
||||||
|
continue;
|
||||||
|
if (!DoesCranePickUpThisCarType(pVehicle->GetModelIndex()) ||
|
||||||
|
m_bIsMilitaryCrane && CCranes::DoesMilitaryCraneHaveThisOneAlready(pVehicle->GetModelIndex())) {
|
||||||
|
if (!pVehicle->bCraneMessageDone) {
|
||||||
|
pVehicle->bCraneMessageDone = true;
|
||||||
|
if (!m_bIsMilitaryCrane)
|
||||||
|
CGarages::TriggerMessage("CR_1", -1, MESSAGE_SHOW_DURATION, -1); // Crane cannot lift this vehicle.
|
||||||
|
else if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex()))
|
||||||
|
CGarages::TriggerMessage("GA_20", -1, MESSAGE_SHOW_DURATION, -1); // We got more of these than we can shift. Sorry man, no deal.
|
||||||
|
else
|
||||||
|
CGarages::TriggerMessage("GA_19", -1, MESSAGE_SHOW_DURATION, -1); // We're not interested in that model.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_pVehiclePickedUp = pVehicle;
|
||||||
|
pVehicle->RegisterReference((CEntity**)&m_pVehiclePickedUp);
|
||||||
|
m_nCraneState = GOING_TOWARDS_TARGET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrane::DoesCranePickUpThisCarType(uint32 mi)
|
||||||
|
{
|
||||||
|
if (m_bIsCrusher) {
|
||||||
|
return mi != MI_FIRETRUCK &&
|
||||||
|
mi != MI_TRASH &&
|
||||||
|
#ifndef FIX_BUGS // why
|
||||||
|
mi != MI_BLISTA &&
|
||||||
|
#endif
|
||||||
|
mi != MI_SECURICA &&
|
||||||
|
mi != MI_BUS &&
|
||||||
|
mi != MI_DODO &&
|
||||||
|
mi != MI_RHINO;
|
||||||
|
}
|
||||||
|
if (m_bIsMilitaryCrane) {
|
||||||
|
return mi == MI_FIRETRUCK ||
|
||||||
|
mi == MI_AMBULAN ||
|
||||||
|
mi == MI_ENFORCER ||
|
||||||
|
mi == MI_FBICAR ||
|
||||||
|
mi == MI_RHINO ||
|
||||||
|
mi == MI_BARRACKS ||
|
||||||
|
mi == MI_POLICE;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi)
|
||||||
|
{
|
||||||
|
switch (mi) {
|
||||||
|
case MI_FIRETRUCK: return (CCranes::CarsCollectedMilitaryCrane & 1);
|
||||||
|
case MI_AMBULAN: return (CCranes::CarsCollectedMilitaryCrane & 2);
|
||||||
|
case MI_ENFORCER: return (CCranes::CarsCollectedMilitaryCrane & 4);
|
||||||
|
case MI_FBICAR: return (CCranes::CarsCollectedMilitaryCrane & 8);
|
||||||
|
case MI_RHINO: return (CCranes::CarsCollectedMilitaryCrane & 0x10);
|
||||||
|
case MI_BARRACKS: return (CCranes::CarsCollectedMilitaryCrane & 0x20);
|
||||||
|
case MI_POLICE: return (CCranes::CarsCollectedMilitaryCrane & 0x40);
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCranes::RegisterCarForMilitaryCrane(uint32 mi)
|
||||||
|
{
|
||||||
|
switch (mi) {
|
||||||
|
case MI_FIRETRUCK: CCranes::CarsCollectedMilitaryCrane |= 1; break;
|
||||||
|
case MI_AMBULAN: CCranes::CarsCollectedMilitaryCrane |= 2; break;
|
||||||
|
case MI_ENFORCER: CCranes::CarsCollectedMilitaryCrane |= 4; break;
|
||||||
|
case MI_FBICAR: CCranes::CarsCollectedMilitaryCrane |= 8; break;
|
||||||
|
case MI_RHINO: CCranes::CarsCollectedMilitaryCrane |= 0x10; break;
|
||||||
|
case MI_BARRACKS: CCranes::CarsCollectedMilitaryCrane |= 0x20; break;
|
||||||
|
case MI_POLICE: CCranes::CarsCollectedMilitaryCrane |= 0x40; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()
|
||||||
|
{
|
||||||
|
return (CCranes::CarsCollectedMilitaryCrane & 0x7F) == 0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier)
|
||||||
|
{
|
||||||
|
bool bAngleMovementFinished, bOffsetMovementFinished, bHeightMovementFinished;
|
||||||
|
float fHookAngleDelta = fAngleToTarget - m_fHookAngle;
|
||||||
|
while (fHookAngleDelta > PI)
|
||||||
|
fHookAngleDelta -= TWOPI;
|
||||||
|
while (fHookAngleDelta < -PI)
|
||||||
|
fHookAngleDelta += TWOPI;
|
||||||
|
float fHookAngleChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_ANGLE_MOVEMENT_SPEED;
|
||||||
|
if (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) {
|
||||||
|
m_fHookAngle = fAngleToTarget;
|
||||||
|
bAngleMovementFinished = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fHookAngleDelta < 0.0f) {
|
||||||
|
m_fHookAngle -= fHookAngleChangeThisFrame;
|
||||||
|
if (m_fHookAngle < 0.0f)
|
||||||
|
m_fHookAngle += TWOPI;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_fHookAngle += fHookAngleChangeThisFrame;
|
||||||
|
if (m_fHookAngle > TWOPI)
|
||||||
|
m_fHookAngle -= TWOPI;
|
||||||
|
}
|
||||||
|
bAngleMovementFinished = false;
|
||||||
|
}
|
||||||
|
float fHookOffsetDelta = fDistanceToTarget - m_fHookOffset;
|
||||||
|
float fHookOffsetChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_OFFSET_MOVEMENT_SPEED;
|
||||||
|
if (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) {
|
||||||
|
m_fHookOffset = fDistanceToTarget;
|
||||||
|
bOffsetMovementFinished = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fHookOffsetDelta < 0.0f)
|
||||||
|
m_fHookOffset -= fHookOffsetChangeThisFrame;
|
||||||
|
else
|
||||||
|
m_fHookOffset += fHookOffsetChangeThisFrame;
|
||||||
|
bOffsetMovementFinished = false;
|
||||||
|
}
|
||||||
|
float fHookHeightDelta = fTargetHeight - m_fHookHeight;
|
||||||
|
float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;
|
||||||
|
if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
|
||||||
|
m_fHookHeight = fTargetHeight;
|
||||||
|
bHeightMovementFinished = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fHookHeightDelta < 0.0f)
|
||||||
|
m_fHookHeight -= fHookHeightChangeThisFrame;
|
||||||
|
else
|
||||||
|
m_fHookHeight += fHookHeightChangeThisFrame;
|
||||||
|
bHeightMovementFinished = false;
|
||||||
|
}
|
||||||
|
return bAngleMovementFinished && bOffsetMovementFinished && bHeightMovementFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier)
|
||||||
|
{
|
||||||
|
bool bHeightMovementFinished;
|
||||||
|
float fHookHeightDelta = fTargetHeight - m_fHookHeight;
|
||||||
|
float fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;
|
||||||
|
if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
|
||||||
|
m_fHookHeight = fTargetHeight;
|
||||||
|
bHeightMovementFinished = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fHookHeightDelta < 0.0f)
|
||||||
|
m_fHookHeight -= fHookHeightChangeThisFrame;
|
||||||
|
else
|
||||||
|
m_fHookHeight += fHookHeightChangeThisFrame;
|
||||||
|
bHeightMovementFinished = false;
|
||||||
|
}
|
||||||
|
return bHeightMovementFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCrane::FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight)
|
||||||
|
{
|
||||||
|
*pAngle = CGeneral::GetATanOfXY(X - m_pCraneEntity->GetPosition().x, Y - m_pCraneEntity->GetPosition().y);
|
||||||
|
*pDistance = ((CVector2D(X, Y) - (CVector2D)m_pCraneEntity->GetPosition())).Magnitude();
|
||||||
|
*pHeight = Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ)
|
||||||
|
{
|
||||||
|
*pX = Cos(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().x;
|
||||||
|
*pY = Sin(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().y;
|
||||||
|
*pZ = m_fHookHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCrane::SetHookMatrix()
|
||||||
|
{
|
||||||
|
if (!m_pHook)
|
||||||
|
return;
|
||||||
|
m_pHook->GetPosition() = m_vecHookCurPos;
|
||||||
|
CVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f);
|
||||||
|
up.Normalise();
|
||||||
|
m_pHook->GetRight() = CrossProduct(CVector(0.0f, 1.0f, 0.0f), up);
|
||||||
|
m_pHook->GetForward() = CrossProduct(up, m_pHook->GetRight());
|
||||||
|
m_pHook->GetUp() = up;
|
||||||
|
m_pHook->SetOrientation(0.0f, 0.0f, -HALFPI);
|
||||||
|
m_pHook->GetMatrix().UpdateRW();
|
||||||
|
m_pHook->UpdateRwFrame();
|
||||||
|
CWorld::Remove(m_pHook);
|
||||||
|
CWorld::Add(m_pHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NumCranes; i++) {
|
||||||
|
if (pVehicle == aCranes[i].m_pVehiclePickedUp) {
|
||||||
|
switch (aCranes[i].m_nCraneState) {
|
||||||
|
case CCrane::GOING_TOWARDS_TARGET_ONLY_HEIGHT:
|
||||||
|
case CCrane::LIFTING_TARGET:
|
||||||
|
case CCrane::ROTATING_TARGET:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NumCranes; i++) {
|
||||||
|
if (pVehicle == aCranes[i].m_pVehiclePickedUp)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCranes::Save(uint8* buf, uint32* size)
|
||||||
|
{
|
||||||
|
INITSAVEBUF
|
||||||
|
|
||||||
|
*size = 2 * sizeof(uint32) + NUM_CRANES * sizeof(CCrane);
|
||||||
|
WriteSaveBuf(buf, NumCranes);
|
||||||
|
WriteSaveBuf(buf, CarsCollectedMilitaryCrane);
|
||||||
|
for (int i = 0; i < NUM_CRANES; i++) {
|
||||||
|
CCrane* pCrane = WriteSaveBuf(buf, aCranes[i]);
|
||||||
|
if (pCrane->m_pCraneEntity)
|
||||||
|
pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pCrane->m_pCraneEntity) + 1);
|
||||||
|
if (pCrane->m_pHook)
|
||||||
|
pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex((CObject*)pCrane->m_pHook) + 1);
|
||||||
|
if (pCrane->m_pVehiclePickedUp)
|
||||||
|
pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex((CVehicle*)pCrane->m_pVehiclePickedUp) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALIDATESAVEBUF(*size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CranesLoad(uint8* buf, uint32 size)
|
||||||
|
{
|
||||||
|
INITSAVEBUF
|
||||||
|
|
||||||
|
CCranes::NumCranes = ReadSaveBuf<int32>(buf);
|
||||||
|
CCranes::CarsCollectedMilitaryCrane = ReadSaveBuf<uint32>(buf);
|
||||||
|
for (int i = 0; i < NUM_CRANES; i++)
|
||||||
|
CCranes::aCranes[i] = ReadSaveBuf<CCrane>(buf);
|
||||||
|
for (int i = 0; i < NUM_CRANES; i++) {
|
||||||
|
CCrane* pCrane = &CCranes::aCranes[i];
|
||||||
|
if (pCrane->m_pCraneEntity)
|
||||||
|
pCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uint32)pCrane->m_pCraneEntity - 1);
|
||||||
|
if (pCrane->m_pHook)
|
||||||
|
pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uint32)pCrane->m_pHook - 1);
|
||||||
|
if (pCrane->m_pVehiclePickedUp)
|
||||||
|
pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp + 1);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NUM_CRANES; i++) {
|
||||||
|
CCranes::aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &CCranes::aCranes[i]);
|
||||||
|
if (CCranes::aCranes[i].m_nAudioEntity)
|
||||||
|
DMAudio.SetEntityStatus(CCranes::aCranes[i].m_nAudioEntity, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALIDATESAVEBUF(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad
|
||||||
|
ENDPATCHES
|
|
@ -1,16 +1,32 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
class CVehicle;
|
class CVehicle;
|
||||||
class CEntity;
|
class CEntity;
|
||||||
class CObject;
|
class CObject;
|
||||||
|
class CBuilding;
|
||||||
|
|
||||||
class CCrane
|
class CCrane
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CEntity *m_pObject;
|
enum CraneState : uint8 {
|
||||||
CObject *m_pMagnet;
|
IDLE = 0,
|
||||||
int m_nAudioEntity;
|
GOING_TOWARDS_TARGET = 1,
|
||||||
|
LIFTING_TARGET = 2,
|
||||||
|
GOING_TOWARDS_TARGET_ONLY_HEIGHT = 3,
|
||||||
|
ROTATING_TARGET = 4,
|
||||||
|
DROPPING_TARGET = 5
|
||||||
|
};
|
||||||
|
enum CraneStatus : uint8 {
|
||||||
|
NONE = 0,
|
||||||
|
ACTIVATED = 1,
|
||||||
|
DEACTIVATED = 2
|
||||||
|
};
|
||||||
|
CBuilding *m_pCraneEntity;
|
||||||
|
CObject *m_pHook;
|
||||||
|
int32 m_nAudioEntity;
|
||||||
float m_fPickupX1;
|
float m_fPickupX1;
|
||||||
float m_fPickupX2;
|
float m_fPickupX2;
|
||||||
float m_fPickupY1;
|
float m_fPickupY1;
|
||||||
|
@ -21,25 +37,39 @@ public:
|
||||||
float m_fDropoffAngle;
|
float m_fDropoffAngle;
|
||||||
float m_fPickupDistance;
|
float m_fPickupDistance;
|
||||||
float m_fDropoffDistance;
|
float m_fDropoffDistance;
|
||||||
float m_fAngle;
|
float m_fPickupHeight;
|
||||||
float m_fDistance;
|
float m_fDropoffHeight;
|
||||||
float m_fHeight;
|
float m_fHookAngle;
|
||||||
float m_fHookOffset;
|
float m_fHookOffset;
|
||||||
float m_fHookHeight;
|
float m_fHookHeight;
|
||||||
CVector m_vecHookInitPos;
|
CVector m_vecHookInitPos;
|
||||||
CVector m_vecHookCurPos;
|
CVector m_vecHookCurPos;
|
||||||
float m_fHookVelocityX;
|
CVector2D m_vecHookVelocity;
|
||||||
float m_fHookVelocityY;
|
|
||||||
CVehicle *m_pVehiclePickedUp;
|
CVehicle *m_pVehiclePickedUp;
|
||||||
int m_nUpdateTimer;
|
uint32 m_nTimeForNextCheck;
|
||||||
char m_bCraneActive;
|
CraneStatus m_nCraneStatus;
|
||||||
char m_bCraneStatus;
|
CraneState m_nCraneState;
|
||||||
char m_bVehiclesCollected;
|
uint8 m_nVehiclesCollected;
|
||||||
char m_bIsCrusher;
|
bool m_bIsCrusher;
|
||||||
char m_bIsMilitaryCrane;
|
bool m_bIsMilitaryCrane;
|
||||||
char field_125;
|
bool m_bWasMilitaryCrane;
|
||||||
char m_bNotMilitaryCrane;
|
bool m_bIsTop;
|
||||||
char gap_127[1];
|
|
||||||
|
void Init(void) { memset(this, 0, sizeof(*this)); }
|
||||||
|
void Update(void);
|
||||||
|
bool RotateCarriedCarProperly(void);
|
||||||
|
void FindCarInSectorList(CPtrList* pList);
|
||||||
|
bool DoesCranePickUpThisCarType(uint32 mi);
|
||||||
|
bool GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier = 1.0f);
|
||||||
|
bool GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier = 1.0f);
|
||||||
|
void FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight);
|
||||||
|
void CalcHookCoordinates(float* pX, float* pY, float* pZ);
|
||||||
|
void SetHookMatrix(void);
|
||||||
|
|
||||||
|
float GetHeightToPickup() { return 4.0f + m_fPickupHeight + (m_bIsCrusher ? 4.5f : 0.0f); };
|
||||||
|
float GetHeightToDropoff() { return m_bIsCrusher ? (2.0f + m_fDropoffHeight + 3.0f) : (2.0f + m_fDropoffHeight); }
|
||||||
|
float GetHeightToPickupHeight() { return m_fPickupHeight + (m_bIsCrusher ? 7.0f : 4.0f); }
|
||||||
|
float GetHeightToDropoffHeight() { return m_fDropoffHeight + (m_bIsCrusher ? 7.0f : 2.0f); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(CCrane) == 128, "CCrane: error");
|
static_assert(sizeof(CCrane) == 128, "CCrane: error");
|
||||||
|
@ -47,15 +77,22 @@ static_assert(sizeof(CCrane) == 128, "CCrane: error");
|
||||||
class CCranes
|
class CCranes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*);
|
|
||||||
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*);
|
|
||||||
static bool IsThisCarPickedUp(float, float, CVehicle*);
|
|
||||||
static bool HaveAllCarsBeenCollectedByMilitaryCrane();
|
|
||||||
static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float);
|
|
||||||
static void DeActivateCrane(float, float);
|
|
||||||
static void InitCranes(void);
|
static void InitCranes(void);
|
||||||
|
static void AddThisOneCrane(CEntity* pCraneEntity);
|
||||||
|
static void 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);
|
||||||
|
static void DeActivateCrane(float fX, float fY);
|
||||||
|
static bool IsThisCarPickedUp(float fX, float fY, CVehicle* pVehicle);
|
||||||
static void UpdateCranes(void);
|
static void UpdateCranes(void);
|
||||||
static void Save(uint8*, uint32*);
|
static bool DoesMilitaryCraneHaveThisOneAlready(uint32 mi);
|
||||||
|
static void RegisterCarForMilitaryCrane(uint32 mi);
|
||||||
|
static bool HaveAllCarsBeenCollectedByMilitaryCrane(void);
|
||||||
|
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle);
|
||||||
|
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle);
|
||||||
|
static void Save(uint8* buf, uint32* size);
|
||||||
|
|
||||||
|
static uint32& CarsCollectedMilitaryCrane;
|
||||||
|
static int32& NumCranes;
|
||||||
|
static CCrane(&aCranes)[NUM_CRANES];
|
||||||
};
|
};
|
||||||
|
|
||||||
void CranesLoad(uint8*, uint32); // is this really outside CCranes?
|
void CranesLoad(uint8*, uint32); // is this really outside CCranes?
|
||||||
|
|
|
@ -126,7 +126,6 @@ uint32& CGarages::MessageEndTime = *(uint32*)0x8F597C;
|
||||||
uint32& CGarages::NumGarages = *(uint32*)0x8F29F4;
|
uint32& CGarages::NumGarages = *(uint32*)0x8F29F4;
|
||||||
bool& CGarages::PlayerInGarage = *(bool*)0x95CD83;
|
bool& CGarages::PlayerInGarage = *(bool*)0x95CD83;
|
||||||
int32& CGarages::PoliceCarsCollected = *(int32*)0x941444;
|
int32& CGarages::PoliceCarsCollected = *(int32*)0x941444;
|
||||||
uint32& CGarages::GarageToBeTidied = *(uint32*)0x623570;
|
|
||||||
CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210;
|
CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210;
|
||||||
CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300;
|
CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300;
|
||||||
CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0;
|
CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0;
|
||||||
|
@ -322,6 +321,9 @@ void CGarage::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)
|
if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)
|
||||||
|
@ -408,11 +410,11 @@ void CGarage::Update()
|
||||||
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
|
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
|
||||||
uint8 colour1, colour2;
|
uint8 colour1, colour2;
|
||||||
uint16 attempt;
|
uint16 attempt;
|
||||||
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2);
|
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
|
||||||
for (attempt = 0; attempt < 10; attempt++) {
|
for (attempt = 0; attempt < 10; attempt++) {
|
||||||
if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2)
|
if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2)
|
||||||
break;
|
break;
|
||||||
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2);
|
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
|
||||||
}
|
}
|
||||||
bChangedColour = (attempt < 10);
|
bChangedColour = (attempt < 10);
|
||||||
FindPlayerVehicle()->m_currentColour1 = colour1;
|
FindPlayerVehicle()->m_currentColour1 = colour1;
|
||||||
|
@ -490,7 +492,7 @@ void CGarage::Update()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) {
|
if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) {
|
||||||
CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each"
|
CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" - weird that the price is hardcoded in message
|
||||||
m_eGarageState = GS_OPENEDCONTAINSCAR;
|
m_eGarageState = GS_OPENEDCONTAINSCAR;
|
||||||
DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);
|
DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -524,7 +526,7 @@ void CGarage::Update()
|
||||||
((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
|
((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
|
||||||
if (m_eGarageType == GARAGE_BOMBSHOP3)
|
if (m_eGarageType == GARAGE_BOMBSHOP3)
|
||||||
CGarages::GivePlayerDetonator();
|
CGarages::GivePlayerDetonator();
|
||||||
CStats::KgOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
|
CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
|
||||||
}
|
}
|
||||||
switch (m_eGarageType) {
|
switch (m_eGarageType) {
|
||||||
case GARAGE_BOMBSHOP1:
|
case GARAGE_BOMBSHOP1:
|
||||||
|
@ -1184,7 +1186,7 @@ bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
|
||||||
if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
|
if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
|
||||||
pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
|
pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
|
||||||
return false;
|
return false;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pEntity->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1201,7 +1203,7 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
|
||||||
pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
|
pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
|
||||||
pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
|
pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
|
||||||
return false;
|
return false;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pEntity->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1218,7 +1220,7 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
|
||||||
if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
|
if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
|
||||||
pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
|
pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
|
||||||
return false;
|
return false;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pEntity->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1250,7 +1252,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
|
||||||
pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
|
pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
|
||||||
pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
|
pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
|
||||||
return false;
|
return false;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pEntity->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||||
radius = pColModel->spheres[i].radius;
|
radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1264,7 +1266,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
|
||||||
|
|
||||||
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
|
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
|
||||||
{
|
{
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pEntity->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1285,7 +1287,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
|
||||||
continue;
|
continue;
|
||||||
if (!IsEntityTouching3D(pVehicle))
|
if (!IsEntityTouching3D(pVehicle))
|
||||||
continue;
|
continue;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pVehicle->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1307,7 +1309,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
|
||||||
continue;
|
continue;
|
||||||
if (!IsEntityTouching3D(pPed))
|
if (!IsEntityTouching3D(pPed))
|
||||||
continue;
|
continue;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pException->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1329,7 +1331,7 @@ bool CGarage::IsAnyCarBlockingDoor()
|
||||||
continue;
|
continue;
|
||||||
if (!IsEntityTouching3D(pVehicle))
|
if (!IsEntityTouching3D(pVehicle))
|
||||||
continue;
|
continue;
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pVehicle->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -1698,8 +1700,8 @@ float CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y)
|
||||||
|
|
||||||
void CGarage::FindDoorsEntities()
|
void CGarage::FindDoorsEntities()
|
||||||
{
|
{
|
||||||
m_pDoor1 = false;
|
m_pDoor1 = nil;
|
||||||
m_pDoor2 = false;
|
m_pDoor2 = nil;
|
||||||
int xstart = max(0, CWorld::GetSectorIndexX(m_fX1));
|
int xstart = max(0, CWorld::GetSectorIndexX(m_fX1));
|
||||||
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
|
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
|
||||||
int ystart = max(0, CWorld::GetSectorIndexY(m_fY1));
|
int ystart = max(0, CWorld::GetSectorIndexY(m_fY1));
|
||||||
|
@ -1992,7 +1994,7 @@ void CGarage::TidyUpGarageClose()
|
||||||
continue;
|
continue;
|
||||||
bool bRemove = false;
|
bool bRemove = false;
|
||||||
if (m_eGarageState != GS_FULLYCLOSED) {
|
if (m_eGarageState != GS_FULLYCLOSED) {
|
||||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
CColModel* pColModel = pVehicle->GetColModel();
|
||||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||||
float radius = pColModel->spheres[i].radius;
|
float radius = pColModel->spheres[i].radius;
|
||||||
|
@ -2227,6 +2229,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
|
||||||
void CGarages::Save(uint8 * buf, uint32 * size)
|
void CGarages::Save(uint8 * buf, uint32 * size)
|
||||||
{
|
{
|
||||||
#ifdef FIX_GARAGE_SIZE
|
#ifdef FIX_GARAGE_SIZE
|
||||||
|
INITSAVEBUF
|
||||||
*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||||
#else
|
#else
|
||||||
* size = 5484;
|
* size = 5484;
|
||||||
|
@ -2248,6 +2251,9 @@ void CGarages::Save(uint8 * buf, uint32 * size)
|
||||||
}
|
}
|
||||||
for (int i = 0; i < NUM_GARAGES; i++)
|
for (int i = 0; i < NUM_GARAGES; i++)
|
||||||
WriteSaveBuf(buf, aGarages[i]);
|
WriteSaveBuf(buf, aGarages[i]);
|
||||||
|
#ifdef FIX_GARAGE_SIZE
|
||||||
|
VALIDATESAVEBUF(*size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CStoredCar::CStoredCar(const CStoredCar & other)
|
CStoredCar::CStoredCar(const CStoredCar & other)
|
||||||
|
@ -2271,6 +2277,7 @@ CStoredCar::CStoredCar(const CStoredCar & other)
|
||||||
void CGarages::Load(uint8* buf, uint32 size)
|
void CGarages::Load(uint8* buf, uint32 size)
|
||||||
{
|
{
|
||||||
#ifdef FIX_GARAGE_SIZE
|
#ifdef FIX_GARAGE_SIZE
|
||||||
|
INITSAVEBUF
|
||||||
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||||
#else
|
#else
|
||||||
assert(size == 5484);
|
assert(size == 5484);
|
||||||
|
@ -2303,6 +2310,9 @@ void CGarages::Load(uint8* buf, uint32 size)
|
||||||
else
|
else
|
||||||
aGarages[i].UpdateDoorsHeight();
|
aGarages[i].UpdateDoorsHeight();
|
||||||
}
|
}
|
||||||
|
#ifdef FIX_GARAGE_SIZE
|
||||||
|
VALIDATESAVEBUF(size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2345,7 +2355,6 @@ CGarages::IsModelIndexADoor(uint32 id)
|
||||||
|
|
||||||
|
|
||||||
STARTPATCHES
|
STARTPATCHES
|
||||||
InjectHook(0x426B20, CGarages::TriggerMessage, PATCH_JUMP); // CCrane::Update, CCrane::FindCarInSectorList
|
|
||||||
InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl
|
InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl
|
||||||
InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl
|
InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl
|
||||||
InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad
|
InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad
|
||||||
|
|
|
@ -194,7 +194,6 @@ class CGarages
|
||||||
static uint32 &NumGarages;
|
static uint32 &NumGarages;
|
||||||
static bool &PlayerInGarage;
|
static bool &PlayerInGarage;
|
||||||
static int32 &PoliceCarsCollected;
|
static int32 &PoliceCarsCollected;
|
||||||
static uint32 &GarageToBeTidied;
|
|
||||||
static CGarage(&aGarages)[NUM_GARAGES];
|
static CGarage(&aGarages)[NUM_GARAGES];
|
||||||
static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS];
|
static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS];
|
||||||
static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS];
|
static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS];
|
||||||
|
|
|
@ -2229,6 +2229,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
|
||||||
if (pos.z <= -100)
|
if (pos.z <= -100)
|
||||||
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
|
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
|
||||||
UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3]));
|
UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3]));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
case COMMAND_DEBUG_ON:
|
case COMMAND_DEBUG_ON:
|
||||||
CTheScripts::DbgFlag = true;
|
CTheScripts::DbgFlag = true;
|
||||||
|
@ -7657,13 +7658,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
|
||||||
assert(pObject);
|
assert(pObject);
|
||||||
if (ScriptParams[1]) {
|
if (ScriptParams[1]) {
|
||||||
if (pObject->bIsStatic) {
|
if (pObject->bIsStatic) {
|
||||||
pObject->bIsStatic = true;
|
pObject->bIsStatic = false;
|
||||||
pObject->AddToMovingList();
|
pObject->AddToMovingList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!pObject->bIsStatic) {
|
if (!pObject->bIsStatic) {
|
||||||
pObject->bIsStatic = false;
|
pObject->bIsStatic = true;
|
||||||
pObject->RemoveFromMovingList();
|
pObject->RemoveFromMovingList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11037,6 +11038,7 @@ void CRunningScript::DoDeatharrestCheck()
|
||||||
int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
|
int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
|
||||||
if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
|
if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
|
||||||
messageId += CTheScripts::BaseBriefIdForContact[contact];
|
messageId += CTheScripts::BaseBriefIdForContact[contact];
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
|
@ -11331,6 +11333,7 @@ INITSAVEBUF
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
|
InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ class CRunningScript;
|
||||||
|
|
||||||
struct CScriptRectangle
|
struct CScriptRectangle
|
||||||
{
|
{
|
||||||
int8 m_bIsUsed;
|
bool m_bIsUsed;
|
||||||
bool m_bBeforeFade;
|
bool m_bBeforeFade;
|
||||||
int16 m_nTextureId;
|
int16 m_nTextureId;
|
||||||
CRect m_sRect;
|
CRect m_sRect;
|
||||||
|
|
|
@ -63,62 +63,56 @@ void CStats::Init()
|
||||||
PeopleKilledByOthers = 0;
|
PeopleKilledByOthers = 0;
|
||||||
PeopleKilledByPlayer = 0;
|
PeopleKilledByPlayer = 0;
|
||||||
ShotsMade = 0;
|
ShotsMade = 0;
|
||||||
CarsExploded = 0;
|
CarsExploded = 0;
|
||||||
HelisDestroyed = 0;
|
HelisDestroyed = 0;
|
||||||
ProgressMade = 0;
|
ProgressMade = 0;
|
||||||
KgsOfExplosivesUsed = 0;
|
KgsOfExplosivesUsed = 0;
|
||||||
InstantHitsFiredByPlayer = 0;
|
InstantHitsFiredByPlayer = 0;
|
||||||
InstantHitsHitByPlayer = 0;
|
InstantHitsHitByPlayer = 0;
|
||||||
CarsCrushed = 0;
|
CarsCrushed = 0;
|
||||||
HeadsPopped = 0;
|
HeadsPopped = 0;
|
||||||
TimesArrested = 0;
|
TimesArrested = 0;
|
||||||
TimesDied = 0;
|
TimesDied = 0;
|
||||||
DaysPassed = 0;
|
DaysPassed = 0;
|
||||||
NumberOfUniqueJumpsFound = 0;
|
NumberOfUniqueJumpsFound = 0;
|
||||||
mmRain = 0;
|
mmRain = 0;
|
||||||
MaximumJumpFlips = 0;
|
MaximumJumpFlips = 0;
|
||||||
MaximumJumpSpins = 0;
|
MaximumJumpSpins = 0;
|
||||||
MaximumJumpDistance = 0;
|
MaximumJumpDistance = 0;
|
||||||
MaximumJumpHeight = 0;
|
MaximumJumpHeight = 0;
|
||||||
BestStuntJump = 0;
|
BestStuntJump = 0;
|
||||||
TotalNumberOfUniqueJumps = 0;
|
TotalNumberOfUniqueJumps = 0;
|
||||||
Record4x4One = 0;
|
Record4x4One = 0;
|
||||||
LongestFlightInDodo = 0;
|
LongestFlightInDodo = 0;
|
||||||
Record4x4Two = 0;
|
Record4x4Two = 0;
|
||||||
PassengersDroppedOffWithTaxi = 0;
|
PassengersDroppedOffWithTaxi = 0;
|
||||||
Record4x4Three = 0;
|
Record4x4Three = 0;
|
||||||
MoneyMadeWithTaxi = 0;
|
MoneyMadeWithTaxi = 0;
|
||||||
Record4x4Mayhem = 0;
|
Record4x4Mayhem = 0;
|
||||||
LivesSavedWithAmbulance = 0;
|
LivesSavedWithAmbulance = 0;
|
||||||
ElBurroTime = 0;
|
ElBurroTime = 0;
|
||||||
CriminalsCaught = 0;
|
CriminalsCaught = 0;
|
||||||
MissionsGiven = 0;
|
MissionsGiven = 0;
|
||||||
HighestLevelAmbulanceMission = 0;
|
HighestLevelAmbulanceMission = 0;
|
||||||
MissionsPassed = 0;
|
MissionsPassed = 0;
|
||||||
FiresExtinguished = 0;
|
FiresExtinguished = 0;
|
||||||
DistanceTravelledOnFoot = 0;
|
DistanceTravelledOnFoot = 0;
|
||||||
TimeTakenDefuseMission = 0;
|
TimeTakenDefuseMission = 0;
|
||||||
NumberKillFrenziesPassed = 0;
|
NumberKillFrenziesPassed = 0;
|
||||||
DistanceTravelledInVehicle = 0;
|
DistanceTravelledInVehicle = 0;
|
||||||
TotalNumberKillFrenzies = 0;
|
TotalNumberKillFrenzies = 0;
|
||||||
TotalNumberMissions = 0;
|
TotalNumberMissions = 0;
|
||||||
KillsSinceLastCheckpoint = 0;
|
KillsSinceLastCheckpoint = 0;
|
||||||
TotalLegitimateKills = 0;
|
TotalLegitimateKills = 0;
|
||||||
for (int i = 0; i < TOTAL_FASTEST_TIMES; i++)
|
for (int i = 0; i < TOTAL_FASTEST_TIMES; i++)
|
||||||
{
|
FastestTimes[i] = 0;
|
||||||
FastestTimes[i] = 0;
|
for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++)
|
||||||
}
|
HighestScores[i] = 0;
|
||||||
for (int i = 0; i < TOTAL_HIGHEST_SCORES; i++)
|
for (int i = 0; i < NUM_PEDTYPES; i++)
|
||||||
{
|
PedsKilledOfThisType[i] = 0;
|
||||||
HighestScores[i] = 0;
|
IndustrialPassed = 0;
|
||||||
}
|
CommercialPassed = 0;
|
||||||
for (int i = 0; i < NUM_PEDTYPES; i++)
|
SuburbanPassed = 0;
|
||||||
{
|
|
||||||
PedsKilledOfThisType[i] = 0;
|
|
||||||
}
|
|
||||||
IndustrialPassed = 0;
|
|
||||||
CommercialPassed = 0;
|
|
||||||
SuburbanPassed = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStats::RegisterFastestTime(int32 index, int32 time)
|
void CStats::RegisterFastestTime(int32 index, int32 time)
|
||||||
|
@ -206,8 +200,6 @@ void CStats::SetTotalNumberMissions(int32 total)
|
||||||
TotalNumberMissions = total;
|
TotalNumberMissions = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
//WRAPPER void CStats::Init() { EAXJMP(0x4AAC60); }
|
|
||||||
|
|
||||||
STARTPATCHES
|
STARTPATCHES
|
||||||
InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables
|
InjectHook(0x48C5A3, CStats::Init, PATCH_JUMP); // CGame::ReInitGameObjectVariables
|
||||||
ENDPATCHES
|
ENDPATCHES
|
|
@ -62,8 +62,6 @@ public:
|
||||||
static int32 &CarsCrushed;
|
static int32 &CarsCrushed;
|
||||||
static int32(&FastestTimes)[TOTAL_FASTEST_TIMES];
|
static int32(&FastestTimes)[TOTAL_FASTEST_TIMES];
|
||||||
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
|
static int32(&HighestScores)[TOTAL_HIGHEST_SCORES];
|
||||||
static int32 &KgOfExplosivesUsed;
|
|
||||||
static int32 &CarsCrushed;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void RegisterFastestTime(int32, int32);
|
static void RegisterFastestTime(int32, int32);
|
||||||
|
@ -85,6 +83,5 @@ public:
|
||||||
static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
|
static void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };
|
||||||
static void RegisterElBurroTime(int32);
|
static void RegisterElBurroTime(int32);
|
||||||
static void SaveStats(uint8 *buf, uint32 *size);
|
static void SaveStats(uint8 *buf, uint32 *size);
|
||||||
|
|
||||||
static void Init(void);
|
static void Init(void);
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,9 @@ enum Config {
|
||||||
NUM_AUDIO_REFLECTIONS = 5,
|
NUM_AUDIO_REFLECTIONS = 5,
|
||||||
NUM_SCRIPT_MAX_ENTITIES = 40,
|
NUM_SCRIPT_MAX_ENTITIES = 40,
|
||||||
|
|
||||||
NUM_GARAGE_STORED_CARS = 6
|
NUM_GARAGE_STORED_CARS = 6,
|
||||||
|
|
||||||
|
NUM_CRANES = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
// We'll use this once we're ready to become independent of the game
|
// We'll use this once we're ready to become independent of the game
|
||||||
|
|
|
@ -243,6 +243,17 @@ public:
|
||||||
m_matrix.pos.y = 0.0f;
|
m_matrix.pos.y = 0.0f;
|
||||||
m_matrix.pos.z = 0.0f;
|
m_matrix.pos.z = 0.0f;
|
||||||
}
|
}
|
||||||
|
void ResetOrientation(void) {
|
||||||
|
m_matrix.right.x = 1.0f;
|
||||||
|
m_matrix.right.y = 0.0f;
|
||||||
|
m_matrix.right.z = 0.0f;
|
||||||
|
m_matrix.up.x = 0.0f;
|
||||||
|
m_matrix.up.y = 1.0f;
|
||||||
|
m_matrix.up.z = 0.0f;
|
||||||
|
m_matrix.at.x = 0.0f;
|
||||||
|
m_matrix.at.y = 0.0f;
|
||||||
|
m_matrix.at.z = 1.0f;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue