From 347f0a0e9c687a198ba7fd0ead67a2d63b7880f2 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 1 Apr 2020 01:58:40 +0300 Subject: [PATCH] vehicles missing functions + fixes --- src/control/Garages.cpp | 12 ++- src/control/Pickups.cpp | 29 +++--- src/vehicles/Vehicle.cpp | 188 ++++++++++++++++++++++++++++++++++++++- src/vehicles/Vehicle.h | 3 +- src/weapons/Weapon.cpp | 1 + src/weapons/Weapon.h | 2 + 6 files changed, 207 insertions(+), 28 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 93857b14..68d58b10 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -2078,14 +2078,12 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle) return; if (IsAnyOtherPedTouchingGarage(FindPlayerPed())) return; - float posX = pVehicle->GetPosition().x; - float posY = pVehicle->GetPosition().y; - float posZ = pVehicle->GetPosition().z; + CVector pos = pVehicle->GetPosition(); float garageX = GetGarageCenterX(); float garageY = GetGarageCenterY(); - float offsetX = garageX - posX; - float offsetY = garageY - posY; - float offsetZ = posZ - posZ; + float offsetX = garageX - pos.x; + float offsetY = garageY - pos.y; + float offsetZ = pos.z - pos.z; float distance = CVector(offsetX, offsetY, offsetZ).Magnitude(); if (distance < RESPRAY_CENTERING_COEFFICIENT) { pVehicle->GetPosition().x = GetGarageCenterX(); @@ -2096,7 +2094,7 @@ void CGarage::CenterCarInGarage(CVehicle* pVehicle) pVehicle->GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance; } if (!IsEntityEntirelyInside3D(pVehicle, 0.1f)) - pVehicle->GetPosition() = CVector(posX, posY, posZ); + pVehicle->GetPosition() = pos; } void CGarages::CloseHideOutGaragesBeforeSave() diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index b1832f0e..3e3c2a48 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -20,6 +20,9 @@ #include "Fire.h" #include "PointLights.h" #include "Pools.h" +#ifdef FIX_BUGS +#include "Replay.h" +#endif #include "Script.h" #include "Shadows.h" #include "SpecialFX.h" @@ -642,32 +645,26 @@ CPickups::AddToCollectedPickupsArray(int32 index) void CPickups::Update() { -#ifndef FIX_BUGS - // BUG: this code can only reach 318 out of 320 pickups +#ifdef FIX_BUGS // RIP speedrunning (solution from SA) + if (CReplay::IsPlayingBack()) + return; +#endif #define PICKUPS_FRAME_SPAN (6) -#define PICKUPS_PER_FRAME (NUMGENERALPICKUPS/PICKUPS_FRAME_SPAN) - - for (uint32 i = PICKUPS_PER_FRAME * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < PICKUPS_PER_FRAME * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) { +#ifdef FIX_BUGS + for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) { +#else // BUG: this code can only reach 318 out of 320 pickups + for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) { +#endif if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { AddToCollectedPickupsArray(i); } } - +#undef PICKUPS_FRAME_SPAN for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) { if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { AddToCollectedPickupsArray(i); } } - -#undef PICKUPS_FRAME_SPAN -#undef PICKUPS_PER_FRAME -#else - for (uint32 i = 0; i < NUMPICKUPS; i++) { - if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) { - AddToCollectedPickupsArray(i); - } - } -#endif } void diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 1fe02953..adeba19e 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -31,10 +31,17 @@ void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehicleP void CVehicle::operator delete(void *p, size_t sz) { CPools::GetVehiclePool()->Delete((CVehicle*)p); } void CVehicle::operator delete(void *p, int handle) { CPools::GetVehiclePool()->Delete((CVehicle*)p); } -WRAPPER bool CVehicle::ShufflePassengersToMakeSpace(void) { EAXJMP(0x5528A0); } -// or Weapon.cpp? -WRAPPER void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage) { EAXJMP(0x563B00); } -WRAPPER void CVehicle::InflictDamage(CEntity *damagedBy, uint32 weaponType, float damage) { EAXJMP(0x551950); } +#ifdef FIX_BUGS +// I think they meant that +#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (MYRAND_MAX * 35 / 100) +#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (MYRAND_MAX * 70 / 100) +#else +#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (35000) +#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (70000) +#endif +#define DAMAGE_HEALTH_TO_FLEE_ALWAYS (200.0f) +#define DAMAGE_HEALTH_TO_CATCH_FIRE (250.0f) + CVehicle::CVehicle(uint8 CreatedBy) { @@ -361,6 +368,119 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec return angularVelocity * CTimer::GetTimeStep(); } +void +CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage) +{ + if (!bCanBeDamaged) + return; + if (bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle())) + return; + bool bFrightensDriver = false; + switch (weaponType) { + case WEAPONTYPE_UNARMED: + case WEAPONTYPE_BASEBALLBAT: + if (bMeleeProof) + return; + break; + case WEAPONTYPE_COLT45: + case WEAPONTYPE_UZI: + case WEAPONTYPE_SHOTGUN: + case WEAPONTYPE_AK47: + case WEAPONTYPE_M16: + case WEAPONTYPE_SNIPERRIFLE: + case WEAPONTYPE_TOTAL_INVENTORY_WEAPONS: + case WEAPONTYPE_UZI_DRIVEBY: + if (bBulletProof) + return; + bFrightensDriver = true; + break; + case WEAPONTYPE_ROCKETLAUNCHER: + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_GRENADE: + case WEAPONTYPE_EXPLOSION: + if (bExplosionProof) + return; + bFrightensDriver = true; + break; + case WEAPONTYPE_FLAMETHROWER: + if (bFireProof) + return; + break; + case WEAPONTYPE_RAMMEDBYCAR: + if (bCollisionProof) + return; + break; + default: + break; + } + if (m_fHealth > 0.0f) { + if (VehicleCreatedBy == RANDOM_VEHICLE && pDriver && + (m_status == STATUS_SIMPLE || m_status == STATUS_PHYSICS) && + AutoPilot.m_nCarMission == MISSION_CRUISE) { + if (m_randomSeed < DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE) { + CCarCtrl::SwitchVehicleToRealPhysics(this); + AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; + AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fUnkMaxVelocity; + m_status = STATUS_PHYSICS; + } + } + m_nLastWeaponDamage = weaponType; + float oldHealth = m_fHealth; + if (m_fHealth > damage) { + m_fHealth -= damage; + if (VehicleCreatedBy == RANDOM_VEHICLE && + (m_fHealth < DAMAGE_HEALTH_TO_FLEE_ALWAYS || + bFrightensDriver && m_randomSeed > DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE)) { + switch (m_status) { + case STATUS_SIMPLE: + case STATUS_PHYSICS: + if (pDriver) { + m_status = STATUS_ABANDONED; + pDriver->bFleeAfterExitingCar = true; + pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + } + for (int i = 0; i < m_nNumMaxPassengers; i++) { + if (pPassengers[i]) { + pPassengers[i]->bFleeAfterExitingCar = true; + pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); + } + } + break; + default: + break; + } + } + if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { + if (IsCar()) { + CAutomobile* pThisCar = (CAutomobile*)this; + pThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE); + pThisCar->m_pSetOnFireEntity = damagedBy; + if (damagedBy) + damagedBy->RegisterReference((CEntity**)&pThisCar->m_pSetOnFireEntity); + } + } + } + else { + m_fHealth = 0.0f; + if (weaponType == WEAPONTYPE_EXPLOSION) { + // between 1000 and 3047. Also not very nice: can't be saved by respray or cheat + m_nBombTimer = 1000 + CGeneral::GetRandomNumber() & 0x7FF; + m_pBlowUpEntity = damagedBy; + if (damagedBy) + damagedBy->RegisterReference((CEntity**)&m_pBlowUpEntity); + } + else + BlowUpCar(damagedBy); + } + } +#ifdef FIX_BUGS // removing dumb case when shooting police car in player's own garage gives wanted level + if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && !bHasBeenOwnedByPlayer) +#else + if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed()) +#endif + FindPlayerPed()->SetWantedLevelNoDrop(1); +} + void CVehicle::ExtinguishCarFire(void) { @@ -375,6 +495,65 @@ CVehicle::ExtinguishCarFire(void) } } +bool +CVehicle::ShufflePassengersToMakeSpace(void) +{ + if (m_nNumPassengers >= m_nNumMaxPassengers) + return false; + if (pPassengers[1] && + !(m_nGettingInFlags & CAR_DOOR_FLAG_LR) && + IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_LEFT, nil)) { + if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) { + pPassengers[2] = pPassengers[1]; + pPassengers[1] = nil; + pPassengers[2]->m_vehEnterType = CAR_DOOR_RR; + return true; + } + if (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) { + pPassengers[0] = pPassengers[1]; + pPassengers[1] = nil; + pPassengers[0]->m_vehEnterType = CAR_DOOR_RF; + return true; + } + return false; + } + if (pPassengers[2] && + !(m_nGettingInFlags & CAR_DOOR_FLAG_RR) && + IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_RIGHT, nil)) { + if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { + pPassengers[1] = pPassengers[2]; + pPassengers[2] = nil; + pPassengers[1]->m_vehEnterType = CAR_DOOR_LR; + return true; + } + if (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) { + pPassengers[0] = pPassengers[2]; + pPassengers[2] = nil; + pPassengers[0]->m_vehEnterType = CAR_DOOR_RF; + return true; + } + return false; + } + if (pPassengers[0] && + !(m_nGettingInFlags & CAR_DOOR_FLAG_RF) && + IsRoomForPedToLeaveCar(COMPONENT_DOOR_FRONT_RIGHT, nil)) { + if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { + pPassengers[1] = pPassengers[0]; + pPassengers[0] = nil; + pPassengers[1]->m_vehEnterType = CAR_DOOR_LR; + return true; + } + if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) { + pPassengers[2] = pPassengers[0]; + pPassengers[0] = nil; + pPassengers[2]->m_vehEnterType = CAR_DOOR_RR; + return true; + } + return false; + } + return false; +} + void CVehicle::ProcessDelayedExplosion(void) { @@ -831,4 +1010,5 @@ STARTPATCHES InjectHook(0x551EB0, &CVehicle::RemovePassenger, PATCH_JUMP); InjectHook(0x5525A0, &CVehicle::ProcessCarAlarm, PATCH_JUMP); InjectHook(0x552620, &CVehicle::IsSphereTouchingVehicle, PATCH_JUMP); + InjectHook(0x551950, &CVehicle::InflictDamage, PATCH_JUMP); ENDPATCHES diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 2ca97841..4639f3e1 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -4,6 +4,7 @@ #include "AutoPilot.h" #include "ModelIndices.h" #include "AnimManager.h" +#include "Weapon.h" class CPed; class CFire; @@ -266,7 +267,7 @@ public: void ProcessCarAlarm(void); bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius); bool ShufflePassengersToMakeSpace(void); - void InflictDamage(CEntity *damagedBy, uint32 weaponType, float damage); + void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage); bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 09844c23..0f41264f 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -14,6 +14,7 @@ WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, fl WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); } WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); } WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); } +WRAPPER void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage) { EAXJMP(0x563B00); } void CWeapon::Initialise(eWeaponType type, int ammo) diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 74145564..84760550 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -81,3 +81,5 @@ public: static void UpdateWeapons(void); }; static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); + +void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage); \ No newline at end of file