Skip to content

Commit d047718

Browse files
committed
Added Crossing Challenge component
Allows to set starting and ending point; controls respawning at the start on death and shows a congratulatory message upon reaching the end. Also fixed a few bugs in the process.
1 parent dc566a5 commit d047718

File tree

8 files changed

+797
-6
lines changed

8 files changed

+797
-6
lines changed

ChaosMod/Components/CrossingChallenge.cpp

Lines changed: 616 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#pragma once
2+
3+
#include <list>
4+
5+
#include "Component.h"
6+
#include "Util/OptionsFile.h"
7+
#include "Util/Text.h"
8+
9+
#define SPLASH_TEXT_DUR_SECS 10
10+
11+
class CrossingChallenge : public Component
12+
{
13+
private:
14+
struct WeaponInfo
15+
{
16+
Hash hash;
17+
int ammo;
18+
};
19+
20+
OptionsFile m_ConfigFile { "chaosmod/configs/crossing.ini", { "chaosmod/crossing.ini" } };
21+
22+
bool m_Enabled = false;
23+
24+
int m_HelpMessageTick = -1;
25+
26+
bool m_CaptureStartFlag = false;
27+
bool m_CaptureEndFlag = false;
28+
29+
int m_StartedState = 0;
30+
31+
bool m_WaitingConfirm = false;
32+
33+
bool m_StartEnabled = false;
34+
Vector3 m_StartLocation = Vector3();
35+
Hash m_StartVehicleHash = 0;
36+
float m_StartHeading = 0.f;
37+
float m_StartCameraHeading = 0.f;
38+
Hash m_StartWeatherType1 = 0;
39+
Hash m_StartWeatherType2 = 0;
40+
float m_StartWeatherPercent = 0.f;
41+
int m_ClockHours = 0;
42+
int m_ClockMinutes = 0;
43+
int m_ClockSeconds = 0;
44+
std::vector<WeaponInfo> m_StartWeapons;
45+
46+
bool m_EndEnabled = false;
47+
Vector3 m_EndLocation = Vector3();
48+
float m_EndRadius = 0.f;
49+
50+
int m_ButtonsScaleformHandle = 0;
51+
bool m_ButtonsScaleformLoading = false;
52+
53+
int m_PassedScaleformHandle = 0;
54+
bool m_PassedScaleformLoading = false;
55+
int m_PassedScaleformTick = 0;
56+
bool m_PassedTransitionStarted = false;
57+
58+
Blip m_StartBlip = 0;
59+
Blip m_EndBlip = 0;
60+
61+
DWORD m_TickCount = 0;
62+
DWORD m_LastTick = 0;
63+
int m_EffectsCount = 0;
64+
bool m_TimerStarted = 0;
65+
66+
void ShowHint(const std::string &text);
67+
68+
void SetStartParams();
69+
void ControlRespawn();
70+
71+
int m_PassedState = 0;
72+
73+
bool CheckEndReached() const;
74+
void ShowPassedScaleform();
75+
void ControlPassed();
76+
77+
void SaveConfig();
78+
79+
void CaptureStart();
80+
void CaptureEnd();
81+
void IncreaseEndRadius();
82+
void DecreaseEndRadius();
83+
bool IsEndValid() const;
84+
void ShowEndCylinder() const;
85+
void ShowHelpButtons();
86+
void ShowBlips();
87+
88+
void ShowProgress() const;
89+
90+
public:
91+
CrossingChallenge();
92+
93+
virtual void OnRun() override;
94+
virtual void OnModPauseCleanup() override;
95+
virtual void OnKeyInput(DWORD key, bool repeated, bool isUpNow, bool isCtrlPressed, bool isShiftPressed,
96+
bool isAltPressed) override;
97+
inline void IncrementEffects()
98+
{
99+
m_EffectsCount++;
100+
}
101+
102+
template <class T>
103+
requires std::is_base_of_v<Component, T>
104+
friend struct ComponentHolder;
105+
};

ChaosMod/Components/EffectDispatchTimer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ void EffectDispatchTimer::ResetTimer()
130130
{
131131
m_TimerPercentage = 0.f;
132132
m_Timer = GetTickCount64();
133+
m_DistanceChaosState.SavedPosition = GET_ENTITY_COORDS(PLAYER_PED_ID(), false);
133134
}
134135

135136
int EffectDispatchTimer::GetRemainingTimerTime() const

ChaosMod/Components/EffectDispatcher.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <stdafx.h>
22

