Ducking, shooting vehicle occupants and weapon fixes

This commit is contained in:
eray orçunus
2020-06-20 16:23:32 +03:00
parent e9e533b0cb
commit 0625954bb7
11 changed files with 240 additions and 94 deletions

View File

@ -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;

View File

@ -386,6 +386,7 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource)
return fired;
}
// --MIAMI: Done
bool
CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right)
{
@ -401,8 +402,11 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right)
{
DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--;
if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--;
if ( m_nAmmoInClip > 0 )
m_nAmmoInClip--;
if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 && (!shooter || shooter->GetStatus() != STATUS_PLAYER || CStats::GetPercentageProgress() < 100.f))
m_nAmmoTotal--;
m_eWeaponState = WEAPONSTATE_FIRING;
@ -418,8 +422,6 @@ CWeapon::FireFromCar(CVehicle *shooter, bool left, bool right)
}
m_nTimer = CTimer::GetTimeInMilliseconds() + 1000;
if ( shooter == FindPlayerVehicle() )
CStats::RoundsFiredByPlayer++;
}
return true;
@ -898,18 +900,17 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)
// bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
CWorld::bIncludeDeadPeds = true;
// bProcessVehicleWheels = true; // TODO(Miami)
CWorld::bIncludeCarTyres = true;
CWorld::ProcessLineOfSight(src, trgt, point, victim, true, true, true, true, true, false, false, true);
// bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
CWorld::bIncludeDeadPeds = false;
// bProcessVehicleWheels = false; // TODO(Miami)
CWorld::bIncludeCarTyres = false;
// TODO(Miami)
// if (victim)
// CWeapon::CheckForShootingVehicleOccupant(v39, victim, point, m_eWeaponType, src, trgt);
if (victim)
CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, src, trgt);
int32 rotSpeed = 1;
if ( m_eWeaponType == WEAPONTYPE_M4 )
if ( m_eWeaponType == WEAPONTYPE_M4 )
rotSpeed = 4;
CVector bulletPos;
@ -1579,12 +1580,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
target *= info->m_fRange;
target += source;
CWorld::bIncludeDeadPeds = true;
//bProcessVehicleWheels = true; // TODO(Miami): bProcessVehicleWheels
CWorld::bIncludeCarTyres = true;
//bProcessPedsOnBoatsAndBikes = true; // TODO(Miami): bProcessPedsOnBoatsAndBikes
CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true);
CWorld::bIncludeDeadPeds = false;
//bProcessVehicleWheels = false; // TODO(Miami): bProcessVehicleWheels
CWorld::bIncludeCarTyres = false;
}
else
{
@ -2074,7 +2075,7 @@ CWeapon::FireSniper(CEntity *shooter)
return true;
}
// --MIAMI: Heavily TODO
// --MIAMI: Done
bool
CWeapon::FireM16_1stPerson(CEntity *shooter)
{
@ -2096,10 +2097,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
CWeaponInfo *info = GetInfo();
CWorld::bIncludeCarTyres = true;
// bProcessPedsOnBoatsAndBikes = true; // TODO(Miami)
CColPoint point;
CEntity *victim;
CWorld::bIncludeCarTyres = true;
CWorld::pIgnoreEntity = shooter;
CWorld::bIncludeDeadPeds = true;
@ -2109,9 +2112,12 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
CVector source = cam->Source;
CVector target = cam->Front*info->m_fRange + source;
ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);
CWorld::bIncludeDeadPeds = false;
if (CWorld::ProcessLineOfSight(source, target, point, victim, true, true, true, true, true, false, false, true)) {
CheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target);
}
CWorld::pIgnoreEntity = nil;
CWorld::bIncludeDeadPeds = false;
// bProcessPedsOnBoatsAndBikes = false; // TODO(Miami)
CWorld::bIncludeCarTyres = false;
CVector2D front(cam->Front.x, cam->Front.y);
@ -2129,18 +2135,18 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
if ( shooter == FindPlayerPed() )
{
CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z);
float mult;
switch (m_eWeaponType) {
case WEAPONTYPE_M4:
case WEAPONTYPE_HELICANNON:
case WEAPONTYPE_M60:
mult = 0.0003f;
break;
case WEAPONTYPE_RUGER:
mult = 0.00015f;
break;
case WEAPONTYPE_HELICANNON:
case WEAPONTYPE_M60:
mult = 0.0003f;
break;
default:
mult = 0.0002f;
break;
@ -2151,6 +2157,13 @@ CWeapon::FireM16_1stPerson(CEntity *shooter)
TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;
TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;
// yes, double
double notFiringRate = (20.0 - info->m_nFiringRate) / 80.0;
double raisedNotFiringRate = Max(1.0, Max(0.0, notFiringRate));
uint8 shakeFreq = 80.0 * raisedNotFiringRate + 130.0;
CPad::GetPad(0)->StartShake(20000.0f * CTimer::GetTimeStep() / shakeFreq, shakeFreq);
}
return true;
@ -2957,6 +2970,81 @@ CWeapon::AddGunFlashBigGuns(CVector start, CVector end)
CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f));
}
// --MIAMI: Done
void
CWeapon::CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target)
{
if (!(*victim)->IsVehicle())
return;
CColSphere headSphere;
CVehicle *veh = (CVehicle*)*victim;
CColPoint origPoint(*point);
float radius = 1.0f;
bool found = false;
CColLine shootLine(source, target);
if (veh->pDriver && veh->pDriver->bCanBeShotInVehicle) {
CVector pos(0.f, 0.f, 0.f);
veh->pDriver->TransformToNode(pos, PED_HEAD);
headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);
if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {
*victim = veh->pDriver;
found = true;
}
}
for(int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {
CPed *passenger = veh->pPassengers[i];
if (passenger && passenger->bCanBeShotInVehicle) {
CVector pos(0.f, 0.f, 0.f);
passenger->TransformToNode(pos, PED_HEAD);
headSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);
if (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {
*victim = passenger;
found = true;
}
}
}
if (veh->IsCar()) {
CVector distVec = target - source;
if (DotProduct(distVec, veh->GetForward()) < 0.0f && DotProduct(distVec, veh->GetUp()) <= 0.0f) {
CColModel *colModel = veh->GetColModel();
if (colModel->numTriangles > 0) {
bool passesGlass = false;
CMatrix invVehMat;
Invert(veh->GetMatrix(), invVehMat);
shootLine.p0 = invVehMat * shootLine.p0;
shootLine.p1 = invVehMat * shootLine.p1;
CCollision::CalculateTrianglePlanes(colModel);
for (int i = 0; i < colModel->numTriangles; i++) {
if (colModel->triangles[i].surface == SURFACE_GLASS &&
CCollision::TestLineTriangle(shootLine, colModel->vertices, colModel->triangles[i], colModel->trianglePlanes[i])) {
passesGlass = true;
break;
}
}
CAutomobile *car = (CAutomobile*)veh;
// No need to damage windscreen if there isn't one.
if (passesGlass && car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN)) {
if (car->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) == PANEL_STATUS_SMASHED2)
car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN);
car->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, true);
DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.f);
}
}
}
}
if (!found) {
*victim = veh;
*point = origPoint;
}
}
#ifdef COMPATIBLE_SAVES
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));

View File

@ -72,8 +72,11 @@ public:
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);