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) bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
{ {
return OnItemGossip(pPlayer, pItem, targets) || OnItemUse(pPlayer, pItem, targets); ObjectGuid guid = pItem->GET_GUID();
// pPlayer->SendEquipError((InventoryResult)83, pItem, NULL); bool castSpell = true;
// return 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) 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, pPlayer);
Push(L, pItem); Push(L, pItem);
#ifdef MANGOS #ifdef MANGOS
@@ -432,20 +455,33 @@ bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targ
else else
Push(L); Push(L);
#endif #endif
ENTRY_EXECUTE(0); ENTRY_EXECUTE(1);
FOR_RETS(i)
{
if (lua_isnoneornil(L, i))
continue;
result = CHECKVAL<bool>(L, i, result);
}
ENDCALL(); ENDCALL();
return true; return result;
} }
bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) 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(); pPlayer->PlayerTalkClass->ClearMenus();
Push(L, pPlayer); Push(L, pPlayer);
Push(L, pItem); 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(); ENDCALL();
return true; return result;
} }
bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto) bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)

View File

@@ -248,7 +248,7 @@ namespace HookMgr
enum ItemEvents enum ItemEvents
{ {
ITEM_EVENT_ON_DUMMY_EFFECT = 1, // (event, caster, spellid, effindex, item) 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_QUEST_ACCEPT = 3, // (event, player, item, quest)
ITEM_EVENT_ON_EXPIRE = 4, // (event, player, itemid) ITEM_EVENT_ON_EXPIRE = 4, // (event, player, itemid)
ITEM_EVENT_ON_REMOVE = 5, // (event, player, item) ITEM_EVENT_ON_REMOVE = 5, // (event, player, item)
@@ -261,7 +261,7 @@ namespace HookMgr
// RegisterPlayerGossipEvent(menu_id, EventId, function) // RegisterPlayerGossipEvent(menu_id, EventId, function)
enum GossipEvents 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_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 GOSSIP_EVENT_COUNT
}; };

View File

@@ -189,7 +189,7 @@ struct EventMgr
Object* obj; // Object to push 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 { "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 { "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 { "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 { "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(optional)) - Interrupts the unit's spell by the spellType. If delayed is true it will skip if the spell is delayed. { "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 { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, // :SendChatMessageToPlayer(type, lang, msg, target) - Unit sends a chat message to the given target player
{ "Emote", &LuaUnit::Emote }, // :Emote(emote) { "Emote", &LuaUnit::Emote }, // :Emote(emote)
{ "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, // :CountPctFromCurHealth(int32 pct) { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, // :CountPctFromCurHealth(int32 pct)

View File

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