diff options
Diffstat (limited to 'src/vehicles/Heli.cpp.autosave')
-rw-r--r-- | src/vehicles/Heli.cpp.autosave | 1055 |
1 files changed, 0 insertions, 1055 deletions
diff --git a/src/vehicles/Heli.cpp.autosave b/src/vehicles/Heli.cpp.autosave deleted file mode 100644 index 9b1a651d..00000000 --- a/src/vehicles/Heli.cpp.autosave +++ /dev/null @@ -1,1055 +0,0 @@ -#include "common.h" -#include "main.h" -#include "patcher.h" -#include "General.h" -#include "Darkel.h" -#include "Stats.h" -#include "SurfaceTable.h" -#include "ModelIndices.h" -#include "Streaming.h" -#include "Camera.h" -#include "VisibilityPlugins.h" -#include "ZoneCull.h" -#include "Particle.h" -#include "Shadows.h" -#include "Coronas.h" -#include "Explosion.h" -#include "TimeCycle.h" -#include "TempColModels.h" -#include "World.h" -#include "WaterLevel.h" -#include "PlayerPed.h" -#include "Object.h" -#include "HandlingMgr.h" -#include "Heli.h" - -enum -{ - HELI_STATUS_HOVER, - HELI_STATUS_CHASE_PLAYER, - HELI_STATUS_FLY_AWAY, - HELI_STATUS_SHOT_DOWN, - HELI_STATUS_HOVER2, -}; - -CHeli **CHeli::pHelis = (CHeli**)0x72CF50; -int16 &CHeli::NumRandomHelis = *(int16*)0x95CCAA; -uint32 &CHeli::TestForNewRandomHelisTimer = *(uint32*)0x8F1A7C; -int16 CHeli::NumScriptHelis; // unused -bool &CHeli::CatalinaHeliOn = *(bool*)0x95CD85; -bool &CHeli::CatalinaHasBeenShotDown = *(bool*)0x95CD56; -bool &CHeli::ScriptHeliOn = *(bool*)0x95CD43; - -CHeli::CHeli(int32 id, uint8 CreatedBy) - : CVehicle(CreatedBy) -{ - int i; - - CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); - m_vehType = VEHICLE_TYPE_HELI; - pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); - SetModelIndex(id); - m_heliStatus = HELI_STATUS_HOVER; - m_pathState = 0; - - m_fMass = 100000000.0f; - m_fTurnMass = 100000000.0f; - m_fAirResistance = 0.9994f; - m_fElasticity = 0.05f; - - m_nHeliId = 0; - m_fRotorRotation = 0.0f; - m_nBulletDamage = 0; - m_fAngularSpeed = 0.0f; - m_fRotation = 0.0f; - m_nSearchLightTimer = CTimer::GetTimeInMilliseconds(); - for(i = 0; i < 6; i++){ - m_aSearchLightHistoryX[i] = 0.0f; - m_aSearchLightHistoryY[i] = 0.0f; - } - - for(i = 0; i < 8; i++) - m_fHeliDustZ[i] = -50.0f; - - m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds(); - m_status = STATUS_HELI; - m_bTestRight = true; - m_fTargetOffset = 0.0f; - m_fSearchLightX = m_fSearchLightY = 0.0f; -} - -void -CHeli::SetModelIndex(uint32 id) -{ - int i; - - CVehicle::SetModelIndex(id); - for(i = 0; i < NUM_HELI_NODES; i++) - m_aHeliNodes[i] = nil; - CClumpModelInfo::FillFrameArray(GetClump(), m_aHeliNodes); -} - -static float CatalinaTargetX[7] = { -478.0, -677.0, -907.0, -1095.0, -1152.0, -1161.0, -1161.0 }; -static float CatalinaTargetY[7] = { 227.0, 206.0, 210.0, 242.0, 278.0, 341.0, 341.0 }; -static float CatalinaTargetZ[7] = { 77.0, 66.0, 60.0, 53.0, 51.0, 46.0, 30.0 }; -static float DamPathX[6] = { -1191.0, -1176.0, -1128.0, -1072.0, -1007.0, -971.0 }; -static float DamPathY[6] = { 350.0, 388.0, 429.0, 447.0, 449.0, 416.0 }; -static float DamPathZ[6] = { 42.0, 37.0, 28.0, 28.0, 31.0, 33.0 }; -static float ShortPathX[4] = { -974.0, -1036.0, -1112.0, -1173.0 }; -static float ShortPathY[4] = { 340.0, 312.0, 317.0, 294.0 }; -static float ShortPathZ[4] = { 41.0, 38.0, 32.0, 39.0 }; -static float LongPathX[7] = { -934.0, -905.0, -906.0, -1063.0, -1204.0, -1233.0, -1207.0 }; -static float LongPathY[7] = { 371.0, 362.0, 488.0, 548.0, 451.0, 346.0, 308.0 }; -static float LongPathZ[7] = { 57.0, 90.0, 105.0, 100.0, 81.0, 79.0, 70.0 }; - -static int PathPoint; - -void -CHeli::ProcessControl(void) -{ - int i; - - if(gbModelViewer) - return; - - // Find target - CVector target(0.0f, 0.0f, 0.0f); - CVector2D vTargetDist; - if(m_heliType == HELI_TYPE_CATALINA && m_heliStatus != HELI_STATUS_SHOT_DOWN){ - switch(m_pathState){ - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - target.x = CatalinaTargetX[m_pathState]; - target.y = CatalinaTargetY[m_pathState]; - target.z = CatalinaTargetZ[m_pathState]; - if((target - GetPosition()).Magnitude() < 9.0f) - m_pathState++; - break; - case 6: - target.x = CatalinaTargetX[m_pathState]; - target.y = CatalinaTargetY[m_pathState]; - target.z = CatalinaTargetZ[m_pathState]; - if(GetPosition().z > 31.55f) - break; - m_pathState = 7; - GetPosition().z = 31.55f; - m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); - break; - case 7: - GetPosition().z = 31.55f; - target = GetPosition(); - break; - - - // Take off - case 8: - target.x = GetPosition().x; - target.y = GetPosition().y; - target.z = 74.0f; - if(GetPosition().z < 40.0f) - break; - PathPoint = 2; - m_pathState = 9; - break; - // Circle around dam - case 9: - target.x = DamPathX[PathPoint]; - target.y = DamPathY[PathPoint]; - target.z = DamPathZ[PathPoint]; - if((target - GetPosition()).Magnitude() < 9.0f){ - PathPoint++; - if(PathPoint >= 6){ - m_pathState = 10; - PathPoint = 0; - } - } - break; - case 10: - target.x = ShortPathX[PathPoint]; - target.y = ShortPathY[PathPoint]; - target.z = ShortPathZ[PathPoint]; - if((target - GetPosition()).Magnitude() < 9.0f){ - PathPoint++; - if(PathPoint >= 3){ - m_pathState = 9; - PathPoint = 1; - } - } - break; - // how do we get here? - case 11: - target.x = LongPathX[PathPoint]; - target.y = LongPathY[PathPoint]; - target.z = LongPathZ[PathPoint]; - if((target - GetPosition()).Magnitude() < 9.0f){ - PathPoint++; - if(PathPoint >= 7){ - m_pathState = 9; - PathPoint = 0; - } - } - break; - - - // Fly away - case 12: - target.x = GetPosition().x; - target.y = GetPosition().y; - target.z = 200.0f; - break; - } - - vTargetDist = target - GetPosition(); - m_fTargetZ = target.z; - if(m_pathState == 6){ - GetPosition().x = GetPosition().x*0.99f + target.x*0.01f; - GetPosition().y = GetPosition().y*0.99f + target.y*0.01f; - } - }else{ - vTargetDist = FindPlayerCoors() - GetPosition(); - m_fTargetZ = FindPlayerCoors().z; - - // Heli flies away to (0, 0) - if(m_heliStatus == HELI_STATUS_FLY_AWAY && GetPosition().z > 20.0f){ - vTargetDist.x = 0.0f - GetPosition().x; - vTargetDist.y = 0.0f - GetPosition().y; - } - - float groundZ; - switch(m_heliStatus){ - case HELI_STATUS_HOVER: - groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f; - break; - case HELI_STATUS_SHOT_DOWN: - groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; - break; - case HELI_STATUS_HOVER2: - groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset; - break; - default: - groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil); - m_fTargetZ = max(groundZ, m_fTargetZ) + 12.0f; - break; - } - - // Move up if too low - if(GetPosition().z - 2.0f < groundZ && m_heliStatus != HELI_STATUS_SHOT_DOWN) - m_vecMoveSpeed.z += CTimer::GetTimeStep()*0.01f; - m_vecMoveSpeed.z = clamp(m_vecMoveSpeed.z, -0.3f, 0.3f); - } - - float fTargetDist = vTargetDist.Magnitude(); - - switch(m_heliStatus){ - case HELI_STATUS_HOVER: - case HELI_STATUS_HOVER2:{ - float targetHeight; - if(m_heliType == HELI_TYPE_CATALINA) - targetHeight = 8.0f; - else - targetHeight = 40.0f - m_nHeliId*10.0f; - if(fTargetDist > targetHeight) - m_heliStatus = HELI_STATUS_CHASE_PLAYER; - } - // fall through, BUG? - case HELI_STATUS_CHASE_PLAYER:{ - float targetHeight; - if(m_heliType == HELI_TYPE_CATALINA) - targetHeight = 4.0f; - else - targetHeight = 30.0f - m_nHeliId*7.5f; - if(fTargetDist < 1.0f || - fTargetDist < targetHeight && CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)) - m_heliStatus = HELI_STATUS_HOVER; - } - } - - // Find xy speed - float speed; - if(fTargetDist > 100.0f) - speed = 1.0f; - else if(fTargetDist > 75.0f) - speed = 0.7f; - else - speed = 0.4f; - if(m_heliStatus == HELI_STATUS_HOVER || m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN) - speed = 0.0f; - - if(fTargetDist != 0.0f) - vTargetDist /= fTargetDist; - else - vTargetDist.x = 1.0f; - CVector2D targetSpeed = vTargetDist * speed; - - if(m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN){ - bool force = !!((CTimer::GetFrameCounter() + m_randomSeed) & 8); - if(m_bTestRight){ - if(force || CWorld::TestSphereAgainstWorld(GetPosition() + 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){ - if(m_heliStatus == HELI_STATUS_SHOT_DOWN){ - m_fTargetOffset -= CTimer::GetTimeStep()*0.05f; - targetSpeed.x -= -vTargetDist.x*0.15f; - targetSpeed.y -= vTargetDist.y*0.15f; - }else{ - targetSpeed.x -= -vTargetDist.x*0.05f; - targetSpeed.y -= vTargetDist.y*0.05f; - } - }else{ - m_bTestRight = false; - if(m_heliStatus == HELI_STATUS_HOVER2) - m_fTargetOffset += 5.0f; - else - m_fTargetOffset -= 5.0f; - } - }else{ - if(force || CWorld::TestSphereAgainstWorld(GetPosition() - 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){ - if(m_heliStatus == HELI_STATUS_SHOT_DOWN){ - m_fTargetOffset -= CTimer::GetTimeStep()*0.05f; - targetSpeed.x += -vTargetDist.x*0.15f; - targetSpeed.y += vTargetDist.y*0.15f; - }else{ - targetSpeed.x += -vTargetDist.x*0.05f; - targetSpeed.y += vTargetDist.y*0.05f; - } - }else{ - m_bTestRight = true; - if(m_heliStatus == HELI_STATUS_HOVER2) - m_fTargetOffset += 5.0f; - else - m_fTargetOffset -= 5.0f; - } - } - - if(m_fTargetOffset > 30.0f) - m_fTargetOffset = 30.0f; - - if(m_heliStatus == HELI_STATUS_SHOT_DOWN && force){ - if(CWorld::TestSphereAgainstWorld(GetPosition() + 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false) || - CWorld::TestSphereAgainstWorld(GetPosition() - 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false)) - m_nExplosionTimer = CTimer::GetPreviousTimeInMilliseconds(); - } - }else - if(m_fTargetOffset >= 2.0f) - m_fTargetOffset -= 2.0f; - - if(m_heliType == HELI_TYPE_CATALINA) - if(m_pathState == 9 || m_pathState == 11 || m_pathState == 10){ - float f = Pow(0.997f, CTimer::GetTimeStep()); - m_vecMoveSpeed.x *= f; - m_vecMoveSpeed.y *= f; - } - - CVector2D speedDir = targetSpeed - m_vecMoveSpeed; - float speedDiff = speedDir.Magnitude(); - if(speedDiff != 0.0f) - speedDir /= speedDiff; - else - speedDir.x = 1.0f; - float speedInc = CTimer::GetTimeStep()*0.002f; - if(speedDiff < speedInc){ - m_vecMoveSpeed.x = targetSpeed.x; - m_vecMoveSpeed.y = targetSpeed.y; - }else{ - m_vecMoveSpeed.x += speedDir.x*speedInc; - m_vecMoveSpeed.y += speedDir.y*speedInc; - } - GetPosition().x += m_vecMoveSpeed.x*CTimer::GetTimeStep(); - GetPosition().y += m_vecMoveSpeed.y*CTimer::GetTimeStep(); - - // Find z target - if(m_heliStatus == HELI_STATUS_FLY_AWAY) - m_fTargetZ = 1000.0f; - if((CTimer::GetTimeInMilliseconds() + 800*m_nHeliId) & 0x800) - m_fTargetZ += 2.0f; - m_fTargetZ += m_nHeliId*5.0f; - - // Find z speed - float targetSpeedZ = (m_fTargetZ - GetPosition().z)*0.01f; - float speedDiffZ = targetSpeedZ - m_vecMoveSpeed.z; - float speedIncZ = CTimer::GetTimeStep()*0.001f; - if(m_heliStatus == HELI_STATUS_FLY_AWAY) - speedIncZ *= 1.5f; - if(Abs(speedDiffZ) < speedIncZ) - m_vecMoveSpeed.z = targetSpeedZ; - else if(speedDiffZ < 0.0f) - m_vecMoveSpeed.z -= speedIncZ; - else - m_vecMoveSpeed.z += speedIncZ*1.5f; - GetPosition().z += m_vecMoveSpeed.z*CTimer::GetTimeStep(); - - // Find angular speed - float targetAngularSpeed; - m_fAngularSpeed *= Pow(0.995f, CTimer::GetTimeStep()); - if(fTargetDist < 8.0f) - targetAngularSpeed = 0.0f; - else{ - float rotationDiff = CGeneral::GetATanOfXY(vTargetDist.x, vTargetDist.y) - m_fRotation; - while(rotationDiff < -3.14f) rotationDiff += 6.28f; - while(rotationDiff > 3.14f) rotationDiff -= 6.28f; - if(Abs(rotationDiff) > 0.4f){ - if(rotationDiff < 0.0f) - targetAngularSpeed = -0.2f; - else - targetAngularSpeed = 0.2f; - }else - targetAngularSpeed = 0.0f; - } - float angularSpeedDiff = targetAngularSpeed - m_fAngularSpeed; - float angularSpeedInc = CTimer::GetTimeStep()*0.0001f; - if(Abs(angularSpeedDiff) < angularSpeedInc) - m_fAngularSpeed = targetAngularSpeed; - else if(angularSpeedDiff < 0.0f) - m_fAngularSpeed -= angularSpeedInc; - else - m_fAngularSpeed += angularSpeedInc; - m_fRotation += m_fAngularSpeed * CTimer::GetTimeStep(); - - // Set matrix - CVector up(3.0f*m_vecMoveSpeed.x, 3.0f*m_vecMoveSpeed.y, 1.0f); - up.Normalise(); - CVector fwd(-Cos(m_fRotation), -Sin(m_fRotation), 0.0f); // not really forward - CVector right = CrossProduct(up, fwd); - fwd = CrossProduct(up, right); - GetRight() = right; - GetForward() = fwd; - GetUp() = up; - - // Search light and shooting - if(m_heliStatus == HELI_STATUS_FLY_AWAY || m_heliType == HELI_TYPE_CATALINA || CCullZones::PlayerNoRain()) - m_fSearchLightIntensity = 0.0f; - else{ - // Update search light history once every 1000ms - int timeDiff = CTimer::GetTimeInMilliseconds() - m_nSearchLightTimer; - while(timeDiff > 1000){ - for(i = 5; i > 0; i--){ - m_aSearchLightHistoryX[i] = m_aSearchLightHistoryX[i-1]; - m_aSearchLightHistoryY[i] = m_aSearchLightHistoryY[i-1]; - } - m_aSearchLightHistoryX[0] = FindPlayerCoors().x + FindPlayerSpeed().x*50.0f*(m_nHeliId+2); - m_aSearchLightHistoryY[0] = FindPlayerCoors().y + FindPlayerSpeed().y*50.0f*(m_nHeliId+2); - - timeDiff -= 1000; - m_nSearchLightTimer += 1000; - } - assert(timeDiff <= 1000); - float f1 = timeDiff/1000.0f; - float f2 = 1.0f - f1; - m_fSearchLightX = m_aSearchLightHistoryX[m_nHeliId+2]*f2 + m_aSearchLightHistoryX[m_nHeliId+2-1]*f1; - m_fSearchLightY = m_aSearchLightHistoryY[m_nHeliId+2]*f2 + m_aSearchLightHistoryY[m_nHeliId+2-1]*f1; - - float searchLightDist = (CVector2D(m_fSearchLightX, m_fSearchLightY) - GetPosition()).Magnitude(); - if(searchLightDist > 60.0f) - m_fSearchLightIntensity = 0.0f; - else if(searchLightDist < 40.0f) - m_fSearchLightIntensity = 1.0f; - else - m_fSearchLightIntensity = 1.0f - (40.0f-searchLightDist)/40.0f; - - if(m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x-m_fSearchLightX) + sq(FindPlayerCoors().y-m_fSearchLightY) > sq(7.0f)) - m_nShootTimer = CTimer::GetTimeInMilliseconds(); - else if(CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer){ - DMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_HELI_PLAYER_FOUND, 0.0f); - m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber()&0xFFF); - } - - // Shoot - int shootTimeout; - if(m_heliType == HELI_TYPE_RANDOM){ - switch(FindPlayerPed()->m_pWanted->m_nWantedLevel){ - case 0: - case 1: - case 2: shootTimeout = 999999; break; - case 3: shootTimeout = 10000; break; - case 4: shootTimeout = 5000; break; - case 5: shootTimeout = 3500; break; - case 6: shootTimeout = 2000; break; - } - if(CCullZones::NoPolice()) - shootTimeout /= 2; - }else - shootTimeout = 1500; - - if(FindPlayerPed()->m_pWanted->IsIgnored()) - m_nShootTimer = CTimer::GetTimeInMilliseconds(); - else{ - // Check if line of sight is clear - if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && - CTimer::GetPreviousTimeInMilliseconds() <= m_nShootTimer + shootTimeout){ - if(CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)){ - if(m_heliStatus == HELI_STATUS_HOVER2) - m_heliStatus = HELI_STATUS_HOVER; - }else{ - m_nShootTimer = CTimer::GetTimeInMilliseconds(); - if(m_heliStatus == HELI_STATUS_HOVER) - m_heliStatus = HELI_STATUS_HOVER2; - } - } - - // Shoot! - if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout && - CTimer::GetTimeInMilliseconds() > m_nLastShotTime + 200){ - CVector shotTarget = FindPlayerCoors(); - // some inaccuracy - shotTarget.x += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f; - shotTarget.y += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f; - CVector direction = FindPlayerCoors() - GetPosition(); - direction.Normalise(); - shotTarget += 3.0f*direction; - CVector shotSource = GetPosition(); - shotSource += 3.0f*direction; - FireOneInstantHitRound(&shotSource, &shotTarget, 20); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); - m_nLastShotTime = CTimer::GetTimeInMilliseconds(); - } - } - } - - // Drop Catalina's bombs - if(m_heliType == HELI_TYPE_CATALINA && m_pathState > 8 && (CTimer::GetTimeInMilliseconds()>>9) != (CTimer::GetPreviousTimeInMilliseconds()>>9)){ - CVector bombPos = GetPosition() - 60.0f*m_vecMoveSpeed; - if(sq(FindPlayerCoors().x-bombPos.x) + sq(FindPlayerCoors().y-bombPos.y) < sq(35.0f)){ - bool found; - float groundZ = CWorld::FindGroundZFor3DCoord(bombPos.x, bombPos.y, bombPos.z, &found); - float waterZ; - if(!CWaterLevel::GetWaterLevelNoWaves(bombPos.x, bombPos.y, bombPos.z, &waterZ)) - waterZ = 0.0f; - if(groundZ > waterZ){ - bombPos.z = groundZ + 2.0f; - CExplosion::AddExplosion(nil, this, EXPLOSION_HELI_BOMB, bombPos, 0); - }else{ - bombPos.z = waterZ; - CVector dir; - for(i = 0; i < 16; i++){ - dir.x = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f; - dir.y = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f; - dir.z = 0.5f; - CParticle::AddParticle(PARTICLE_BOAT_SPLASH, bombPos, dir, nil, 0.2f); - } - } - } - } - - RemoveAndAdd(); - bIsInSafePosition = true; - GetMatrix().UpdateRW(); - UpdateRwFrame(); -} - -void -CHeli::PreRender(void) -{ - float angle; - uint8 i; - CColPoint point; - CEntity *entity; - uint8 r, g, b; - float testLowZ = FindPlayerCoors().z - 10.0f; - float radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f; - int frm = CTimer::GetFrameCounter() & 7; - - i = 0; - for(angle = 0.0f; angle < TWOPI; angle += TWOPI/32){ - CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f); - CVector dir = pos*0.01f; - pos += GetPosition(); - - if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)) - m_fHeliDustZ[frm] = point.point.z; - else - m_fHeliDustZ[frm] = -101.0f; - - switch(point.surfaceB){ - default: - case SURFACE_TARMAC: - r = 10; - g = 10; - b = 10; - break; - case SURFACE_GRASS: - r = 10; - g = 6; - b = 3; - break; - case SURFACE_DIRT: - r = 10; - g = 8; - b = 7; - break; - case SURFACE_DIRTTRACK: - r = 10; - g = 6; - b = 3; - break; - } - RwRGBA col = { r, g, b, 32 }; - pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4? - if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f) - CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col); - i++; - } -} - -void -CHeli::Render(void) -{ - CMatrix mat; - CVector pos; - - mat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_TOPROTOR])); - pos = mat.GetPosition(); - mat.SetRotateZ(m_fRotorRotation); - mat.Translate(pos); - mat.UpdateRW(); - - m_fRotorRotation += 3.14f/6.5f; - if(m_fRotorRotation > 6.28f) - m_fRotorRotation -= 6.28f; - - mat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_BACKROTOR])); - pos = mat.GetPosition(); - mat.SetRotateX(m_fRotorRotation); - mat.Translate(pos); - mat.UpdateRW(); - - CEntity::Render(); -} - -void -CHeli::PreRenderAlways(void) -{ - CVector shadowPos(m_fSearchLightX, m_fSearchLightY, GetPosition().z); - if(m_fSearchLightIntensity > 0.0f){ - CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &shadowPos, - 6.0f, 0.0f, 0.0f, -6.0f, - 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, - 50.0f, true, 1.0f); - - CVector front = GetMatrix() * CVector(0.0f, 7.0f, 0.0f); - CVector toPlayer = FindPlayerCoors() - front; - toPlayer.Normalise(); - float intensity = m_fSearchLightIntensity*sq(CTimeCycle::GetSpriteBrightness()); - if(DotProduct(toPlayer, TheCamera.GetForward()) < -0.8f) - CCoronas::RegisterCorona((uintptr)this, 255*intensity, 255*intensity, 255*intensity, 255, - front, 10.0f, 60.0f, CCoronas::TYPE_STAR, - CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - else - CCoronas::RegisterCorona((uintptr)this, 200*intensity, 200*intensity, 200*intensity, 255, - front, 8.0f, 60.0f, CCoronas::TYPE_STAR, - CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - } - - CVector back = GetMatrix() * CVector(0.0f, -9.0f, 0.0f); - if(CTimer::GetTimeInMilliseconds() & 0x100) - CCoronas::RegisterCorona((uintptr)this + 2, 255, 0, 0, 255, - back, 1.0f, 60.0f, CCoronas::TYPE_STAR, - CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); - else - CCoronas::RegisterCorona((uintptr)this + 2, 0, 0, 0, 255, - back, 1.0f, 60.0f, CCoronas::TYPE_STAR, - CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); -} - -RwObject* -GetHeliAtomicObjectCB(RwObject *object, void *data) -{ - RpAtomic *atomic = (RpAtomic*)object; - assert(RwObjectGetType(object) == rpATOMIC); - if(RpAtomicGetFlags(atomic) & rpATOMICRENDER) - *(RpAtomic**)data = atomic; - return object; -} - -CObject* -CHeli::SpawnFlyingComponent(int32 component) -{ - RpAtomic *atomic; - RwFrame *frame; - RwMatrix *matrix; - CObject *obj; - - if(m_aHeliNodes[component] == nil) - return nil; - - atomic = nil; - RwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic); - if(atomic == nil) - return nil; - - obj = new CObject; - if(obj == nil) - return nil; - - obj->SetModelIndexNoCreate(MI_CAR_WHEEL); - // object needs base model - obj->RefModelInfo(GetModelIndex()); - - // create new atomic - matrix = RwFrameGetLTM(m_aHeliNodes[component]); - frame = RwFrameCreate(); - atomic = RpAtomicClone(atomic); - *RwFrameGetMatrix(frame) = *matrix; - RpAtomicSetFrame(atomic, frame); - CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); - obj->AttachToRwObject((RwObject*)atomic); - - // init object - obj->m_fMass = 10.0f; - obj->m_fTurnMass = 25.0f; - obj->m_fAirResistance = 0.99f; - obj->m_fElasticity = 0.1f; - obj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f; - obj->ObjectCreatedBy = TEMP_OBJECT; - obj->bIsStatic = false; - obj->bIsPickup = false; - - // life time - CObject::nNoTempObjects++; - if(component == HELI_TOPROTOR) - obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 1000; - else - obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 3000; - - obj->m_vecMoveSpeed = m_vecMoveSpeed; - if(obj->m_vecMoveSpeed.z > 0.0f) - obj->m_vecMoveSpeed.z = 0.3f; - else - obj->m_vecMoveSpeed.z = 0.0f; - - obj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f; - - if(component == HELI_BACKROTOR) - obj->m_vecTurnSpeed.x = 0.5f; - else if(component == HELI_TOPROTOR || component == HELI_TOPKNOT) - obj->m_vecTurnSpeed.z = 0.5f; - else - obj->m_vecTurnSpeed.y = 0.5f; - - obj->bRenderScorched = true; - - CWorld::Add(obj); - - atomic = nil; - RwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic); - if(atomic) - RpAtomicSetFlags(atomic, 0); - - return obj; -} - - - -void -CHeli::InitHelis(void) -{ - int i; - - NumRandomHelis = 0; - TestForNewRandomHelisTimer = 0; - NumScriptHelis = 0; - CatalinaHeliOn = false; - ScriptHeliOn = false; - for(i = 0; i < NUM_HELIS; i++) - pHelis[i] = nil; - - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1); - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1); -} - -CHeli* -GenerateHeli(bool catalina) -{ - CHeli *heli; - CVector heliPos; - int i; - - if(catalina) - heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE); - else - heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE); - - if(catalina) - heliPos = CVector(-224.0f, 201.0f, 83.0f); - else{ - heliPos = FindPlayerCoors(); - float angle = (float)(CGeneral::GetRandomNumber() & 0xFF)/0xFF * 6.28f; - heliPos.x += 250.0f*Sin(angle); - heliPos.y += 250.0f*Cos(angle); - if(heliPos.x < -2000.0f || heliPos.x > 2000.0f || heliPos.y < -2000.0f || heliPos.y > 2000.0f){ - // directly above player - heliPos.x -= 250.0f*Sin(angle); - heliPos.y -= 250.0f*Cos(angle); - } - heliPos.z += 50.0f; - } - heli->GetMatrix().SetTranslate(heliPos); - if(catalina) - heli->GetMatrix().SetRotateZOnly(DEGTORAD(270.0f)); // game actually uses 3.14 here - - heli->m_status = STATUS_ABANDONED; - - int id = -1; - bool found = false; - while(!found){ - id++; - found = true; - for(i = 0; i < 4; i++) - if(CHeli::pHelis[i] && CHeli::pHelis[i]->m_nHeliId == id) - found = false; - } - heli->m_nHeliId = id; - - CWorld::Add(heli); - - return heli; -} - -void -CHeli::UpdateHelis(void) -{ - int i, j; - - // Spawn new police helis - int numHelisRequired = FindPlayerPed()->m_pWanted->NumOfHelisRequired(); - if(CStreaming::HasModelLoaded(MI_CHOPPER) && CTimer::GetTimeInMilliseconds() > TestForNewRandomHelisTimer){ - // Spawn a police heli - TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 15000; - if(NumRandomHelis < numHelisRequired){ - NumRandomHelis++; - CHeli *heli = GenerateHeli(false); - heli->m_heliType = HELI_TYPE_RANDOM; - if(pHelis[HELI_RANDOM0] == nil) - pHelis[HELI_RANDOM0] = heli; - else if(pHelis[HELI_RANDOM1] == nil) - pHelis[HELI_RANDOM1] = heli; - else - assert(0 && "too many helis"); - } - } - - // Handle script heli - if(ScriptHeliOn){ - if(CStreaming::HasModelLoaded(MI_CHOPPER) && pHelis[HELI_SCRIPT] == nil){ - pHelis[HELI_SCRIPT] = GenerateHeli(false); - pHelis[HELI_SCRIPT]->m_heliType = HELI_TYPE_SCRIPT; - }else - CStreaming::RequestModel(MI_CHOPPER, 0); - }else{ - if(pHelis[HELI_SCRIPT]) - pHelis[HELI_SCRIPT]->m_heliStatus = HELI_STATUS_FLY_AWAY; - } - - // Handle Catalina's heli - if(CatalinaHeliOn){ - if(CStreaming::HasModelLoaded(MI_ESCAPE) && pHelis[HELI_CATALINA] == nil){ - pHelis[HELI_CATALINA] = GenerateHeli(true); - pHelis[HELI_CATALINA]->m_heliType = HELI_TYPE_CATALINA; - }else - CStreaming::RequestModel(MI_ESCAPE, STREAMFLAGS_DONT_REMOVE); - }else{ - if(pHelis[HELI_CATALINA]) - pHelis[HELI_CATALINA]->m_heliStatus = HELI_STATUS_FLY_AWAY; - } - - // Delete helis that we no longer need - for(i = 0; i < NUM_HELIS; i++) - if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_FLY_AWAY && pHelis[i]->GetPosition().z > 150.0f){ - CWorld::Remove(pHelis[i]); - delete pHelis[i]; - pHelis[i] = nil; - if(i != HELI_SCRIPT && i != HELI_CATALINA) - NumRandomHelis--; - } - - // Handle explosions - for(i = 0; i < NUM_HELIS; i++){ - if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds() > pHelis[i]->m_nExplosionTimer){ - // Second part of explosion - static int nFrameGen; - CRGBA colors[8]; - - TheCamera.CamShake(0.7f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z); - - colors[0] = CRGBA(0, 0, 0, 255); - colors[1] = CRGBA(224, 230, 238, 255); - colors[2] = CRGBA(0, 0, 0, 255); - colors[3] = CRGBA(0, 0, 0, 255); - colors[4] = CRGBA(66, 162, 252, 255); - colors[5] = CRGBA(0, 0, 0, 255); - colors[6] = CRGBA(0, 0, 0, 255); - colors[7] = CRGBA(0, 0, 0, 255); - - CVector pos = pHelis[i]->GetPosition(); - CVector dir; - for(j = 0; j < 40; j++){ - dir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); - dir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f); - dir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f); - int rotSpeed = CGeneral::GetRandomNumberInRange(10, 30); - if(CGeneral::GetRandomNumber() & 1) - rotSpeed = -rotSpeed; - int f = ++nFrameGen & 3; - CParticle::AddParticle(PARTICLE_HELI_DEBRIS, pos, dir, - nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f), - colors[nFrameGen], rotSpeed, 0, f, 0); - } - - CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0); - - pHelis[i]->SpawnFlyingComponent(HELI_SKID_LEFT); - pHelis[i]->SpawnFlyingComponent(HELI_SKID_RIGHT); - pHelis[i]->SpawnFlyingComponent(HELI_TOPROTOR); - - CDarkel::RegisterCarBlownUpByPlayer(pHelis[i]); - CWorld::Remove(pHelis[i]); - delete pHelis[i]; - pHelis[i] = nil; - if(i != HELI_SCRIPT && i != HELI_CATALINA) - NumRandomHelis--; - if(i == HELI_CATALINA) - CatalinaHasBeenShotDown = true; - - CStats::HelisDestroyed++; - CStats::PeopleKilledByOthers += 2; - CStats::PedsKilledOfThisType[PEDTYPE_COP] += 2; - CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250; - pos = CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition(); - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->RegisterCrime_Immediately(CRIME_SHOOT_HELI, - pos, i + 19843, false); - - TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 50000; - }else if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds()+7000 > pHelis[i]->m_nExplosionTimer){ - // First part of explosion - if(CTimer::GetPreviousTimeInMilliseconds()+7000 < pHelis[i]->m_nExplosionTimer){ - pHelis[i]->SpawnFlyingComponent(HELI_BACKROTOR); - pHelis[i]->SpawnFlyingComponent(HELI_TAIL); - pHelis[i]->m_fAngularSpeed *= -2.5f; - pHelis[i]->bRenderScorched = true; - - TheCamera.CamShake(0.4f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z); - - CVector pos = pHelis[i]->GetPosition() - 2.5f*pHelis[i]->GetUp(); - CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0); - }else - pHelis[i]->m_fAngularSpeed *= 1.03f; - } - } - - // Find police helis to remove - for(i = 0; i < 2; i++) - if(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_FLY_AWAY){ - if(numHelisRequired > 0) - numHelisRequired--; - else - pHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY; - } - - // Remove all helis if in a tunnel - if(FindPlayerCoors().z < - 2.0f) - for(i = 0; i < NUM_HELIS; i++) - if(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_SHOT_DOWN) - pHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY; -} - -void -CHeli::SpecialHeliPreRender(void) -{ - int i; - for(i = 0; i < NUM_HELIS; i++) - if(pHelis[i]) - pHelis[i]->PreRenderAlways(); -} - -bool -CHeli::TestRocketCollision(CVector *rocketPos) -{ - int i; - bool hit = false; - - for(i = 0; i < NUM_HELIS; i++){ - if(pHelis[i] && !pHelis[i]->bExplosionProof && (*rocketPos - pHelis[i]->GetPosition()).MagnitudeSqr() < sq(8.0f)){ - pHelis[i]->m_fAngularSpeed = (CGeneral::GetRandomNumber() < RAND_MAX/2) ? 0.05f : -0.05f; - pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN; - pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000; - hit = true; - } - } - return hit; -} - -bool -CHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, int32 damage) -{ - int i; - bool hit = false; - - for(i = 0; i < NUM_HELIS; i++) - if(pHelis[i] && !pHelis[i]->bBulletProof && CCollision::DistToLine(line0, line1, &pHelis[i]->GetPosition()) < 5.0f){ - // Find bullet position - float distToHeli = (pHelis[i]->GetPosition() - *line0).Magnitude(); - CVector line = (*line1 - *line0); - float lineLength = line.Magnitude(); - *bulletPos = *line0 + line*max(1.0f, distToHeli-5.0f); - - pHelis[i]->m_nBulletDamage += damage; - - if(pHelis[i]->m_heliType == HELI_CATALINA && pHelis[i]->m_nBulletDamage > 400 || - pHelis[i]->m_heliType != HELI_CATALINA && pHelis[i]->m_nBulletDamage > 700){ - pHelis[i]->m_fAngularSpeed = (CGeneral::GetRandomNumber() < RAND_MAX/2) ? 0.05f : -0.05f; - pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN; - pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000; - } - - hit = true; - } - return hit; -} - -void CHeli::StartCatalinaFlyBy(void) -{ - CatalinaHeliOn = true; - CatalinaHasBeenShotDown = false; -} - -void -CHeli::RemoveCatalinaHeli(void) -{ - CatalinaHeliOn = false; - if(pHelis[HELI_CATALINA]){ - CWorld::Remove(pHelis[HELI_CATALINA]); - delete pHelis[HELI_CATALINA]; - pHelis[HELI_CATALINA] = nil; - } -} - -CHeli *CHeli::FindPointerToCatalinasHeli(void) { return pHelis[HELI_CATALINA]; } -void CHeli::CatalinaTakeOff(void) { pHelis[HELI_CATALINA]->m_pathState = 8; } -void CHeli::MakeCatalinaHeliFlyAway(void) { pHelis[HELI_CATALINA]->m_pathState = 12; } -bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; } - -void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; } - - -class CHeli_ : public CHeli -{ -public: - void ctor(int32 id, uint8 CreatedBy) { ::new (this) CHeli(id, CreatedBy); } - void dtor(void) { CHeli::~CHeli(); } -}; - -STARTPATCHES - InjectHook(0x547220, &CHeli_::ctor, PATCH_JUMP); - InjectHook(0x5474A0, &CHeli_::dtor, PATCH_JUMP); - InjectHook(0x54AE50, &CHeli::SpawnFlyingComponent, PATCH_JUMP); - InjectHook(0x549970, CHeli::InitHelis, PATCH_JUMP); - InjectHook(0x5499F0, CHeli::UpdateHelis, PATCH_JUMP); - InjectHook(0x54AE10, CHeli::SpecialHeliPreRender, PATCH_JUMP); - InjectHook(0x54AA30, CHeli::TestRocketCollision, PATCH_JUMP); - InjectHook(0x54AB30, CHeli::TestBulletCollision, PATCH_JUMP); - InjectHook(0x54A640, GenerateHeli, PATCH_JUMP); -ENDPATCHES |