mod-paragon: let class 12 actually USE class-restricted glyphs / items

Two paths still rejected glyph use on Paragon characters even after the
earlier AllowableClass server bypass:

1. Spell::CheckItems (server) treated cast-from-glyph as a normal
   "equipped item required" cast and called HasItemFitToSpellRequirements,
   which only handles weapon/armor and falls through default for
   ITEM_CLASS_GLYPH -> SPELL_FAILED_EQUIPPED_ITEM_CLASS. Skip that check
   when the cast item itself is the glyph.

2. The 3.3.5 client engine pre-checks ItemTemplate.AllowableClass against
   the player's class locally and refuses the right-click before sending
   CMSG_USE_ITEM, regardless of what the server would do. Bake the
   Paragon class bit (1<<11 = 2048) into AllowableClass for every
   class-restricted item via a mod-paragon SQL migration so the engine's
   pre-check passes for class 12.

Cache caveat: clients that previously inspected an affected item have
the old AllowableClass cached in Cache/<locale>/itemcache.wdb; deleting
the Cache folder forces a re-query. The server also caches item_template
in memory at boot, so this migration only takes effect for clients after
a worldserver restart (or .reload item_template) once the SQL has been
applied -- DBUpdater handles the SQL automatically on the next start.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Docker Build
2026-05-09 16:52:37 -04:00
parent a212717c37
commit f986fdcddd
2 changed files with 40 additions and 2 deletions
+10 -2
View File
@@ -7296,8 +7296,16 @@ SpellCastResult Spell::CheckItems(uint32* param1, uint32* param2)
{
// Xinef: this is not true in my opinion, in eg bladestorm will not be canceled after disarm
//if (!HasTriggeredCastFlag(TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT))
if (m_caster->IsPlayer() && !m_caster->ToPlayer()->HasItemFitToSpellRequirements(m_spellInfo))
return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
if (m_caster->IsPlayer())
{
// Cast-from-glyph: many glyph on-use spells set EquippedItemClass to ITEM_CLASS_GLYPH.
// HasItemFitToSpellRequirements only implements weapon/armor, so it would always fail here
// even though the glyph item in the bag is the valid spell source.
bool const castFromGlyphScroll = m_CastItem && m_CastItem->GetTemplate() &&
m_CastItem->GetTemplate()->Class == ITEM_CLASS_GLYPH;
if (!castFromGlyphScroll && !m_caster->ToPlayer()->HasItemFitToSpellRequirements(m_spellInfo))
return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
}
}
// do not take reagents for these item casts