3+
#include "Components/CrossingChallenge.h"
34
#include "Components/EffectDispatchTimer.h"
45
#include "Components/EffectDispatcher.h"
56
#include "Components/EffectSound/EffectSoundManager.h"
@@ -525,6 +526,8 @@ void EffectDispatcher::DispatchEffect(const EffectIdentifier &effectId, Dispatch
525526
const std::string &suffix)
526527
{
527528
EffectDispatchQueue.push({ .Id = effectId, .Suffix = suffix, .Flags = dispatchEffectFlags });
529+
if (ComponentExists<CrossingChallenge>())
530+
GetComponent<CrossingChallenge>()->IncrementEffects();
528531
}
529532

530533
void EffectDispatcher::DispatchRandomEffect(DispatchEffectFlags dispatchEffectFlags, const std::string &suffix)

ChaosMod/Main.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Main.h"
44

5+
#include "Components/CrossingChallenge.h"
56
#include "Components/DebugMenu.h"
67
#include "Components/DebugSocket.h"
78
#include "Components/EffectDispatchTimer.h"
@@ -31,6 +32,7 @@ static struct
3132
bool ClearEffectsShortcutEnabled = false;
3233
bool ToggleModShortcutEnabled = false;
3334
bool ToggleModState = false;
35+
bool DisableMod = false;
3436
bool PauseTimerShortcutEnabled = false;
3537
bool HaveLateHooksRan = false;
3638
bool AntiSoftlockShortcutEnabled = false;
@@ -204,6 +206,8 @@ static void Init()
204206

205207
INIT_COMPONENT("HelpTextQueue", "script help text queue", HelpTextQueue);
206208

209+
INIT_COMPONENT("CrossingChallenge", "Crossing Challenge", CrossingChallenge);
210+
207211
#ifdef WITH_DEBUG_PANEL_SUPPORT
208212
if (DoesFeatureFlagExist("enabledebugsocket"))
209213
INIT_COMPONENT("DebugSocket", "Debug Websocket", DebugSocket);
@@ -227,6 +231,15 @@ static void MainRun()
227231

228232
ms_Flags.ToggleModState = g_OptionsManager.GetConfigValue({ "DisableStartup" }, OPTION_DEFAULT_DISABLE_STARTUP);
229233

234+
if (!g_Components.empty())
235+
{
236+
for (auto component : g_Components)
237+
component->OnModPauseCleanup();
238+
239+
g_Components.clear();
240+
}
241+
ClearEntityPool();
242+
230243
Init();
231244

232245
bool isDisabled = false;
@@ -246,10 +259,8 @@ static void MainRun()
246259
}
247260
}
248261

249-
if (ms_Flags.ToggleModState)
262+
if (ms_Flags.ToggleModState || ms_Flags.DisableMod)
250263
{
251-
ms_Flags.ToggleModState = false;
252-
253264
if (!isDisabled)
254265
{
255266
isDisabled = true;
@@ -273,7 +284,7 @@ static void MainRun()
273284
for (auto component : g_Components)
274285
component->OnModPauseCleanup();
275286
}
276-
else
287+
else if (ms_Flags.ToggleModState)
277288
{
278289
isDisabled = false;
279290

@@ -288,6 +299,9 @@ static void MainRun()
288299
// Restart the main part of the mod completely
289300
Init();
290301
}
302+
303+
ms_Flags.ToggleModState = false;
304+
ms_Flags.DisableMod = false;
291305
}
292306

293307
if (isDisabled)
@@ -323,8 +337,8 @@ static void MainRun()
323337

324338
for (auto component : g_Components)
325339
component->OnRun();
340+
}
326341
}
327-
}
328342

329343
namespace Main
330344
{
@@ -337,6 +351,8 @@ namespace Main
337351

338352
void OnCleanup()
339353
{
354+
for (auto component : g_Components)
355+
component->OnModPauseCleanup();
340356
}
341357

342358
void OnKeyboardInput(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore,
@@ -391,4 +407,9 @@ namespace Main
391407
for (auto component : g_Components)
392408
component->OnKeyInput(key, wasDownBefore, isUpNow, isCtrlPressed, isShiftPressed, isWithAlt);
393409
}
410+
411+
void Stop()
412+
{
413+
ms_Flags.DisableMod = true;
414+
}
394415
}

ChaosMod/Main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ namespace Main
1313
void OnCleanup();
1414
void OnKeyboardInput(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore,
1515
BOOL isUpNow);
16+
void Stop();
1617
}

