/* * Ascent MMORPG Server * Copyright (C) 2005-2007 Ascent Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "StdAfx.h" void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { if(!_player->IsInWorld()) return; typedef std::list AuraList; Player* p_User = GetPlayer(); sLog.outDetail("WORLD: got use Item packet, data length = %i",recvPacket.size()); int8 tmp1,slot,tmp3; uint32 spellId = 0; recvPacket >> tmp1 >> slot >> tmp3; Item* tmpItem = NULL; tmpItem = p_User->GetItemInterface()->GetInventoryItem(tmp1,slot); if (!tmpItem) tmpItem = p_User->GetItemInterface()->GetInventoryItem(slot); if (!tmpItem) return; ItemPrototype *itemProto = tmpItem->GetProto(); if(!itemProto) return; if(itemProto->Bonding == ITEM_BIND_ON_USE) tmpItem->SoulBind(); if(itemProto->QuestId) { // Item Starter Quest *qst = QuestStorage.LookupEntry(itemProto->QuestId); if(!qst) return; WorldPacket data; sQuestMgr.BuildQuestDetails(&data, qst, tmpItem, 0); SendPacket(&data); } SpellCastTargets targets(recvPacket, _player->GetGUID()); for(int x = 0; x < 5; x++) { if(itemProto->Spells[x].Trigger == USE) { if(itemProto->Spells[x].Id) { spellId = itemProto->Spells[x].Id; break; } } } if(!spellId) return; // check for spell id SpellEntry *spellInfo = sSpellStore.LookupEntry( spellId ); if(!spellInfo) { sLog.outError("WORLD: unknown spell id %i\n", spellId); return; } if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP) { if (p_User->isInCombat()) { _player->GetItemInterface()->BuildInventoryChangeError(tmpItem,NULL,INV_ERR_CANT_DO_IN_COMBAT); return; } if(p_User->GetStandState()!=1) p_User->SetStandState(STANDSTATE_SIT); // loop through the auras and removing existing eating spells } if (spellInfo->Category > 1) // 0 and -1 a.k.a. infinite not included { ItemCooldown * item = new ItemCooldown; for(uint32 i = 0; i < 5; i++) { if(itemProto->Spells[i].Id) { if(itemProto->Spells[i].Trigger == USE) { item->ItemEntry = itemProto->ItemId; item->SpellID = spellId; item->SpellCategory = itemProto->Spells[i].Category; if(itemProto->Spells[i].Category) { item->Cooldown = itemProto->Spells[i].CategoryCooldown; item->CooldownTimeStamp = now() + itemProto->Spells[i].CategoryCooldown; } else { item->Cooldown = itemProto->Spells[i].Cooldown; item->CooldownTimeStamp = now() + itemProto->Spells[i].Cooldown; } } } } _player->m_itemcooldown.insert(item); } Spell *spell = new Spell(_player, spellInfo, false, NULL); spell->i_caster = tmpItem; //GetPlayer()->setCurrentSpell(spell); spell->prepare(&targets); } void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { if(!_player->IsInWorld()) return; uint32 spellId; recvPacket >> spellId; sLog.outDetail("WORLD: got cast spell packet, spellId - %i, data length = %i", spellId, recvPacket.size()); // Cheat Detection only if player and not from an item // this could fuck up things but meh it's needed ALOT of the newbs are using WPE now // WPE allows them to mod the outgoing packet and basicly choose what ever spell they want :( if( !GetPlayer()->HasSpell(spellId) ) { sLog.outDetail("WORLD: Spell isn't casted because player \"%s\" is cheating", GetPlayer()->GetName()); return; } if (GetPlayer()->GetOnMeleeSpell() != spellId) { // check for spell id SpellEntry *spellInfo = sSpellStore.LookupEntry(spellId ); if(!spellInfo || !sHookInterface.OnCastSpell(_player, spellInfo)) { sLog.outError("WORLD: unknown spell id %i\n", spellId); return; } //autoshot 75 if((spellInfo->Flags3 & FLAGS3_ACTIVATE_AUTO_SHOT) /*spellInfo->Attributes == 327698*/) // auto shot.. { Item *weapon = GetPlayer()->GetItemInterface()->GetInventoryItem(EQUIPMENT_SLOT_RANGED); if(!weapon) return; uint32 spellid; switch(weapon->GetProto()->SubClass) { case 2: // bows case 3: // guns case 18: // crossbow spellid = SPELL_RANGED_GENERAL; break; case 16: // thrown spellid = SPELL_RANGED_THROW; break; case 19: // wands spellid = SPELL_RANGED_WAND; break; default: spellid = 0; break; } if(!spellid) spellid = spellInfo->Id; if(!_player->m_onAutoShot) { if(_player->IsMounted()) { _player->SendCastResult(spellInfo->Id, SPELL_FAILED_NOT_MOUNTED, 0); return; } _player->m_AutoShotStartX = _player->GetPositionX(); _player->m_AutoShotStartY = _player->GetPositionY(); _player->m_AutoShotStartZ = _player->GetPositionZ(); _player->m_AutoShotTarget = _player->GetSelection(); uint32 duration = _player->GetUInt32Value(UNIT_FIELD_RANGEDATTACKTIME); SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID()); if(!targets.m_unitTarget) return; SpellEntry *sp = sSpellStore.LookupEntry(spellid); _player->m_AutoShotSpell = sp; _player->m_AutoShotDuration = duration; //This will fix fast clicks if(_player->m_AutoShotAttackTimer < 500) _player->m_AutoShotAttackTimer = 500; _player->m_onAutoShot = true; } return; } /*const char * name = sSpellStore.LookupString(spellInfo->Name); if(name) sChatHandler.SystemMessageToPlr(_player, "%sSpell Cast:%s %s %s[Group %u, family %u]", MSG_COLOR_LIGHTBLUE, MSG_COLOR_SUBWHITE, name, MSG_COLOR_YELLOW, spellInfo->SpellGroupType, spellInfo->SpellFamilyName);*/ if(GetPlayer()->m_currentSpell && GetCastTime(sCastTime.LookupEntry(spellInfo->CastingTimeIndex))) { _player->SendCastResult(spellInfo->Id, SPELL_FAILED_SPELL_IN_PROGRESS, 0); return; } Spell *spell = new Spell(GetPlayer(), spellInfo, false, NULL); SpellCastTargets targets(recvPacket,GetPlayer()->GetGUID()); spell->prepare(&targets); } } void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; if(GetPlayer()->m_currentSpell) GetPlayer()->m_currentSpell->cancel(); } void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; for(uint32 x = 0; x < MAX_AURAS+MAX_POSITIVE_AURAS; ++x) { if(_player->m_auras[x] && _player->m_auras[x]->IsPositive() && _player->m_auras[x]->GetSpellId() == spellId) _player->m_auras[x]->Remove(); } sLog.outDebug("removing aura %u",spellId); } void WorldSession::HandleCancelChannellingOpcode( WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; Player *plyr = GetPlayer(); if(!plyr) return; if(plyr->m_currentSpell) { plyr->m_currentSpell->cancel(); } } void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& recv_data) { //sLog.outString("Received CMSG_CANCEL_AUTO_REPEAT_SPELL message."); //on original we automatically enter combat when creature got close to us // GetPlayer()->GetSession()->OutPacket(SMSG_CANCEL_COMBAT); GetPlayer()->m_onAutoShot = false; } void WorldSession::HandleAddDynamicTargetOpcode(WorldPacket & recvPacket) { uint64 guid; uint32 spellid; uint8 flags; recvPacket >> guid >> spellid >> flags; SpellEntry * sp = sSpellStore.LookupEntry(spellid); // Summoned Elemental's Freeze if (spellid == 33395) { if (!_player->m_Summon) return; } else if (!_player->m_CurrentCharm || guid != _player->m_CurrentCharm->GetGUID()) { return; } /* burlex: this is.. strange */ SpellCastTargets targets; targets.m_targetMask = flags; if(flags == 0) targets.m_unitTarget = guid; else if(flags == 0x02) { WoWGuid guid; recvPacket >> flags; // skip one byte recvPacket >> guid; targets.m_unitTarget = guid.GetOldGuid(); } else if(flags == 0x40) { recvPacket >> flags; // skip one byte recvPacket >> targets.m_destX >> targets.m_destY >> targets.m_destZ; } if(spellid == 33395) // Summoned Water Elemental's freeze { Spell * pSpell = new Spell(_player->m_Summon, sp, false, 0); pSpell->prepare(&targets); } else // trinket? { Spell * pSpell = new Spell(_player->m_CurrentCharm, sp, false, 0); pSpell->prepare(&targets); } }