2
0
Эх сурвалжийг харах

Merge pull request #5723 from Laserlicht/cheats

Cheats improvements
Ivan Savenko 4 сар өмнө
parent
commit
4cd911247d

+ 6 - 1
client/CPlayerInterface.cpp

@@ -46,6 +46,7 @@
 #include "render/CAnimation.h"
 #include "render/IImage.h"
 #include "render/IRenderHandler.h"
+#include "render/IScreenHandler.h"
 
 #include "widgets/Buttons.h"
 #include "widgets/CComponent.h"
@@ -1826,6 +1827,11 @@ void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectP
 	adventureInt->openWorldView(objectPositions, showTerrain );
 }
 
+void CPlayerInterface::setColorScheme(ColorScheme scheme)
+{
+	ENGINE->screenHandler().setColorScheme(scheme);
+}
+
 std::optional<BattleAction> CPlayerInterface::makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState)
 {
 	return std::nullopt;
@@ -1843,4 +1849,3 @@ void CPlayerInterface::unregisterBattleInterface(std::shared_ptr<CBattleGameInte
 	GAME->server().client->unregisterBattleInterface(autofightingAI, playerID);
 	autofightingAI.reset();
 }
-

+ 1 - 0
client/CPlayerInterface.h

@@ -145,6 +145,7 @@ protected: // Call-ins from server, should not be called directly, but only via
 	void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active interface
 	void playerEndsTurn(PlayerColor player) override;
 	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
+	void setColorScheme(ColorScheme scheme) override;
 
 	//for battles
 	void actionFinished(const BattleID & battleID, const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero

+ 1 - 0
client/ClientNetPackVisitors.h

@@ -103,6 +103,7 @@ public:
 	void visitNewObject(NewObject & pack) override;
 	void visitSetAvailableArtifacts(SetAvailableArtifacts & pack) override;
 	void visitEntitiesChanged(EntitiesChanged & pack) override;
+	void visitPlayerCheated(PlayerCheated & pack) override;
 };
 
 class ApplyFirstClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)

+ 6 - 1
client/NetPacksClient.cpp

@@ -1074,8 +1074,13 @@ void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts
 	}
 }
 
-
 void ApplyClientNetPackVisitor::visitEntitiesChanged(EntitiesChanged & pack)
 {
 	callAllInterfaces(cl, &CGameInterface::invalidatePaths);
 }
+
+void ApplyClientNetPackVisitor::visitPlayerCheated(PlayerCheated & pack)
+{
+	if(pack.colorScheme != ColorScheme::KEEP && vstd::contains(cl.playerint, pack.player))
+		cl.playerint[pack.player]->setColorScheme(pack.colorScheme);
+}

+ 4 - 0
client/render/IScreenHandler.h

@@ -10,6 +10,8 @@
 
 #pragma once
 
+#include "../../lib/constants/Enumerations.h"
+
 VCMI_LIB_NAMESPACE_BEGIN
 class Point;
 class Rect;
@@ -58,4 +60,6 @@ public:
 
 	/// Window has focus
 	virtual bool hasFocus() = 0;
+
+	virtual void setColorScheme(ColorScheme scheme) = 0;
 };

+ 42 - 21
client/renderSDL/SDL_Extensions.cpp

@@ -542,38 +542,59 @@ void CSDL_Ext::putPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x,
 		CSDL_Ext::putPixelWithoutRefresh(ekran, x, y, R, G, B, A);
 }
 
