fix(Core/Items): armor type requirement for needing items in LFG grou… (#7523)

- Closes #7467
This commit is contained in:
UltraNix
2021-09-02 10:39:57 +02:00
committed by GitHub
parent fb0c3b4cb2
commit 2f9f95221b
3 changed files with 111 additions and 30 deletions

View File

@@ -817,6 +817,9 @@ struct ItemTemplate
[[nodiscard]] bool IsArmorVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT; }
[[nodiscard]] bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_FLAG_CONJURED); }
[[nodiscard]] bool HasStat(ItemModType stat) const;
[[nodiscard]] bool HasSpellPowerStat() const;
void InitializeQueryData();
};

View File

@@ -2353,13 +2353,13 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
// Used by group, function NeedBeforeGreed, to know if a prototype can be used by a player
const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] =
{
SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES,
SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0,
SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0,
SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS,
SKILL_FISHING
}; //Copy from function Item::GetSkill()
{
SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES,
SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0,
SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS,0,
SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS,
SKILL_FISHING
}; //Copy from function Item::GetSkill()
if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
@@ -2380,36 +2380,50 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISC && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK)
if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISC && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER &&
proto->InventoryType != INVTYPE_CLOAK)
{
if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT)
uint32 subclassToCompare = ITEM_SUBCLASS_ARMOR_CLOTH;
switch (_class)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
case CLASS_WARRIOR:
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE)
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN)
{
if (getLevel() < 40)
{
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
}
[[fallthrough]];
case CLASS_DEATH_KNIGHT:
case CLASS_PALADIN:
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
break;
case CLASS_HUNTER:
case CLASS_SHAMAN:
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
break;
case CLASS_ROGUE:
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL)
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
[[fallthrough]];
case CLASS_DRUID:
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
break;
default:
break;
}
if (_class == CLASS_ROGUE || _class == CLASS_DRUID)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER)
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK)
if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH)
if (proto->SubClass > subclassToCompare)
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
else if (proto->ItemLevel > 70)
{
if (proto->SubClass < subclassToCompare)
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
}
}
return EQUIP_ERR_OK;

View File

@@ -290,6 +290,70 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
_player->DestroyItem(bag, slot, true);
}
bool ItemTemplate::HasStat(ItemModType stat) const
{
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
if (i >= StatsCount)
{
break;
}
if (ItemStat[i].ItemStatType == stat)
{
return true;
}
}
return false;
}
bool ItemTemplate::HasSpellPowerStat() const
{
bool invalid = false;
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
_Spell const& spellData = Spells[i];
if (!spellData.SpellId)
{
continue;
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellData.SpellId);
if (!spellInfo)
{
continue;
}
for (uint8 j = EFFECT_0; j <= EFFECT_2; ++j)
{
switch (spellInfo->Effects[j].ApplyAuraName)
{
case SPELL_AURA_MOD_HEALING_DONE:
case SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT:
case SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER:
case SPELL_AURA_MOD_HEALING:
invalid = true;
break;
case SPELL_AURA_MOD_DAMAGE_DONE:
case SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT:
case SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER:
case SPELL_AURA_MOD_DAMAGE_TAKEN:
if (!(spellInfo->Effects[j].MiscValue & SPELL_SCHOOL_MASK_SPELL))
{
return false;
}
invalid = true;
break;
default:
break;
}
}
}
return invalid;
}
void ItemTemplate::InitializeQueryData()
{
queryData.Initialize(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 1);