ChaosMod/Util/OptionsFile.h

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ class OptionsFile
1313
{
1414
private:
1515
const char *m_FileName;
16+
const char *m_FoundFileName;
1617
std::vector<const char *> m_CompatFileNames;
1718
std::unordered_map<std::string, std::string> m_Options;
1819

1920
public:
2021
OptionsFile(const char *fileName, std::vector<const char *> compatFileNames = {})
21-
: m_FileName(fileName), m_CompatFileNames(compatFileNames)
22+
: m_FileName(fileName), m_CompatFileNames(compatFileNames), m_FoundFileName("")
2223
{
2324
Reset();
2425
}
@@ -57,13 +58,33 @@ class OptionsFile
5758
bool dataRead = false;
5859
for (auto compatFileName : m_CompatFileNames)
5960
if ((dataRead = readData(compatFileName)))
61+
{
62+
m_FoundFileName = compatFileName;
6063
break;
64+
}
6165

6266
if (!dataRead)
6367
LOG("Config file " << m_FileName << " not found!");
6468
}
6569
}
6670

71+
inline void WriteFile()
72+
{
73+
std::ofstream file(m_FoundFileName, std::ofstream::out | std::ofstream::trunc);
74+
if (!file)
75+
{
76+
LOG("Couldn't write config file " << m_FileName);
77+
return;
78+
}
79+
for (auto &[key, value] : m_Options)
80+
file << key << "=" << value << std::endl;
81+
}
82+
83+
template <typename T> inline T ReadValue(const std::string &key, T defaultValue) const
84+
{
85+
return ReadValue(std::vector<std::string> { key }, defaultValue);
86+
}
87+
6788
template <typename T> inline T ReadValue(const std::vector<std::string> &keys, T defaultValue) const
6889
{
6990
for (const auto &key : keys)
@@ -93,4 +114,20 @@ class OptionsFile
93114

94115
return defaultValue;
95116
}
117+
118+
inline void SetValueString(const std::string& szKey, const std::string& value)
119+
{
120+
if (m_Options.contains(szKey))
121+
{
122+
m_Options[szKey] = value;
123+
}
124+
else
125+
{
126+
m_Options.emplace(szKey, value);
127+
}
128+
}
129+
template <typename T> inline void SetValue(const std::string& szKey, T value)
130+
{
131+
SetValueString(szKey, std::to_string(value));
132+
}
96133
};

ConfigApp/Tabs/MiscTab.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class MiscTab : Tab
2929
private CheckBox? m_EnableDistanceBasedDispatch = null;
3030
private TextBox? m_DistanceBasedDispatchDistance = null;
3131
private ComboBox? m_DistanceBasedDispatchType = null;
32+
private CheckBox? m_EnableCrossingChallenge = null;
3233

3334
private static ColorPicker GenerateCommonColorPicker(Color defaultColor)
3435
{
@@ -125,6 +126,9 @@ protected override void InitContent()
125126
"Displacement"
126127
}
127128
});
129+
grid.PopRow();
130+
131+
grid.PushRowSpacedPair("Enable Crossing Challenge™", m_EnableCrossingChallenge = Utils.GenerateCommonCheckBox());
128132

129133
scrollViewer.Content = grid.Grid;
130134

@@ -182,6 +186,8 @@ public override void OnLoadValues()
182186
m_DistanceBasedDispatchDistance.Text = OptionsManager.ConfigFile.ReadValue("DistanceToActivateEffect", "250");
183187
if (m_DistanceBasedDispatchType is not null)
184188
m_DistanceBasedDispatchType.SelectedIndex = OptionsManager.ConfigFile.ReadValueInt("DistanceType", 0);
189+
if (m_EnableCrossingChallenge is not null)
190+
m_EnableCrossingChallenge.IsChecked = OptionsManager.ConfigFile.ReadValueBool("EnableCrossingChallenge", false);
185191
}
186192

187193
public override void OnSaveValues()
@@ -208,6 +214,7 @@ public override void OnSaveValues()
208214
OptionsManager.ConfigFile.WriteValue("EnableDistanceBasedEffectDispatch", m_EnableDistanceBasedDispatch?.IsChecked);
209215
OptionsManager.ConfigFile.WriteValue("DistanceToActivateEffect", m_DistanceBasedDispatchDistance?.Text);
210216
OptionsManager.ConfigFile.WriteValue("DistanceType", m_DistanceBasedDispatchType?.SelectedIndex);
217+
OptionsManager.ConfigFile.WriteValue("EnableCrossingChallenge", m_EnableCrossingChallenge?.IsChecked);
211218
}
212219
}
213220
}

0 commit comments

Comments
 (0)