-template<int bpp>
-void CSDL_Ext::convertToGrayscaleBpp(SDL_Surface * surf, const Rect & rect )
+template<typename Functor>
+void loopOverPixel(SDL_Surface * surf, const Rect & rect, Functor functor)
 {
 	uint8_t * pixels = static_cast<uint8_t*>(surf->pixels);
 
-	for(int yp = rect.top(); yp < rect.bottom(); ++yp)
+	tbb::parallel_for(tbb::blocked_range<size_t>(rect.top(), rect.bottom()), [&](const tbb::blocked_range<size_t>& r)
 	{
-		uint8_t * pixel_from = pixels + yp * surf->pitch + rect.left() * surf->format->BytesPerPixel;
-		uint8_t * pixel_dest = pixels + yp * surf->pitch + rect.right() * surf->format->BytesPerPixel;
-
-		for (uint8_t * pixel = pixel_from; pixel < pixel_dest; pixel += surf->format->BytesPerPixel)
+		for(int yp = r.begin(); yp != r.end(); ++yp)
 		{
-			int r = Channels::px<bpp>::r.get(pixel);
-			int g = Channels::px<bpp>::g.get(pixel);
-			int b = Channels::px<bpp>::b.get(pixel);
+			uint8_t * pixel_from = pixels + yp * surf->pitch + rect.left() * surf->format->BytesPerPixel;
+			uint8_t * pixel_dest = pixels + yp * surf->pitch + rect.right() * surf->format->BytesPerPixel;
+
+			for (uint8_t * pixel = pixel_from; pixel < pixel_dest; pixel += surf->format->BytesPerPixel)
+			{
+				int r = Channels::px<4>::r.get(pixel);
+				int g = Channels::px<4>::g.get(pixel);
+				int b = Channels::px<4>::b.get(pixel);
 
-			int gray = static_cast<int>(0.299 * r + 0.587 * g + 0.114 *b);
+				functor(r, g, b);
 
-			Channels::px<bpp>::r.set(pixel, gray);
-			Channels::px<bpp>::g.set(pixel, gray);
-			Channels::px<bpp>::b.set(pixel, gray);
+				Channels::px<4>::r.set(pixel, r);
+				Channels::px<4>::g.set(pixel, g);
+				Channels::px<4>::b.set(pixel, b);
+			}
 		}
-	}
+	});
 }
 
-void CSDL_Ext::convertToGrayscale( SDL_Surface * surf, const Rect & rect )
+void CSDL_Ext::convertToGrayscale(SDL_Surface * surf, const Rect & rect )
 {
-	switch(surf->format->BytesPerPixel)
-	{
-		case 3: convertToGrayscaleBpp<3>(surf, rect); break;
-		case 4: convertToGrayscaleBpp<4>(surf, rect); break;
-	}
+	loopOverPixel(surf, rect, [](int &r, int &g, int &b){
+		int gray = static_cast<int>(0.299 * r + 0.587 * g + 0.114 * b);
+		r = gray;
+		g = gray;
+		b = gray;
+	});
+}
+
+void CSDL_Ext::convertToH2Scheme(SDL_Surface * surf, const Rect & rect )
+{
+	loopOverPixel(surf, rect, [](int &r, int &g, int &b){
+		double gray = 0.3 * r + 0.59 * g + 0.11 * b;
+		double factor = 2.0;
+
+		//fast approximation instead of colorspace conversion
+		r = static_cast<int>(gray + (r - gray) * factor);
+		g = static_cast<int>(gray + (g - gray) * factor);
+		b = static_cast<int>(gray + (b - gray) * factor);
+
+		r = std::clamp(r, 0, 255);
+		g = std::clamp(g, 0, 255);
+		b = std::clamp(b, 0, 255);
+	});
 }
 
 void CSDL_Ext::blitSurface(SDL_Surface * src, const Rect & srcRectInput, SDL_Surface * dst, const Point & dstPoint)

+ 1 - 2
client/renderSDL/SDL_Extensions.h

@@ -67,9 +67,8 @@ SDL_Color toSDL(const ColorRGBA & color);
 	SDL_Surface * newSurface(const Point & dimensions, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given
 	SDL_Surface * newSurface(const Point & dimensions); //creates new surface, with flags/format same as in screen surface
 
-	template<int bpp>
-	void convertToGrayscaleBpp(SDL_Surface * surf, const Rect & rect);
 	void convertToGrayscale(SDL_Surface * surf, const Rect & rect);
+	void convertToH2Scheme(SDL_Surface * surf, const Rect & rect);
 
 	void setColorKey(SDL_Surface * surface, SDL_Color color);
 

+ 20 - 1
client/renderSDL/ScreenHandler.cpp

@@ -11,6 +11,8 @@
 #include "StdInc.h"
 #include "ScreenHandler.h"
 
+#include "SDL_Extensions.h"
+
 #include "../CMT.h"
 #include "../eventsSDL/NotificationHandler.h"
 #include "../GameEngine.h"
@@ -623,7 +625,19 @@ Canvas ScreenHandler::getScreenCanvas() const
 
 void ScreenHandler::updateScreenTexture()
 {
-	SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch);
+	if(colorScheme == ColorScheme::NONE)
+	{
+		SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch);
+		return;
+	}
+
+	SDL_Surface * screenScheme = SDL_ConvertSurface(screen, screen->format, screen->flags);
+	if(colorScheme == ColorScheme::GRAYSCALE)
+		CSDL_Ext::convertToGrayscale(screenScheme, Rect(0, 0, screen->w, screen->h));
+	else if(colorScheme == ColorScheme::H2_SCHEME)
+		CSDL_Ext::convertToH2Scheme(screenScheme, Rect(0, 0, screen->w, screen->h));
+	SDL_UpdateTexture(screenTexture, nullptr, screenScheme->pixels, screenScheme->pitch);
+	SDL_FreeSurface(screenScheme);
 }
 
 void ScreenHandler::presentScreenTexture()
