diff --git a/README.md b/README.md index 6d4d6afd..8b9ac448 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ CBulletInfo CBulletTraces CCam CCamera -CCivilianPed CCopPed CCrane CCranes @@ -64,9 +63,7 @@ CGlass CMenuManager CMotionBlurStreaks CPacManPickups -CPed - being worked on CPedIK -CPhoneInfo - one function left CPlayerInfo CPlayerPed CProjectile 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(buf); - m_nNum = ReadSaveBuf(buf); + m_nScriptPhonesMax = ReadSaveBuf(buf); for (int i = 0; i < NUMPHONES; i++) { m_aPhones[i] = ReadSaveBuf(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(buf); + CWorld::Players[CWorld::PlayerInFocus].m_WBState = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_nWBTime = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_bFastReload = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree = ReadSaveBuf(buf); + CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree = ReadSaveBuf(buf); + for (int i = 0; i < sizeof(CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName); i++) { + CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName[i] = ReadSaveBuf(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 @@ -1011,6 +1011,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) { @@ -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