diff --git a/zone/effects.cpp b/zone/effects.cpp index 27cccd0a9..1b1eeb2ea 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -740,6 +740,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ 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); @@ -760,6 +761,8 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ dist_targ = center->DistNoRoot(*curmob); 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) { diff --git a/zone/entity.cpp b/zone/entity.cpp index 3d316585d..5ff19847f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4538,7 +4538,7 @@ Mob *EntityList::GetClosestMobByBodyType(Mob *sender, bodyType BodyType) return ClosestMob; } -void EntityList::GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list &m_list) +void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list) { auto it = mob_list.begin(); while (it != mob_list.end()) { @@ -4547,15 +4547,15 @@ void EntityList::GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, ++it; continue; } - int32 x_diff = ptr->GetX() - start->GetX(); - int32 y_diff = ptr->GetY() - start->GetY(); - int32 z_diff = ptr->GetZ() - start->GetZ(); + float x_diff = ptr->GetX() - start->GetX(); + float y_diff = ptr->GetY() - start->GetY(); + float z_diff = ptr->GetZ() - start->GetZ(); x_diff *= x_diff; y_diff *= y_diff; z_diff *= z_diff; - if ((x_diff + y_diff) <= (radius * radius)) + if ((x_diff + y_diff) <= (radius * radius) && (x_diff + y_diff) >= (min_radius * min_radius)) if(z_diff <= (height * height)) m_list.push_back(ptr); diff --git a/zone/entity.h b/zone/entity.h index 8b94b0e0a..c1ba0936c 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -406,7 +406,7 @@ public: void GetObjectList(std::list &o_list); void GetDoorsList(std::list &d_list); void GetSpawnList(std::list &d_list); - void GetTargetsForConeArea(Mob *start, uint32 radius, uint32 height, std::list &m_list); + void GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list); void DepopAll(int NPCTypeID, bool StartSpawnTimer = true); diff --git a/zone/groups.cpp b/zone/groups.cpp index c9f6e9127..d948eb476 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -658,6 +658,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { range = caster->GetAOERange(spell_id); float range2 = range*range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; // caster->SpellOnTarget(spell_id, caster); @@ -673,7 +674,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { else if(members[z] != nullptr) { distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { + if(distance <= range2 && distance >= min_range2) { members[z]->CalcSpellPowerDistanceMod(spell_id, distance); caster->SpellOnTarget(spell_id, members[z]); #ifdef GROUP_BUFF_PETS diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index f3de52544..1b585ca32 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -567,6 +567,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range) //So keep a list of entity ids and look up after std::list id_list; range = range * range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; auto iterator = list.begin(); while (iterator != list.end()) @@ -575,7 +576,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range) if(range > 0) { dist_targ = caster->DistNoRoot(*h->ent); - if(dist_targ <= range) + if(dist_targ <= range && dist_targ >= min_range2) { id_list.push_back(h->ent->GetID()); h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 864bf004c..2312614bc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -205,7 +205,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) effect_value = GetMaxHP(); if (_IsPowerDistModSpell) - effect_value += (effect_value*(GetSpellPowerDistanceMod()/100)/100); + effect_value = effect_value*(GetSpellPowerDistanceMod()/100); #ifdef SPELL_EFFECT_SPAM effect_desc[0] = 0; @@ -6471,6 +6471,6 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range)); mod *= 100.0f; - SetSpellPowerDistanceMod(static_cast(mod)); + SetSpellPSetSpellPowerDistanceMod(static_cast(mod)); } } \ No newline at end of file diff --git a/zone/spells.cpp b/zone/spells.cpp index f5bd8f09d..ca6d80f6f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1909,12 +1909,19 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 //casting a spell on somebody but ourself, make sure they are in range float dist2 = DistNoRoot(*spell_target); float range2 = range * range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; if(dist2 > range2) { //target is out of range. mlog(SPELLS__CASTING, "Spell %d: Spell target is out of range (squared: %f > %f)", spell_id, dist2, range2); Message_StringID(13, TARGET_OUT_OF_RANGE); return(false); } + else if (dist2 < min_range2){ + //target is too close range. + mlog(SPELLS__CASTING, "Spell %d: Spell target is too close (squared: %f < %f)", spell_id, dist2, min_range2); + Message_StringID(13, TARGET_TOO_CLOSE); + return(false); + } spell_target->CalcSpellPowerDistanceMod(spell_id, dist2); } @@ -2100,7 +2107,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 std::list targets_in_range; std::list::iterator iter; - entity_list.GetTargetsForConeArea(this, spells[spell_id].aoerange, spells[spell_id].aoerange / 2, targets_in_range); + entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].aoerange, spells[spell_id].aoerange / 2, targets_in_range); iter = targets_in_range.begin(); while(iter != targets_in_range.end()) {