@@ -674,3 +688,8 @@ bool ScreenHandler::hasFocus()
 	ui32 flags = SDL_GetWindowFlags(mainWindow);
 	return flags & SDL_WINDOW_INPUT_FOCUS;
 }
+
+void ScreenHandler::setColorScheme(ColorScheme scheme)
+{
+	colorScheme = scheme;
+}

+ 3 - 0
client/renderSDL/ScreenHandler.h

@@ -49,6 +49,7 @@ class ScreenHandler final : public IScreenHandler
 	SDL_Surface * screen = nullptr;
 
 	EUpscalingFilter upscalingFilter = EUpscalingFilter::AUTO;
+	ColorScheme colorScheme = ColorScheme::NONE;
 
 	/// Dimensions of target surfaces/textures, this value is what game logic views as screen size
 	Point getPreferredLogicalResolution() const;
@@ -124,4 +125,6 @@ public:
 	std::vector<Point> getSupportedResolutions(int displayIndex) const;
 	std::tuple<int, int> getSupportedScalingRange() const final;
 	Rect convertLogicalPointsToWindow(const Rect & input) const final;
+
+	void setColorScheme(ColorScheme filter) final;
 };

+ 17 - 15
docs/players/Cheat_Codes.md

@@ -8,12 +8,12 @@ To use cheat code, press `Tab` key or click/tap on status bar to open game chat
 
 ### Spells
 
-`nwcthereisnospoon` or `vcmiistari` or `vcmispells` - give a spell book, all spells and 999 mana to currently selected hero
+`nwcthereisnospoon`, `nwcmidichlorians`, `nwctim`, `vcmiistari` or `vcmispells` - give a spell book, all spells and 999 mana to currently selected hero
 
 ### Army
 
-`nwctrinity` or `vcmiainur` or `vcmiarchangel` - give 5 Archangels in every empty slot (to currently selected hero)  
-`nwcagents` or `vcmiangband` or `vcmiblackknight` - give 10 black knight in every empty slot  
+`nwctrinity`, `nwcpadme`, `nwcavertingoureyes`, `vcmiainur` or `vcmiarchangel` - give 5 Archangels in every empty slot (to currently selected hero)  
+`nwcagents`, `nwcdarthmaul`, `nwcfleshwound` or `vcmiangband` or `vcmiblackknight` - give 10 black knight in every empty slot  
 `vcmiglaurung` or `vcmicrystal` - give 5000 crystal dragons in every empty slot  
 `vcmiazure` - give 5000 azure dragons in every empty slot  
 `vcmifaerie` - give 5000 faerie dragons in every empty slot  
@@ -25,32 +25,32 @@ Gives specific creature in every slot, with optional amount. Examples:
 
 ### Town buildings
 
-`nwczion` or `vcmiarmenelos` or `vcmibuild` - build all buildings in currently selected town
+`nwczion`, `nwccoruscant`, `nwconlyamodel`, `vcmiarmenelos` or `vcmibuild` - build all buildings in currently selected town
 
 ### Artifacts
 
-`nwclotsofguns` or `vcminoldor` or `vcmimachines` - give ballista, ammo cart and first aid tent  
+`nwclotsofguns`, `nwcr2d2`, `nwcantioch`, `vcminoldor` or `vcmimachines` - give ballista, ammo cart and first aid tent  
 `vcmiforgeofnoldorking` or `vcmiartifacts` - give all artifacts, except spell book, spell scrolls and war machines. Artifacts added via mods included  
 `vcmiscrolls` - give spell scrolls for every possible spells
 
 ### Movement points
 
