Skip to content

Commit 6378ce9

Browse files
committed
campaignid only for non official missions
1 parent ffa0f9f commit 6378ce9

3 files changed

Lines changed: 155 additions & 0 deletions

File tree

src/Misc/SavedGamesInSubdir.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
#include <Utilities/Macro.h>
2323
#include <Spawner/Spawner.h>
2424

25+
#include <HouseClass.h>
26+
#include <AnimClass.h>
27+
2528
#include <filesystem>
29+
#include <optional>
2630

2731
namespace SavedGames
2832
{
@@ -161,3 +165,151 @@ DEFINE_HOOK(0x67FD26, LoadOptionsClass_ReadSaveInfo_SGInSubdir, 0x5)
161165

162166
return 0;
163167
}
168+
169+
170+
namespace SavedGames
171+
{
172+
//issue #18
173+
struct CampaignID
174+
{
175+
static constexpr wchar_t* SaveName = L"Campaign ID";
176+
177+
int Number;
178+
explicit CampaignID() :
179+
Number { SessionClass::IsCampaign() ? Spawner::GetConfig()->CampaignID : 0 }
180+
{
181+
}
182+
183+
operator int () const
184+
{
185+
return Number;
186+
}
187+
188+
CampaignID(noinit_t()) { }
189+
};
190+
191+
// More fun
192+
struct ExtraMetaInfo
193+
{
194+
static constexpr wchar_t* SaveName = L"Spawner extra info";
195+
196+
int CurrentFrame;
197+
int PlayerCount;
198+
int TechnoCount;
199+
int AnimCount;
200+
201+
explicit ExtraMetaInfo()
202+
:CurrentFrame { Unsorted::CurrentFrame }
203+
, PlayerCount { HouseClass::Array->Count }
204+
, TechnoCount { TechnoClass::Array->Count }
205+
, AnimCount { AnimClass::Array->Count }
206+
{
207+
}
208+
209+
ExtraMetaInfo(noinit_t()) { }
210+
};
211+
212+
template<typename T>
213+
bool AppendToStorage(IStorage* pStorage)
214+
{
215+
IStream* pStream = nullptr;
216+
bool ret = false;
217+
HRESULT hr = pStorage->CreateStream(
218+
T::SaveName,
219+
STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
220+
0,
221+
0,
222+
&pStream
223+
);
224+
225+
if (SUCCEEDED(hr) && pStream != nullptr)
226+
{
227+
T info {};
228+
ULONG written = 0;
229+
hr = pStream->Write(&info, sizeof(info), &written);
230+
ret = SUCCEEDED(hr) && written == sizeof(info);
231+
pStream->Release();
232+
}
233+
234+
return ret;
235+
}
236+
237+
238+
template<typename T>
239+
std::optional<T> ReadFromStorage(IStorage* pStorage)
240+
{
241+
IStream* pStream = nullptr;
242+
bool hasValue = false;
243+
HRESULT hr = pStorage->OpenStream(
244+
T::SaveName,
245+
NULL,
246+
STGM_READ | STGM_SHARE_EXCLUSIVE,
247+
0,
248+
&pStream
249+
);
250+
251+
T info;
252+
253+
if (SUCCEEDED(hr) && pStream != nullptr)
254+
{
255+
ULONG read = 0;
256+
hr = pStream->Read(&info, sizeof(info), &read);
257+
hasValue = SUCCEEDED(hr) && read == sizeof(info);
258+
259+
pStream->Release();
260+
}
261+
262+
return hasValue ? std::make_optional(info) : std::nullopt;
263+
}
264+
265+
}
266+
267+
// Write : A la fin
268+
DEFINE_HOOK(0x67D2E3, GameSave_AdditionalInfoForClient, 0x6)
269+
{
270+
GET_STACK(IStorage*, pStorage, STACK_OFFSET(0x4A0, -0x490));
271+
using namespace SavedGames;
272+
273+
if (pStorage)
274+
{
275+
if (CampaignID {} != 0)
276+
AppendToStorage<CampaignID>(pStorage);
277+
if (AppendToStorage<ExtraMetaInfo>(pStorage))
278+
Debug::Log("[Spawner] Extra meta info appended on sav file\n");
279+
}
280+
281+
return 0;
282+
}
283+
284+
// Read : Au debut
285+
DEFINE_HOOK(0x67E4DC, LoadGame_AdditionalInfoForClient, 0x7)
286+
{
287+
LEA_STACK(const wchar_t*, filename, STACK_OFFSET(0x518, -0x4F4));
288+
IStorage* pStorage = nullptr;
289+
using namespace SavedGames;
290+
291+
if (SUCCEEDED(StgOpenStorage(filename,NULL,
292+
STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
293+
0,0,&pStorage)
294+
))
295+
{
296+
if (auto id = ReadFromStorage<CampaignID>(pStorage))
297+
{
298+
int num = id.value().Number;
299+
Debug::Log("[Spawner] sav file CampaignID = %d\n", num);
300+
Spawner::GetConfig()->CampaignID = num;
301+
}
302+
if (auto info = ReadFromStorage<ExtraMetaInfo>(pStorage))
303+
{
304+
Debug::Log("[Spawner] CurrentFrame = %d, TechnoCount = %d, AnimCount = %d \n"
305+
, info.value().CurrentFrame
306+
, info.value().TechnoCount
307+
, info.value().AnimCount
308+
);
309+
}
310+
}
311+
if (pStorage)
312+
pStorage->Release();
313+
314+
return 0;
315+
}

src/Spawner/Spawner.Config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void SpawnerConfig::LoadFromINIFile(CCINIClass* pINI)
5555
LoadSaveGame = pINI->ReadBool(pSettingsSection, "LoadSaveGame", LoadSaveGame);
5656
/* SavedGameDir */ pINI->ReadString(pSettingsSection, "SavedGameDir", SavedGameDir, SavedGameDir, sizeof(SavedGameDir));
5757
/* SaveGameName */ pINI->ReadString(pSettingsSection, "SaveGameName", SaveGameName, SaveGameName, sizeof(SaveGameName));
58+
CampaignID = pINI->ReadInteger(pSettingsSection, "CampaignID", 0);
5859

5960
{ // Scenario Options
6061
Seed = pINI->ReadInteger(pSettingsSection, "Seed", Seed);

src/Spawner/Spawner.Config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class SpawnerConfig
9494
bool LoadSaveGame;
9595
char SavedGameDir[MAX_PATH]; // Nested paths are also supported, e.g. "Saved Games\\Yuri's Revenge"
9696
char SaveGameName[60];
97+
int CampaignID;
9798

9899
// Scenario Options
99100
int Seed;
@@ -161,6 +162,7 @@ class SpawnerConfig
161162
, LoadSaveGame { false }
162163
, SavedGameDir { "Saved Games" }
163164
, SaveGameName { "" }
165+
, CampaignID { 0 }
164166

165167
// Scenario Options
166168
, Seed { 0 }

0 commit comments

Comments
 (0)