/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ * Copyright (c) 2009-2016, 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 "player/C4ScenarioParameters.h" #include "c4group/C4Components.h" #include "script/C4Aul.h" // *** 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 (const auto & Option : Options) if (Option.Value == val) return &Option; return nullptr; } const C4ScenarioParameterDef::Option *C4ScenarioParameterDef::GetOptionByIndex(size_t idx) const { if (idx >= Options.size()) return nullptr; 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 ParTypeEntries[] = { { "Enumeration", SPDT_Enum }, { nullptr, SPDT_Enum } }; pComp->Value(mkNamingAdapt(mkEnumAdaptT(Type, ParTypeEntries), "Type", SPDT_Enum)); pComp->Value(mkNamingAdapt(Default, "Default", 0)); pComp->Value(mkNamingAdapt(LeagueValue, "LeagueValue", 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 nullptr; 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(*this, Buf, C4CFN_ScenarioParameterDefs)) { return false; } return true; } void C4ScenarioParameterDefs::RegisterScriptConstants(const C4ScenarioParameters &values) { // register constants for all parameters in script engine // old-style: one constant per parameter for (const auto & Parameter : Parameters) { StdStrBuf constant_name; constant_name.Format("SCENPAR_%s", Parameter.GetID()); int32_t constant_value = values.GetValueByID(Parameter.GetID(), Parameter.GetDefault()); ::ScriptEngine.RegisterGlobalConstant(constant_name.getData(), C4VInt(constant_value)); } // new-style: all constants in a proplist auto scenpar = C4PropList::NewStatic(nullptr, nullptr, &Strings.P[P_SCENPAR]); for (const auto & Parameter : Parameters) { int32_t constant_value = values.GetValueByID(Parameter.GetID(), Parameter.GetDefault()); scenpar->SetPropertyByS(Strings.RegString(StdStrBuf(Parameter.GetID())), C4VInt(constant_value)); } scenpar->Freeze(); ::ScriptEngine.RegisterGlobalConstant("SCENPAR", C4Value(scenpar)); } void C4ScenarioParameters::Clear() { Parameters.clear(); } void C4ScenarioParameters::Merge(const C4ScenarioParameters &other) { // Merge lists and keep larger value for (const auto & Parameter : other.Parameters) { auto j = Parameters.find(Parameter.first); if (j != Parameters.end()) if (j->second >= Parameter.second) continue; // existing value is same or larger - keep old // update to new value from other list Parameters[Parameter.first] = Parameter.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->isDeserializer()) { Parameters.clear(); if (pComp->hasNaming()) { // load from INI size_t name_count = pComp->NameCount(); for (size_t i=0; iGetNameByIndex(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; iValue(name); pComp->Value(v); Parameters[name] = v; } } } else { if (pComp->hasNaming()) { // save to INI for (auto & Parameter : Parameters) pComp->Value(mkNamingAdapt(Parameter.second, Parameter.first.getData())); } else { // save to binary int32_t name_count=Parameters.size(); pComp->Value(name_count); for (auto & Parameter : Parameters) { pComp->Value(const_cast(Parameter.first)); pComp->Value(Parameter.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 && SEqual2NoCase(sPart.getPtr(len - 4), ".oc", 3)) { // .oc* folders separated by underscores sResult.Append(sPart.getData(), len - 4); sResult.AppendChar('_'); } } sResult.Append(id); return sResult; }