diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index b92d10de2..c74feb4ee 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -307,9 +307,11 @@ "vcmi.optionsTab.extraOptions.hover" : "Extra Options", "vcmi.optionsTab.extraOptions.help" : "Additional settings for the game.", - + "vcmi.optionsTab.cheatAllowed.hover" : "Allow cheats", + "vcmi.optionsTab.unlimitedReplay.hover" : "Unlimited battle replay", "vcmi.optionsTab.cheatAllowed.help" : "{Allow cheats}\nAllows the inputs of cheats during the game.", + "vcmi.optionsTab.unlimitedReplay.help" : "{Unlimited battle replay}\nNo limit of replaying battles.", // Custom victory conditions for H3 campaigns and HotA maps "vcmi.map.victoryCondition.daysPassed.toOthers" : "The enemy has managed to survive till this day. Victory is theirs!", diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json index f9913c466..63b47a326 100644 --- a/Mods/vcmi/config/vcmi/german.json +++ b/Mods/vcmi/config/vcmi/german.json @@ -303,7 +303,9 @@ "vcmi.optionsTab.extraOptions.help" : "Zusätzliche Einstellungen für das Spiel.", "vcmi.optionsTab.cheatAllowed.hover" : "Cheats erlauben", + "vcmi.optionsTab.unlimitedReplay.hover" : "Unbegrenzte Kampfwiederholung", "vcmi.optionsTab.cheatAllowed.help" : "{Cheats erlauben}\nErlaubt die Eingabe von Cheats während des Spiels.", + "vcmi.optionsTab.unlimitedReplay.help" : "{Unbegrenzte Kampfwiederholung}\nKämpfe lassen sich unbegrenzt wiederholen.", // Custom victory conditions for H3 campaigns and HotA maps "vcmi.map.victoryCondition.daysPassed.toOthers" : "Der Feind hat es geschafft, bis zum heutigen Tag zu überleben. Der Sieg gehört ihm!", diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 0fd4f4db6..28e65961c 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -507,11 +507,11 @@ void CServerHandler::setTurnTimerInfo(const TurnTimerInfo & info) const sendLobbyPack(lstt); } -void CServerHandler::setCheatAllowedInfo(bool allowed) const +void CServerHandler::setExtraOptionsInfo(const ExtraOptionsInfo & info) const { - LobbySetCheatAllowed lsca; - lsca.allowed = allowed; - sendLobbyPack(lsca); + LobbySetExtraOptions lseo; + lseo.extraOptionsInfo = info; + sendLobbyPack(lseo); } void CServerHandler::sendMessage(const std::string & txt) const diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 9d196fab8..e4a5d02ca 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -72,7 +72,7 @@ public: virtual void setDifficulty(int to) const = 0; virtual void setTurnTimerInfo(const TurnTimerInfo &) const = 0; virtual void setSimturnsInfo(const SimturnsInfo &) const = 0; - virtual void setCheatAllowedInfo(bool allowed) const = 0; + virtual void setExtraOptionsInfo(const ExtraOptionsInfo & info) const = 0; virtual void sendMessage(const std::string & txt) const = 0; virtual void sendGuiAction(ui8 action) const = 0; // TODO: possibly get rid of it? virtual void sendStartGame(bool allowOnlyAI = false) const = 0; @@ -159,7 +159,7 @@ public: void setDifficulty(int to) const override; void setTurnTimerInfo(const TurnTimerInfo &) const override; void setSimturnsInfo(const SimturnsInfo &) const override; - void setCheatAllowedInfo(bool allowed) const override; + void setExtraOptionsInfo(const ExtraOptionsInfo &) const override; void sendMessage(const std::string & txt) const override; void sendGuiAction(ui8 action) const override; void sendRestartGame() const override; diff --git a/client/battle/BattleInterfaceClasses.cpp b/client/battle/BattleInterfaceClasses.cpp index 0986834ce..6ef0b7b73 100644 --- a/client/battle/BattleInterfaceClasses.cpp +++ b/client/battle/BattleInterfaceClasses.cpp @@ -471,7 +471,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface exit = std::make_shared(Point(384, 505), AnimationPath::builtin("iok6432.def"), std::make_pair("", ""), [&](){ bExitf();}, EShortcut::GLOBAL_ACCEPT); exit->setBorderColor(Colors::METALLIC_GOLD); - if(allowReplay) + if(allowReplay || owner.cb->getStartInfo()->extraOptionsInfo.unlimitedReplay) { repeat = std::make_shared(Point(24, 505), AnimationPath::builtin("icn6432.def"), std::make_pair("", ""), [&](){ bRepeatf();}, EShortcut::GLOBAL_CANCEL); repeat->setBorderColor(Colors::METALLIC_GOLD); diff --git a/client/lobby/OptionsTabBase.cpp b/client/lobby/OptionsTabBase.cpp index 421b5673b..c0bba17e6 100644 --- a/client/lobby/OptionsTabBase.cpp +++ b/client/lobby/OptionsTabBase.cpp @@ -91,7 +91,15 @@ OptionsTabBase::OptionsTabBase(const JsonPath & configPath) }); addCallback("setCheatAllowed", [&](int index){ - CSH->setCheatAllowedInfo(index); + ExtraOptionsInfo info = SEL->getStartInfo()->extraOptionsInfo; + info.cheatsAllowed = index; + CSH->setExtraOptionsInfo(info); + }); + + addCallback("setUnlimitedReplay", [&](int index){ + ExtraOptionsInfo info = SEL->getStartInfo()->extraOptionsInfo; + info.unlimitedReplay = index; + CSH->setExtraOptionsInfo(info); }); addCallback("setTurnTimerAccumulate", [&](int index){ @@ -391,5 +399,8 @@ void OptionsTabBase::recreate() } if(auto buttonCheatAllowed = widget("buttonCheatAllowed")) - buttonCheatAllowed->setSelectedSilent(SEL->getStartInfo()->cheatAllowed); + buttonCheatAllowed->setSelectedSilent(SEL->getStartInfo()->extraOptionsInfo.cheatsAllowed); + + if(auto buttonUnlimitedReplay = widget("buttonUnlimitedReplay")) + buttonUnlimitedReplay->setSelectedSilent(SEL->getStartInfo()->extraOptionsInfo.unlimitedReplay); } diff --git a/config/widgets/extraOptionsTab.json b/config/widgets/extraOptionsTab.json index cabc24dfe..1c77dfeab 100644 --- a/config/widgets/extraOptionsTab.json +++ b/config/widgets/extraOptionsTab.json @@ -1,4 +1,6 @@ { + "library" : "config/widgets/settings/library.json", + "items": [ { @@ -52,21 +54,48 @@ "color": [24, 41, 90, 255] }, { - "name": "buttonCheatAllowed", + "name": "ExtraOptionsButtons", + "type" : "verticalLayout", + "customType" : "toggleButton", "position": {"x": 70, "y": 100}, - "type": "toggleButton", - "image": "lobby/checkbox", - "callback" : "setCheatAllowed", - "selected" : true + "items": + [ + { + "name": "buttonCheatAllowed", + "image": "lobby/checkbox", + "callback" : "setCheatAllowed", + "selected" : true + }, + { + "name": "buttonUnlimitedReplay", + "image": "lobby/checkbox", + "callback" : "setUnlimitedReplay", + "selected" : true + } + ] }, { - "name": "labelCheatAllowed", - "type": "label", - "font": "small", - "alignment": "left", - "color": "yellow", - "text": "vcmi.optionsTab.cheatAllowed.hover", - "position": {"x": 110, "y": 103} + "name": "ExtraOptionsLabels", + "type" : "verticalLayout", + "customType" : "label", + "position": {"x": 110, "y": 103}, + "items": + [ + { + "name": "labelCheatAllowed", + "font": "small", + "alignment": "left", + "color": "yellow", + "text": "vcmi.optionsTab.cheatAllowed.hover" + }, + { + "name": "labelUnlimitedReplay", + "font": "small", + "alignment": "left", + "color": "yellow", + "text": "vcmi.optionsTab.unlimitedReplay.hover" + } + ] } ] } diff --git a/lib/ExtraOptionsInfo.cpp b/lib/ExtraOptionsInfo.cpp new file mode 100644 index 000000000..2411608b7 --- /dev/null +++ b/lib/ExtraOptionsInfo.cpp @@ -0,0 +1,21 @@ +/* + * ExtraOptionsInfo.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "ExtraOptionsInfo.h" + +VCMI_LIB_NAMESPACE_BEGIN + +bool ExtraOptionsInfo::operator == (const ExtraOptionsInfo & other) const +{ + return cheatsAllowed == other.cheatsAllowed && + unlimitedReplay == other.unlimitedReplay; +} + +VCMI_LIB_NAMESPACE_END diff --git a/lib/ExtraOptionsInfo.h b/lib/ExtraOptionsInfo.h new file mode 100644 index 000000000..3b1e65d1b --- /dev/null +++ b/lib/ExtraOptionsInfo.h @@ -0,0 +1,30 @@ +/* + * ExtraOptionsInfo.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +#pragma once + +VCMI_LIB_NAMESPACE_BEGIN + +struct DLL_LINKAGE ExtraOptionsInfo +{ + bool cheatsAllowed = true; + bool unlimitedReplay = false; + + bool operator == (const ExtraOptionsInfo & other) const; + + template + void serialize(Handler &h, const int version) + { + h & cheatsAllowed; + h & unlimitedReplay; + } +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/StartInfo.h b/lib/StartInfo.h index 1c854c2c5..eed03eb21 100644 --- a/lib/StartInfo.h +++ b/lib/StartInfo.h @@ -13,6 +13,7 @@ #include "GameConstants.h" #include "TurnTimerInfo.h" +#include "ExtraOptionsInfo.h" #include "campaign/CampaignConstants.h" VCMI_LIB_NAMESPACE_BEGIN @@ -105,8 +106,6 @@ struct DLL_LINKAGE StartInfo EMode mode; ui8 difficulty; //0=easy; 4=impossible - bool cheatAllowed; - using TPlayerInfos = std::map; TPlayerInfos playerInfos; //color indexed @@ -117,6 +116,7 @@ struct DLL_LINKAGE StartInfo std::string fileURI; SimturnsInfo simturnsInfo; TurnTimerInfo turnTimerInfo; + ExtraOptionsInfo extraOptionsInfo; std::string mapname; // empty for random map, otherwise name of the map or savegame bool createRandomMap() const { return mapGenOptions != nullptr; } std::shared_ptr mapGenOptions; @@ -144,16 +144,16 @@ struct DLL_LINKAGE StartInfo h & simturnsInfo; h & turnTimerInfo; if(version >= 832) - h & cheatAllowed; + h & extraOptionsInfo; else - cheatAllowed = true; + extraOptionsInfo = ExtraOptionsInfo(); h & mapname; h & mapGenOptions; h & campState; } StartInfo() : mode(INVALID), difficulty(1), seedToBeUsed(0), seedPostInit(0), - mapfileChecksum(0), startTimeIso8601(vstd::getDateTimeISO8601Basic(std::time(nullptr))), fileURI(""), cheatAllowed(true) + mapfileChecksum(0), startTimeIso8601(vstd::getDateTimeISO8601Basic(std::time(nullptr))), fileURI("") { } diff --git a/lib/networkPacks/NetPackVisitor.h b/lib/networkPacks/NetPackVisitor.h index 94a24c533..c77705174 100644 --- a/lib/networkPacks/NetPackVisitor.h +++ b/lib/networkPacks/NetPackVisitor.h @@ -164,7 +164,7 @@ public: virtual void visitLobbySetPlayerName(LobbySetPlayerName & pack) {} virtual void visitLobbySetSimturns(LobbySetSimturns & pack) {} virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) {} - virtual void visitLobbySetCheatAllowed(LobbySetCheatAllowed & pack) {} + virtual void visitLobbySetExtraOptions(LobbySetExtraOptions & pack) {} virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) {} virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) {} virtual void visitLobbyShowMessage(LobbyShowMessage & pack) {} diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 08134f3aa..a1b9a299e 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -770,9 +770,9 @@ void LobbySetTurnTime::visitTyped(ICPackVisitor & visitor) visitor.visitLobbySetTurnTime(*this); } -void LobbySetCheatAllowed::visitTyped(ICPackVisitor & visitor) +void LobbySetExtraOptions::visitTyped(ICPackVisitor & visitor) { - visitor.visitLobbySetCheatAllowed(*this); + visitor.visitLobbySetExtraOptions(*this); } void LobbySetDifficulty::visitTyped(ICPackVisitor & visitor) diff --git a/lib/networkPacks/PacksForLobby.h b/lib/networkPacks/PacksForLobby.h index eb2c55371..50b001425 100644 --- a/lib/networkPacks/PacksForLobby.h +++ b/lib/networkPacks/PacksForLobby.h @@ -287,15 +287,15 @@ struct DLL_LINKAGE LobbySetTurnTime : public CLobbyPackToServer } }; -struct DLL_LINKAGE LobbySetCheatAllowed : public CLobbyPackToServer +struct DLL_LINKAGE LobbySetExtraOptions : public CLobbyPackToServer { - bool allowed; + ExtraOptionsInfo extraOptionsInfo; void visitTyped(ICPackVisitor & visitor) override; template void serialize(Handler &h, const int version) { - h & allowed; + h & extraOptionsInfo; } }; diff --git a/lib/registerTypes/RegisterTypesLobbyPacks.h b/lib/registerTypes/RegisterTypesLobbyPacks.h index c5b5814b1..8ef908b34 100644 --- a/lib/registerTypes/RegisterTypesLobbyPacks.h +++ b/lib/registerTypes/RegisterTypesLobbyPacks.h @@ -57,7 +57,7 @@ void registerTypesLobbyPacks(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); - s.template registerType(); + s.template registerType(); } VCMI_LIB_NAMESPACE_END diff --git a/server/LobbyNetPackVisitors.h b/server/LobbyNetPackVisitors.h index 4b93ea26c..6304f561a 100644 --- a/server/LobbyNetPackVisitors.h +++ b/server/LobbyNetPackVisitors.h @@ -88,7 +88,7 @@ public: virtual void visitLobbySetPlayer(LobbySetPlayer & pack) override; virtual void visitLobbySetPlayerName(LobbySetPlayerName & pack) override; virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) override; - virtual void visitLobbySetCheatAllowed(LobbySetCheatAllowed & pack) override; + virtual void visitLobbySetExtraOptions(LobbySetExtraOptions & pack) override; virtual void visitLobbySetSimturns(LobbySetSimturns & pack) override; virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) override; virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) override; diff --git a/server/NetPacksLobbyServer.cpp b/server/NetPacksLobbyServer.cpp index 787d8a63a..bb99323a5 100644 --- a/server/NetPacksLobbyServer.cpp +++ b/server/NetPacksLobbyServer.cpp @@ -414,9 +414,9 @@ void ApplyOnServerNetPackVisitor::visitLobbySetTurnTime(LobbySetTurnTime & pack) result = true; } -void ApplyOnServerNetPackVisitor::visitLobbySetCheatAllowed(LobbySetCheatAllowed & pack) +void ApplyOnServerNetPackVisitor::visitLobbySetExtraOptions(LobbySetExtraOptions & pack) { - srv.si->cheatAllowed = pack.allowed; + srv.si->extraOptionsInfo = pack.extraOptionsInfo; result = true; } diff --git a/server/processors/PlayerMessageProcessor.cpp b/server/processors/PlayerMessageProcessor.cpp index 94a9ca789..0cf0a19b4 100644 --- a/server/processors/PlayerMessageProcessor.cpp +++ b/server/processors/PlayerMessageProcessor.cpp @@ -440,7 +440,7 @@ bool PlayerMessageProcessor::handleCheatCode(const std::string & cheat, PlayerCo std::vector words; boost::split(words, cheat, boost::is_any_of("\t\r\n ")); - if (words.empty() || !gameHandler->getStartInfo()->cheatAllowed) + if (words.empty() || !gameHandler->getStartInfo()->extraOptionsInfo.cheatsAllowed) return false; //Make cheat name case-insensitive, but keep words/parameters (e.g. creature name) as it