diff --git a/data/sql/updates/pending_db_world/rev_1549320792563626100.sql b/data/sql/updates/pending_db_world/rev_1549320792563626100.sql new file mode 100644 index 000000000..31c14d6ff --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1549320792563626100.sql @@ -0,0 +1,14 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1549320792563626100'); + +DELETE FROM `command` WHERE `name`='taxicheat'; +DELETE FROM `command` WHERE `name`='waterwalk'; + +DELETE FROM `command` WHERE `name`='cheat' OR `name` LIKE 'cheat%'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('cheat', 2, 'Syntax: .cheat $subcommand\r\nType .cheat to see the list of possible subcommands or .help cheat $subcommand to see info on subcommands'), +('cheat god', 2, 'Syntax: .cheat god [on/off]\r\nTurn the user invulnerable.'), +('cheat casttime', 2, 'Syntax: .cheat casttime [on/off]\r\nRemove spells\' casting time.'), +('cheat cooldown', 2, 'Syntax: .cheat cooldown [on/off]\r\nDisable spells\' cooldowns.'), +('cheat power', 2, 'Syntax: .cheat power [on/off]\r\nRemove spells\' cost (mana, energy, rage...).'), +('cheat waterwalk', 2, 'Syntax: .cheat waterwalk on/off\r\nAllow to walk on water (self or selected character).'), +('cheat taxi', 2, 'Syntax: .cheat taxi on/off\r\nTemporary grant access to all taxi routes for the selected character.\r\n If no character is selected, hide or reveal all routes to you. Visited taxi nodes are still accessible after removing access.'); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b132f8ef7..57ac1f4e3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -912,6 +912,8 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) SetPendingBind(0, 0); + _activeCheats = CHEAT_NONE; + m_achievementMgr = new AchievementMgr(this); m_reputationMgr = new ReputationMgr(this); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index d3b1f8fd1..4f4b918ad 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -899,6 +899,16 @@ enum AdditionalSaving ADDITIONAL_SAVING_QUEST_STATUS = 0x02, }; +enum PlayerCommandStates +{ + CHEAT_NONE = 0x00, + CHEAT_GOD = 0x01, + CHEAT_CASTTIME = 0x02, + CHEAT_COOLDOWN = 0x04, + CHEAT_POWER = 0x08, + CHEAT_WATERWALK = 0x10 +}; + class PlayerTaxi { public: @@ -1177,6 +1187,11 @@ class Player : public Unit, public GridObject void InitStatsForLevel(bool reapplyMods = false); + // .cheat command related + bool GetCommandStatus(uint32 command) const { return _activeCheats & command; } + void SetCommandStatusOn(uint32 command) { _activeCheats |= command; } + void SetCommandStatusOff(uint32 command) { _activeCheats &= ~command; } + // Played Time Stuff time_t m_logintime; time_t m_Last_tick; @@ -2938,6 +2953,8 @@ class Player : public Unit, public GridObject uint32 _pendingBindId; uint32 _pendingBindTimer; + uint32 _activeCheats; + // duel health and mana reset attributes uint32 healthBeforeDuel; uint32 manaBeforeDuel; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6fb8b3869..1fd6ccb90 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -696,6 +696,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage // Signal to pets that their owner was attacked Pet* pet = victim->ToPlayer()->GetPet(); + if (victim->GetTypeId() == TYPEID_PLAYER) + if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD)) + return 0; + if (pet && pet->IsAlive()) pet->AI()->OwnerAttackedBy(attacker); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index cd286f3fb..ebb932b93 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3414,6 +3414,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) m_casttime = (_triggeredCastFlags & TRIGGERED_CAST_DIRECTLY) ? 0 : m_spellInfo->CalcCastTime(m_caster, this); + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_CASTTIME)) + m_casttime = 0; + // don't allow channeled spells / spells with cast time to be casted while moving // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in) if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT && !IsTriggered()) @@ -3832,6 +3836,10 @@ void Spell::_cast(bool skipCheck) if (GetDelayMoment() > 0 && !m_caster->IsFriendlyTo(target) && !m_spellInfo->HasAura(SPELL_AURA_BIND_SIGHT) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) m_caster->CombatStartOnCast(target, !m_spellInfo->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO), GetDelayMoment() + 500); // xinef: increase this time so we dont leave and enter combat in a moment + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) + m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); + SetExecutedCurrently(false); } @@ -4951,6 +4959,11 @@ void Spell::TakePower() if (m_CastItem || m_triggeredByAuraSpell) return; + //Don't take power if the spell is cast while .cheat power is enabled. + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_POWER)) + return; + Powers powerType = Powers(m_spellInfo->PowerType); bool hit = true; if (m_caster->GetTypeId() == TYPEID_PLAYER) @@ -8300,6 +8313,10 @@ void Spell::TriggerGlobalCooldown() return; } + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) + return; + // Global cooldown can't leave range 1..1.5 secs // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns // but as tests show are not affected by any spell mods. diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 371cfb987..a75ee33e0 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -276,6 +276,10 @@ void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/) if (!unitTarget || !unitTarget->IsAlive() || unitTarget->HasAura(27827)) // Spirit of redemption doesn't make you death, but can cause infinite loops return; + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + if (unitTarget->ToPlayer()->GetCommandStatus(CHEAT_GOD)) + return; + if (m_caster == unitTarget) // prevent interrupt message finish(); diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 097be2b95..07f3aba29 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -16,6 +16,7 @@ set(scripts_STAT_SRCS Commands/cs_bf.cpp Commands/cs_cast.cpp Commands/cs_character.cpp + Commands/cs_cheat.cpp Commands/cs_debug.cpp Commands/cs_disable.cpp Commands/cs_event.cpp diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp new file mode 100644 index 000000000..c70be564d --- /dev/null +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2016+ AzerothCore + */ + +#include "Chat.h" +#include "Language.h" +#include "Player.h" +#include "ScriptMgr.h" + +class cheat_commandscript : public CommandScript +{ +public: + cheat_commandscript() : CommandScript("cheat_commandscript") { } + + std::vector GetCommands() const override + { + + static std::vector cheatCommandTable = + { + { "god", SEC_GAMEMASTER, false, &HandleGodModeCheatCommand, "" }, + { "casttime", SEC_GAMEMASTER, false, &HandleCasttimeCheatCommand, "" }, + { "cooldown", SEC_GAMEMASTER, false, &HandleCoolDownCheatCommand, "" }, + { "power", SEC_GAMEMASTER, false, &HandlePowerCheatCommand, "" }, + { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterwalkCheatCommand, "" }, + { "status", SEC_GAMEMASTER, false, &HandleCheatStatusCommand, "" }, + { "taxi", SEC_GAMEMASTER, false, &HandleTaxiCheatCommand, "" }, + + }; + + static std::vector commandTable = + { + { "cheat", SEC_GAMEMASTER, false, nullptr, "", cheatCommandTable }, + + }; + return commandTable; + } + + static bool HandleGodModeCheatCommand(ChatHandler* handler, char const* args) + { + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_GOD)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_GOD); + handler->SendSysMessage("Godmode is OFF. You can take damage."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_GOD); + handler->SendSysMessage("Godmode is ON. You won't take damage."); + return true; + } + + return false; + } + + static bool HandleCasttimeCheatCommand(ChatHandler* handler, char const* args) + { + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_CASTTIME)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_CASTTIME); + handler->SendSysMessage("CastTime Cheat is OFF. Your spells will have a casttime."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_CASTTIME); + handler->SendSysMessage("CastTime Cheat is ON. Your spells won't have a casttime."); + return true; + } + + return false; + } + + static bool HandleCoolDownCheatCommand(ChatHandler* handler, char const* args) + { + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_COOLDOWN); + handler->SendSysMessage("Cooldown Cheat is OFF. You are on the global cooldown."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_COOLDOWN); + handler->SendSysMessage("Cooldown Cheat is ON. You are not on the global cooldown."); + return true; + } + + return false; + } + + static bool HandlePowerCheatCommand(ChatHandler* handler, char const* args) + { + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_POWER)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_POWER); + handler->SendSysMessage("Power Cheat is OFF. You need mana/rage/energy to use spells."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_POWER); + handler->SendSysMessage("Power Cheat is ON. You don't need mana/rage/energy to use spells."); + return true; + } + + return false; + } + + static bool HandleWaterwalkCheatCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* player = handler->getSelectedPlayer(); + if (!player) + { + handler->PSendSysMessage(LANG_NO_CHAR_SELECTED); + handler->SetSentErrorMessage(true); + return false; + } + + // check online security + if (handler->HasLowerSecurity(player, 0)) + return false; + + if (strncmp(args, "on", 3) == 0) + { + player->SetMovement(MOVE_WATER_WALK); // ON + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_WATERWALK); + } + else if (strncmp(args, "off", 4) == 0) + { + player->SetMovement(MOVE_LAND_WALK); // OFF + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_WATERWALK); + } + else + { + handler->SendSysMessage(LANG_USE_BOL); + return false; + } + + handler->PSendSysMessage(LANG_YOU_SET_WATERWALK, args, handler->GetNameLink(player).c_str()); + if (handler->needReportToTarget(player)) + ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, handler->GetNameLink().c_str()); + return true; + } + + static bool HandleCheatStatusCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + + char const* enabled = "ON"; + char const* disabled = "OFF"; + + handler->SendSysMessage(LANG_COMMAND_CHEAT_STATUS); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_GOD, player->GetCommandStatus(CHEAT_GOD) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_CD, player->GetCommandStatus(CHEAT_COOLDOWN) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_CT, player->GetCommandStatus(CHEAT_CASTTIME) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_POWER, player->GetCommandStatus(CHEAT_POWER) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_WW, player->GetCommandStatus(CHEAT_WATERWALK) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_TAXINODES, player->isTaxiCheater() ? enabled : disabled); + + return true; + } + + + static bool HandleTaxiCheatCommand(ChatHandler* handler, char const* args) + { + std::string argStr = (char*)args; + + Player* chr = handler->getSelectedPlayer(); + + if (!chr) + chr = handler->GetSession()->GetPlayer(); + else if (handler->HasLowerSecurity(chr, 0)) // check online security + return false; + + if (!*args) + argStr = (chr->isTaxiCheater()) ? "off" : "on"; + + if (argStr == "off") + { + chr->SetTaxiCheater(false); + handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); + + return true; + } + else if (argStr == "on") + { + chr->SetTaxiCheater(true); + handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); + return true; + } + + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + + return false; + } +}; + +void AddSC_cheat_commandscript() +{ + new cheat_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 6fb08f45a..cb4cfc55b 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -80,7 +80,6 @@ public: { "saveall", SEC_GAMEMASTER, true, &HandleSaveAllCommand, "" }, { "kick", SEC_GAMEMASTER, true, &HandleKickPlayerCommand, "" }, { "unstuck", SEC_GAMEMASTER, true, &HandleUnstuckCommand, "" }, - { "taxicheat", SEC_GAMEMASTER, false, &HandleTaxiCheatCommand, "" }, { "linkgrave", SEC_ADMINISTRATOR, false, &HandleLinkGraveCommand, "" }, { "neargrave", SEC_GAMEMASTER, false, &HandleNearGraveCommand, "" }, { "explorecheat", SEC_ADMINISTRATOR, false, &HandleExploreCheatCommand, "" }, @@ -105,7 +104,6 @@ public: { "combatstop", SEC_GAMEMASTER, true, &HandleCombatStopCommand, "" }, { "flusharenapoints", SEC_ADMINISTRATOR, false, &HandleFlushArenaPointsCommand, "" }, { "repairitems", SEC_GAMEMASTER, true, &HandleRepairitemsCommand, "" }, - { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterwalkCommand, "" }, { "freeze", SEC_GAMEMASTER, false, &HandleFreezeCommand, "" }, { "unfreeze", SEC_GAMEMASTER, false, &HandleUnFreezeCommand, "" }, { "group", SEC_GAMEMASTER, false, nullptr, "", groupCommandTable }, @@ -1201,49 +1199,6 @@ public: return false; } - // Enable on\off all taxi paths - static bool HandleTaxiCheatCommand(ChatHandler* handler, char const* args) - { - if (!*args) - { - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - return false; - } - - std::string argStr = (char*)args; - - Player* chr = handler->getSelectedPlayer(); - - if (!chr) - chr = handler->GetSession()->GetPlayer(); - else if (handler->HasLowerSecurity(chr, 0)) // check online security - return false; - - if (argStr == "on") - { - chr->SetTaxiCheater(true); - handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); - return true; - } - - if (argStr == "off") - { - chr->SetTaxiCheater(false); - handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); - - return true; - } - - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - - return false; - } static bool HandleLinkGraveCommand(ChatHandler* handler, char const* args) { @@ -1392,9 +1347,9 @@ public: for (uint8 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) { if (flag != 0) - handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0xFFFFFFFF); + handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1 + i, 0xFFFFFFFF); else - handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0); + handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1 + i, 0); } return true; @@ -2608,39 +2563,6 @@ public: return true; } - static bool HandleWaterwalkCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - Player* player = handler->getSelectedPlayer(); - if (!player) - { - handler->PSendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(player, 0)) - return false; - - if (strncmp(args, "on", 3) == 0) - player->SetMovement(MOVE_WATER_WALK); // ON - else if (strncmp(args, "off", 4) == 0) - player->SetMovement(MOVE_LAND_WALK); // OFF - else - { - handler->SendSysMessage(LANG_USE_BOL); - return false; - } - - handler->PSendSysMessage(LANG_YOU_SET_WATERWALK, args, handler->GetNameLink(player).c_str()); - if (handler->needReportToTarget(player)) - ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, handler->GetNameLink().c_str()); - return true; - } - // Send mail by command static bool HandleSendMailCommand(ChatHandler* handler, char const* args) { diff --git a/src/server/scripts/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp index 7d1cf04a4..80c1e9921 100644 --- a/src/server/scripts/ScriptLoader.cpp +++ b/src/server/scripts/ScriptLoader.cpp @@ -32,6 +32,7 @@ void AddSC_ban_commandscript(); void AddSC_bf_commandscript(); void AddSC_cast_commandscript(); void AddSC_character_commandscript(); +void AddSC_cheat_commandscript(); void AddSC_debug_commandscript(); void AddSC_disable_commandscript(); void AddSC_event_commandscript(); @@ -608,6 +609,7 @@ void AddCommandScripts() AddSC_bf_commandscript(); AddSC_cast_commandscript(); AddSC_character_commandscript(); + AddSC_cheat_commandscript(); AddSC_debug_commandscript(); AddSC_disable_commandscript(); AddSC_event_commandscript();