diff options
author | Nikolay Korolev <nickvnuk@gmail.com> | 2019-10-06 13:26:50 +0200 |
---|---|---|
committer | Nikolay Korolev <nickvnuk@gmail.com> | 2019-10-06 13:26:50 +0200 |
commit | e10f5ee6a3f94a5ff2559f868c884e47d4628271 (patch) | |
tree | 3b2a2ceafc26e4215b49bf56e75cf80568251f26 /src/control | |
parent | car AI (diff) | |
parent | Fixed player blip heading when looking left/right/behind (diff) | |
download | re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar.gz re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar.bz2 re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar.lz re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar.xz re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.tar.zst re3-e10f5ee6a3f94a5ff2559f868c884e47d4628271.zip |
Diffstat (limited to '')
-rw-r--r-- | src/control/CarCtrl.cpp | 9 | ||||
-rw-r--r-- | src/control/Darkel.cpp | 298 | ||||
-rw-r--r-- | src/control/Darkel.h | 10 | ||||
-rw-r--r-- | src/control/Garages.cpp | 3 | ||||
-rw-r--r-- | src/control/Garages.h | 3 | ||||
-rw-r--r-- | src/control/Pickups.cpp | 1058 | ||||
-rw-r--r-- | src/control/Pickups.h | 168 | ||||
-rw-r--r-- | src/control/Script.cpp | 8 |
8 files changed, 1331 insertions, 226 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index a6cbad5e..4775d595 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -696,7 +696,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) } if (pVehicle->bExtendedRange) threshold *= 1.5f; - if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){ + if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)){ pVehicle->bFadeOut = true; }else{ @@ -712,9 +712,10 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f && !IsThisVehicleInteresting(pVehicle) && !pVehicle->bIsLocked && + pVehicle->CanBeDeleted() && !CTrafficLights::ShouldCarStopForLight(pVehicle, true) && !CTrafficLights::ShouldCarStopForBridge(pVehicle) && - !CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){ + !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ CWorld::Remove(pVehicle); delete pVehicle; return; @@ -724,7 +725,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 && (!pVehicle->GetIsOnScreen() || !CRenderer::IsEntityCullZoneVisible(pVehicle))){ if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){ - if (!CGarages::IsPointWithinHideOutGarage(&pVehicle->GetPosition())){ + if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ CWorld::Remove(pVehicle); delete pVehicle; } @@ -1322,7 +1323,7 @@ void CCarCtrl::WeaveThroughPedsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh continue; if (pPed->GetPosition().y < y_inf || pPed->GetPosition().y > y_sup) continue; - if (Abs(pPed->GetPosition().z - pPed->GetPosition().z) >= PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING) + if (Abs(pPed->GetPosition().z - pVehicle->GetPosition().z) >= PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING) continue; if (pPed->m_pCurSurface != pVehicle) WeaveForPed(pPed, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight); diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp index 670c10fb..da28faa7 100644 --- a/src/control/Darkel.cpp +++ b/src/control/Darkel.cpp @@ -2,12 +2,12 @@ #include "patcher.h" #include "main.h" #include "Darkel.h" +#include "PlayerPed.h" #include "Timer.h" #include "DMAudio.h" #include "Population.h" #include "Weapon.h" #include "World.h" -#include "PlayerPed.h" #include "Stats.h" #include "Font.h" #include "Text.h" @@ -19,105 +19,140 @@ int32 &CDarkel::WeaponType = *(int32*)0x9430F0; int32 &CDarkel::AmmoInterruptedWeapon = *(int32*)0x8E29C8; int32 &CDarkel::KillsNeeded = *(int32*)0x8F1AB8; int8 &CDarkel::InterruptedWeapon = *(int8*)0x95CD60; + +/* + * bStandardSoundAndMessages is a completely beta thing, + * makes game handle sounds & messages instead of SCM (just like in GTA2) + * but it's never been used in the game. Has unused sliding text when frenzy completed etc. + */ int8 &CDarkel::bStandardSoundAndMessages = *(int8*)0x95CDB6; int8 &CDarkel::bNeedHeadShot = *(int8*)0x95CDCA; int8 &CDarkel::bProperKillFrenzy = *(int8*)0x95CD98; eKillFrenzyStatus &CDarkel::Status = *(eKillFrenzyStatus*)0x95CCB4; -int16 *CDarkel::RegisteredKills = (int16*)0x6EDBE0; +uint16 (&CDarkel::RegisteredKills)[NUMDEFAULTMODELS] = *(uint16(*)[NUMDEFAULTMODELS]) * (uintptr*)0x6EDBE0; int32 &CDarkel::ModelToKill = *(int32*)0x8F2C78; int32 &CDarkel::ModelToKill2 = *(int32*)0x885B40; int32 &CDarkel::ModelToKill3 = *(int32*)0x885B3C; int32 &CDarkel::ModelToKill4 = *(int32*)0x885B34; wchar *CDarkel::pStartMessage = (wchar*)0x8F2C08; -int32 CDarkel::CalcFade(uint32 time, int32 start, uint32 end) { +uint8 +CDarkel::CalcFade(uint32 time, uint32 start, uint32 end) +{ if (time >= start && time <= end) { if (time >= start + 500) { if (time <= end - 500) return 255; else return 255 * (end - time) / 500; - } - else + } else return 255 * (time - start) / 500; - } - else + } else return 0; } -// This function has been cleaned up from unused stuff. -#if 0 -WRAPPER void CDarkel::DrawMessages(void) { EAXJMP(0x420920); } -#else -void CDarkel::DrawMessages() +// Screen positions taken from VC +void +CDarkel::DrawMessages() { - bool DisplayTimers = false; - switch (Status) { - case KILLFRENZY_ONGOING: - assert(pStartMessage != nil); - DisplayTimers = true; - break; - case KILLFRENZY_PASSED: - case KILLFRENZY_FAILED: - DisplayTimers = false; - break; - }; - - if (DisplayTimers) { - CFont::SetPropOn(); - CFont::SetBackgroundOff(); - CFont::SetBackGroundOnlyTextOn(); - CFont::SetAlignment(ALIGN_RIGHT); - CFont::SetRightJustifyWrap(-SCREEN_WIDTH); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f)); - - float AlignToHUD = SCREEN_SCALE_X(-10.0f); - int32 a = (TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart)); - if (CTimer::GetFrameCounter() & 8 || a > 4000) { - sprintf(gString, "%d:%02d", a / 60000, a % 60000 / 1000); + case KILLFRENZY_ONGOING: + { + CFont::SetJustifyOff(); + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(30.0f)); + CFont::SetCentreOn(); + CFont::SetPropOn(); + uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; + if (CDarkel::bStandardSoundAndMessages) { + if (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) { + CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f)); + CFont::SetJustifyOff(); + CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000))); + CFont::SetFontStyle(FONT_BANK); + if (pStartMessage) { + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage); + } + } + } else { + if (timePassedSinceStart < 8000) { + CFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f)); + CFont::SetJustifyOff(); + CFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000))); + CFont::SetFontStyle(FONT_BANK); + if (pStartMessage) { + CFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage); + } + } + } + CFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(1.5f)); + CFont::SetCentreOff(); + CFont::SetRightJustifyOn(); + CFont::SetFontStyle(FONT_HEADING); + if (CDarkel::TimeLimit >= 0) { + uint32 timeLeft = CDarkel::TimeLimit - (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart); + sprintf(gString, "%d:%02d", timeLeft / 60000, timeLeft % 60000 / 1000); + AsciiToUnicode(gString, gUString); + if (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) { + CFont::SetColor(CRGBA(0, 0, 0, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString); + CFont::SetColor(CRGBA(150, 100, 255, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString); + } + } + sprintf(gString, "%d", (CDarkel::KillsNeeded >= 0 ? CDarkel::KillsNeeded : 0)); AsciiToUnicode(gString, gUString); CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(25.0f) + AlignToHUD, SCREEN_SCALE_Y(112.0f), gUString); - - CFont::SetColor(CRGBA(150, 100, 255, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + AlignToHUD, SCREEN_SCALE_Y(110.0f), gUString); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(144.0f), gUString); + CFont::SetColor(CRGBA(255, 128, 128, 255)); + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(143.0f), gUString); + break; } - - if (KillsNeeded <= 0) - KillsNeeded = 0; - - sprintf((char *)gString, "%d", KillsNeeded); - AsciiToUnicode(gString, gUString); - - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(25.0f) + AlignToHUD, SCREEN_SCALE_Y(134.0f), gUString); - - CFont::SetColor(CRGBA(255, 128, 128, 255)); - CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(27.0f) + AlignToHUD, SCREEN_SCALE_Y(132.0f), gUString); + case KILLFRENZY_PASSED: + { + if (CDarkel::bStandardSoundAndMessages) { + uint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart; + if (CTimer::GetTimeInMilliseconds() - CDarkel::TimeOfFrenzyStart < 5000) { + CFont::SetBackgroundOff(); + CFont::SetCentreSize(SCREEN_SCALE_FROM_RIGHT(20.0f)); + CFont::SetCentreOn(); + CFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f)); + CFont::SetJustifyOff(); + CFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000))); + CFont::SetFontStyle(FONT_BANK); + int y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f); + CFont::PrintString(SCREEN_WIDTH / 2, y, TheText.Get("KF_3")); + } + } + break; + } + default: + break; } } -#endif -void CDarkel::Init() +void +CDarkel::Init() { Status = KILLFRENZY_NONE; } -int16 CDarkel::QueryModelsKilledByPlayer(int32 modelId) +uint16 +CDarkel::QueryModelsKilledByPlayer(int32 modelId) { return RegisteredKills[modelId]; } -bool CDarkel::FrenzyOnGoing() +bool +CDarkel::FrenzyOnGoing() { return Status == KILLFRENZY_ONGOING; } -eKillFrenzyStatus CDarkel::ReadStatus() +uint16 +CDarkel::ReadStatus() { return Status; } @@ -141,21 +176,24 @@ void CDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapontype, bool he } #endif -void CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype) +void +CDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype) { - ++CStats::NumberKillFrenziesPassed; + ++CStats::PeopleKilledByOthers; } -void CDarkel::ResetModelsKilledByPlayer() +void +CDarkel::ResetModelsKilledByPlayer() { - for (int i = 0; i < 200; i++) + for (int i = 0; i < NUMDEFAULTMODELS; i++) RegisteredKills[i] = 0; } #if 0 WRAPPER void CDarkel::ResetOnPlayerDeath() { EAXJMP(0x420E70); } #else -void CDarkel::ResetOnPlayerDeath() +void +CDarkel::ResetOnPlayerDeath() { if (Status != KILLFRENZY_ONGOING) return; @@ -164,48 +202,37 @@ void CDarkel::ResetOnPlayerDeath() Status = KILLFRENZY_FAILED; TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds(); + eWeaponType fixedWeapon; if (WeaponType == WEAPONTYPE_UZI_DRIVEBY) - WeaponType = WEAPONTYPE_UZI; - - if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; - } - - if (FindPlayerVehicle()) { - FindPlayerPed()->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nModelId); - FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_currentWeapon); - } - - - CPopulation::m_AllRandomPedsThisType = -1; - Status = KILLFRENZY_FAILED; - TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds(); - - if (WeaponType == WEAPONTYPE_UZI_DRIVEBY) - WeaponType = WEAPONTYPE_UZI; + fixedWeapon = WEAPONTYPE_UZI; + else + fixedWeapon = (eWeaponType)WeaponType; - if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; + CPlayerPed *player = FindPlayerPed(); + if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) { + player->m_nSelectedWepSlot = InterruptedWeapon; + player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon; } if (FindPlayerVehicle()) { - FindPlayerPed()->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nModelId); - FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_currentWeapon); + player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId); + player->m_currentWeapon = player->m_nSelectedWepSlot; + player->MakeChangesForNewWeapon(player->m_currentWeapon); } } #endif #if 0 -WRAPPER void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot) { EAXJMP(0x4210E0); } +WRAPPER void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot) { EAXJMP(0x4210E0); } #else -void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot) +void +CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot) { + eWeaponType fixedWeapon; if (weaponType == WEAPONTYPE_UZI_DRIVEBY) - weaponType = WEAPONTYPE_UZI; + fixedWeapon = WEAPONTYPE_UZI; + else + fixedWeapon = weaponType; WeaponType = weaponType; Status = KILLFRENZY_ONGOING; @@ -219,8 +246,7 @@ void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 if (text == TheText.Get("PAGE_00")) { CDarkel::bProperKillFrenzy = 1; CDarkel::pStartMessage = 0; - } - else + } else bProperKillFrenzy = 0; bStandardSoundAndMessages = standardSound; @@ -229,20 +255,19 @@ void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 TimeLimit = time; PreviousTime = time / 1000; - if (weaponType < WEAPONTYPE_TOTALWEAPONS) { - InterruptedWeapon = FindPlayerPed()->m_currentWeapon; - FindPlayerPed()->GiveWeapon(weaponType, 0); - AmmoInterruptedWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal; - FindPlayerPed()->GiveWeapon(weaponType, 30000); - FindPlayerPed()->m_nSelectedWepSlot = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_nSelectedWepSlot); + CPlayerPed *player = FindPlayerPed(); + if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) { + InterruptedWeapon = player->m_currentWeapon; + player->GiveWeapon(fixedWeapon, 0); + AmmoInterruptedWeapon = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal; + player->GiveWeapon(fixedWeapon, 30000); + player->m_nSelectedWepSlot = player->GetWeaponSlot(fixedWeapon); + player->MakeChangesForNewWeapon(player->m_nSelectedWepSlot); if (FindPlayerVehicle()) { - FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal <= CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip) - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoInClip = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal; - - FindPlayerPed()->ClearWeaponTarget(); + player->m_currentWeapon = player->m_nSelectedWepSlot; + player->GetWeapon()->m_nAmmoInClip = min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition); + player->ClearWeaponTarget(); } } if (CDarkel::bStandardSoundAndMessages) @@ -250,13 +275,15 @@ void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 } #endif -void CDarkel::Update() +void +CDarkel::Update() { if (Status != KILLFRENZY_ONGOING) return; int32 FrameTime = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart); if ((TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart)) > 0 || TimeLimit < 0) { + DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_ONGOING, FrameTime); int32 PrevTime = FrameTime / 1000; @@ -267,24 +294,27 @@ void CDarkel::Update() PreviousTime = PrevTime; } - } - else { + } else { CPopulation::m_AllRandomPedsThisType = -1; Status = KILLFRENZY_FAILED; TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds(); + eWeaponType fixedWeapon; if (WeaponType == WEAPONTYPE_UZI_DRIVEBY) - WeaponType = WEAPONTYPE_UZI; + fixedWeapon = WEAPONTYPE_UZI; + else + fixedWeapon = (eWeaponType)WeaponType; - if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; + CPlayerPed *player = FindPlayerPed(); + if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) { + player->m_nSelectedWepSlot = InterruptedWeapon; + player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon; } if (FindPlayerVehicle()) { - FindPlayerPed()->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nModelId); - FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_currentWeapon); + player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId); + player->m_currentWeapon = player->m_nSelectedWepSlot; + player->MakeChangesForNewWeapon(player->m_currentWeapon); } if (bStandardSoundAndMessages) @@ -302,18 +332,22 @@ void CDarkel::Update() FindPlayerPed()->m_pWanted->SetWantedLevel(0); + eWeaponType fixedWeapon; if (WeaponType == WEAPONTYPE_UZI_DRIVEBY) - WeaponType = WEAPONTYPE_UZI; + fixedWeapon = WEAPONTYPE_UZI; + else + fixedWeapon = (eWeaponType)WeaponType; - if (WeaponType < WEAPONTYPE_TOTALWEAPONS) { - FindPlayerPed()->m_nSelectedWepSlot = InterruptedWeapon; - CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_nAmmoTotal = AmmoInterruptedWeapon; + CPlayerPed* player = FindPlayerPed(); + if (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) { + player->m_nSelectedWepSlot = InterruptedWeapon; + player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal = CDarkel::AmmoInterruptedWeapon; } if (FindPlayerVehicle()) { - FindPlayerPed()->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(FindPlayerPed()->GetWeapon()->m_eWeaponType)->m_nModelId); - FindPlayerPed()->m_currentWeapon = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType; - FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_currentWeapon); + player->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId); + player->m_currentWeapon = player->m_nSelectedWepSlot; + player->MakeChangesForNewWeapon(player->m_currentWeapon); } if (bStandardSoundAndMessages) @@ -322,17 +356,17 @@ void CDarkel::Update() } STARTPATCHES - /*InjectHook(0x421380, CDarkel::CalcFade, PATCH_JUMP); - InjectHook(0x420920, CDarkel::DrawMessages, PATCH_JUMP); - InjectHook(0x420E60, CDarkel::FrenzyOnGoing, PATCH_JUMP); + InjectHook(0x421380, CDarkel::CalcFade, PATCH_JUMP); InjectHook(0x420650, CDarkel::Init, PATCH_JUMP); - InjectHook(0x421370, CDarkel::QueryModelsKilledByPlayer, PATCH_JUMP); + InjectHook(0x420660, CDarkel::Update, PATCH_JUMP); + InjectHook(0x420E60, CDarkel::FrenzyOnGoing, PATCH_JUMP); InjectHook(0x420E50, CDarkel::ReadStatus, PATCH_JUMP); - InjectHook(0x421070, CDarkel::RegisterCarBlownUpByPlayer, PATCH_JUMP); - InjectHook(0x420F60, CDarkel::RegisterKillByPlayer, PATCH_JUMP); - InjectHook(0x421060, CDarkel::RegisterKillNotByPlayer, PATCH_JUMP); - InjectHook(0x421310, CDarkel::ResetModelsKilledByPlayer, PATCH_JUMP); InjectHook(0x420E70, CDarkel::ResetOnPlayerDeath, PATCH_JUMP); InjectHook(0x4210E0, CDarkel::StartFrenzy, PATCH_JUMP); - InjectHook(0x420660, CDarkel::Update, PATCH_JUMP);*/ + InjectHook(0x421370, CDarkel::QueryModelsKilledByPlayer, PATCH_JUMP); + InjectHook(0x421060, CDarkel::RegisterKillNotByPlayer, PATCH_JUMP); + InjectHook(0x421310, CDarkel::ResetModelsKilledByPlayer, PATCH_JUMP); + InjectHook(0x420920, CDarkel::DrawMessages, PATCH_JUMP); + //InjectHook(0x421070, CDarkel::RegisterCarBlownUpByPlayer, PATCH_JUMP); + //InjectHook(0x420F60, CDarkel::RegisterKillByPlayer, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/control/Darkel.h b/src/control/Darkel.h index 77a14bb8..0171cd2c 100644 --- a/src/control/Darkel.h +++ b/src/control/Darkel.h @@ -26,7 +26,7 @@ private: static int8 &bNeedHeadShot; static int8 &bProperKillFrenzy; static eKillFrenzyStatus &Status; - static int16 *RegisteredKills; + static uint16 (&RegisteredKills)[NUMDEFAULTMODELS]; static int32 &ModelToKill; static int32 &ModelToKill2; static int32 &ModelToKill3; @@ -34,18 +34,18 @@ private: static wchar *pStartMessage; public: - static int32 CalcFade(uint32 time, int32 min, uint32 max); + static uint8 CalcFade(uint32 time, uint32 min, uint32 max); static void DrawMessages(void); static bool FrenzyOnGoing(); static void Init(); - static int16 QueryModelsKilledByPlayer(int32 modelId); - static eKillFrenzyStatus ReadStatus(); + static uint16 QueryModelsKilledByPlayer(int32 modelId); + static uint16 ReadStatus(); static void RegisterCarBlownUpByPlayer(CVehicle *vehicle); static void RegisterKillByPlayer(CPed *victim, eWeaponType weapontype, bool headshot = false); static void RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype); static void ResetModelsKilledByPlayer(); static void ResetOnPlayerDeath(); - static void StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot); + static void StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot); static void Update(); }; diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 0e9592dc..560a9c0c 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -69,7 +69,8 @@ bool CGarages::HasCarBeenCrushed(int32 handle) } WRAPPER void CGarages::TriggerMessage(const char *text, int16, uint16 time, int16) { EAXJMP(0x426B20); } -WRAPPER bool CGarages::IsPointWithinHideOutGarage(CVector*) { EAXJMP(0x428260); } +WRAPPER bool CGarages::IsPointWithinHideOutGarage(CVector&) { EAXJMP(0x428260); } +WRAPPER bool CGarages::IsPointWithinAnyGarage(CVector&) { EAXJMP(0x428320); } #if 0 WRAPPER void CGarages::PrintMessages(void) { EAXJMP(0x426310); } diff --git a/src/control/Garages.h b/src/control/Garages.h index 4c35fad1..cc5fb62b 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -25,5 +25,6 @@ public: static void TriggerMessage(const char *text, int16, uint16 time, int16); static void PrintMessages(void); static bool HasCarBeenCrushed(int32); - static bool IsPointWithinHideOutGarage(CVector*); + static bool IsPointWithinHideOutGarage(CVector&); + static bool IsPointWithinAnyGarage(CVector&); }; diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 81642a85..8a67e248 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -1,20 +1,1038 @@ -#include "common.h" -#include "patcher.h" -#include "Pickups.h" - -CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; - -// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4) -uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 }; -uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 }; - -WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); } -WRAPPER void CPickups::DoCollectableEffects(CEntity *ent) { EAXJMP(0x431C30); } -WRAPPER void CPickups::DoMoneyEffects(CEntity *ent) { EAXJMP(0x431F40); } -WRAPPER void CPickups::DoMineEffects(CEntity *ent) { EAXJMP(0x4321C0); } -WRAPPER void CPickups::DoPickUpEffects(CEntity *ent) { EAXJMP(0x431520); } -WRAPPER void CPickups::RemoveAllFloatingPickups() { EAXJMP(0x430800); } -WRAPPER int32 CPickups::GenerateNewOne(CVector, uint32, uint8, uint32) { EAXJMP(0x4304B0); } -WRAPPER int32 CPickups::GenerateNewOne_WeaponType(CVector, eWeaponType, uint8, uint32) { EAXJMP(0x430660); } - -WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } +#include "common.h"
+#include "patcher.h"
+#include "main.h"
+#include "Pickups.h"
+#include "Camera.h"
+#include "Entity.h"
+#include "Timer.h"
+#include "Shadows.h"
+#include "Coronas.h"
+#include "World.h"
+#include "ModelIndices.h"
+#include "PlayerPed.h"
+#include "Object.h"
+#include "Pools.h"
+#include "Pad.h"
+#include "Script.h"
+#include "Darkel.h"
+#include "Garages.h"
+#include "Explosion.h"
+#include "WaterLevel.h"
+#include "MoneyMessages.h"
+#include "PointLights.h"
+#include "Sprite.h"
+#include "Font.h"
+
+CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98;
+int16 CPickups::NumMessages;// = *(int16*)0x95CC98;
+int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];// = *(int32(*)[NUMCOLLECTEDPICKUPS])*(uintptr*)0x87C538;
+int16 CPickups::CollectedPickUpIndex;// = *(int16*)0x95CC8A;
+
+// unused
+bool &CPickups::bPickUpcamActivated = *(bool*)0x95CD71;
+CVehicle *&CPickups::pPlayerVehicle = *(CVehicle**)0x8F29E8;
+CVector &CPickups::StaticCamCoors = *(CVector*)0x9404C8;
+uint32 &CPickups::StaticCamStartTime = *(uint32*)0x8E289C;
+
+tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];
+
+// 20 ?! Some Miami leftover? (Originally at 0x5ED8D4)
+uint16 AmmoForWeapon[20] = { 0, 1, 45, 125, 25, 150, 300, 25, 5, 250, 5, 5, 0, 500, 0, 100, 0, 0, 0, 0 };
+uint16 AmmoForWeapon_OnStreet[20] = { 0, 1, 9, 25, 5, 30, 60, 5, 1, 50, 1, 1, 0, 200, 0, 100, 0, 0, 0, 0 };
+uint16 CostOfWeapon[20] = { 0, 10, 250, 800, 1500, 3000, 5000, 10000, 25000, 25000, 2000, 2000, 0, 50000, 0, 3000, 0, 0, 0, 0 };
+
+uint8 aWeaponReds[] = { 255, 0, 128, 255, 255, 0, 255, 0, 128, 128, 255, 0255, 128, 0, 255, 0 };
+uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 255, 0, 255, 0 };
+uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
+float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
+
+WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+
+
+void
+CPickup::RemoveKeepType()
+{
+ CWorld::Remove(m_pObject);
+ delete m_pObject;
+
+ m_bRemoved = true;
+ m_pObject = nil;
+}
+
+void
+CPickup::Remove()
+{
+ RemoveKeepType();
+ m_eType = PICKUP_NONE;
+}
+
+CObject *
+CPickup::GiveUsAPickUpObject(int32 handle)
+{
+ CObject *object;
+
+ if (handle <= 0) object = new CObject(m_eModelIndex, false);
+ else {
+ CPools::MakeSureSlotInObjectPoolIsEmpty(handle);
+ object = new(handle) CObject(m_eModelIndex, false);
+ }
+
+ if (object == nil) return nil;
+ object->ObjectCreatedBy = MISSION_OBJECT;
+ object->GetPosition() = m_vecPos;
+ object->SetOrientation(0.0f, 0.0f, -HALFPI);
+ object->GetMatrix().UpdateRW();
+ object->UpdateRwFrame();
+
+ object->bAffectedByGravity = false;
+ object->bExplosionProof = true;
+ object->bUsesCollision = false;
+ object->bIsPickup = true;
+
+ object->field_172 = m_eModelIndex == MI_PICKUP_BONUS ? m_nQuantity : 0;
+
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ object->m_obj_flag2 = true;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ case PICKUP_COLLECTABLE1:
+ case PICKUP_MONEY:
+ case PICKUP_MINE_INACTIVE:
+ case PICKUP_MINE_ARMED:
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ case PICKUP_FLOATINGPACKAGE:
+ case PICKUP_ON_STREET_SLOW:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = false;
+ break;
+ case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ object->m_obj_flag2 = false;
+ object->bOutOfStock = true;
+ object->bRenderScorched = true;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ return object;
+}
+
+bool
+CPickup::CanBePickedUp(CPlayerPed *player)
+{
+ assert(m_pObject != nil);
+ bool cannotBePickedUp =
+ (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > 99.5f)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0)
+ || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame));
+ return !cannotBePickedUp;
+}
+
+bool
+CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
+{
+ float waterLevel;
+
+ if (m_bRemoved) {
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer) {
+ // respawn pickup if we're far enough
+ float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);
+ if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {
+ m_pObject = GiveUsAPickUpObject(-1);
+ if (m_pObject) {
+ CWorld::Add(m_pObject);
+ m_bRemoved = false;
+ }
+ }
+ }
+ return false;
+ }
+
+ if (!m_pObject) return false;
+
+ if (!IsMine()) {
+ // let's check if we touched the pickup
+ bool isPickupTouched = false;
+ if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {
+ if (vehicle != nil) {
+ if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))
+ isPickupTouched = true;
+ }
+ else {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ isPickupTouched = true;
+ }
+ } else if (vehicle == nil) {
+ if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {
+ if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +
+ (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)
+ isPickupTouched = true;
+ }
+ }
+
+ // if we didn't then we've got nothing to do
+ if (isPickupTouched && CanBePickedUp(player)) {
+ CPad::GetPad(0)->StartShake(120, 100);
+ switch (m_eType)
+ {
+ case PICKUP_IN_SHOP:
+ if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]) {
+ CGarages::TriggerMessage("PU_MONY", -1, 6000, -1);
+ } else {
+ CWorld::Players[playerId].m_nMoney -= CostOfWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())];
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ RemoveKeepType();
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ return true;
+ }
+ break;
+ case PICKUP_ON_STREET:
+ case PICKUP_ON_STREET_SLOW:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon_OnStreet[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) {
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ CPickups::bPickUpcamActivated = true;
+ CPickups::pPlayerVehicle = FindPlayerVehicle();
+ CPickups::StaticCamCoors = m_pObject->GetPosition();
+ CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ if (m_eType == PICKUP_ON_STREET) {
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ } else if (m_eType == PICKUP_ON_STREET_SLOW) {
+ if (MI_PICKUP_BRIBE == m_pObject->m_modelIndex)
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 300000;
+ else
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 720000;
+ }
+
+ RemoveKeepType();
+ return true;
+ case PICKUP_ONCE:
+ case PICKUP_ONCE_TIMEOUT:
+ if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {
+ if (CPickups::WeaponForModel(m_pObject->GetModelIndex())) {
+ player->GiveWeapon(CPickups::WeaponForModel(m_pObject->GetModelIndex()), m_nQuantity != 0 ? m_nQuantity : AmmoForWeapon[CPickups::WeaponForModel(m_pObject->GetModelIndex())]);
+ if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))
+ player->m_nSelectedWepSlot = player->GetWeaponSlot(CPickups::WeaponForModel(m_pObject->GetModelIndex()));
+ }
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);
+ }
+ Remove();
+ return true;
+ case PICKUP_COLLECTABLE1:
+ CWorld::Players[playerId].m_nCollectedPackages++;
+ CWorld::Players[playerId].m_nMoney += 1000;
+
+ if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {
+ printf("All collectables have been picked up\n");
+ CGarages::TriggerMessage("CO_ALL", -1, 5000, -1);
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000000;
+ } else
+ CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);
+
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);
+ return true;
+ case PICKUP_MONEY:
+ CWorld::Players[playerId].m_nMoney += m_nQuantity;
+ sprintf(gString, "$%d", m_nQuantity);
+#ifdef MONEY_MESSAGES
+ CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);
+#endif
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
+ return true;
+ //case PICKUP_IN_SHOP_OUT_OF_STOCK:
+ //case PICKUP_MINE_INACTIVE:
+ //case PICKUP_MINE_ARMED:
+ //case PICKUP_NAUTICAL_MINE_INACTIVE:
+ //case PICKUP_NAUTICAL_MINE_ARMED:
+ //case PICKUP_FLOATINGPACKAGE:
+ //case PICKUP_FLOATINGPACKAGE_FLOATING:
+ default:
+ break;
+ }
+ }
+ } else {
+ switch (m_eType)
+ {
+ case PICKUP_MINE_INACTIVE:
+ if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ m_eType = PICKUP_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ case PICKUP_NAUTICAL_MINE_INACTIVE:
+ {
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+
+ bool touched = false;
+ for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ touched = true;
+ break; // added break here
+ }
+ }
+
+ if (!touched) {
+ m_eType = PICKUP_NAUTICAL_MINE_ARMED;
+ m_nTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ }
+ break;
+ }
+ case PICKUP_NAUTICAL_MINE_ARMED:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))
+ m_pObject->GetPosition().z = waterLevel + 0.6f;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ // no break here
+ case PICKUP_MINE_ARMED:
+ {
+ bool explode = false;
+ if (CTimer::GetTimeInMilliseconds() > m_nTimer)
+ explode = true;
+ else {// added else here since vehicle lookup is useless
+ for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake
+ CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
+ explode = true;
+ break; // added break here
+ }
+ }
+ }
+ if (explode) {
+ CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);
+ Remove();
+ }
+ break;
+ }
+ case PICKUP_FLOATINGPACKAGE:
+ m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
+ m_pObject->GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z)
+ m_eType = PICKUP_FLOATINGPACKAGE_FLOATING;
+ break;
+ case PICKUP_FLOATINGPACKAGE_FLOATING:
+ if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0))
+ m_pObject->GetPosition().z = waterLevel;
+
+ m_pObject->GetMatrix().UpdateRW();
+ m_pObject->UpdateRwFrame();
+ if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {
+ Remove();
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);
+ }
+ break;
+ }
+ }
+ if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)
+ Remove();
+ return false;
+}
+
+void
+CPickups::Init(void)
+{
+ NumMessages = 0;
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ aPickUps[i].m_eType = PICKUP_NONE;
+ aPickUps[i].m_nIndex = 1;
+ aPickUps[i].m_pObject = nil;
+ }
+
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = 0;
+
+ CollectedPickUpIndex = 0;
+}
+
+bool
+CPickups::IsPickUpPickedUp(int32 pickupId)
+{
+ for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
+ if (pickupId == aPickUpsCollected[i]) {
+ aPickUpsCollected[i] = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+CPickups::PassTime(uint32 time)
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE) {
+ if (aPickUps[i].m_nTimer <= time)
+ aPickUps[i].m_nTimer = 0;
+ else
+ aPickUps[i].m_nTimer -= time;
+ }
+ }
+}
+
+int32
+CPickups::GetActualPickupIndex(int32 index)
+{
+ if (index == -1) return -1;
+
+ // doesn't look nice
+ if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;
+ return (uint16)index;
+}
+
+bool
+CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)
+{
+ CPlayerPed *player;
+
+ if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ else player = CWorld::Players[playerIndex].m_pPed;
+
+ if (modelIndex == MI_PICKUP_ADRENALINE) {
+ player->m_bAdrenalineActive = true;
+ player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;
+ player->m_fCurrentStamina = player->m_fMaxStamina;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BODYARMOUR) {
+ player->m_fArmour = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_INFO) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_HEALTH) {
+ player->m_fHealth = 100.0f;
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BONUS) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_BRIBE) {
+ int32 level = FindPlayerPed()->m_pWanted->m_nWantedLevel - 1;
+ if (level < 0) level = 0;
+ player->SetWantedLevel(level);
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ } else if (modelIndex == MI_PICKUP_KILLFRENZY) {
+ DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);
+ return true;
+ }
+ return false;
+}
+
+void
+CPickups::RemoveAllFloatingPickups()
+{
+ for (int i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE || aPickUps[i].m_eType == PICKUP_FLOATINGPACKAGE_FLOATING) {
+ if (aPickUps[i].m_pObject) {
+ CWorld::Remove(aPickUps[i].m_pObject);
+ delete aPickUps[i].m_pObject;
+ aPickUps[i].m_pObject = nil;
+ }
+ }
+ }
+}
+
+void
+CPickups::RemovePickUp(int32 pickupIndex)
+{
+ int32 index = CPickups::GetActualPickupIndex(pickupIndex);
+ if (index == -1) return;
+
+ if (aPickUps[index].m_pObject) {
+ CWorld::Remove(aPickUps[index].m_pObject);
+ delete aPickUps[index].m_pObject;
+ aPickUps[index].m_pObject = nil;
+ }
+ aPickUps[index].m_eType = PICKUP_NONE;
+ aPickUps[index].m_bRemoved = true;
+}
+
+int32
+CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity)
+{
+ bool bFreeFound = false;
+ int32 slot = 0;
+
+ if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE) {
+ for (slot = NUMPICKUPS; slot >= 0; slot--) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ } else {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_NONE) {
+ bFreeFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFreeFound)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS)
+ {
+ for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
+ if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
+ }
+
+ if (slot >= NUMGENERALPICKUPS) return -1;
+ }
+ }
+
+ if (slot >= NUMPICKUPS) return -1;
+
+ aPickUps[slot].m_eType = (ePickupType)type;
+ aPickUps[slot].m_bRemoved = false;
+ aPickUps[slot].m_nQuantity = quantity;
+ if (type == PICKUP_ONCE_TIMEOUT)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;
+ else if (type == PICKUP_MONEY)
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {
+ aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;
+ aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ }
+ aPickUps[slot].m_eModelIndex = modelIndex;
+ aPickUps[slot].m_vecPos = pos;
+ aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(-1);
+ if (aPickUps[slot].m_pObject)
+ CWorld::Add(aPickUps[slot].m_pObject);
+ return GetNewUniquePickupIndex(slot);
+}
+
+int32
+CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)
+{
+ return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);
+}
+
+int32
+CPickups::GetNewUniquePickupIndex(int32 slot)
+{
+ if (aPickUps[slot].m_nIndex >= 0xFFFE)
+ aPickUps[slot].m_nIndex = 1;
+ else
+ aPickUps[slot].m_nIndex++;
+ return slot | (aPickUps[slot].m_nIndex << 16);
+}
+
+int32
+CPickups::ModelForWeapon(eWeaponType weaponType)
+{
+ switch (weaponType)
+ {
+ case WEAPONTYPE_BASEBALLBAT: return MI_BASEBALL_BAT;
+ case WEAPONTYPE_COLT45: return MI_COLT;
+ case WEAPONTYPE_UZI: return MI_UZI;
+ case WEAPONTYPE_SHOTGUN: return MI_SHOTGUN;
+ case WEAPONTYPE_AK47: return MI_AK47;
+ case WEAPONTYPE_M16: return MI_M16;
+ case WEAPONTYPE_SNIPERRIFLE: return MI_SNIPER;
+ case WEAPONTYPE_ROCKETLAUNCHER: return MI_ROCKETLAUNCHER;
+ case WEAPONTYPE_FLAMETHROWER: return MI_FLAMETHROWER;
+ case WEAPONTYPE_MOLOTOV: return MI_MOLOTOV;
+ case WEAPONTYPE_GRENADE: return MI_GRENADE;
+ }
+ return 0;
+}
+
+eWeaponType
+CPickups::WeaponForModel(int32 model)
+{
+ if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;
+ switch (model)
+ {
+ case MI_GRENADE: return WEAPONTYPE_GRENADE;
+ case MI_AK47: return WEAPONTYPE_AK47;
+ case MI_BASEBALL_BAT: return WEAPONTYPE_BASEBALLBAT;
+ case MI_COLT: return WEAPONTYPE_COLT45;
+ case MI_MOLOTOV: return WEAPONTYPE_MOLOTOV;
+ case MI_ROCKETLAUNCHER: return WEAPONTYPE_ROCKETLAUNCHER;
+ case MI_SHOTGUN: return WEAPONTYPE_SHOTGUN;
+ case MI_SNIPER: return WEAPONTYPE_SNIPERRIFLE;
+ case MI_UZI: return WEAPONTYPE_UZI;
+ case MI_MISSILE: return WEAPONTYPE_UNARMED;
+ case MI_M16: return WEAPONTYPE_M16;
+ case MI_FLAMETHROWER: return WEAPONTYPE_FLAMETHROWER;
+ }
+ return WEAPONTYPE_UNARMED;
+}
+
+int32
+CPickups::FindColourIndexForWeaponMI(int32 model)
+{
+ return WeaponForModel(model) - 1;
+}
+
+void
+CPickups::AddToCollectedPickupsArray(int32 index)
+{
+ aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);
+ if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)
+ CollectedPickUpIndex = 0;
+}
+
+void
+CPickups::Update()
+{
+#ifndef FIX_BUGS
+ // BUG: this code can only reach 318 out of 320 pickups
+#define PICKUPS_FRAME_SPAN (6)
+#define PICKUPS_PER_FRAME (NUMGENERALPICKUPS/PICKUPS_FRAME_SPAN)
+
+ for (uint32 i = PICKUPS_PER_FRAME * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < PICKUPS_PER_FRAME * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+
+ for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+
+#undef PICKUPS_FRAME_SPAN
+#undef PICKUPS_PER_FRAME
+#else
+ for (uint32 i = 0; i < NUMPICKUPS; i++) {
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) {
+ AddToCollectedPickupsArray(i);
+ }
+ }
+#endif
+}
+
+void
+CPickups::DoPickUpEffects(CEntity *entity)
+{
+ if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ entity->m_flagD80 = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;
+
+ if (!entity->m_flagD80) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+ float modifiedSin = 0.3 * (s + 1.0f);
+
+
+ int16 colorId;
+
+ if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA)
+ colorId = 11;
+ else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR || entity->GetModelIndex() == MI_PICKUP_BRIBE)
+ colorId = 12;
+ else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)
+ colorId = 13;
+ else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS)
+ colorId = 14;
+ else
+ colorId = FindColourIndexForWeaponMI(entity->GetModelIndex());
+
+ assert(colorId >= 0);
+
+ CVector &pos = entity->GetPosition();
+
+ float colorModifier = ((double)(rand() & 0x1F) * 0.015f + 1.0f) * modifiedSin * 0.15f;
+ CShadows::StoreStaticShadow(
+ (uintptr)entity,
+ SHADOWTYPE_ADDITIVE,
+ gpShadowExplosionTex,
+ &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ aWeaponReds[colorId] * colorModifier, aWeaponGreens[colorId] * colorModifier, aWeaponBlues[colorId] * colorModifier,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+
+ float radius = (double)(rand() & 0xF) * 0.1 + 3.0;
+ CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aWeaponReds[colorId] * modifiedSin / 256.0f, aWeaponGreens[colorId] * modifiedSin / 256.0f, aWeaponBlues[colorId] * modifiedSin / 256.0f, CPointLights::FOG_NONE, true);
+ float size = (double)(rand() & 0xF) * 0.0005 + 0.6;
+ CCoronas::RegisterCorona( (uintptr)entity,
+ aWeaponReds[colorId] * modifiedSin / 2.0f, aWeaponGreens[colorId] * modifiedSin / 2.0f, aWeaponBlues[colorId] * modifiedSin / 2.0f,
+ 255,
+ pos,
+ size, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+
+ CObject *object = (CObject*)entity;
+ if (object->m_obj_flag2 || object->bOutOfStock || object->field_172) {
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 12.0f;
+
+ if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {
+ RwV3d vecOut;
+ float fDistX, fDistY;
+ if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {
+ aMessages[NumMessages].m_pos.x = vecOut.x;
+ aMessages[NumMessages].m_pos.y = vecOut.y;
+ aMessages[NumMessages].m_dist.x = fDistX;
+ aMessages[NumMessages].m_dist.y = fDistY;
+ aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());
+ aMessages[NumMessages].m_color.red = aWeaponReds[colorId];
+ aMessages[NumMessages].m_color.green = aWeaponGreens[colorId];
+ aMessages[NumMessages].m_color.blue = aWeaponBlues[colorId];
+ aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;
+ aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;
+ aMessages[NumMessages].m_quantity = object->field_172;
+ NumMessages++;
+ }
+ }
+ }
+
+ entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), aWeaponScale[colorId]);
+ }
+}
+
+void
+CPickups::DoMineEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));
+
+ int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ red, 0, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));
+}
+
+void
+CPickups::DoMoneyEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 20.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));
+
+ int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ 0, green, 0,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));
+}
+
+void
+CPickups::DoCollectableEffects(CEntity *entity)
+{
+ CVector &pos = entity->GetPosition();
+ float dist = (TheCamera.GetPosition() - pos).Magnitude();
+ const float MAXDIST = 14.0f;
+
+ if (dist < MAXDIST) {
+ float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));
+
+ int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;
+ CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,
+ 2.0f, 0.0f, 0.0f, -2.0f,
+ 255, // this is 0 on PC which results in no shadow
+ color, color, color,
+ 4.0f, 1.0f, 40.0f, false, 0.0f);
+ CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
+ }
+
+ entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));
+}
+
+void
+CPickups::RenderPickUpText()
+{
+ wchar *strToPrint;
+ for (int32 i = 0; i < NumMessages; i++) {
+ if (aMessages[i].m_quantity <= 39) {
+ switch (aMessages[i].m_quantity) // could use some enum maybe
+ {
+ case 0:
+ if (aMessages[i].m_weaponType == WEAPONTYPE_TOTALWEAPONS) { // unreachable code?
+ // what is this??
+ sprintf(gString, "%d/%d", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 2903);
+ } else {
+ if (aMessages[i].m_bOutOfStock)
+ strToPrint = TheText.Get("STOCK");
+ else {
+ sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]);
+ AsciiToUnicode(gString, gUString);
+ strToPrint = gUString;
+ }
+ }
+ break;
+ case 1:
+ strToPrint = TheText.Get("SECURI");
+ break;
+ case 2:
+ strToPrint = TheText.Get("MOONBM");
+ break;
+ case 3:
+ strToPrint = TheText.Get("COACH");
+ break;
+ case 4:
+ strToPrint = TheText.Get("FLATBED");
+ break;
+ case 5:
+ strToPrint = TheText.Get("LINERUN");
+ break;
+ case 6:
+ strToPrint = TheText.Get("TRASHM");
+ break;
+ case 7:
+ strToPrint = TheText.Get("PATRIOT");
+ break;
+ case 8:
+ strToPrint = TheText.Get("WHOOPEE");
+ break;
+ case 9:
+ strToPrint = TheText.Get("BLISTA");
+ break;
+ case 10:
+ strToPrint = TheText.Get("MULE");
+ break;
+ case 11:
+ strToPrint = TheText.Get("YANKEE");
+ break;
+ case 12:
+ strToPrint = TheText.Get("BOBCAT");
+ break;
+ case 13:
+ strToPrint = TheText.Get("DODO");
+ break;
+ case 14:
+ strToPrint = TheText.Get("BUS");
+ break;
+ case 15:
+ strToPrint = TheText.Get("RUMPO");
+ break;
+ case 16:
+ strToPrint = TheText.Get("PONY");
+ break;
+ case 17:
+ strToPrint = TheText.Get("SENTINL");
+ break;
+ case 18:
+ strToPrint = TheText.Get("CHEETAH");
+ break;
+ case 19:
+ strToPrint = TheText.Get("BANSHEE");
+ break;
+ case 20:
+ strToPrint = TheText.Get("IDAHO");
+ break;
+ case 21:
+ strToPrint = TheText.Get("INFERNS");
+ break;
+ case 22:
+ strToPrint = TheText.Get("TAXI");
+ break;
+ case 23:
+ strToPrint = TheText.Get("KURUMA");
+ break;
+ case 24:
+ strToPrint = TheText.Get("STRETCH");
+ break;
+ case 25:
+ strToPrint = TheText.Get("PEREN");
+ break;
+ case 26:
+ strToPrint = TheText.Get("STINGER");
+ break;
+ case 27:
+ strToPrint = TheText.Get("MANANA");
+ break;
+ case 28:
+ strToPrint = TheText.Get("LANDSTK");
+ break;
+ case 29:
+ strToPrint = TheText.Get("STALION");
+ break;
+ case 30:
+ strToPrint = TheText.Get("BFINJC");
+ break;
+ case 31:
+ strToPrint = TheText.Get("CABBIE");
+ break;
+ case 32:
+ strToPrint = TheText.Get("ESPERAN");
+ break;
+ case 33:
+ strToPrint = TheText.Get("FIRETRK");
+ break;
+ case 34:
+ strToPrint = TheText.Get("AMBULAN");
+ break;
+ case 35:
+ strToPrint = TheText.Get("ENFORCR");
+ break;
+ case 36:
+ strToPrint = TheText.Get("FBICAR");
+ break;
+ case 37:
+ strToPrint = TheText.Get("RHINO");
+ break;
+ case 38:
+ strToPrint = TheText.Get("BARRCKS");
+ break;
+ case 39:
+ strToPrint = TheText.Get("POLICAR");
+ break;
+ default:
+ break;
+ }
+ }
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+
+ const float MAX_SCALE = 1.0f;
+
+ float fScaleY = aMessages[i].m_dist.y / 100.0f;
+ if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
+
+ float fScaleX = aMessages[i].m_dist.x / 100.0f;
+ if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
+
+ CFont::SetScale(fScaleX, fScaleY);
+ CFont::SetCentreOn();
+ CFont::SetCentreSize(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+
+ CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);
+ }
+ NumMessages = 0;
+}
+
+void
+CPickups::Load(uint8 *buffer, uint32 size)
+{
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ CPickup *buf_pickup = (CPickup*)buffer;
+ aPickUps[i] = *buf_pickup;
+
+ if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
+ aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
+
+ buffer += sizeof(CPickup);
+ }
+
+ CollectedPickUpIndex = *(uint16*)buffer;
+ buffer += sizeof(uint16);
+ NumMessages = 0;
+ buffer += sizeof(uint16);
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
+ aPickUpsCollected[i] = *(int32*)buffer;
+ buffer += sizeof(int32);
+ }
+}
+
+void
+CPickups::Save(uint8 *buffer, uint32 *size)
+{
+ *size = sizeof(CPickup) * NUMPICKUPS;
+ *size += sizeof(uint32) * NUMCOLLECTEDPICKUPS + 4;
+
+ for (int32 i = 0; i < NUMPICKUPS; i++) {
+ CPickup *buf_pickup = (CPickup*)buffer;
+ *buf_pickup = aPickUps[i];
+ if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
+ buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1);
+
+ buffer += sizeof(CPickup);
+ }
+
+ *(uint16*)buffer = CollectedPickUpIndex;
+ buffer += sizeof(uint16);
+ *(uint16*)buffer = 0; // possibly was NumMessages
+ buffer += sizeof(uint16);
+
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
+ *(int32*)buffer = aPickUpsCollected[i];
+ buffer += sizeof(int32);
+ }
+}
+
+STARTPATCHES
+ InjectHook(0x430220, CPickups::Init, PATCH_JUMP);
+ InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP);
+ InjectHook(0x432440, CPickups::RenderPickUpText, PATCH_JUMP);
+ InjectHook(0x431C30, CPickups::DoCollectableEffects, PATCH_JUMP);
+ InjectHook(0x431F40, CPickups::DoMoneyEffects, PATCH_JUMP);
+ InjectHook(0x4321C0, CPickups::DoMineEffects, PATCH_JUMP);
+ InjectHook(0x431520, CPickups::DoPickUpEffects, PATCH_JUMP);
+ InjectHook(0x4304B0, CPickups::GenerateNewOne, PATCH_JUMP);
+ InjectHook(0x430660, CPickups::GenerateNewOne_WeaponType, PATCH_JUMP);
+ InjectHook(0x4307A0, CPickups::RemovePickUp, PATCH_JUMP);
+ InjectHook(0x430800, CPickups::RemoveAllFloatingPickups, PATCH_JUMP);
+ InjectHook(0x433D60, CPickups::AddToCollectedPickupsArray, PATCH_JUMP);
+ InjectHook(0x430770, CPickups::IsPickUpPickedUp, PATCH_JUMP);
+ InjectHook(0x430690, CPickups::ModelForWeapon, PATCH_JUMP);
+ InjectHook(0x4306F0, CPickups::WeaponForModel, PATCH_JUMP);
+ InjectHook(0x431510, CPickups::FindColourIndexForWeaponMI, PATCH_JUMP);/**/
+ InjectHook(0x433DF0, CPickups::GetActualPickupIndex, PATCH_JUMP);
+ InjectHook(0x433DB0, CPickups::GetNewUniquePickupIndex, PATCH_JUMP);
+ InjectHook(0x433B60, CPickups::PassTime, PATCH_JUMP);
+ InjectHook(0x4339F0, CPickups::GivePlayerGoodiesWithPickUpMI, PATCH_JUMP);
+ InjectHook(0x433F60, CPickups::Load, PATCH_JUMP);
+ InjectHook(0x433E40, CPickups::Save, PATCH_JUMP);
+ InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP);
+ InjectHook(0x430860, &CPickup::Update, PATCH_JUMP);
+ENDPATCHES
\ No newline at end of file diff --git a/src/control/Pickups.h b/src/control/Pickups.h index 8c2014d6..b49a5544 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -1,59 +1,109 @@ -#pragma once -#include "Weapon.h" - -enum ePickupType -{ - PICKUP_NONE = 0, - PICKUP_IN_SHOP = 1, - PICKUP_ON_STREET = 2, - PICKUP_ONCE = 3, - PICKUP_ONCE_TIMEOUT = 4, - PICKUP_COLLECTABLE1 = 5, - PICKUP_IN_SHOP_OUT_OF_STOCK = 6, - PICKUP_MONEY = 7, - PICKUP_MINE_INACTIVE = 8, - PICKUP_MINE_ARMED = 9, - PICKUP_NAUTICAL_MINE_INACTIVE = 10, - PICKUP_NAUTICAL_MINE_ARMED = 11, - PICKUP_FLOATINGPACKAGE = 12, - PICKUP_FLOATINGPACKAGE_FLOATING = 13, - PICKUP_ON_STREET_SLOW = 14, -}; - -class CEntity; -class CObject; - -class CPickup -{ - ePickupType m_eType; - uint16 m_wQuantity; - CObject *m_pObject; - uint32 m_nTimer; - int16 m_eModelIndex; - int16 m_wIndex; - CVector m_vecPos; -}; - -class CPickups -{ -public: - static void RenderPickUpText(void); - static void DoCollectableEffects(CEntity *ent); - static void DoMoneyEffects(CEntity *ent); - static void DoMineEffects(CEntity *ent); - static void DoPickUpEffects(CEntity *ent); - static void RemoveAllFloatingPickups(); - static int32 GenerateNewOne(CVector, uint32, uint8, uint32); - static int32 GenerateNewOne_WeaponType(CVector, eWeaponType, uint8, uint32); - - static CPickup (&aPickUps)[NUMPICKUPS]; -}; - -extern uint16 AmmoForWeapon[20]; -extern uint16 AmmoForWeapon_OnStreet[20]; - -class CPacManPickups -{ -public: - static void Render(void); -}; +#pragma once
+#include "Weapon.h"
+
+enum ePickupType : uint8
+{
+ PICKUP_NONE = 0,
+ PICKUP_IN_SHOP,
+ PICKUP_ON_STREET,
+ PICKUP_ONCE,
+ PICKUP_ONCE_TIMEOUT,
+ PICKUP_COLLECTABLE1,
+ PICKUP_IN_SHOP_OUT_OF_STOCK,
+ PICKUP_MONEY,
+ PICKUP_MINE_INACTIVE,
+ PICKUP_MINE_ARMED,
+ PICKUP_NAUTICAL_MINE_INACTIVE,
+ PICKUP_NAUTICAL_MINE_ARMED,
+ PICKUP_FLOATINGPACKAGE,
+ PICKUP_FLOATINGPACKAGE_FLOATING,
+ PICKUP_ON_STREET_SLOW,
+ PICKUP_NUMOFTYPES
+};
+
+class CEntity;
+class CObject;
+class CVehicle;
+class CPlayerPed;
+
+class CPickup
+{
+public:
+ ePickupType m_eType;
+ bool m_bRemoved;
+ uint16 m_nQuantity;
+ CObject *m_pObject;
+ uint32 m_nTimer;
+ int16 m_eModelIndex;
+ uint16 m_nIndex;
+ CVector m_vecPos;
+
+ CObject *GiveUsAPickUpObject(int32 handle);
+ bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
+private:
+ bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
+ inline bool CanBePickedUp(CPlayerPed *player);
+ void RemoveKeepType();
+ void Remove();
+};
+
+static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
+
+struct tPickupMessage
+{
+ CVector2D m_pos;
+ eWeaponType m_weaponType;
+ CVector2D m_dist;
+ CRGBA m_color;
+ uint8 m_bOutOfStock : 1;
+ uint8 m_quantity;
+};
+
+class CPickups
+{
+ static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
+ static int16 CollectedPickUpIndex;
+ static int16 NumMessages;
+ static tPickupMessage aMessages[NUMPICKUPMESSAGES];
+public:
+ static void Init();
+ static void Update();
+ static void RenderPickUpText();
+ static void DoCollectableEffects(CEntity *ent);
+ static void DoMoneyEffects(CEntity *ent);
+ static void DoMineEffects(CEntity *ent);
+ static void DoPickUpEffects(CEntity *ent);
+ static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
+ static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
+ static void RemovePickUp(int32 pickupIndex);
+ static void RemoveAllFloatingPickups();
+ static void AddToCollectedPickupsArray(int32 index);
+ static bool IsPickUpPickedUp(int32 pickupId);
+ static int32 ModelForWeapon(eWeaponType weaponType);
+ static enum eWeaponType WeaponForModel(int32 model);
+ static int32 FindColourIndexForWeaponMI(int32 model);
+ static int32 GetActualPickupIndex(int32 index);
+ static int32 GetNewUniquePickupIndex(int32 slot);
+ static void PassTime(uint32 time);
+ static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
+ static void Load(uint8 *buffer, uint32 size);
+ static void Save(uint8 *buffer, uint32 *size);
+
+ static CPickup(&aPickUps)[NUMPICKUPS];
+
+ // unused
+ static bool &bPickUpcamActivated;
+ static CVehicle *&pPlayerVehicle;
+ static CVector &StaticCamCoors;
+ static uint32 &StaticCamStartTime;
+};
+
+extern uint16 AmmoForWeapon[20];
+extern uint16 AmmoForWeapon_OnStreet[20];
+extern uint16 CostOfWeapon[20];
+
+class CPacManPickups
+{
+public:
+ static void Render(void);
+};
diff --git a/src/control/Script.cpp b/src/control/Script.cpp index 885d1d47..db4ef82f 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -130,7 +130,7 @@ void CMissionCleanup::Process() CCarCtrl::CarDensityMultiplier = 1.0; FindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f; TheCamera.Restore(); - TheCamera.SetWidescreenOff(); + TheCamera.SetWideScreenOff(); DMAudio.ClearMissionAudio(); CWeather::ReleaseWeather(); for (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++) @@ -1707,7 +1707,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) ped->SetOrientation(0.0f, 0.0f, 0.0f); CTheScripts::ClearSpaceForMissionEntity(pos, ped); CWorld::Add(ped); - ped->m_level = CTheZones::GetLevelFromPosition(pos); + ped->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); CPopulation::ms_nTotalMissionPeds++; ScriptParams[0] = CPools::GetPedPool()->GetIndex(ped); StoreParameters(&m_nIp, 1); @@ -1948,7 +1948,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command) car->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f; car->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0; car->bEngineOn = false; - car->m_level = CTheZones::GetLevelFromPosition(pos); + car->m_nZoneLevel = CTheZones::GetLevelFromPosition(pos); car->bHasBeenOwnedByPlayer = true; CWorld::Add(car); handle = CPools::GetVehiclePool()->GetIndex(car); @@ -2748,7 +2748,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command) AnimationId anim = pVehicle->bLowVehicle ? ANIM_CAR_LSIT : ANIM_CAR_SIT; pPed->m_pVehicleAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, anim, 100.0f); pPed->StopNonPartialAnims(); - pPed->m_level = CTheZones::GetLevelFromPosition(pPed->GetPosition()); + pPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(pPed->GetPosition()); CWorld::Add(pPed); ScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed); StoreParameters(&m_nIp, 1); |