// solar: causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { LinkedListIterator<Mob*> iterator(mob_list); Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); const int MAX_TARGETS_ALLOWED = 4; int iCounter = 0; for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) { curmob = iterator.GetData(); if(curmob == center) //do not affect center continue; if(curmob == caster && !affect_caster) //watch for caster too continue; if(center->DistNoRoot(*curmob) > dist2) //make sure they are in range continue; if(isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if(bad) { //affect mobs that are on our hate list, or //which have bad faction with us if( ! (caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) ) continue; } else { //only affect mobs we would assist. if( ! (f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if(bad) { if(!caster->IsAttackAllowed(curmob, true)) continue; if(!center->CheckLosFN(curmob)) continue; } //if we get here... cast the spell. if(IsTargetableAESpell(spell_id) && bad) { if(iCounter < MAX_TARGETS_ALLOWED) { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } if(!isnpc) //npcs are not target limited... iCounter++; } }
// solar: causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); const int MAX_TARGETS_ALLOWED = 4; int iCounter = 0; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curmob = it->second; // test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading()) continue; if (curmob == center) //do not affect center continue; if (curmob == caster && !affect_caster) //watch for caster too continue; if (center->DistNoRoot(*curmob) > dist2) //make sure they are in range continue; if (isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (bad) { //affect mobs that are on our hate list, or //which have bad faction with us if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) ) continue; } else { //only affect mobs we would assist. if (!(f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if (bad) { if (!caster->IsAttackAllowed(curmob, true)) continue; if (!center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // This does not check faction for beneficial AE buffs..only agro and attackable. // I've tested for spells that I can find without problem, but a faction-based // check may still be needed. Any changes here should also reflect in BardAEPulse() -U if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) continue; } //if we get here... cast the spell. if (IsTargetableAESpell(spell_id) && bad) { if (iCounter < MAX_TARGETS_ALLOWED) { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } if (!isnpc) //npcs are not target limited... iCounter++; } }
// causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); int MAX_TARGETS_ALLOWED = 4; if (spells[spell_id].aemaxtargets) MAX_TARGETS_ALLOWED = spells[spell_id].aemaxtargets; int iCounter = 0; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curmob = it->second; // test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading()) continue; if (curmob == center) //do not affect center continue; if (curmob == caster && !affect_caster) //watch for caster too continue; if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && curmob->IsPetOwnerClient()) continue; if (spells[spell_id].targettype == ST_AreaClientOnly && !curmob->IsClient()) continue; if (spells[spell_id].targettype == ST_AreaNPCOnly && !curmob->IsNPC()) continue; if (spells[spell_id].targettype == ST_Ring) { dist_targ = DistanceSquared(static_cast<glm::vec3>(curmob->GetPosition()), caster->GetTargetRingLocation()); } else if (center) { dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition()); } if (dist_targ > dist2) //make sure they are in range continue; if (dist_targ < min_range2) //make sure they are in range continue; if (isnpc && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (bad) { //affect mobs that are on our hate list, or //which have bad faction with us if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) ) continue; } else { //only affect mobs we would assist. if (!(f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if (bad) { if (!caster->IsAttackAllowed(curmob, true)) continue; if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob)) continue; if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize())) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // This does not check faction for beneficial AE buffs..only agro and attackable. // I've tested for spells that I can find without problem, but a faction-based // check may still be needed. Any changes here should also reflect in BardAEPulse() if (caster->IsAttackAllowed(curmob, true)) continue; if (caster->CheckAggro(curmob)) continue; } curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ); //if we get here... cast the spell. if (IsTargetableAESpell(spell_id) && bad) { if (iCounter < MAX_TARGETS_ALLOWED) { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } else { if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); if (!spells[spell_id].aemaxtargets) caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } if (!isnpc || spells[spell_id].aemaxtargets) //npcs are not target limited (unless casting a spell with a target limit)... iCounter++; } }
// solar: causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { Mob *curmob; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; bool detrimental = IsDetrimentalSpell(spell_id); bool clientcaster = caster->IsClient(); const int MAX_TARGETS_ALLOWED = 4; int targets_hit = 0; if(center->IsBeacon()) targets_hit = center->CastToBeacon()->GetTargetsHit(); for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { curmob = it->second; // test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading()) continue; if (curmob == center) //do not affect center continue; if (curmob == caster && !affect_caster) //watch for caster too continue; dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition()); if (dist_targ > dist2) //make sure they are in range continue; if (dist_targ < min_range2) //make sure they are in range continue; if (!clientcaster && curmob->IsNPC()) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (detrimental) { //affect mobs that are on our hate list, or //which have bad faction with us if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS)) continue; } else { //only affect mobs we would assist. if (!(f <= FACTION_AMIABLE)) continue; } } //finally, make sure they are within range if (detrimental) { if (!caster->IsAttackAllowed(curmob, true)) { Log.Out(Logs::Detail, Logs::Spells, "Attempting to cast a detrimental AE spell/song on a player."); continue; } if (!zone->SkipLoS() && !spells[spell_id].npc_no_los && curmob != caster && !center->CheckLosFN(curmob)) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // This does not check faction for beneficial AE buffs..only agro and attackable. // I've tested for spells that I can find without problem, but a faction-based // check may still be needed. Any changes here should also reflect in BardAEPulse() -U if (caster->IsAttackAllowed(curmob, true)) { Log.Out(Logs::Detail, Logs::Spells, "Attempting to cast a beneficial AE spell/song on a NPC."); caster->Message_StringID(MT_SpellFailure, SPELL_NO_HOLD); continue; } if (caster->CheckAggro(curmob)) continue; } curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ); //if we get here... cast the spell. if (IsTargetableAESpell(spell_id) && detrimental) { if (targets_hit < MAX_TARGETS_ALLOWED || (clientcaster && curmob == caster)) { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); Log.Out(Logs::Detail, Logs::Spells, "AE Rain Spell: %d has hit target #%d: %s", spell_id, targets_hit, curmob->GetCleanName()); if (clientcaster && curmob != caster) //npcs are not target limited, pc caster does not count towards the limit. ++targets_hit; } } else { caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); } } if(center->IsBeacon()) center->CastToBeacon()->SetTargetsHit(targets_hit); }