Eluna fix crash on InterruptSpell. Make item use and item gossip hooks to be able to return false to stop spell casting.

This commit is contained in:
Rochet2
2014-06-27 22:15:30 +03:00
committed by Foereaper
parent 1591e7a40d
commit 0f8f37678d
5 changed files with 55 additions and 16 deletions

View File

@@ -398,13 +398,36 @@ bool Eluna::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
{
return OnItemGossip(pPlayer, pItem, targets) || OnItemUse(pPlayer, pItem, targets);
// pPlayer->SendEquipError((InventoryResult)83, pItem, NULL);
// return true;
ObjectGuid guid = pItem->GET_GUID();
bool castSpell = true;
if (!OnItemGossip(pPlayer, pItem, targets))
castSpell = false;
pItem = pPlayer->GetItemByGuid(guid);
if (pItem && OnItemUse(pPlayer, pItem, targets))
pItem = pPlayer->GetItemByGuid(guid);
else
castSpell = false;
if (pItem && castSpell)
return true;
// Send equip error that shows no message
// This is a hack fix to stop spell casting visual bug when a spell is not cast on use
WorldPacket data(SMSG_INVENTORY_CHANGE_FAILURE, 18);
data << uint8(83);
data << ObjectGuid(guid);
data << ObjectGuid(0);
data << uint8(0);
pPlayer->GetSession()->SendPacket(&data);
return false;
}
bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
{
ENTRY_BEGIN(ItemEventBindings, pItem->GetEntry(), ITEM_EVENT_ON_USE, return false);
bool result = true;
ENTRY_BEGIN(ItemEventBindings, pItem->GetEntry(), ITEM_EVENT_ON_USE, return result);
Push(L, pPlayer);
Push(L, pItem);
#ifdef MANGOS
@@ -432,20 +455,33 @@ bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targ
else
Push(L);
#endif
ENTRY_EXECUTE(0);
ENTRY_EXECUTE(1);
FOR_RETS(i)
{
if (lua_isnoneornil(L, i))
continue;
result = CHECKVAL<bool>(L, i, result);
}
ENDCALL();
return true;
return result;
}
bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/)
{
ENTRY_BEGIN(ItemGossipBindings, pItem->GetEntry(), GOSSIP_EVENT_ON_HELLO, return false);
bool result = true;
ENTRY_BEGIN(ItemGossipBindings, pItem->GetEntry(), GOSSIP_EVENT_ON_HELLO, return result);
pPlayer->PlayerTalkClass->ClearMenus();
Push(L, pPlayer);
Push(L, pItem);
ENTRY_EXECUTE(0);
ENTRY_EXECUTE(1);
FOR_RETS(i)
{
if (lua_isnoneornil(L, i))
continue;
result = CHECKVAL<bool>(L, i, result);
}
ENDCALL();
return true;
return result;
}
bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)

View File

@@ -248,7 +248,7 @@ namespace HookMgr
enum ItemEvents
{
ITEM_EVENT_ON_DUMMY_EFFECT = 1, // (event, caster, spellid, effindex, item)
ITEM_EVENT_ON_USE = 2, // (event, player, item, target)
ITEM_EVENT_ON_USE = 2, // (event, player, item, target) - Can return false to stop the spell casting
ITEM_EVENT_ON_QUEST_ACCEPT = 3, // (event, player, item, quest)
ITEM_EVENT_ON_EXPIRE = 4, // (event, player, itemid)
ITEM_EVENT_ON_REMOVE = 5, // (event, player, item)
@@ -261,7 +261,7 @@ namespace HookMgr
// RegisterPlayerGossipEvent(menu_id, EventId, function)
enum GossipEvents
{
GOSSIP_EVENT_ON_HELLO = 1, // (event, player, object) - Object is the Creature/GameObject/Item
GOSSIP_EVENT_ON_HELLO = 1, // (event, player, object) - Object is the Creature/GameObject/Item. For item gossip can return false to stop spell casting.
GOSSIP_EVENT_ON_SELECT = 2, // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip
GOSSIP_EVENT_COUNT
};

View File

@@ -189,7 +189,7 @@ struct EventMgr
Object* obj; // Object to push
};
EventMgr(Eluna& _E) : E(_E)
EventMgr(Eluna& _E): E(_E)
{
}

View File

@@ -338,8 +338,8 @@ ElunaRegister<Unit> UnitMethods[] =
{ "PlayDirectSound", &LuaUnit::PlayDirectSound }, // :PlayDirectSound(soundId, player) - Unit plays soundID to player, or everyone around if no player
{ "PlayDistanceSound", &LuaUnit::PlayDistanceSound }, // :PlayDistanceSound(soundId, player) - Unit plays soundID to player, or everyone around if no player. The sound fades the further you are
{ "Kill", &LuaUnit::Kill }, // :Kill(target, durabilityLoss) - Unit kills the target. Durabilityloss is true by default
{ "StopSpellCast", &LuaUnit::StopSpellCast }, // :StopSpellCast(spellId(optional)) - Stops the unit from casting a spell. If a spellId is defined, it will stop that unit from casting that spell
{ "InterruptSpell", &LuaUnit::InterruptSpell }, // :InterruptSpell(spellType, delayed(optional)) - Interrupts the unit's spell by the spellType. If delayed is true it will skip if the spell is delayed.
{ "StopSpellCast", &LuaUnit::StopSpellCast }, // :StopSpellCast([spellId]) - Stops the unit from casting a spell. If a spellId is defined, it will stop that unit from casting that spell
{ "InterruptSpell", &LuaUnit::InterruptSpell }, // :InterruptSpell(spellType[, delayed]) - Interrupts the unit's spell by the spellType. If delayed is true it will skip if the spell is delayed.
{ "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, // :SendChatMessageToPlayer(type, lang, msg, target) - Unit sends a chat message to the given target player
{ "Emote", &LuaUnit::Emote }, // :Emote(emote)
{ "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, // :CountPctFromCurHealth(int32 pct)

View File

@@ -853,8 +853,8 @@ namespace LuaUnit
/*
int GetVehicle(lua_State* L, Unit* unit)
{
Eluna::Push(L, unit->GetVehicle());
return 1;
Eluna::Push(L, unit->GetVehicle());
return 1;
}
*/
@@ -1478,7 +1478,10 @@ namespace LuaUnit
case 3:
spellType = CURRENT_AUTOREPEAT_SPELL;
break;
default:
return luaL_argerror(L, 2, "valid CurrentSpellTypes expected");
}
unit->InterruptSpell((CurrentSpellTypes)spellType, delayed);
return 0;
}