-`nwcnebuchadnezzar` or `vcminahar` or `vcmimove` - give unlimited (or specified amount of) movement points and free ship boarding
+`nwcnebuchadnezzar`, `nwcpodracer`, `nwccoconuts`, `vcminahar` or `vcmimove` - give unlimited (or specified amount of) movement points and free ship boarding
 Alternative usage: `vcmimove <amount>` - gives specified amount of movement points
 
 ### Resources
 
-`nwctheconstruct` or `vcmiformenos` or `vcmiresources` - give resources (100000 gold, 100 of wood, ore and rare resources)  
+`nwctheconstruct`, `nwcwatto`, `nwcshrubbery`, `vcmiformenos` or `vcmiresources` - give resources (100000 gold, 100 of wood, ore and rare resources)  
 Alternative usage: `vcmiresources <amount>` - gives specified amount of all resources and x1000 of gold
 
 ### Fog of War
 
-`nwcwhatisthematrix` or `vcmieagles` or `vcmimap` - reveal Fog of War  
-`nwcignoranceisbliss` or `vcmiungoliant` or `vcmihidemap` - conceal Fog of War  
+`nwcwhatisthematrix`, `nwcrevealourselves`, `nwcgeneraldirection`, `vcmieagles` or `vcmimap` - reveal Fog of War  
+`nwcignoranceisbliss`,  `vcmiungoliant` or `vcmihidemap` - conceal Fog of War  
 
 ### Experience
 
-`nwcneo` or `vcmiglorfindel` or `vcmilevel` - advances currently selected hero to the next level
+`nwcneo`, `nwcquigon`, `nwcigotbetter`, `vcmiglorfindel` or `vcmilevel` - advances currently selected hero to the next level
 Alternative usage: `vcmilevel <amount>` - advances hero by specified number of levels
 
 - `vcmiolorin` or `vcmiexp` - gives selected hero 10000 experience
@@ -58,21 +58,23 @@ Alternative usage: `vcmiexp <amount>` - gives selected hero specified amount of
 
 ### Luck and morale
 
-`nwcfollowthewhiterabbit` or `vcmiluck` - the currently selected hero permanently gains maximum luck
-`nwcmorpheus` or `vcmimorale` - the currently selected hero permanently gains maximum morale
+`nwcfollowthewhiterabbit`, `nwccastleanthrax` or `vcmiluck` - the currently selected hero permanently gains maximum luck
+`nwcmorpheus`, `nwcmuchrejoicing` or `vcmimorale` - the currently selected hero permanently gains maximum morale
 
 ### Puzzle map
 
-`nwcoracle` or `vcmiobelisk` - reveals the puzzle map
+`nwcoracle`, `nwcprophecy`, `nwcalreadygotone` or `vcmiobelisk` - reveals the puzzle map
 
 ### Finishing the game
 
-`nwcredpill` or `vcmisilmaril` or `vcmiwin` - player wins
-`nwcbluepill` or `vcmimelkor` or `vcmilose` - player loses
+`nwcredpill`, `nwctrojanrabbit`, `vcmisilmaril` or `vcmiwin` - player wins
+`nwcbluepill`, `nwcsirrobin`, `vcmimelkor` or `vcmilose` - player loses
 
 ### Misc
 
 `nwctheone` or `vcmigod` - reveals the whole map, gives 5 archangels in each empty slot, unlimited movement points and permanent flight
+`nwcphisherprice` or `vcmicolor` - change game color palette to Heroes II like until game restart
+`vcmigray` - change game color palette to grayscale until game restart
 
 ## Using cheat codes on other players
 

+ 3 - 0
lib/callback/CGameInterface.h

@@ -11,6 +11,7 @@
 
 #include "CBattleGameInterface.h"
 #include "IGameEventsReceiver.h"
+#include "../constants/Enumerations.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -51,6 +52,8 @@ public:
 
 	/// Invalidates and destroys all paths for all heroes
 	virtual void invalidatePaths(){};
+
+	virtual void setColorScheme(ColorScheme scheme){};
 };
 
 VCMI_LIB_NAMESPACE_END

+ 8 - 0
lib/constants/Enumerations.h

@@ -259,6 +259,14 @@ enum class EWeekType : int8_t
 	PLAGUE
 };
 
