openclonk/src/player/C4ScenarioParameters.cpp

272 lines
8.3 KiB
C++

/*
* 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;
}