bool OnUse (Player *pPlayer, Item *pItem, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 20748 && !targets.getUnitTarget()->HasAura(32578)) return false; pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pItem, NULL); return true; }
bool ItemUse_item_attuned_crystal_cores(Player *player, Item* _Item, SpellCastTargets const& targets) { if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 24972 && targets.getUnitTarget()->isDead() ) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); return true; }
bool ItemUse_item_protovoltaic_magneto_collector(Player *player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 21729) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); return true; }
bool ItemUse_item_razorthorn_flayer_gland(Player *player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 24922) return false; player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); return true; }
bool ItemUse_item_disciplinary_rod(Player *player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && (targets.getUnitTarget()->GetEntry() == 15941 || targets.getUnitTarget()->GetEntry() == 15945)) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); return true; }
bool ItemUse_item_gor_dreks_ointment(Player *player, Item* _Item, SpellCastTargets const& targets) { if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 20748 && !targets.getUnitTarget()->HasAura(32578) ) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,_Item,NULL); return true; }
bool ItemUse_item_blackwhelp_net(Player *player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 21387) return false; player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); return true; }
bool ItemUse_item_attuned_crystal_cores(Player* player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == ERRATIC_SENTRY && targets.getUnitTarget()->isDead() && (player->GetQuestStatus(ERRATIC_BEHAVIOUR) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(FURTHER_CONVERSIONS) == QUEST_STATUS_INCOMPLETE)) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, _Item, NULL); return true; }
bool ItemUse_item_battery(Player* player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 18879 && player->GetQuestStatus(10190) == QUEST_STATUS_INCOMPLETE && (targets.getUnitTarget()->GetHealthPct() <= 25)) return false; player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, _Item, NULL); return true; }
bool ItemUse_item_vorenthals_presence(Player *player, Item* _Item, SpellCastTargets const& targets) { // allow use if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 20132) return false; // error player->SendEquipError(EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM,_Item,NULL); return true; }
bool ItemUse_item_attuned_crystal_cores(Player* player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == 24972 && targets.getUnitTarget()->isDead() && (player->GetQuestStatus(11524) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11525) == QUEST_STATUS_INCOMPLETE)) { CAST_CRE(targets.getUnitTarget())->RemoveCorpse(); return false; } player->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, _Item, NULL); return true; }
bool ItemUse_item_alystrosAggro(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) { if(pTargets.getUnitTarget()->GetEntry() == 27249) { pTargets.getUnitTarget()->AddThreat(pPlayer,20.0f); } else { Spell::SendCastResult(pPlayer, GetSpellStore()->LookupEntry(49566), 1, SPELL_FAILED_BAD_TARGETS); return false; } return true; }
bool ItemUse_item_voodoo_charm(Player *player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->isDead() && targets.getUnitTarget()->GetEntry()==7318) return false; WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message data << uint32(_Item->GetEntry()); // itemId data << uint8(SPELL_FAILED_BAD_TARGETS); // reason player->GetSession()->SendPacket(&data); // send message: Invalid target player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell return true; }
bool ItemUse_item_Tillinghasts_Plague_Canister(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) { if(pTargets.getUnitTarget()->GetEntry() == 23777) { pPlayer->CastSpell(pTargets.getUnitTarget(),43157,true); pPlayer->DealDamage(pTargets.getUnitTarget(),pTargets.getUnitTarget()->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } else { Spell::SendCastResult(pPlayer, GetSpellStore()->LookupEntry(43157), 1, SPELL_FAILED_BAD_TARGETS); return false; } return true; }
bool ItemUse_item_gor_dreks_ointment(Player* pPlayer, Item* pItem, const SpellCastTargets& pTargets) { if (pTargets.getUnitTarget() && pTargets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && pTargets.getUnitTarget()->HasAura(SPELL_GORDREKS_OINTMENT)) { pPlayer->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_GORDREKS_OINTMENT)) Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_TARGET_AURASTATE); return true; } return false; }
bool ItemUse_item_chest_of_containment_coffers(Player* player, Item* _Item, SpellCastTargets const& targets) { if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && targets.getUnitTarget()->IsAlive() && targets.getUnitTarget()->GetEntry() == MOB_RIFT_SPAWN && targets.getUnitTarget()->HasAura(SPELL_SELF_STUN_30SEC)) return false; WorldPacket data(SMSG_CAST_FAILED, (4 + 2)); // prepare packet error message data << uint32(_Item->GetEntry()); // itemId data << uint8(SPELL_FAILED_NOT_READY); // reason player->GetSession()->SendPacket(&data); // send message: Not ready yet player->SendEquipError(EQUIP_ERR_NONE, _Item, NULL); // break spell return true; }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId; uint8 cast_count; recvPacket >> spellId; recvPacket >> cast_count; DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i", spellId, cast_count, recvPacket.size()); SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); return; } // not have spell or spell passive and not casted by client if (!_player->HasSpell (spellId) || IsPassiveSpell(spellId)) { //cheater? kick? ban? return; } // can't use our own spells when we're in possession of another unit, if (_player->isPossessing()) return; // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(_player); Unit* target = targets.getUnitTarget(); if (target) // auto-selection buff level base at target level (in spellInfo) { // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(spellInfo, target->getLevel())) spellInfo = actualSpellInfo; } if (spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG) { if (_player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo->Id == spellInfo->Id) return; } // When casting a combat spell the unit has to be flagged as initiating combat // No need to check if spell is self-cast because combat spells can only be cast on self with commands if (target && !IsNonCombatSpell(spellInfo)) _player->setInitiatingCombat(true); Spell* spell = new Spell(_player, spellInfo, false); spell->m_cast_count = cast_count; // set count of casts spell->prepare(&targets); }
bool ItemUse_item_muiseks_vessel(Player *player, Item* _Item, SpellCastTargets const& targets) { Unit* uTarget = targets.getUnitTarget(); uint32 itemSpell = _Item->GetProto()->Spells[0].SpellId; uint32 cEntry = 0; uint32 cEntry2 = 0; uint32 cEntry3 = 0; uint32 cEntry4 = 0; if(itemSpell) { switch(itemSpell) { case 11885: //Wandering Forest Walker cEntry = 7584; break; case 11886: //Owlbeasts cEntry = 2927; cEntry2 = 2928; cEntry3 = 2929; cEntry4 = 7808; break; case 11887: //Freyfeather Hippogryphs cEntry = 5300; cEntry2 = 5304; cEntry3 = 5305; cEntry4 = 5306; break; case 11888: //Sprite Dragon Sprite Darters cEntry = 5276; cEntry2 = 5278; break; case 11889: //Zapped Land Walker Land Walker Zapped Cliff Giant Cliff Giant cEntry = 5357; cEntry2 = 5358; cEntry3 = 14640; cEntry4 = 14604; break; } if( uTarget && uTarget->GetTypeId()==TYPEID_UNIT && uTarget->isDead() && (uTarget->GetEntry()==cEntry || uTarget->GetEntry()==cEntry2 || uTarget->GetEntry()==cEntry3 || uTarget->GetEntry()==cEntry4) ) { ((Creature*)uTarget)->RemoveCorpse(); return false; } } WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message data << uint32(_Item->GetEntry()); // itemId data << uint8(SPELL_FAILED_BAD_TARGETS); // reason player->GetSession()->SendPacket(&data); // send message: Invalid target player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell return true; }
bool Spell_seed_of_corruption_proc(Unit* pCaster, std::list<Unit*> &unitList, SpellCastTargets const& targets, SpellEntry const *pSpell, uint32 effect_index) { if (effect_index != 0) return true; if (unitList.empty()) return true; unitList.remove(targets.getUnitTarget()); return true; }
bool ItemUse_item_tame_beast_rods(Player *player, Item* _Item, SpellCastTargets const& targets) { uint32 itemSpell = _Item->GetProto()->Spells[0].SpellId; uint32 cEntry = 0; if(itemSpell) { switch(itemSpell) { case 19548: cEntry = 1196; break; //Ice Claw Bear case 19674: cEntry = 1126; break; //Large Crag Boar case 19687: cEntry = 1201; break; //Snow Leopard case 19688: cEntry = 2956; break; //Adult Plainstrider case 19689: cEntry = 2959; break; //Prairie Stalker case 19692: cEntry = 2970; break; //Swoop case 19693: cEntry = 1998; break; //Webwood Lurker case 19694: cEntry = 3099; break; //Dire Mottled Boar case 19696: cEntry = 3107; break; //Surf Crawler case 19697: cEntry = 3126; break; //Armored Scorpid case 19699: cEntry = 2043; break; //Nightsaber Stalker case 19700: cEntry = 1996; break; //Strigid Screecher case 30646: cEntry = 17217; break; //Barbed Crawler case 30653: cEntry = 17374; break; //Greater Timberstrider case 30654: cEntry = 17203; break; //Nightstalker case 30099: cEntry = 15650; break; //Crazed Dragonhawk case 30102: cEntry = 15652; break; //Elder Springpaw case 30105: cEntry = 16353; break; //Mistbat } if( targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId()==TYPEID_UNIT && targets.getUnitTarget()->GetEntry() == cEntry ) return false; } WorldPacket data(SMSG_CAST_FAILED, (4+2)); // prepare packet error message data << uint32(_Item->GetEntry()); // itemId data << uint8(SPELL_FAILED_BAD_TARGETS); // reason player->GetSession()->SendPacket(&data); // send message: Invalid target player->SendEquipError(EQUIP_ERR_NONE,_Item,NULL); // break spell return true; }
bool Spell_intimidating_shout_5246(Unit* pCaster, std::list<Unit*> &unitList, SpellCastTargets const& targets, SpellEntry const *pSpell, uint32 effect_index) { if (effect_index == 0) return true; if (unitList.empty()) return true; // remove current target from AOE Fear, AOE Speed aura our target gets stun effect provided by 1st effect unitList.remove(targets.getUnitTarget()); return true; }
bool ItemUse_item_RaeloraszSpear(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) { if(pTargets.getUnitTarget()->GetEntry() == 26127) { // TODO : script de capture du dragon } else { Spell::SendCastResult(pPlayer, GetSpellStore()->LookupEntry(43157), 1, SPELL_FAILED_BAD_TARGETS); return false; } return true; }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket,1+4+1); uint32 spellId; uint8 cast_count, unk_flags; recvPacket >> cast_count; recvPacket >> spellId; recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", spellId, cast_count, unk_flags, recvPacket.size()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); return; } // not have spell or spell passive and not casted by client if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) ) { //cheater? kick? ban? return; } // client provided targets SpellCastTargets targets; if(!targets.read(&recvPacket,_player)) return; // auto-selection buff level base at target level (in spellInfo) if(targets.getUnitTarget()) { SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if(actualSpellInfo) spellInfo = actualSpellInfo; } Spell *spell = new Spell(_player, spellInfo, false); spell->m_cast_count = cast_count; // set count of casts spell->prepare(&targets); }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; sLog.outDebug("WORLD: got cast spell packet, spellId - %u, data length = %i", spellId, (uint32)recvPacket.size()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); return; } // not have spell or spell passive and not casted by client if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) ) { //cheater? kick? ban? return; } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(_player); // auto-selection buff level base at target level (in spellInfo) if(targets.getUnitTarget()) { SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if(actualSpellInfo) spellInfo = actualSpellInfo; } Spell *spell = new Spell(_player, spellInfo, false); spell->prepare(&targets); }
bool ItemUse_item_yehkinyas_bramble(Player* player, Item* _Item, SpellCastTargets const& targets) { if (player->GetQuestStatus(3520) == QUEST_STATUS_INCOMPLETE) { Unit* unit_target = targets.getUnitTarget(); if (unit_target && unit_target->GetTypeId() == TYPEID_UNIT && unit_target->isDead() && // cast only on corpse 5307 or 5308 (unit_target->GetEntry() == 5307 || unit_target->GetEntry() == 5308)) { CAST_CRE(unit_target)->RemoveCorpse(); // remove corpse for cancelling second use return false; // all ok } } WorldPacket data(SMSG_CAST_FAILED, (4 + 2)); // prepare packet error message data << uint32(10699); // itemId data << uint8(SPELL_FAILED_BAD_TARGETS); // reason player->GetSession()->SendPacket(&data); // send message: Bad target player->SendEquipError(EQUIP_ERR_NONE, _Item, NULL); // break spell return true; }
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { // TODO: add targets.read() check Player* pUser = _player; // ignore for remote control state if(pUser->m_mover != pUser) return; uint8 bagIndex, slot; uint8 unk_flags; // flags (if 0x02 - some additional data are received) uint8 cast_count; // next cast if exists (single or not) uint64 item_guid; uint32 glyphIndex; // something to do with glyphs? uint32 spellid; // casted spell id recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; // reject fake data if (glyphIndex >= MAX_GLYPH_SLOT_INDEX) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); return; } Item *pItem = pUser->GetItemByPos(bagIndex, slot); if (!pItem) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); return; } if (pItem->GetGUID() != item_guid) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); return; } sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, (uint32)recvPacket.size()); ItemPrototype const *proto = pItem->GetProto(); if (!proto) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); return; } // some item classes can be used only in equipped state if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); return; } uint8 msg = pUser->CanUseItem(pItem); if (msg != EQUIP_ERR_OK) { pUser->SendEquipError( msg, pItem, NULL ); return; } // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) && pUser->InArena()) { pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL); return; } if (pUser->isInCombat()) { for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) { if (IsNonCombatSpell(spellInfo)) { pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); return; } } } } // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) if( pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) { if (!pItem->IsSoulBound()) { pItem->SetState(ITEM_CHANGED, pUser); pItem->SetBinding( true ); } } SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pUser); targets.Update(pUser); if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) { // free gray item after use fail pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); // send spell error if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid)) { // for implicit area/coord target spells if (IsPointEffectTarget(Targets(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_0])) || IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_0]))) Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_NO_VALID_TARGETS); // for explicit target spells else Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_BAD_TARGETS); } return; } //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. if(!Script->ItemUse(pUser,pItem,targets)) { // no script or script not process request by self pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex); } }
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { uint8 bagIndex, slot; uint8 spell_count; // number of spells at item, not used recvPacket >> bagIndex >> slot >> spell_count; // TODO: add targets.read() check Player* pUser = _player; // ignore for remote control state if (!pUser->IsSelfMover()) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail return; } Item* pItem = pUser->GetItemByPos(bagIndex, slot); if (!pItem) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr); return; } DETAIL_LOG("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , Item: %u, data length = %u", bagIndex, slot, spell_count, pItem->GetEntry(), (uint32)recvPacket.size()); ItemPrototype const* proto = pItem->GetProto(); if (!proto) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, nullptr); return; } // some item classes can be used only in equipped state if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, nullptr); return; } InventoryResult msg = pUser->CanUseItem(pItem); if (msg != EQUIP_ERR_OK) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(msg, pItem, nullptr); return; } // not allow use item from trade (cheat way only) if (pItem->IsInTrade()) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, nullptr); return; } if (pUser->isInCombat()) { for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) { if (IsNonCombatSpell(spellInfo)) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT, pItem, nullptr); return; } } } } // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) if (pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM) { if (!pItem->IsSoulBound()) { pItem->SetState(ITEM_CHANGED, pUser); pItem->SetBinding(true); } } SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pUser); targets.Update(pUser); if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) { // free gray item after use fail pUser->SendEquipError(EQUIP_ERR_NONE, pItem, nullptr); // search spell for spell error uint32 spellid = 0; for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) { spellid = proto->Spells[i].SpellId; break; } } // send spell error if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid)) Spell::SendCastResult(_player, spellInfo, SPELL_FAILED_BAD_TARGETS); return; } // Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. if (!sScriptMgr.OnItemUse(pUser, pItem, targets)) { // no script or script not process request by self pUser->CastItemUseSpell(pItem, targets); } }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; // ignore for remote control state (for player case) Unit* mover = _player->GetMover(); if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, data length = " SIZEFMTD, spellId, recvPacket.size()); SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } if (mover->GetTypeId() == TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if (!((Player*)mover)->HasActiveSpell(spellId) || IsPassiveSpell(spellInfo)) { sLog.outError("World: Player %u casts spell %u which he shouldn't have", mover->GetGUIDLow(), spellId); // cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } else { // not have spell in spellbook or spell passive and not casted by client if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellInfo)) { // cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet return; } } // client provided targets SpellCastTargets targets; recvPacket >> targets.ReadForCaster(_player); // auto-selection buff level base at target level (in spellInfo) if (Unit* target = targets.getUnitTarget()) { // if rank not found then function return nullptr but in explicit cast case original spell can be casted and later failed with appropriate error message if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, _player, target)) spellInfo = actualSpellInfo; } Spell* spell = new Spell(_player, spellInfo, false); spell->SpellStart(&targets); }
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { // TODO: add targets.read() check Player* pUser = _player; uint8 bagIndex, slot; uint8 spell_count; // number of spells at item, not used recvPacket >> bagIndex >> slot >> spell_count; Item *pItem = pUser->GetItemByPos(bagIndex, slot); if(!pItem) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); return; } sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , Item: %u, data length = %i", bagIndex, slot, spell_count, pItem->GetEntry(), (uint32)recvPacket.size()); ItemPrototype const *proto = pItem->GetProto(); if(!proto) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); return; } // some item classes can be used only in equipped state if(proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); return; } uint8 msg = pUser->CanUseItem(pItem); if( msg != EQUIP_ERR_OK ) { pUser->SendEquipError( msg, pItem, NULL ); return; } if (pUser->isInCombat()) { for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) { if (IsNonCombatSpell(spellInfo)) { pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); return; } } } } // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) if( pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) { if (!pItem->IsSoulBound()) { pItem->SetState(ITEM_CHANGED, pUser); pItem->SetBinding( true ); } } SpellCastTargets targets; recvPacket >> targets.ReadForCaster(pUser); targets.Update(pUser); if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) { // free gray item after use fail pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); // search spell for spell error uint32 spellid = 0; for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { if( proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) { spellid = proto->Spells[i].SpellId; break; } } // send spell error if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid)) Spell::SendCastResult(_player,spellInfo,SPELL_FAILED_BAD_TARGETS); return; } //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. if(!Script->ItemUse(pUser,pItem,targets)) { // no script or script not process request by self // special learning case if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) { uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN); if(!spellInfo) { sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN); pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); return; } Spell *spell = new Spell(pUser, spellInfo, false); spell->m_CastItem = pItem; spell->m_currentBasePoints[0] = learning_spell_id; spell->prepare(&targets); return; } // use triggered flag only for items with many spell casts and for not first cast int count = 0; for(int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = pItem->GetProto()->Spells[i]; // no spell if(!spellData.SpellId) continue; // wrong triggering type if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) continue; SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); if(!spellInfo) { sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId); continue; } Spell *spell = new Spell(pUser, spellInfo, (count > 0)); spell->m_CastItem = pItem; spell->prepare(&targets); ++count; } } }
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { uint32 spellId; uint8 cast_count, unk_flags; recvPacket >> cast_count; recvPacket >> spellId; recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) // ignore for remote control state (for player case) Unit* mover = _player->m_mover; if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER) return; sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", spellId, cast_count, unk_flags, (uint32)recvPacket.size()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %u", spellId); return; } if(mover->GetTypeId()==TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellId) ) { //cheater? kick? ban? return; } } else { // not have spell in spellbook or spell passive and not casted by client if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellId) ) { //cheater? kick? ban? return; } } // Client is resending autoshot cast opcode when other spell is casted during shoot rotation // Skip it to prevent "interrupt" message if (IsAutoRepeatRangedSpell(spellInfo) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) return; // can't use our own spells when we're in possession of another unit, if(_player->isPossessing()) return; // client provided targets SpellCastTargets targets; if(!targets.read(&recvPacket,mover)) return; // auto-selection buff level base at target level (in spellInfo) if(targets.getUnitTarget()) { SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message if(actualSpellInfo) spellInfo = actualSpellInfo; } Spell *spell = new Spell(mover, spellInfo, false); spell->m_cast_count = cast_count; // set count of casts spell->prepare(&targets); }