diff options
Diffstat (limited to 'src/weapons/Weapon.cpp')
-rw-r--r-- | src/weapons/Weapon.cpp | 1933 |
1 files changed, 1475 insertions, 458 deletions
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 6eab1a65..2d219e2d 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -30,25 +30,47 @@ #include "WaterLevel.h" #include "WeaponInfo.h" #include "World.h" +#include "SurfaceTable.h" +#include "Bike.h" +#include "Glass.h" +#include "Sprite.h" +#include "Pickups.h" #include "SaveBuf.h" -uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = +float fReloadAnimSampleFraction[5] = { 0.5f, 0.7f, 0.75f, 0.75f, 0.7f }; +float fSeaSparrowAimingAngle = 10.0f; +float fHunterAimingAngle = 30.0f; +float fPlayerAimScaleDist = 5.0f; +float fPlayerAimScale = 2.5f; + +bool CWeapon::bPhotographHasBeenTaken; + +#ifdef SECUROM +int32 sniperPirateCheck = 0x00797743; // 'Cwy\0' ??? +#endif + +#ifdef FREE_CAM +static bool +Find3rdPersonCamTargetVectorFromCachedVectors(float dist, CVector pos, CVector& source, CVector& target, CVector camSource, CVector camFront, CVector camUp) { - 0, // UNARMED - 0, // BASEBALLBAT - 250, // COLT45 - 400, // UZI - 650, // SHOTGUN - 300, // AK47 - 300, // M16 - 423, // SNIPERRIFLE - 400, // ROCKETLAUNCHER - 0, // FLAMETHROWER - 0, // MOLOTOV - 0, // GRENADE - 0, // DETONATOR - 0 // HELICANNON -}; + if (CPad::GetPad(0)->GetLookBehindForPed()) { + source = pos; + target = dist * FindPlayerPed()->GetForward() + source; + return false; + } else { + float angleX = DEGTORAD((CCamera::m_f3rdPersonCHairMultX - 0.5f) * 1.8f * 0.5f * TheCamera.Cams[TheCamera.ActiveCam].FOV * CDraw::GetAspectRatio()); + float angleY = DEGTORAD((0.5f - CCamera::m_f3rdPersonCHairMultY) * 1.8f * 0.5f * TheCamera.Cams[TheCamera.ActiveCam].FOV); + source = camSource; + target = camFront; + target += camUp * Tan(angleY); + target += CrossProduct(camFront, camUp) * Tan(angleX); + target.Normalise(); + source += DotProduct(pos - source, target) * target; + target = dist * target + source; + return true; + } +} +#endif CWeaponInfo * CWeapon::GetInfo() @@ -58,6 +80,17 @@ CWeapon::GetInfo() return info; } +CWeapon::CWeapon(eWeaponType type, int32 ammo) +{ + m_eWeaponType = type; + m_eWeaponState = WEAPONSTATE_READY; + m_nAmmoTotal = Min(ammo, 99999); + m_nAmmoInClip = 0; + Reload(); + m_nTimer = 0; + m_bAddRotOffset = false; +} + void CWeapon::InitialiseWeapons(void) { @@ -66,6 +99,7 @@ CWeapon::InitialiseWeapons(void) CExplosion::Initialise(); CProjectileInfo::Initialise(); CBulletInfo::Initialise(); + bPhotographHasBeenTaken = false; } void @@ -87,18 +121,41 @@ CWeapon::UpdateWeapons(void) CBulletInfo::Update(); } + void CWeapon::Initialise(eWeaponType type, int32 ammo) { m_eWeaponType = type; m_eWeaponState = WEAPONSTATE_READY; - if (ammo > 99999) - m_nAmmoTotal = 99999; - else - m_nAmmoTotal = ammo; + m_nAmmoTotal = Min(ammo, 99999); m_nAmmoInClip = 0; Reload(); m_nTimer = 0; + int32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; + int32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; + + if ( modelId != -1 ) + CModelInfo::GetModelInfo(modelId)->AddRef(); + if ( model2Id != -1 ) + CModelInfo::GetModelInfo(model2Id)->AddRef(); +} + +void +CWeapon::Shutdown() +{ + int32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId; + if (modelId != -1) + CModelInfo::GetModelInfo(modelId)->RemoveRef(); + + int32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id; + if (model2Id != -1) + CModelInfo::GetModelInfo(model2Id)->RemoveRef(); + + m_eWeaponType = WEAPONTYPE_UNARMED; + m_eWeaponState = WEAPONSTATE_READY; + m_nAmmoInClip = 0; + m_nAmmoTotal = 0; + m_nTimer = 0; } bool @@ -108,19 +165,18 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; - - if (!fireSource) - { - fireOffset = shooter->GetMatrix() * fireOffset; #ifdef FIX_BUGS - static CVector tmp; - tmp = fireOffset; - source = &tmp; + static CVector shooterSource; #else - source = &fireOffset; + CVector shooterSource; #endif - + + if ( !fireSource ) + { + shooterSource = shooter->GetMatrix() * fireOffset; + source = &shooterSource; } + if ( m_bAddRotOffset ) { float heading = RADTODEG(shooter->GetForward().Heading()); @@ -133,44 +189,60 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return false; bool fired; + bool addFireRateAsDelay = true; 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 ) { case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: { + addFireRateAsDelay = true; fired = FireShotgun(shooter, source); break; } - case WEAPONTYPE_COLT45: - case WEAPONTYPE_UZI: - case WEAPONTYPE_AK47: - { - fired = FireInstantHit(shooter, source); - - break; - } - case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: { - fired = FireSniper(shooter); - + if (shooter == FindPlayerPed()) + fired = FireSniper(shooter); + else + fired = FireInstantHit(shooter, source); + break; } - - case WEAPONTYPE_M16: + + case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_UZI: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: { - if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() ) + if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON) + && shooter == FindPlayerPed()) { + addFireRateAsDelay = true; fired = FireM16_1stPerson(shooter); - else + } else { + addFireRateAsDelay = false; fired = FireInstantHit(shooter, source); - + } break; } @@ -193,12 +265,12 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) case WEAPONTYPE_MOLOTOV: case WEAPONTYPE_GRENADE: + case WEAPONTYPE_DETONATOR_GRENADE: + case WEAPONTYPE_TEARGAS: { if ( shooter == FindPlayerPed() ) { fired = FireProjectile(shooter, source, ((CPlayerPed*)shooter)->m_fAttackButtonCounter*0.0375f); - if ( m_eWeaponType == WEAPONTYPE_GRENADE ) - CStats::KgsOfExplosivesUsed++; } else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { @@ -210,6 +282,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) else fired = FireProjectile(shooter, source, 0.3f); + if (m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) { + ((CPed*)shooter)->GiveWeapon(WEAPONTYPE_DETONATOR, 1, true); + ((CPed*)shooter)->GetWeapon(((CPed*)shooter)->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY; + ((CPed*)shooter)->SetCurrentWeapon(WEAPONTYPE_DETONATOR); + } break; } @@ -229,16 +306,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) break; } - - case WEAPONTYPE_HELICANNON: + + case WEAPONTYPE_CAMERA: { - if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ) - && shooter == FindPlayerPed() ) - { - fired = FireM16_1stPerson(shooter); - } - else - fired = FireInstantHit(shooter, source); + fired = TakePhotograph(shooter); break; } @@ -257,17 +328,65 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if (shooter->IsPed()) { CPed* shooterPed = (CPed*)shooter; - - shooterPed->bIsShooting = true; - - if (shooterPed->IsPlayer()) - isPlayer = true; - + + if ( m_eWeaponType != WEAPONTYPE_CAMERA ) + { + shooterPed->bIsShooting = true; + + if (shooterPed->IsPlayer()) + isPlayer = true; + } + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + + if ( isPlayer ) + { + CPed *aimPed = (CPed *)shooterPed->m_pSeekTarget; + if ( aimPed ) + { + if ( aimPed->IsPed() ) + shooterPed->Say(SOUND_PED_ON_FIRE); + } + } } + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_SPAS12_SHOTGUN: + case WEAPONTYPE_STUBBY_SHOTGUN: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + CStats::RoundsFiredByPlayer++; + break; + + case WEAPONTYPE_GRENADE: + case WEAPONTYPE_DETONATOR_GRENADE: + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_ROCKET: + case WEAPONTYPE_ROCKETLAUNCHER: + case WEAPONTYPE_DETONATOR: + case WEAPONTYPE_HELICANNON: + CStats::KgsOfExplosivesUsed++; + break; + } + + + if (m_nAmmoInClip > 0) + m_nAmmoInClip--; - if (m_nAmmoInClip > 0) m_nAmmoInClip--; - if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer)) m_nAmmoTotal--; + if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR)) + m_nAmmoTotal--; if (m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); @@ -276,8 +395,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; @@ -291,9 +414,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) return true; } - m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; - if (shooter == FindPlayerPed()) - CStats::RoundsFiredByPlayer++; + if ( addFireRateAsDelay ) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate; + else + m_nTimer = CTimer::GetTimeInMilliseconds(); } } else @@ -302,9 +426,14 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) { m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; m_eWeaponState = WEAPONSTATE_FIRING; + + if (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW) + { + DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, SOUND_MELEE_ATTACK_START, m_eWeaponType << 8); + } } - FireMelee(shooter, *source); + fired = FireMelee(shooter, *source); } if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) @@ -314,7 +443,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } bool -CWeapon::FireFromCar(CAutomobile *shooter, bool left) +CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right) { ASSERT(shooter!=nil); @@ -324,12 +453,15 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left) if ( m_nAmmoInClip <= 0 ) return false; - if ( FireInstantHitFromCar(shooter, left) ) + if ( FireInstantHitFromCar(shooter, left, 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; @@ -345,8 +477,6 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left) } m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; - if ( shooter == FindPlayerVehicle() ) - CStats::RoundsFiredByPlayer++; } return true; @@ -360,27 +490,45 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) CWeaponInfo *info = GetInfo(); bool anim2Playing = false; - if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) ) - anim2Playing = true; - + + if ( CPed::GetFireAnimGround(info, false) != (AnimationId)0 ) + { + if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false)) ) + anim2Playing = true; + } + ASSERT(shooter->IsPed()); CPed *shooterPed = (CPed*)shooter; + if (shooterPed == FindPlayerPed()) + { + if (m_eWeaponType == WEAPONTYPE_GOLFCLUB || m_eWeaponType == WEAPONTYPE_NIGHTSTICK || + (m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW)) + { + CGlass::BreakGlassPhysically(fireSource, info->m_fRadius); + + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); + } + } + + int damageEntityRegistered = 0; + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) { CPed *victimPed = shooterPed->m_nearPeds[i]; ASSERT(victimPed!=nil); if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) - && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) + && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) + && (!shooterPed->IsGangMember() || victimPed->CanBeDamagedByThisGangMember(shooterPed)) ) { bool collided = false; - CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; - if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) - victimPedCol = &CTempColModels::ms_colModelPedGroundHit; - + if (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE + || info->IsFlagSet(WEAPONFLAG_FIGHTMODE))) + continue; float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) @@ -389,12 +537,28 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( SQR(victimPedRadius) > (victimPedPos-fireSource).MagnitudeSqr() ) { CVector collisionDist; + CColModel* victimPedCol = &CTempColModels::ms_colModelPed1; + bool useLocalPos = false; + if (victimPed->m_nPedState == PED_FALL + || victimPed->m_nPedState == PED_DIE && victimPed->bIsPedDieAnimPlaying + || victimPed->m_nWaitState == WAITSTATE_SIT_IDLE + || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) + { + useLocalPos = true; + victimPedCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(victimPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(victimPed->GetClump()); + } else if (victimPed->DyingOrDead()) { + victimPedCol = &CTempColModels::ms_colModelPedGroundHit; + } int32 s = 0; while ( s < victimPedCol->numSpheres ) { CColSphere *sphere = &victimPedCol->spheres[s]; - collisionDist = victimPedPos+sphere->center-fireSource; + + if (useLocalPos) + collisionDist = sphere->center - fireSource; + else + collisionDist = victimPedPos + sphere->center - fireSource; if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { @@ -415,65 +579,127 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) int32 localDir = victimPed->GetLocalDirection(posOffset); - bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + bool isHeavy = m_eWeaponType >= WEAPONTYPE_GOLFCLUB && m_eWeaponType <= WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_HAMMER; + + if (shooterPed->m_fDamageImpulse == 0.0f) + { + shooterPed->m_pDamageEntity = victimPed; + victimPed->RegisterReference(&shooterPed->m_pDamageEntity); + } + + damageEntityRegistered = 3; + if (victimPed->bInVehicle) + { + CVehicle *victimVeh = victimPed->m_pMyVehicle; + if (victimVeh) + { + if (victimVeh->IsBike()) + { + CBike *victimBike = (CBike*)victimVeh; + victimBike->KnockOffRider(m_eWeaponType, localDir, victimPed, false); + if (victimBike->pDriver) + victimBike->pDriver->ReactToAttack(shooterPed); + else + { + if (victimVeh->pPassengers[0]) + victimVeh->pPassengers[0]->ReactToAttack(shooterPed); + } + continue; + } + } + } if ( !victimPed->DyingOrDead() ) victimPed->ReactToAttack(shooterPed); uint8 hitLevel = HITLEVEL_HIGH; - if ( isBat && victimPed->OnGround() ) + if ( isHeavy && (victimPed->OnGround() || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE)) hitLevel = HITLEVEL_GROUND; victimPed->StartFightDefend(localDir, hitLevel, 10); if ( !victimPed->DyingOrDead() ) { - if ( shooterPed->IsPlayer() && isBat && anim2Playing ) + if ( shooterPed->IsPlayer() && isHeavy && anim2Playing ) victimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir); else if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive ) victimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir); else { - if ( victimPed->IsPlayer() && isBat ) // wtf, it's not fair + if ( victimPed->IsPlayer() && isHeavy ) // wtf, it's not fair victimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir); else victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); } } - if ( CGame::nastyGame ) + if ( CGame::nastyGame && victimPed->GetIsOnScreen() ) { - if ( victimPed->GetIsOnScreen() ) - { - CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); + CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + if ( isHeavy ) + { + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + } - if ( isBat ) + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + if (victimPed->m_nPedState != PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 1) + || victimPed->m_nPedState == PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 3)) { - dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - - dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); - CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_TEST, bloodPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f); } + CVector newDir(dir); + newDir.z += 0.2f; + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, bloodPos, newDir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir); + newDir.z = dir.z + 0.1f; + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir); + newDir.x = 0.0f; + newDir.y = 0.0f; + newDir.z = 0.01f; + CParticle::AddParticle(PARTICLE_DEBRIS2, bloodPos, newDir); + + CVector dropDir(CGeneral::GetRandomNumberInRange(-0.15f, 0.15f), CGeneral::GetRandomNumberInRange(0.1f, 0.35f), 0.f); + CVector dropPos(CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_X(50.0f), SCREEN_STRETCH_FROM_RIGHT(50.0f)), + CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_Y(50.0f), SCREEN_STRETCH_FROM_BOTTOM(50.0f)), 1.f); + CParticle::AddParticle(PARTICLE_BLOODDROP, dropPos, dropDir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.15f), + CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 0); + + } + if (info->m_AnimToPlay == ASSOCGRP_KNIFE) + { + dir += 0.1f * shooterPed->GetUp() + 0.05f * shooterPed->GetRight(); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir); } } if ( !victimPed->OnGround() ) { if ( victimPed->m_fHealth > 0.0f - && (victimPed->m_fHealth < 20.0f && victimPedHealth > 20.0f || isBat && !victimPed->IsPlayer()) ) + && (victimPed->m_fHealth < 30.0f && victimPedHealth > 30.0f || + (isHeavy || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) && !victimPed->IsPlayer()) ) { posOffset.Normalise(); victimPed->bIsStanding = false; - victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + if(m_eWeaponType == WEAPONTYPE_CHAINSAW) + victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 2.0f); + else + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); - if ( isBat && victimPed->IsPlayer() ) + if ( isHeavy && victimPed->IsPlayer() ) victimPed->SetFall(3000, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false); else victimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false); @@ -486,21 +712,151 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { posOffset.Normalise(); victimPed->bIsStanding = false; - victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + if(m_eWeaponType == WEAPONTYPE_CHAINSAW) + victimPed->ApplyMoveForce(posOffset.x*-1.0f, posOffset.y*-1.0f, 1.0f); + else + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); } m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; - if ( victimPed->m_nPedType == PEDTYPE_COP ) - CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); - else - CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + if (m_eWeaponType != WEAPONTYPE_KNIFE && m_eWeaponType != WEAPONTYPE_MACHETE + && m_eWeaponType != WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_CHAINSAW) { + + if (victimPed->m_nPedType == PEDTYPE_COP) + CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } else { + if (victimPed->m_nPedType == PEDTYPE_COP) + CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } } } } } } } + CVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, false, true, false, false, false, false); + if (nearVeh && nearVeh->IsCar()) + { + CAutomobile *nearCar = (CAutomobile*)nearVeh; + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + if (shooterPed == FindPlayerPed()) + { + if (nearCar->IsLawEnforcementVehicle()) + { + FindPlayerPed()->SetWantedLevelNoDrop(1); + } + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_VEHICLE, nearCar, shooterPed, 2000); + } + float oldHealth = nearCar->m_fHealth; + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + for( int32 i=0; i<4; i++ ) + { + CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f)); + CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, gaTempSphereColPoints[0].normal * 0.1f); + } + } + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + nearCar->VehicleDamage(info->m_nDamage * (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); + + CParticle::AddParticle(PARTICLE_HEATHAZE, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0); + } + else + { + nearCar->VehicleDamage(info->m_nDamage* (0.01f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB); + } + if (nearCar->m_fHealth < oldHealth) + { + nearCar->m_nLastWeaponDamage = m_eWeaponType; + nearCar->m_pLastDamageEntity = shooterPed; + } + if (shooterPed->m_fDamageImpulse == 0.0f) + { + shooterPed->m_pDamageEntity = nearCar; + nearCar->RegisterReference(&shooterPed->m_pDamageEntity); + } + damageEntityRegistered = 2; + if (FindPlayerPed()->GetWeapon() == this && nearCar->VehicleCreatedBy != MISSION_VEHICLE) + { + if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH + && (CGeneral::GetRandomTrueFalse() || nearCar->AutoPilot.m_nCarMission != MISSION_CRUISE)) + { + int leaveCarDelay = 200; + CPed *driver = nearCar->pDriver; + if (driver && driver->CharCreatedBy != MISSION_CHAR) + { + if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear) + { + driver->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + } + else + { + driver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed()); + driver->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; + driver->m_prevObjective = OBJECTIVE_KILL_CHAR_ON_FOOT; + } + driver->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 200; + leaveCarDelay = 400; + } + for (int j = 0; j < nearCar->m_nNumPassengers; ++j) + { + CPed *passenger = nearCar->pPassengers[j]; + if (passenger && passenger->CharCreatedBy != MISSION_CHAR) + { + nearCar->pPassengers[j]->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE); + passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + leaveCarDelay; + leaveCarDelay += 200; + } + } + } + else + { + CPed *driver = nearCar->pDriver; + if (driver) + { + if (driver->m_objective != OBJECTIVE_LEAVE_CAR && driver->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && + driver->m_objective != OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE) + { + if (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH) + nearCar->AutoPilot.m_nCruiseSpeed = nearCar->AutoPilot.m_nCruiseSpeed * 1.5f; + + nearCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH; + } + } + } + } + } + if (m_eWeaponType == WEAPONTYPE_CHAINSAW) + { + CEntity *nearStatic = (CObject*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, true, false, false, true, false, false); + if (nearStatic) + { + for(int i=0; i < 4; i++) { + CParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f), 0, 0.0f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, 0.1f * gaTempSphereColPoints[0].normal, 0, 0.0f, 0, 0, 0, 0); + } + + CParticle::AddParticle(PARTICLE_HEATHAZE, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0); + + if (!damageEntityRegistered) + { + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + if (shooterPed->m_fDamageImpulse == 0.0f) + { + shooterPed->m_pDamageEntity = nearStatic; + nearStatic->RegisterReference(&shooterPed->m_pDamageEntity); + } + } + if (nearStatic->IsObject() && ((CObject*)nearStatic)->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY) + ((CObject*)nearStatic)->ObjectDamage(200.0f); + } + } return true; } @@ -542,9 +898,6 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) int32 accuracy = shooterPed->m_wepAccuracy; int32 inaccuracy = 100-accuracy; - if ( accuracy != 100 ) - FindPlayerPed(); //what ? - CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; if ( threatAttack->IsPed() ) { @@ -555,19 +908,40 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) target = threatAttack->GetPosition(); target -= *fireSource; - target *= info->m_fRange / target.Magnitude(); + float distToTarget = Max(target.Magnitude(), 0.01f); + target *= info->m_fRange / distToTarget; target += *fireSource; - if ( inaccuracy != 0 ) + if (shooter == FindPlayerPed() && inaccuracy != 0.f) + { + float newInaccuracy = fPlayerAimScale * FindPlayerPed()->m_fAttackButtonCounter * (inaccuracy * Min(1.f, fPlayerAimScaleDist / distToTarget)); + if (FindPlayerPed()->bIsDucking) + newInaccuracy *= 0.4f; + + target.x += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f) * newInaccuracy; + target.y += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f) * newInaccuracy; + target.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * newInaccuracy; + FindPlayerPed()->m_fAttackButtonCounter += info->m_nDamage * 0.04f; + } + else if (inaccuracy > 0.f) { + if (threatAttack == FindPlayerPed()) + { + float speed = Min(0.33f, FindPlayerPed()->m_vecMoveSpeed.Magnitude()); + inaccuracy *= (0.3f * speed * 100.f / 33.f + 0.8f); + } target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy; } - CWorld::bIncludeDeadPeds = true; - ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + if (shooter == FindPlayerPed()) + CWorld::bIncludeDeadPeds = true; + + CWorld::bIncludeBikers = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); CWorld::bIncludeDeadPeds = false; + CWorld::bIncludeBikers = false; } else { @@ -577,11 +951,13 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) shooterPed->TransformToNode(target, PED_HANDR); - ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeBikers = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); + CWorld::bIncludeBikers = false; } #ifdef FIX_BUGS // fix muzzleflash rotation - heading = CGeneral::GetAngleBetweenPoints(fireSource->x, fireSource->y, target.x, target.y); + heading = CGeneral::GetAngleBetweenPoints(source.x, source.y, target.x, target.y); angle = DEGTORAD(heading); ahead = CVector2D(-Sin(angle), Cos(angle)); @@ -590,38 +966,49 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } else if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) { - CVector src, trgt; - TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); #ifdef FREE_CAM - CPed *shooterPed = (CPed *)shooter; - if((shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY) == 0) { - trgt.x = info->m_fRange; - trgt.y = 0.0f; - trgt.z = 0.0f; + if (CCamera::bFreeCam) { + CPlayerPed* shooterPed = (CPlayerPed*)shooter; + Find3rdPersonCamTargetVectorFromCachedVectors(info->m_fRange, *fireSource, source, target, shooterPed->m_cachedCamSource, shooterPed->m_cachedCamFront, shooterPed->m_cachedCamUp); - shooterPed->TransformToNode(trgt, PED_HANDR); - } + if ((shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY) == 0) { + target.x = info->m_fRange; + target.y = 0.0f; + target.z = 0.0f; + + shooterPed->TransformToNode(target, PED_HANDR); + } + } else #endif + { + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); + } #ifdef FIX_BUGS // fix muzzleflash rotation - heading = CGeneral::GetAngleBetweenPoints(src.x, src.y, trgt.x, trgt.y); + heading = CGeneral::GetAngleBetweenPoints(source.x, source.y, target.x, target.y); angle = DEGTORAD(heading); ahead = CVector2D(-Sin(angle), Cos(angle)); ahead.Normalise(); #endif - + CWorld::bIncludeBikers = true; CWorld::bIncludeDeadPeds = true; - ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeCarTyres = true; + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); + CWorld::bIncludeBikers = false; CWorld::bIncludeDeadPeds = false; + CWorld::bIncludeCarTyres = false; + + if (victim) + CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target); int32 rotSpeed = 1; - if ( m_eWeaponType == WEAPONTYPE_M16 ) + if ( m_eWeaponType == WEAPONTYPE_M4 ) rotSpeed = 4; CVector bulletPos; - if ( CHeli::TestBulletCollision(&src, &trgt, &bulletPos, 4) ) + if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) ) { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); @@ -629,140 +1016,117 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } else { - float shooterHeading = RADTODEG(shooter->GetForward().Heading()); - float shooterAngle = DEGTORAD(shooterHeading); + uint32 model = shooter->GetModelIndex(); + if (model == MI_HUNTER || model == MI_SEASPAR || model == MI_SPARROW) + { + float inaccuracyMult = 0.6f; + target = shooter->GetForward(); + if (shooter->GetStatus() == STATUS_PLAYER) + { + target *= info->m_fRange; + target += *fireSource; + CWeapon::DoDriveByAutoAiming(FindPlayerPed(), (CVehicle*)shooter, fireSource, &target); + target -= *fireSource; + target.Normalise(); + if (model == MI_SEASPAR || model == MI_SPARROW) + inaccuracyMult = 0.1f; + else + inaccuracyMult = 0.3f; + } + target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracyMult; + target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracyMult; + target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracyMult; - CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); - rotOffset.Normalise(); + target.Normalise(); + target *= info->m_fRange; + target += *fireSource; + CWorld::pIgnoreEntity = shooter; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::pIgnoreEntity = nil; - target = *fireSource; - target.x += rotOffset.x * info->m_fRange; - target.y += rotOffset.y * info->m_fRange; + int32 rotSpeed = 1; + if (m_eWeaponType == WEAPONTYPE_M4) + rotSpeed = 4; - if ( shooter->IsPed() ) - DoDoomAiming(shooter, fireSource, &target); + CVector bulletPos; + if (CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4)) + { + for (int32 i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); + } + } + else + { + float shooterHeading = RADTODEG(shooter->GetForward().Heading()); + float shooterAngle = DEGTORAD(shooterHeading); - ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); + rotOffset.Normalise(); - int32 rotSpeed = 1; - if ( m_eWeaponType == WEAPONTYPE_M16 ) - rotSpeed = 4; + target = *fireSource; + target.x += rotOffset.x * info->m_fRange; + target.y += rotOffset.y * info->m_fRange; - CVector bulletPos; - if ( CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4) ) - { - for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); + CParticle::HandleShootableBirdsStuff(shooter, *fireSource); + if (shooter->IsPed() && ((CPed*)shooter)->bDoomAim && (shooter != FindPlayerPed() || !info->IsFlagSet(WEAPONFLAG_CANAIM))) + { + CWeapon::DoDoomAiming(shooter, fireSource, &target); + } + + CWorld::bIncludeBikers = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); + CWorld::bIncludeBikers = false; + + int32 rotSpeed = 1; + if (m_eWeaponType == WEAPONTYPE_M4) + rotSpeed = 4; + + CVector bulletPos; + if (CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4)) + { + for (int32 i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); + } } } - if ( victim && shooter->IsPed() && victim == ((CPed*)shooter)->m_leader ) - return false; + if ( shooter->IsPed() && victim) + { + if (victim == ((CPed*)shooter)->m_leader) + return false; + + if (victim->IsPed() && ((CPed*)shooter)->IsGangMember() && !((CPed*)victim)->CanBeDamagedByThisGangMember((CPed*)shooter)) + return false; + } - CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); + if (shooter->IsPed()) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); + else if (shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000); if ( shooter == FindPlayerPed() ) { - CStats::InstantHitsFiredByPlayer++; if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target); } switch ( m_eWeaponType ) { - case WEAPONTYPE_AK47: - { - static uint8 counter = 0; - - if ( !(++counter & 1) ) - { - CPointLights::AddLight(CPointLights::LIGHT_POINT, - *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, - 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - - CVector gunflashPos = *fireSource; - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.10f); - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); - gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - - CVector gunsmokePos = *fireSource; - float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - - CVector gunshellPos = *fireSource; - gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); - CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); - dir.Normalise2D(); - AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); - } - - break; - } - - case WEAPONTYPE_M16: + case WEAPONTYPE_M4: + case WEAPONTYPE_RUGER: + case WEAPONTYPE_M60: + case WEAPONTYPE_MINIGUN: + case WEAPONTYPE_HELICANNON: { static uint8 counter = 0; - if ( !(++counter & 1) ) + if ( info->m_nFiringRate >= 50 || !(++counter & 1) ) { - CPointLights::AddLight(CPointLights::LIGHT_POINT, - *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, - 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - - CVector gunflashPos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); - - gunflashPos = *fireSource; - gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); - gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - gunflashPos.z += 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - gunflashPos = *fireSource; - gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); - gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - gunflashPos.z -= 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); - offset.Normalise2D(); - - gunflashPos = *fireSource; - gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); - gunflashPos += CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos += CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); - gunflashPos += CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - gunflashPos = *fireSource; - gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); - gunflashPos -= CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); - gunflashPos -= CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); - gunflashPos -= CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); - - CVector gunsmokePos = *fireSource; - float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); +#ifdef FIX_BUGS + AddGunFlashBigGuns(*fireSource, target); +#else + AddGunFlashBigGuns(*fireSource, *fireSource + target); +#endif CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f); @@ -775,6 +1139,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } case WEAPONTYPE_UZI: + case WEAPONTYPE_TEC9: + case WEAPONTYPE_SILENCED_INGRAM: + case WEAPONTYPE_MP5: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -813,6 +1180,9 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } case WEAPONTYPE_COLT45: + case WEAPONTYPE_PYTHON: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_LASERSCOPE: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -851,6 +1221,71 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } void +CWeapon::AddGunFlashBigGuns(CVector start, CVector end) +{ + CPointLights::AddLight(CPointLights::LIGHT_POINT, + start, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + CVector gunflashPos = start; + + CVector shootVec = end - start; + + // Wtf did you do there R*? + shootVec.Normalise(); + CVector2D ahead = shootVec; + ahead.Normalise(); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); + gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + gunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos.z += 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos.z -= 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + offset.Normalise2D(); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos += CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos += CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); + gunflashPos += CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + gunflashPos = start; + gunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f); + gunflashPos -= CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + gunflashPos -= CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); + gunflashPos -= CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + + CVector gunsmokePos = start; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f)); +} + +void CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) { ASSERT(shooter!=nil); @@ -879,6 +1314,7 @@ CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &d } } + void CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead) @@ -892,72 +1328,99 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victim ) { - CGlass::WasGlassHitByBullet(victim, point->point); - - CVector traceTarget = point->point; - CBulletTraces::AddTrace(source, &traceTarget); - - if ( shooter != nil ) + if (shooter) { - if ( shooter == FindPlayerPed() ) + if (shooter && shooter->IsPed() && ((CPed*)shooter)->m_attachedTo == victim) + return; + + if (shooter->IsPed() && !((CPed*)shooter)->IsPlayer()) { - if ( victim->IsPed() || victim->IsVehicle() ) - CStats::InstantHitsHitByPlayer++; + CPed* shooterPed = (CPed*)shooter; + CEntity* guyWePointGun = shooterPed->m_pPointGunAt; + if (guyWePointGun) + { + if (victim != guyWePointGun) + { + float distWithAim = (guyWePointGun->GetPosition() - shooter->GetPosition()).Magnitude(); + float distWithBullet = (point->point - shooter->GetPosition()).Magnitude(); + if (distWithAim > 0.1f && distWithBullet > 0.1f) + { + // Normalize + CVector aimDir = (guyWePointGun->GetPosition() - shooter->GetPosition()) * (1.0f / distWithAim); + CVector bulletDir = (point->point - shooter->GetPosition()) * (1.0f / distWithBullet); + + float dotProd = DotProduct(aimDir, bulletDir); + float aimAndBulletAngle; + if (dotProd <= 0.35f) + aimAndBulletAngle = PI; + else + aimAndBulletAngle = Acos(dotProd); + + if (aimAndBulletAngle <= DEGTORAD(45.0f) && (aimAndBulletAngle <= DEGTORAD(15.0f) || distWithBullet / distWithAim >= 0.75f) && distWithBullet / distWithAim >= 0.99f) + { + shooterPed->bObstacleShowedUpDuringKillObjective = false; + shooterPed->m_shotTime = 0; + } + else + { + shooterPed->bObstacleShowedUpDuringKillObjective = true; + shooterPed->m_shootTimer = 0; + shooterPed->m_shotTime = CTimer::GetTimeInMilliseconds(); + if (distWithAim < 10.0f) + shooterPed->SetAttackTimer(1500); + else + shooterPed->SetAttackTimer(3000); + } + } + } + } } } + CGlass::WasGlassHitByBullet(victim, point->point); + + CVector traceTarget = point->point; + CBulletTraces::AddTrace(source, &traceTarget, m_eWeaponType, shooter); - if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) + if (victim->IsPed() && shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver) + shooter = ((CVehicle*)shooter)->pDriver; + + if ( victim->IsPed() && shooter->IsPed() && + (((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 || + !((CPed*)shooter)->IsGangMember() && ((CPed*)shooter)->m_nPedType != PEDTYPE_COP)) { CPed *victimPed = (CPed *)victim; if ( !victimPed->DyingOrDead() && victim != shooter ) { - if ( victimPed->DoesLOSBulletHitPed(*point) ) - { - CVector pos = victimPed->GetPosition(); + CVector pos = victimPed->GetPosition(); - CVector2D posOffset(source->x-pos.x, source->y-pos.y); - int32 localDir = victimPed->GetLocalDirection(posOffset); + CVector2D posOffset(source->x-pos.x, source->y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); - victimPed->ReactToAttack(shooter); + victimPed->ReactToAttack(shooter); - if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) + if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) + { + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + else + { + if ( victimPed->bCanBeShotInVehicle && (IsShotgun(m_eWeaponType) || + (!victimPed->IsPlayer() && (m_eWeaponType == WEAPONTYPE_HELICANNON || m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_PYTHON)))) { + posOffset.Normalise(); + victimPed->bIsStanding = false; + + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); + victimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false); + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } else { - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + if ( victimPed->IsPlayer() ) { - posOffset.Normalise(); - victimPed->bIsStanding = false; - - victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); - victimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false); - - victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); - } - else - { - if ( victimPed->IsPlayer() ) - { - CPlayerPed *victimPlayer = (CPlayerPed *)victimPed; - if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() ) - { - victimPed->ClearAttackByRemovingAnim(); - - CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir)); - ASSERT(asoc!=nil); - - asoc->blendAmount = 0.0f; - asoc->blendDelta = 8.0f; - - if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) - victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; - else - victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000; - } - } - else + CPlayerPed *victimPlayer = (CPlayerPed *)victimPed; + if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() && victimPed->m_nPedState != PED_DRIVING ) { victimPed->ClearAttackByRemovingAnim(); @@ -966,31 +1429,53 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; + + if ( m_eWeaponType == WEAPONTYPE_M4 ) + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; + else + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000; } + } + else + { + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir)); + ASSERT(asoc!=nil); - victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; } + + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } + } - if ( victimPed->m_nPedType == PEDTYPE_COP ) - CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - else - CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - if ( CGame::nastyGame ) - { - uint8 bloodAmount = 8; - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) - bloodAmount = 32; + if ( CGame::nastyGame ) + { + uint8 bloodAmount = 8; + if ( IsShotgun(m_eWeaponType) || m_eWeaponType == WEAPONTYPE_HELICANNON ) + bloodAmount = 32; - CVector dir = (point->point - victim->GetPosition()) * 0.01f; - dir.z = 0.01f; + CVector dir = (point->point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; - if ( victimPed->GetIsOnScreen() ) - { - for ( uint8 i = 0; i < bloodAmount; i++ ) - CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point, dir); - } + if ( victimPed->GetIsOnScreen() ) + { + for ( uint8 i = 0; i < bloodAmount; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point, dir); + } + + if (m_eWeaponType == WEAPONTYPE_MINIGUN) + { + CParticle::AddParticle(PARTICLE_TEST, point->point, CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_TEST, point->point + CVector(0.2f, -0.2f, 0.f), CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0); + CParticle::AddParticle(PARTICLE_TEST, point->point + CVector(-0.2f, 0.2f, 0.f), CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0); } } } @@ -1035,9 +1520,9 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); #ifndef FIX_BUGS - CVector dist = point->point - (*source); - CVector offset = dist - Max(0.2f * dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); - CVector smokePos = *source + offset; + CVector dist = point->point - (*source); + float distMagnitude = dist.Magnitude(); + CVector smokePos = point->point - Max(distMagnitude / 10.0f, 0.2f) * dist / distMagnitude; #else CVector smokePos = point->point; #endif // !FIX_BUGS @@ -1052,20 +1537,30 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } case ENTITY_TYPE_VEHICLE: { - ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + if (point->pieceB >= CAR_PIECE_WHEEL_LF && point->pieceB <= CAR_PIECE_WHEEL_RR) { + ((CVehicle*)victim)->BurstTyre(point->pieceB, true); - for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + for (int32 i = 0; i < 4; i++) + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point->point, point->normal * 0.05f); + } + else + { + ((CVehicle*)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for (int32 i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal * 0.05f); #ifndef FIX_BUGS - CVector dist = point->point - (*source); - CVector offset = dist - Max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); - CVector smokePos = *source + offset; + CVector dist = point->point - (*source); + CVector offset = dist - Max(0.2f * dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); + CVector smokePos = *source + offset; #else - CVector smokePos = point->point; -#endif // !FIX_BUGS + CVector smokePos = point->point; +#endif + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + } - CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); if ( shooter->IsPed() ) { @@ -1090,19 +1585,23 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CObject *victimObject = (CObject *)victim; - if ( !victimObject->bInfiniteMass ) + if ( !victimObject->bInfiniteMass && victimObject->m_fCollisionDamageMultiplier < 99.9f) { - if ( victimObject->GetIsStatic() && victimObject->m_fUprootLimit <= 0.0f ) + bool notStatic = !victimObject->GetIsStatic(); + if (notStatic && victimObject->m_fUprootLimit <= 0.0f) { victimObject->SetIsStatic(false); victimObject->AddToMovingList(); } - if ( !victimObject->GetIsStatic()) + notStatic = !victimObject->GetIsStatic(); + if (!notStatic) { - CVector moveForce = point->normal*-4.0f; + CVector moveForce = point->normal * -4.0f; victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); } + } else if (victimObject->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY) { + victimObject->ObjectDamage(50.f); } break; @@ -1120,17 +1619,20 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } case ENTITY_TYPE_VEHICLE: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); break; } case ENTITY_TYPE_PED: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); break; } case ENTITY_TYPE_OBJECT: { + CStats::BulletsThatHit++; PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point->point); break; } @@ -1143,7 +1645,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } } else - CBulletTraces::AddTrace(source, target); + CBulletTraces::AddTrace(source, target, m_eWeaponType, shooter); if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); @@ -1151,6 +1653,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, BlowUpExplosiveThings(victim); } + bool CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { @@ -1196,10 +1699,35 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) else shooterAngle = RADTODEG(shooter->GetForward().Heading()); + int shootsAtOnce; + int checkObstacleOnShootNo; + float angleRange; + switch (m_eWeaponType) { + case WEAPONTYPE_SHOTGUN: + angleRange = DEGTORAD(9.0f); + checkObstacleOnShootNo = 1; + shootsAtOnce = 3; + break; + case WEAPONTYPE_SPAS12_SHOTGUN: + angleRange = DEGTORAD(6.0f); + checkObstacleOnShootNo = 1; + shootsAtOnce = 3; + break; + case WEAPONTYPE_STUBBY_SHOTGUN: + angleRange = DEGTORAD(18.0f); + checkObstacleOnShootNo = 2; + shootsAtOnce = 5; + break; + default: + break; + } + bool statUpdated = false; + float halfAngleRange = angleRange / 2.f; + float angleBetweenTwoShot = angleRange / (shootsAtOnce - 1.f); - for ( int32 i = 0; i < 5; i++ ) // five shoots at once + for ( int32 i = 0; i < shootsAtOnce; i++ ) { - float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); + float shootAngle = DEGTORAD(RADTODEG(halfAngleRange - angleBetweenTwoShot * i) + shooterAngle); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); shootRot.Normalise(); @@ -1209,15 +1737,30 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) { - TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target); - CVector Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up); + CVector Left; +#ifdef FREE_CAM + if (CCamera::bFreeCam) { + CPlayerPed* shooterPed = (CPlayerPed*)shooter; + Find3rdPersonCamTargetVectorFromCachedVectors(1.0f, *fireSource, source, target, shooterPed->m_cachedCamSource, shooterPed->m_cachedCamFront, shooterPed->m_cachedCamUp); + Left = CrossProduct(shooterPed->m_cachedCamFront, shooterPed->m_cachedCamUp); + } + else +#endif + { + TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target); + Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up); + } - float f = float(i - 2) * (DEGTORAD(7.5f) / 2); + float f = (i - (shootsAtOnce / 2)) * angleBetweenTwoShot; target = f * Left + target - source; target *= info->m_fRange; target += source; - - ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeCarTyres = true; + CWorld::bIncludeBikers = true; + CWorld::bIncludeDeadPeds = true; + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); + CWorld::bIncludeDeadPeds = false; + CWorld::bIncludeCarTyres = false; } else { @@ -1233,24 +1776,84 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) DoDoomAiming(shooter, fireSource, &target); else { - float distToTarget = (shooterPed->m_pPointGunAt->GetPosition() - (*fireSource)).Magnitude2D(); - target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); + CVector pos; + if (shooterPed->m_pPointGunAt->IsPed()) { + ((CPed*)shooterPed->m_pPointGunAt)->m_pedIK.GetComponentPosition(pos, PED_MID); + } else { + pos = ((CPed*)shooterPed->m_pPointGunAt)->GetPosition(); + } + + float distToTarget = (pos - (*fireSource)).Magnitude2D(); + target.z += info->m_fRange / distToTarget * (pos.z - target.z); } } + if (shooter == FindPlayerPed()) + CWorld::bIncludeDeadPeds = true; - ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeBikers = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false); + CWorld::bIncludeDeadPeds = false; } + CWorld::bIncludeBikers = false; if ( victim ) { CGlass::WasGlassHitByBullet(victim, point.point); + CWeapon::BlowUpExplosiveThings(victim); + if (i == checkObstacleOnShootNo) + { + if (shooter) + { + if (shooter->IsPed() && !((CPed*)shooter)->IsPlayer()) + { + CPed *shooterPed = (CPed*)shooter; + CEntity *guyWePointGun = shooterPed->m_pPointGunAt; + if (guyWePointGun) + { + if (victim != guyWePointGun) + { + float distWithAim = (guyWePointGun->GetPosition() - shooter->GetPosition()).Magnitude(); + float distWithBullet = (point.point - shooter->GetPosition()).Magnitude(); + if (distWithAim > 0.1f && distWithBullet > 0.1f) + { + // Normalize + CVector aimDir = (guyWePointGun->GetPosition() - shooter->GetPosition()) * (1.0f / distWithAim); + CVector bulletDir = (point.point - shooter->GetPosition()) * (1.0f / distWithBullet); + + float dotProd = DotProduct(aimDir, bulletDir); + float aimAndBulletAngle; + if (dotProd <= 0.35f) + aimAndBulletAngle = PI; + else + aimAndBulletAngle = Acos(dotProd); - CBulletTraces::AddTrace(fireSource, &point.point); + if (aimAndBulletAngle <= DEGTORAD(45.0f) && (aimAndBulletAngle <= DEGTORAD(15.0f) || distWithBullet / distWithAim >= 0.75f) && distWithBullet / distWithAim >= 0.99f) + { + shooterPed->bObstacleShowedUpDuringKillObjective = false; + shooterPed->m_shotTime = 0; + } + else + { + shooterPed->bObstacleShowedUpDuringKillObjective = true; + shooterPed->m_shootTimer = 0; + shooterPed->m_shotTime = CTimer::GetTimeInMilliseconds(); + if (distWithAim < 10.0f) + shooterPed->SetAttackTimer(1500); + else + shooterPed->SetAttackTimer(3000); + } + } + } + } + } + } + } + CBulletTraces::AddTrace(fireSource, &point.point, m_eWeaponType, shooter); if ( victim->IsPed() ) { CPed *victimPed = (CPed *)victim; - if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) + if ( !victimPed->DyingOrDead() && victim != shooter ) { bool cantStandup = true; @@ -1263,7 +1866,8 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) posOffset.Normalise(); - if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) || + !victimPed->bCanBeShotInVehicle) cantStandup = false; if ( victimPed->bIsStanding && cantStandup ) @@ -1288,7 +1892,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( CGame::nastyGame ) { uint8 bloodAmount = 8; - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) + if ( IsShotgun(m_eWeaponType) ) bloodAmount = 32; CVector dir = (point.point - victim->GetPosition()) * 0.01f; @@ -1300,6 +1904,36 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point, dir); } } + } else { + if (CGame::nastyGame) + { + CVector dir = (point.point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if (victimPed->GetIsOnScreen()) + { + for (uint8 i = 0; i < 8; i++) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point + CVector(0.0f, 0.0f, 0.15f), dir); + } + if (victimPed->Dead()) + { + CAnimBlendAssociation *hitAssoc; + if (RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FRONTAL)) + { + hitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f); + } + else + { + hitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR, 8.0f); + } + if (hitAssoc) + { + hitAssoc->SetCurrentTime(0.0f); + hitAssoc->SetRun(); + hitAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + } + } + } } } else @@ -1308,21 +1942,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { case ENTITY_TYPE_VEHICLE: { - ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + if (point.pieceB >= CAR_PIECE_WHEEL_LF && point.pieceB <= CAR_PIECE_WHEEL_RR) { + ((CVehicle*)victim)->BurstTyre(point.pieceB, true); - for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + for (int32 i = 0; i < 4; i++) + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal * 0.05f); + } + else + { + ((CVehicle*)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for (int32 i = 0; i < 16; i++) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal * 0.05f); #ifndef FIX_BUGS - CVector dist = point.point - (*fireSource); - CVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); - CVector smokePos = *fireSource + offset; + CVector dist = point.point - (*fireSource); + CVector offset = dist - Max(0.2f * dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; #else - CVector smokePos = point.point; + CVector smokePos = point.point; #endif - CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + } break; } @@ -1352,13 +1994,15 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) if ( !victimObject->bInfiniteMass ) { - if ( victimObject->GetIsStatic() && victimObject->m_fUprootLimit <= 0.0f ) + bool notStatic = !victimObject->GetIsStatic(); + if ( notStatic && victimObject->m_fUprootLimit <= 0.0f ) { victimObject->SetIsStatic(false); victimObject->AddToMovingList(); } - if ( !victimObject->GetIsStatic()) + notStatic = !victimObject->GetIsStatic(); + if ( !notStatic ) { CVector moveForce = point.normal*-5.0f; victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); @@ -1381,17 +2025,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } case ENTITY_TYPE_VEHICLE: { + if (!statUpdated) { + CStats::BulletsThatHit++; + statUpdated = true; + } DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); break; } case ENTITY_TYPE_PED: { + if (!statUpdated) { + CStats::BulletsThatHit++; + statUpdated = true; + } DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); break; } case ENTITY_TYPE_OBJECT: { + if (!statUpdated) { + CStats::BulletsThatHit++; + statUpdated = true; + } PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); break; } @@ -1407,7 +2063,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { CVector traceTarget = *fireSource; traceTarget += (target - (*fireSource)) * Min(info->m_fRange, 30.0f) / info->m_fRange; - CBulletTraces::AddTrace(fireSource, &traceTarget); + CBulletTraces::AddTrace(fireSource, &traceTarget, m_eWeaponType, shooter); } } @@ -1424,10 +2080,12 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) ASSERT(fireSource!=nil); CVector source, target; + eWeaponType projectileType = m_eWeaponType; if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ) { source = *fireSource; + projectileType = WEAPONTYPE_ROCKET; if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() ) { @@ -1469,7 +2127,7 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) ) { if ( m_eWeaponType != WEAPONTYPE_GRENADE ) - CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + CProjectileInfo::RemoveNotAdd(shooter, projectileType, *fireSource); else { if ( shooter->IsPed() ) @@ -1478,14 +2136,22 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) source.z -= 0.4f; if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, nil, false, false, true, false, false, false) ) - CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f); + CProjectileInfo::AddProjectile(shooter, WEAPONTYPE_GRENADE, source, 0.0f); else - CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + CProjectileInfo::RemoveNotAdd(shooter, WEAPONTYPE_GRENADE, *fireSource); } } } else - CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power); + CProjectileInfo::AddProjectile(shooter, projectileType, *fireSource, power); + + + CWorld::pIgnoreEntity = nil; + + if ( shooter->IsPed() ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); + else if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000); return true; } @@ -1525,7 +2191,16 @@ CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) { - TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); +#ifdef FREE_CAM + if (CCamera::bFreeCam) { + CPlayerPed* shooterPed = (CPlayerPed*)shooter; + Find3rdPersonCamTargetVectorFromCachedVectors(info->m_fRange, *fireSource, source, target, shooterPed->m_cachedCamSource, shooterPed->m_cachedCamFront, shooterPed->m_cachedCamUp); + } + else +#endif + { + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); + } float norm = (1.0f / info->m_fRange); dir = (target - source) * norm; } @@ -1538,25 +2213,84 @@ CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); + + if ( shooter == (CEntity *)FindPlayerPed() ) + { + for ( int32 i = 0; i < FindPlayerPed()->m_numNearPeds; i++ ) + { + if ( FindPlayerPed()->m_nearPeds[i]->CharCreatedBy == RANDOM_CHAR ) + { + if ( FindPlayerPed()->m_nearPeds[i]->IsPedInControl() && FindPlayerPed()->m_nearPeds[i]->m_nPedState != PED_FLEE_ENTITY ) + FindPlayerPed()->m_nearPeds[i]->SetFlee(shooter, 10000); + } + } + } return true; } bool +CWeapon::LaserScopeDot(CVector *pOutPos, float *pOutSize) +{ + CWeaponInfo *info = GetInfo(); + + float range = info->m_fRange; + + CVector source, target; + CEntity *foundEnt = nil; + CColPoint foundCol; + + source = 0.5f * TheCamera.Cams[TheCamera.ActiveCam].Front + TheCamera.Cams[TheCamera.ActiveCam].Source; + target = TheCamera.Cams[TheCamera.ActiveCam].Front; + target.Normalise(); + target *= range; + target += source; + + if ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, false, false, false) ) + { + CVector pos = foundCol.point; + float w, h; + + if ( CSprite::CalcScreenCoors(foundCol.point, &pos, &w, &h, true) ) + { + *pOutPos = pos; + *pOutSize = w * 0.05f; + + CCoronas::RegisterCorona((uintptr)this + 7, 128, 0, 0, 255, pos, 1.2f, 50.0f, CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); + + return true; + } + } + + return false; +} + +bool CWeapon::FireSniper(CEntity *shooter) { ASSERT(shooter!=nil); - - int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - if (!( mode == CCam::MODE_M16_1STPERSON - || mode == CCam::MODE_SNIPER - || mode == CCam::MODE_ROCKETLAUNCHER - || mode == CCam::MODE_M16_1STPERSON_RUNABOUT - || mode == CCam::MODE_SNIPER_RUNABOUT - || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + + if ( (CEntity *)FindPlayerPed() == shooter ) { - return false; + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_CAMERA + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } + } + +#ifdef SECUROM + if (sniperPirateCheck){ + // if not pirated game + // sniperPirateCheck = 0; } +#endif #ifndef FIX_BUGS CWeaponInfo *info = GetInfo(); //unused @@ -1569,15 +2303,16 @@ CWeapon::FireSniper(CEntity *shooter) CVector dir = cam->Front; if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f ) - CCoronas::bSmallMoon = !CCoronas::bSmallMoon; + CCoronas::MoonSize = (CCoronas::MoonSize+1) & 7; dir.Normalise(); dir *= 16.0f; - CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); +#ifdef SECUROM + if (sniperPirateCheck) return true; +#endif - if ( shooter == FindPlayerPed() ) - CStats::InstantHitsFiredByPlayer++; + CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); if ( shooter == FindPlayerPed() ) { @@ -1585,14 +2320,75 @@ CWeapon::FireSniper(CEntity *shooter) FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + CParticle::HandleShootableBirdsStuff(shooter, source); CamShakeNoPos(&TheCamera, 0.2f); } + if ( shooter->IsPed() ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); + else if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver ) + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000); + return true; } bool +CWeapon::TakePhotograph(CEntity *shooter) +{ + if ( TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA ) + { + CSpecialFX::bSnapShotActive = true; + CSpecialFX::SnapShotFrames = 0; + CStats::PhotosTaken++; + bPhotographHasBeenTaken = true; + + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) + { + CPed *ped = CPools::GetPedPool()->GetSlot(i); + if ( ped ) + { + if ( (ped->GetPosition() - TheCamera.GetPosition()).Magnitude() < 125.0f ) + { + CVector pedPos = ped->GetPosition(); + pedPos.z += 0.8f; + + CVector pos; + float w, h; + + if ( CSprite::CalcScreenCoors(pedPos, &pos, &w, &h, false) ) + { + if ( SCREEN_WIDTH * 0.1f < pos.x && SCREEN_WIDTH * 0.9f > pos.x + && SCREEN_HEIGHT * 0.1f < pos.y && SCREEN_HEIGHT * 0.9f > pos.y ) + { + CVector source, target; + CEntity *foundEnt = nil; + CColPoint foundCol; + + target = pedPos; + source = TheCamera.GetForward() * 2.0f + TheCamera.GetPosition(); + + if ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, true, true, false) ) + { + if ( foundEnt != (CEntity*)ped ) + continue; + } + + ped->bHasBeenPhotographed = true; + } + } + } + } + } + + return true; + } + + return false; +} + +bool CWeapon::FireM16_1stPerson(CEntity *shooter) { ASSERT(shooter!=nil); @@ -1601,6 +2397,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) if (!( mode == CCam::MODE_M16_1STPERSON || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_CAMERA || mode == CCam::MODE_ROCKETLAUNCHER || mode == CCam::MODE_M16_1STPERSON_RUNABOUT || mode == CCam::MODE_SNIPER_RUNABOUT @@ -1612,10 +2409,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) CWeaponInfo *info = GetInfo(); + CWorld::bIncludeCarTyres = true; + CWorld::bIncludeBikers = true; + CColPoint point; CEntity *victim; - CWorld::bIncludeCarTyres = true; CWorld::pIgnoreEntity = shooter; CWorld::bIncludeDeadPeds = true; @@ -1625,9 +2424,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 (ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false)) { + CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target); + } CWorld::pIgnoreEntity = nil; + CWorld::bIncludeDeadPeds = false; + CWorld::bIncludeBikers = false; CWorld::bIncludeCarTyres = false; CVector2D front(cam->Front.x, cam->Front.y); @@ -1636,7 +2438,8 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) DoBulletImpact(shooter, victim, &source, &target, &point, front); CVector bulletPos; - if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) ) + + if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, (m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_HELICANNON ? 20 : 4)) ) { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); @@ -1644,77 +2447,137 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) if ( shooter == FindPlayerPed() ) { -#ifdef FIX_BUGS - CStats::InstantHitsFiredByPlayer++; -#endif - CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - - if ( m_eWeaponType == WEAPONTYPE_M16 ) - { - TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; - TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; - } - else if ( m_eWeaponType == WEAPONTYPE_HELICANNON ) - { - TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; - TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; + float mult; + switch (m_eWeaponType) { + case WEAPONTYPE_M4: + 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; } + + if (FindPlayerPed()->bIsDucking || FindPlayerPed()->m_attachedTo) + mult *= 0.3f; + + 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; } bool -CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) +CWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right) { CWeaponInfo *info = GetInfo(); CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); - + CVector source, target; - if ( left ) + + if ( shooter->IsBike() ) { - source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, - float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); - source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - - target = shooter->GetMatrix() * CVector(-info->m_fRange, - modelInfo->GetFrontSeatPosn().y, + if ( shooter->pDriver ) + { + source = info->m_vecFireOffset; + + shooter->pDriver->TransformToNode(source, PED_HANDR); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + if ( left ) + target = source - info->m_fRange * shooter->GetRight(); + else if ( right ) + target = source + info->m_fRange * shooter->GetRight(); + else + target = source + info->m_fRange * shooter->GetForward(); + + } + else if ( left ) + { + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.25f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.05f, + modelInfo->GetFrontSeatPosn().z + 0.63f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + + target = shooter->GetMatrix() * CVector(-info->m_fRange, + modelInfo->GetFrontSeatPosn().y, + modelInfo->GetFrontSeatPosn().z + 0.6f); + } + else if ( right ) + { + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.25f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.18f, + modelInfo->GetFrontSeatPosn().z + 0.52f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(info->m_fRange, + modelInfo->GetFrontSeatPosn().y, + modelInfo->GetFrontSeatPosn().z + 0.5f); + } + else + { + source = shooter->GetMatrix() * CVector(float(CGeneral::GetRandomNumber() & 255) * 0.001f + -0.4f, + modelInfo->GetFrontSeatPosn().y + shooter->GetColModel()->boundingBox.max.y + 0.2f, + modelInfo->GetFrontSeatPosn().z + 0.55f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(0.0f, + info->m_fRange, modelInfo->GetFrontSeatPosn().z + 0.5f); + } } else { - source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, - float(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); + if ( left ) + source = info->m_vecFireOffset; + else + { + source = 1.8f * info->m_vecFireOffset; + source.z -= 0.1f; + } + + shooter->pDriver->TransformToNode(source, PED_HANDR); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - target = shooter->GetMatrix() * CVector(info->m_fRange, - modelInfo->GetFrontSeatPosn().y, - modelInfo->GetFrontSeatPosn().z + 0.5f); - } - #undef FRONTSEATPOS - - if ( TheCamera.GetLookingLRBFirstPerson() && !left ) - { - source -= 0.3f * shooter->GetForward(); - target -= 0.3f * shooter->GetForward(); + + if ( left ) + target = source - info->m_fRange * shooter->GetRight(); + else + target = source + info->m_fRange * shooter->GetRight(); } target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f); - DoDriveByAutoAiming(FindPlayerPed(), &source, &target); + DoDriveByAutoAiming(FindPlayerPed(), shooter, &source, &target); CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); if ( !TheCamera.GetLookingLRBFirstPerson() ) - CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + { + if ( !shooter->IsBike() ) + CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + else + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.4f*shooter->m_vecMoveSpeed); + } else - CamShakeNoPos(&TheCamera, 0.01f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.6f*shooter->m_vecMoveSpeed, nil, 0.18f); CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); @@ -1723,7 +2586,12 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) CColPoint point; CEntity *victim; + + CWorld::bIncludeBikers = true; + CWorld::pIgnoreEntity = shooter; ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::pIgnoreEntity = NULL; + CWorld::bIncludeBikers = false; if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot(shooter, &source, &target); @@ -1731,7 +2599,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) if ( victim ) { CVector traceTarget = point.point; - CBulletTraces::AddTrace(&source, &traceTarget); + CBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter); if ( victim->IsPed() ) { @@ -1818,7 +2686,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) { float norm = 30.0f/info->m_fRange; CVector traceTarget = (target-source)*norm + source; - CBulletTraces::AddTrace(&source, &traceTarget); + CBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter); } if ( shooter == FindPlayerVehicle() ) @@ -1839,8 +2707,6 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) #endif CPed *shooterPed = (CPed*)shooter; - if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) - return; int16 lastEntity; CEntity *entities[16]; @@ -1859,7 +2725,8 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) if ( !(victim->GetStatus() == STATUS_TRAIN_MOVING || victim->GetStatus() == STATUS_TRAIN_NOT_MOVING || victim->GetStatus() == STATUS_HELI - || victim->GetStatus() == STATUS_PLANE) ) + || victim->GetStatus() == STATUS_PLANE + || victim->GetStatus() == STATUS_WRECKED) ) { float distToVictim = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D(); float distToVictimZ = Abs(shooterPed->GetPosition().z-victim->GetPosition().z); @@ -1878,7 +2745,10 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) } } - if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) + CColPoint foundCol; + CEntity *foundEnt; + if (closestEntityDist < DOOMAUTOAIMING_MAXDIST + && !CWorld::ProcessLineOfSight(*source, entities[closestEntity]->GetPosition(), foundCol, foundEnt, true, false, false, false, false, false, false, true)) { CEntity *victim = entities[closestEntity]; ASSERT(victim !=nil); @@ -1967,10 +2837,11 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV } } + void -CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) +CWeapon::DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target) { - ASSERT(shooter!=nil); + ASSERT(driver!=nil); ASSERT(source!=nil); ASSERT(target!=nil); @@ -1978,27 +2849,36 @@ CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) CEntity entity; // unused #endif - CPed *shooterPed = (CPed*)shooter; - if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) - return; + CPed *shooterPed = (CPed*)driver; int16 lastEntity; - CEntity *entities[16]; - CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, false, true, false, false); + CEntity *peds[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, peds, false, false, true, false, false); float closestEntityDist = 10000.0f; int16 closestEntity; for ( int32 i = 0; i < lastEntity; i++ ) { - CEntity *victim = entities[i]; + CPed *victim = (CPed*)peds[i]; ASSERT(victim!=nil); - if ( shooter != victim ) + if (driver != victim && !victim->DyingOrDead() && victim->m_attachedTo != vehicle) { float lineDist = CCollision::DistToLine(source, target, &victim->GetPosition()); - float distToVictim = (victim->GetPosition() - shooter->GetPosition()).Magnitude(); - float pedDist = 0.15f*distToVictim + lineDist; + + uint32 model = vehicle->GetModelIndex(); + float pedDist; + if (model == MI_HUNTER || model == MI_SEASPAR || model == MI_SPARROW) + { + float distToVictim = (victim->GetPosition() - vehicle->GetPosition()).Magnitude(); + pedDist = lineDist / Max(5.f, distToVictim); + } + else + { + float distToVictim = (victim->GetPosition() - driver->GetPosition()).Magnitude(); + pedDist = 0.15f * distToVictim + lineDist; + } if ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist) { @@ -2007,14 +2887,24 @@ CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) } } } + uint32 model = vehicle->GetModelIndex(); + float maxAimDistance = CAR_DRIVEBYAUTOAIMING_MAXDIST; + if (model == MI_HUNTER) + { + maxAimDistance = Tan(DEGTORAD(fHunterAimingAngle)); + } + else if (model == MI_SEASPAR || model == MI_SPARROW) + { + maxAimDistance = Tan(DEGTORAD(fSeaSparrowAimingAngle)); + } - if ( closestEntityDist < DRIVEBYAUTOAIMING_MAXDIST ) + if ( closestEntityDist < maxAimDistance ) { - CEntity *victim = entities[closestEntity]; + CEntity *victim = peds[closestEntity]; ASSERT(victim!=nil); float distToTarget = (*source - *target).Magnitude(); - float distToSource = (*source - victim->GetPosition()).Magnitude(); + float distToSource = (*source - victim->GetPosition()).Magnitude(); *target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source; } } @@ -2034,8 +2924,10 @@ CWeapon::Reload(void) } void -CWeapon::Update(int32 audioEntity) +CWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound) { + CWeaponInfo *info = GetInfo(); + switch ( m_eWeaponState ) { case WEAPONSTATE_MELEE_MADECONTACT: @@ -2046,18 +2938,19 @@ CWeapon::Update(int32 audioEntity) case WEAPONSTATE_FIRING: { - if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) + if ( IsShotgun(m_eWeaponType) && AEHANDLE_IS_OK(audioEntity) ) { - uint32 timePassed = m_nTimer - gReloadSampleTime[WEAPONTYPE_SHOTGUN]; + uint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType]; if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } 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 + CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(m_eWeaponType); + } else m_eWeaponState = WEAPONSTATE_READY; } @@ -2066,11 +2959,49 @@ CWeapon::Update(int32 audioEntity) case WEAPONSTATE_RELOADING: { - if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) + if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_TOTALWEAPONS) { - uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; - if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) - DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + CAnimBlendAssociation *reloadAssoc = nil; + if (pedToAdjustSound) { + if (CPed::GetReloadAnim(info) && (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload || !pedToAdjustSound->IsPlayer())) { + reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetReloadAnim(info)); + if (!reloadAssoc) { + reloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetCrouchReloadAnim(info)); + } + } + } + if (reloadAssoc && reloadAssoc->IsRunning() && reloadAssoc->blendAmount > 0.2f) { + float soundStart = 0.75f; + switch (info->m_AnimToPlay) { + case ASSOCGRP_PYTHON: + soundStart = fReloadAnimSampleFraction[0]; + break; + case ASSOCGRP_COLT: + case ASSOCGRP_TEC: + soundStart = fReloadAnimSampleFraction[1]; + break; + case ASSOCGRP_UZI: + soundStart = fReloadAnimSampleFraction[2]; + break; + case ASSOCGRP_RIFLE: + soundStart = fReloadAnimSampleFraction[3]; + break; + case ASSOCGRP_M60: + soundStart = fReloadAnimSampleFraction[4]; + break; + default: + break; + } + if (reloadAssoc->GetProgress() >= soundStart && (reloadAssoc->currentTime - reloadAssoc->timeStep) / reloadAssoc->hierarchy->totalLength < soundStart) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType); + if (CTimer::GetTimeInMilliseconds() > m_nTimer && reloadAssoc->GetProgress() < 0.9f) { + m_nTimer = CTimer::GetTimeInMilliseconds(); + } + } else { + uint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType]; + if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType); + } } if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) @@ -2157,17 +3088,20 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) } case ENTITY_TYPE_VEHICLE: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); break; } case ENTITY_TYPE_PED: { + CStats::BulletsThatHit++; DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); break; } case ENTITY_TYPE_OBJECT: { + CStats::BulletsThatHit++; PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); break; } @@ -2193,13 +3127,15 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) bool CWeapon::IsTypeMelee(void) { - return m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + return CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE; } bool CWeapon::IsType2Handed(void) { - return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; + return m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || m_eWeaponType == WEAPONTYPE_M60 || + m_eWeaponType == WEAPONTYPE_M4 || IsShotgun(m_eWeaponType) || + m_eWeaponType == WEAPONTYPE_RUGER || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || m_eWeaponType == WEAPONTYPE_LASERSCOPE; } void @@ -2284,14 +3220,14 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing) { CObject *object = (CObject*)thing; int32 mi = object->GetModelIndex(); - if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged ) + if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged && object->IsObject() ) { object->bHasBeenDamaged = true; CExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100); if ( MI_EXPLODINGBARREL == mi ) - object->m_vecMoveSpeed.z += 0.75f; + object->m_vecMoveSpeed.z += 0.55f; else object->m_vecMoveSpeed.z += 0.45f; @@ -2310,19 +3246,25 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing) bool CWeapon::HasWeaponAmmoToBeUsed(void) { - switch (m_eWeaponType) { - case WEAPONTYPE_UNARMED: - case WEAPONTYPE_BASEBALLBAT: - return true; - default: - return m_nAmmoTotal != 0; - } + // FIX: This is better (not bug tho) +//#if 0 + if (m_eWeaponType <= WEAPONTYPE_CHAINSAW) +//#else +// if (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE) +//#endif + return true; + else + return m_nAmmoTotal != 0; } bool CPed::IsPedDoingDriveByShooting(void) { +#ifdef FIX_BUGS + if (FindPlayerPed() == this && CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nWeaponSlot == WEAPONSLOT_SUBMACHINEGUN) { +#else if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) { +#endif if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight) return true; } @@ -2332,7 +3274,82 @@ CPed::IsPedDoingDriveByShooting(void) bool CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { - return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects); + return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, false, ignoreSomeObjects, true); +} + + +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 |