+enum class ColorScheme : int8_t
+{
+	NONE,
+	KEEP,
+	GRAYSCALE,
+	H2_SCHEME
+};
+
 enum class ChangeValueMode : int8_t
 {
 	RELATIVE,

+ 1 - 1
lib/gameState/GameStatePackVisitor.cpp

@@ -1422,7 +1422,7 @@ void GameStatePackVisitor::visitPlayerCheated(PlayerCheated & pack)
 
 	gs.getPlayerState(pack.player)->enteredLosingCheatCode = pack.losingCheatCode;
 	gs.getPlayerState(pack.player)->enteredWinningCheatCode = pack.winningCheatCode;
-	gs.getPlayerState(pack.player)->cheated = true;
+	gs.getPlayerState(pack.player)->cheated = !pack.localOnlyCheat;
 }
 
 void GameStatePackVisitor::visitPlayerStartsTurn(PlayerStartsTurn & pack)

+ 5 - 0
lib/networkPacks/PacksForClient.h

@@ -112,16 +112,21 @@ struct DLL_LINKAGE PlayerBlocked : public CPackForClient
 struct DLL_LINKAGE PlayerCheated : public CPackForClient
 {
 	PlayerColor player;
+	bool localOnlyCheat = false;
+
 	bool losingCheatCode = false;
 	bool winningCheatCode = false;
+	ColorScheme colorScheme = ColorScheme::KEEP;
 
 	void visitTyped(ICPackVisitor & visitor) override;
 
 	template <typename Handler> void serialize(Handler & h)
 	{
 		h & player;
+		h & localOnlyCheat;
 		h & losingCheatCode;
 		h & winningCheatCode;
+		h & colorScheme;
 	}
 };
 

+ 120 - 75
server/processors/PlayerMessageProcessor.cpp

@@ -494,6 +494,15 @@ void PlayerMessageProcessor::cheatGiveScrolls(PlayerColor player, const CGHeroIn
 		}
 }
 
