diff --git a/MissionEditor/functions.cpp b/MissionEditor/functions.cpp index 4974653..f422de8 100644 --- a/MissionEditor/functions.cpp +++ b/MissionEditor/functions.cpp @@ -28,6 +28,7 @@ #include "inlines.h" #include "mmsystem.h" +#include #define DBG #undef DBG @@ -146,22 +147,14 @@ char *strcpy_safe( char *strDestination, const char *strSource ) CString TranslateHouse(CString original, BOOL bToUI) { #ifdef RA2_MODE - if(bToUI) - { + if(bToUI) { // CCStrings[*rules.sections[HOUSES].GetValue(i)].wString - int i; - for(i=0;i=0) - { - CString s=language.sections["English-StringsRA2"].values[name]; - return ToACP(s); - } + auto const strRA2Sec = theApp.m_Options.LanguageName + "-StringsRA2"; + if (auto const& translated = language.GetSection(strRA2Sec).TryGetString(name)) { + return ToACP(*translated); + } + if(auto const& def = language.GetSection("English-StringsRA2").TryGetString(name)) { + return ToACP(*def); } - else - return ToACP(language.sections[sec2].values[name]); #endif - - - if(language.sections[theApp.m_Options.LanguageName+"-Strings"].values.find(name)==language.sections[theApp.m_Options.LanguageName+"-Strings"].values.end()) - { - CString s=language.sections["English-Strings"].values[name]; + auto const defSec = theApp.m_Options.LanguageName + "-Strings"; + auto const translated = language.GetSection(defSec).TryGetString(name); + if(!translated) { + CString s = language.GetSection("English-Strings").GetString(name); #ifndef RA2_MODE - s=TranslateStringVariables(9, s, "FinalSun"); + s = TranslateStringVariables(9, s, "FinalSun"); #else #ifdef YR_MODE - s=TranslateStringVariables(9, s, "FinalAlert 2: Yuri's Revenge"); + s = TranslateStringVariables(9, s, "FinalAlert 2: Yuri's Revenge"); #else - s=TranslateStringVariables(9, s, "FinalAlert 2"); + s = TranslateStringVariables(9, s, "FinalAlert 2"); #endif #endif return ToACP(s); } CString s; - s= language.sections[theApp.m_Options.LanguageName+"-Strings"].values[name]; + s = *translated; #ifndef RA2_MODE - if(s.Find("%9")>=0) s=TranslateStringVariables(9,s,"FinalSun"); + if (s.Find("%9") >= 0) s = TranslateStringVariables(9, s, "FinalSun"); #else #ifdef YR_MODE - if(s.Find("%9")>=0) s=TranslateStringVariables(9,s,"FinalAlert 2: Yuri's Revenge"); + if (s.Find("%9") >= 0) s = TranslateStringVariables(9, s, "FinalAlert 2: Yuri's Revenge"); #else - if(s.Find("%9")>=0) s=TranslateStringVariables(9,s,"FinalAlert 2"); + if (s.Find("%9") >= 0) s = TranslateStringVariables(9, s, "FinalAlert 2"); #endif #endif @@ -472,71 +460,11 @@ CString TranslateStringACP(WCHAR* u16EnglishString) // tranlate a string/word by using the table from english to the current language CString TranslateStringACP(CString u8EnglishString) { - if (!isValidUtf8(u8EnglishString)) - { + if (!isValidUtf8(u8EnglishString)) { errstream << "TranslateStringACP(\"" << u8EnglishString << "\") called with an invalid UTF-8 string" << std::endl; return u8EnglishString; } - -#ifdef RA2_MODE - CString sec2=theApp.m_Options.LanguageName+"-TranslationsRA2"; - if(language.sections[sec2].values.end()==language.sections[sec2].values.find(u8EnglishString)) - { - if(language.sections["English-TranslationsRA2"].FindName(u8EnglishString)>=0) - { - CString s=language.sections["English-TranslationsRA2"].values[u8EnglishString]; - return ToACP(s); - } - } - else - return ToACP(language.sections[sec2].values[u8EnglishString]); -#endif - - - CString sec=theApp.m_Options.LanguageName+"-Translations"; - - // check if the string can be translated - if(language.sections[sec].values.end()==language.sections[sec].values.find(u8EnglishString)) - { - CString seceng; - seceng="English-Translations"; - if(language.sections[seceng].FindName(u8EnglishString)>=0) - { - CString s=language.sections[seceng].values[u8EnglishString]; -#ifndef RA2_MODE - s=TranslateStringVariables(9, s, "FinalSun"); -#else -#ifdef YR_MODE - s=TranslateStringVariables(9, s, "FinalAlert 2: Yuri's Revenge"); -#else - s=TranslateStringVariables(9, s, "FinalAlert 2"); -#endif -#endif - return ToACP(s); - } -#ifndef RA2_MODE - return ToACP(TranslateStringVariables(9,u8EnglishString,"FinalSun")); -#else -#ifdef YR_MODE - return ToACP(TranslateStringVariables(9,u8EnglishString,"FinalAlert 2: Yuri's Revenge")); -#else - return ToACP(TranslateStringVariables(9,u8EnglishString,"FinalAlert 2")); -#endif -#endif - } - - CString s=language.sections[sec].values[u8EnglishString]; -#ifndef RA2_MODE - s=TranslateStringVariables(9,s,"FinalSun"); -#else -#ifdef YR_MODE - s=TranslateStringVariables(9,s,"FinalAlert 2: Yuri's Revenge"); -#else - s=TranslateStringVariables(9,s,"FinalAlert 2"); -#endif -#endif - - return ToACP(s); + return GetLanguageStringACP(u8EnglishString); } @@ -766,210 +694,100 @@ std::array HSVToRGB(const unsigned char hsv[3]) return ret; } -void ListBuildings(CComboBox& cb, BOOL bININame) +void listSpecifcTechnoTypes(CComboBox& cb, const CString& sectionName, bool clear = true, bool useIniName = false) { - while(cb.DeleteString(0)!=CB_ERR); + if (clear) { + while (cb.DeleteString(0) != CB_ERR); + } + auto const& sec = rules.GetSection(sectionName); + for (auto idx = 0; idx < sec.Size(); ++idx) { + char idxNum[50]; + itoa(idx, idxNum, 10); + CString record = idxNum; - int i; - for(i=0;iGetUnitName(*rules.sections["BuildingTypes"].GetValue(i)); - - if(bININame) s=*rules.sections["BuildingTypes"].GetValue(i); - - s+=" "; + if (useIniName) { + record = kvPair.second; + } + record += " "; - CString t=Map->GetUnitName(*rules.sections["BuildingTypes"].GetValue(i)); + CString translated = Map->GetUnitName(kvPair.second); //if(t!="MISSING") { - s+=t; - cb.AddString(s); + record += translated; + cb.AddString(record); } } } +void listSpecifcTypesWithSequence(CComboBox& cb, const CString& sectionName, bool clear = true) { + if (clear) { + while (cb.DeleteString(0) != CB_ERR); + } + auto const& sec = rules.GetSection(sectionName); + for (auto idx = 0; idx < sec.Size(); ++idx) { + char idxNum[50]; + itoa(idx, idxNum, 10); + auto const& kvPair = sec.Nth(idx); + CString record = idxNum; + record += " "; + record += kvPair.second; + cb.AddString(record); + } +} + +void ListBuildings(CComboBox& cb, bool bININame) +{ + listSpecifcTechnoTypes(cb, "BuildingTypes", true, bININame); +} + void ListInfantry(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - for(i=0;iGetUnitName(*rules.sections["InfantryTypes"].GetValue(i)); - CString t=Map->GetUnitName(*rules.sections["InfantryTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } + listSpecifcTechnoTypes(cb, "InfantryTypes"); } void ListUnits(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - for(i=0;iGetUnitName(*rules.sections["VehicleTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } + listSpecifcTechnoTypes(cb, "VehicleTypes"); } void ListAircraft(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - for(i=0;iGetUnitName(*rules.sections["AircraftTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } + listSpecifcTechnoTypes(cb, "AircraftTypes"); } void ListTechtypes(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - for(i=0;iGetUnitName(*rules.sections["AircraftTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } - for(i=0;iGetUnitName(*rules.sections["InfantryTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } - for(i=0;iGetUnitName(*rules.sections["VehicleTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } - } - for(i=0;iGetUnitName(*rules.sections["BuildingTypes"].GetValue(i)); - //if(t!="MISSING") - { - s+=t; - cb.AddString(s); - } + for (auto const& kvPair : ini.GetSection("VariableNames")) { + auto const desc = kvPair.first + " " + kvPair.second; + cb.AddString(desc); } } // should be ListLocals() void ListGlobals(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - CIniFile& ini=Map->GetIniFile(); - for(i=0;iGetIniFile()); } void ListRulesGlobals(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - for(i=0;i AllStrings; +extern TranslationMap AllStrings; void ListTutorial(CComboBox& cb) { while(cb.DeleteString(0)!=CB_ERR); @@ -1014,22 +832,18 @@ void ListTutorial(CComboBox& cb) void ListTriggers(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); - int i; - CIniFile& ini=Map->GetIniFile(); - for(i=0;iGetIniFile(); + + for (auto const& kvPair : ini.GetSection("Triggers")) { + auto s = kvPair.first; + s += " ("; + s += GetParam(kvPair.second, 2); + s += ")"; cb.AddString(s); - } + } + } void ListYesNo(CComboBox& cb) @@ -1041,106 +855,57 @@ void ListYesNo(CComboBox& cb) void ListSounds(CComboBox& cb) { - while(cb.DeleteString(0)!=CB_ERR); + while (cb.DeleteString(0) != CB_ERR); #ifdef RA2_MODE - int i; - for(i=0;i"); - for(i=0;i"); } - if(sel>=0) cb.SetCurSel(sel); + auto const& movieList = art.GetSection("Movies"); + for (auto idx = 0; idx < movieList.Size();++idx) { + if (idx < atoi(g_data.GetString("MovieList", "Start"))) { + continue; + } + CString movieID = movieList.Nth(idx).second; + cb.AddString(movieID); + } + if (sel >= 0) { + cb.SetCurSel(sel); + } + return; } - else - { - - while(cb.DeleteString(0)!=CB_ERR); - - int i; - for(i=0;iGetIniFile(); + CIniFile& ini = Map->GetIniFile(); - int sel=cb.GetCurSel(); + int sel = cb.GetCurSel(); - while(cb.DeleteString(0)!=CB_ERR); + while (cb.DeleteString(0) != CB_ERR); int i; - if(bListNone) cb.AddString("None"); - for(i=0;i=0) cb.SetCurSel(sel); + if (sel >= 0) { + cb.SetCurSel(sel); + } } int GetRulesHousesSize() { - int i; - int count=0; - for(i=0;i(); + toDelete.reserve(sec.Size()); - for(i=0;iRemoveAt(idx); + } + } - return count; + return GetRulesHousesSize(); } // MW 07/27/01: Modified for etc in YR @@ -1264,22 +1017,23 @@ void ListHouses(CComboBox &cb, BOOL bNumbers, BOOL bCountries, BOOL bPlayers) { CIniFile& ini=Map->GetIniFile(); - int i; - int sel=cb.GetCurSel(); - int crulesh=GetRulesHousesSize(); + int sel = cb.GetCurSel(); + int crulesh = GetRulesHousesSize(); - if(Map->IsMultiplayer()==FALSE) bPlayers=FALSE; // really only for multi maps! + // TODO: align with RN edition + if (Map->IsMultiplayer() == FALSE) { + bPlayers = FALSE; // really only for multi maps! + } - //for(i=0;iSize() == 0) { + goto wasnohouse; + } // we use the map definitions! if(yuri_mode && bPlayers) @@ -1310,79 +1064,74 @@ void ListHouses(CComboBox &cb, BOOL bNumbers, BOOL bCountries, BOOL bPlayers) } - for(i=0;iSize(); i++) { CString j; #ifdef RA2_MODE - j=*ini.sections[sSection].GetValue(i); + j = mapHouseList->Nth(i).second; j.MakeLower(); - if(j=="nod" || j=="gdi") continue; -#endif + if (j == "nod" || j == "gdi") { + continue; + } +#endif - if(bNumbers) - { - char c[50]; - int n=atoi(*ini.sections[sSection].GetValueName(i)); - itoa(n, c, 10); + if(bNumbers) { + char idxStr[50]; + itoa(i, idxStr, 10); #ifdef RA2_MODE - if(bCountries) - { - int preexisting=0; + if(bCountries) { + int preexisting = 0; int e; - for(e=0;e=0) + auto const& rulesMapList = rules.GetSection(sSection); + for (e = 0; e < i; e++) { + if (rulesMapList.HasValue(mapHouseList->Nth(e).second)) { preexisting++; + } } - if(rules.sections[sSection].FindValue(*ini.sections[sSection].GetValue(i))>=0) - { - itoa(rules.sections[sSection].value_orig_pos[*rules.sections[sSection].GetValueName(rules.sections[sSection].FindValue(*ini.sections[sSection].GetValue(i)))], c, 10); + if (rulesMapList.HasValue(mapHouseList->Nth(i).second)) { + auto const& mapHouseID = mapHouseList->Nth(i).second; + auto const& idxInRules = rulesMapList.FindValue(mapHouseID); + itoa(idxInRules, idxStr, 10); } - else - { - itoa(n+crulesh-preexisting, c, 10); + else { + itoa(i + crulesh - preexisting, idxStr, 10); } } #endif - j=c; - j+=" "; - j+=TranslateHouse(*ini.sections[sSection].GetValue(i), TRUE); + j = idxStr; + j += " "; + j += TranslateHouse(mapHouseList->Nth(i).second, TRUE); + } + else { + j = TranslateHouse(mapHouseList->Nth(i).second, TRUE); } - else - j=TranslateHouse(*ini.sections[sSection].GetValue(i), TRUE); - cb.AddString(j); } } - else - { + else { wasnohouse: - if(bNumbers) - { - - for(i=0;i"); cb.AddString("4476 "); cb.AddString("4477 "); @@ -1412,10 +1160,8 @@ void ListHouses(CComboBox &cb, BOOL bNumbers, BOOL bCountries, BOOL bPlayers) cb.AddString("4482 "); } } - else - { - if(yuri_mode && bPlayers) - { + else { + if(yuri_mode && bPlayers) { cb.AddString(""); cb.AddString(""); cb.AddString(""); @@ -1426,77 +1172,76 @@ void ListHouses(CComboBox &cb, BOOL bNumbers, BOOL bCountries, BOOL bPlayers) cb.AddString(""); } - for(i=0;i=0) cb.SetCurSel(sel); - + if (sel >= 0) { + cb.SetCurSel(sel); + } } void ListTeamTypes(CComboBox &cb, BOOL bListNone) { - CIniFile& ini=Map->GetIniFile(); + CIniFile& ini = Map->GetIniFile(); - int sel=cb.GetCurSel(); + int sel = cb.GetCurSel(); - while(cb.DeleteString(0)!=CB_ERR); + while (cb.DeleteString(0) != CB_ERR); int i; - if(bListNone) cb.AddString(""); - for(i=0;i"); + } + auto const& teamTypeList = ini.GetSection("TeamTypes"); + for (auto const& [seq, id] : teamTypeList) { + auto const& teamTypeDetail = ini.GetSection(id); + CString record = id + " " + teamTypeDetail.GetString("Name"); + cb.AddString(record); } - if(sel>=0) cb.SetCurSel(sel); + if (sel >= 0) { + cb.SetCurSel(sel); + } } void ListWaypoints(CComboBox &cb) { - CIniFile& ini=Map->GetIniFile(); + CIniFile& ini = Map->GetIniFile(); - int sel=cb.GetCurSel(); + int sel = cb.GetCurSel(); - while(cb.DeleteString(0)!=CB_ERR); + while (cb.DeleteString(0) != CB_ERR); - int i; - for(i=0;i=0) cb.SetCurSel(sel); + if (sel >= 0) { + cb.SetCurSel(sel); + } } void ListTargets(CComboBox &cb) @@ -1532,42 +1277,41 @@ CString GetHouseSectionName(CString lpHouse) CString GetFreeID() { - CIniFile& ini=Map->GetIniFile(); + auto const& ini = Map->GetIniFile(); - int n=1000000; - while(TRUE) - { + int n = 1000000; + + auto isIDInUse = [&ini](const CString& input) { + static const CString typeListSections[] = { + "ScriptTypes", + "TaskForces", + "TeamTypes", + }; + static const CString idListSections[] = { + "Triggers", + "Events", + "Tags", + "Actions", + "AITriggerTypes", + }; + auto const found = find(std::begin(typeListSections), std::end(typeListSections), [&ini, input](auto const& key) { + return ini.GetSection(key).HasValue(input); + }); + if (found != std::end(typeListSections)) { + return true; + } + }; + + for (;;) { char p[50]; - p[0]='0'; - itoa(n,p+1,10); - if(ini.sections["ScriptTypes"].FindValue(p)==-1) - { - if(ini.sections["TaskForces"].FindValue(p)==-1) - { - if(ini.sections["TeamTypes"].FindValue(p)==-1) - { - if(ini.sections["Triggers"].values.find(p)==ini.sections["Triggers"].values.end()) - { - if(ini.sections["Events"].values.find(p)==ini.sections["Events"].values.end()) - { - if(ini.sections["Tags"].values.find(p)==ini.sections["Tags"].values.end()) - { - if(ini.sections["Actions"].values.find(p)==ini.sections["Actions"].values.end()) - { - if(ini.sections["AITriggerTypes"].values.find(p)==ini.sections["AITriggerTypes"].values.end()) - { - if(ini.sections.find(p)==ini.sections.end()) - return p; - } - } - } - } - } - } - } + p[0] = '0'; + itoa(n, p + 1, 10); + + if (!isIDInUse(p)) { + return p; } n++; - } + } return ""; } @@ -1597,74 +1341,72 @@ void GetNodeName(CString & name, int n) name=c; } -int GetNodeAt(CString& owner, CString& type, int x, int y) +int GetNodeAt(CString& owner, CString& buildingTypeID, int x, int y) { - CIniFile& ini=Map->GetIniFile(); + CIniFile& ini = Map->GetIniFile(); - type=""; - owner=""; + buildingTypeID = ""; + owner = ""; int owners; - if(ini.sections.find(HOUSES)!=ini.sections.end()) - { - for(owners=0;owners