Implemented broad support for fields min_dist, min_dist_mod, max_dist, max_dist_mod -

Scales spell power based on targets distance from caster.
This implemented in a broad way to function with spells
that would make sense to scale. Some work will still be needed on this.

Be aware if making custom
spells not everything will work and certain effects just
should not be included (use common sense).
This commit is contained in:
KayenEQ 2014-08-02 21:10:44 -04:00
parent e0e473ce06
commit 52d92b7181
10 changed files with 68 additions and 6 deletions

View File

@ -5,7 +5,9 @@ Kayen: Implemented spell_news fields
- npc_no_los (check if LOS is required for spells)
- InCombat, OutofCombat - Used together to restrict spells to only be cast while
in/out of combat (beneficial) or if target is in/out of combat (detrimental).
Many new fields added and defined for future development.
-min_dist, min_dist_mod, max_dist, max_dist_mod - Scales spell power based on targets distance from caster.
*This will require further work to fully implement but will work with 90% of live spells as is.
*If making custom spells do not include effects that can't be scaled (like a spell trigger)
Required SQL: utils/sql/git/required/2014_08_02_spells_new.sql

View File

@ -1040,6 +1040,15 @@ bool IsCastonFadeDurationSpell(uint16 spell_id)
return false;
}
bool IsPowerDistModSpell(uint16 spell_id)
{
if (IsValidSpell(spell_id) &&
(spells[spell_id].max_dist_mod || spells[spell_id].min_dist_mod) && spells[spell_id].max_dist > spells[spell_id].min_dist)
return true;
return false;
}
uint32 GetPartialMeleeRuneReduction(uint32 spell_id)
{
for (int i = 0; i < EFFECT_COUNT; ++i)

View File

@ -845,6 +845,7 @@ bool IsPersistDeathSpell(uint16 spell_id);
bool IsSuspendableSpell(uint16 spell_id);
uint32 GetMorphTrigger(uint32 spell_id);
bool IsCastonFadeDurationSpell(uint16 spell_id);
bool IsPowerDistModSpell(uint16 spell_id);
uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);

View File

@ -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 dist_targ = 0;
bool bad = IsDetrimentalSpell(spell_id);
bool isnpc = caster->IsNPC();
@ -755,7 +756,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
continue;
if (curmob == caster && !affect_caster) //watch for caster too
continue;
if (center->DistNoRoot(*curmob) > dist2) //make sure they are in range
dist_targ = center->DistNoRoot(*curmob);
if (dist_targ > dist2) //make sure they are in range
continue;
if (isnpc && curmob->IsNPC()) { //check npc->npc casting
FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
@ -786,6 +789,8 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
continue;
}
curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ);
//if we get here... cast the spell.
if (IsTargetableAESpell(spell_id) && bad) {
if (iCounter < MAX_TARGETS_ALLOWED) {

View File

@ -674,6 +674,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) {
{
distance = caster->DistNoRoot(*members[z]);
if(distance <= range2) {
members[z]->CalcSpellPowerDistanceMod(spell_id, distance);
caster->SpellOnTarget(spell_id, members[z]);
#ifdef GROUP_BUFF_PETS
if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed())

View File

@ -567,20 +567,24 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
//So keep a list of entity ids and look up after
std::list<uint32> id_list;
range = range * range;
float dist_targ = 0;
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *h = (*iterator);
if(range > 0)
{
if(caster->DistNoRoot(*h->ent) <= range)
dist_targ = caster->DistNoRoot(*h->ent);
if(dist_targ <= range)
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ);
}
}
else
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster);
}
++iterator;
}

View File

@ -182,6 +182,7 @@ Mob::Mob(const char* in_name,
has_numhits = false;
has_MGB = false;
has_ProjectIllusion = false;
SpellPowerDistanceMod = 0;
if(in_aa_title>0)
aa_title = in_aa_title;

View File

@ -615,6 +615,9 @@ public:
bool ImprovedTaunt();
bool TryRootFadeByDamage(int buffslot, Mob* attacker);
int16 GetSlowMitigation() const {return slow_mitigation;}
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
void ModSkillDmgTaken(SkillUseTypes skill_num, int value);
int16 GetModSkillDmgTaken(const SkillUseTypes skill_num);
@ -1114,6 +1117,7 @@ protected:
bool has_numhits;
bool has_MGB;
bool has_ProjectIllusion;
int16 SpellPowerDistanceMod;
// Bind wound
Timer bindwound_timer;

View File

@ -186,6 +186,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
buffs[buffslot].numhits = numhit;
}
bool _IsPowerDistModSpell = false;
if (IsPowerDistModSpell(spell_id))
_IsPowerDistModSpell = true;
else
SetSpellPowerDistanceMod(0);
// iterate through the effects in the spell
for (i = 0; i < EFFECT_COUNT; i++)
{
@ -198,6 +204,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands))
effect_value = GetMaxHP();
if (_IsPowerDistModSpell)
effect_value += (effect_value*(GetSpellPowerDistanceMod()/100)/100);
#ifdef SPELL_EFFECT_SPAM
effect_desc[0] = 0;
#endif
@ -6445,3 +6454,23 @@ bool Mob::CheckSpellCategory(uint16 spell_id, int category_id, int effect_id){
return false;
}
void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster)
{
if (IsPowerDistModSpell(spell_id)){
float distance = 0;
if (caster && !range)
distance = caster->CalculateDistance(GetX(), GetY(), GetZ());
else
distance = sqrt(range);
float dm_range = spells[spell_id].max_dist - spells[spell_id].min_dist;
float dm_mod_interval = spells[spell_id].max_dist_mod - spells[spell_id].min_dist_mod;
float dist_from_min = distance - spells[spell_id].min_dist;
float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range));
mod *= 100.0f;
SetSpellPowerDistanceMod(static_cast<int>(mod));
}
}

View File

@ -1915,6 +1915,8 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
Message_StringID(13, TARGET_OUT_OF_RANGE);
return(false);
}
spell_target->CalcSpellPowerDistanceMod(spell_id, dist2);
}
//
@ -2114,18 +2116,22 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
if((heading_to_target >= angle_start && heading_to_target <= 360.0f) ||
(heading_to_target >= 0.0f && heading_to_target <= angle_end))
{
if(CheckLosFN(spell_target))
if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los){
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
SpellOnTarget(spell_id, spell_target, false, true, resist_adjust);
}
}
}
else
{
if(heading_to_target >= angle_start && heading_to_target <= angle_end)
{
if(CheckLosFN((*iter)))
if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los){
(*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this);
SpellOnTarget(spell_id, (*iter), false, true, resist_adjust);
}
}
}
++iter;
}
break;