diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audio/AudioManager.cpp | 6 | ||||
-rw-r--r-- | src/control/Phones.cpp | 201 | ||||
-rw-r--r-- | src/control/Phones.h | 33 | ||||
-rw-r--r-- | src/control/Replay.cpp | 2 | ||||
-rw-r--r-- | src/control/Script.cpp | 6 | ||||
-rw-r--r-- | src/core/Explosion.cpp | 1 | ||||
-rw-r--r-- | src/core/Explosion.h | 1 | ||||
-rw-r--r-- | src/core/Fire.cpp | 21 | ||||
-rw-r--r-- | src/core/Fire.h | 2 | ||||
-rw-r--r-- | src/core/Pad.h | 2 | ||||
-rw-r--r-- | src/core/PlayerInfo.cpp | 245 | ||||
-rw-r--r-- | src/core/PlayerInfo.h | 15 | ||||
-rw-r--r-- | src/core/Radar.cpp | 4 | ||||
-rw-r--r-- | src/core/World.cpp | 48 | ||||
-rw-r--r-- | src/core/World.h | 2 | ||||
-rw-r--r-- | src/peds/CivilianPed.cpp | 31 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 64 | ||||
-rw-r--r-- | src/peds/Ped.h | 3 | ||||
-rw-r--r-- | src/weapons/ProjectileInfo.cpp | 2 | ||||
-rw-r--r-- | src/weapons/ProjectileInfo.h | 1 |
20 files changed, 554 insertions, 136 deletions
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index f823cf19..abfbde00 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -5536,12 +5536,12 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params) if(params->m_fDistance < 49.f) { ped = params->m_pPed; - if(!ped->bIsAimingGun || ped->m_bodyPartBleeding != 2) { + if(!ped->bIsAimingGun || ped->m_bodyPartBleeding != PED_HEAD) { CalculateDistance(params->m_bDistanceCalculated, params->m_fDistance); if(ped->bInVehicle && ped->m_nPedState == PED_DRIVING) { emittingVol = 10; veh = ped->m_pMyVehicle; - if(veh && veh->m_type == 0) { + if(veh && veh->IsCar()) { for(int32 i = 2; i < 6; i++) { if(!veh->IsDoorClosed((eDoors)i) || veh->IsDoorMissing((eDoors)i)) { emittingVol = 42; @@ -6451,7 +6451,7 @@ cAudioManager::ProcessPhysical(int32 id) { CPhysical *entity = (CPhysical *)m_asAudioEntities[id].m_pEntity; if(entity) { - switch(entity->m_type & 7) { + switch(entity->m_type) { case ENTITY_TYPE_VEHICLE: ProcessVehicle((CVehicle *)m_asAudioEntities[id].m_pEntity); break; case ENTITY_TYPE_PED: ProcessPed((CPhysical *)m_asAudioEntities[id].m_pEntity); break; default: return; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index a5c4f74d..f3b3a8db 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -6,16 +6,146 @@ #include "Ped.h" #include "Pad.h" #include "Messages.h" +#include "Camera.h" +#include "World.h" +#include "General.h" +#include "AudioScriptObject.h" +#include "RpAnimBlend.h" CPhoneInfo &gPhoneInfo = *(CPhoneInfo*)0x732A20; -bool &CPhoneInfo::isPhonePickedUp = *(bool*)0x6283AC; -uint32 &CPhoneInfo::phoneMessagesTimer = *(uint32*)0x6283A8; -CPhone *&CPhoneInfo::pickedUpPhone = *(CPhone**)0x6283B0; -bool &CPhoneInfo::isPhoneBeingPickedUp = *(bool*)0x6283B4; -CPed *&CPhoneInfo::pedWhoPickingUpPhone = *(CPed**)0x6283B8; +bool &CPhoneInfo::bDisplayingPhoneMessage = *(bool*)0x6283AC; // is phone picked up +uint32 &CPhoneInfo::PhoneEnableControlsTimer = *(uint32*)0x6283A8; +CPhone *&CPhoneInfo::pPhoneDisplayingMessages = *(CPhone**)0x6283B0; +bool &CPhoneInfo::bPickingUpPhone = *(bool*)0x6283B4; +CPed *&CPhoneInfo::pCallBackPed = *(CPed**)0x6283B8; // ped who picking up the phone (reset after pickup cb) -WRAPPER void CPhoneInfo::Update(void) { EAXJMP(0x42F7A0); } +/* + Entering phonebooth cutscene, showing messages and triggering these things + by checking coordinates happens in here - blue mission marker is cosmetic. + + Repeated message means after the script set the messages for a particular phone, + player can pick the phone again with the same messages appearing, + after 60 seconds of last phone pick-up. +*/ + +#ifdef TOGGLEABLE_BETA_FEATURES +CPed* crimeReporters[NUMPHONES] = {}; +bool +isPhoneAvailable(int m_phoneId) +{ + return gPhoneInfo.m_aPhones[m_phoneId].m_nState == PHONE_STATE_FREE && + (crimeReporters[m_phoneId] == nil || !crimeReporters[m_phoneId]->IsPointerValid() || !crimeReporters[m_phoneId]->bRunningToPhone || crimeReporters[m_phoneId]->m_objective > OBJECTIVE_IDLE || + crimeReporters[m_phoneId]->m_nLastPedState != PED_SEEK_POS && + (crimeReporters[m_phoneId]->m_nPedState != PED_MAKE_CALL && crimeReporters[m_phoneId]->m_nPedState != PED_FACE_PHONE && crimeReporters[m_phoneId]->m_nPedState != PED_SEEK_POS)); +} +#endif + +void +CPhoneInfo::Update(void) +{ + CPlayerPed *player = FindPlayerPed(); + CPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus]; + if (bDisplayingPhoneMessage && CTimer::GetTimeInMilliseconds() > PhoneEnableControlsTimer) { + playerInfo->MakePlayerSafe(false); + TheCamera.SetWideScreenOff(); + pPhoneDisplayingMessages = nil; + bDisplayingPhoneMessage = false; + CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(player->GetClump(), ANIM_PHONE_TALK); + if (talkAssoc && talkAssoc->blendAmount > 0.5f) { + CAnimBlendAssociation *endAssoc = CAnimManager::BlendAnimation(player->GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f); + endAssoc->flags &= ~ASSOC_DELETEFADEDOUT; + endAssoc->SetFinishCallback(PhonePutDownCB, player); + } else { + CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_40; + if (player->m_nPedState == PED_MAKE_CALL) + player->m_nPedState = PED_IDLE; + } + } + bool notInCar; + CVector playerPos; + if (FindPlayerVehicle()) { + notInCar = false; + playerPos = FindPlayerVehicle()->GetPosition(); + } else { + notInCar = true; + playerPos = player->GetPosition(); + } + bool phoneRings = false; + bool scratchTheCabinet; + for(int phoneId = 0; phoneId < m_nScriptPhonesMax; phoneId++) { + if (m_aPhones[phoneId].m_visibleToCam) { + switch (m_aPhones[phoneId].m_nState) { + case PHONE_STATE_ONETIME_MESSAGE_SET: + case PHONE_STATE_REPEATED_MESSAGE_SET: + case PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE: + if (bPickingUpPhone) { + scratchTheCabinet = false; + phoneRings = false; + } else { + scratchTheCabinet = (CTimer::GetTimeInMilliseconds() / 1880) % 2 == 1; + phoneRings = (CTimer::GetPreviousTimeInMilliseconds() / 1880) % 2 == 1; + } + if (scratchTheCabinet) { + m_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f; + if (!phoneRings) + PlayOneShotScriptObject(_SCRSOUND_PHONE_RING, m_aPhones[phoneId].m_pEntity->GetPosition()); + } else { + m_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f; + } + m_aPhones[phoneId].m_pEntity->GetMatrix().UpdateRW(); + m_aPhones[phoneId].m_pEntity->UpdateRwFrame(); + if (notInCar && !bPickingUpPhone && player->IsPedInControl()) { + CVector2D distToPhone = playerPos - m_aPhones[phoneId].m_vecPos; + if (Abs(distToPhone.x) < 1.0f && Abs(distToPhone.y) < 1.0f) { + if (DotProduct2D(distToPhone, m_aPhones[phoneId].m_pEntity->GetForward()) / distToPhone.Magnitude() < -0.85f) { + CVector2D distToPhoneObj = playerPos - m_aPhones[phoneId].m_pEntity->GetPosition(); + float angleToFace = CGeneral::GetATanOfXY(distToPhoneObj.x, distToPhoneObj.y) + HALFPI; + if (angleToFace > TWOPI) + angleToFace = angleToFace - TWOPI; + player->m_fRotationCur = angleToFace; + player->m_fRotationDest = angleToFace; + player->SetHeading(angleToFace); + player->m_nPedState = PED_MAKE_CALL; + CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_40; + TheCamera.SetWideScreenOn(); + playerInfo->MakePlayerSafe(true); + CAnimBlendAssociation *phonePickAssoc = CAnimManager::BlendAnimation(player->GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f); + phonePickAssoc->SetFinishCallback(PhonePickUpCB, &m_aPhones[phoneId]); + bPickingUpPhone = true; + pCallBackPed = player; + } + } + } + break; + case PHONE_STATE_REPEATED_MESSAGE_STARTED: + if (CTimer::GetTimeInMilliseconds() - m_aPhones[phoneId].m_repeatedMessagePickupStart > 60000) + m_aPhones[phoneId].m_nState = PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE; + break; + case PHONE_STATE_9: + scratchTheCabinet = (CTimer::GetTimeInMilliseconds() / 1880) % 2 == 1; + phoneRings = (CTimer::GetPreviousTimeInMilliseconds() / 1880) % 2 == 1; + if (scratchTheCabinet) { + m_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f; + if (!phoneRings) + PlayOneShotScriptObject(_SCRSOUND_PHONE_RING, m_aPhones[phoneId].m_pEntity->GetPosition()); + } else { + m_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f; + } + m_aPhones[phoneId].m_pEntity->GetMatrix().UpdateRW(); + m_aPhones[phoneId].m_pEntity->UpdateRwFrame(); + break; + default: + break; + } + if (CVector2D(TheCamera.GetPosition() - m_aPhones[phoneId].m_vecPos).MagnitudeSqr() > sq(100.0f)) + m_aPhones[phoneId].m_visibleToCam = false; + } else if (!((CTimer::GetFrameCounter() + m_aPhones[phoneId].m_pEntity->m_randomSeed) % 16)) { + if (CVector2D(TheCamera.GetPosition() - m_aPhones[phoneId].m_vecPos).MagnitudeSqr() < sq(60.0f)) + m_aPhones[phoneId].m_visibleToCam = true; + } + } +} int CPhoneInfo::FindNearestFreePhone(CVector *pos) @@ -25,7 +155,11 @@ CPhoneInfo::FindNearestFreePhone(CVector *pos) for (int phoneId = 0; phoneId < m_nMax; phoneId++) { - if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE) { + if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE +#ifdef TOGGLEABLE_BETA_FEATURES + && isPhoneAvailable(phoneId) +#endif + ) { float phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D(); if (phoneDist < nearestPhoneDist) { @@ -50,20 +184,20 @@ CPhoneInfo::PhoneAtThisPosition(CVector pos) bool CPhoneInfo::HasMessageBeenDisplayed(int phoneId) { - if (isPhonePickedUp) + if (bDisplayingPhoneMessage) return false; int state = m_aPhones[phoneId].m_nState; return state == PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE || - state == PHONE_STATE_ONETIME_MESSAGE_SHOWN || - state == PHONE_STATE_REPEATED_MESSAGE_SHOWN; + state == PHONE_STATE_ONETIME_MESSAGE_STARTED || + state == PHONE_STATE_REPEATED_MESSAGE_STARTED; } bool CPhoneInfo::IsMessageBeingDisplayed(int phoneId) { - return pickedUpPhone == &m_aPhones[phoneId]; + return pPhoneDisplayingMessages == &m_aPhones[phoneId]; } void @@ -71,7 +205,7 @@ CPhoneInfo::Load(uint8 *buf, uint32 size) { INITSAVEBUF m_nMax = ReadSaveBuf<int32>(buf); - m_nNum = ReadSaveBuf<int32>(buf); + m_nScriptPhonesMax = ReadSaveBuf<int32>(buf); for (int i = 0; i < NUMPHONES; i++) { m_aPhones[i] = ReadSaveBuf<CPhone>(buf); // It's saved as building pool index in save file, convert it to true entity @@ -127,7 +261,7 @@ CPhoneInfo::GrabPhone(float xPos, float yPos) CVector pos(xPos, yPos, 0.0f); float nearestPhoneDist = 100.0f; - for (int phoneId = m_nNum; phoneId < m_nMax; phoneId++) { + for (int phoneId = m_nScriptPhonesMax; phoneId < m_nMax; phoneId++) { float phoneDistance = (m_aPhones[phoneId].m_vecPos - pos).Magnitude2D(); if (phoneDistance < nearestPhoneDist) { nearestPhoneDist = phoneDistance; @@ -136,23 +270,23 @@ CPhoneInfo::GrabPhone(float xPos, float yPos) } m_aPhones[nearestPhoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED; - CPhone oldFirstPhone = m_aPhones[m_nNum]; - m_aPhones[m_nNum] = m_aPhones[nearestPhoneId]; + CPhone oldFirstPhone = m_aPhones[m_nScriptPhonesMax]; + m_aPhones[m_nScriptPhonesMax] = m_aPhones[nearestPhoneId]; m_aPhones[nearestPhoneId] = oldFirstPhone; - m_nNum++; - return m_nNum - 1; + m_nScriptPhonesMax++; + return m_nScriptPhonesMax - 1; } void CPhoneInfo::Initialise(void) { CBuildingPool *pool = CPools::GetBuildingPool(); - pedWhoPickingUpPhone = nil; - isPhonePickedUp = false; - isPhoneBeingPickedUp = false; - pickedUpPhone = nil; + pCallBackPed = nil; + bDisplayingPhoneMessage = false; + bPickingUpPhone = false; + pPhoneDisplayingMessages = nil; m_nMax = 0; - m_nNum = 0; + m_nScriptPhonesMax = 0; for (int i = pool->GetSize() - 1; i >= 0; i--) { CBuilding *building = pool->GetSlot(i); if (building) { @@ -173,7 +307,7 @@ CPhoneInfo::Save(uint8 *buf, uint32 *size) *size = sizeof(CPhoneInfo); INITSAVEBUF WriteSaveBuf(buf, m_nMax); - WriteSaveBuf(buf, m_nNum); + WriteSaveBuf(buf, m_nScriptPhonesMax); for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) { CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]); @@ -189,7 +323,7 @@ void CPhoneInfo::Shutdown(void) { m_nMax = 0; - m_nNum = 0; + m_nScriptPhonesMax = 0; } void @@ -221,26 +355,26 @@ PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) } } - CPhoneInfo::isPhoneBeingPickedUp = false; - CPhoneInfo::isPhonePickedUp = true; - CPhoneInfo::pickedUpPhone = phone; - CPhoneInfo::phoneMessagesTimer = CTimer::GetTimeInMilliseconds() + messagesDisplayTime; + CPhoneInfo::bPickingUpPhone = false; + CPhoneInfo::bDisplayingPhoneMessage = true; + CPhoneInfo::pPhoneDisplayingMessages = phone; + CPhoneInfo::PhoneEnableControlsTimer = CTimer::GetTimeInMilliseconds() + messagesDisplayTime; if (phone->m_nState == PHONE_STATE_ONETIME_MESSAGE_SET) { - phone->m_nState = PHONE_STATE_ONETIME_MESSAGE_SHOWN; + phone->m_nState = PHONE_STATE_ONETIME_MESSAGE_STARTED; } else { - phone->m_nState = PHONE_STATE_REPEATED_MESSAGE_SHOWN; - phone->m_lastTimeRepeatedMsgShown = CTimer::GetTimeInMilliseconds(); + phone->m_nState = PHONE_STATE_REPEATED_MESSAGE_STARTED; + phone->m_repeatedMessagePickupStart = CTimer::GetTimeInMilliseconds(); } - CPed *ped = CPhoneInfo::pedWhoPickingUpPhone; + CPed *ped = CPhoneInfo::pCallBackPed; ped->m_nMoveState = PEDMOVE_STILL; CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f); if (assoc->blendAmount > 0.5f && ped) CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f); - CPhoneInfo::pedWhoPickingUpPhone = nil; + CPhoneInfo::pCallBackPed = nil; } STARTPATCHES @@ -255,6 +389,7 @@ STARTPATCHES InjectHook(0x42F710, &CPhoneInfo::Shutdown, PATCH_JUMP); InjectHook(0x42F640, &CPhoneInfo::Initialise, PATCH_JUMP); InjectHook(0x42FDB0, &CPhoneInfo::GrabPhone, PATCH_JUMP); + InjectHook(0x42F7A0, &CPhoneInfo::Update, PATCH_JUMP); InjectHook(0x42F570, &PhonePutDownCB, PATCH_JUMP); InjectHook(0x42F470, &PhonePickUpCB, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/control/Phones.h b/src/control/Phones.h index 62ea6f50..e7e3c9a7 100644 --- a/src/control/Phones.h +++ b/src/control/Phones.h @@ -5,7 +5,7 @@ class CPed; class CAnimBlendAssociation; -enum { +enum PhoneState { PHONE_STATE_FREE, PHONE_STATE_REPORTING_CRIME, // CCivilianPed::ProcessControl sets it but unused PHONE_STATE_2, @@ -13,9 +13,9 @@ enum { PHONE_STATE_ONETIME_MESSAGE_SET, PHONE_STATE_REPEATED_MESSAGE_SET, PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE, - PHONE_STATE_ONETIME_MESSAGE_SHOWN, - PHONE_STATE_REPEATED_MESSAGE_SHOWN, - PHONE_STATE_9 + PHONE_STATE_ONETIME_MESSAGE_STARTED, + PHONE_STATE_REPEATED_MESSAGE_STARTED, + PHONE_STATE_9 // just rings, picking being handled via script. most of the time game uses this }; class CPhone @@ -23,10 +23,10 @@ class CPhone public: CVector m_vecPos; wchar *m_apMessages[6]; - uint32 m_lastTimeRepeatedMsgShown; + uint32 m_repeatedMessagePickupStart; CEntity *m_pEntity; // stored as building pool index in save files - int32 m_nState; - uint8 field_30; + PhoneState m_nState; + bool m_visibleToCam; CPhone() { } ~CPhone() { } @@ -36,14 +36,14 @@ static_assert(sizeof(CPhone) == 0x34, "CPhone: error"); class CPhoneInfo { public: - static bool &isPhonePickedUp; - static uint32 &phoneMessagesTimer; - static CPhone *&pickedUpPhone; - static bool &isPhoneBeingPickedUp; - static CPed *&pedWhoPickingUpPhone; + static bool &bDisplayingPhoneMessage; + static uint32 &PhoneEnableControlsTimer; + static CPhone *&pPhoneDisplayingMessages; + static bool &bPickingUpPhone; + static CPed *&pCallBackPed; int32 m_nMax; - int32 m_nNum; + int32 m_nScriptPhonesMax; CPhone m_aPhones[NUMPHONES]; CPhoneInfo() { } @@ -66,4 +66,9 @@ public: extern CPhoneInfo &gPhoneInfo; void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg); -void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg);
\ No newline at end of file +void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); + +#ifdef TOGGLEABLE_BETA_FEATURES +extern CPed *crimeReporters[NUMPHONES]; +bool isPhoneAvailable(int); +#endif
\ No newline at end of file diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 1bd1bf4b..ea305778 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -346,7 +346,7 @@ void CReplay::StorePedUpdate(CPed *ped, int id) pp->matrix.CompressFromFullMatrix(ped->GetMatrix()); pp->assoc_group_id = ped->m_animGroup; /* Would be more sane to use GetJustIndex(ped->m_pMyVehicle) in following assignment */ - if (ped->bInVehicle && ped->m_pMyVehicle) + if (ped->InVehicle()) pp->vehicle_index = (CPools::GetVehiclePool()->GetIndex(ped->m_pMyVehicle) >> 8) + 1; else pp->vehicle_index = 0; diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 2e3d287a..15cf798b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -1734,7 +1734,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) CollectParameters(&m_nIp, 1); CPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]); if (ped) { - if (ped->bInVehicle && ped->m_pMyVehicle) { + if (ped->InVehicle()) { if (ped->m_pMyVehicle->pDriver == ped) { ped->m_pMyVehicle->RemoveDriver(); ped->m_pMyVehicle->m_status = STATUS_ABANDONED; @@ -4947,7 +4947,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command) assert(pPed); CObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]); bool isTouching = false; - if (pPed->bInVehicle && pPed->m_pMyVehicle) + if (pPed->InVehicle()) isTouching = false; else if (pPed->GetHasCollidedWith(pObject)) isTouching = true; @@ -5090,7 +5090,7 @@ int8 CRunningScript::ProcessCommandsFrom500To599(int32 command) case COMMAND_HAS_PHONE_DISPLAYED_MESSAGE: { CollectParameters(&m_nIp, 1); - gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0]); + UpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0])); return 0; } case COMMAND_TURN_PHONE_OFF: diff --git a/src/core/Explosion.cpp b/src/core/Explosion.cpp index 9ccd6e81..30809dc9 100644 --- a/src/core/Explosion.cpp +++ b/src/core/Explosion.cpp @@ -3,6 +3,7 @@ #include "Explosion.h" WRAPPER void CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32) { EAXJMP(0x5591C0); } +WRAPPER void CExplosion::RemoveAllExplosionsInArea(CVector, float) { EAXJMP(0x55AD40); } WRAPPER int8 CExplosion::GetExplosionActiveCounter(uint8 id) diff --git a/src/core/Explosion.h b/src/core/Explosion.h index fde4ad7f..0768bbe4 100644 --- a/src/core/Explosion.h +++ b/src/core/Explosion.h @@ -27,4 +27,5 @@ public: static CVector *GetExplosionPosition(uint8 id); static uint8 GetExplosionType(uint8 id); static void ResetExplosionActiveCounter(uint8 id); + static void RemoveAllExplosionsInArea(CVector, float); }; diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp index 0317ccbe..7657d8e9 100644 --- a/src/core/Fire.cpp +++ b/src/core/Fire.cpp @@ -5,6 +5,9 @@ CFireManager &gFireManager = *(CFireManager*)0x8F31D0; WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); } +WRAPPER void CFireManager::StartFire(CEntity* entityOnFire, CEntity* culprit, float, uint32) { EAXJMP(0x479590); } +WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); } +WRAPPER CFire* CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); } CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance) { @@ -31,6 +34,18 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance) return nil; } -WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); } -WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); } -WRAPPER CFire *CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); } +void +CFireManager::ExtinguishPoint(CVector point, float range) +{ + for (int i = 0; i < NUM_FIRES; i++) { + if (m_aFires[i].m_bIsOngoing) { + if ((point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range)) + m_aFires[i].Extinguish(); + } + } +} + +STARTPATCHES + InjectHook(0x479DB0, &CFireManager::ExtinguishPoint, PATCH_JUMP); + InjectHook(0x479340, &CFireManager::FindNearestFire, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/core/Fire.h b/src/core/Fire.h index c752b2a6..e0ad7cdf 100644 --- a/src/core/Fire.h +++ b/src/core/Fire.h @@ -34,6 +34,8 @@ public: void Update(void); CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float); CFire *FindNearestFire(CVector, float*); + void ExtinguishPoint(CVector, float); + uint32 GetTotalActiveFires() const { return m_nTotalFires; } }; extern CFireManager &gFireManager; diff --git a/src/core/Pad.h b/src/core/Pad.h index eadbd299..03b734cb 100644 --- a/src/core/Pad.h +++ b/src/core/Pad.h @@ -7,7 +7,7 @@ enum { PLAYERCONTROL_DISABLED_4 = 4, PLAYERCONTROL_DISABLED_8 = 8, PLAYERCONTROL_DISABLED_10 = 16, - PLAYERCONTROL_DISABLED_20 = 32, + PLAYERCONTROL_DISABLED_20 = 32, // used on CPlayerInfo::MakePlayerSafe PLAYERCONTROL_DISABLED_40 = 64, // used on phone calls PLAYERCONTROL_DISABLED_80 = 128, }; diff --git a/src/core/PlayerInfo.cpp b/src/core/PlayerInfo.cpp index f0b7d444..85682ae3 100644 --- a/src/core/PlayerInfo.cpp +++ b/src/core/PlayerInfo.cpp @@ -3,15 +3,24 @@ #include "PlayerPed.h" #include "PlayerInfo.h" #include "Frontend.h" -#include "Vehicle.h" #include "PlayerSkin.h" #include "Darkel.h" #include "Messages.h" #include "Text.h" #include "Stats.h" +#include "Remote.h" +#include "World.h" +#include "Replay.h" +#include "Pad.h" +#include "ProjectileInfo.h" +#include "Explosion.h" +#include "Script.h" +#include "Vehicle.h" +#include "HandlingMgr.h" +#include "General.h" +#include "main.h" +#include "SpecialFX.h" -WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); } -WRAPPER void CPlayerInfo::AwardMoneyForExplosion(CVehicle *vehicle) { EAXJMP(0x4A15F0); } WRAPPER void CPlayerInfo::Process(void) { EAXJMP(0x49FD30); } void @@ -24,7 +33,7 @@ CPlayerInfo::SetPlayerSkin(char *skin) CVector& CPlayerInfo::GetPos() { - if (m_pPed->bInVehicle && m_pPed->m_pMyVehicle) + if (m_pPed->InVehicle()) return m_pPed->m_pMyVehicle->GetPosition(); return m_pPed->GetPosition(); } @@ -44,7 +53,7 @@ CPlayerInfo::DeletePlayerSkin() {
if (m_pSkinTexture) {
RwTextureDestroy(m_pSkinTexture);
- m_pSkinTexture = NULL;
+ m_pSkinTexture = nil;
} } @@ -88,9 +97,227 @@ CPlayerInfo::PlayerFailedCriticalMission() CDarkel::ResetOnPlayerDeath(); } +void
+CPlayerInfo::Clear(void)
+{
+ m_pPed = nil;
+ m_pRemoteVehicle = nil;
+ if (m_pVehicleEx) {
+ m_pVehicleEx->bUsingSpecialColModel = false;
+ m_pVehicleEx = nil;
+ }
+ m_nVisibleMoney = 0;
+ m_nMoney = m_nVisibleMoney;
+ m_WBState = WBSTATE_PLAYING;
+ m_nWBTime = 0;
+ m_nTrafficMultiplier = 0;
+ m_fRoadDensity = 1.0f;
+ m_bInRemoteMode = false;
+ m_bSwitchTaxi = false;
+ m_nSwitchTaxiTime = 0;
+ m_nCollectedPackages = 0;
+ m_nTotalPackages = 3;
+ m_nTimeLastHealthLoss = 0;
+ m_nTimeLastArmourLoss = 0;
+ m_nNextSexFrequencyUpdateTime = 0;
+ m_nNextSexMoneyUpdateTime = 0;
+ m_nSexFrequency = 0;
+ m_pHooker = nil;
+ m_nTimeTankShotGun = 0;
+ field_248 = 0;
+ m_nUpsideDownCounter = 0;
+ m_bInfiniteSprint = false;
+ m_bFastReload = false;
+ m_bGetOutOfJailFree = false;
+ m_bGetOutOfHospitalFree = false;
+ m_nPreviousTimeRewardedForExplosion = 0;
+ m_nExplosionsSinceLastReward = 0;
+} + +void
+CPlayerInfo::BlowUpRCBuggy(void)
+{
+ if (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)
+ return;
+
+ CRemote::TakeRemoteControlledCarFromPlayer();
+ m_pRemoteVehicle->BlowUpCar(FindPlayerPed());
+} +
+void
+CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
+{
+ if (!car || car == m_pPed->m_pMyVehicle) {
+ if (m_pPed->m_nPedState == PED_CARJACK || m_pPed->m_nPedState == PED_ENTER_CAR)
+ m_pPed->QuitEnteringCar();
+ }
+ if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
+ m_pPed->ClearObjective();
+} + +void
+CPlayerInfo::MakePlayerSafe(bool toggle)
+{
+ if (toggle) {
+ CTheScripts::CountdownToMakePlayerUnsafe = 0;
+ m_pPed->m_pWanted->m_bIgnoredByEveryone = true;
+ CWorld::StopAllLawEnforcersInTheirTracks();
+ CPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_DISABLED_20;
+ CPad::StopPadsShaking();
+ m_pPed->bBulletProof = true;
+ m_pPed->bFireProof = true;
+ m_pPed->bCollisionProof = true;
+ m_pPed->bMeleeProof = true;
+ m_pPed->bOnlyDamagedByPlayer = true;
+ m_pPed->bExplosionProof = true;
+ m_pPed->m_bCanBeDamaged = false;
+ ((CPlayerPed*)m_pPed)->ClearAdrenaline();
+ CancelPlayerEnteringCars(false);
+ gFireManager.ExtinguishPoint(GetPos(), 4000.0f);
+ CExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);
+ CProjectileInfo::RemoveAllProjectiles();
+ CWorld::SetAllCarsCanBeDamaged(false);
+ CWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);
+ CReplay::DisableReplays();
+
+ } else if (!CGame::playingIntro && !CTheScripts::CountdownToMakePlayerUnsafe) {
+ m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
+ CPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_DISABLED_20;
+ m_pPed->bBulletProof = false;
+ m_pPed->bFireProof = false;
+ m_pPed->bCollisionProof = false;
+ m_pPed->bMeleeProof = false;
+ m_pPed->bOnlyDamagedByPlayer = false;
+ m_pPed->bExplosionProof = false;
+ m_pPed->m_bCanBeDamaged = true;
+ CWorld::SetAllCarsCanBeDamaged(true);
+ CReplay::EnableReplays();
+ }
+} + +bool +CPlayerInfo::IsRestartingAfterDeath() +{ + return m_WBState == WBSTATE_WASTED; +} + +bool +CPlayerInfo::IsRestartingAfterArrest() +{ + return m_WBState == WBSTATE_BUSTED; +} + +// lastClosestness is passed to other calls of this function +void
+CPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastClosestness, CVehicle **closestCarOutput)
+{
+ // This dist used for determining the angle to face
+ CVector2D dist(carToTest->GetPosition() - player->GetPosition());
+ float neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);
+ while (neededTurn >= PI) {
+ neededTurn -= 2 * PI;
+ }
+
+ while (neededTurn < -PI) {
+ neededTurn += 2 * PI;
+ }
+
+ // This dist used for evaluating cars' distances, weird...
+ // Accounts inverted needed turn (or needed turn in long way) and car dist.
+ float closestness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);
+ if (closestness > *lastClosestness) {
+ *lastClosestness = closestness;
+ *closestCarOutput = (CVehicle*)carToTest;
+ }
+} + +// There is something unfinished in here... Sadly all IDBs we have have it unfinished. +void
+CPlayerInfo::AwardMoneyForExplosion(CVehicle *wreckedCar)
+{
+ if (CTimer::GetTimeInMilliseconds() - m_nPreviousTimeRewardedForExplosion < 6000)
+ ++m_nExplosionsSinceLastReward;
+ else
+ m_nExplosionsSinceLastReward = 1;
+
+ m_nPreviousTimeRewardedForExplosion = CTimer::GetTimeInMilliseconds();
+ int award = wreckedCar->pHandling->nMonetaryValue * 0.002f;
+ sprintf(gString, "$%d", award);
+#ifdef MONEY_MESSAGES
+ // This line is a leftover from PS2, I don't know what it was meant to be.
+ // CVector sth(TheCamera.GetPosition() * 4.0f);
+
+ CMoneyMessages::RegisterOne(wreckedCar->GetPosition() + CVector(0.0f, 0.0f, 2.0f), gString, 0, 255, 0, 2.0f, 0.5f);
+#endif
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
+
+ for (int i = m_nExplosionsSinceLastReward; i > 1; --i) {
+ CGeneral::GetRandomNumber();
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += award;
+ }
+} + +void
+CPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)
+{
+ // Interesting
+ *size = sizeof(CPlayerInfo);
+
+INITSAVEBUF
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);
+ for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
+ WriteSaveBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i]);
+ }
+// Save struct is different
+// VALIDATESAVEBUF(*size)
+} + +void
+CPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)
+{
+INITSAVEBUF
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = ReadSaveBuf<uint32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf<int8>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf<uint32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf<int16>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf<float>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf<int32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf<int32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf<int32>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf<bool>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf<bool>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf<bool>(buf);
+ CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf<bool>(buf);
+ for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) {
+ CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf<char>(buf);
+ }
+// Save struct is different
+// VALIDATESAVEBUF(size)
+} + STARTPATCHES -InjectHook(0x4A1700, &CPlayerInfo::LoadPlayerSkin, PATCH_JUMP); -InjectHook(0x4A1750, &CPlayerInfo::DeletePlayerSkin, PATCH_JUMP); -InjectHook(0x4A12E0, &CPlayerInfo::KillPlayer, PATCH_JUMP); -InjectHook(0x4A1330, &CPlayerInfo::ArrestPlayer, PATCH_JUMP); + InjectHook(0x4B5DC0, &CPlayerInfo::dtor, PATCH_JUMP); + InjectHook(0x4A1700, &CPlayerInfo::LoadPlayerSkin, PATCH_JUMP); + InjectHook(0x4A1750, &CPlayerInfo::DeletePlayerSkin, PATCH_JUMP); + InjectHook(0x4A12E0, &CPlayerInfo::KillPlayer, PATCH_JUMP); + InjectHook(0x4A1330, &CPlayerInfo::ArrestPlayer, PATCH_JUMP); + InjectHook(0x49FC10, &CPlayerInfo::Clear, PATCH_JUMP); + InjectHook(0x4A15C0, &CPlayerInfo::BlowUpRCBuggy, PATCH_JUMP); + InjectHook(0x4A13B0, &CPlayerInfo::CancelPlayerEnteringCars, PATCH_JUMP); + InjectHook(0x4A1400, &CPlayerInfo::MakePlayerSafe, PATCH_JUMP); + InjectHook(0x4A0EC0, &CPlayerInfo::EvaluateCarPosition, PATCH_JUMP); + InjectHook(0x4A15F0, &CPlayerInfo::AwardMoneyForExplosion, PATCH_JUMP); + InjectHook(0x4A0B20, &CPlayerInfo::LoadPlayerInfo, PATCH_JUMP); + InjectHook(0x4A0960, &CPlayerInfo::SavePlayerInfo, PATCH_JUMP); ENDPATCHES diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 12c71766..28881796 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -10,6 +10,8 @@ enum eWastedBustedState WBSTATE_FAILED_CRITICAL_MISSION, }; +class CEntity; +class CPed; class CVehicle; class CPlayerPed; class CCivilianPed; @@ -40,7 +42,7 @@ public: int8 field_217; int8 field_218; int8 field_219; - int32 m_nWBTime; + uint32 m_nWBTime; bool m_bInRemoteMode; int8 field_225; int8 field_226; @@ -77,6 +79,17 @@ public: void ArrestPlayer(void); bool IsPlayerInRemoteMode(void); void PlayerFailedCriticalMission(void); + void Clear(void); + void BlowUpRCBuggy(void); + void CancelPlayerEnteringCars(CVehicle*); + bool IsRestartingAfterDeath(void); + bool IsRestartingAfterArrest(void); + void EvaluateCarPosition(CEntity*, CPed*, float, float*, CVehicle**); + void LoadPlayerInfo(uint8 *buf, uint32 size); + void SavePlayerInfo(uint8 *buf, uint32* size); + + ~CPlayerInfo() { }; + void dtor(void) { this->CPlayerInfo::~CPlayerInfo(); } }; static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); diff --git a/src/core/Radar.cpp b/src/core/Radar.cpp index f06e5317..ab7de13e 100644 --- a/src/core/Radar.cpp +++ b/src/core/Radar.cpp @@ -312,7 +312,7 @@ void CRadar::DrawBlips() break; case BLIP_CHAR: blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - if (blipEntity && ((CPed*)blipEntity)->bInVehicle && ((CPed*)blipEntity)->m_pMyVehicle) { + if (blipEntity && ((CPed*)blipEntity)->InVehicle()) { blipEntity = ((CPed*)blipEntity)->m_pMyVehicle; } break; @@ -415,7 +415,7 @@ void CRadar::DrawBlips() break; case BLIP_CHAR: blipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle); - if (blipEntity && ((CPed*)blipEntity)->bInVehicle && ((CPed*)blipEntity)->m_pMyVehicle) { + if (blipEntity && ((CPed*)blipEntity)->InVehicle()) { blipEntity = ((CPed*)blipEntity)->m_pMyVehicle; } break; diff --git a/src/core/World.cpp b/src/core/World.cpp index ae0d67cc..dac64970 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -859,8 +859,8 @@ FindPlayerPed(void) CVehicle* FindPlayerVehicle(void) { - CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - if(ped->bInVehicle && ped->m_pMyVehicle) + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) return ped->m_pMyVehicle; else return nil; @@ -878,8 +878,8 @@ FindPlayerTrain(void) CEntity* FindPlayerEntity(void) { - CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - if(ped->bInVehicle && ped->m_pMyVehicle) + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) return ped->m_pMyVehicle; else return ped; @@ -888,8 +888,8 @@ FindPlayerEntity(void) CVector FindPlayerCoors(void) { - CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - if(ped->bInVehicle && ped->m_pMyVehicle) + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) return ped->m_pMyVehicle->GetPosition(); else return ped->GetPosition(); @@ -898,8 +898,8 @@ FindPlayerCoors(void) CVector& FindPlayerSpeed(void) { - CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed; - if(ped->bInVehicle && ped->m_pMyVehicle) + CPlayerPed *ped = FindPlayerPed(); + if(ped->InVehicle()) return ped->m_pMyVehicle->m_vecMoveSpeed; else return ped->m_vecMoveSpeed; @@ -926,7 +926,7 @@ FindPlayerCentreOfWorld_NoSniperShift(void) return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition(); if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition(); - return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition(); + return FindPlayerPed()->GetPosition(); } float @@ -936,7 +936,7 @@ FindPlayerHeading(void) return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading(); if(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading(); - return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetForward().Heading(); + return FindPlayerPed()->GetForward().Heading(); } void @@ -1012,6 +1012,30 @@ CWorld::StopAllLawEnforcersInTheirTracks(void) } void +CWorld::SetAllCarsCanBeDamaged(bool toggle) +{ + int poolSize = CPools::GetVehiclePool()->GetSize(); + for (int poolIndex = 0; poolIndex < poolSize; poolIndex++) { + CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if (veh) + veh->bCanBeDamaged = toggle; + } +} + +void +CWorld::ExtinguishAllCarFiresInArea(CVector point, float range) +{ + int poolSize = CPools::GetVehiclePool()->GetSize(); + for (int poolIndex = 0; poolIndex < poolSize; poolIndex++) { + CVehicle* veh = CPools::GetVehiclePool()->GetSlot(poolIndex); + if (veh) { + if ((point - veh->GetPosition()).MagnitudeSqr() < sq(range)) + veh->ExtinguishCarFire(); + } + } +} + +void CWorld::Process(void) { if (!(CTimer::GetFrameCounter() & 63)) @@ -1212,5 +1236,9 @@ STARTPATCHES InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP); InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP); + InjectHook(0x4B5BC0, CWorld::StopAllLawEnforcersInTheirTracks, PATCH_JUMP); + InjectHook(0x4B53F0, CWorld::SetAllCarsCanBeDamaged, PATCH_JUMP); + InjectHook(0x4B5460, CWorld::ExtinguishAllCarFiresInArea, PATCH_JUMP); + InjectHook(0x4B1A60, CWorld::Process, PATCH_JUMP); ENDPATCHES diff --git a/src/core/World.h b/src/core/World.h index 3b04403e..119c6324 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -121,6 +121,8 @@ public: static void RemoveFallenCars(); static void StopAllLawEnforcersInTheirTracks(); + static void SetAllCarsCanBeDamaged(bool); + static void ExtinguishAllCarFiresInArea(CVector, float); static void Initialise(); static void ShutDown(); diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 34a0a35f..6fce25e8 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -19,15 +19,6 @@ CCivilianPed::CCivilianPed(int pedtype, int mi) : CPed(pedtype) void CCivilianPed::CivilianAI(void) { -#ifdef TOGGLEABLE_BETA_FEATURES - if (bRunningToPhone && m_nPedState != PED_SEEK_POS && m_nPedState != PED_FALL && m_nPedState != PED_GETUP && - m_nPedState != PED_DIVE_AWAY && m_nPedState != PED_MAKE_CALL && m_nPedState != PED_FACE_PHONE) { - bRunningToPhone = false; - if (gPhoneInfo.m_aPhones[m_phoneId].m_nState == PHONE_STATE_REPORTING_CRIME) - gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; - } -#endif - if (CTimer::GetTimeInMilliseconds() <= m_fleeTimer || m_objective != OBJECTIVE_NONE && !bRespondsToThreats || !IsPedInControl()) { @@ -248,17 +239,27 @@ CCivilianPed::ProcessControl(void) if (Seek()) { if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) && m_pNextPathNode) { m_pNextPathNode = nil; +#ifdef TOGGLEABLE_BETA_FEATURES + } else if (bRunningToPhone && m_objective < OBJECTIVE_FLEE_TILL_SAFE) { + if (!isPhoneAvailable(m_phoneId)) { + RestorePreviousState(); + crimeReporters[m_phoneId] = nil; + m_phoneId = -1; + bRunningToPhone = false; + } else { + crimeReporters[m_phoneId] = this; + m_nPedState = PED_FACE_PHONE; + } +#else } else if (bRunningToPhone) { if (gPhoneInfo.m_aPhones[m_phoneId].m_nState != PHONE_STATE_FREE) { RestorePreviousState(); m_phoneId = -1; -#ifdef FIX_BUGS - bRunningToPhone = false; -#endif } else { gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_REPORTING_CRIME; m_nPedState = PED_FACE_PHONE; } +#endif } else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) { if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION) { if (m_moved.Magnitude() == 0.0f) { @@ -275,12 +276,6 @@ CCivilianPed::ProcessControl(void) } } } -#ifdef TOGGLEABLE_BETA_FEATURES - else if (bRunningToPhone) { - // Designed for running to phone, but never used - CheckAroundForPossibleCollisions(); - } -#endif break; case PED_FACE_PHONE: if (FacePhone()) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 0f304c38..ee4a5f7c 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -337,7 +337,7 @@ CPed::~CPed(void) { CWorld::Remove(this); CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); - if (bInVehicle && m_pMyVehicle){ + if (InVehicle()){ uint8 door_flag = GetCarDoorFlag(m_vehEnterType); if (m_pMyVehicle->pDriver == this) m_pMyVehicle->pDriver = nil; @@ -362,7 +362,7 @@ void CPed::FlagToDestroyWhenNextProcessed(void) { bRemoveFromWorld = true; - if (!bInVehicle || !m_pMyVehicle) + if (!InVehicle()) return; if (m_pMyVehicle->pDriver == this){ m_pMyVehicle->pDriver = nil; @@ -2397,7 +2397,7 @@ CPed::CalculateNewVelocity(void) bool CPed::CanBeDeleted(void) { - if (this->bInVehicle) + if (bInVehicle) return false; switch (CharCreatedBy) { @@ -2993,7 +2993,7 @@ CPed::ReactToAttack(CEntity *attacker) } #ifdef VC_PED_PORTS - if (m_nPedState == PED_DRIVING && bInVehicle && m_pMyVehicle + if (m_nPedState == PED_DRIVING && InVehicle() && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING)) { if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE @@ -3187,6 +3187,9 @@ CPed::MakePhonecall(void) SetIdle(); gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; +#ifdef TOGGLEABLE_BETA_FEATURES + crimeReporters[m_phoneId] = nil; +#endif m_phoneId = -1; return true; } @@ -4297,7 +4300,7 @@ CPed::RestorePreviousState(void) if (m_nPedState == PED_GETUP && !bGetUpAnimStarted) return; - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { m_nPedState = PED_DRIVING; m_nLastPedState = PED_NONE; } else { @@ -5908,13 +5911,6 @@ CPed::SetDead(void) if (m_nPedState == PED_DRIVING) bIsVisible = false; -#ifdef TOGGLEABLE_BETA_FEATURES - if (bRunningToPhone) { - if (gPhoneInfo.m_aPhones[m_phoneId].m_nState == PHONE_STATE_REPORTING_CRIME) - gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE; - } -#endif - m_nPedState = PED_DEAD; m_pVehicleAnim = nil; m_pCollidingEntity = nil; @@ -10384,8 +10380,8 @@ CPed::ProcessControl(void) if (pad->GetHorn()) { float c = Cos(m_fRotationCur); float s = Sin(m_fRotationCur); - m_pMyVehicle->GetRight() = CVector(c, 0.0f, 0.0f); - m_pMyVehicle->GetForward() = CVector(0.0f, s, 0.0f); + m_pMyVehicle->GetRight() = CVector(1.0f, 0.0f, 0.0f); + m_pMyVehicle->GetForward() = CVector(0.0f, 1.0f, 0.0f); m_pMyVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); if (pad->GetAccelerate()) { m_pMyVehicle->ApplyMoveForce(GetForward() * 30.0f); @@ -11682,15 +11678,14 @@ CPed::RunToReportCrime(eCrimeType crimeToReport) if (phoneId == -1) return false; - if (gPhoneInfo.m_aPhones[phoneId].m_nState != PHONE_STATE_FREE) + CPhone *phone = &gPhoneInfo.m_aPhones[phoneId]; + if (phone->m_nState != PHONE_STATE_FREE) return false; bRunningToPhone = true; - SetSeek(gPhoneInfo.m_aPhones[phoneId].m_vecPos, 0.7f); // original: 0.35f + SetSeek(phone->m_pEntity->GetPosition() - phone->m_pEntity->GetForward(), 1.3f); // original: phone.m_vecPos, 0.3f SetMoveState(PEDMOVE_RUN); -#ifdef FIX_BUGS - bIsRunning = true; -#endif + bIsRunning = true; // not there in original m_phoneId = phoneId; m_crimeToReportOnPhone = crimeToReport; return true; @@ -12404,11 +12399,8 @@ CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh) void CPed::Render(void) { - if (!bInVehicle - || m_nPedState == PED_EXIT_CAR - || m_nPedState == PED_DRAG_FROM_CAR - || bRenderPedInCar && - sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) { + if (!bInVehicle || m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR || + bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) { CEntity::Render(); } } @@ -12438,7 +12430,7 @@ CPed::ProcessObjective(void) } if (m_pedInObjective) { - if (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR && m_pedInObjective->m_pMyVehicle) { + if (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) { targetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition(); } else { targetCarOrHisPos = m_pedInObjective->GetPosition(); @@ -12465,7 +12457,7 @@ CPed::ProcessObjective(void) SetMoveState(PEDMOVE_STILL); break; case OBJECTIVE_FLEE_TILL_SAFE: - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); bFleeAfterExitingCar = true; } else if (m_nPedState != PED_FLEE_POS) { @@ -12521,7 +12513,7 @@ CPed::ProcessObjective(void) SetObjective(OBJECTIVE_FLEE_TILL_SAFE); break; } - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { if (distWithTarget.Magnitude() >= 20.0f || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) { if (m_pMyVehicle->pDriver == this @@ -12619,7 +12611,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_KILL_CHAR_ON_FOOT: { bool killPlayerInNoPoliceZone = false; - if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && bInVehicle && m_pMyVehicle) { + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) { SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); break; } @@ -12974,7 +12966,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE: case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: { - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { if (m_nPedState == PED_DRIVING) SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); } else if (m_nPedState != PED_FLEE_ENTITY) { @@ -13273,12 +13265,12 @@ CPed::ProcessObjective(void) { distWithTarget = m_nextRoutePointPos - GetPosition(); distWithTarget.z = 0.0f; - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { CCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos); CCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle); if (distWithTarget.MagnitudeSqr() < sq(20.0f)) { m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - CPed::ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); + ForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS); SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); } break; @@ -13322,7 +13314,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_RUN_TO_AREA: { if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA) - && bInVehicle && m_pMyVehicle) { + && InVehicle()) { SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle); } else { distWithTarget = m_nextRoutePointPos - GetPosition(); @@ -13583,7 +13575,7 @@ CPed::ProcessObjective(void) // fall through case OBJECTIVE_LEAVE_VEHICLE: if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN && (m_nPedType != PEDTYPE_COP || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < 0.000025f)) { @@ -13601,7 +13593,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_LEAVE_CAR_AND_DIE: { if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) { - if (bInVehicle && m_pMyVehicle) { + if (InVehicle()) { if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) { // VC calls SetExitBoat for boats, which is not seperate func. in III but housed in CPlayerInfo::Process. @@ -14802,7 +14794,7 @@ CPed::SetRadioStation(void) } } -bool +inline bool CPed::IsNotInWreckedVehicle() { return m_pMyVehicle != nil && m_pMyVehicle->m_status != STATUS_WRECKED; @@ -16178,7 +16170,7 @@ CPed::UpdateFromLeader(void) return; CVector leaderDist; - if (m_leader->bInVehicle && m_leader->m_pMyVehicle) + if (m_leader->InVehicle()) leaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition(); else leaderDist = m_leader->GetPosition() - GetPosition(); diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 9e2f0e9f..f4647831 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -243,7 +243,7 @@ enum PedState PED_STEP_AWAY, PED_ON_FIRE, - PED_UNKNOWN, // HANG_OUT in Fire_Head's idb + PED_UNKNOWN, // Same with IDLE, but also infects up to 5 peds with same pedType and WANDER_PATH, so they become stone too. HANG_OUT in Fire_Head's idb PED_STATES_NO_AI, @@ -787,6 +787,7 @@ public: PedState GetPedState(void) { return m_nPedState; } void SetPedState(PedState state) { m_nPedState = state; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. void ReplaceWeaponWhenExitingVehicle(void); void RemoveWeaponWhenEnteringVehicle(void); bool IsNotInWreckedVehicle(); diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp index 50d75516..198d9b67 100644 --- a/src/weapons/ProjectileInfo.cpp +++ b/src/weapons/ProjectileInfo.cpp @@ -3,5 +3,5 @@ #include "ProjectileInfo.h" #include "Projectile.h" - +WRAPPER void CProjectileInfo::RemoveAllProjectiles(void) { EAXJMP(0x55BB80); } WRAPPER bool CProjectileInfo::RemoveIfThisIsAProjectile(CObject *pObject) { EAXJMP(0x55BBD0); }
\ No newline at end of file diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h index f4753b28..5db57fec 100644 --- a/src/weapons/ProjectileInfo.h +++ b/src/weapons/ProjectileInfo.h @@ -6,4 +6,5 @@ class CProjectileInfo {
public:
static bool RemoveIfThisIsAProjectile(CObject *pObject);
+ static void RemoveAllProjectiles(void);
};
\ No newline at end of file |