+void PlayerMessageProcessor::cheatColorSchemeChange(PlayerColor player, ColorScheme scheme)
+{
+	PlayerCheated pc;
+	pc.player = player;
+	pc.colorScheme = scheme;
+	pc.localOnlyCheat = true;
+	gameHandler->sendAndApply(pc);
+}
+
 void PlayerMessageProcessor::cheatLevelup(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words)
 {
 	if (!hero)
@@ -697,32 +706,45 @@ bool PlayerMessageProcessor::handleCheatCode(const std::string & cheat, PlayerCo
 	std::string cheatName = boost::to_lower_copy(words[0]);
 	words.erase(words.begin());
 
-	std::vector<std::string> townTargetedCheats = { "vcmiarmenelos", "vcmibuild", "nwczion" };
+	//	VCMI                       VCMI simple        SoD/HotA                   AB                    RoE
+	std::vector<std::string> localCheats = {
+		                           "vcmicolor",       "nwcphisherprice",
+		                           "vcmigray"
+	};
+	std::vector<std::string> townTargetedCheats = {
+		"vcmiarmenelos",           "vcmibuild",       "nwczion",                 "nwccoruscant",       "nwconlyamodel"
+	};
 	std::vector<std::string> playerTargetedCheats = {
-		"vcmiformenos",  "vcmiresources", "nwctheconstruct",
-		"vcmimelkor",    "vcmilose",      "nwcbluepill",
-		"vcmisilmaril",  "vcmiwin",       "nwcredpill",
-		"vcmieagles",    "vcmimap",       "nwcwhatisthematrix",
-		"vcmiungoliant", "vcmihidemap",   "nwcignoranceisbliss",
-		"vcmiobelisk",                    "nwcoracle"
+		"vcmiformenos",            "vcmiresources",   "nwctheconstruct",         "nwcwatto",           "nwcshrubbery",
+		"vcmimelkor",              "vcmilose",        "nwcbluepill",                                   "nwcsirrobin",
+		"vcmisilmaril",            "vcmiwin",         "nwcredpill",                                    "nwctrojanrabbit",
+		"vcmieagles",              "vcmimap",         "nwcwhatisthematrix",      "nwcrevealourselves", "nwcgeneraldirection",
+		"vcmiungoliant",           "vcmihidemap",     "nwcignoranceisbliss",
+		                           "vcmiobelisk",     "nwcoracle",               "nwcprophecy",        "nwcalreadygotone"
 	};
 	std::vector<std::string> heroTargetedCheats = {
-		"vcmiainur",               "vcmiarchangel",   "nwctrinity",
-		"vcmiangband",             "vcmiblackknight", "nwcagents",
+		"vcmiainur",               "vcmiarchangel",   "nwctrinity",              "nwcpadme",           "nwcavertingoureyes",
+		"vcmiangband",             "vcmiblackknight", "nwcagents",               "nwcdarthmaul",       "nwcfleshwound"
 		"vcmiglaurung",            "vcmicrystal",     "vcmiazure",
 		"vcmifaerie",              "vcmiarmy",        "vcminissi",
-		"vcmiistari",              "vcmispells",      "nwcthereisnospoon",
-		"vcminoldor",              "vcmimachines",    "nwclotsofguns",
-		"vcmiglorfindel",          "vcmilevel",       "nwcneo",
-		"vcminahar",               "vcmimove",        "nwcnebuchadnezzar",
+		"vcmiistari",              "vcmispells",      "nwcthereisnospoon",       "nwcmidichlorians",   "nwctim",
+		"vcminoldor",              "vcmimachines",    "nwclotsofguns",           "nwcr2d2",            "nwcantioch",
+		"vcmiglorfindel",          "vcmilevel",       "nwcneo",                  "nwcquigon",          "nwcigotbetter",
+		"vcminahar",               "vcmimove",        "nwcnebuchadnezzar",       "nwcpodracer",        "nwccoconuts",
 		"vcmiforgeofnoldorking",   "vcmiartifacts",
 		"vcmiolorin",              "vcmiexp",
-		"vcmiluck",                                   "nwcfollowthewhiterabbit", 
-		"vcmimorale",                                 "nwcmorpheus",
-		"vcmigod",                                    "nwctheone",
-		"vcmiscrolls"
+		                           "vcmiluck",        "nwcfollowthewhiterabbit",                       "nwccastleanthrax",
+		                           "vcmimorale",      "nwcmorpheus",                                   "nwcmuchrejoicing",
+		                           "vcmigod",         "nwctheone",
+		                           "vcmiscrolls"
 	};
 
+	if(vstd::contains(localCheats, cheatName))
+	{
+		executeCheatCode(cheatName, player, currObj, words);
+		return true;
+	}
+
 	if (!vstd::contains(townTargetedCheats, cheatName) && !vstd::contains(playerTargetedCheats, cheatName) && !vstd::contains(heroTargetedCheats, cheatName))
 		return false;
 
@@ -807,66 +829,89 @@ void PlayerMessageProcessor::executeCheatCode(const std::string & cheatName, Pla
 		cheatMovement(player, hero, { });
 		cheatFly(player, hero);
 	};
-
-	// Unimplemented H3 cheats:
-	// nwcphisherprice - Changes and brightens the game colors.
+	const auto & doColorSchemeChange = [&](ColorScheme filter) { cheatColorSchemeChange(player, filter); };
 
 	std::map<std::string, std::function<void()>> callbacks = {
-		{"vcmiainur",              [&] () {doCheatGiveArmyFixed({ "archangel", "5" });} },
-		{"nwctrinity",             [&] () {doCheatGiveArmyFixed({ "archangel", "5" });} },
-		{"vcmiangband",            [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });} },
-		{"vcmiglaurung",           [&] () {doCheatGiveArmyFixed({ "crystalDragon", "5000" });} },
-		{"vcmiarchangel",          [&] () {doCheatGiveArmyFixed({ "archangel", "5" });} },
-		{"nwcagents",              [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });} },
-		{"vcmiblackknight",        [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });} },
-		{"vcmicrystal",            [&] () {doCheatGiveArmyFixed({ "crystalDragon", "5000" });} },
-		{"vcmiazure",              [&] () {doCheatGiveArmyFixed({ "azureDragon", "5000" });} },
-		{"vcmifaerie",             [&] () {doCheatGiveArmyFixed({ "fairieDragon", "5000" });} },
-		{"vcmiarmy",                doCheatGiveArmyCustom },
-		{"vcminissi",               doCheatGiveArmyCustom },
-		{"vcmiistari",              doCheatGiveSpells     },
-		{"vcmispells",              doCheatGiveSpells     },
-		{"nwcthereisnospoon",       doCheatGiveSpells     },
-		{"vcmiarmenelos",           doCheatBuildTown      },
-		{"vcmibuild",               doCheatBuildTown      },
-		{"nwczion",                 doCheatBuildTown      },
-		{"vcminoldor",              doCheatGiveMachines   },
-		{"vcmimachines",            doCheatGiveMachines   },
-		{"nwclotsofguns",           doCheatGiveMachines   },
-		{"vcmiforgeofnoldorking",   doCheatGiveArtifacts  },
-		{"vcmiartifacts",           doCheatGiveArtifacts  },
-		{"vcmiglorfindel",          doCheatLevelup        },
-		{"vcmilevel",               doCheatLevelup        },
-		{"nwcneo",                  doCheatLevelup        },
-		{"vcmiolorin",              doCheatExperience     },
-		{"vcmiexp",                 doCheatExperience     },
-		{"vcminahar",               doCheatMovement       },
-		{"vcmimove",                doCheatMovement       },
-		{"nwcnebuchadnezzar",       doCheatMovement       },
-		{"vcmiformenos",            doCheatResources      },
-		{"vcmiresources",           doCheatResources      },
-		{"nwctheconstruct",         doCheatResources      },
-		{"nwcbluepill",             doCheatDefeat         },
-		{"vcmimelkor",              doCheatDefeat         },
-		{"vcmilose",                doCheatDefeat         },
-		{"nwcredpill",              doCheatVictory        },
-		{"vcmisilmaril",            doCheatVictory        },
-		{"vcmiwin",                 doCheatVictory        },
-		{"nwcwhatisthematrix",      doCheatMapReveal      },
-		{"vcmieagles",              doCheatMapReveal      },
-		{"vcmimap",                 doCheatMapReveal      },
-		{"vcmiungoliant",           doCheatMapHide        },
-		{"vcmihidemap",             doCheatMapHide        },
-		{"nwcignoranceisbliss",     doCheatMapHide        },
-		{"vcmiobelisk",             doCheatRevealPuzzle   },
-		{"nwcoracle",               doCheatRevealPuzzle   },
-		{"vcmiluck",                doCheatMaxLuck        },
-		{"nwcfollowthewhiterabbit", doCheatMaxLuck        },
-		{"vcmimorale",              doCheatMaxMorale      },
-		{"nwcmorpheus",             doCheatMaxMorale      },
-		{"vcmigod",                 doCheatTheOne         },
-		{"nwctheone",               doCheatTheOne         },
-		{"vcmiscrolls",             doCheatGiveScrolls    },
+		{"vcmiainur",               [&] () {doCheatGiveArmyFixed({ "archangel", "5" });}        },
+		{"nwctrinity",              [&] () {doCheatGiveArmyFixed({ "archangel", "5" });}        },
+		{"nwcpadme",                [&] () {doCheatGiveArmyFixed({ "archangel", "5" });}        },
+		{"nwcavertingoureyes",      [&] () {doCheatGiveArmyFixed({ "archangel", "5" });}        },
+		{"vcmiangband",             [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });}     },
+		{"vcmiglaurung",            [&] () {doCheatGiveArmyFixed({ "crystalDragon", "5000" });} },
+		{"vcmiarchangel",           [&] () {doCheatGiveArmyFixed({ "archangel", "5" });}        },
+		{"nwcagents",               [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });}     },
+		{"nwcdarthmaul",            [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });}     },
+		{"nwcfleshwound",           [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });}     },
+		{"vcmiblackknight",         [&] () {doCheatGiveArmyFixed({ "blackKnight", "10" });}     },
+		{"vcmicrystal",             [&] () {doCheatGiveArmyFixed({ "crystalDragon", "5000" });} },
+		{"vcmiazure",               [&] () {doCheatGiveArmyFixed({ "azureDragon", "5000" });}   },
+		{"vcmifaerie",              [&] () {doCheatGiveArmyFixed({ "fairieDragon", "5000" });}  },
+		{"vcmiarmy",                doCheatGiveArmyCustom                                       },
+		{"vcminissi",               doCheatGiveArmyCustom                                       },
+		{"vcmiistari",              doCheatGiveSpells                                           },
+		{"vcmispells",              doCheatGiveSpells                                           },
+		{"nwcthereisnospoon",       doCheatGiveSpells                                           },
+		{"nwcmidichlorians",        doCheatGiveSpells                                           },
+		{"nwctim",                  doCheatGiveSpells                                           },
+		{"vcmiarmenelos",           doCheatBuildTown                                            },
+		{"vcmibuild",               doCheatBuildTown                                            },
+		{"nwczion",                 doCheatBuildTown                                            },
+		{"nwccoruscant",            doCheatBuildTown                                            },
+		{"nwconlyamodel",           doCheatBuildTown                                            },
+		{"vcminoldor",              doCheatGiveMachines                                         },
+		{"vcmimachines",            doCheatGiveMachines                                         },
+		{"nwclotsofguns",           doCheatGiveMachines                                         },
+		{"nwcr2d2",                 doCheatGiveMachines                                         },
+		{"nwcantioch",              doCheatGiveMachines                                         },
+		{"vcmiforgeofnoldorking",   doCheatGiveArtifacts                                        },
+		{"vcmiartifacts",           doCheatGiveArtifacts                                        },
+		{"vcmiglorfindel",          doCheatLevelup                                              },
+		{"vcmilevel",               doCheatLevelup                                              },
+		{"nwcneo",                  doCheatLevelup                                              },
+		{"vcmiolorin",              doCheatExperience                                           },
+		{"vcmiexp",                 doCheatExperience                                           },
+		{"vcminahar",               doCheatMovement                                             },
+		{"vcmimove",                doCheatMovement                                             },
+		{"nwcnebuchadnezzar",       doCheatMovement                                             },
+		{"nwcpodracer",             doCheatMovement                                             },
+		{"nwccoconuts",             doCheatMovement                                             },
+		{"vcmiformenos",            doCheatResources                                            },
+		{"vcmiresources",           doCheatResources                                            },
+		{"nwctheconstruct",         doCheatResources                                            },
+		{"nwcwatto",                doCheatResources                                            },
+		{"nwcshrubbery",            doCheatResources                                            },
+		{"nwcbluepill",             doCheatDefeat                                               },
+		{"nwcsirrobin",             doCheatDefeat                                               },
+		{"vcmimelkor",              doCheatDefeat                                               },
+		{"vcmilose",                doCheatDefeat                                               },
+		{"nwcredpill",              doCheatVictory                                              },
+		{"nwctrojanrabbit",         doCheatVictory                                              },
+		{"vcmisilmaril",            doCheatVictory                                              },
+		{"vcmiwin",                 doCheatVictory                                              },
+		{"nwcwhatisthematrix",      doCheatMapReveal                                            },
+		{"nwcrevealourselves",      doCheatMapReveal                                            },
+		{"nwcgeneraldirection",     doCheatMapReveal                                            },
+		{"vcmieagles",              doCheatMapReveal                                            },
+		{"vcmimap",                 doCheatMapReveal                                            },
+		{"vcmiungoliant",           doCheatMapHide                                              },
+		{"vcmihidemap",             doCheatMapHide                                              },
+		{"nwcignoranceisbliss",     doCheatMapHide                                              },
+		{"vcmiobelisk",             doCheatRevealPuzzle                                         },
+		{"nwcoracle",               doCheatRevealPuzzle                                         },
+		{"nwcprophecy",             doCheatRevealPuzzle                                         },
+		{"nwcalreadygotone",        doCheatRevealPuzzle                                         },
+		{"vcmiluck",                doCheatMaxLuck                                              },
+		{"nwcfollowthewhiterabbit", doCheatMaxLuck                                              },
+		{"nwccastleanthrax",        doCheatMaxLuck                                              },
+		{"vcmimorale",              doCheatMaxMorale                                            },
+		{"nwcmorpheus",             doCheatMaxMorale                                            },
+		{"nwcmuchrejoicing",        doCheatMaxMorale                                            },
+		{"vcmigod",                 doCheatTheOne                                               },
+		{"nwctheone",               doCheatTheOne                                               },
+		{"vcmiscrolls",             doCheatGiveScrolls                                          },
+		{"vcmicolor",               [&] () {doColorSchemeChange(ColorScheme::H2_SCHEME);}       },
+		{"nwcphisherprice",         [&] () {doColorSchemeChange(ColorScheme::H2_SCHEME);}       },
+		{"vcmigray",                [&] () {doColorSchemeChange(ColorScheme::GRAYSCALE);}       },
 	};
 
 	assert(callbacks.count(cheatName));

+ 1 - 0
server/processors/PlayerMessageProcessor.h

@@ -47,6 +47,7 @@ class PlayerMessageProcessor
 	void cheatGiveMachines(PlayerColor player, const CGHeroInstance * hero);
 	void cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatGiveScrolls(PlayerColor player, const CGHeroInstance * hero);
+	void cheatColorSchemeChange(PlayerColor player, ColorScheme scheme);
 	void cheatLevelup(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatExperience(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatMovement(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);