Example #1
0
// 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++;
	}
}
Example #2
0
// 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);
}