/// Spell Target Handling for type 76 All targets in area void Spell::SpellTargetAllTargetsInArea(uint32 i, uint32 j) { if( !m_caster || !m_caster->IsInWorld() ) return; FillAllTargetsInArea(i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, GetDBCCastTime(i)); }
/// Spell Target Handling for type 31: related to scripted effects void Spell::SpellTargetScriptedEffects(uint32 i, uint32 j) { if( m_spellInfo->NameHash == SPELL_HASH_WILD_GROWTH || m_spellInfo->NameHash == SPELL_HASH_CIRCLE_OF_HEALING ) { if( p_caster == NULL || !p_caster->IsInWorld() ) return; if( p_caster->GetGroup() ) { uint32 TargetCount = 0; p_caster->GetGroup()->Lock(); for(uint32 x = 0; x < p_caster->GetGroup()->GetSubGroupCount(); ++x) { if( TargetCount == 5 ) break; for(GroupMembersSet::iterator itr = p_caster->GetGroup()->GetSubGroup( x )->GetGroupMembersBegin(); itr != p_caster->GetGroup()->GetSubGroup( x )->GetGroupMembersEnd(); itr++) { if((*itr)->m_loggedInPlayer && TargetCount != 5) { Player* p_target = (*itr)->m_loggedInPlayer; if( p_caster->GetDistance2dSq( p_target ) <= 225 ) // both spells have 15yd range, change in future if needed { _AddTargetForced( (*itr)->m_loggedInPlayer->GetGUID(), i ); TargetCount += 1; } } } } p_caster->GetGroup()->Unlock(); } } else FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); }
SpellDesc* MoonScriptCreatureAI::AddSpell(uint32 pSpellId, TargetType pTargetType, float pChance, float pCastTime, int32 pCooldown, float pMinRange, float pMaxRange, bool pStrictRange, const char* pText, TextType pTextType, uint32 pSoundId, EmoteType pEmoteType) { //Cannot add twice same spell id - M4ksiu: Disabled, until I rewrite SetPhase(...) function to not disable same spells that are in different phases //SpellDesc* NewSpell = FindSpellById(pSpellId); //if( NewSpell ) return NewSpell; SpellDesc* NewSpell = NULL; //Find spell info from spell id SpellEntry* Info = dbcSpell.LookupEntry(pSpellId); // Let us just make sure // Use DBC info if we need to. if(Info != NULL) { if(pCastTime == NULL) pCastTime = GetDBCCastTime(dbcSpellCastTime.LookupEntry(Info->CastingTimeIndex)); if(pCooldown == NULL) pCooldown = Info->RecoveryTime; if(pMinRange == NULL) pMinRange = GetDBCMinRange(dbcSpellRange.LookupEntry(Info->rangeIndex)); if(pMaxRange == NULL) pMaxRange = GetDBCMaxRange(dbcSpellRange.LookupEntry(Info->rangeIndex)); } //Create new spell NewSpell = new SpellDesc(Info, NULL, pTargetType, pChance, pCastTime, pCooldown, pMinRange, pMaxRange, pStrictRange, pText, pTextType, pSoundId, pEmoteType); mSpells.push_back(NewSpell); return NewSpell; }
void AIInterface::addSpellToList(AI_Spell *sp) { ASSERT(m_Unit != NULL); if(sp->info == NULL) return; if(sp->info->Id == 0) return; AI_Spell* nSP = new AI_Spell(sp, sp->cooldown, sp->procCounter); if(nSP->info->buffType) if(nSP->TargetType != TargetGen_SummonOwner) nSP->TargetType = TargetGen_Self; if(nSP->casttime == 0) nSP->casttime = GetDBCCastTime(dbcSpellCastTime.LookupEntry( nSP->info->CastingTimeIndex )); if(nSP->maxdist2cast == 0.0f) { nSP->maxdist2cast = GetDBCMaxRange( dbcSpellRange.LookupEntry( nSP->info->rangeIndex ) ); if( nSP->maxdist2cast < sqrt( nSP->info->base_range_or_radius_sqr ) ) nSP->maxdist2cast = sqrt( nSP->info->base_range_or_radius_sqr ); } if(nSP->mindist2cast == 0.0f) nSP->mindist2cast = GetDBCMinRange( dbcSpellRange.LookupEntry( nSP->info->rangeIndex ) ); if(nSP->cooldown == 0) nSP->cooldown = nSP->info->StartRecoveryTime; //avoid spell spamming if(nSP->cooldown == 0) nSP->cooldown = nSP->info->StartRecoveryCategory; //still 0 ? if(nSP->cooldown == 0) nSP->cooldown = 4000; //omg, avoid spamming at least m_spells.insert(make_pair(nSP->info->Id, nSP)); }
/// Spell Target Handling for type 54: Targets in Front of the Caster void Spell::SpellTargetInFrontOfCaster2(uint32 i, uint32 j) { unordered_set<Object*>::iterator itr; for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd(); ++itr ) { if(!((*itr)->IsUnit()) || !TO_UNIT(*itr)->isAlive()) continue; //is Creature in range if(m_caster->isInRange(TO_UNIT(*itr),GetDBCCastTime(i))) { if(m_caster->isInFront(TO_UNIT(*itr))) { if(isAttackable(u_caster, TO_UNIT(*itr))) _AddTarget(TO_UNIT(*itr), i); } } } }
/// Spell Target Handling for type 24: Targets in Front of the Caster void Spell::SpellTargetInFrontOfCaster(uint32 i, uint32 j) { unordered_set<Object*>::iterator itr,itr2; if( m_spellInfo->cone_width == 0.0f ) { for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd();) { itr2 = itr; itr++; if(!((*itr2)->IsUnit()) || !TO_UNIT(*itr2)->isAlive()) continue; //is Creature in range if(m_caster->isInRange((*itr2),GetDBCCastTime(i))) { if(m_caster->isInFront(*itr2)) { if(isAttackable(u_caster, (*itr2))) _AddTarget(TO_UNIT(*itr2), i); } } } } else { for( itr = m_caster->GetInRangeSetBegin(); itr != m_caster->GetInRangeSetEnd();) { itr2 = itr; itr++; if(!((*itr2)->IsUnit()) || !TO_UNIT(*itr2)->isAlive()) continue; //is Creature in range if(m_caster->isInArc(*itr2, m_spellInfo->cone_width)) { if(m_caster->isInFront((*itr2))) { if(isAttackable(u_caster, (*itr2))) _AddTarget(TO_UNIT(*itr2), i); } } } } }
/// Spell Target Handling for type 33: Party members of totem, inside given range void Spell::SpellTargetNearbyPartyMembers(uint32 i, uint32 j) { // this implementation is wrong.... this one is for totems if( u_caster != NULL ) { if( u_caster->GetTypeId()==TYPEID_UNIT) { if( TO_CREATURE( u_caster )->IsTotem() ) { float r = GetDBCCastTime(i); r *= r; Player* p = TO_PLAYER( TO_CREATURE(u_caster)->GetSummonOwner()); if( p == NULL) return; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),p,r)) _AddTargetForced(p->GetGUID(), i); SubGroup * pGroup = p->GetGroup() ? p->GetGroup()->GetSubGroup(p->GetSubGroup()) : 0; if(pGroup) { p->GetGroup()->Lock(); for(GroupMembersSet::iterator itr = pGroup->GetGroupMembersBegin(); itr != pGroup->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || p == (*itr)->m_loggedInPlayer) continue; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr)->m_loggedInPlayer,r)) _AddTargetForced((*itr)->m_loggedInPlayer->GetGUID(), i); } p->GetGroup()->Unlock(); } } } } }
/// Spell Target Handling for type 38: Dummy Target (Server-side script effect) void Spell::SpellTargetDummyTarget(uint32 i, uint32 j) { //TargetsList *tmpMap=&m_targetUnits[i]; if( m_spellInfo->Id == 51699 ) { if( p_caster ) { Aura* aur = p_caster->FindAura( 52916 ); if( aur && aur->GetUnitCaster() ) { _AddTargetForced(aur->GetUnitCaster()->GetGUID(), i); return; } } } else if( m_spellInfo->Id == 12938 ) { //FIXME:this ll be immortal targets FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); } _AddTargetForced(m_caster->GetGUID(), i); }
/// Spell Target Handling for type 18: All Party Members around the Caster in given range NOT RAID void Spell::SpellTargetAllPartyMembersRangeNR(uint32 i, uint32 j) { Player* p = p_caster; if( p == NULL ) { if( TO_CREATURE( u_caster)->IsTotem() ) p = TO_PLAYER( TO_CREATURE(u_caster)->GetSummonOwner()); else if( u_caster->IsPet() && TO_PET( u_caster )->GetPetOwner() ) p = TO_PET( u_caster )->GetPetOwner(); } if( p == NULL ) return; float r = GetDBCCastTime(i); r *= r; if( IsInrange( m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), p, r ) ) _AddTargetForced(p->GetGUID(), i); SubGroup* subgroup = p->GetGroup() ? p->GetGroup()->GetSubGroup( p->GetSubGroup() ) : 0; if( subgroup != NULL ) { p->GetGroup()->Lock(); for(GroupMembersSet::iterator itr = subgroup->GetGroupMembersBegin(); itr != subgroup->GetGroupMembersEnd(); itr++) { if(!(*itr)->m_loggedInPlayer || m_caster == (*itr)->m_loggedInPlayer) continue; if(IsInrange(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),(*itr)->m_loggedInPlayer,r)) _AddTargetForced( (*itr)->m_loggedInPlayer->GetGUID(), i ); } p->GetGroup()->Unlock(); } }
/// Spell Target Handling for type 30: PBAE Party Based Area Effect void Spell::SpellTargetAllyBasedAreaEffect(uint32 i, uint32 j) { /* Description We take the selected party member(also known as target), then we get a list of all the party members in the area // Used in 26043 -> Battle Shout */ FillAllFriendlyInArea(i,m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),GetDBCCastTime(i)); }
/// this is handled in DO /// Spell Target Handling for type 28: All Enemies in Area of Effect(Blizzard/Rain of Fire/volley) channeled void Spell::SpellTargetEnemysAreaOfEffect(uint32 i, uint32 j) { FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); }
/// Spell Target Handling for type 22: Enemy Targets around the Caster//changed party members around you /// place around the target / near the target //targeted Area effect void Spell::SpellTargetAoE(uint32 i, uint32 j) // something special // grep: this is *totally* broken. AoE only attacking friendly party members and self // is NOT correct. // not correct at all:P { FillAllTargetsInArea(i,m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ(),GetDBCCastTime(i)); }
/// Spell Target Handling for type 18: Land under caster void Spell::SpellTargetLandUnderCaster(uint32 i, uint32 j) /// I don't think this is the correct name for this one { if( m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_DEMON && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_WILD && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT1 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT2 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT3 && m_spellInfo->Effect[i] != SPELL_EFFECT_SUMMON_OBJECT_SLOT4 ) FillAllTargetsInArea(i, m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), GetDBCCastTime(i)); else _AddTargetForced(m_caster->GetGUID(), i); }
// Spell Target Handling for type 8: related to Chess Move (DND), Firecrackers, Spotlight, aedm, Spice Mortar // Seems to be some kind of custom area of effect... Scripted... or something like that void Spell::SpellTargetCustomAreaOfEffect(uint32 i, uint32 j) { // This should be good enough for now FillAllTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i)); }
void Spell::SpellTargetInvisibleAOE(uint32 i, uint32 j) { FillSpecifiedTargetsInArea(i,m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,GetDBCCastTime(i),1); //TARGET_SPEC_INVISIBLE); }
void GameObject::InitAI() { if(pInfo == NULL) return; // this fixes those fuckers in booty bay if(pInfo->SpellFocus == 0 && pInfo->sound1 == 0 && pInfo->sound2 == 0 && pInfo->sound3 != 0 && pInfo->sound5 != 3 && pInfo->sound9 == 1) return; uint32 spellid = 0; switch(pInfo->Type) { case GAMEOBJECT_TYPE_TRAP: { spellid = pInfo->sound3; }break; case GAMEOBJECT_TYPE_SPELL_FOCUS://redirect to properties of another go { uint32 new_entry = pInfo->sound2; if(new_entry) { pInfo = GameObjectNameStorage.LookupEntry( new_entry ); if(pInfo == NULL) { Log.Warning("GameObject","Redirected gameobject %u doesn't seem to exists in database, skipping",new_entry); return; } if(pInfo->sound3) spellid = pInfo->sound3; } }break; case GAMEOBJECT_TYPE_RITUAL: { m_ritualmembers = new uint32[pInfo->SpellFocus]; memset(m_ritualmembers,0,sizeof(uint32)*pInfo->SpellFocus); }break; case GAMEOBJECT_TYPE_CHEST: { Lock *pLock = dbcLock.LookupEntry(GetInfo()->SpellFocus); if(pLock) { for(uint32 i = 0; i < 5; i++) { if(pLock->locktype[i]) { if(pLock->locktype[i] == 2) //locktype; { //herbalism and mining; if(pLock->lockmisc[i] == LOCKTYPE_MINING || pLock->lockmisc[i] == LOCKTYPE_HERBALISM) { CalcMineRemaining(true); } } } } } else if(pInfo->Type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) { Health = pInfo->SpellFocus + pInfo->sound5; } } } //Null out gossip_script here, will be set with sScriptMgr.register_go_gossip_script (if any). pInfo->gossip_script = NULL; myScript = sScriptMgr.CreateAIScriptClassForGameObject(GetEntry(), this); // hackfix for bad spell in BWL if(!spellid || spellid == 22247) return; SpellEntry *sp= dbcSpell.LookupEntry(spellid); if(!sp) { spell = NULL; return; } else { spell = sp; } //ok got valid spell that will be casted on target when it comes close enough //get the range for that float r = 0; for(uint32 i = 0; i < 3; i++) { if(sp->Effect[i]) { float t = GetDBCCastTime(dbcSpellRadius.LookupEntry(sp->EffectRadiusIndex[i])); if(t > r) r = t; } } if(r < 0.1)//no range r = GetMaxRange(dbcSpellRange.LookupEntry(sp->rangeIndex)); range = r*r;//square to make code faster checkrate = 20;//once in 2 seconds }