From 7b7958c5485678d439f13fdb25dbe6a8f8b5315b Mon Sep 17 00:00:00 2001 From: Arseniy Shestakov Date: Sun, 2 Oct 2016 16:21:46 +0300 Subject: [PATCH] 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. --- server/CGameHandler.cpp | 317 ++++++++++++++++++++++------------------ server/CGameHandler.h | 3 +- 2 files changed, 176 insertions(+), 144 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 8ce6b2e82..5ebab8d98 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -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 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;imap->width * gs->map->height * (gs->map->twoLevel ? 2 : 1)]; - int lastUnc = 0; - for(int i=0;imap->width;i++) - for(int j=0;jmap->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> 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; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 8d8267eae..f2b6b0a6a 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -194,7 +194,7 @@ public: void handleConnection(std::set 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();