fix: Fix for console commands of azerothcore/mod-transmog#83

This commit is contained in:
Gozzim
2022-05-30 18:05:55 +02:00
parent 1a569e34bb
commit 5ea075e554
3 changed files with 192 additions and 39 deletions

View File

@@ -501,6 +501,9 @@ bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTempl
if (IsAllowed(proto->ItemId))
return true;
if (!CheckPureProtoRequirements(proto))
return false;
//[AZTH] Yehonal
if (proto->SubClass > 0 && player->GetSkillValue(proto->GetSkill()) == 0)
{
@@ -518,15 +521,6 @@ bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTempl
return false;
}
if (IsNotAllowed(proto->ItemId))
return false;
if (!AllowFishingPoles && proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
return false;
if (!IsAllowedQuality(proto->Quality)) // (proto->Quality == ITEM_QUALITY_LEGENDARY)
return false;
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeamId() != TEAM_HORDE)
return false;
@@ -553,6 +547,121 @@ bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTempl
if (!IgnoreReqLevel && player->getLevel() < proto->RequiredLevel)
return false;
return true;
}
bool Transmogrification::SuitableForTransmogrification(ObjectGuid::LowType playerGuid, ItemTemplate const* proto) const
{
if (!playerGuid || !proto)
return false;
if (proto->Class != ITEM_CLASS_ARMOR &&
proto->Class != ITEM_CLASS_WEAPON)
return false;
// Skip all checks for allowed items
if (IsAllowed(proto->ItemId))
return true;
if (!CheckPureProtoRequirements(proto))
return false;
uint32 playerRaceMask;
uint32 playerClassMask;
TeamId playerTeamId;
uint8 playerLevel;
std::unordered_map<uint32, uint32> playerSkillValues;
if (QueryResult resultPlayer = CharacterDatabase.Query("SELECT `race`, `class`, `level` FROM `characters` WHERE `guid` = {}", playerGuid))
{
Field* fields = resultPlayer->Fetch();
uint8 playerRace = fields[0].Get<uint8>();
uint8 playerClass = fields[1].Get<uint8>();
playerLevel = fields[2].Get<uint8>();
playerRaceMask = 1 << (playerRace - 1);
playerClassMask = 1 << (playerClass - 1);
playerTeamId = Player::TeamIdForRace(playerRace);
}
else
{
LOG_ERROR("module", "Transmogification could not find player with guid {} in database.", playerGuid);
return false;
}
if (QueryResult resultSkills = CharacterDatabase.Query("SELECT `skill`, `value` FROM `character_skills` WHERE `guid` = {}", playerGuid))
{
do
{
Field* fields = resultSkills->Fetch();
uint16 skill = fields[0].Get<uint16>();
uint16 value = fields[1].Get<uint16>();
playerSkillValues[skill] = value;
} while (resultSkills->NextRow());
}
else {
LOG_ERROR("module", "Transmogification could not find skills for player with guid {} in database.", playerGuid);
return false;
}
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && playerTeamId != TEAM_HORDE)
return false;
if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && playerTeamId != TEAM_ALLIANCE)
return false;
if (!IgnoreReqClass && (proto->AllowableClass & playerClassMask) == 0)
return false;
if (!IgnoreReqRace && (proto->AllowableRace & playerRaceMask) == 0)
return false;
if (!IgnoreReqLevel && playerLevel < proto->RequiredLevel)
return false;
if (!IgnoreReqSkill && proto->RequiredSkill != 0)
{
if (playerSkillValues[proto->RequiredSkill] == 0)
return false;
else if (playerSkillValues[proto->RequiredSkill] < proto->RequiredSkillRank)
return false;
}
if (proto->SubClass > 0 && playerSkillValues[proto->GetSkill()] == 0)
{
if (proto->Class == ITEM_CLASS_ARMOR)
{
if (!AllowMixedArmorTypes)
return false;
}
else if (proto->Class == ITEM_CLASS_WEAPON)
{
if (!AllowMixedWeaponTypes)
return false;
}
else
return false;
}
if (!IgnoreReqSpell && proto->RequiredSpell != 0 && !(CharacterDatabase.Query("SELECT `spell` FROM `character_spell` WHERE `guid` = {} and `spell` = {}", playerGuid, proto->RequiredSpell)))
return false;
return true;
}
bool Transmogrification::CheckPureProtoRequirements(ItemTemplate const* proto) const
{
if (!proto)
return false;
if (IsNotAllowed(proto->ItemId))
return false;
if (!AllowFishingPoles && proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
return false;
if (!IsAllowedQuality(proto->Quality)) // (proto->Quality == ITEM_QUALITY_LEGENDARY)
return false;
// If World Event is not active, prevent using event dependant items
if (!IgnoreReqEvent && proto->HolidayId && !IsHolidayActive((HolidayIds)proto->HolidayId))
return false;
@@ -560,8 +669,8 @@ bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTempl
if (!IgnoreReqStats)
{
if (!proto->RandomProperty && !proto->RandomSuffix
/*[AZTH] Yehonal: we should transmorg also items without stats*/
&& proto->StatsCount > 0)
/*[AZTH] Yehonal: we should transmorg also items without stats*/
&& proto->StatsCount > 0)
{
bool found = false;
for (uint8 i = 0; i < proto->StatsCount; ++i)

View File

@@ -158,6 +158,8 @@ public:
TransmogAcoreStrings Transmogrify(Player* player, Item* itemTransmogrifier, uint8 slot, /*uint32 newEntry, */bool no_cost = false, bool hidden_transmog = false);
bool CanTransmogrifyItemWithItem(Player* player, ItemTemplate const* destination, ItemTemplate const* source) const;
bool SuitableForTransmogrification(Player* player, ItemTemplate const* proto) const;
bool SuitableForTransmogrification(ObjectGuid::LowType playerGuid, ItemTemplate const* proto) const;
bool CheckPureProtoRequirements(ItemTemplate const* proto) const;
// bool CanBeTransmogrified(Item const* item);
// bool CanTransmogrify(Item const* item);
uint32 GetSpecialPrice(ItemTemplate const* proto) const;

View File

@@ -20,11 +20,39 @@
#include "Player.h"
#include "ScriptMgr.h"
#include "Transmogrification.h"
#include "Tokenize.h"
using namespace Acore::ChatCommands;
class transmog_commandscript : public CommandScript
{
private:
static uint32 GetTransmogSettingValue(ObjectGuid::LowType guid, TransmogSettings settingIndex)
{
if (!sWorld->getBoolConfig(CONFIG_PLAYER_SETTINGS_ENABLED))
{
return 0;
}
if (QueryResult result = CharacterDatabase.Query("SELECT data FROM character_settings WHERE guid = {} AND source = \"mod-transmog\"", guid))
{
Field* fields = result->Fetch();
std::string data = fields[0].Get<std::string>();
std::vector<std::string_view> tokens = Acore::Tokenize(data, ' ', false);
if (tokens.size() < settingIndex + 1)
{
return 0;
}
auto setting = tokens[settingIndex];
return Acore::StringTo<uint32>(setting).value();
}
return 0;
}
public:
transmog_commandscript() : CommandScript("transmog_commandscript") { }
@@ -92,8 +120,19 @@ public:
}
Player* target = player->GetConnectedPlayer();
bool isNotConsole = handler->GetSession();
bool suitableForTransmog;
if (!sTransmogrification->GetTrackUnusableItems() && !sTransmogrification->SuitableForTransmogrification(target, itemTemplate))
if (target)
{
suitableForTransmog = sTransmogrification->SuitableForTransmogrification(target, itemTemplate);
}
else
{
suitableForTransmog = sTransmogrification->SuitableForTransmogrification(player->GetGUID().GetCounter(), itemTemplate);
}
if (!sTransmogrification->GetTrackUnusableItems() && !suitableForTransmog)
{
handler->SendSysMessage(LANG_CMD_TRANSMOG_ADD_UNSUITABLE);
handler->SetSentErrorMessage(true);
@@ -124,33 +163,30 @@ public:
tempStream << std::hex << ItemQualityColors[itemTemplate->Quality];
std::string itemQuality = tempStream.str();
std::string itemName = itemTemplate->Name1;
bool isNotConsoleAndIsPlayerOnline = handler->GetSession() && target->GetSession();
std::string playerName = player->GetName();
std::string nameLink = handler->playerLink(playerName);
if (sTransmogrification->AddCollectedAppearance(accountId, itemId))
{
if (isNotConsoleAndIsPlayerOnline)
// Notify target of new item in appearance collection
if (target && !(target->GetPlayerSetting("mod-transmog", SETTING_HIDE_TRANSMOG).value))
{
std::string nameLink = handler->playerLink(target->GetName());
ChatHandler(target->GetSession()).PSendSysMessage(R"(|c%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r has been added to your appearance collection.)", itemQuality.c_str(), itemId, itemName.c_str());
}
if (!(target->GetPlayerSetting("mod-transmog", SETTING_HIDE_TRANSMOG).value))
{
ChatHandler(target->GetSession()).PSendSysMessage(R"(|c%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r has been added to your appearance collection.)", itemQuality.c_str(), itemId, itemName.c_str());
}
if (target != handler->GetPlayer())
{
handler->PSendSysMessage(R"(|c%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r has been added to the appearance collection of Player %s.)", itemQuality.c_str(), itemId, itemName.c_str(), nameLink);
}
// Feedback of successful command execution to GM
if (isNotConsole && target != handler->GetPlayer())
{
handler->PSendSysMessage(R"(|c%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r has been added to the appearance collection of Player %s.)", itemQuality.c_str(), itemId, itemName.c_str(), nameLink);
}
CharacterDatabase.Execute("INSERT INTO custom_unlocked_appearances (account_id, item_template_id) VALUES ({}, {})", accountId, itemId);
}
else
{
if (isNotConsoleAndIsPlayerOnline)
// Feedback of failed command execution to GM
if (isNotConsole)
{
std::string nameLink = handler->playerLink(target->GetName());
handler->PSendSysMessage(R"(Player %s already has item |c%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r in the appearance collection.)", nameLink, itemQuality.c_str(), itemId, itemName.c_str());
handler->SetSentErrorMessage(true);
}
@@ -183,6 +219,7 @@ public:
Player* target = player->GetConnectedPlayer();
ItemSetEntry const* set = sItemSetStore.LookupEntry(uint32(itemSetId));
bool isNotConsole = handler->GetSession();
if (!set)
{
@@ -215,7 +252,10 @@ public:
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
if (itemTemplate)
{
if (!sTransmogrification->GetTrackUnusableItems() && !sTransmogrification->SuitableForTransmogrification(target, itemTemplate))
if (!sTransmogrification->GetTrackUnusableItems() && (
(target && !sTransmogrification->SuitableForTransmogrification(target, itemTemplate)) ||
!sTransmogrification->SuitableForTransmogrification(player->GetGUID().GetCounter(), itemTemplate)
))
{
error = LANG_CMD_TRANSMOG_ADD_UNSUITABLE;
continue;
@@ -242,14 +282,14 @@ public:
return true;
}
bool isNotConsoleAndIsPlayerOnline = handler->GetSession() && target->GetSession();
int locale = handler->GetSessionDbcLocale();
std::string setName = set->name[locale];
std::string nameLink = handler->playerLink(target->GetName());
if (isNotConsoleAndIsPlayerOnline)
// Feedback of command execution to GM
if (isNotConsole)
{
int locale = handler->GetSessionDbcLocale();
std::string setName = set->name[locale];
std::string nameLink = handler->playerLink(target->GetName());
// Failed command execution
if (!added)
{
handler->PSendSysMessage("Player %s already has ItemSet |cffffffff|Hitemset:%d|h[%s %s]|h|r in the appearance collection.", nameLink, uint32(itemSetId), setName.c_str(), localeNames[locale]);
@@ -257,17 +297,19 @@ public:
return true;
}
if (!(target->GetPlayerSetting("mod-transmog", SETTING_HIDE_TRANSMOG).value))
{
ChatHandler(target->GetSession()).PSendSysMessage("ItemSet |cffffffff|Hitemset:%d|h[%s %s]|h|r has been added to your appearance collection.", uint32(itemSetId), setName.c_str(), localeNames[locale]);
}
// Successful command execution
if (target != handler->GetPlayer())
{
handler->PSendSysMessage("ItemSet |cffffffff|Hitemset:%d|h[%s %s]|h|r has been added to the appearance collection of Player %s.", uint32(itemSetId), setName.c_str(), localeNames[locale], nameLink);
}
}
// Notify target of new item in appearance collection
if (target && !(target->GetPlayerSetting("mod-transmog", SETTING_HIDE_TRANSMOG).value))
{
ChatHandler(target->GetSession()).PSendSysMessage("ItemSet |cffffffff|Hitemset:%d|h[%s %s]|h|r has been added to your appearance collection.", uint32(itemSetId), setName.c_str(), localeNames[locale]);
}
return true;
}
};