From c1e13177a1bbc6ce17d1ddc14cecc74cb278b853 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 27 May 2020 22:32:33 +0200 Subject: [PATCH] some CAutomobile --- librw | 2 +- src/core/Stats.cpp | 1 + src/core/Stats.h | 1 + src/core/config.h | 2 +- src/entities/Entity.cpp | 6 +- src/entities/Entity.h | 2 +- src/render/Glass.h | 4 + src/render/Renderer.cpp | 2 +- src/vehicles/Automobile.cpp | 522 +++++++++++++++++++++++---------- src/vehicles/Automobile.h | 15 +- src/vehicles/DamageManager.cpp | 30 +- src/vehicles/DamageManager.h | 2 +- src/vehicles/Vehicle.cpp | 47 ++- src/vehicles/Vehicle.h | 3 +- 14 files changed, 445 insertions(+), 194 deletions(-) diff --git a/librw b/librw index 6ff378bb..84c582c1 160000 --- a/librw +++ b/librw @@ -1 +1 @@ -Subproject commit 6ff378bb16007ad003b1a71996944a20f2e76556 +Subproject commit 84c582c1d7a64a213523b8e4c8211f8b7a4fdcd1 diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 34fc41d1..91f583bd 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -67,6 +67,7 @@ float CStats::AutoPaintingBudget; int32 CStats::NoMoreHurricanes; float CStats::FashionBudget; int32 CStats::SafeHouseVisits; +int32 CStats::TyresPopped; void CStats::Init() { diff --git a/src/core/Stats.h b/src/core/Stats.h index 485bdccf..33d4ef72 100644 --- a/src/core/Stats.h +++ b/src/core/Stats.h @@ -71,6 +71,7 @@ public: static int32 NoMoreHurricanes; static float FashionBudget; static int32 SafeHouseVisits; + static int32 TyresPopped; public: static void Init(void); diff --git a/src/core/config.h b/src/core/config.h index c90d3cbf..d7e83ddc 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -41,7 +41,7 @@ enum Config { NUMANIMBLOCKS = 35, NUMANIMATIONS = 450, - NUMTEMPOBJECTS = 30, + NUMTEMPOBJECTS = 40, // Path data NUM_PATHNODES = 9650, diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 68486a3c..41a2e2bd 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -81,7 +81,7 @@ CEntity::CEntity(void) m_flagE2 = false; bOffscreen = false; bIsStaticWaitingForCollision = false; - m_flagE10 = false; + bDontStream = false; bUnderwater = false; bHasPreRenderEffects = false; @@ -1083,7 +1083,7 @@ CEntity::SaveEntityFlags(uint8*& buf) if (m_flagE2) tmp |= BIT(9); if (bOffscreen) tmp |= BIT(10); if (bIsStaticWaitingForCollision) tmp |= BIT(11); - if (m_flagE10) tmp |= BIT(12); + if (bDontStream) tmp |= BIT(12); if (bUnderwater) tmp |= BIT(13); if (bHasPreRenderEffects) tmp |= BIT(14); @@ -1139,7 +1139,7 @@ CEntity::LoadEntityFlags(uint8*& buf) m_flagE2 = !!(tmp & BIT(9)); bOffscreen = !!(tmp & BIT(10)); bIsStaticWaitingForCollision = !!(tmp & BIT(11)); - m_flagE10 = !!(tmp & BIT(12)); + bDontStream = !!(tmp & BIT(12)); bUnderwater = !!(tmp & BIT(13)); bHasPreRenderEffects = !!(tmp & BIT(14)); } diff --git a/src/entities/Entity.h b/src/entities/Entity.h index e7d402d0..f506017a 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -87,7 +87,7 @@ public: uint32 m_flagE2 : 1; uint32 bOffscreen : 1; // offscreen flag. This can only be trusted when it is set to true uint32 bIsStaticWaitingForCollision : 1; // this is used by script created entities - they are static until the collision is loaded below them - uint32 m_flagE10 : 1; // probably bDontStream + uint32 bDontStream : 1; // tell the streaming not to stream me uint32 bUnderwater : 1; // this object is underwater change drawing order uint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it diff --git a/src/render/Glass.h b/src/render/Glass.h index 51c5aae9..736e5205 100644 --- a/src/render/Glass.h +++ b/src/render/Glass.h @@ -1,6 +1,7 @@ #pragma once class CEntity; +class CVehicle; class CFallingGlassPane : public CMatrix { @@ -49,4 +50,7 @@ public: static void WindowRespondsToSoftCollision(CEntity *entity, float amount); static void WasGlassHitByBullet(CEntity *entity, CVector point); static void WindowRespondsToExplosion(CEntity *entity, CVector point); + +//TODO(MIAMI) + static void CarWindscreenShatters(CVehicle *vehicle, bool unk) {} }; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f149c6fb..6ac10cb0 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -394,7 +394,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent) } return VIS_VISIBLE; } - if(ent->m_flagE10){ + if(ent->bDontStream){ if(ent->m_rwObject == nil || !ent->bIsVisible) return VIS_INVISIBLE; if(!ent->GetIsOnScreen() || ent->IsEntityOccluded()) diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 9fa0df39..ab73394f 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -17,6 +17,7 @@ #include "Explosion.h" #include "Particle.h" #include "ParticleObject.h" +#include "Glass.h" #include "Antennas.h" #include "Skidmarks.h" #include "Shadows.h" @@ -35,6 +36,7 @@ #include "Population.h" #include "CarCtrl.h" #include "CarAI.h" +#include "Stats.h" #include "Garages.h" #include "PathFind.h" #include "AnimManager.h" @@ -2118,6 +2120,7 @@ CAutomobile::Render(void) CEntity::Render(); } +//--MIAMI: done int32 CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) { @@ -2137,6 +2140,10 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) for(i = 0; i < 4; i++) prevRatios[i] = m_aSuspensionSpringRatio[i]; + if(m_bIsVehicleBeingShifted || bSkipLineCol || ent->IsPed() || + GetModelIndex() == MI_DODO && ent->IsVehicle()) + colModel->numLines = 0; + int numCollisions = CCollision::ProcessColModels(GetMatrix(), *colModel, ent->GetMatrix(), *ent->GetColModel(), colpoints, @@ -2145,12 +2152,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) // m_aSuspensionSpringRatio are now set to the point where the tyre touches ground. // In ProcessControl these will be re-normalized to ignore the tyre radius. - if(m_bIsVehicleBeingShifted || bSkipLineCol || - GetModelIndex() == MI_DODO && (ent->IsPed() || ent->IsVehicle())){ - // don't do line collision - for(i = 0; i < 4; i++) - m_aSuspensionSpringRatio[i] = prevRatios[i]; - }else{ + if(colModel->numLines){ for(i = 0; i < 4; i++) if(m_aSuspensionSpringRatio[i] < 1.0f && m_aSuspensionSpringRatio[i] < prevRatios[i]){ numWheelCollisions++; @@ -2162,32 +2164,14 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) m_aGroundPhysical[i] = phys; phys->RegisterReference((CEntity**)&m_aGroundPhysical[i]); m_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition(); - -#if 0 - if(phys->GetModelIndex() == MI_BODYCAST && GetStatus() == STATUS_PLAYER){ - // damage body cast - float speed = m_vecMoveSpeed.MagnitudeSqr(); - if(speed > 0.1f){ - CObject::nBodyCastHealth -= 0.1f*m_fMass*speed; - DMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_BODYCAST_HIT, 0.0f); - } - - // move body cast - if(phys->IsStatic()){ - phys->bIsStatic = false; - phys->m_nStaticFrames = 0; - phys->ApplyMoveForce(m_vecMoveSpeed / Sqrt(speed)); - phys->AddToMovingList(); - } - } -#endif } m_nSurfaceTouched = m_aWheelColPoints[i].surfaceB; if(ent->IsBuilding()) m_pCurGroundEntity = ent; } - } + }else + colModel->numLines = 4; if(numCollisions > 0 || numWheelCollisions > 0){ AddCollisionRecord(ent); @@ -3077,6 +3061,46 @@ CAutomobile::DoDriveByShootings(void) } } +//--MIAMI: done +void +CAutomobile::DoHoverSuspensionRatios(void) +{ + int i; + + if(GetUp().z < 0.1f) + return; + + CColModel *colmodel = GetColModel(); + for(i = 0; i < 4; i++){ + float z, waterZ; + CVector upper = GetMatrix() * colmodel->lines[i].p0; + CVector lower = GetMatrix() * colmodel->lines[i].p1; + if(m_aSuspensionSpringRatio[i] < 1.0f) + z = m_aWheelColPoints[i].point.z; + else + z = -100.0f; + // see if touching water + if(CWaterLevel::GetWaterLevel(lower, &waterZ, false) && + waterZ > z && lower.z-1.0f < waterZ){ + // compress spring + if(lower.z < waterZ){ + if(upper.z < waterZ) + m_aSuspensionSpringRatio[i] = 0.0f; + else + m_aSuspensionSpringRatio[i] = (upper.z - waterZ)/(upper.z - lower.z); + }else + m_aSuspensionSpringRatio[i] = 0.99999f; + + m_aWheelColPoints[i].point.x = (lower.x - upper.x)*m_aSuspensionSpringRatio[i] + upper.x; + m_aWheelColPoints[i].point.y = (lower.y - upper.y)*m_aSuspensionSpringRatio[i] + upper.y; + m_aWheelColPoints[i].point.z = waterZ; + m_aWheelColPoints[i].normal = CVector(0.01f, 0.0f, 1.0f); + m_aWheelColPoints[i].surfaceB = SURFACE_WATER; + } + } +} + +//--MIAMI: done int32 CAutomobile::RcbanditCheckHitWheels(void) { @@ -3104,6 +3128,7 @@ CAutomobile::RcbanditCheckHitWheels(void) return 0; } +//--MIAMI: done int32 CAutomobile::RcbanditCheck1CarWheels(CPtrList &list) { @@ -3116,7 +3141,8 @@ CAutomobile::RcbanditCheck1CarWheels(CPtrList &list) for(node = list.first; node; node = node->next){ car = (CAutomobile*)node->item; - if(this != car && car->IsCar() && car->m_scanCode != CWorld::GetCurrentScanCode()){ + if(this != car && car->IsCar() && car->GetModelIndex() != MI_RCBANDIT && + car->m_scanCode != CWorld::GetCurrentScanCode()){ car->m_scanCode = CWorld::GetCurrentScanCode(); if(Abs(this->GetPosition().x - car->GetPosition().x) < 10.0f && @@ -3141,6 +3167,7 @@ CAutomobile::RcbanditCheck1CarWheels(CPtrList &list) return 0; } +//--MIAMI: done void CAutomobile::PlaceOnRoadProperly(void) { @@ -3186,12 +3213,12 @@ CAutomobile::PlaceOnRoadProperly(void) GetMatrix().GetPosition() = CVector((front.x + rear.x) / 2.0f, (front.y + rear.y) / 2.0f, (frontZ + rearZ) / 2.0f + GetHeightAboveRoad()); } +//--MIAMI: done void CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) { int i; - float damageMultiplier = 0.2f; - bool doubleMoney = false; + float damageMultiplier = 0.333f; if(impulse == 0.0f){ impulse = m_fDamageImpulse; @@ -3199,22 +3226,33 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) damageMultiplier = 1.0f; } + if(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f) + impulse *= 0.5f; + CVector pos(0.0f, 0.0f, 0.0f); if(!bCanBeDamaged) return; + if(m_pDamageEntity && m_pDamageEntity->IsPed() && ((CPed*)m_pDamageEntity)->bIsStanding){ + float speed = ((CPed*)m_pDamageEntity)->m_vecAnimMoveDelta.y * DotProduct(GetForward(), m_vecDamageNormal); + if(speed < 0.0f) + impulse = Max(impulse + ((CPed*)m_pDamageEntity)->m_fMass * speed, 0.0f); + } + // damage flipped over car if(GetUp().z < 0.0f && this != FindPlayerVehicle()){ if(bNotDamagedUpsideDown || GetStatus() == STATUS_PLAYER_REMOTE || bIsInWater) return; - m_fHealth -= 4.0f*CTimer::GetTimeStep(); + if(GetStatus() != STATUS_WRECKED) + m_fHealth = Max(m_fHealth - 4.0f*CTimer::GetTimeStep(), 0.0f); } - if(impulse > 25.0f && GetStatus() != STATUS_WRECKED){ + float minImpulse = GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_RCGOBLIN ? 1.0f : 25.0f; + if(impulse > minImpulse && GetStatus() != STATUS_WRECKED){ if(bIsLawEnforcer && FindPlayerVehicle() && FindPlayerVehicle() == m_pDamageEntity && - GetStatus() != STATUS_ABANDONED && + GetStatus() != STATUS_ABANDONED && FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() >= m_vecMoveSpeed.Magnitude() && FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() > 0.1f) FindPlayerPed()->SetWantedLevelNoDrop(1); @@ -3224,12 +3262,17 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) CPad::GetPad(0)->StartShake(40000/freq, freq); } - if(bOnlyDamagedByPlayer){ + if(GetStatus() != STATUS_PLAYER && bOnlyDamagedByPlayer){ if(m_pDamageEntity != FindPlayerPed() && m_pDamageEntity != FindPlayerVehicle()) return; } + if(m_pDamageEntity && m_pDamageEntity->IsVehicle()){ + m_nLastWeaponDamage = WEAPONTYPE_RAMMEDBYCAR; + m_pLastDamageEntity = m_pDamageEntity; + } + if(bCollisionProof) return; @@ -3249,108 +3292,81 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) switch(damagedPiece){ case CAR_PIECE_BUMP_FRONT: GetComponentWorldPosition(CAR_BUMP_FRONT, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT); - doubleMoney = true; - } if(m_aCarNodes[CAR_BONNET] && Damage.GetPanelStatus(VEHBUMPER_FRONT) == PANEL_STATUS_MISSING){ case CAR_PIECE_BONNET: GetComponentWorldPosition(CAR_BONNET, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(GetModelIndex() != MI_DODO) + if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_BONNET, DOOR_BONNET); - doubleMoney = true; - } } break; case CAR_PIECE_BUMP_REAR: GetComponentWorldPosition(CAR_BUMP_REAR, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_BUMPER_REAR, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR); - doubleMoney = true; - } if(m_aCarNodes[CAR_BOOT] && Damage.GetPanelStatus(VEHBUMPER_REAR) == PANEL_STATUS_MISSING){ case CAR_PIECE_BOOT: GetComponentWorldPosition(CAR_BOOT, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_BOOT, DOOR_BOOT); - doubleMoney = true; - } } break; case CAR_PIECE_DOOR_LF: GetComponentWorldPosition(CAR_DOOR_LF, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) && - Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT); - doubleMoney = true; - } break; case CAR_PIECE_DOOR_RF: GetComponentWorldPosition(CAR_DOOR_RF, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) && - Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT); - doubleMoney = true; - } break; case CAR_PIECE_DOOR_LR: GetComponentWorldPosition(CAR_DOOR_LR, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) && - Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT); - doubleMoney = true; - } break; case CAR_PIECE_DOOR_RR: GetComponentWorldPosition(CAR_DOOR_RR, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) && - Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT); - doubleMoney = true; - } break; case CAR_PIECE_WING_LF: GetComponentWorldPosition(CAR_WING_LF, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT); - doubleMoney = true; - } break; case CAR_PIECE_WING_RF: GetComponentWorldPosition(CAR_WING_RF, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT); - doubleMoney = true; - } break; case CAR_PIECE_WING_LR: GetComponentWorldPosition(CAR_WING_LR, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT); - doubleMoney = true; - } break; case CAR_PIECE_WING_RR: GetComponentWorldPosition(CAR_WING_RR, pos); - dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); + if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT); - doubleMoney = true; - } break; case CAR_PIECE_WHEEL_LF: @@ -3364,37 +3380,43 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) uint8 oldStatus = Damage.GetPanelStatus(VEHPANEL_WINDSCREEN); SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN); if(oldStatus != Damage.GetPanelStatus(VEHPANEL_WINDSCREEN)){ - DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f); - doubleMoney = true; + // DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f); } } break; } - - if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle() && impulse > 10.0f){ - int money = (doubleMoney ? 2 : 1) * impulse*pHandling->nMonetaryValue/1000000.0f; - money = Min(money, 40); - if(money > 2){ - sprintf(gString, "$%d", money); - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += money; - } - } } - float damage = (impulse-25.0f)*pHandling->fCollisionDamageMultiplier*0.6f*damageMultiplier; + float damage = (impulse-minImpulse)*pHandling->fCollisionDamageMultiplier*0.6f*damageMultiplier; if(GetModelIndex() == MI_SECURICA && m_pDamageEntity && m_pDamageEntity->GetStatus() == STATUS_PLAYER) damage *= 7.0f; + if(GetModelIndex() == MI_RCGOBLIN || GetModelIndex() == MI_RCRAIDER) + damage *= 30.0f; + if(damage > 0.0f){ - int oldHealth = m_fHealth; - if(this == FindPlayerVehicle()){ - m_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f; - }else{ - if(damage > 35.0f && pDriver) - pDriver->Say(SOUND_PED_CAR_COLLISION); - m_fHealth -= bTakeLessDamage ? damage/12.0f : damage/4.0f; + if(damage > 5.0f && + pDriver && + m_pDamageEntity && m_pDamageEntity->IsVehicle() && + (this != FindPlayerVehicle() || ((CVehicle*)m_pDamageEntity)->VehicleCreatedBy == MISSION_VEHICLE) && + ((CVehicle*)m_pDamageEntity)->pDriver){ +// TODO(MIAMI) +// if(GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR) +// pDriver->Say(145); +// else +// pDriver->Say(144); } + + int oldHealth = m_fHealth; + if(this == FindPlayerVehicle()) + m_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f; + else if(bTakeLessDamage) + m_fHealth -= damage/12.0f; + else if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle()) + m_fHealth -= damage/1.5f; + else + m_fHealth -= damage/4.0f; if(m_fHealth <= 0.0f && oldHealth > 0) m_fHealth = 1.0f; } @@ -3427,6 +3449,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) } } +//--MIAMI: done void CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount) { @@ -3518,17 +3541,20 @@ CAutomobile::AddDamagedVehicleParticles(void) } } +//--MIAMI: done int32 CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) { int i; CVector dir; static RwRGBA grassCol = { 8, 24, 8, 255 }; - static RwRGBA dirtCol = { 64, 64, 64, 255 }; - static RwRGBA dirttrackCol = { 64, 32, 16, 255 }; + static RwRGBA gravelCol = { 64, 64, 64, 255 }; + static RwRGBA mudCol = { 64, 32, 16, 255 }; + static RwRGBA sandCol = { 170, 165, 140, 255 }; static RwRGBA waterCol = { 48, 48, 64, 0 }; - if(!belowEffectSpeed) + if(!belowEffectSpeed && + colpoint->surfaceB != SURFACE_SAND && colpoint->surfaceB != SURFACE_SAND_BEACH) return 0; switch(colpoint->surfaceB){ @@ -3547,7 +3573,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) for(i = 0; i < 4; i++){ dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f); CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol); + CGeneral::GetRandomNumberInRange(0.05f, 0.09f), gravelCol); } return 1; case SURFACE_MUD_DRY: @@ -3556,7 +3582,20 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) for(i = 0; i < 4; i++){ dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f); CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirttrackCol); + CGeneral::GetRandomNumberInRange(0.02f, 0.06f), mudCol); + } + return 0; + case SURFACE_SAND: + case SURFACE_SAND_BEACH: + if(CTimer::GetFrameCounter() & 2 || + CGeneral::GetRandomNumberInRange(CWeather::WetRoads, 1.01f) > 0.5f) + return 0; + dir.x = 0.5f*m_vecMoveSpeed.x; + dir.y = 0.5f*m_vecMoveSpeed.y; + for(i = 0; i < 1; i++){ + dir.z = CGeneral::GetRandomNumberInRange(0.02f, 0.055f); + CParticle::AddParticle(PARTICLE_SAND, colpoint->point, dir, nil, + 2.0f*m_vecMoveSpeed.Magnitude(), sandCol); } return 0; default: @@ -3573,11 +3612,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) PARTICLE_WATERSPRAY, #endif colpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f), -#ifdef PC_PARTICLE - CVector(0.0f, 0.0f, 1.0f), -#else CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.005f, 0.04f)), -#endif nil, CGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol); return 0; @@ -3587,6 +3622,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) } } +//--MIAMI: done void CAutomobile::GetComponentWorldPosition(int32 component, CVector &pos) { @@ -3598,12 +3634,14 @@ CAutomobile::GetComponentWorldPosition(int32 component, CVector &pos) pos = *RwMatrixGetPos(ltm); } +//--MIAMI: done bool CAutomobile::IsComponentPresent(int32 comp) { return m_aCarNodes[comp] != nil; } +//--MIAMI: done void CAutomobile::SetComponentRotation(int32 component, CVector rotation) { @@ -3617,6 +3655,7 @@ CAutomobile::SetComponentRotation(int32 component, CVector rotation) mat.UpdateRW(); } +//--MIAMI: done void CAutomobile::OpenDoor(int32 component, eDoors door, float openRatio) { @@ -3693,6 +3732,8 @@ inline void ProcessDoorOpenCloseAnimation(CAutomobile *car, uint32 component, eD car->OpenDoor(component, door, 0.0f); } } + +//--MIAMI: done void CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) { @@ -3713,13 +3754,13 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) case ANIM_CAR_QJACK: case ANIM_CAR_OPEN_LHS: case ANIM_CAR_OPEN_RHS: - ProcessDoorOpenAnimation(this, component, door, time, 0.66f, 0.8f); + ProcessDoorOpenAnimation(this, component, door, time, 0.41f, 0.89f); break; case ANIM_CAR_CLOSEDOOR_LHS: case ANIM_CAR_CLOSEDOOR_LOW_LHS: case ANIM_CAR_CLOSEDOOR_RHS: case ANIM_CAR_CLOSEDOOR_LOW_RHS: - ProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.63f); + ProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.45f); break; case ANIM_CAR_ROLLDOOR: case ANIM_CAR_ROLLDOOR_LOW: @@ -3764,6 +3805,7 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) } } +//--MIAMI: done bool CAutomobile::IsDoorReady(eDoors door) { @@ -3780,24 +3822,66 @@ CAutomobile::IsDoorReady(eDoors door) return (doorflag & m_nGettingInFlags) == 0; } +//--MIAMI: done bool CAutomobile::IsDoorFullyOpen(eDoors door) { return Doors[door].IsFullyOpen() || IsDoorMissing(door); } +//--MIAMI: done bool CAutomobile::IsDoorClosed(eDoors door) { return !!Doors[door].IsClosed(); } +//--MIAMI: done bool CAutomobile::IsDoorMissing(eDoors door) { return Damage.GetDoorStatus(door) == DOOR_STATUS_MISSING; } +//--MIAMI: done +bool +CAutomobile::IsDoorReady(uint32 door) +{ + switch(door){ + case CAR_DOOR_RF: return IsDoorReady(DOOR_FRONT_RIGHT); + case CAR_DOOR_RR: return IsDoorReady(DOOR_REAR_RIGHT); + case CAR_DOOR_LF: return IsDoorReady(DOOR_FRONT_LEFT); + case CAR_DOOR_LR: return IsDoorReady(DOOR_REAR_LEFT); + default: + return false; + } +} + +//--MIAMI: done +bool +CAutomobile::IsDoorMissing(uint32 door) +{ + switch(door){ + case CAR_DOOR_RF: return IsDoorMissing(DOOR_FRONT_RIGHT); + case CAR_DOOR_RR: return IsDoorMissing(DOOR_REAR_RIGHT); + case CAR_DOOR_LF: return IsDoorMissing(DOOR_FRONT_LEFT); + case CAR_DOOR_LR: return IsDoorMissing(DOOR_REAR_LEFT); + default: + return false; + } +} + +//--MIAMI: done +bool +CAutomobile::IsOpenTopCar(void) +{ + return GetModelIndex() == MI_STINGER || + // component 0 is assumed to be a roof + GetModelIndex() == MI_COMET && m_aExtras[0] != 0 && m_aExtras[1] != 0 || + GetModelIndex() == MI_STALLION && m_aExtras[0] != 0 && m_aExtras[1] != 0; +} + +//--MIAMI: done void CAutomobile::RemoveRefsToVehicle(CEntity *ent) { @@ -3807,15 +3891,21 @@ CAutomobile::RemoveRefsToVehicle(CEntity *ent) m_aGroundPhysical[i] = nil; } +//--MIAMI void CAutomobile::BlowUpCar(CEntity *culprit) { - int i; RpAtomic *atomic; if(!bCanBeDamaged) return; + if(culprit == FindPlayerPed() || culprit == FindPlayerVehicle()){ + CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 20; + CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 10.0f; + CStats::PropertyDestroyed += CGeneral::GetRandomNumber()%6000 + 4000; + } + // explosion pushes vehicle up m_vecMoveSpeed.z += 0.13f; SetStatus(STATUS_WRECKED); @@ -3845,27 +3935,7 @@ CAutomobile::BlowUpCar(CEntity *culprit) TheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z); - // kill driver and passengers - if(pDriver){ - CDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION); - if(pDriver->GetPedState() == PED_DRIVING){ - pDriver->SetDead(); - if(!pDriver->IsPlayer()) - pDriver->FlagToDestroyWhenNextProcessed(); - }else - pDriver->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } - for(i = 0; i < m_nNumMaxPassengers; i++){ - if(pPassengers[i]){ - CDarkel::RegisterKillByPlayer(pPassengers[i], WEAPONTYPE_EXPLOSION); - if(pPassengers[i]->GetPedState() == PED_DRIVING){ - pPassengers[i]->SetDead(); - if(!pPassengers[i]->IsPlayer()) - pPassengers[i]->FlagToDestroyWhenNextProcessed(); - }else - pPassengers[i]->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); - } - } + KillPedsInVehicle(); bEngineOn = false; bLightsOn = false; @@ -3889,12 +3959,17 @@ CAutomobile::BlowUpCar(CEntity *culprit) CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0); } +//--MIAMI: done bool CAutomobile::SetUpWheelColModel(CColModel *colModel) { CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); CColModel *vehColModel = mi->GetColModel(); + if(GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || + GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) + return false; + colModel->boundingSphere = vehColModel->boundingSphere; colModel->boundingBox = vehColModel->boundingBox; @@ -3920,19 +3995,27 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) return true; } +//--MIAMI: done void CAutomobile::BurstTyre(uint8 wheel, bool applyForces) { + if(GetModelIndex() == MI_RHINO || bTyresDontBurst) + return; + switch(wheel){ case CAR_PIECE_WHEEL_LF: wheel = VEHWHEEL_FRONT_LEFT; break; case CAR_PIECE_WHEEL_LR: wheel = VEHWHEEL_REAR_LEFT; break; case CAR_PIECE_WHEEL_RF: wheel = VEHWHEEL_FRONT_RIGHT; break; case CAR_PIECE_WHEEL_RR: wheel = VEHWHEEL_REAR_RIGHT; break; + default: assert(0 && "invalid wheel"); } int status = Damage.GetWheelStatus(wheel); if(status == WHEEL_STATUS_OK){ Damage.SetWheelStatus(wheel, WHEEL_STATUS_BURST); + CStats::TyresPopped++; +// TODO(MIAMI) +// DMAudio.PlayOneShot(m_audioEntityId, SOUND_15, 0.0f); if(GetStatus() == STATUS_SIMPLE){ SetStatus(STATUS_PHYSICS); @@ -3946,6 +4029,7 @@ CAutomobile::BurstTyre(uint8 wheel, bool applyForces) } } +//--MIAMI: done bool CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset) { @@ -4008,24 +4092,20 @@ CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset) return true; } +//-MIAMI: done float CAutomobile::GetHeightAboveRoad(void) { return m_fHeightAboveRoad; } +//-MIAMI: done void CAutomobile::PlayCarHorn(void) { int r; - if (m_nAlarmState && m_nAlarmState != -1) - return; - - if (GetStatus() == STATUS_WRECKED) - return; - - if(m_nCarHornTimer != 0) + if (IsAlarmOn() || GetStatus() == STATUS_WRECKED || m_nCarHornTimer != 0) return; if (m_nCarHornDelay) { @@ -4047,6 +4127,7 @@ CAutomobile::PlayCarHorn(void) } } +//--MIAMI: done void CAutomobile::PlayHornIfNecessary(void) { @@ -4056,7 +4137,7 @@ CAutomobile::PlayHornIfNecessary(void) PlayCarHorn(); } - +//--MIAMI: done void CAutomobile::ResetSuspension(void) { @@ -4069,6 +4150,7 @@ CAutomobile::ResetSuspension(void) } } +//--MIAMI: done void CAutomobile::SetupSuspensionLines(void) { @@ -4099,8 +4181,8 @@ CAutomobile::SetupSuspensionLines(void) } // Compress spring somewhat to get normal height on road - m_fHeightAboveRoad = -(colModel->lines[0].p0.z + (colModel->lines[0].p1.z - colModel->lines[0].p0.z)* - (1.0f - 1.0f/(8.0f*pHandling->fSuspensionForceLevel))); + m_fHeightAboveRoad = m_aSuspensionSpringLength[0]*(1.0f - 1.0f/(4.0f*pHandling->fSuspensionForceLevel)) + - colModel->lines[0].p0.z + mi->m_wheelScale*0.5f; for(i = 0; i < 4; i++) m_aWheelPosition[i] = mi->m_wheelScale*0.5f - m_fHeightAboveRoad; @@ -4118,6 +4200,7 @@ CAutomobile::SetupSuspensionLines(void) } } +//--MIAMI: done // called on police cars void CAutomobile::ScanForCrimes(void) @@ -4129,6 +4212,7 @@ CAutomobile::ScanForCrimes(void) CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetWantedLevelNoDrop(1); } +//--MIAMI: done void CAutomobile::BlowUpCarsInPath(void) { @@ -4139,10 +4223,14 @@ CAutomobile::BlowUpCarsInPath(void) if(m_aCollisionRecords[i] && m_aCollisionRecords[i]->IsVehicle() && m_aCollisionRecords[i]->GetModelIndex() != MI_RHINO && - !m_aCollisionRecords[i]->bRenderScorched) + !m_aCollisionRecords[i]->bRenderScorched){ + if(this == FindPlayerVehicle()) + CEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, this, FindPlayerPed(), 2000); ((CVehicle*)m_aCollisionRecords[i])->BlowUpCar(this); + } } +//--MIAMI: done bool CAutomobile::HasCarStoppedBecauseOfLight(void) { @@ -4174,6 +4262,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void) return false; } +//--MIAMI: done void CAutomobile::SetBusDoorTimer(uint32 timer, uint8 type) { @@ -4188,6 +4277,7 @@ CAutomobile::SetBusDoorTimer(uint32 timer, uint8 type) m_nBusDoorTimerEnd = m_nBusDoorTimerStart + timer; } +//--MIAMI: done void CAutomobile::ProcessAutoBusDoors(void) { @@ -4227,6 +4317,7 @@ CAutomobile::ProcessAutoBusDoors(void) } } +//--MIAMI: done void CAutomobile::ProcessSwingingDoor(int32 component, eDoors door) { @@ -4242,8 +4333,30 @@ CAutomobile::ProcessSwingingDoor(int32 component, eDoors door) mat.SetRotate(axes[0], axes[1], axes[2]); mat.Translate(pos); mat.UpdateRW(); + + // make wind rip off bonnet + if(door == DOOR_BONNET && Doors[door].m_nDoorState == DOORST_OPEN && + DotProduct(m_vecMoveSpeed, GetForward()) > 0.4f){ +#ifdef FIX_BUGS + CObject *comp = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_BONNET); +#else + CObject *comp = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR); +#endif + // make both doors invisible on car + SetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE); + Damage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING); + + if(comp){ + if(CGeneral::GetRandomNumber() & 1) + comp->m_vecMoveSpeed = 0.4f*m_vecMoveSpeed + 0.1f*GetRight() + 0.5f*GetUp(); + else + comp->m_vecMoveSpeed = 0.4f*m_vecMoveSpeed - 0.1f*GetRight() + 0.5f*GetUp(); + comp->ApplyTurnForce(10.0f*GetUp(), GetForward()); + } + } } +//--MIAMI: done void CAutomobile::Fix(void) { @@ -4268,8 +4381,22 @@ CAutomobile::Fix(void) mat.UpdateRW(); } } + + for(component = 0; component < 4; component++) + Damage.SetWheelStatus(component, WHEEL_STATUS_OK); + + if(GetModelIndex() == MI_HUNTER){ + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0); + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0); + }else if(IsRealHeli()){ + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0); + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0); + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0); + RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0); + } } +//--MIAMI: done void CAutomobile::SetupDamageAfterLoad(void) { @@ -4299,6 +4426,7 @@ CAutomobile::SetupDamageAfterLoad(void) SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT); } +//--MIAMI: done RwObject* GetCurrentAtomicObjectCB(RwObject *object, void *data) { @@ -4309,8 +4437,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; - +//--MIAMI: done CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) { @@ -4343,6 +4470,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) case COMPGROUP_DOOR: obj->SetModelIndexNoCreate(MI_CAR_DOOR); obj->SetCenterOfMass(0.0f, -0.5f, 0.0f); + obj->bDrawLast = true; break; case COMPGROUP_BONNET: obj->SetModelIndexNoCreate(MI_CAR_BONNET); @@ -4369,6 +4497,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) RpAtomicSetFrame(atomic, frame); CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); obj->AttachToRwObject((RwObject*)atomic); + obj->bDontStream = true; // init object obj->m_fMass = 10.0f; @@ -4415,7 +4544,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) dist += GetUp(); if(GetUp().z > 0.0f){ // simulate fast upward movement if going fast - float speed = CVector2D(m_vecMoveSpeed).MagnitudeSqr(); + float speed = CVector2D(m_vecMoveSpeed).Magnitude(); obj->GetMatrix().Translate(GetUp()*speed); } } @@ -4427,9 +4556,16 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) obj->m_fAirResistance = 0.99f; } + if(GetStatus() == STATUS_WRECKED && IsVisible() && DotProduct(dist, TheCamera.GetPosition() - GetPosition()) > -0.5f){ + dist = TheCamera.GetPosition() - GetPosition(); + dist.Normalise(); + dist.z += 0.3f; + ApplyMoveForce(5.0f*dist); + } + if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - aTempPedColPts, nil, nil) > 0) + CWorld::m_aTempColPts, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) @@ -4440,6 +4576,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) return obj; } +//--MIAMI: done CObject* CAutomobile::RemoveBonnetInPedCollision(void) { @@ -4447,8 +4584,11 @@ CAutomobile::RemoveBonnetInPedCollision(void) if(Damage.GetDoorStatus(DOOR_BONNET) == DOOR_STATUS_SWINGING && Doors[DOOR_BONNET].RetAngleWhenOpen()*0.4f < Doors[DOOR_BONNET].m_fAngle){ - // BUG? why not COMPGROUP_BONNET? +#ifdef FIX_BUGS + obj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_BONNET); +#else obj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR); +#endif // make both doors invisible on car SetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE); Damage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING); @@ -4457,6 +4597,7 @@ CAutomobile::RemoveBonnetInPedCollision(void) return nil; } +//--MIAMI:: done void CAutomobile::SetPanelDamage(int32 component, ePanels panel, bool noFlyingComponents) { @@ -4464,16 +4605,21 @@ CAutomobile::SetPanelDamage(int32 component, ePanels panel, bool noFlyingCompone if(m_aCarNodes[component] == nil) return; if(status == PANEL_STATUS_SMASHED1){ +// TODO(MIAMI) +// DMAudio.PlayOneShot(m_audioEntityId, SOUND_12, 0.0f); // show damaged part SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM); }else if(status == PANEL_STATUS_MISSING){ if(!noFlyingComponents) SpawnFlyingComponent(component, COMPGROUP_PANEL); + else + CGlass::CarWindscreenShatters(this, false); // hide both SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE); } } +//--MIAMI: done void CAutomobile::SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents) { @@ -4494,6 +4640,7 @@ CAutomobile::SetBumperDamage(int32 component, ePanels panel, bool noFlyingCompon } } +//--MIAMI: done void CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents) { @@ -4504,18 +4651,26 @@ CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents return; } + if(!CanDoorsBeDamaged() && status > DOOR_STATUS_SMASHED && door != DOOR_BONNET && door != DOOR_BOOT){ + Damage.SetDoorStatus(door, DOOR_STATUS_SMASHED); + status = DOOR_STATUS_SMASHED; + } + if(door == DOOR_BOOT && status == DOOR_STATUS_SWINGING && pHandling->Flags & HANDLING_NOSWING_BOOT){ Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_MISSING); status = DOOR_STATUS_MISSING; } - if(status == DOOR_STATUS_SMASHED){ + switch(status){ + case DOOR_STATUS_SMASHED: // show damaged part SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM); - }else if(status == DOOR_STATUS_SWINGING){ + break; + case DOOR_STATUS_SWINGING: // turn off angle cull for swinging doors RwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL); - }else if(status == DOOR_STATUS_MISSING){ + break; + case DOOR_STATUS_MISSING: if(!noFlyingComponents){ if(door == DOOR_BONNET) SpawnFlyingComponent(component, COMPGROUP_BONNET); @@ -4526,10 +4681,12 @@ CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents } // hide both SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE); + break; } } +//--MIAMI: done static RwObject* SetVehicleAtomicVisibilityCB(RwObject *object, void *data) { @@ -4542,6 +4699,7 @@ SetVehicleAtomicVisibilityCB(RwObject *object, void *data) return object; } +//--MIAMI: done void CAutomobile::SetComponentVisibility(RwFrame *frame, uint32 flags) { @@ -4550,6 +4708,7 @@ CAutomobile::SetComponentVisibility(RwFrame *frame, uint32 flags) RwFrameForAllObjects(frame, SetVehicleAtomicVisibilityCB, (void*)flags); } +//--MIAMI: done void CAutomobile::SetupModelNodes(void) { @@ -4559,12 +4718,14 @@ CAutomobile::SetupModelNodes(void) CClumpModelInfo::FillFrameArray((RpClump*)m_rwObject, m_aCarNodes); } +//--MIAMI: done void CAutomobile::SetTaxiLight(bool light) { bTaxiLight = light; } +//--MIAMI: done bool CAutomobile::GetAllWheelsOffGround(void) { @@ -4583,6 +4744,7 @@ CAutomobile::ShowAllComps(void) // empty } +//--MIAMI: done void CAutomobile::ReduceHornCounter(void) { @@ -4608,6 +4770,54 @@ CAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed) //TODO(MIAMI) } +//--MIAMI: done +void +CAutomobile::PopBoot(void) +{ + switch(Damage.GetDoorStatus(DOOR_BOOT)){ + case DOOR_STATUS_OK: + case DOOR_STATUS_SMASHED: + Doors[DOOR_BOOT].m_fAngle = Doors[DOOR_BOOT].m_fMinAngle; + CMatrix mat(RwFrameGetMatrix(m_aCarNodes[DOOR_BOOT])); + CVector pos = mat.GetPosition(); + float axes[3] = { 0.0f, 0.0f, 0.0f }; + axes[Doors[DOOR_BOOT].m_nAxis] = Doors[DOOR_BOOT].m_fAngle; + mat.SetRotate(axes[0], axes[1], axes[2]); + mat.Translate(pos); + mat.UpdateRW(); + } +} + +//--MIAMI: done +void +CAutomobile::PopBootUsingPhysics(void) +{ + switch(Damage.GetDoorStatus(DOOR_BOOT)) + case DOOR_STATUS_OK: + case DOOR_STATUS_SMASHED: + Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_SWINGING); + Doors[DOOR_BOOT].m_fAngle = -2.0f; +} + +//--MIAMI: done +void +CAutomobile::CloseAllDoors(void) +{ + CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); + if(!IsDoorMissing(DOOR_FRONT_LEFT)) + OpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f); + if(mi->m_numDoors > 1){ + if(!IsDoorMissing(DOOR_FRONT_RIGHT)) + OpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f); + if(mi->m_numDoors > 2){ + if(!IsDoorMissing(DOOR_REAR_LEFT)) + OpenDoor(CAR_DOOR_LR, DOOR_REAR_LEFT, 0.0f); + if(!IsDoorMissing(DOOR_REAR_RIGHT)) + OpenDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT, 0.0f); + } + } +} + #ifdef COMPATIBLE_SAVES void CAutomobile::Save(uint8*& buf) diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 883177aa..e9837a3b 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -69,7 +69,6 @@ enum { class CAutomobile : public CVehicle { public: - // 0x288 CDamageManager Damage; CDoor Doors[6]; RwFrame *m_aCarNodes[NUM_CAR_NODES]; @@ -83,10 +82,8 @@ public: float m_aWheelRotation[4]; float m_aWheelPosition[4]; float m_aWheelSpeed[4]; - float m_fRotorSpeed; uint8 field_4D8; uint8 bTaxiLight : 1; - //uint8 bHadDriver : 1; // for bombs uint8 bFixedColour : 1; uint8 bBigWheels : 1; uint8 bWaterTight : 1; // no damage for non-player peds @@ -111,6 +108,7 @@ public: float m_weaponDoorTimerRight; float m_fCarGunLR; float m_fCarGunUD; + float m_fHeliOrientation; float m_fPropellerRotation; uint8 stuff4[4]; uint8 m_nWheelsOnGround; @@ -144,6 +142,9 @@ public: bool IsDoorFullyOpen(eDoors door); bool IsDoorClosed(eDoors door); bool IsDoorMissing(eDoors door); + bool IsDoorReady(uint32 door); + bool IsDoorMissing(uint32 door); + bool IsOpenTopCar(void); void RemoveRefsToVehicle(CEntity *ent); void BlowUpCar(CEntity *ent); bool SetUpWheelColModel(CColModel *colModel); @@ -158,6 +159,7 @@ public: void VehicleDamage(float impulse, uint16 damagedPiece); void ProcessBuoyancy(void); void DoDriveByShootings(void); + void DoHoverSuspensionRatios(void); int32 RcbanditCheckHitWheels(void); int32 RcbanditCheck1CarWheels(CPtrList &list); void PlaceOnRoadProperly(void); @@ -181,6 +183,8 @@ public: void SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false); void TellHeliToGoToCoors(float x, float y, float z, uint8 speed); + void SetHeliOrientation(float orient) { m_fHeliOrientation = orient; } + void ClearHeliOrientation(void) { m_fHeliOrientation = -1.0f; } void Fix(void); void SetComponentVisibility(RwFrame *frame, uint32 flags); @@ -190,6 +194,11 @@ public: void HideAllComps(void); void ShowAllComps(void); void ReduceHornCounter(void); + + void PopBoot(void); + void PopBootUsingPhysics(void); + void CloseAllDoors(void); + #ifdef COMPATIBLE_SAVES virtual void Save(uint8*& buf); virtual void Load(uint8*& buf); diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp index 6b59ccda..e4c28c95 100644 --- a/src/vehicles/DamageManager.cpp +++ b/src/vehicles/DamageManager.cpp @@ -10,14 +10,20 @@ float G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f }; CDamageManager::CDamageManager(void) { ResetDamageStatus(); - m_fWheelDamageEffect = 0.75f; - field_24 = 1; + m_fWheelDamageEffect = 0.5f; + field_18 = 1; } void CDamageManager::ResetDamageStatus(void) { - memset(this, 0, sizeof(*this)); + int i; + m_fWheelDamageEffect = 0.0f; + m_engineStatus = 0; + for(i = 0; i < ARRAY_SIZE(m_wheelStatus); i++) m_wheelStatus[i] = 0; + for(i = 0; i < ARRAY_SIZE(m_doorStatus); i++) m_doorStatus[i] = 0; + m_lightStatus = 0; + m_panelStatus = 0; } void @@ -28,12 +34,8 @@ CDamageManager::FuckCarCompletely(void) m_wheelStatus[0] = WHEEL_STATUS_MISSING; // wheels 1-3 not reset? - m_doorStatus[0] = DOOR_STATUS_MISSING; - m_doorStatus[1] = DOOR_STATUS_MISSING; - m_doorStatus[2] = DOOR_STATUS_MISSING; - m_doorStatus[3] = DOOR_STATUS_MISSING; - m_doorStatus[4] = DOOR_STATUS_MISSING; - m_doorStatus[5] = DOOR_STATUS_MISSING; + for(i = 0; i < ARRAY_SIZE(m_doorStatus); i++) + m_doorStatus[i] = DOOR_STATUS_MISSING; for(i = 0; i < 3; i++){ #ifdef FIX_BUGS @@ -59,6 +61,8 @@ CDamageManager::ApplyDamage(tComponent component, float damage, float unused) GetComponentGroup(component, &group, &subComp); damage *= G_aComponentDamage[group]; + if(component == COMPONENT_PANEL_WINDSCREEN) + damage *= 0.6f; if(damage > 150.0f){ switch(group){ case COMPGROUP_WHEEL: @@ -222,10 +226,6 @@ CDamageManager::GetEngineStatus(void) bool CDamageManager::ProgressEngineDamage(void) { - int status = GetEngineStatus(); - int newstatus = status + 32 + (CGeneral::GetRandomNumber() & 0x1F); - if(status < ENGINE_STATUS_ON_FIRE && newstatus > ENGINE_STATUS_ON_FIRE-1) - newstatus = ENGINE_STATUS_ON_FIRE-1; - SetEngineStatus(newstatus); - return true; + // gone in VC + return false; } diff --git a/src/vehicles/DamageManager.h b/src/vehicles/DamageManager.h index bf0c59a1..312006e3 100644 --- a/src/vehicles/DamageManager.h +++ b/src/vehicles/DamageManager.h @@ -86,7 +86,7 @@ public: uint8 m_doorStatus[6]; uint32 m_lightStatus; uint32 m_panelStatus; - uint32 field_24; + uint8 field_18; CDamageManager(void); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 7e4ff2fe..8479f570 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -707,12 +707,12 @@ CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix & // Apply Collision if(IsCar()){ CAutomobile *heli = (CAutomobile*)this; - if(heli->m_fRotorSpeed > 0.15f){ + if(heli->m_aWheelSpeed[1] > 0.15f){ ApplyCollision(CWorld::m_aTempColPts[i], impulse); ApplyTurnForce(m_fTurnMass*ROTOR_COL_TURNMULT*tangentSpeed, colpos - center); - heli->m_fRotorSpeed = 0.15f; - }else if(heli->m_fRotorSpeed < 0.075f && heli->m_fRotorSpeed > 0.0f) - heli->m_fRotorSpeed *= -1.0f; + heli->m_aWheelSpeed[1] = 0.15f; + }else if(heli->m_aWheelSpeed[1] < 0.075f && heli->m_aWheelSpeed[1] > 0.0f) + heli->m_aWheelSpeed[1] *= -1.0f; } float damageImpulse = damageMult * Max(impulse, ROTOR_DEFAULT_DAMAGE*m_fMass/3000.0f); @@ -1395,7 +1395,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) return false; if (pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_LEFT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) { pPassengers[2] = pPassengers[1]; pPassengers[1] = nil; @@ -1412,7 +1412,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) } if (pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_RIGHT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { pPassengers[1] = pPassengers[2]; pPassengers[2] = nil; @@ -1429,7 +1429,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) } if (pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_FRONT_RIGHT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { pPassengers[1] = pPassengers[0]; pPassengers[0] = nil; @@ -1581,9 +1581,8 @@ CVehicle::CarHasRoof(void) { if((pHandling->Flags & HANDLING_HAS_NO_ROOF) == 0) return true; - if(m_aExtras[0] && m_aExtras[1]) - return false; - return true; + // component 0 is assumed to be a roof + return m_aExtras[0] == 0 || m_aExtras[1] == 0; } bool @@ -1977,7 +1976,7 @@ CVehicle::ProcessCarAlarm(void) { uint32 step; - if(m_nAlarmState == 0 || m_nAlarmState == -1) + if(!IsAlarmOn()) return; step = CTimer::GetTimeStepInMilliseconds(); @@ -2267,6 +2266,32 @@ CVehicle::DoSunGlare(void) } } +void +CVehicle::KillPedsInVehicle(void) +{ + int i; + if(pDriver){ + CDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION); + if(pDriver->GetPedState() == PED_DRIVING){ + pDriver->SetDead(); + if(!pDriver->IsPlayer()) + pDriver->FlagToDestroyWhenNextProcessed(); + }else + pDriver->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } + for(i = 0; i < m_nNumMaxPassengers; i++){ + if(pPassengers[i]){ + CDarkel::RegisterKillByPlayer(pPassengers[i], WEAPONTYPE_EXPLOSION); + if(pPassengers[i]->GetPedState() == PED_DRIVING){ + pPassengers[i]->SetDead(); + if(!pPassengers[i]->IsPlayer()) + pPassengers[i]->FlagToDestroyWhenNextProcessed(); + }else + pPassengers[i]->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f); + } + } +} + void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) { diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 083a8a15..cec039fb 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -276,7 +276,7 @@ public: virtual void BlowUpCar(CEntity *ent) {} virtual bool SetUpWheelColModel(CColModel *colModel) { return false; } virtual void BurstTyre(uint8 tyre, bool applyForces) {} - virtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false;} + virtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false; } virtual bool IsClearToDriveAway(void); virtual float GetHeightAboveRoad(void); virtual void PlayCarHorn(void) {} @@ -340,6 +340,7 @@ public: void FireFixedMachineGuns(void); void ActivateBomb(void); void ActivateBombWhenEntered(void); + void KillPedsInVehicle(void); void SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha); void UpdateClumpAlpha(void);