forked from Mirrors/openclonk
Added scenario achievements displayed as small symbols beside the scenario name in the startup selection screen.
They can be used e.g. to show that you have finished a scenario on different difficulty levels.issue1247
parent
378bda5546
commit
abab7be591
|
@ -457,6 +457,8 @@ set(OC_CLONK_SOURCES
|
|||
src/player/C4PlayerList.h
|
||||
src/player/C4RankSystem.cpp
|
||||
src/player/C4RankSystem.h
|
||||
src/player/C4ScenarioParameters.cpp
|
||||
src/player/C4ScenarioParameters.h
|
||||
src/script/C4AulDebug.cpp
|
||||
src/script/C4AulDebug.h
|
||||
thirdparty/timsort/sort.h
|
||||
|
|
|
@ -47,6 +47,12 @@
|
|||
<col>Value of default option that is chosen if the user does not select anything.</col>
|
||||
<col>0</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>Achievement</col>
|
||||
<col>String</col>
|
||||
<col>If set to an achievement ID, this parameter is hidden in the selection dialogue and only used to track player achievements for this scenario. See section below.</col>
|
||||
<col></col>
|
||||
</row>
|
||||
</table>
|
||||
</text>
|
||||
<text>Each parameter of type Enumeration should be followed by subordinate section [Options], which contains several subordinate sections [Option]. Subordinate sections need to be indented further than their parent section.</text>
|
||||
|
@ -79,6 +85,11 @@
|
|||
</row>
|
||||
</table>
|
||||
</text>
|
||||
<h>Achievements</h>
|
||||
<text>Scenario achievements are special parameter definitions for which the values are stored per player and per scenario. These parameters cannot be set maually, but can only be gained in game using the <funclink>GainScenarioAchievement</funclink> function. Each achievement that has been gained is represented by a small image beside the scenario title in the scenario selection dialogue.</text>
|
||||
<text>Achievements need to be defined as parameter definition with the Achievement value set in the [ParameterDef] section. The value corresponds to the icon file name formatted as Achv*.png, where * is replaced by the achievement name. The icon may either be placed in the scenario or - if multiple scenarios share the same icon - in the global Graphics.ocg file. Icons are square with the height determining the dimensions.</text>
|
||||
<text>By using achievement values higher than one, multiple stages of an achievement may be defined e.g. for finishing a scenario on different difficulties. The achievement value denotes the 1-based index in the icon file with multiple icons arranged from left to right.</text>
|
||||
<text>If several players are activated while the scenario selection dialogue is opened, the player with the highest achievement value is considered for each achievement.</text>
|
||||
<h>Example</h>
|
||||
<text>Example ParameterDef.txt file for a difficulty setting in a scenario that controls the amount of meteorites:</text>
|
||||
<code>[ParameterDef]
|
||||
|
@ -95,19 +106,40 @@ Default=15
|
|||
[Option]
|
||||
Name=$Hard$
|
||||
Description=$DescHard$
|
||||
Value=100</code>
|
||||
Value=100
|
||||
|
||||
[ParameterDef]
|
||||
ID=Done
|
||||
Achievement=Done
|
||||
[Options]
|
||||
|
||||
[Option]
|
||||
Description=$AchvEasy$
|
||||
Value=1
|
||||
|
||||
[Option]
|
||||
Description=$AchvHard$
|
||||
Value=3</code>
|
||||
<text>The names and descriptions are localized strings which can be set for English in a StringTblUS.txt:</text>
|
||||
<code>Difficulty=Difficulty
|
||||
Easy=Easy
|
||||
Hard=Hard
|
||||
DescDifficulty=Conrols the amount of meteorites
|
||||
DescEasy=Very few meteorites
|
||||
DescHard=Lots of meteorites</code>
|
||||
<text>Finally, the Script.c file of the scenario should contain code to evaluate the setting:</text>
|
||||
DescHard=Lots of meteorites
|
||||
AchvEasy=Finished on easy.
|
||||
AchvHard=Finished on hard.</code>
|
||||
<text>Finally, the Script.c file of the scenario should contain code to evaluate the setting and give an achievement accordingly:</text>
|
||||
<code>func Initialize()
|
||||
{
|
||||
// Meteorite amount depending on difficulty setting
|
||||
Meteor->SetChance(SCENPAR_Difficulty);
|
||||
}
|
||||
|
||||
func OnGoalsFulfilled()
|
||||
{
|
||||
<funclink>GainScenarioAchievement</funclink>("Done", BoundBy(SCENPAR_Difficulty, 1, 3)); // 1 for easy, 3 for hard
|
||||
return false;
|
||||
}</code>
|
||||
<author>Sven2</author><date>2014-09</date>
|
||||
</doc>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE funcs
|
||||
SYSTEM '../../../clonk.dtd'>
|
||||
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
|
||||
<funcs>
|
||||
<func>
|
||||
<title>GainScenarioAchievement</title>
|
||||
<category>Player</category>
|
||||
<version>5.4 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>string</type>
|
||||
<name>id</name>
|
||||
<desc>ID of achievement to gain. Must be defined as a custom scenario parameter for the scenario.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>value</type>
|
||||
<name>int</name>
|
||||
<desc>Value to set for this achievement. Defaults to 1.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
<param>
|
||||
<type>player</type>
|
||||
<name>int</name>
|
||||
<desc>Value to set for this achievement. If nil or NO_OWNER, the achievement is gained for all player currently in the game.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
<param>
|
||||
<type>string</type>
|
||||
<name>scenario_name</name>
|
||||
<desc>Can be set to the filename of another scenario to gain an achievement for that scenario. Scenario paths contain all .oc* paths, e.g. "Missions.ocf\Raid.ocs". Defaults to the filename of the current scenario or its origin.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Gain a scenario achievement. Gained achievements are represented as small symbols beside the scenario name in the selection screen.</desc>
|
||||
<remark>Make sure the gain the achievement before players are saved, i.e. before the game is evaluated. Otherwise, gained achievements are not stored.</remark>
|
||||
<related><funclink>GainMissionAccess</funclink></related>
|
||||
<related><emlink href="scenario/ParameterDefs.xml">Scenario parameter definitions</emlink></related>
|
||||
</func>
|
||||
<author>Sven2</author><date>2014-09</date>
|
||||
</funcs>
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
|
@ -14,3 +14,16 @@ Default=1
|
|||
Name=$Hard$
|
||||
Description=$DescHard$
|
||||
Value=99
|
||||
|
||||
[ParameterDef]
|
||||
ID=Done
|
||||
Achievement=Done
|
||||
[Options]
|
||||
|
||||
[Option]
|
||||
Description=$AchvEasy$
|
||||
Value=1
|
||||
|
||||
[Option]
|
||||
Description=$AchvHard$
|
||||
Value=3
|
||||
|
|
|
@ -1,4 +1,26 @@
|
|||
static num_to_collect;
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
Log("Difficulty = %d", SCENPAR_Difficulty);
|
||||
num_to_collect = SCENPAR_Difficulty;
|
||||
for (var i=0; i<num_to_collect; ++i)
|
||||
{
|
||||
var ng = CreateObject(Nugget, Random(LandscapeWidth()-100) + 50, 10);
|
||||
ng.Entrance = Scenario.GotNugget;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func GotNugget()
|
||||
{
|
||||
--num_to_collect;
|
||||
if (num_to_collect == 0) GameCall("Finished");
|
||||
}
|
||||
|
||||
func Finished()
|
||||
{
|
||||
Log("All nuggets collected!");
|
||||
GainScenarioAchievement("Done", BoundBy(SCENPAR_Difficulty, 1, 3));
|
||||
GameOver();
|
||||
}
|
||||
|
|
|
@ -4,3 +4,5 @@ Hard=Schwer
|
|||
DescDifficulty=Setzt SCENPAR_Difficulty auf einen Wert.
|
||||
DescEasy=SCENPAR_Difficulty ist 1
|
||||
DescHard=SCENPAR_Difficulty ist 99
|
||||
AchvEasy=Auf einfach geschafft.
|
||||
AchvHard=Auf schwer geschafft.
|
||||
|
|
|
@ -4,3 +4,5 @@ Hard=Hard
|
|||
DescDifficulty=Sets SCENPAR_Difficulty to a value.
|
||||
DescEasy=SCENPAR_Difficulty is 1
|
||||
DescHard=SCENPAR_Difficulty is 99
|
||||
AchvEasy=Finished on easy.
|
||||
AchvHard=Finished on hard.
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#define C4CFN_ScenarioObjects "Objects.txt"
|
||||
#define C4CFN_ScenarioDesc "Desc%s.rtf"
|
||||
#define C4CFN_DefMaterials "*.material"
|
||||
#define C4CFN_Achievements "Achv*.png"
|
||||
|
||||
#define C4CFN_DefMesh "Graphics.mesh"
|
||||
#define C4CFN_DefMeshXml C4CFN_DefMesh ".xml"
|
||||
|
@ -169,7 +170,7 @@
|
|||
|
||||
// TODO: proper sorting of scaled def graphics (once we know what order we might load them in...)
|
||||
|
||||
#define C4FLS_Scenario "Loader*.bmp|Loader*.png|Loader*.jpeg|Loader*.jpg|Fonts.txt|Scenario.txt|Title*.txt|Info.txt|Desc*.rtf|Icon.png|Icon.bmp|Game.txt|StringTbl*.txt|ParameterDefs.txt|Teams.txt|Parameters.txt|Info.txt|Sect*.ocg|Music.ocg|*.mid|*.wav|Desc*.rtf|Title.png|Title.jpg|*.ocd|Material.ocg|MatMap.txt|Landscape.bmp|Landscape.png|" C4CFN_DiffLandscape "|Sky.bmp|Sky.png|Sky.jpeg|Sky.jpg|PXS.ocb|MassMover.ocb|CtrlRec.ocb|Strings.txt|Objects.txt|RoundResults.txt|Author.txt|Version.txt|Names.txt|*.ocd|Script.c|Script*.c|Map.c|Objects.c|System.ocg"
|
||||
#define C4FLS_Scenario "Loader*.bmp|Loader*.png|Loader*.jpeg|Loader*.jpg|Fonts.txt|Scenario.txt|Title*.txt|Info.txt|Desc*.rtf|Icon.png|Icon.bmp|Achv*.png|Game.txt|StringTbl*.txt|ParameterDefs.txt|Teams.txt|Parameters.txt|Info.txt|Sect*.ocg|Music.ocg|*.mid|*.wav|Desc*.rtf|Title.png|Title.jpg|*.ocd|Material.ocg|MatMap.txt|Landscape.bmp|Landscape.png|" C4CFN_DiffLandscape "|Sky.bmp|Sky.png|Sky.jpeg|Sky.jpg|PXS.ocb|MassMover.ocb|CtrlRec.ocb|Strings.txt|Objects.txt|RoundResults.txt|Author.txt|Version.txt|Names.txt|*.ocd|Script.c|Script*.c|Map.c|Objects.c|System.ocg"
|
||||
#define C4FLS_Section "Scenario.txt|Game.txt|Landscape.bmp|Landscape.png|Sky.bmp|Sky.png|Sky.jpeg|Sky.jpg|PXS.ocb|MassMover.ocb|CtrlRec.ocb|Strings.txt|Objects.txt|Objects.c"
|
||||
#define C4FLS_SectionLandscape "Scenario.txt|Landscape.bmp|Landscape.png|PXS.ocb|MassMover.ocb"
|
||||
#define C4FLS_SectionObjects "Strings.txt|Objects.txt|Objects.c"
|
||||
|
@ -179,7 +180,7 @@
|
|||
#define C4FLS_Folder "Folder.txt|Title*.txt|Info.txt|Desc*.rtf|Title.png|Title.jpg|Icon.png|Icon.bmp|Author.txt|Version.txt|*.ocs|Loader*.bmp|Loader*.png|Loader*.jpeg|Loader*.jpg|FolderMap.txt|FolderMap.png"
|
||||
#define C4FLS_Material "TexMap.txt|*.bmp|*.png|*.ocm"
|
||||
#define C4FLS_Graphics "Loader*.bmp|Loader*.png|Loader*.jpeg|Loader*.jpg|Font*.png"\
|
||||
"|Control.png|Fire.png|Background.png|Flag.png|Crew.png|Wealth.png|Player.png|Rank.png|Captain.png|Cursor.png|SelectMark.png|MenuSymbol.png|Menu.png|Logo.png|Construction.png|Energy.png|Options.png|UpperBoard.png|Arrow.png|Exit.png|Hand.png|Gamepad.png|Build.png"\
|
||||
"|Control.png|Fire.png|Background.png|Flag.png|Crew.png|Wealth.png|Player.png|Rank.png|Captain.png|Cursor.png|SelectMark.png|MenuSymbol.png|Menu.png|Logo.png|Construction.png|Energy.png|Options.png|UpperBoard.png|Arrow.png|Exit.png|Hand.png|Gamepad.png|Build.png|Achv*.png"\
|
||||
"|GUIProgress.png|Endeavour.ttf|GUICaption.png|GUIButton.png|GUIButtonDown.png|GUIButtonHighlight.png|GUIButtonHighlightRound.png|GUIIcons.png|GUIIcons2.png|GUIScroll.png|GUIContext.png|GUISubmenu.png|GUICheckBox.png|GUIBigArrows.png"\
|
||||
"|StartupMainMenuBG.*|StartupScenSelBG.*|StartupPlrSelBG.*|StartupPlrPropBG.*|StartupNetworkBG.*|StartupAboutBG.*|StartupBigButton.png|StartupBigButtonDown.png|StartupBookScroll.png|StartupContext.png|StartupScenSelIcons.png|StartupScenSelTitleOv.png|StartupDlgPaper.png|StartupOptionIcons.png|StartupTabClip.png|StartupNetGetRef.png|StartupLogo.png"
|
||||
#define C4FLS_Objects "Names*.txt|Desc*.txt|*.ocd"
|
||||
|
|
|
@ -371,152 +371,6 @@ void C4GameResList::CompileFunc(StdCompiler *pComp)
|
|||
}
|
||||
|
||||
|
||||
// *** C4ScenarioParameters
|
||||
|
||||
void C4ScenarioParameterDef::Option::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("Option")) { pComp->NameEnd(); pComp->excNotFound("Option"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Name, StdCompiler::RCT_All), "Name", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Description, StdCompiler::RCT_All), "Description", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt( Value, "Value", 0));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef::Option *C4ScenarioParameterDef::GetOptionByValue(int32_t val) const
|
||||
{
|
||||
// search option by value
|
||||
for (auto i = Options.cbegin(); i != Options.cend(); ++i)
|
||||
if (i->Value == val)
|
||||
return &*i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef::Option *C4ScenarioParameterDef::GetOptionByIndex(size_t idx) const
|
||||
{
|
||||
if (idx >= Options.size()) return NULL;
|
||||
return &Options[idx];
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDef::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("ParameterDef")) { pComp->NameEnd(); pComp->excNotFound("ParameterDef"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Name, StdCompiler::RCT_All), "Name", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Description, StdCompiler::RCT_All), "Description", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(ID, StdCompiler::RCT_Idtf), "ID", StdCopyStrBuf()));
|
||||
StdEnumEntry<ParameterType> ParTypeEntries[] =
|
||||
{
|
||||
{ "Enumeration", SPDT_Enum },
|
||||
{ NULL, SPDT_Enum }
|
||||
};
|
||||
pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(Type, ParTypeEntries), "Type", SPDT_Enum));
|
||||
pComp->Value(mkNamingAdapt(Default, "Default", 0));
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Options, StdCompiler::SEP_NONE), "Options"));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDefs::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkSTLContainerAdapt(Parameters, StdCompiler::SEP_NONE));
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef *C4ScenarioParameterDefs::GetParameterDefByIndex(size_t idx) const
|
||||
{
|
||||
if (idx >= Parameters.size()) return NULL;
|
||||
return &Parameters[idx];
|
||||
}
|
||||
|
||||
bool C4ScenarioParameterDefs::Load(C4Group &hGroup, C4LangStringTable *pLang)
|
||||
{
|
||||
// Load buffer, localize and parse
|
||||
StdStrBuf Buf;
|
||||
if (!hGroup.LoadEntryString(C4CFN_ScenarioParameterDefs,&Buf)) return false;
|
||||
if (pLang) pLang->ReplaceStrings(Buf);
|
||||
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Buf, C4CFN_ScenarioCore))
|
||||
{ return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDefs::RegisterScriptConstants(const C4ScenarioParameters &values)
|
||||
{
|
||||
// register constants for all parameters in script engine
|
||||
for (auto i = Parameters.cbegin(); i != Parameters.cend(); ++i)
|
||||
{
|
||||
StdStrBuf constant_name;
|
||||
constant_name.Format("SCENPAR_%s", i->GetID());
|
||||
int32_t constant_value = values.GetValueByID(i->GetID(), i->GetDefault());
|
||||
::ScriptEngine.RegisterGlobalConstant(constant_name.getData(), C4VInt(constant_value));
|
||||
}
|
||||
}
|
||||
|
||||
int32_t C4ScenarioParameters::GetValueByID(const char *id, int32_t default_value) const
|
||||
{
|
||||
// return map value if name is in map. Otherwise, return default value.
|
||||
auto i = Parameters.find(StdStrBuf(id));
|
||||
if (i != Parameters.end()) return i->second; else return default_value;
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::SetValue(const char *id, int32_t value)
|
||||
{
|
||||
// just update map
|
||||
Parameters[StdStrBuf(id)] = value;
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
// Unfortunately, StdCompiler cannot save std::map yet
|
||||
if (pComp->isCompiler())
|
||||
{
|
||||
Parameters.clear();
|
||||
if (pComp->hasNaming())
|
||||
{
|
||||
// load from INI
|
||||
size_t name_count = pComp->NameCount();
|
||||
for (size_t i=0; i<name_count; ++i)
|
||||
{
|
||||
int32_t v=0;
|
||||
const char *name = pComp->GetNameByIndex(0); // always get name index 0, because names are removed after values have been extracted for them
|
||||
StdCopyStrBuf sName(name);
|
||||
if (!name) continue;
|
||||
pComp->Value(mkNamingAdapt(v, sName.getData(), 0));
|
||||
Parameters[sName] = v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// load from binary
|
||||
int32_t name_count=0;
|
||||
pComp->Value(name_count);
|
||||
for (int32_t i=0; i<name_count; ++i)
|
||||
{
|
||||
StdCopyStrBuf name; int32_t v;
|
||||
pComp->Value(name);
|
||||
pComp->Value(v);
|
||||
Parameters[name] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pComp->hasNaming())
|
||||
{
|
||||
// save to INI
|
||||
for (auto i = Parameters.begin(); i != Parameters.end(); ++i)
|
||||
pComp->Value(mkNamingAdapt(i->second, i->first.getData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// save to binary
|
||||
int32_t name_count=Parameters.size();
|
||||
pComp->Value(name_count);
|
||||
for (auto i = Parameters.begin(); i != Parameters.end(); ++i)
|
||||
{
|
||||
pComp->Value(const_cast<StdCopyStrBuf &>(i->first));
|
||||
pComp->Value(i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *** C4GameParameters
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "C4PlayerInfo.h"
|
||||
#include "C4LangStringTable.h"
|
||||
#include "C4Teams.h"
|
||||
#include "C4InfoCore.h"
|
||||
|
||||
class C4GameRes
|
||||
{
|
||||
|
@ -95,40 +96,6 @@ protected:
|
|||
void LoadFoldersWithLocalDefs(const char *szPath);
|
||||
};
|
||||
|
||||
// Definitions of custom parameters that can be set before scenario start
|
||||
class C4ScenarioParameterDefs
|
||||
{
|
||||
std::vector<C4ScenarioParameterDef> Parameters;
|
||||
|
||||
public:
|
||||
C4ScenarioParameterDefs() {}
|
||||
~C4ScenarioParameterDefs() {}
|
||||
|
||||
void Clear() { Parameters.clear(); }
|
||||
|
||||
const C4ScenarioParameterDef *GetParameterDefByIndex(size_t idx) const;
|
||||
|
||||
bool Load(C4Group &hGroup, class C4LangStringTable *pLang);
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
||||
void RegisterScriptConstants(const class C4ScenarioParameters &values); // register constants for all parameters in script engine
|
||||
};
|
||||
|
||||
// Parameter values that correspond to settings offered in C4ScenarioParameterDefs
|
||||
class C4ScenarioParameters
|
||||
{
|
||||
std::map<StdCopyStrBuf, int32_t> Parameters;
|
||||
|
||||
public:
|
||||
C4ScenarioParameters() {}
|
||||
~C4ScenarioParameters() {}
|
||||
|
||||
int32_t GetValueByID(const char *id, int32_t default_value) const;
|
||||
void SetValue(const char *id, int32_t value);
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
class C4GameParameters
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -2468,6 +2468,29 @@ static int32_t FnGetStartupPlayerCount(C4PropList * _this)
|
|||
return ::Game.StartupPlayerCount;
|
||||
}
|
||||
|
||||
static bool FnGainScenarioAchievement(C4PropList * _this, C4String *achievement_name, Nillable<long> avalue, Nillable<long> player, C4String *for_scenario)
|
||||
{
|
||||
// safety
|
||||
if (!achievement_name || !achievement_name->GetData().getLength()) return false;
|
||||
// default parameter
|
||||
long value = avalue.IsNil() ? 1 : avalue;
|
||||
// gain achievement
|
||||
bool result = true;
|
||||
if (!player.IsNil() && player != NO_OWNER)
|
||||
{
|
||||
C4Player *plr = ::Players.Get(player);
|
||||
if (!plr) return false;
|
||||
result = plr->GainScenarioAchievement(achievement_name->GetCStr(), value, for_scenario ? for_scenario->GetCStr() : NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (C4Player *plr = ::Players.First; plr; plr = plr->Next)
|
||||
if (!plr->GainScenarioAchievement(achievement_name->GetCStr(), value, for_scenario ? for_scenario->GetCStr() : NULL))
|
||||
result = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
extern C4ScriptConstDef C4ScriptGameConstMap[];
|
||||
extern C4ScriptFnDef C4ScriptGameFnMap[];
|
||||
|
||||
|
@ -2634,6 +2657,7 @@ void InitGameFunctionMap(C4AulScriptEngine *pEngine)
|
|||
AddFunc(pEngine, "GetStartupPlayerCount", FnGetStartupPlayerCount);
|
||||
AddFunc(pEngine, "PlayerObjectCommand", FnPlayerObjectCommand);
|
||||
AddFunc(pEngine, "EditCursor", FnEditCursor);
|
||||
AddFunc(pEngine, "GainScenarioAchievement", FnGainScenarioAchievement);
|
||||
|
||||
F(GetPlrKnowledge);
|
||||
F(GetComponent);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <C4DrawGL.h>
|
||||
|
||||
/* C4GraphicsResource */
|
||||
|
||||
C4GraphicsResource::C4GraphicsResource():
|
||||
idSfcCaption(0), idSfcButton(0), idSfcButtonD(0), idSfcScroll(0), idSfcContext(0),
|
||||
CaptionFont(FontCaption), TitleFont(FontTitle), TextFont(FontRegular), MiniFont(FontTiny), TooltipFont(FontTooltip)
|
||||
|
@ -138,6 +140,8 @@ void C4GraphicsResource::Clear()
|
|||
// unhook deflist from font
|
||||
FontRegular.SetCustomImages(NULL);
|
||||
|
||||
Achievements.Clear();
|
||||
|
||||
// closing the group set will also close the graphics.ocg
|
||||
// this is just for games that failed to init
|
||||
// normally, this is done after successful init anyway
|
||||
|
@ -251,6 +255,9 @@ bool C4GraphicsResource::Init()
|
|||
if (!LoadFile(fctGamepad, "Gamepad", Files, 80)) return false;
|
||||
if (!LoadFile(fctBuild, "Build", Files)) return false;
|
||||
|
||||
// achievements
|
||||
if (!Achievements.Init(Files)) return false;
|
||||
|
||||
// create ColorByOwner overlay surfaces
|
||||
if (fctCrew.idSourceGroup != fctCrewClr.idSourceGroup)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <C4Surface.h>
|
||||
#include <C4FacetEx.h>
|
||||
#include <C4Gui.h>
|
||||
#include <C4ScenarioParameters.h>
|
||||
|
||||
class C4GraphicsResource
|
||||
{
|
||||
|
@ -101,6 +102,9 @@ public:
|
|||
CStdFont FontCaption; // used for title bars
|
||||
CStdFont FontTitle; // huge font for titles
|
||||
CStdFont FontTooltip; // normal, non-shadowed font (same as BookFont)
|
||||
|
||||
// achievement graphics
|
||||
C4AchievementGraphics Achievements;
|
||||
public:
|
||||
int32_t GetColorIndex(int32_t iColor, bool fLast=false);
|
||||
CStdFont &GetFontByHeight(int32_t iHgt, float *pfZoom=NULL); // get optimal font for given control size
|
||||
|
|
|
@ -495,7 +495,7 @@ namespace C4GameLobby
|
|||
case PID_SetScenarioParameter: // set a scenario parameter value
|
||||
{
|
||||
GETPKT(C4PacketSetScenarioParameter, Pkt);
|
||||
::Game.Parameters.ScenarioParameters.SetValue(Pkt.GetID(), Pkt.GetValue());
|
||||
::Game.Parameters.ScenarioParameters.SetValue(Pkt.GetID(), Pkt.GetValue(), false);
|
||||
// reflect updated value immediately on clients
|
||||
if (pRightTab->GetActiveSheetIndex() == SheetIdx_Options) if (pOptionsList) pOptionsList->Update();
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ void C4GameOptionsList::OptionScenarioParameter::DoDropdownSelChange(int32_t idN
|
|||
C4GameLobby::C4PacketSetScenarioParameter pck(ParameterDef->GetID(), idNewSelection);
|
||||
::Network.Clients.BroadcastMsgToClients(MkC4NetIOPacket(PID_SetScenarioParameter, pck));
|
||||
// also process on host
|
||||
::Game.Parameters.ScenarioParameters.SetValue(ParameterDef->GetID(), idNewSelection);
|
||||
::Game.Parameters.ScenarioParameters.SetValue(ParameterDef->GetID(), idNewSelection, false);
|
||||
}
|
||||
|
||||
void C4GameOptionsList::OptionScenarioParameter::Update()
|
||||
|
@ -295,7 +295,8 @@ void C4GameOptionsList::InitOptions()
|
|||
// create options for custom scenario parameters
|
||||
size_t idx = 0; const C4ScenarioParameterDef *def;
|
||||
while (def = ::Game.ScenarioParameterDefs.GetParameterDefByIndex(idx++))
|
||||
new OptionScenarioParameter(this, def);
|
||||
if (!def->IsAchievement()) // achievements are displayed in scenario selection. no need to repeat them here
|
||||
new OptionScenarioParameter(this, def);
|
||||
// creates option selection components
|
||||
new OptionControlMode(this);
|
||||
new OptionControlRate(this);
|
||||
|
|
|
@ -405,7 +405,7 @@ void C4MapFolderData::ResetSelection()
|
|||
// ------------------------------------
|
||||
// Entry
|
||||
|
||||
C4ScenarioListLoader::Entry::Entry(Folder *pParent) : pNext(NULL), pParent(pParent), fBaseLoaded(false), fExLoaded(false)
|
||||
C4ScenarioListLoader::Entry::Entry(class C4ScenarioListLoader *pLoader, Folder *pParent) : pLoader(pLoader), pNext(NULL), pParent(pParent), fBaseLoaded(false), fExLoaded(false)
|
||||
{
|
||||
// ctor: Put into parent tree node
|
||||
if (pParent)
|
||||
|
@ -550,20 +550,20 @@ bool DirContainsScenarios(const char *szDir)
|
|||
return !!szChildFilename;
|
||||
}
|
||||
|
||||
C4ScenarioListLoader::Entry *C4ScenarioListLoader::Entry::CreateEntryForFile(const StdStrBuf &sFilename, Folder *pParent)
|
||||
C4ScenarioListLoader::Entry *C4ScenarioListLoader::Entry::CreateEntryForFile(const StdStrBuf &sFilename, C4ScenarioListLoader *pLoader, Folder *pParent)
|
||||
{
|
||||
// determine entry type by file type
|
||||
const char *szFilename = sFilename.getData();
|
||||
if (!szFilename || !*szFilename) return NULL;
|
||||
if (WildcardMatch(C4CFN_ScenarioFiles, sFilename.getData())) return new Scenario(pParent);
|
||||
if (WildcardMatch(C4CFN_FolderFiles, sFilename.getData())) return new SubFolder(pParent);
|
||||
if (WildcardMatch(C4CFN_ScenarioFiles, sFilename.getData())) return new Scenario(pLoader, pParent);
|
||||
if (WildcardMatch(C4CFN_FolderFiles, sFilename.getData())) return new SubFolder(pLoader, pParent);
|
||||
// regular, open folder (C4Group-packed folders without extensions are not regarded, because they could contain anything!)
|
||||
const char *szExt = GetExtension(szFilename);
|
||||
if ((!szExt || !*szExt) && DirectoryExists(sFilename.getData()))
|
||||
{
|
||||
// open folders only if they contain a scenario or folder
|
||||
if (DirContainsScenarios(szFilename))
|
||||
return new RegularFolder(pParent);
|
||||
return new RegularFolder(pLoader, pParent);
|
||||
}
|
||||
// type not recognized
|
||||
return NULL;
|
||||
|
@ -670,6 +670,39 @@ bool C4ScenarioListLoader::Scenario::LoadCustomPre(C4Group &rGrp)
|
|||
if (!rGrp.LoadEntryString(C4CFN_ScenarioCore, &sFileContents)) return false;
|
||||
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(mkParAdapt(C4S, false), sFileContents, (rGrp.GetFullName() + DirSep C4CFN_ScenarioCore).getData()))
|
||||
return false;
|
||||
// ...and localized parameter definitions. needed for achievements and parameter input boxes.
|
||||
C4LangStringTable ScenarioLangStringTable;
|
||||
C4Language::LoadComponentHost(&ScenarioLangStringTable, rGrp, C4CFN_ScriptStringTbl, Config.General.LanguageEx);
|
||||
ParameterDefs.Load(rGrp, &ScenarioLangStringTable);
|
||||
// achievement images
|
||||
const C4ScenarioParameterDef *def; size_t idx=0, aidx=0; nAchievements = 0;
|
||||
while (def = ParameterDefs.GetParameterDefByIndex(idx++))
|
||||
if (def->IsAchievement())
|
||||
{
|
||||
int32_t val = pLoader->GetAchievements().GetValueByID(C4ScenarioParameters::AddFilename2ID(rGrp.GetFullName().getData(), def->GetID()).getData(), def->GetDefault());
|
||||
if (val)
|
||||
{
|
||||
// player has this achievement - find graphics for it
|
||||
const char *achievement_gfx = def->GetAchievement();
|
||||
StdStrBuf sAchievementFilename(C4CFN_Achievements);
|
||||
sAchievementFilename.Replace("*", achievement_gfx);
|
||||
if (!fctAchievements[aidx].Load(rGrp, sAchievementFilename.getData(), C4FCT_Height, C4FCT_Full))
|
||||
{
|
||||
const C4FacetSurface *fct = ::GraphicsResource.Achievements.FindByName(achievement_gfx);
|
||||
if (!fct) continue; // achievement graphics not found :(
|
||||
fctAchievements[aidx].Set((const C4Facet &)*fct);
|
||||
}
|
||||
// section by achievement index (1-based, since zero means no achievement)
|
||||
if (val>1) fctAchievements[aidx].Set(fctAchievements[aidx].GetSection(val-1));
|
||||
// description for this achievement is taken from option
|
||||
const C4ScenarioParameterDef::Option *opt = def->GetOptionByValue(val);
|
||||
if (opt) sAchievementDescriptions[aidx] = opt->Description;
|
||||
// keep track of achievement count
|
||||
++aidx; ++nAchievements;
|
||||
if (aidx == C4StartupScenSel_MaxAchievements) break;
|
||||
;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -694,6 +727,15 @@ bool C4ScenarioListLoader::Scenario::LoadCustom(C4Group &rGrp, bool fNameLoaded,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4ScenarioListLoader::Scenario::GetAchievement(int32_t idx, C4Facet *out_facet, const char **out_description)
|
||||
{
|
||||
// return true and fill output parameters if player got the indexed achievement
|
||||
if (idx < 0 || idx >= nAchievements) return false;
|
||||
*out_facet = fctAchievements[idx];
|
||||
*out_description = sAchievementDescriptions[idx].getData();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4ScenarioListLoader::Scenario::Start()
|
||||
{
|
||||
// gogo!
|
||||
|
@ -978,7 +1020,7 @@ bool C4ScenarioListLoader::SubFolder::DoLoadContents(C4ScenarioListLoader *pLoad
|
|||
sChildFilename.Ref(ChildFilename);
|
||||
// okay; create this item
|
||||
//LogF("SubFolder \"%s\" loading \"%s\"", (const char *) sFilename, (const char *) sChildFilename);
|
||||
Entry *pNewEntry = Entry::CreateEntryForFile(sChildFilename, this);
|
||||
Entry *pNewEntry = Entry::CreateEntryForFile(sChildFilename, pLoader, this);
|
||||
if (pNewEntry)
|
||||
{
|
||||
// ...and load it
|
||||
|
@ -1071,7 +1113,7 @@ bool C4ScenarioListLoader::RegularFolder::DoLoadContents(C4ScenarioListLoader *p
|
|||
if (names.find(szChildFilename) != names.end()) continue;
|
||||
names.insert(szChildFilename);
|
||||
// filename okay; create this item
|
||||
Entry *pNewEntry = Entry::CreateEntryForFile(sChildFilename, this);
|
||||
Entry *pNewEntry = Entry::CreateEntryForFile(sChildFilename, pLoader, this);
|
||||
if (pNewEntry)
|
||||
{
|
||||
// ...and load it
|
||||
|
@ -1098,7 +1140,7 @@ void C4ScenarioListLoader::RegularFolder::Merge(const char *szPath)
|
|||
// ------------------------------------
|
||||
// C4ScenarioListLoader
|
||||
|
||||
C4ScenarioListLoader::C4ScenarioListLoader() : pRootFolder(NULL), pCurrFolder(NULL),
|
||||
C4ScenarioListLoader::C4ScenarioListLoader(const C4ScenarioParameters &Achievements) : Achievements(Achievements), pRootFolder(NULL), pCurrFolder(NULL),
|
||||
iLoading(0), iProgress(0), iMaxProgress(0), fAbortThis(false), fAbortPrevious(false)
|
||||
{
|
||||
}
|
||||
|
@ -1158,7 +1200,7 @@ bool C4ScenarioListLoader::Load(const StdStrBuf &sRootFolder)
|
|||
// (unthreaded) loading of all entries in root folder
|
||||
if (!BeginActivity(true)) return false;
|
||||
if (pRootFolder) { delete pRootFolder; pRootFolder = NULL; }
|
||||
pCurrFolder = pRootFolder = new RegularFolder(NULL);
|
||||
pCurrFolder = pRootFolder = new RegularFolder(this, NULL);
|
||||
// Load regular game data if no explicit path specified
|
||||
if(!sRootFolder.getData())
|
||||
for(C4Reloc::iterator iter = Reloc.begin(); iter != Reloc.end(); ++iter)
|
||||
|
@ -1238,10 +1280,26 @@ C4StartupScenSelDlg::ScenListItem::ScenListItem(C4GUI::ListBox *pForListBox, C4S
|
|||
pIcon = new C4GUI::Picture(C4Rect(0, 0, iHeight, iHeight), true);
|
||||
pIcon->SetFacet(pScenListEntry->GetIconFacet());
|
||||
pNameLabel = new C4GUI::Label(pScenListEntry->GetName().getData(), iHeight + IconLabelSpacing, IconLabelSpacing, ALeft, fEnabled ? ClrScenarioItem : ClrScenarioItemDisabled, &rUseFont, false, false);
|
||||
// achievement components
|
||||
for (int32_t i=0; i<C4StartupScenSel_MaxAchievements; ++i)
|
||||
{
|
||||
C4Facet fct; const char *desc;
|
||||
if (pForEntry->GetAchievement(i, &fct, &desc))
|
||||
{
|
||||
ppAchievements[i] = new C4GUI::Picture(C4Rect(iHeight * (i+2), 0, iHeight, iHeight), true); // position will be adjusted later
|
||||
ppAchievements[i]->SetFacet(fct);
|
||||
ppAchievements[i]->SetToolTip(desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppAchievements[i] = NULL;
|
||||
}
|
||||
}
|
||||
// calc own bounds - use icon bounds only, because only the height is used when the item is added
|
||||
SetBounds(pIcon->GetBounds());
|
||||
// add components
|
||||
AddElement(pIcon); AddElement(pNameLabel);
|
||||
for (int32_t i=0; i<C4StartupScenSel_MaxAchievements; ++i) if (ppAchievements[i]) AddElement(ppAchievements[i]);
|
||||
// tooltip by name, so long names can be read via tooltip
|
||||
SetToolTip(pScenListEntry->GetName().getData());
|
||||
// add to listbox (will get resized horizontally and moved) - zero indent; no tree structure in this dialog
|
||||
|
@ -1258,9 +1316,12 @@ void C4StartupScenSelDlg::ScenListItem::UpdateOwnPos()
|
|||
// parent for client rect
|
||||
typedef C4GUI::Window ParentClass;
|
||||
ParentClass::UpdateOwnPos();
|
||||
// reposition items
|
||||
// reposition achievement items
|
||||
C4GUI::ComponentAligner caBounds(GetContainedClientRect(), IconLabelSpacing, IconLabelSpacing);
|
||||
// nothing to reposition for now...
|
||||
for (int32_t i=0; i<C4StartupScenSel_MaxAchievements; ++i) if (ppAchievements[i])
|
||||
{
|
||||
ppAchievements[i]->SetBounds(caBounds.GetFromRight(caBounds.GetHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
void C4StartupScenSelDlg::ScenListItem::MouseInput(C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
|
||||
|
@ -1453,9 +1514,11 @@ void C4StartupScenSelDlg::DrawElement(C4TargetFacet &cgo)
|
|||
void C4StartupScenSelDlg::OnShown()
|
||||
{
|
||||
C4StartupDlg::OnShown();
|
||||
// Collect achievements of all activated players
|
||||
UpdateAchievements();
|
||||
// init file list
|
||||
fIsInitialLoading = true;
|
||||
if (!pScenLoader) pScenLoader = new C4ScenarioListLoader();
|
||||
if (!pScenLoader) pScenLoader = new C4ScenarioListLoader(Achievements);
|
||||
pScenLoader->Load(StdStrBuf()); //Config.General.ExePath));
|
||||
UpdateList();
|
||||
UpdateSelection();
|
||||
|
@ -1840,4 +1903,21 @@ void C4StartupScenSelDlg::AbortRenaming()
|
|||
if (pRenameEdit) pRenameEdit->Abort();
|
||||
}
|
||||
|
||||
// NICHT: 9, 7.2.2, 113-114
|
||||
void C4StartupScenSelDlg::UpdateAchievements()
|
||||
{
|
||||
// Extract all achievements from activated player files and merge them
|
||||
Achievements.Clear();
|
||||
char PlayerFilename[_MAX_FNAME+1];
|
||||
C4Group PlayerGrp;
|
||||
for (int i = 0; SCopySegment(Config.General.Participants, i, PlayerFilename, ';', _MAX_FNAME, true); i++)
|
||||
{
|
||||
const char *szPlayerFilename = Config.AtUserDataPath(PlayerFilename);
|
||||
if (!FileExists(szPlayerFilename)) continue;
|
||||
if (!PlayerGrp.Open(szPlayerFilename)) continue;
|
||||
C4PlayerInfoCore nfo;
|
||||
if (!nfo.Load(PlayerGrp)) continue;
|
||||
Achievements.Merge(nfo.Achievements);
|
||||
}
|
||||
}
|
||||
|
||||
// NICHT: 9, 7.2.2, 113-114, 8a
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "C4Startup.h"
|
||||
#include "C4Scenario.h"
|
||||
#include "C4Folder.h"
|
||||
#include "C4ScenarioParameters.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
@ -36,7 +37,8 @@ const int32_t C4StartupScenSel_DefaultIcon_Scenario = 14,
|
|||
C4StartupScenSel_TitlePictureWdt = 200,
|
||||
C4StartupScenSel_TitlePictureHgt = 150,
|
||||
C4StartupScenSel_TitlePicturePadding = 10,
|
||||
C4StartupScenSel_TitleOverlayMargin = 10; // number of pixels to each side of title overlay picture
|
||||
C4StartupScenSel_TitleOverlayMargin = 10, // number of pixels to each side of title overlay picture
|
||||
C4StartupScenSel_MaxAchievements = 3; // maximum number of achievements shown next to entry
|
||||
|
||||
// a list of loaded scenarios
|
||||
class C4ScenarioListLoader
|
||||
|
@ -47,6 +49,7 @@ public:
|
|||
class Entry
|
||||
{
|
||||
protected:
|
||||
class C4ScenarioListLoader *pLoader;
|
||||
Entry *pNext;
|
||||
class Folder *pParent;
|
||||
|
||||
|
@ -61,7 +64,7 @@ public:
|
|||
int iFolderIndex;
|
||||
|
||||
public:
|
||||
Entry(class Folder *pParent);
|
||||
Entry(class C4ScenarioListLoader *pLoader, class Folder *pParent);
|
||||
virtual ~Entry(); // dtor: unlink from tree
|
||||
|
||||
bool Load(C4Group *pFromGrp, const StdStrBuf *psFilename, bool fLoadEx); // load as child if pFromGrp, else directly from filename
|
||||
|
@ -83,8 +86,9 @@ public:
|
|||
Entry *GetNext() const { return pNext; }
|
||||
class Folder *GetParent() const { return pParent; }
|
||||
virtual StdStrBuf GetTypeName() = 0;
|
||||
virtual bool GetAchievement(int32_t idx, C4Facet *out_facet, const char **out_description) { return false; } // return true and fill output parameters if player got the indexed achievement
|
||||
|
||||
static Entry *CreateEntryForFile(const StdStrBuf &sFilename, Folder *pParent); // create correct entry type based on file extension
|
||||
static Entry *CreateEntryForFile(const StdStrBuf &sFilename, C4ScenarioListLoader *pLoader, Folder *pParent); // create correct entry type based on file extension
|
||||
|
||||
virtual bool CanOpen(StdStrBuf &sError) { return true; } // whether item can be started/opened (e.g. mission access, unregistered)
|
||||
virtual bool IsGrayed() { return false; } // additional condition for graying out - notice unreg folders are grayed but can still be opened
|
||||
|
@ -104,11 +108,15 @@ public:
|
|||
{
|
||||
private:
|
||||
C4Scenario C4S;
|
||||
C4ScenarioParameterDefs ParameterDefs;
|
||||
C4FacetSurface fctAchievements[C4StartupScenSel_MaxAchievements];
|
||||
StdCopyStrBuf sAchievementDescriptions[C4StartupScenSel_MaxAchievements];
|
||||
int32_t nAchievements;
|
||||
bool fNoMissionAccess;
|
||||
int32_t iMinPlrCount;
|
||||
|
||||
public:
|
||||
Scenario(class Folder *pParent) : Entry(pParent), fNoMissionAccess(false), iMinPlrCount(0) {}
|
||||
Scenario(class C4ScenarioListLoader *pLoader, class Folder *pParent) : Entry(pLoader, pParent), fNoMissionAccess(false), iMinPlrCount(0), nAchievements(0) {}
|
||||
virtual ~Scenario() {}
|
||||
|
||||
virtual bool LoadCustom(C4Group &rGrp, bool fNameLoaded, bool fIconLoaded); // do fallbacks for title and icon; check whether scenario is valid
|
||||
|
@ -121,6 +129,7 @@ public:
|
|||
virtual StdStrBuf GetOpenText(); // get open button text
|
||||
virtual StdStrBuf GetOpenTooltip();
|
||||
const C4Scenario &GetC4S() const { return C4S; } // get scenario core
|
||||
virtual bool GetAchievement(int32_t idx, C4Facet *out_facet, const char **out_description); // return true and fill output parameters if player got the indexed achievement
|
||||
|
||||
virtual StdStrBuf GetTypeName() { return StdCopyStrBuf(LoadResStr("IDS_TYPE_SCENARIO"), true); }
|
||||
|
||||
|
@ -140,7 +149,7 @@ public:
|
|||
friend class Entry;
|
||||
|
||||
public:
|
||||
Folder(Folder *pParent) : Entry(pParent), fContentsLoaded(false), pFirst(NULL), pMapData(NULL) {}
|
||||
Folder(class C4ScenarioListLoader *pLoader, Folder *pParent) : Entry(pLoader, pParent), fContentsLoaded(false), pFirst(NULL), pMapData(NULL) {}
|
||||
virtual ~Folder();
|
||||
|
||||
virtual bool LoadCustomPre(C4Group &rGrp); // load folder core
|
||||
|
@ -171,7 +180,7 @@ public:
|
|||
class SubFolder : public Folder
|
||||
{
|
||||
public:
|
||||
SubFolder(Folder *pParent) : Folder(pParent) {}
|
||||
SubFolder(class C4ScenarioListLoader *pLoader, Folder *pParent) : Folder(pLoader, pParent) {}
|
||||
virtual ~SubFolder() {}
|
||||
|
||||
virtual const char *GetDefaultExtension() { return "ocf"; }
|
||||
|
@ -187,7 +196,7 @@ public:
|
|||
class RegularFolder : public Folder
|
||||
{
|
||||
public:
|
||||
RegularFolder(Folder *pParent) : Folder(pParent) {}
|
||||
RegularFolder(class C4ScenarioListLoader *pLoader, Folder *pParent) : Folder(pLoader, pParent) {}
|
||||
virtual ~RegularFolder();
|
||||
|
||||
virtual StdStrBuf GetTypeName() { return StdCopyStrBuf(LoadResStr("IDS_TYPE_DIRECTORY"), true); }
|
||||
|
@ -207,9 +216,10 @@ private:
|
|||
Folder *pCurrFolder; // scenario list in working directory
|
||||
int32_t iLoading, iProgress, iMaxProgress;
|
||||
bool fAbortThis, fAbortPrevious; // activity state
|
||||
const C4ScenarioParameters &Achievements;
|
||||
|
||||
public:
|
||||
C4ScenarioListLoader();
|
||||
C4ScenarioListLoader(const C4ScenarioParameters &Achievements);
|
||||
~C4ScenarioListLoader();
|
||||
|
||||
private:
|
||||
|
@ -235,6 +245,8 @@ public:
|
|||
int32_t GetProgress() const { return iProgress; }
|
||||
int32_t GetMaxProgress() const { return iMaxProgress; }
|
||||
int32_t GetProgressPercent() const { return iProgress * 100 / Max<int32_t>(iMaxProgress, 1); }
|
||||
|
||||
const C4ScenarioParameters &GetAchievements() const { return Achievements; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -354,6 +366,7 @@ public:
|
|||
// subcomponents
|
||||
C4GUI::Picture *pIcon; // item icon
|
||||
C4GUI::Label *pNameLabel; // item caption
|
||||
C4GUI::Picture *ppAchievements[C4StartupScenSel_MaxAchievements]; // achievement icons
|
||||
C4ScenarioListLoader::Entry *pScenListEntry; // associated, loaded item info
|
||||
|
||||
public:
|
||||
|
@ -409,6 +422,9 @@ private:
|
|||
|
||||
C4GUI::RenameEdit *pRenameEdit;
|
||||
|
||||
// achievements of all activated players
|
||||
C4ScenarioParameters Achievements;
|
||||
|
||||
public:
|
||||
static C4StartupScenSelDlg *pInstance; // singleton
|
||||
|
||||
|
@ -447,6 +463,7 @@ private:
|
|||
C4ScenarioListLoader::Entry *GetSelectedEntry();
|
||||
void SetOpenButtonDefaultText();
|
||||
void FocusScenList();
|
||||
void UpdateAchievements();
|
||||
|
||||
public:
|
||||
bool StartScenario(C4ScenarioListLoader::Scenario *pStartScen);
|
||||
|
|
|
@ -221,50 +221,6 @@ public:
|
|||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
// Definition for a custom setting for the scenario
|
||||
class C4ScenarioParameterDef
|
||||
{
|
||||
public:
|
||||
// what kind of parameter?
|
||||
enum ParameterType
|
||||
{
|
||||
SPDT_Enum, // only one type so far
|
||||
};
|
||||
|
||||
// single option for an enum type parameter
|
||||
struct Option
|
||||
{
|
||||
int32_t Value; // integer value that will be assigned to the script constant
|
||||
StdCopyStrBuf Name; // localized name
|
||||
StdCopyStrBuf Description; // localized description. to be displayed as hover text for this option.
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
private:
|
||||
StdCopyStrBuf Name; // localized name
|
||||
StdCopyStrBuf Description; // localized description. to be displayed as hover text for this parameter input control
|
||||
StdCopyStrBuf ID; // Identifier for value storage and script access
|
||||
ParameterType Type; // Type of parameter. Always enum.
|
||||
|
||||
std::vector<Option> Options; // possible options to be selected for an enum type
|
||||
int32_t Default; // value of option selected by default for an enum type
|
||||
|
||||
public:
|
||||
C4ScenarioParameterDef() : Default(0) {}
|
||||
~C4ScenarioParameterDef() {}
|
||||
|
||||
const char *GetName() const { return Name.getData(); }
|
||||
const char *GetDescription() const { return Description.getData(); }
|
||||
const char *GetID() const { return ID.getData(); }
|
||||
ParameterType GetType() const { return Type; }
|
||||
int32_t GetDefault() const { return Default; }
|
||||
const Option *GetOptionByValue(int32_t val) const;
|
||||
const Option *GetOptionByIndex(size_t idx) const;
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
class C4Scenario
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -36,13 +36,20 @@
|
|||
|
||||
C4PlayerInfoCore::C4PlayerInfoCore()
|
||||
{
|
||||
ZeroMem(this,sizeof(C4PlayerInfoCore));
|
||||
Default();
|
||||
}
|
||||
|
||||
void C4PlayerInfoCore::Default(C4RankSystem *pRanks)
|
||||
{
|
||||
ZeroMem(this,sizeof(C4PlayerInfoCore));
|
||||
*Comment='\0';
|
||||
*RankName='\0';
|
||||
TotalScore=0;
|
||||
Rounds=RoundsWon=RoundsLost=0;
|
||||
TotalPlayingTime=0;
|
||||
*LeagueName='\0';
|
||||
LastRound.Default();
|
||||
ExtraData = C4ValueMapData();
|
||||
PrefControl.Clear();
|
||||
Rank=0;
|
||||
SCopy("Neuling",PrefName);
|
||||
if (pRanks) SCopy(pRanks->GetRankName(Rank,false).getData(),RankName);
|
||||
|
@ -166,6 +173,7 @@ void C4PlayerInfoCore::CompileFunc(StdCompiler *pComp)
|
|||
|
||||
pComp->Value(mkNamingAdapt(LastRound, "LastRound"));
|
||||
|
||||
pComp->Value(mkNamingAdapt(Achievements, "Achievements"));
|
||||
}
|
||||
|
||||
//------------------------------- Object Info ----------------------------------------
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <C4ValueMap.h>
|
||||
#include "C4Real.h"
|
||||
#include "C4InputValidation.h"
|
||||
#include "C4ScenarioParameters.h"
|
||||
|
||||
const int32_t C4MaxPhysical = 100000,
|
||||
C4MaxDeathMsg = 75;
|
||||
|
@ -108,6 +109,9 @@ public:
|
|||
int32_t OldPrefControl;
|
||||
int32_t OldPrefControlStyle;
|
||||
int32_t OldPrefAutoContextMenu;
|
||||
|
||||
// achievements indexed by achievement name and scenario
|
||||
C4ScenarioParameters Achievements;
|
||||
public:
|
||||
void Default(C4RankSystem *pRanks=NULL);
|
||||
void Promote(int32_t iRank, C4RankSystem &rRanks);
|
||||
|
|
|
@ -2028,3 +2028,17 @@ void C4Player::SetViewLocked(bool to_val)
|
|||
if (ViewMode == C4PVM_Scrolling) SetViewMode(C4PVM_Cursor);
|
||||
}
|
||||
}
|
||||
|
||||
bool C4Player::GainScenarioAchievement(const char *achievement_id, int32_t value, const char *scen_name_override)
|
||||
{
|
||||
// Determine full ID of achievement
|
||||
if (!scen_name_override)
|
||||
if (::Game.C4S.Head.Origin.getLength())
|
||||
scen_name_override = ::Game.C4S.Head.Origin.getData();
|
||||
else
|
||||
scen_name_override = ::Game.ScenarioFilename;
|
||||
StdStrBuf sAchvID = C4ScenarioParameters::AddFilename2ID(scen_name_override, achievement_id);
|
||||
// Gain achievement iff it's an improvement
|
||||
Achievements.SetValue(sAchvID.getData(), value, true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -272,6 +272,10 @@ public:
|
|||
private:
|
||||
bool AdjustZoomParameter(int32_t *range_par, int32_t new_val, bool no_increase, bool no_decrease);
|
||||
bool AdjustZoomParameter(C4Fixed *zoom_par, C4Fixed new_val, bool no_increase, bool no_decrease);
|
||||
|
||||
public:
|
||||
// custom scenario achievements
|
||||
bool GainScenarioAchievement(const char *achievement_id, int32_t value, const char *scen_name_override=NULL);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
||||
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
||||
*
|
||||
* Distributed under the terms of the ISC license; see accompanying file
|
||||
* "COPYING" for details.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||
* See accompanying file "TRADEMARK" for details.
|
||||
*
|
||||
* To redistribute this file separately, substitute the full license texts
|
||||
* for the above references.
|
||||
*/
|
||||
#include "C4Include.h"
|
||||
#include "C4ScenarioParameters.h"
|
||||
#include "C4Components.h"
|
||||
#include "C4Aul.h"
|
||||
#include "C4FacetEx.h"
|
||||
|
||||
|
||||
/* C4AchievementGraphics */
|
||||
|
||||
bool C4AchievementGraphics::Init(C4Group &File)
|
||||
{
|
||||
// Load all graphics matching achievement filename and register them to map
|
||||
char FileName[_MAX_FNAME];
|
||||
File.ResetSearch();
|
||||
while (File.FindNextEntry(C4CFN_Achievements, FileName))
|
||||
{
|
||||
C4FacetSurface *new_fct = new C4FacetSurface();
|
||||
if (!new_fct->Load(File, FileName, C4FCT_Height, C4FCT_Full))
|
||||
{
|
||||
delete new_fct;
|
||||
LogF(LoadResStr("IDS_PRC_NOGFXFILE"), FileName, LoadResStr("IDS_ERR_NOFILE"));
|
||||
return false;
|
||||
}
|
||||
// Register under filename excluding the leading "Achv" part. Delete any existing file with same name.
|
||||
RemoveExtension(FileName);
|
||||
int32_t id_offset = SCharPos('*', C4CFN_Achievements); assert(id_offset>=0);
|
||||
StdCopyStrBuf sFileName(FileName + id_offset);
|
||||
auto i = Graphics.find(sFileName);
|
||||
if (i != Graphics.end()) delete i->second;
|
||||
Graphics[sFileName] = new_fct;
|
||||
}
|
||||
// done. success no matter how many files were loaded.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4AchievementGraphics::Init(C4GroupSet &Files)
|
||||
{
|
||||
int32_t idNewGrp=0;
|
||||
C4Group *pGrp = Files.FindEntry(C4CFN_Achievements, NULL, &idNewGrp);
|
||||
if (!pGrp) return true; // no achievement gfx. That's OK.
|
||||
if (idNewGrp == idGrp) return true; // no update
|
||||
idGrp = idNewGrp;
|
||||
// OK, load from this group
|
||||
return Init(*pGrp);
|
||||
}
|
||||
|
||||
void C4AchievementGraphics::Clear()
|
||||
{
|
||||
for (auto i = Graphics.begin(); i != Graphics.end(); ++i)
|
||||
delete i->second;
|
||||
Graphics.clear();
|
||||
idGrp = 0;
|
||||
}
|
||||
|
||||
C4FacetSurface *C4AchievementGraphics::FindByName(const char *name) const
|
||||
{
|
||||
auto i = Graphics.find(StdCopyStrBuf(name));
|
||||
if (i != Graphics.end()) return i->second; else return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// *** C4ScenarioParameters
|
||||
|
||||
void C4ScenarioParameterDef::Option::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("Option")) { pComp->NameEnd(); pComp->excNotFound("Option"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Name, StdCompiler::RCT_All), "Name", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Description, StdCompiler::RCT_All), "Description", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt( Value, "Value", 0));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef::Option *C4ScenarioParameterDef::GetOptionByValue(int32_t val) const
|
||||
{
|
||||
// search option by value
|
||||
for (auto i = Options.cbegin(); i != Options.cend(); ++i)
|
||||
if (i->Value == val)
|
||||
return &*i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef::Option *C4ScenarioParameterDef::GetOptionByIndex(size_t idx) const
|
||||
{
|
||||
if (idx >= Options.size()) return NULL;
|
||||
return &Options[idx];
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDef::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
if (!pComp->Name("ParameterDef")) { pComp->NameEnd(); pComp->excNotFound("ParameterDef"); }
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Name, StdCompiler::RCT_All), "Name", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Description, StdCompiler::RCT_All), "Description", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(ID, StdCompiler::RCT_Idtf), "ID", StdCopyStrBuf()));
|
||||
StdEnumEntry<ParameterType> ParTypeEntries[] =
|
||||
{
|
||||
{ "Enumeration", SPDT_Enum },
|
||||
{ NULL, SPDT_Enum }
|
||||
};
|
||||
pComp->Value(mkNamingAdapt(mkEnumAdaptT<uint8_t>(Type, ParTypeEntries), "Type", SPDT_Enum));
|
||||
pComp->Value(mkNamingAdapt(Default, "Default", 0));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(Achievement, StdCompiler::RCT_Idtf), "Achievement", StdCopyStrBuf()));
|
||||
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Options, StdCompiler::SEP_NONE), "Options"));
|
||||
pComp->NameEnd();
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDefs::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
pComp->Value(mkSTLContainerAdapt(Parameters, StdCompiler::SEP_NONE));
|
||||
}
|
||||
|
||||
const C4ScenarioParameterDef *C4ScenarioParameterDefs::GetParameterDefByIndex(size_t idx) const
|
||||
{
|
||||
if (idx >= Parameters.size()) return NULL;
|
||||
return &Parameters[idx];
|
||||
}
|
||||
|
||||
bool C4ScenarioParameterDefs::Load(C4Group &hGroup, C4LangStringTable *pLang)
|
||||
{
|
||||
// Load buffer, localize and parse
|
||||
StdStrBuf Buf;
|
||||
if (!hGroup.LoadEntryString(C4CFN_ScenarioParameterDefs,&Buf)) return false;
|
||||
if (pLang) pLang->ReplaceStrings(Buf);
|
||||
if (!CompileFromBuf_LogWarn<StdCompilerINIRead>(*this, Buf, C4CFN_ScenarioCore))
|
||||
{ return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4ScenarioParameterDefs::RegisterScriptConstants(const C4ScenarioParameters &values)
|
||||
{
|
||||
// register constants for all parameters in script engine
|
||||
for (auto i = Parameters.cbegin(); i != Parameters.cend(); ++i)
|
||||
{
|
||||
StdStrBuf constant_name;
|
||||
constant_name.Format("SCENPAR_%s", i->GetID());
|
||||
int32_t constant_value = values.GetValueByID(i->GetID(), i->GetDefault());
|
||||
::ScriptEngine.RegisterGlobalConstant(constant_name.getData(), C4VInt(constant_value));
|
||||
}
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::Clear()
|
||||
{
|
||||
Parameters.clear();
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::Merge(const C4ScenarioParameters &other)
|
||||
{
|
||||
// Merge lists and keep larger value
|
||||
for (auto i = other.Parameters.cbegin(); i != other.Parameters.cend(); ++i)
|
||||
{
|
||||
auto j = Parameters.find(i->first);
|
||||
if (j != Parameters.end())
|
||||
if (j->second >= i->second)
|
||||
continue; // existing value is same or larger - keep old
|
||||
// update to new value from other list
|
||||
Parameters[i->first] = i->second;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t C4ScenarioParameters::GetValueByID(const char *id, int32_t default_value) const
|
||||
{
|
||||
// return map value if name is in map. Otherwise, return default value.
|
||||
auto i = Parameters.find(StdStrBuf(id));
|
||||
if (i != Parameters.end()) return i->second; else return default_value;
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::SetValue(const char *id, int32_t value, bool only_if_larger)
|
||||
{
|
||||
if (only_if_larger)
|
||||
{
|
||||
auto i = Parameters.find(StdStrBuf(id));
|
||||
if (i != Parameters.end())
|
||||
if (i->second >= value)
|
||||
// could become smaller. don't set.
|
||||
return;
|
||||
}
|
||||
// just update map
|
||||
Parameters[StdCopyStrBuf(id)] = value;
|
||||
}
|
||||
|
||||
void C4ScenarioParameters::CompileFunc(StdCompiler *pComp)
|
||||
{
|
||||
// Unfortunately, StdCompiler cannot save std::map yet
|
||||
if (pComp->isCompiler())
|
||||
{
|
||||
Parameters.clear();
|
||||
if (pComp->hasNaming())
|
||||
{
|
||||
// load from INI
|
||||
size_t name_count = pComp->NameCount();
|
||||
for (size_t i=0; i<name_count; ++i)
|
||||
{
|
||||
int32_t v=0;
|
||||
const char *name = pComp->GetNameByIndex(0); // always get name index 0, because names are removed after values have been extracted for them
|
||||
StdCopyStrBuf sName(name);
|
||||
if (!name) continue;
|
||||
pComp->Value(mkNamingAdapt(v, sName.getData(), 0));
|
||||
Parameters[sName] = v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// load from binary
|
||||
int32_t name_count=0;
|
||||
pComp->Value(name_count);
|
||||
for (int32_t i=0; i<name_count; ++i)
|
||||
{
|
||||
StdCopyStrBuf name; int32_t v;
|
||||
pComp->Value(name);
|
||||
pComp->Value(v);
|
||||
Parameters[name] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pComp->hasNaming())
|
||||
{
|
||||
// save to INI
|
||||
for (auto i = Parameters.begin(); i != Parameters.end(); ++i)
|
||||
pComp->Value(mkNamingAdapt(i->second, i->first.getData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// save to binary
|
||||
int32_t name_count=Parameters.size();
|
||||
pComp->Value(name_count);
|
||||
for (auto i = Parameters.begin(); i != Parameters.end(); ++i)
|
||||
{
|
||||
pComp->Value(const_cast<StdCopyStrBuf &>(i->first));
|
||||
pComp->Value(i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StdStrBuf C4ScenarioParameters::AddFilename2ID(const char *filename, const char *id)
|
||||
{
|
||||
// composes an ID string that contains both the relevant part of the filename and the ID
|
||||
// we care for .oc* folders only
|
||||
StdStrBuf sResult, sSource(filename, true), sPart;
|
||||
sSource.ReplaceChar(AltDirectorySeparator, DirectorySeparator);
|
||||
size_t idx=0;
|
||||
while (sSource.GetSection(idx++, &sPart, DirectorySeparator))
|
||||
{
|
||||
size_t len = sPart.getLength();
|
||||
if (len > 4 && !strnicmp(sPart.getPtr(len - 4), ".oc", 3))
|
||||
{
|
||||
// .oc* folders separated by underscores
|
||||
sResult.Append(sPart.getData(), len - 4);
|
||||
sResult.AppendChar('_');
|
||||
}
|
||||
}
|
||||
sResult.Append(id);
|
||||
return sResult;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 1998-2000, Matthes Bender
|
||||
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
|
||||
* Copyright (c) 2009-2013, The OpenClonk Team and contributors
|
||||
*
|
||||
* Distributed under the terms of the ISC license; see accompanying file
|
||||
* "COPYING" for details.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||
* See accompanying file "TRADEMARK" for details.
|
||||
*
|
||||
* To redistribute this file separately, substitute the full license texts
|
||||
* for the above references.
|
||||
*/
|
||||
|
||||
/* Structures for object and player info components */
|
||||
|
||||
#ifndef INC_C4ScenarioParameters
|
||||
#define INC_C4ScenarioParameters
|
||||
|
||||
// Maps IDs to achievement graphics to be shown beside scenarios (and maybe other things)
|
||||
class C4AchievementGraphics
|
||||
{
|
||||
std::map<StdCopyStrBuf, C4FacetSurface *> Graphics;
|
||||
int32_t idGrp; // ID of group file from which achievements were loaded
|
||||
|
||||
public:
|
||||
C4AchievementGraphics() : idGrp(0) {}
|
||||
|
||||
// Init will always load all achievement files from the first group that contains achievements
|
||||
bool Init(C4Group &File);
|
||||
bool Init(C4GroupSet &Files);
|
||||
void Clear();
|
||||
|
||||
C4FacetSurface *FindByName(const char *name) const;
|
||||
};
|
||||
|
||||
// Definition for a custom setting for the scenario
|
||||
class C4ScenarioParameterDef
|
||||
{
|
||||
public:
|
||||
// what kind of parameter?
|
||||
enum ParameterType
|
||||
{
|
||||
SPDT_Enum, // only one type so far
|
||||
};
|
||||
|
||||
// single option for an enum type parameter
|
||||
struct Option
|
||||
{
|
||||
int32_t Value; // integer value that will be assigned to the script constant
|
||||
StdCopyStrBuf Name; // localized name
|
||||
StdCopyStrBuf Description; // localized description. to be displayed as hover text for this option.
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
private:
|
||||
StdCopyStrBuf Name; // localized name
|
||||
StdCopyStrBuf Description; // localized description. to be displayed as hover text for this parameter input control
|
||||
StdCopyStrBuf ID; // Identifier for value storage and script access
|
||||
ParameterType Type; // Type of parameter. Always enum.
|
||||
|
||||
std::vector<Option> Options; // possible options to be selected for an enum type
|
||||
int32_t Default; // value of option selected by default for an enum type
|
||||
|
||||
StdCopyStrBuf Achievement; // if this parameter is an achievement, this string contains the name of the achievement graphics to be used
|
||||
|
||||
public:
|
||||
C4ScenarioParameterDef() : Default(0) {}
|
||||
~C4ScenarioParameterDef() {}
|
||||
|
||||
const char *GetName() const { return Name.getData(); }
|
||||
const char *GetDescription() const { return Description.getData(); }
|
||||
const char *GetID() const { return ID.getData(); }
|
||||
ParameterType GetType() const { return Type; }
|
||||
int32_t GetDefault() const { return Default; }
|
||||
const Option *GetOptionByValue(int32_t val) const;
|
||||
const Option *GetOptionByIndex(size_t idx) const;
|
||||
|
||||
bool IsAchievement() const { return Achievement.getLength()>0; }
|
||||
const char *GetAchievement() const { return Achievement.getData(); }
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
};
|
||||
|
||||
// Definitions of custom parameters that can be set before scenario start
|
||||
class C4ScenarioParameterDefs
|
||||
{
|
||||
std::vector<C4ScenarioParameterDef> Parameters;
|
||||
|
||||
public:
|
||||
C4ScenarioParameterDefs() {}
|
||||
~C4ScenarioParameterDefs() {}
|
||||
|
||||
void Clear() { Parameters.clear(); }
|
||||
|
||||
const C4ScenarioParameterDef *GetParameterDefByIndex(size_t idx) const;
|
||||
|
||||
bool Load(C4Group &hGroup, class C4LangStringTable *pLang);
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
||||
void RegisterScriptConstants(const class C4ScenarioParameters &values); // register constants for all parameters in script engine
|
||||
};
|
||||
|
||||
// Parameter values that correspond to settings offered in C4ScenarioParameterDefs
|
||||
class C4ScenarioParameters
|
||||
{
|
||||
std::map<StdCopyStrBuf, int32_t> Parameters;
|
||||
|
||||
public:
|
||||
C4ScenarioParameters() {}
|
||||
~C4ScenarioParameters() {}
|
||||
|
||||
void Clear();
|
||||
void Merge(const C4ScenarioParameters &other);
|
||||
|
||||
int32_t GetValueByID(const char *id, int32_t default_value) const;
|
||||
void SetValue(const char *id, int32_t value, bool only_if_larger);
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
||||
static StdStrBuf AddFilename2ID(const char *filename, const char *id);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // INC_C4ScenarioParameters
|
Loading…
Reference in New Issue