mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Cheat codes: add option to apply cheats on different players
All suitable codes can now be used with "ai", "all" color or with object ID: vcminahar all - will apply cheat to all heroes of all players vcminahar ai - will apply cheat to all heroes of AI players vcminahar blue - will apply it to all heroes of blue player vcminahar 553 - will apply cheat to hero with instance id of 553 if it's exist Cheats without options work as before.
This commit is contained in:
		| @@ -4250,163 +4250,64 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) | ||||
| 	return ok; | ||||
| } | ||||
|  | ||||
| void CGameHandler::playerMessage( PlayerColor player, const std::string &message, ObjectInstanceID currObj ) | ||||
| void CGameHandler::playerMessage(PlayerColor player, const std::string &message, ObjectInstanceID currObj) | ||||
| { | ||||
| 	bool cheated=true; | ||||
| 	bool cheated = true; | ||||
| 	PlayerMessage temp_message(player, message, ObjectInstanceID(-1)); // don't inform other client on selected object | ||||
|  | ||||
| 	sendAndApply(&temp_message); | ||||
| 	if(message == "vcmiistari") //give all spells and 999 mana | ||||
|  | ||||
| 	std::vector<std::string> cheat; | ||||
| 	boost::split(cheat, message, boost::is_any_of(" ")); | ||||
| 	int obj = 0; | ||||
| 	if(cheat.size() == 2) | ||||
| 	{ | ||||
| 		SetMana sm; | ||||
| 		GiveBonus giveBonus(GiveBonus::HERO); | ||||
|  | ||||
| 		const CGHeroInstance * h = getHero(currObj); | ||||
| 		if(!h && complain("Cannot realize cheat, no hero selected!")) return; | ||||
|  | ||||
| 		sm.hid = h->id; | ||||
|  | ||||
| 		giveBonus.id = h->id.getNum(); | ||||
|  | ||||
| 		//give all spells with bonus (to allow banned spells) | ||||
| 		giveBonus.bonus = Bonus(Bonus::PERMANENT, Bonus::SPELLS_OF_LEVEL, Bonus::OTHER, 0, 0); | ||||
| 		//start with level 0 to skip abilities | ||||
| 		for(int level = 1; level <= GameConstants::SPELL_LEVELS; level++) | ||||
| 		{ | ||||
| 			giveBonus.bonus.subtype = level; | ||||
| 			sendAndApply(&giveBonus); | ||||
| 		} | ||||
| 		//give mana | ||||
| 		sm.val = 999; | ||||
| 		sm.absolute = true; | ||||
|  | ||||
| 		if(!h->hasSpellbook()) //hero doesn't have spellbook | ||||
| 			giveHeroNewArtifact(h, VLC->arth->artifacts[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); //give spellbook | ||||
|  | ||||
| 		sendAndApply(&sm); | ||||
| 		obj = std::atoi(cheat[1].c_str()); | ||||
| 		if(obj) | ||||
| 			currObj = ObjectInstanceID(obj); | ||||
| 	} | ||||
| 	else if (message == "vcmiarmenelos") //build all buildings in selected town | ||||
|  | ||||
| 	const CGHeroInstance * hero = getHero(currObj); | ||||
| 	const CGTownInstance * town = getTown(currObj); | ||||
| 	if(!town && hero) | ||||
| 		town = hero->visitedTown; | ||||
|  | ||||
| 	if(cheat.size() == 1 || obj) | ||||
| 		handleCheatCode(cheat[0], player, hero, town, cheated); | ||||
| 	else | ||||
| 	{ | ||||
| 		const CGHeroInstance * hero = getHero(currObj); | ||||
| 		const CGTownInstance * town; | ||||
|  | ||||
| 		if (hero) | ||||
| 			town = hero->visitedTown; | ||||
| 		else | ||||
| 			town = getTown(currObj); | ||||
|  | ||||
| 		if (town) | ||||
| 		for(const auto & i : gs->players) | ||||
| 		{ | ||||
| 			for (auto & build : town->town->buildings) | ||||
| 			if(i.first == PlayerColor::NEUTRAL) | ||||
| 				continue; | ||||
| 			if(cheat[1] == "ai") | ||||
| 			{ | ||||
| 				if (!town->hasBuilt(build.first) | ||||
| 				    && !build.second->Name().empty() | ||||
| 				    && build.first != BuildingID::SHIP) | ||||
| 				if(i.second.human) | ||||
| 					continue; | ||||
| 			} | ||||
| 			else if(cheat[1] != "all" && cheat[1] != i.first.getStr()) | ||||
| 				continue; | ||||
|  | ||||
| 			if(cheat[0] == "vcmiformenos" || cheat[0] == "vcmieagles" || cheat[0] == "vcmiungoliant") | ||||
| 			{ | ||||
| 				handleCheatCode(cheat[0], i.first, nullptr, nullptr, cheated); | ||||
| 			} | ||||
| 			else if(cheat[0] == "vcmiarmenelos") | ||||
| 			{ | ||||
| 				for(const auto & t : i.second.towns) | ||||
| 				{ | ||||
| 					buildStructure(town->id, build.first, true); | ||||
| 					handleCheatCode(cheat[0], i.first, nullptr, t, cheated); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				for(const auto & h : i.second.heroes) | ||||
| 				{ | ||||
| 					handleCheatCode(cheat[0], i.first, h, nullptr, cheated); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if(message == "vcmiainur") //gives 5 archangels into each slot | ||||
| 	{ | ||||
| 		const CGHeroInstance * hero = getHero(currObj); | ||||
| 		const CCreature *archangel = VLC->creh->creatures.at(13); | ||||
| 		if(!hero) return; | ||||
|  | ||||
| 		for(int i = 0; i < GameConstants::ARMY_SIZE; i++) | ||||
| 			if(!hero->hasStackAtSlot(SlotID(i))) | ||||
| 				insertNewStack(StackLocation(hero, SlotID(i)), archangel, 5); | ||||
| 	} | ||||
| 	else if(message == "vcmiangband") //gives 10 black knight into each slot | ||||
| 	{ | ||||
| 		const CGHeroInstance * hero = getHero(currObj); | ||||
| 		const CCreature *blackKnight = VLC->creh->creatures.at(66); | ||||
| 		if(!hero) return; | ||||
|  | ||||
| 		for(int i = 0; i < GameConstants::ARMY_SIZE; i++) | ||||
| 			if(!hero->hasStackAtSlot(SlotID(i))) | ||||
| 				insertNewStack(StackLocation(hero, SlotID(i)), blackKnight, 10); | ||||
| 	} | ||||
| 	else if(message == "vcmiglaurung") //gives 5000 crystal dragons into each slot | ||||
| 	{ | ||||
| 		const CGHeroInstance * hero = getHero(currObj); | ||||
| 		const CCreature *crystalDragon = VLC->creh->creatures.at(133); | ||||
| 		if(!hero) return; | ||||
|  | ||||
| 		for(int i = 0; i < GameConstants::ARMY_SIZE; i++) | ||||
| 			if(!hero->hasStackAtSlot(SlotID(i))) | ||||
| 				insertNewStack(StackLocation(hero, SlotID(i)), crystalDragon, 5000); | ||||
| 	} | ||||
| 	else if(message == "vcminoldor") //all war machines | ||||
| 	{ | ||||
| 		const CGHeroInstance * hero = getHero(currObj); | ||||
| 		if(!hero) return; | ||||
|  | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH1)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::BALLISTA], ArtifactPosition::MACH1); | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH2)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::AMMO_CART], ArtifactPosition::MACH2); | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH3)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3); | ||||
| 	} | ||||
| 	else if (message == "vcmiforgeofnoldorking") //hero gets all artifacts except war machines, spell scrolls and spell book | ||||
| 	{ | ||||
| 		const CGHeroInstance *hero = gs->getHero(currObj); | ||||
| 		if(!hero) return; | ||||
| 		for (int g = 7; g < VLC->arth->artifacts.size(); ++g) //including artifacts from mods | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[g], ArtifactPosition::PRE_FIRST); | ||||
| 	} | ||||
| 	else if(message == "vcmiglorfindel") //selected hero gains a new level | ||||
| 	{ | ||||
| 		CGHeroInstance *hero = gs->getHero(currObj); | ||||
| 		changePrimSkill(hero, PrimarySkill::EXPERIENCE, VLC->heroh->reqExp(hero->level+1) - VLC->heroh->reqExp(hero->level)); | ||||
| 	} | ||||
| 	else if(message == "vcminahar") //1000000 movement points | ||||
| 	{ | ||||
| 		CGHeroInstance *hero = gs->getHero(currObj); | ||||
| 		if(!hero) return; | ||||
| 		SetMovePoints smp; | ||||
| 		smp.hid = hero->id; | ||||
| 		smp.val = 1000000; | ||||
| 		sendAndApply(&smp); | ||||
| 	} | ||||
| 	else if(message == "vcmiformenos") //give resources | ||||
| 	{ | ||||
| 		SetResources sr; | ||||
| 		sr.player = player; | ||||
| 		sr.res = getPlayer(player)->resources; | ||||
| 		for(int i=0;i<Res::GOLD;i++) | ||||
| 			sr.res[i] += 100; | ||||
| 		sr.res[Res::GOLD] += 100000; //100k | ||||
| 		sendAndApply(&sr); | ||||
| 	} | ||||
| 	else if(message == "vcmieagles" || message == "vcmiungoliant") //reveal or conceal FoW | ||||
| 	{ | ||||
| 		FoWChange fc; | ||||
| 		fc.mode = (message == "vcmieagles" ? 1 : 0); | ||||
| 		fc.player = player; | ||||
| 		auto  hlp_tab = new int3[gs->map->width * gs->map->height * (gs->map->twoLevel ? 2 : 1)]; | ||||
| 		int lastUnc = 0; | ||||
| 		for(int i=0;i<gs->map->width;i++) | ||||
| 			for(int j=0;j<gs->map->height;j++) | ||||
| 				for(int k = 0; k < (gs->map->twoLevel ? 2 : 1); k++) | ||||
| 					if(!gs->getPlayerTeam(fc.player)->fogOfWarMap.at(i).at(j).at(k) || message == "vcmiungoliant") | ||||
| 						hlp_tab[lastUnc++] = int3(i,j,k); | ||||
| 		fc.tiles.insert(hlp_tab, hlp_tab + lastUnc); | ||||
| 		delete [] hlp_tab; | ||||
| 		sendAndApply(&fc); | ||||
| 	} | ||||
| 	else if(message == "vcmisilmaril") //player wins | ||||
| 	{ | ||||
| 		gs->getPlayer(player)->enteredWinningCheatCode = 1; | ||||
| 	} | ||||
| 	else if(message == "vcmimelkor") //player looses | ||||
| 	{ | ||||
| 		gs->getPlayer(player)->enteredLosingCheatCode = 1; | ||||
| 	} | ||||
| 	else | ||||
| 		cheated = false; | ||||
| 	if(cheated) | ||||
| 	{ | ||||
| 		SystemMessage temp_message(VLC->generaltexth->allTexts.at(260)); | ||||
| @@ -6004,6 +5905,136 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, const CGHeroInstance * hero, const CGTownInstance * town, bool & cheated) | ||||
| { | ||||
| 	if(cheat == "vcmiistari") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///Give hero spellbook | ||||
| 		if(!hero->hasSpellbook()) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); | ||||
|  | ||||
| 		///Give all spells with bonus (to allow banned spells) | ||||
| 		GiveBonus giveBonus(GiveBonus::HERO); | ||||
| 		giveBonus.id = hero->id.getNum(); | ||||
| 		giveBonus.bonus = Bonus(Bonus::PERMANENT, Bonus::SPELLS_OF_LEVEL, Bonus::OTHER, 0, 0); | ||||
| 		//start with level 0 to skip abilities | ||||
| 		for(int level = 1; level <= GameConstants::SPELL_LEVELS; level++) | ||||
| 		{ | ||||
| 			giveBonus.bonus.subtype = level; | ||||
| 			sendAndApply(&giveBonus); | ||||
| 		} | ||||
|  | ||||
| 		///Give mana | ||||
| 		SetMana sm; | ||||
| 		sm.hid = hero->id; | ||||
| 		sm.val = 999; | ||||
| 		sm.absolute = true; | ||||
| 		sendAndApply(&sm); | ||||
| 	} | ||||
| 	else if(cheat == "vcmiarmenelos") | ||||
| 	{ | ||||
| 		if(!town) return; | ||||
| 		///Build all buildings in selected town | ||||
| 		for(auto & build : town->town->buildings) | ||||
| 		{ | ||||
| 			if(!town->hasBuilt(build.first) | ||||
| 				&& !build.second->Name().empty() | ||||
| 				&& build.first != BuildingID::SHIP) | ||||
| 			{ | ||||
| 				buildStructure(town->id, build.first, true); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if(cheat == "vcmiainur" || cheat == "vcmiangband" || cheat == "vcmiglaurung") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///Gives N creatures into each slot | ||||
| 		std::map<std::string, std::pair<int, int>> creatures; | ||||
| 		creatures.insert(std::make_pair("vcmiainur", std::make_pair(13, 5))); //5 archangels | ||||
| 		creatures.insert(std::make_pair("vcmiangband", std::make_pair(66, 10))); //10 black knights | ||||
| 		creatures.insert(std::make_pair("vcmiglaurung", std::make_pair(133, 5000))); //5000 crystal dragons | ||||
|  | ||||
| 		const CCreature * creature = VLC->creh->creatures.at(creatures[cheat].first); | ||||
| 		for(int i = 0; i < GameConstants::ARMY_SIZE; i++) | ||||
| 			if(!hero->hasStackAtSlot(SlotID(i))) | ||||
| 				insertNewStack(StackLocation(hero, SlotID(i)), creature, creatures[cheat].second); | ||||
| 	} | ||||
| 	else if(cheat == "vcminoldor") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///Give all war machines to hero | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH1)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::BALLISTA], ArtifactPosition::MACH1); | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH2)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::AMMO_CART], ArtifactPosition::MACH2); | ||||
| 		if(!hero->getArt(ArtifactPosition::MACH3)) | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3); | ||||
| 	} | ||||
| 	else if(cheat == "vcmiforgeofnoldorking") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///Give hero all artifacts except war machines, spell scrolls and spell book | ||||
| 		for(int g = 7; g < VLC->arth->artifacts.size(); ++g) //including artifacts from mods | ||||
| 			giveHeroNewArtifact(hero, VLC->arth->artifacts[g], ArtifactPosition::PRE_FIRST); | ||||
| 	} | ||||
| 	else if(cheat == "vcmiglorfindel") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///selected hero gains a new level | ||||
| 		changePrimSkill(hero, PrimarySkill::EXPERIENCE, VLC->heroh->reqExp(hero->level + 1) - VLC->heroh->reqExp(hero->level)); | ||||
| 	} | ||||
| 	else if(cheat == "vcminahar") | ||||
| 	{ | ||||
| 		if(!hero) return; | ||||
| 		///Give 1000000 movement points to hero | ||||
| 		SetMovePoints smp; | ||||
| 		smp.hid = hero->id; | ||||
| 		smp.val = 1000000; | ||||
| 		sendAndApply(&smp); | ||||
| 	} | ||||
| 	else if(cheat == "vcmiformenos") | ||||
| 	{ | ||||
| 		///Give resources to player | ||||
| 		TResources resources; | ||||
| 		resources[Res::GOLD] = 100000; | ||||
| 		for(Res::ERes i = Res::WOOD; i < Res::GOLD; vstd::advance(i, 1)) | ||||
| 			resources[i] = 100; | ||||
|  | ||||
| 		giveResources(player, resources); | ||||
| 	} | ||||
| 	else if(cheat == "vcmisilmaril") | ||||
| 	{ | ||||
| 		///Player wins | ||||
| 		gs->getPlayer(player)->enteredWinningCheatCode = 1; | ||||
| 	} | ||||
| 	else if(cheat == "vcmimelkor") | ||||
| 	{ | ||||
| 		///Player looses | ||||
| 		gs->getPlayer(player)->enteredLosingCheatCode = 1; | ||||
| 	} | ||||
| 	else if(cheat == "vcmieagles" || cheat == "vcmiungoliant") | ||||
| 	{ | ||||
| 		///Reveal or conceal FoW | ||||
| 		FoWChange fc; | ||||
| 		fc.mode = (cheat == "vcmieagles" ? 1 : 0); | ||||
| 		fc.player = player; | ||||
| 		const auto & fowMap = gs->getPlayerTeam(player)->fogOfWarMap; | ||||
| 		auto hlp_tab = new int3[gs->map->width * gs->map->height * (gs->map->twoLevel ? 2 : 1)]; | ||||
| 		int lastUnc = 0; | ||||
| 		for(int i = 0; i < gs->map->width; i++) | ||||
| 			for(int j = 0; j < gs->map->height; j++) | ||||
| 				for(int k = 0; k < (gs->map->twoLevel ? 2 : 1); k++) | ||||
| 					if(!fowMap.at(i).at(j).at(k) || !fc.mode) | ||||
| 						hlp_tab[lastUnc++] = int3(i, j, k); | ||||
| 		fc.tiles.insert(hlp_tab, hlp_tab + lastUnc); | ||||
| 		delete [] hlp_tab; | ||||
| 		sendAndApply(&fc); | ||||
| 	} | ||||
| 	else | ||||
| 		cheated = false; | ||||
| } | ||||
|  | ||||
| void CGameHandler::removeObstacle(const CObstacleInstance &obstacle) | ||||
| { | ||||
| 	ObstaclesRemoved obsRem; | ||||
|   | ||||
| @@ -194,7 +194,7 @@ public: | ||||
| 	void handleConnection(std::set<PlayerColor> players, CConnection &c); | ||||
| 	PlayerColor getPlayerAt(CConnection *c) const; | ||||
|  | ||||
| 	void playerMessage( PlayerColor player, const std::string &message, ObjectInstanceID currObj); | ||||
| 	void playerMessage(PlayerColor player, const std::string &message, ObjectInstanceID currObj); | ||||
| 	void updateGateState(); | ||||
| 	bool makeBattleAction(BattleAction &ba); | ||||
| 	bool makeAutomaticAction(const CStack *stack, BattleAction &ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack) | ||||
| @@ -284,6 +284,7 @@ public: | ||||
| 	void attackCasting(const BattleAttack & bat, Bonus::BonusType attackMode, const CStack * attacker); | ||||
| 	bool sacrificeArtifact(const IMarket * m, const CGHeroInstance * hero, ArtifactPosition slot); | ||||
| 	void spawnWanderingMonsters(CreatureID creatureID); | ||||
| 	void handleCheatCode(std::string & cheat, PlayerColor player, const CGHeroInstance * hero, const CGTownInstance * town, bool & cheated); | ||||
| 	friend class CVCMIServer; | ||||
|  | ||||
| 	CRandomGenerator & getRandomGenerator(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user