diff options
Diffstat (limited to 'src/weapons/Weapon.cpp')
-rw-r--r-- | src/weapons/Weapon.cpp | 160 |
1 files changed, 130 insertions, 30 deletions
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index e8c5c3d1..a895315e 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -194,8 +194,12 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) { - if ( m_nAmmoInClip <= 0 ) - return false; + if (m_nAmmoInClip <= 0) { + if (m_nAmmoTotal <= 0 || m_eWeaponState == WEAPONSTATE_RELOADING) + return false; + + Reload(); + } switch ( m_eWeaponType ) { @@ -223,10 +227,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) { if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) && shooter == FindPlayerPed()) { - addFireRateAsDelay = false; + addFireRateAsDelay = true; fired = FireM16_1stPerson(shooter); } else { - addFireRateAsDelay = true; + addFireRateAsDelay = false; fired = FireInstantHit(shooter, source); } break; @@ -235,8 +239,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) case WEAPONTYPE_SNIPERRIFLE: case WEAPONTYPE_LASERSCOPE: { - fired = FireSniper(shooter); - + if (shooter == FindPlayerPed()) { + fired = FireSniper(shooter); + } else { + fired = FireInstantHit(shooter, source); + } break; } @@ -339,8 +346,12 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if (m_nAmmoInClip == 0) { - if (m_nAmmoTotal == 0) + if (m_nAmmoTotal == 0) { + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA) + CPad::GetPad(0)->Clear(false); + return true; + } m_eWeaponState = WEAPONSTATE_RELOADING; m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; @@ -386,6 +397,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return fired; } +// --MIAMI: Done bool CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) { @@ -401,8 +413,11 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) { DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); - if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; - if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--; + if ( m_nAmmoInClip > 0 ) + m_nAmmoInClip--; + + if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 && (!shooter || shooter->GetStatus() != STATUS_PLAYER || CStats::GetPercentageProgress() < 100.f)) + m_nAmmoTotal--; m_eWeaponState = WEAPONSTATE_FIRING; @@ -418,8 +433,6 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) } m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; - if ( shooter == FindPlayerVehicle() ) - CStats::RoundsFiredByPlayer++; } return true; @@ -898,18 +911,17 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) CWorld::bIncludeDeadPeds = true; - // bProcessVehicleWheels = true; // TODO(Miami) + CWorld::bIncludeCarTyres = true; CWorld::ProcessLineOfSight(src, trgt, point, victim, true, true, true, true, true, false, false, true); // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) CWorld::bIncludeDeadPeds = false; - // bProcessVehicleWheels = false; // TODO(Miami) + CWorld::bIncludeCarTyres = false; - // TODO(Miami) - // if (victim) - // CWeapon::CheckForShootingVehicleOccupant(v39, victim, point, m_eWeaponType, src, trgt); + if (victim) + CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, src, trgt); int32 rotSpeed = 1; - if ( m_eWeaponType == WEAPONTYPE_M4 ) + if ( m_eWeaponType == WEAPONTYPE_M4 ) rotSpeed = 4; CVector bulletPos; @@ -1025,7 +1037,7 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { static uint8 counter = 0; - if ( info->m_nFiringRate >= 50 && !(++counter & 1) ) + if ( info->m_nFiringRate >= 50 || !(++counter & 1) ) { AddGunFlashBigGuns(*fireSource, *fireSource + target); @@ -1579,12 +1591,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target *= info->m_fRange; target += source; CWorld::bIncludeDeadPeds = true; - //bProcessVehicleWheels = true; // TODO(Miami): bProcessVehicleWheels + CWorld::bIncludeCarTyres = true; //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true); CWorld::bIncludeDeadPeds = false; - //bProcessVehicleWheels = false; // TODO(Miami): bProcessVehicleWheels + CWorld::bIncludeCarTyres = false; } else { @@ -2074,7 +2086,7 @@ CWeapon::FireSniper(CEntity *shooter) return true; } -// --MIAMI: Heavily TODO +// --MIAMI: Done bool CWeapon::FireM16_1stPerson(CEntity *shooter) { @@ -2096,10 +2108,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) CWeaponInfo *info = GetInfo(); + CWorld::bIncludeCarTyres = true; + // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami) + CColPoint point; CEntity *victim; - CWorld::bIncludeCarTyres = true; CWorld::pIgnoreEntity = shooter; CWorld::bIncludeDeadPeds = true; @@ -2109,9 +2123,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) CVector source = cam->Source; CVector target = cam->Front*info->m_fRange + source; - ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); - CWorld::bIncludeDeadPeds = false; + if (CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true)) { + CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target); + } CWorld::pIgnoreEntity = nil; + CWorld::bIncludeDeadPeds = false; + // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami) CWorld::bIncludeCarTyres = false; CVector2D front(cam->Front.x, cam->Front.y); @@ -2129,18 +2146,18 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) if ( shooter == FindPlayerPed() ) { - CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - float mult; switch (m_eWeaponType) { case WEAPONTYPE_M4: - case WEAPONTYPE_HELICANNON: - case WEAPONTYPE_M60: mult = 0.0003f; break; case WEAPONTYPE_RUGER: mult = 0.00015f; break; + case WEAPONTYPE_HELICANNON: + case WEAPONTYPE_M60: + mult = 0.0003f; + break; default: mult = 0.0002f; break; @@ -2151,6 +2168,13 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * mult; TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * mult; + + // yes, double + double notFiringRate = (20.0 - info->m_nFiringRate) / 80.0; + double raisedNotFiringRate = Max(1.0, Max(0.0, notFiringRate)); + + uint8 shakeFreq = 80.0 * raisedNotFiringRate + 130.0; + CPad::GetPad(0)->StartShake(20000.0f * CTimer::GetTimeStep() / shakeFreq, shakeFreq); } return true; @@ -2573,9 +2597,10 @@ CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) { - if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) { m_eWeaponState = WEAPONSTATE_OUT_OF_AMMO; - else + // TODO(Miami): CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo + } else m_eWeaponState = WEAPONSTATE_READY; } @@ -2957,6 +2982,81 @@ CWeapon::AddGunFlashBigGuns(CVector start, CVector end) CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f)); } +// --MIAMI: Done +void +CWeapon::CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target) +{ + if (!(*victim)->IsVehicle()) + return; + + CColSphere headSphere; + + CVehicle *veh = (CVehicle*)*victim; + CColPoint origPoint(*point); + float radius = 1.0f; + bool found = false; + CColLine shootLine(source, target); + + if (veh->pDriver && veh->pDriver->bCanBeShotInVehicle) { + CVector pos(0.f, 0.f, 0.f); + veh->pDriver->TransformToNode(pos, PED_HEAD); + headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD); + if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) { + *victim = veh->pDriver; + found = true; + } + } + + for(int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) { + CPed *passenger = veh->pPassengers[i]; + if (passenger && passenger->bCanBeShotInVehicle) { + CVector pos(0.f, 0.f, 0.f); + passenger->TransformToNode(pos, PED_HEAD); + headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD); + if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) { + *victim = passenger; + found = true; + } + } + } + if (veh->IsCar()) { + CVector distVec = target - source; + if (DotProduct(distVec, veh->GetForward()) < 0.0f && DotProduct(distVec, veh->GetUp()) <= 0.0f) { + CColModel *colModel = veh->GetColModel(); + if (colModel->numTriangles > 0) { + bool passesGlass = false; + CMatrix invVehMat; + Invert(veh->GetMatrix(), invVehMat); + shootLine.p0 = invVehMat * shootLine.p0; + shootLine.p1 = invVehMat * shootLine.p1; + CCollision::CalculateTrianglePlanes(colModel); + for (int i = 0; i < colModel->numTriangles; i++) { + if (colModel->triangles[i].surface == SURFACE_GLASS && + CCollision::TestLineTriangle(shootLine, colModel->vertices, colModel->triangles[i], colModel->trianglePlanes[i])) { + passesGlass = true; + break; + } + } + CAutomobile *car = (CAutomobile*)veh; + + // No need to damage windscreen if there isn't one. + if (passesGlass && car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN)) { + if (car->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) == PANEL_STATUS_SMASHED2) + car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN); + + car->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, true); + DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.f); + } + } + } + } + + if (!found) { + *victim = veh; + *point = origPoint; + } +} + #ifdef COMPATIBLE_SAVES #define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); #define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data)); |