summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/control/Darkel.cpp331
-rw-r--r--src/control/Darkel.h39
-rw-r--r--src/core/Camera.cpp9
-rw-r--r--src/core/Camera.h1
-rw-r--r--src/core/Stats.cpp13
-rw-r--r--src/core/Stats.h11
-rw-r--r--src/core/Wanted.cpp93
-rw-r--r--src/core/Wanted.h12
-rw-r--r--src/peds/Ped.cpp9
-rw-r--r--src/peds/Ped.h4
-rw-r--r--src/peds/PlayerPed.cpp16
-rw-r--r--src/peds/PlayerPed.h1
-rw-r--r--src/render/WeaponEffects.cpp7
-rw-r--r--src/render/WeaponEffects.h14
-rw-r--r--src/weapons/Weapon.h18
-rw-r--r--src/weapons/WeaponInfo.cpp6
16 files changed, 555 insertions, 29 deletions
diff --git a/src/control/Darkel.cpp b/src/control/Darkel.cpp
index 32d975e0..ab55c4d4 100644
--- a/src/control/Darkel.cpp
+++ b/src/control/Darkel.cpp
@@ -1,12 +1,337 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
#include "Darkel.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"
+int32 &CDarkel::TimeLimit = *(int32*)0x885BAC;
+int32 &CDarkel::PreviousTime = *(int32*)0x885B00;
+int32 &CDarkel::TimeOfFrenzyStart = *(int32*)0x9430D8;
+int32 &CDarkel::WeaponType = *(int32*)0x9430F0;
+int32 &CDarkel::AmmoInterruptedWeapon = *(int32*)0x8E29C8;
+int32 &CDarkel::KillsNeeded = *(int32*)0x8F1AB8;
+int8 &CDarkel::InterruptedWeapon = *(int8*)0x95CD60;
+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;
+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) {
+ if (time >= start && time <= end) {
+ if (time >= start + 500) {
+ if (time <= end - 500)
+ return 0;
+ else
+ return 255 * (end - time) / 500;
+ }
+ else
+ return 255 * (time - start) / 500;
+ }
+ 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()
+{
+ bool DisplayTimers = false;
+
+ switch (Status) {
+ case KILLFRENZY_ONGOING:
+ 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);
+ 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);
+ }
+
+ 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);
+ }
+}
+#endif
+
+void CDarkel::Init()
+{
+ Status = KILLFRENZY_NONE;
+}
+
+int16 CDarkel::QueryModelsKilledByPlayer(int32 modelId)
+{
+ return RegisteredKills[modelId];
+}
-bool CDarkel::Status = *(bool*)0x95CCB4;
bool CDarkel::FrenzyOnGoing()
{
- return Status == 1;
-} \ No newline at end of file
+ return Status == KILLFRENZY_ONGOING;
+}
+
+
+eKillFrenzyStatus CDarkel::ReadStatus()
+{
+ return Status;
+}
+
+#if 1
+WRAPPER int32 CDarkel::RegisterCarBlownUpByPlayer(eKillFrenzyStatus status) { EAXJMP(0x421070); }
+#else
+int32 CDarkel::RegisterCarBlownUpByPlayer(eKillFrenzyStatus status)
+{
+ return 0;
+}
+#endif
+
+#if 1
+WRAPPER void CDarkel::RegisterKillByPlayer(int32 modelid, eWeaponType weapontype, bool flag) { EAXJMP(0x420F60); }
+#else
+void CDarkel::RegisterKillByPlayer(int32 modelid, eWeaponType weapontype, bool flag)
+{
+
+
+}
+#endif
+
+void CDarkel::RegisterKillNotByPlayer()
+{
+ ++CStats::NumberKillFrenziesPassed;
+}
+
+void CDarkel::ResetModelsKilledByPlayer()
+{
+ for (int i = 0; i < 200; i++)
+ RegisteredKills[i] = 0;
+}
+
+#if 0
+WRAPPER void CDarkel::ResetOnPlayerDeath() { EAXJMP(0x420E70); }
+#else
+void CDarkel::ResetOnPlayerDeath()
+{
+ if (Status != KILLFRENZY_ONGOING)
+ return;
+
+ CPopulation::m_AllRandomPedsThisType = -1;
+ Status = KILLFRENZY_FAILED;
+ TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
+
+ if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
+ WeaponType = WEAPONTYPE_UZI;
+
+ if (WeaponType < WEAPONTYPE_TOTALWEAPONS) {
+ FindPlayerPed()->m_bWeaponSlot = 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;
+
+ if (WeaponType < WEAPONTYPE_TOTALWEAPONS) {
+ FindPlayerPed()->m_bWeaponSlot = 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);
+ }
+}
+#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); }
+#else
+void CDarkel::StartFrenzy(eWeaponType weaponType, int32 time, int16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot)
+{
+ if (weaponType == WEAPONTYPE_UZI_DRIVEBY)
+ weaponType = WEAPONTYPE_UZI;
+
+ WeaponType = weaponType;
+ Status = KILLFRENZY_ONGOING;
+ KillsNeeded = kill;
+ ModelToKill = modelId0;
+ ModelToKill2 = modelId2;
+ ModelToKill3 = modelId3;
+ ModelToKill4 = modelId4;
+ pStartMessage = text;
+
+ if (text == TheText.Get("PAGE_00")) {
+ CDarkel::bProperKillFrenzy = 1;
+ CDarkel::pStartMessage = 0;
+ }
+ else
+ bProperKillFrenzy = 0;
+
+ bStandardSoundAndMessages = standardSound;
+ bNeedHeadShot = needHeadShot;
+ TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
+ 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_bWeaponSlot = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_weapons[CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_currentWeapon].m_eWeaponType;
+ FindPlayerPed()->MakeChangesForNewWeapon(FindPlayerPed()->m_bWeaponSlot);
+
+ 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();
+ }
+ }
+ if (CDarkel::bStandardSoundAndMessages)
+ DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_START, 0);
+}
+#endif
+
+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;
+
+ if (PrevTime != PreviousTime) {
+ if (PreviousTime < 12)
+ DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, PrevTime);
+ PreviousTime = PrevTime;
+ }
+
+ }
+ else {
+ CPopulation::m_AllRandomPedsThisType = -1;
+ Status = KILLFRENZY_FAILED;
+ TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
+
+ if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
+ WeaponType = WEAPONTYPE_UZI;
+
+ if (WeaponType < WEAPONTYPE_TOTALWEAPONS) {
+ FindPlayerPed()->m_bWeaponSlot = 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);
+ }
+
+ if (bStandardSoundAndMessages)
+ DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_FAILED, 0);
+ }
+
+ if (KillsNeeded <= 0) {
+ CPopulation::m_AllRandomPedsThisType = -1;
+ Status = KILLFRENZY_PASSED;
+
+ if (bProperKillFrenzy)
+ CStats::AnotherKillFrenzyPassed();
+
+ TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
+
+ FindPlayerPed()->m_pWanted->SetWantedLevel(NOTWANTED);
+
+ if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
+ WeaponType = WEAPONTYPE_UZI;
+
+ if (WeaponType < WEAPONTYPE_TOTALWEAPONS) {
+ FindPlayerPed()->m_bWeaponSlot = 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);
+ }
+
+ if (bStandardSoundAndMessages)
+ DMAudio.PlayFrontEndSound(SOUND_RAMPAGE_PASSED, 0);
+ }
+}
+
+STARTPATCHES
+ /*InjectHook(0x421380, CDarkel::CalcFade, PATCH_JUMP);
+ InjectHook(0x420920, CDarkel::DrawMessages, PATCH_JUMP);
+ InjectHook(0x420E60, CDarkel::FrenzyOnGoing, PATCH_JUMP);
+ InjectHook(0x420650, CDarkel::Init, PATCH_JUMP);
+ InjectHook(0x421370, CDarkel::QueryModelsKilledByPlayer, 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);*/
+ENDPATCHES \ No newline at end of file
diff --git a/src/control/Darkel.h b/src/control/Darkel.h
index ed78d4e1..da1df24a 100644
--- a/src/control/Darkel.h
+++ b/src/control/Darkel.h
@@ -1,11 +1,48 @@
#pragma once
+#include "Weapon.h"
+
+enum eKillFrenzyStatus
+{
+ KILLFRENZY_NONE,
+ KILLFRENZY_ONGOING,
+ KILLFRENZY_PASSED,
+ KILLFRENZY_FAILED,
+};
class CDarkel
{
private:
- static bool Status;
+ static int32 &TimeLimit;
+ static int32 &PreviousTime;
+ static int32 &TimeOfFrenzyStart;
+ static int32 &WeaponType;
+ static int32 &AmmoInterruptedWeapon;
+ static int32 &KillsNeeded;
+ static int8 &InterruptedWeapon;
+ static int8 &bStandardSoundAndMessages;
+ static int8 &bNeedHeadShot;
+ static int8 &bProperKillFrenzy;
+ static eKillFrenzyStatus &Status;
+ static int16 *RegisteredKills;
+ static int32 &ModelToKill;
+ static int32 &ModelToKill2;
+ static int32 &ModelToKill3;
+ static int32 &ModelToKill4;
+ static wchar *pStartMessage;
public:
+ static int32 CalcFade(uint32 time, int32 min, uint32 max);
static void DrawMessages(void);
static bool FrenzyOnGoing();
+ static void Init();
+ static int16 QueryModelsKilledByPlayer(int32 modelId);
+ static eKillFrenzyStatus ReadStatus();
+ static int32 RegisterCarBlownUpByPlayer(eKillFrenzyStatus status);
+ static void RegisterKillByPlayer(int32 modelid, eWeaponType weapontype, bool flag);
+ static void RegisterKillNotByPlayer();
+ 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 Update();
+
};
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 660be333..58e65d24 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -136,6 +136,15 @@ CCamera::RenderMotionBlur(void)
m_motionBlur, m_BlurType, m_imotionBlurAddAlpha);
}
+void
+CCamera::ClearPlayerWeaponMode()
+{
+ PlayerWeaponMode.Mode = 0;
+ PlayerWeaponMode.MaxZoom = 1;
+ PlayerWeaponMode.MinZoom = -1;
+ PlayerWeaponMode.Duration = 0.0f;
+}
+
/*
*
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 84c3060b..db5fff46 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -457,6 +457,7 @@ int m_iModeObbeCamIsInForCar;
void SetMotionBlur(int r, int g, int b, int a, int type);
void SetMotionBlurAlpha(int a);
void RenderMotionBlur(void);
+ void ClearPlayerWeaponMode();
void CalculateDerivedValues(void);
void DrawBordersForWideScreen(void);
diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp
index 3c5b55e4..921586bb 100644
--- a/src/core/Stats.cpp
+++ b/src/core/Stats.cpp
@@ -1,6 +1,13 @@
#include "common.h"
#include "Stats.h"
-int32& CStats::DaysPassed = *(int32*)0x8F2BB8;
-int32& CStats::HeadShots = *(int32*)0x8F647C;
-bool& CStats::CommercialPassed = *(bool*)0x8F4334; \ No newline at end of file
+int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
+int32 &CStats::HeadShots = *(int32*)0x8F647C;
+bool& CStats::CommercialPassed = *(bool*)0x8F4334;
+int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
+int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
+
+void CStats::AnotherKillFrenzyPassed()
+{
+ ++NumberKillFrenziesPassed;
+} \ No newline at end of file
diff --git a/src/core/Stats.h b/src/core/Stats.h
index 39b0e184..a5670020 100644
--- a/src/core/Stats.h
+++ b/src/core/Stats.h
@@ -3,7 +3,12 @@
class CStats
{
public:
- static int32& DaysPassed;
- static int32& HeadShots;
- static bool& CommercialPassed;
+ static int32 &DaysPassed;
+ static int32 &HeadShots;
+ static bool& CommercialPassed;
+ static int32 &NumberKillFrenziesPassed;
+ static int32 &PeopleKilledByOthers;
+
+public:
+ static void AnotherKillFrenzyPassed();
}; \ No newline at end of file
diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp
index ece68e64..21853308 100644
--- a/src/core/Wanted.cpp
+++ b/src/core/Wanted.cpp
@@ -2,6 +2,8 @@
#include "patcher.h"
#include "Wanted.h"
+int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714;
+
bool CWanted::AreSwatRequired()
{
return m_nWantedLevel >= 4;
@@ -33,4 +35,95 @@ int CWanted::NumOfHelisRequired()
default:
return 0;
};
+}
+
+void CWanted::SetWantedLevel(int32 level)
+{
+ ClearQdCrimes();
+ switch (level) {
+ case NOTWANTED:
+ m_nChaos = 0;
+ break;
+ case WANTEDLEVEL_1:
+ m_nChaos = 60;
+ break;
+ case WANTEDLEVEL_2:
+ m_nChaos = 220;
+ break;
+ case WANTEDLEVEL_3:
+ m_nChaos = 420;
+ break;
+ case WANTEDLEVEL_4:
+ m_nChaos = 820;
+ break;
+ case WANTEDLEVEL_5:
+ m_nChaos = 1620;
+ break;
+ case WANTEDLEVEL_6:
+ m_nChaos = 3220;
+ break;
+ default:
+ if (level > MaximumWantedLevel)
+ m_nChaos = MaximumWantedLevel;
+ break;
+ }
+ UpdateWantedLevel();
+}
+
+void CWanted::ClearQdCrimes()
+{
+ for (int i = 0; i < 16; i++) {
+ m_sCrimes[i].m_eCrimeType = CRIME_NONE;
+ };
+}
+
+void CWanted::UpdateWantedLevel()
+{
+ int32 CurrWantedLevel = m_nWantedLevel;
+
+ if (m_nChaos >= 0 && m_nChaos < 40) {
+ m_nWantedLevel = NOTWANTED;
+ m_MaximumLawEnforcerVehicles = 0;
+ m_MaxCops = 0;
+ m_RoadblockDensity = 0;
+ }
+ else if (m_nChaos >= 40 && m_nChaos < 200) {
+ m_nWantedLevel = WANTEDLEVEL_1;
+ m_MaximumLawEnforcerVehicles = 1;
+ m_MaxCops = 1;
+ m_RoadblockDensity = 0;
+ }
+ else if (m_nChaos >= 200 && m_nChaos < 400) {
+ m_nWantedLevel = WANTEDLEVEL_2;
+ m_MaximumLawEnforcerVehicles = 2;
+ m_MaxCops = 3;
+ m_RoadblockDensity = 0;
+ }
+ else if (m_nChaos >= 400 && m_nChaos < 800) {
+ m_nWantedLevel = WANTEDLEVEL_3;
+ m_MaximumLawEnforcerVehicles = 2;
+ m_MaxCops = 4;
+ m_RoadblockDensity = 4;
+ }
+ else if (m_nChaos >= 800 && m_nChaos < 1600) {
+ m_nWantedLevel = WANTEDLEVEL_4;
+ m_MaximumLawEnforcerVehicles = 2;
+ m_MaxCops = 6;
+ m_RoadblockDensity = 8;
+ }
+ else if (m_nChaos >= 1600 && m_nChaos < 3200) {
+ m_nWantedLevel = WANTEDLEVEL_5;
+ m_MaximumLawEnforcerVehicles = 3;
+ m_MaxCops = 8;
+ m_RoadblockDensity = 10;
+ }
+ else if (m_nChaos >= 3200) {
+ m_nWantedLevel = WANTEDLEVEL_6;
+ m_MaximumLawEnforcerVehicles = 3;
+ m_MaxCops = 10;
+ m_RoadblockDensity = 12;
+ }
+
+ if (CurrWantedLevel != m_nWantedLevel)
+ m_nLastWantedLevelChange = CTimer::GetTimeInMilliseconds();
} \ No newline at end of file
diff --git a/src/core/Wanted.h b/src/core/Wanted.h
index aafa9ac0..d14bb905 100644
--- a/src/core/Wanted.h
+++ b/src/core/Wanted.h
@@ -20,11 +20,11 @@ public:
int32 m_nLastUpdateTime;
int32 m_nLastWantedLevelChange;
float m_fCrimeSensitivity;
- uint8 m_bCurrentCops;
- uint8 m_bMaxCops;
- uint8 m_bMaximumLawEnforcerVehicles;
+ uint8 m_CurrentCops;
+ uint8 m_MaxCops;
+ uint8 m_MaximumLawEnforcerVehicles;
int8 field_19;
- int16 m_wRoadblockDensity;
+ int16 m_RoadblockDensity;
uint8 m_IsIgnoredByCops : 1;
uint8 m_IsIgnoredByEveryOne : 1;
uint8 m_IsSwatRequired : 1;
@@ -34,12 +34,16 @@ public:
int32 m_nWantedLevel;
CCrime m_sCrimes[16];
CCopPed *m_pCops[10];
+ static int32 &MaximumWantedLevel;
public:
bool AreSwatRequired();
bool AreFbiRequired();
bool AreArmyRequired();
int NumOfHelisRequired();
+ void SetWantedLevel(int32);
+ void ClearQdCrimes();
+ void UpdateWantedLevel();
};
static_assert(sizeof(CWanted) == 0x204, "CWanted: error");
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 80ef53ee..e4cc848e 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -41,6 +41,7 @@ WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); }
WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); }
WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); }
WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); }
+WRAPPER void CPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); }
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
@@ -456,9 +457,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
}
m_maxWeaponTypeAllowed = 0;
m_currentWeapon = 0;
- m_storedWeapon = NO_STORED_WEAPON;
+ m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
- for(int i = 0; i < NUM_PED_WEAPONTYPES; i++)
+ for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++)
{
CWeapon &weapon = GetWeapon(i);
weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
@@ -1427,9 +1428,9 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
// Only uzi can be used on cars, so previous weapon was stored
if (ped->IsPlayer() && weaponType == WEAPONTYPE_UZI) {
- if (ped->m_storedWeapon != NO_STORED_WEAPON) {
+ if (ped->m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
ped->SetCurrentWeapon(ped->m_storedWeapon);
- ped->m_storedWeapon = NO_STORED_WEAPON;
+ ped->m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
}
} else {
ped->AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 95731e15..0493eeee 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -351,7 +351,7 @@ public:
uint8 pad_351[3];
uint32 m_timerUnused;
CEntity *m_targetUnused;
- CWeapon m_weapons[NUM_PED_WEAPONTYPES];
+ CWeapon m_weapons[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS];
eWeaponType m_storedWeapon;
uint8 m_currentWeapon; // eWeaponType
uint8 m_maxWeaponTypeAllowed; // eWeaponType
@@ -465,6 +465,8 @@ public:
void RegisterThreatWithGangPeds(CEntity*);
bool TurnBody(void);
void Chat(void);
+ void MakeChangesForNewWeapon(int8);
+
// Static methods
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset);
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 2d67d5b2..7eb01db0 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -1,6 +1,8 @@
#include "common.h"
#include "patcher.h"
#include "PlayerPed.h"
+#include "Camera.h"
+#include "WeaponEffects.h"
CPlayerPed::~CPlayerPed()
{
@@ -9,6 +11,18 @@ CPlayerPed::~CPlayerPed()
WRAPPER void CPlayerPed::ReApplyMoveAnims(void) { EAXJMP(0x4F07C0); }
+void CPlayerPed::ClearWeaponTarget()
+{
+ if (!m_nPedType) {
+ m_pPointGunAt = 0;
+ TheCamera.ClearPlayerWeaponMode();
+ CWeaponEffects::ClearCrosshair();
+ }
+ ClearPointGunAt();
+}
+
STARTPATCHES
- InjectHook(0x4EFB30, &CPlayerPed::dtor, PATCH_JUMP);
+InjectHook(0x4EFB30, &CPlayerPed::dtor, PATCH_JUMP);
+InjectHook(0x4F28A0, &CPlayerPed::ClearWeaponTarget, PATCH_JUMP);
+
ENDPATCHES \ No newline at end of file
diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h
index 15ad74a6..4f325da3 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -43,6 +43,7 @@ public:
void dtor(void) { this->CPlayerPed::~CPlayerPed(); }
void ReApplyMoveAnims(void);
+ void ClearWeaponTarget();
};
static_assert(sizeof(CPlayerPed) == 0x5F0, "CPlayerPed: error");
diff --git a/src/render/WeaponEffects.cpp b/src/render/WeaponEffects.cpp
index a1a6d25a..e062da07 100644
--- a/src/render/WeaponEffects.cpp
+++ b/src/render/WeaponEffects.cpp
@@ -3,3 +3,10 @@
#include "WeaponEffects.h"
WRAPPER void CWeaponEffects::Render(void) { EAXJMP(0x564D70); }
+
+CWeaponEffects &gCrossHair = *(CWeaponEffects*)0x6503BC;
+
+void CWeaponEffects::ClearCrosshair()
+{
+ gCrossHair.m_bCrosshair = false;
+}
diff --git a/src/render/WeaponEffects.h b/src/render/WeaponEffects.h
index 63c8fd7d..7176c26d 100644
--- a/src/render/WeaponEffects.h
+++ b/src/render/WeaponEffects.h
@@ -3,5 +3,19 @@
class CWeaponEffects
{
public:
+ bool m_bCrosshair;
+ int8 gap_1[3];
+ CVector m_vecPos;
+ int8 field_16;
+ int8 field_17;
+ int8 field_18;
+ int8 field_19;
+ float field_20;
+ int32 field_24;
+ RwTexture *m_pTexture;
+ RwRaster *m_pRaster;
+
+public:
static void Render(void);
+ static void ClearCrosshair();
};
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index ba552035..81516c4e 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -1,9 +1,9 @@
#pragma once
#include "Entity.h"
-enum eWeaponType : uint32
+enum eWeaponType
{
- WEAPONTYPE_UNARMED = 0,
+ WEAPONTYPE_UNARMED,
WEAPONTYPE_BASEBALLBAT,
WEAPONTYPE_COLT45,
WEAPONTYPE_UZI,
@@ -16,10 +16,16 @@ enum eWeaponType : uint32
WEAPONTYPE_MOLOTOV,
WEAPONTYPE_GRENADE,
WEAPONTYPE_DETONATOR,
- NUM_PED_WEAPONTYPES = 13,
- WEAPONTYPE_HELICANNON = 13,
- NUM_WEAPONTYPES,
- NO_STORED_WEAPON = 22
+ WEAPONTYPE_TOTAL_INVENTORY_WEAPONS,
+ WEAPONTYPE_TOTALWEAPONS,
+ WEAPONTYPE_ARMOUR,
+ WEAPONTYPE_RAMMEDBYCAR,
+ WEAPONTYPE_RUNOVERBYCAR,
+ WEAPONTYPE_EXPLOSION,
+ WEAPONTYPE_UZI_DRIVEBY,
+ WEAPONTYPE_WATER,
+ WEAPONTYPE_FALL_DAMAGE,
+ WEAPONTYPE_UNIDENTIFIED,
};
enum eWeaponFire {
diff --git a/src/weapons/WeaponInfo.cpp b/src/weapons/WeaponInfo.cpp
index 5be18c3c..6884d347 100644
--- a/src/weapons/WeaponInfo.cpp
+++ b/src/weapons/WeaponInfo.cpp
@@ -6,7 +6,7 @@
#include "AnimBlendAssociation.h"
//CWeaponInfo (&CWeaponInfo::ms_apWeaponInfos)[14] = * (CWeaponInfo(*)[14]) * (uintptr*)0x6503EC;
-CWeaponInfo CWeaponInfo::ms_apWeaponInfos[NUM_WEAPONTYPES];
+CWeaponInfo CWeaponInfo::ms_apWeaponInfos[WEAPONTYPE_TOTALWEAPONS];
static char ms_aWeaponNames[][32] = {
"Unarmed",
@@ -34,7 +34,7 @@ void
CWeaponInfo::Initialise(void)
{
debug("Initialising CWeaponInfo...\n");
- for (int i = 0; i < NUM_WEAPONTYPES; i++) {
+ for (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {
ms_apWeaponInfos[i].m_eWeaponFire = WEAPON_FIRE_INSTANT_HIT;
ms_apWeaponInfos[i].m_AnimToPlay = ANIM_PUNCH_R;
ms_apWeaponInfos[i].m_Anim2ToPlay = NUM_ANIMS;
@@ -176,7 +176,7 @@ CWeaponInfo::LoadWeaponData(void)
eWeaponType
CWeaponInfo::FindWeaponType(char *name)
{
- for (int i = 0; i < NUM_WEAPONTYPES; i++) {
+ for (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {
if (strcmp(ms_aWeaponNames[i], name) == 0) {
return static_cast<eWeaponType>(i);
}