summaryrefslogtreecommitdiffstats
path: root/src/weapons
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/weapons/BulletInfo.cpp30
-rw-r--r--src/weapons/Explosion.cpp2
-rw-r--r--src/weapons/Explosion.h3
-rw-r--r--src/weapons/ProjectileInfo.cpp82
-rw-r--r--src/weapons/ProjectileInfo.h1
-rw-r--r--src/weapons/ShotInfo.cpp2
-rw-r--r--src/weapons/Weapon.cpp1511
-rw-r--r--src/weapons/Weapon.h21
-rw-r--r--src/weapons/WeaponEffects.cpp2
-rw-r--r--src/weapons/WeaponInfo.cpp138
-rw-r--r--src/weapons/WeaponInfo.h32
-rw-r--r--src/weapons/WeaponType.h47
12 files changed, 1410 insertions, 461 deletions
diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp
index 26fc459d..129e4b2b 100644
--- a/src/weapons/BulletInfo.cpp
+++ b/src/weapons/BulletInfo.cpp
@@ -76,7 +76,6 @@ bool CBulletInfo::AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosit
void CBulletInfo::Update(void)
{
- bool bAddSound = true;
bPlayerSniperBullet = false;
for (int i = 0; i < NUM_BULLETS; i++) {
CBulletInfo* pBullet = &gaBulletInfo[i];
@@ -93,26 +92,23 @@ void CBulletInfo::Update(void)
CWorld::pIgnoreEntity = pBullet->m_pSource;
CColPoint point;
CEntity* pHitEntity;
- if (CWorld::ProcessLineOfSight(vecOldPos, vecNewPos, point, pHitEntity, true, true, true, true, true, true)) {
+ if (CWorld::ProcessLineOfSight(vecOldPos, vecNewPos, point, pHitEntity, true, true, true, true, true, false, false, true)) {
if (pBullet->m_pSource && (pHitEntity->IsPed() || pHitEntity->IsVehicle()))
CStats::InstantHitsHitByPlayer++;
+
+ CWeapon::CheckForShootingVehicleOccupant(&pHitEntity, &point, pBullet->m_eWeaponType, vecOldPos, vecNewPos);
if (pHitEntity->IsPed()) {
CPed* pPed = (CPed*)pHitEntity;
if (!pPed->DyingOrDead() && pPed != pBullet->m_pSource) {
- if (pPed->DoesLOSBulletHitPed(point)) {
- if (pPed->IsPedInControl() && !pPed->bIsDucking) {
- pPed->ClearAttackByRemovingAnim();
- CAnimBlendAssociation* pAnim = CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_SHOT_FRONT_PARTIAL);
- pAnim->SetBlend(0.0f, 8.0f);
- }
- pPed->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage, (ePedPieceTypes)point.pieceB, pPed->GetLocalDirection(pPed->GetPosition() - point.point));
- CEventList::RegisterEvent(pPed->m_nPedType == PEDTYPE_COP ? EVENT_SHOOT_COP : EVENT_SHOOT_PED, EVENT_ENTITY_PED, pPed, (CPed*)pBullet->m_pSource, 1000);
- pBullet->m_bInUse = false;
- vecNewPos = point.point;
- }
- else {
- bAddSound = false;
+ if (pPed->IsPedInControl() && !pPed->bIsDucking) {
+ pPed->ClearAttackByRemovingAnim();
+ CAnimBlendAssociation* pAnim = CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_SHOT_FRONT_PARTIAL);
+ pAnim->SetBlend(0.0f, 8.0f);
}
+ pPed->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage, (ePedPieceTypes)point.pieceB, pPed->GetLocalDirection(pPed->GetPosition() - point.point));
+ CEventList::RegisterEvent(pPed->m_nPedType == PEDTYPE_COP ? EVENT_SHOOT_COP : EVENT_SHOOT_PED, EVENT_ENTITY_PED, pPed, (CPed*)pBullet->m_pSource, 1000);
+ pBullet->m_bInUse = false;
+ vecNewPos = point.point;
}
if (CGame::nastyGame) {
CVector vecParticleDirection = (point.point - pPed->GetPosition()) * 0.01f;
@@ -170,7 +166,7 @@ void CBulletInfo::Update(void)
vecNewPos = point.point;
#endif
}
- if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE && bAddSound) {
+ if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || pBullet->m_eWeaponType == WEAPONTYPE_LASERSCOPE) {
cAudioScriptObject* pAudio;
switch (pHitEntity->GetType()) {
case ENTITY_TYPE_BUILDING:
@@ -210,7 +206,7 @@ void CBulletInfo::Update(void)
CWorld::pIgnoreEntity = nil;
CWorld::bIncludeDeadPeds = false;
CWorld::bIncludeCarTyres = false;
- if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE) {
+ if (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || pBullet->m_eWeaponType == WEAPONTYPE_LASERSCOPE) {
bPlayerSniperBullet = true;
PlayerSniperBulletStart = pBullet->m_vecPosition;
PlayerSniperBulletEnd = vecNewPos;
diff --git a/src/weapons/Explosion.cpp b/src/weapons/Explosion.cpp
index d0a68279..f4ad346d 100644
--- a/src/weapons/Explosion.cpp
+++ b/src/weapons/Explosion.cpp
@@ -86,7 +86,7 @@ CExplosion::GetExplosionPosition(uint8 id)
}
bool
-CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime)
+CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime, bool unk)
{
CVector pPosn;
CVector posGround;
diff --git a/src/weapons/Explosion.h b/src/weapons/Explosion.h
index bf54328c..c8539cca 100644
--- a/src/weapons/Explosion.h
+++ b/src/weapons/Explosion.h
@@ -40,7 +40,8 @@ public:
static void ResetExplosionActiveCounter(uint8 id);
static uint8 GetExplosionType(uint8 id);
static CVector *GetExplosionPosition(uint8 id);
- static bool AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime);
+// TODO(MIAMI): that new parameter
+ static bool AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime, bool unk = true);
static void Update();
static bool TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2);
static void RemoveAllExplosionsInArea(CVector pos, float radius);
diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp
index 47bc65ac..35e55b36 100644
--- a/src/weapons/ProjectileInfo.cpp
+++ b/src/weapons/ProjectileInfo.cpp
@@ -45,6 +45,7 @@ CProjectileInfo::GetProjectileInfo(int32 id)
return &gaProjectileInfo[id];
}
+// --MIAMI: Mostly done
bool
CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos, float speed)
{
@@ -58,32 +59,36 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
switch (weapon)
{
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
{
- float vy = 1.25f;
- time = CTimer::GetTimeInMilliseconds() + 1400;
- if (ped->IsPlayer()) {
- matrix.GetForward() = TheCamera.Cams[TheCamera.ActiveCam].Front;
- matrix.GetUp() = TheCamera.Cams[TheCamera.ActiveCam].Up;
- matrix.GetRight() = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Up, TheCamera.Cams[TheCamera.ActiveCam].Front);
+ float vy = 0.35f;
+ time = CTimer::GetTimeInMilliseconds() + 2000;
+ if (entity->GetModelIndex() == MI_SPARROW || entity->GetModelIndex() == MI_HUNTER || entity->GetModelIndex() == MI_SENTINEL) {
+ matrix = ped->GetMatrix();
matrix.GetPosition() = pos;
- } else if (ped->m_pSeekTarget != nil) {
+ CVector vecSpeed = ((CPhysical*)entity)->m_vecMoveSpeed;
+ vy += Max(0.0f, DotProduct(vecSpeed, entity->GetForward())) + Max(0.0f, DotProduct(vecSpeed, entity->GetUp()));
+ } else {
+ if (ped->IsPlayer()) {
+ matrix.GetForward() = TheCamera.Cams[TheCamera.ActiveCam].Front;
+ matrix.GetUp() = TheCamera.Cams[TheCamera.ActiveCam].Up;
+ matrix.GetRight() = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Up, TheCamera.Cams[TheCamera.ActiveCam].Front);
+ matrix.GetPosition() = pos;
+ } else if (ped->m_pSeekTarget != nil) {
float ry = CGeneral::GetRadianAngleBetweenPoints(1.0f, ped->m_pSeekTarget->GetPosition().z, 1.0f, pos.z);
float rz = Atan2(-ped->GetForward().x, ped->GetForward().y);
vy = 0.35f * speed + 0.15f;
matrix.SetTranslate(0.0f, 1.0f, 1.0f);
matrix.Rotate(0.0f, ry, rz);
matrix.GetPosition() += pos;
- } else {
- matrix = ped->GetMatrix();
+ } else {
+ matrix = ped->GetMatrix();
+ }
}
velocity = Multiply3x3(matrix, CVector(0.0f, vy, 0.0f));
gravity = false;
break;
}
- case WEAPONTYPE_FLAMETHROWER:
- Error("Undefined projectile type, AddProjectile, ProjectileInfo.cpp");
- break;
case WEAPONTYPE_MOLOTOV:
{
time = CTimer::GetTimeInMilliseconds() + 2000;
@@ -100,6 +105,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
break;
}
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
{
time = CTimer::GetTimeInMilliseconds() + 2000;
float scale = 0.0f;
@@ -116,7 +122,9 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
elasticity = 0.5f;
break;
}
- default: break;
+ default:
+ Error("Undefined projectile type, AddProjectile, ProjectileInfo.cpp");
+ break;
}
int i = 0;
@@ -127,7 +135,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
switch (weapon)
{
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
ms_apProjectile[i] = new CProjectile(MI_MISSILE);
break;
case WEAPONTYPE_FLAMETHROWER:
@@ -136,6 +144,7 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
ms_apProjectile[i] = new CProjectile(MI_MOLOTOV);
break;
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
ms_apProjectile[i] = new CProjectile(MI_GRENADE);
break;
default: break;
@@ -158,6 +167,10 @@ CProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos,
CWorld::Add(ms_apProjectile[i]);
gaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();
+
+ if (entity && entity->IsPed() && !ped->m_pCollidingEntity) {
+ ped->m_pCollidingEntity = ms_apProjectile[i];
+ }
return true;
}
@@ -182,7 +195,7 @@ CProjectileInfo::RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector p
case WEAPONTYPE_MOLOTOV:
CExplosion::AddExplosion(nil, entity, EXPLOSION_MOLOTOV, pos, 0);
break;
- case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_ROCKET:
CExplosion::AddExplosion(nil, entity, EXPLOSION_ROCKET, pos, 0);
break;
default: break;
@@ -204,17 +217,17 @@ CProjectileInfo::Update()
continue;
}
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {
CParticle::AddParticle(PARTICLE_SMOKE, ms_apProjectile[i]->GetPosition(), CVector(0.0f, 0.0f, 0.0f));
}
if (CTimer::GetTimeInMilliseconds() <= gaProjectileInfo[i].m_nExplosionTime) {
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {
CVector pos = ms_apProjectile[i]->GetPosition();
CWorld::pIgnoreEntity = ms_apProjectile[i];
if (ms_apProjectile[i]->bHasCollided
|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)
- || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
+ || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
}
CWorld::pIgnoreEntity = nil;
@@ -227,14 +240,25 @@ CProjectileInfo::Update()
{
if (ms_apProjectile[i]->bHasCollided
|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)
- || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
+ || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET && (CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos))) {
RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
}
}
CWorld::pIgnoreEntity = nil;
}
} else {
- RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {
+ CEntity *ent = gaProjectileInfo[i].m_pSource;
+ if (ent->IsPed() && ((CPed*)ped)->IsPlayer()) {
+ CPed *ped = (CPed*)ent;
+ if (ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponType != WEAPONTYPE_DETONATOR
+ || ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_nAmmoTotal == 0) {
+ gaProjectileInfo[i].m_nExplosionTime = 0;
+ }
+ }
+ } else {
+ RemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);
+ }
}
gaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();
@@ -247,7 +271,7 @@ CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, flo
bool result = false;
for (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {
if (gaProjectileInfo[i].m_bInUse) {
- if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_GRENADE) {
+ if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_GRENADE) {
const CVector &pos = ms_apProjectile[i]->GetPosition();
if (pos.x >= x1 && pos.x <= x2 && pos.y >= y1 && pos.y <= y2 && pos.z >= z1 && pos.z <= z2) {
result = true;
@@ -263,6 +287,20 @@ CProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, flo
return result;
}
+// --MIAMI: Done
+void
+CProjectileInfo::RemoveDetonatorProjectiles()
+{
+ for (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {
+ if (gaProjectileInfo[i].m_bInUse && gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {
+ CExplosion::AddExplosion(nil, gaProjectileInfo[i].m_pSource, EXPLOSION_GRENADE, gaProjectileInfo[i].m_vecPos, 0); // TODO(Miami): New parameter (1)
+ gaProjectileInfo[i].m_bInUse = false;
+ CWorld::Remove(ms_apProjectile[i]);
+ delete ms_apProjectile[i];
+ }
+ }
+}
+
void
CProjectileInfo::RemoveAllProjectiles()
{
diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h
index 3d8074c9..d1688948 100644
--- a/src/weapons/ProjectileInfo.h
+++ b/src/weapons/ProjectileInfo.h
@@ -26,6 +26,7 @@ public:
static void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);
static bool RemoveIfThisIsAProjectile(CObject *pObject);
static void RemoveAllProjectiles();
+ static void RemoveDetonatorProjectiles();
static void Update();
static bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);
};
diff --git a/src/weapons/ShotInfo.cpp b/src/weapons/ShotInfo.cpp
index f09ae052..6fc6341d 100644
--- a/src/weapons/ShotInfo.cpp
+++ b/src/weapons/ShotInfo.cpp
@@ -128,4 +128,4 @@ CShotInfo::Update()
if (!((CTimer::GetFrameCounter() + slot) & 3))
CWorld::SetCarsOnFire(shot.m_startPos.x, shot.m_startPos.y, shot.m_startPos.z, 4.0f, shot.m_sourceEntity);
}
-} \ No newline at end of file
+}
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index aea14f6a..8e7e4265 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -30,23 +30,52 @@
#include "WaterLevel.h"
#include "WeaponInfo.h"
#include "World.h"
+#include "SurfaceTable.h"
+#include "Bike.h"
-uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] =
+// TODO(Miami)
+#define AUDIO_NOT_READY
+
+// TODO(Miami): Those are mostly placeholders!!!
+uint16 gReloadSampleTime[] =
{
0, // UNARMED
- 0, // BASEBALLBAT
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, // GRENADE
+ 0, // DETONATEGRENADE
+ 0, // TEARGAS
+ 0, // MOLOTOV
+ 0, // ROCKET
250, // COLT45
- 400, // UZI
+ 250, // PYTHON
650, // SHOTGUN
- 300, // AK47
+ 650, // SPAS12 SHOTGUN
+ 650, // STUBBY SHOTGUN
+ 400, // TEC9
+ 400, // UZIhec
+ 400, // SILENCED_INGRAM
+ 400, // MP5
300, // M16
+ 300, // AK47
423, // SNIPERRIFLE
+ 423, // LASERSCOPE
400, // ROCKETLAUNCHER
0, // FLAMETHROWER
- 0, // MOLOTOV
- 0, // GRENADE
+ 0, // M60
+ 0, // MINIGUN
0, // DETONATOR
- 0 // HELICANNON
+ 0, // HELICANNON
+ 0 // CAMERA
};
CWeaponInfo *
@@ -86,18 +115,54 @@ CWeapon::UpdateWeapons(void)
CBulletInfo::Update();
}
+//--MIAMI: done
+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;
+}
+
+// --MIAMI: Done
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;
+ int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;
+ if (modelId != -1)
+ CModelInfo::GetModelInfo(modelId)->AddRef();
+
+ int model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id;
+ if (model2Id != -1)
+ CModelInfo::GetModelInfo(model2Id)->AddRef();
+}
+
+// --MIAMI: Done
+void
+CWeapon::Shutdown()
+{
+ int modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;
+ if (modelId != -1)
+ CModelInfo::GetModelInfo(modelId)->RemoveRef();
+
+ int 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
@@ -125,44 +190,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_PYTHON:
case WEAPONTYPE_UZI:
- case WEAPONTYPE_AK47:
+ 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:
{
- fired = FireInstantHit(shooter, source);
-
+ if ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON)
+ && shooter == FindPlayerPed()) {
+ addFireRateAsDelay = true;
+ fired = FireM16_1stPerson(shooter);
+ } else {
+ addFireRateAsDelay = false;
+ fired = FireInstantHit(shooter, source);
+ }
break;
}
case WEAPONTYPE_SNIPERRIFLE:
+ case WEAPONTYPE_LASERSCOPE:
{
- fired = FireSniper(shooter);
-
- break;
- }
-
- case WEAPONTYPE_M16:
- {
- if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() )
- fired = FireM16_1stPerson(shooter);
- else
+ if (shooter == FindPlayerPed()) {
+ fired = FireSniper(shooter);
+ } else {
fired = FireInstantHit(shooter, source);
-
+ }
break;
}
@@ -185,6 +266,8 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
case WEAPONTYPE_MOLOTOV:
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_DETONATOR_GRENADE:
+ case WEAPONTYPE_TEARGAS:
{
if ( shooter == FindPlayerPed() )
{
@@ -202,6 +285,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;
}
@@ -222,19 +310,6 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
break;
}
- case WEAPONTYPE_HELICANNON:
- {
- 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);
-
- break;
- }
-
default:
{
debug("Unknown weapon type, Weapon.cpp");
@@ -258,8 +333,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
}
- if (m_nAmmoInClip > 0) m_nAmmoInClip--;
- if (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer)) m_nAmmoTotal--;
+ if (m_nAmmoInClip > 0)
+ m_nAmmoInClip--;
+
+ 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);
@@ -268,8 +346,12 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
if (m_nAmmoInClip == 0)
{
- if (m_nAmmoTotal == 0)
+ if (m_nAmmoTotal == 0) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA)
+ CPad::GetPad(0)->Clear(false);
+
return true;
+ }
m_eWeaponState = WEAPONSTATE_RELOADING;
m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;
@@ -283,7 +365,11 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
return true;
}
- m_nTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ if (addFireRateAsDelay)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate;
+ else
+ m_nTimer = CTimer::GetTimeInMilliseconds();
+
if (shooter == FindPlayerPed())
CStats::RoundsFiredByPlayer++;
}
@@ -294,9 +380,15 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
{
m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;
m_eWeaponState = WEAPONSTATE_FIRING;
+#ifndef AUDIO_NOT_READY
+ if (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW)
+ {
+ DMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, 188, m_eWeaponType << 8);
+ }
+#endif
}
- FireMelee(shooter, *source);
+ fired = FireMelee(shooter, *source);
}
if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT )
@@ -305,8 +397,9 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
return fired;
}
+// --MIAMI: Done
bool
-CWeapon::FireFromCar(CAutomobile *shooter, bool left)
+CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right)
{
ASSERT(shooter!=nil);
@@ -316,12 +409,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;
@@ -337,13 +433,12 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left)
}
m_nTimer = CTimer::GetTimeInMilliseconds() + 1000;
- if ( shooter == FindPlayerVehicle() )
- CStats::RoundsFiredByPlayer++;
}
return true;
}
+// --MIAMI: Done, except commented things
bool
CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
{
@@ -351,28 +446,39 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource)
CWeaponInfo *info = GetInfo();
- bool anim2Playing = false;
- if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) )
- anim2Playing = true;
+ bool anim2Playing = RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false));
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)) {
+
+ // TODO(Miami): BreakGlassPhysically
+ 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->m_bFightMode))
+ continue;
float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius;
if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() )
@@ -381,12 +487,29 @@ 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() )
{
@@ -407,65 +530,124 @@ 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.x += 0.1f * shooterPed->GetUp().x + 0.05f * shooterPed->GetRight().x;
+ dir.y += 0.1f * shooterPed->GetUp().y + 0.05f * shooterPed->GetRight().y;
+ dir.z += 0.1f * shooterPed->GetUp().z + 0.05f * shooterPed->GetRight().z;
+ 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 > 20.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_KO_SKID_FRONT + localDir), false);
else
victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false);
@@ -478,25 +660,155 @@ 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(int 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.00075f * 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;
}
+// --MIAMI: Done except comments
bool
CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)
{
@@ -534,32 +846,50 @@ 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() )
{
- threatAttack->m_pedIK.GetComponentPosition(target, PED_MID);
+ threatAttack->m_pedIK.GetComponentPosition(*(RwV3d *)&target, PED_MID);
threatAttack->ReactToPointGun(shooter);
}
else
target = threatAttack->GetPosition();
target -= *fireSource;
- target *= info->m_fRange / target.Magnitude();
+ float distToTarget = target.Magnitude();
+ target *= info->m_fRange / distToTarget;
target += *fireSource;
- if ( inaccuracy != 0 )
+ if (shooter == FindPlayerPed() && inaccuracy != 0.f)
+ {
+ float newInaccuracy = 2.5f * FindPlayerPed()->m_fAttackButtonCounter * (inaccuracy * Min(1.f, 5.f / 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;
+
+ // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
+ CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true);
CWorld::bIncludeDeadPeds = false;
+ // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
}
else
{
@@ -569,7 +899,9 @@ 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);
+ // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
+ CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true);
+ // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
}
}
else if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() )
@@ -577,12 +909,19 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)
CVector src, trgt;
TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt);
+ // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
CWorld::bIncludeDeadPeds = true;
- ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);
+ CWorld::bIncludeCarTyres = true;
+ CWorld::ProcessLineOfSight(src, trgt, point, victim, true, true, true, true, true, false, false, true);
+ // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
CWorld::bIncludeDeadPeds = false;
+ CWorld::bIncludeCarTyres = false;
+
+ if (victim)
+ CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, src, trgt);
int32 rotSpeed = 1;
- if ( m_eWeaponType == WEAPONTYPE_M16 )
+ if ( m_eWeaponType == WEAPONTYPE_M4 )
rotSpeed = 4;
CVector bulletPos;
@@ -594,140 +933,113 @@ 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;
+
+ target.Normalise();
+ target *= info->m_fRange;
+ target += *fireSource;
+ CWorld::pIgnoreEntity = shooter;
+ CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true);
+ CWorld::pIgnoreEntity = nil;
- CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle));
- rotOffset.Normalise();
+ int32 rotSpeed = 1;
+ if (m_eWeaponType == WEAPONTYPE_M4)
+ 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);
+ }
+ }
+ else
+ {
+ float shooterHeading = RADTODEG(shooter->GetForward().Heading());
+ float shooterAngle = DEGTORAD(shooterHeading);
- if ( shooter->IsPed() )
- DoDoomAiming(shooter, fireSource, &target);
+ CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle));
+ rotOffset.Normalise();
- ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);
+ target = *fireSource;
+ target.x += rotOffset.x * info->m_fRange;
+ target.y += rotOffset.y * info->m_fRange;
- int32 rotSpeed = 1;
- if ( m_eWeaponType == WEAPONTYPE_M16 )
- rotSpeed = 4;
+ CParticle::HandleShootableBirdsStuff(shooter, *fireSource);
+ if (shooter->IsPed() && ((CPed*)shooter)->bDoomAim && (shooter != FindPlayerPed() || !info->m_bCanAim))
+ {
+ CWeapon::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);
+ // CWorld::bProcessPedsOnBoatsAndBikes = 1; // TODO(Miami)
+ CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true);
+ // CWorld::bProcessPedsOnBoatsAndBikes = 0; // TODO(Miami)
+
+ 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 (victim && shooter->IsPed())
+ {
+ if (victim == ((CPed*)shooter)->m_leader)
+ return false;
- CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000);
+ if (victim->IsPed() && ((CPed*)shooter)->IsGangMember() && !((CPed*)victim)->CanBeDamagedByThisGangMember((CPed*)shooter))
+ return false;
+ }
+
+ 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));
+ AddGunFlashBigGuns(*fireSource, *fireSource + target);
CVector gunshellPos = *fireSource;
gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f);
@@ -740,6 +1052,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,
@@ -778,6 +1093,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,
@@ -844,6 +1162,7 @@ CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &d
}
}
+// --MIAMI: Done?
void
CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
CVector *source, CVector *target, CColPoint *point, CVector2D ahead)
@@ -857,72 +1176,99 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
if ( victim )
{
+ if (shooter)
+ {
+ if (shooter && shooter->IsPed() && ((CPed*)shooter)->m_attachedTo == victim)
+ return;
+
+ 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);
+
+ 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);
- if ( shooter != nil )
- {
- if ( shooter == FindPlayerPed() )
- {
- if ( victim->IsPed() || victim->IsVehicle() )
- CStats::InstantHitsHitByPlayer++;
- }
- }
+ if (victim->IsPed() && shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver)
+ shooter = ((CVehicle*)shooter)->pDriver;
- if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 )
+ 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_KO_SKID_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_KO_SKID_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_SHOT_FRONT_PARTIAL + 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();
@@ -931,31 +1277,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_SHOT_FRONT_PARTIAL + 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);
}
}
}
@@ -1000,9 +1368,8 @@ 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);
+ CVector smokePos = point->point - Max(0.1f * dist.Magnitude(), 0.2f) / dist.Magnitude();
#else
CVector smokePos = point->point;
#endif // !FIX_BUGS
@@ -1017,20 +1384,30 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
}
case ENTITY_TYPE_VEHICLE:
{
- ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage);
+ if (point->pieceB >= SURFACE_LAMP_POST && point->pieceB <= SURFACE_METAL_CHAIN_FENCE) {
+ ((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 - (*fireSource);
+ CVector offset = dist - Max(0.2f * dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f);
+ CVector smokePos = *fireSource + 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() )
{
@@ -1055,19 +1432,23 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
CObject *victimObject = (CObject *)victim;
- if ( !victimObject->bInfiniteMass )
+ if ( !victimObject->bInfiniteMass && victimObject->m_fCollisionDamageMultiplier < 99.9f)
{
- if ( victimObject->IsStatic() && victimObject->m_fUprootLimit <= 0.0f )
+ bool notStatic = !victimObject->IsStatic();
+ if (notStatic && victimObject->m_fUprootLimit <= 0.0f)
{
victimObject->bIsStatic = false;
victimObject->AddToMovingList();
}
- if ( !victimObject->IsStatic())
+ notStatic = !victimObject->IsStatic();
+ 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;
@@ -1085,17 +1466,20 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
}
case ENTITY_TYPE_VEHICLE:
{
+ CStats::InstantHitsHitByPlayer++;
DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);
break;
}
case ENTITY_TYPE_PED:
{
+ CStats::InstantHitsHitByPlayer++;
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::InstantHitsHitByPlayer++;
PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point->point);
break;
}
@@ -1116,6 +1500,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
BlowUpExplosiveThings(victim);
}
+// --MIAMI: Done except comments, and didn't check particle coords precisely
bool
CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
{
@@ -1161,10 +1546,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));
CVector source, target;
@@ -1176,12 +1586,17 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target);
CVector 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;
+ CWorld::bIncludeDeadPeds = true;
+ CWorld::bIncludeCarTyres = true;
+ //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes
- ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);
+ CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true);
+ CWorld::bIncludeDeadPeds = false;
+ CWorld::bIncludeCarTyres = false;
}
else
{
@@ -1197,24 +1612,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(*(RwV3d *)&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);
+ //bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes
+ CWorld::ProcessLineOfSight(*fireSource, target, point, victim, true, true, true, true, true, false, false, true);
+ CWorld::bIncludeDeadPeds = false;
}
+ //bProcessPedsOnBoatsAndBikes = false; // TODO(Miami): bProcessPedsOnBoatsAndBikes
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);
+ 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);
if ( victim->IsPed() )
{
CPed *victimPed = (CPed *)victim;
- if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) )
+ if ( !victimPed->DyingOrDead() && victim != shooter )
{
bool cantStandup = true;
@@ -1227,7 +1702,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 )
@@ -1252,7 +1728,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;
@@ -1264,6 +1740,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_FLOOR_HIT_F, 8.0f);
+ }
+ else
+ {
+ hitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
+ }
+ if (hitAssoc)
+ {
+ hitAssoc->SetCurrentTime(0.0f);
+ hitAssoc->SetRun();
+ hitAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ }
+ }
+ }
}
}
else
@@ -1272,21 +1778,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
{
case ENTITY_TYPE_VEHICLE:
{
- ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage);
+ if (point.pieceB >= SURFACE_LAMP_POST && point.pieceB <= SURFACE_METAL_CHAIN_FENCE) {
+ ((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;
}
@@ -1316,13 +1830,15 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
if ( !victimObject->bInfiniteMass )
{
- if ( victimObject->IsStatic() && victimObject->m_fUprootLimit <= 0.0f )
+ bool notStatic = !victimObject->IsStatic();
+ if ( notStatic && victimObject->m_fUprootLimit <= 0.0f )
{
victimObject->bIsStatic = false;
victimObject->AddToMovingList();
}
- if ( !victimObject->IsStatic())
+ notStatic = !victimObject->IsStatic();
+ if ( !notStatic )
{
CVector moveForce = point.normal*-5.0f;
victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z);
@@ -1345,17 +1861,29 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
}
case ENTITY_TYPE_VEHICLE:
{
+ if (!statUpdated) {
+ CStats::InstantHitsHitByPlayer++;
+ statUpdated = true;
+ }
DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);
break;
}
case ENTITY_TYPE_PED:
{
+ if (!statUpdated) {
+ CStats::InstantHitsHitByPlayer++;
+ 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::InstantHitsHitByPlayer++;
+ statUpdated = true;
+ }
PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point);
break;
}
@@ -1388,10 +1916,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() )
{
@@ -1433,7 +1963,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() )
@@ -1442,14 +1972,14 @@ 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);
return true;
}
@@ -1533,7 +2063,7 @@ 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;
@@ -1556,6 +2086,7 @@ CWeapon::FireSniper(CEntity *shooter)
return true;
}
+// --MIAMI: Done
bool
CWeapon::FireM16_1stPerson(CEntity *shooter)
{
@@ -1565,6 +2096,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
@@ -1576,10 +2108,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
CWeaponInfo *info = GetInfo();
+ CWorld::bIncludeCarTyres = true;
+ // bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
+
CColPoint point;
CEntity *victim;
- CWorld::bIncludeCarTyres = true;
CWorld::pIgnoreEntity = shooter;
CWorld::bIncludeDeadPeds = true;
@@ -1589,9 +2123,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
CVector source = cam->Source;
CVector target = cam->Front*info->m_fRange + source;
- ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);
- CWorld::bIncludeDeadPeds = false;
+ if (CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true)) {
+ CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target);
+ }
CWorld::pIgnoreEntity = nil;
+ CWorld::bIncludeDeadPeds = false;
+ // bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
CWorld::bIncludeCarTyres = false;
CVector2D front(cam->Front.x, cam->Front.y);
@@ -1600,7 +2137,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));
@@ -1608,26 +2146,44 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
if ( shooter == FindPlayerPed() )
{
- 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)
{
+// TODO(MIAMI): bikes
CWeaponInfo *info = GetInfo();
CVehicleModelInfo *modelInfo = shooter->GetModelInfo();
@@ -1668,7 +2224,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left)
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);
@@ -1788,6 +2344,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left)
return true;
}
+// --MIAMI: Done
void
CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target)
{
@@ -1800,8 +2357,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];
@@ -1820,7 +2375,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);
@@ -1839,7 +2395,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);
@@ -1928,10 +2487,11 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV
}
}
+// --MIAMI: Done
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);
@@ -1939,27 +2499,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)
{
@@ -1968,14 +2537,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(30.f));
+ }
+ else if (model == MI_SEASPAR || model == MI_SPARROW)
+ {
+ maxAimDistance = Tan(DEGTORAD(10.f));
+ }
- 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;
}
}
@@ -1995,8 +2574,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:
@@ -2007,18 +2588,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 - gReloadSampleTime[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
+ // TODO(Miami): CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo
+ } else
m_eWeaponState = WEAPONSTATE_READY;
}
@@ -2027,11 +2609,59 @@ 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 = 0.5f;
+ break;
+ case ASSOCGRP_COLT:
+ case ASSOCGRP_TEC:
+ soundStart = 0.7f;
+ break;
+ case ASSOCGRP_UZI:
+ soundStart = 0.75f;
+ break;
+ case ASSOCGRP_RIFLE:
+ soundStart = 0.75f;
+ break;
+ case ASSOCGRP_M60:
+ soundStart = 0.7f;
+ break;
+ default:
+ break;
+ }
+ if (reloadAssoc->GetProgress() >= soundStart && (reloadAssoc->currentTime - reloadAssoc->timeStep) / reloadAssoc->hierarchy->totalLength < soundStart) {
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);
+#else
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);
+#endif
+ }
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer && reloadAssoc->GetProgress() < 0.9f) {
+ m_nTimer = CTimer::GetTimeInMilliseconds();
+ }
+ } else {
+ uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType];
+ if (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed) {
+#ifdef AUDIO_NOT_READY
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);
+#else
+ DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);
+#endif
+ }
+ }
}
if ( CTimer::GetTimeInMilliseconds() > m_nTimer )
@@ -2154,13 +2784,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
@@ -2234,6 +2866,7 @@ CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo)
return false;
}
+// --MIAMI: Done
void
CWeapon::BlowUpExplosiveThings(CEntity *thing)
{
@@ -2241,14 +2874,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;
@@ -2267,13 +2900,15 @@ 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
@@ -2282,6 +2917,146 @@ CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPo
return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects);
}
+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));
+}
+
+// --MIAMI: Done
+void
+CWeapon::CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target)
+{
+ if (!(*victim)->IsVehicle())
+ return;
+
+ CColSphere headSphere;
+
+ CVehicle *veh = (CVehicle*)*victim;
+ CColPoint origPoint(*point);
+ float radius = 1.0f;
+ bool found = false;
+ CColLine shootLine(source, target);
+
+ if (veh->pDriver && veh->pDriver->bCanBeShotInVehicle) {
+ CVector pos(0.f, 0.f, 0.f);
+ veh->pDriver->TransformToNode(pos, PED_HEAD);
+ headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);
+ if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {
+ *victim = veh->pDriver;
+ found = true;
+ }
+ }
+
+ for(int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
+ CPed *passenger = veh->pPassengers[i];
+ if (passenger && passenger->bCanBeShotInVehicle) {
+ CVector pos(0.f, 0.f, 0.f);
+ passenger->TransformToNode(pos, PED_HEAD);
+ headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);
+ if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {
+ *victim = passenger;
+ found = true;
+ }
+ }
+ }
+ if (veh->IsCar()) {
+ CVector distVec = target - source;
+ if (DotProduct(distVec, veh->GetForward()) < 0.0f && DotProduct(distVec, veh->GetUp()) <= 0.0f) {
+ CColModel *colModel = veh->GetColModel();
+ if (colModel->numTriangles > 0) {
+ bool passesGlass = false;
+ CMatrix invVehMat;
+ Invert(veh->GetMatrix(), invVehMat);
+ shootLine.p0 = invVehMat * shootLine.p0;
+ shootLine.p1 = invVehMat * shootLine.p1;
+ CCollision::CalculateTrianglePlanes(colModel);
+ for (int i = 0; i < colModel->numTriangles; i++) {
+ if (colModel->triangles[i].surface == SURFACE_GLASS &&
+ CCollision::TestLineTriangle(shootLine, colModel->vertices, colModel->triangles[i], colModel->trianglePlanes[i])) {
+ passesGlass = true;
+ break;
+ }
+ }
+ CAutomobile *car = (CAutomobile*)veh;
+
+ // No need to damage windscreen if there isn't one.
+ if (passesGlass && car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN)) {
+ if (car->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) == PANEL_STATUS_SMASHED2)
+ car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN);
+
+ car->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, true);
+ DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.f);
+ }
+ }
+ }
+ }
+
+ if (!found) {
+ *victim = veh;
+ *point = origPoint;
+ }
+}
+
#ifdef COMPATIBLE_SAVES
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index c7685e0d..cb59582f 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -2,12 +2,13 @@
#include "WeaponType.h"
-#define DRIVEBYAUTOAIMING_MAXDIST (2.5f)
+#define CAR_DRIVEBYAUTOAIMING_MAXDIST (2.5f)
#define DOOMAUTOAIMING_MAXDIST (9000.0f)
class CEntity;
class CPhysical;
-class CAutomobile;
+class CVehicle;
+class CPed;
struct CColPoint;
class CWeaponInfo;
@@ -24,6 +25,7 @@ public:
CWeapon() {
m_bAddRotOffset = false;
}
+ CWeapon(eWeaponType type, int32 ammo);
CWeaponInfo *GetInfo();
@@ -32,9 +34,10 @@ public:
static void UpdateWeapons (void);
void Initialise(eWeaponType type, int32 ammo);
+ void Shutdown();
bool Fire (CEntity *shooter, CVector *fireSource);
- bool FireFromCar (CAutomobile *shooter, bool left);
+ bool FireFromCar (CVehicle *shooter, bool left, bool right);
bool FireMelee (CEntity *shooter, CVector &fireSource);
bool FireInstantHit(CEntity *shooter, CVector *fireSource);
@@ -49,14 +52,14 @@ public:
bool FireAreaEffect (CEntity *shooter, CVector *fireSource);
bool FireSniper (CEntity *shooter);
bool FireM16_1stPerson (CEntity *shooter);
- bool FireInstantHitFromCar(CAutomobile *shooter, bool left);
+ bool FireInstantHitFromCar(CVehicle *shooter, bool left, bool right);
static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target);
static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target);
- static void DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target);
+ static void DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target);
void Reload(void);
- void Update(int32 audioEntity);
+ void Update(int32 audioEntity, CPed *pedToAdjustSound);
bool IsTypeMelee (void);
bool IsType2Handed(void);
@@ -65,9 +68,15 @@ public:
bool HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo);
static void BlowUpExplosiveThings(CEntity *thing);
bool HasWeaponAmmoToBeUsed(void);
+ static void AddGunFlashBigGuns(CVector, CVector);
+ static bool IsShotgun(int weapon) { return weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_SPAS12_SHOTGUN || weapon == WEAPONTYPE_STUBBY_SHOTGUN; }
+
+ // TODO(Miami): Is that still used?
static bool 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);
+ static void CheckForShootingVehicleOccupant(CEntity**, CColPoint*, eWeaponType, CVector const&, CVector const&);
+
#ifdef COMPATIBLE_SAVES
void Save(uint8*& buf);
void Load(uint8*& buf);
diff --git a/src/weapons/WeaponEffects.cpp b/src/weapons/WeaponEffects.cpp
index 46195d2c..fb50bbe0 100644
--- a/src/weapons/WeaponEffects.cpp
+++ b/src/weapons/WeaponEffects.cpp
@@ -36,7 +36,7 @@ CWeaponEffects::Init(void)
int32 slot = CTxdStore::FindTxdSlot("particle");
CTxdStore::SetCurrentTxd(slot);
- gpCrossHairTex = RwTextureRead("crosshair", nil);
+ gpCrossHairTex = RwTextureRead("target256", "target256m");
gpCrossHairRaster = RwTextureGetRaster(gpCrossHairTex);
CTxdStore::PopCurrentTxd();
diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp
index c4ab75d2..bd53d8c5 100644
--- a/src/weapons/WeaponInfo.cpp
+++ b/src/weapons/WeaponInfo.cpp
@@ -6,70 +6,119 @@
#include "AnimManager.h"
#include "AnimBlendAssociation.h"
#include "Weapon.h"
+#include "ModelInfo.h"
+#include "ModelIndices.h"
+
+// Yeah...
+int32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS];
+// --MIAMI: Todo
static char ms_aWeaponNames[][32] = {
"Unarmed",
+ "BrassKnuckle",
+ "ScrewDriver",
+ "GolfClub",
+ "NightStick",
+ "Knife",
"BaseballBat",
+ "Hammer",
+ "Cleaver",
+ "Machete",
+ "Katana",
+ "Chainsaw",
+ "Grenade",
+ "DetonateGrenade",
+ "TearGas",
+ "Molotov",
+ "Rocket",
"Colt45",
- "Uzi",
+ "Python",
"Shotgun",
- "AK47",
- "M16",
+ "Spas12Shotgun",
+ "StubbyShotgun",
+ "Tec9",
+ "Uzi",
+ "SilencedIngram",
+ "Mp5",
+ "m4",
+ "Ruger",
"SniperRifle",
+ "LaserScope",
"RocketLauncher",
"FlameThrower",
- "Molotov",
- "Grenade",
+ "M60",
+ "Minigun",
"Detonator",
- "HeliCannon"
+ "HeliCannon",
+ "Camera",
};
CWeaponInfo*
-CWeaponInfo::GetWeaponInfo(eWeaponType weaponType) {
+CWeaponInfo::GetWeaponInfo(eWeaponType weaponType)
+{
return &CWeaponInfo::ms_apWeaponInfos[weaponType];
}
+// --MIAMI: done except WEAPONTYPE_TOTALWEAPONS value
void
CWeaponInfo::Initialise(void)
{
debug("Initialising CWeaponInfo...\n");
for (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {
ms_apWeaponInfos[i].m_eWeaponFire = WEAPON_FIRE_INSTANT_HIT;
- ms_apWeaponInfos[i].m_AnimToPlay = ANIM_PUNCH_R;
- ms_apWeaponInfos[i].m_Anim2ToPlay = NUM_ANIMS;
+ ms_apWeaponInfos[i].m_fRange = 0.0f;
+ ms_apWeaponInfos[i].m_nFiringRate = 0;
+ ms_apWeaponInfos[i].m_nReload = 0;
+ ms_apWeaponInfos[i].m_nAmountofAmmunition = 0;
+ ms_apWeaponInfos[i].m_nDamage = 0;
+ ms_apWeaponInfos[i].m_fSpeed = 0.0f;
+ ms_apWeaponInfos[i].m_fRadius = 0.0f;
+ ms_apWeaponInfos[i].m_fLifespan = 0.0f;
+ ms_apWeaponInfos[i].m_fSpread = 0.0f;
+ ms_apWeaponInfos[i].m_vecFireOffset = CVector(0.0f, 0.0f, 0.0f);
+ ms_apWeaponInfos[i].m_AnimToPlay = ASSOCGRP_UNARMED;
+ ms_apWeaponInfos[i].m_fAnimLoopStart = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimLoopEnd = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimFrameFire = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2LoopStart = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2LoopEnd = 0.0f;
+ ms_apWeaponInfos[i].m_fAnim2FrameFire = 0.0f;
+ ms_apWeaponInfos[i].m_fAnimBreakout = 0.0f;
ms_apWeaponInfos[i].m_bUseGravity = 1;
ms_apWeaponInfos[i].m_bSlowsDown = 1;
ms_apWeaponInfos[i].m_bRandSpeed = 1;
ms_apWeaponInfos[i].m_bExpands = 1;
ms_apWeaponInfos[i].m_bExplodes = 1;
+ ms_apWeaponInfos[i].m_nWeaponSlot = 0;
}
debug("Loading weapon data...\n");
LoadWeaponData();
debug("CWeaponInfo ready\n");
}
+// --MIAMI: Done, commented parts wait for weapons port
void
CWeaponInfo::LoadWeaponData(void)
{
float spread, speed, lifeSpan, radius;
float range, fireOffsetX, fireOffsetY, fireOffsetZ;
- float delayBetweenAnimAndFire, delayBetweenAnim2AndFire, animLoopStart, animLoopEnd;
+ float anim2LoopStart, anim2LoopEnd, delayBetweenAnim2AndFire, animBreakout;
+ float delayBetweenAnimAndFire, animLoopStart, animLoopEnd;
int flags, ammoAmount, damage, reload, weaponType;
- int firingRate, modelId;
+ int firingRate, modelId, modelId2, weaponSlot;
char line[256], weaponName[32], fireType[32];
- char animToPlay[32], anim2ToPlay[32];
-
- CAnimBlendAssociation *animAssoc;
- AnimationId animId;
+ char animToPlay[32];
int bp, buflen;
int lp, linelen;
CFileMgr::SetDir("DATA");
buflen = CFileMgr::LoadFile("WEAPON.DAT", work_buff, sizeof(work_buff), "r");
- CFileMgr::SetDir("");
for (bp = 0; bp < buflen; ) {
// read file line by line
@@ -101,10 +150,9 @@ CWeaponInfo::LoadWeaponData(void)
fireType[0] = '\0';
fireOffsetY = 0.0f;
fireOffsetZ = 0.0f;
- animId = ANIM_WALK;
sscanf(
&line[lp],
- "%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %s %f %f %f %f %d %d",
+ "%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %f %f %f %f %f %f %f %d %d %x %d",
weaponName,
fireType,
&range,
@@ -120,27 +168,23 @@ CWeaponInfo::LoadWeaponData(void)
&fireOffsetY,
&fireOffsetZ,
animToPlay,
- anim2ToPlay,
&animLoopStart,
&animLoopEnd,
&delayBetweenAnimAndFire,
+ &anim2LoopStart,
+ &anim2LoopEnd,
&delayBetweenAnim2AndFire,
+ &animBreakout,
&modelId,
- &flags);
+ &modelId2,
+ &flags,
+ &weaponSlot);
if (strncmp(weaponName, "ENDWEAPONDATA", 13) == 0)
return;
weaponType = FindWeaponType(weaponName);
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animToPlay);
- animId = static_cast<AnimationId>(animAssoc->animId);
-
- if (strncmp(anim2ToPlay, "null", 4) != 0) {
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, anim2ToPlay);
- ms_apWeaponInfos[weaponType].m_Anim2ToPlay = (AnimationId) animAssoc->animId;
- }
-
CVector vecFireOffset(fireOffsetX, fireOffsetY, fireOffsetZ);
ms_apWeaponInfos[weaponType].m_eWeaponFire = FindWeaponFireType(fireType);
@@ -154,12 +198,16 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_fLifespan = lifeSpan;
ms_apWeaponInfos[weaponType].m_fSpread = spread;
ms_apWeaponInfos[weaponType].m_vecFireOffset = vecFireOffset;
- ms_apWeaponInfos[weaponType].m_AnimToPlay = animId;
ms_apWeaponInfos[weaponType].m_fAnimLoopStart = animLoopStart / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnimLoopEnd = animLoopEnd / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnim2LoopStart = anim2LoopStart / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnim2LoopEnd = anim2LoopEnd / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;
ms_apWeaponInfos[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;
+ ms_apWeaponInfos[weaponType].m_fAnimBreakout = animBreakout / 30.0f;
ms_apWeaponInfos[weaponType].m_nModelId = modelId;
+ ms_apWeaponInfos[weaponType].m_nModel2Id = modelId2;
+
ms_apWeaponInfos[weaponType].m_bUseGravity = flags;
ms_apWeaponInfos[weaponType].m_bSlowsDown = flags >> 1;
ms_apWeaponInfos[weaponType].m_bDissipates = flags >> 2;
@@ -171,6 +219,37 @@ CWeaponInfo::LoadWeaponData(void)
ms_apWeaponInfos[weaponType].m_b1stPerson = flags >> 8;
ms_apWeaponInfos[weaponType].m_bHeavy = flags >> 9;
ms_apWeaponInfos[weaponType].m_bThrow = flags >> 10;
+ ms_apWeaponInfos[weaponType].m_bReloadLoop2Start = flags >> 11;
+ ms_apWeaponInfos[weaponType].m_bUse2nd = flags >> 12;
+ ms_apWeaponInfos[weaponType].m_bGround2nd = flags >> 13;
+ ms_apWeaponInfos[weaponType].m_bFinish3rd = flags >> 14;
+ ms_apWeaponInfos[weaponType].m_bReload = flags >> 15;
+ ms_apWeaponInfos[weaponType].m_bFightMode = flags >> 16;
+ ms_apWeaponInfos[weaponType].m_bCrouchFire = flags >> 17;
+ ms_apWeaponInfos[weaponType].m_bCop3rd = flags >> 18;
+ ms_apWeaponInfos[weaponType].m_bGround3rd = flags >> 19;
+ ms_apWeaponInfos[weaponType].m_bPartialAttack = flags >> 20;
+ ms_apWeaponInfos[weaponType].m_bAnimDetonate = flags >> 21;
+
+ ms_apWeaponInfos[weaponType].m_nWeaponSlot = weaponSlot;
+
+ if (animLoopEnd < 98.0f && weaponType != WEAPONTYPE_FLAMETHROWER && !CWeapon::IsShotgun(weaponType))
+ ms_apWeaponInfos[weaponType].m_nFiringRate = ((ms_apWeaponInfos[weaponType].m_fAnimLoopEnd - ms_apWeaponInfos[weaponType].m_fAnimLoopStart) * 900.0f);
+
+ if (weaponType == WEAPONTYPE_DETONATOR || weaponType == WEAPONTYPE_HELICANNON)
+ modelId = -1;
+ else if (weaponType == WEAPONTYPE_DETONATOR_GRENADE)
+ modelId = MI_BOMB;
+
+ if (modelId != -1)
+ ((CWeaponModelInfo*)CModelInfo::GetModelInfo(modelId))->SetWeaponInfo(weaponType);
+
+ for (int i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++) {
+ if (!strcmp(animToPlay, CAnimManager::GetAnimGroupName((AssocGroupId)i))) {
+ ms_apWeaponInfos[weaponType].m_AnimToPlay = (AssocGroupId)i;
+ break;
+ }
+ }
}
}
@@ -192,6 +271,7 @@ CWeaponInfo::FindWeaponFireType(char *name)
if (strcmp(name, "INSTANT_HIT") == 0) return WEAPON_FIRE_INSTANT_HIT;
if (strcmp(name, "PROJECTILE") == 0) return WEAPON_FIRE_PROJECTILE;
if (strcmp(name, "AREA_EFFECT") == 0) return WEAPON_FIRE_AREA_EFFECT;
+ if (strcmp(name, "CAMERA") == 0) return WEAPON_FIRE_CAMERA;
Error("Unknown weapon fire type, WeaponInfo.cpp");
return WEAPON_FIRE_INSTANT_HIT;
}
diff --git a/src/weapons/WeaponInfo.h b/src/weapons/WeaponInfo.h
index c89dd482..e7013004 100644
--- a/src/weapons/WeaponInfo.h
+++ b/src/weapons/WeaponInfo.h
@@ -1,12 +1,16 @@
#pragma once
+#include "AnimManager.h"
#include "AnimationId.h"
#include "WeaponType.h"
+enum AssocGroupId;
+
class CWeaponInfo {
-// static CWeaponInfo(&ms_apWeaponInfos)[14];
- static CWeaponInfo ms_apWeaponInfos[WEAPONTYPE_LAST_WEAPONTYPE];
+ static CWeaponInfo ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS];
public:
+ static int32 ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS];
+
eWeaponFire m_eWeaponFire;
float m_fRange;
uint32 m_nFiringRate;
@@ -18,13 +22,16 @@ public:
float m_fLifespan;
float m_fSpread;
CVector m_vecFireOffset;
- AnimationId m_AnimToPlay;
- AnimationId m_Anim2ToPlay;
+ AssocGroupId m_AnimToPlay;
float m_fAnimLoopStart;
float m_fAnimLoopEnd;
float m_fAnimFrameFire;
+ float m_fAnim2LoopStart;
+ float m_fAnim2LoopEnd;
float m_fAnim2FrameFire;
+ float m_fAnimBreakout;
int32 m_nModelId;
+ int32 m_nModel2Id;
// flags
uint8 m_bUseGravity : 1;
uint8 m_bSlowsDown : 1;
@@ -34,9 +41,24 @@ public:
uint8 m_bExplodes : 1;
uint8 m_bCanAim : 1;
uint8 m_bCanAimWithArm : 1;
+
uint8 m_b1stPerson : 1;
uint8 m_bHeavy : 1;
uint8 m_bThrow : 1;
+ uint8 m_bReloadLoop2Start : 1;
+ uint8 m_bUse2nd : 1;
+ uint8 m_bGround2nd : 1;
+ uint8 m_bFinish3rd : 1;
+ uint8 m_bReload : 1;
+
+ uint8 m_bFightMode : 1;
+ uint8 m_bCrouchFire : 1;
+ uint8 m_bCop3rd : 1;
+ uint8 m_bGround3rd : 1;
+ uint8 m_bPartialAttack : 1;
+ uint8 m_bAnimDetonate : 1;
+
+ uint32 m_nWeaponSlot;
static void Initialise(void);
static void LoadWeaponData(void);
@@ -46,4 +68,4 @@ public:
static void Shutdown(void);
};
-VALIDATE_SIZE(CWeaponInfo, 0x54); \ No newline at end of file
+VALIDATE_SIZE(CWeaponInfo, 0x64);
diff --git a/src/weapons/WeaponType.h b/src/weapons/WeaponType.h
index b45740b7..65d715ec 100644
--- a/src/weapons/WeaponType.h
+++ b/src/weapons/WeaponType.h
@@ -3,20 +3,44 @@
enum eWeaponType
{
WEAPONTYPE_UNARMED,
+ WEAPONTYPE_BRASSKNUCKLE,
+ WEAPONTYPE_SCREWDRIVER,
+ WEAPONTYPE_GOLFCLUB,
+ WEAPONTYPE_NIGHTSTICK,
+ WEAPONTYPE_KNIFE,
WEAPONTYPE_BASEBALLBAT,
+ WEAPONTYPE_HAMMER,
+ WEAPONTYPE_CLEAVER,
+ WEAPONTYPE_MACHETE,
+ WEAPONTYPE_KATANA,
+ WEAPONTYPE_CHAINSAW,
+ WEAPONTYPE_GRENADE,
+ WEAPONTYPE_DETONATOR_GRENADE,
+ WEAPONTYPE_TEARGAS,
+ WEAPONTYPE_MOLOTOV,
+ WEAPONTYPE_ROCKET,
WEAPONTYPE_COLT45,
- WEAPONTYPE_UZI,
+ WEAPONTYPE_PYTHON,
WEAPONTYPE_SHOTGUN,
- WEAPONTYPE_AK47,
- WEAPONTYPE_M16,
+ WEAPONTYPE_SPAS12_SHOTGUN,
+ WEAPONTYPE_STUBBY_SHOTGUN,
+ WEAPONTYPE_TEC9,
+ WEAPONTYPE_UZI,
+ WEAPONTYPE_SILENCED_INGRAM,
+ WEAPONTYPE_MP5,
+ WEAPONTYPE_M4,
+ WEAPONTYPE_RUGER,
WEAPONTYPE_SNIPERRIFLE,
+ WEAPONTYPE_LASERSCOPE,
WEAPONTYPE_ROCKETLAUNCHER,
WEAPONTYPE_FLAMETHROWER,
- WEAPONTYPE_MOLOTOV,
- WEAPONTYPE_GRENADE,
+ WEAPONTYPE_M60,
+ WEAPONTYPE_MINIGUN,
WEAPONTYPE_DETONATOR,
WEAPONTYPE_HELICANNON,
- WEAPONTYPE_LAST_WEAPONTYPE,
+ WEAPONTYPE_CAMERA,
+ WEAPONTYPE_TOTALWEAPONS = 37,
+ WEAPONTYPE_HEALTH = 37,
WEAPONTYPE_ARMOUR,
WEAPONTYPE_RAMMEDBYCAR,
WEAPONTYPE_RUNOVERBYCAR,
@@ -25,9 +49,12 @@ enum eWeaponType
WEAPONTYPE_DROWNING,
WEAPONTYPE_FALL,
WEAPONTYPE_UNIDENTIFIED,
-
- WEAPONTYPE_TOTALWEAPONS = WEAPONTYPE_LAST_WEAPONTYPE,
- WEAPONTYPE_TOTAL_INVENTORY_WEAPONS = 13,
+ WEAPONTYPE_ANYMELEE,
+ WEAPONTYPE_ANYWEAPON
+};
+
+enum {
+ TOTAL_WEAPON_SLOTS = 10,
};
enum eWeaponFire {
@@ -35,7 +62,7 @@ enum eWeaponFire {
WEAPON_FIRE_INSTANT_HIT,
WEAPON_FIRE_PROJECTILE,
WEAPON_FIRE_AREA_EFFECT,
- WEAPON_FIRE_USE
+ WEAPON_FIRE_CAMERA
};
// Taken from MTA SA, seems it's unchanged