mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
Rework buff duration formulas
These are derived from the client SE_IllusionPresistence will also set the duration to 10k tics like live
This commit is contained in:
+1
-1
@@ -1473,7 +1473,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
|
||||
}
|
||||
|
||||
void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId,
|
||||
uint8 WornType, uint32 ticsremaining, int buffslot, int instrument_mod,
|
||||
uint8 WornType, int32 ticsremaining, int buffslot, int instrument_mod,
|
||||
bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max)
|
||||
{
|
||||
int i, effect_value, base2, max, effectid;
|
||||
|
||||
+14
-10
@@ -89,7 +89,7 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
|
||||
if (IsClient() && GetClass() == WIZARD)
|
||||
ratio += RuleI(Spells, WizCritRatio); //Default is zero
|
||||
|
||||
|
||||
if (Critical){
|
||||
|
||||
value = value_BaseEffect*ratio/100;
|
||||
@@ -172,7 +172,7 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
|
||||
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
|
||||
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
|
||||
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
|
||||
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
|
||||
GetFocusEffect(focusFcDamageAmt, spell_id);
|
||||
|
||||
@@ -219,11 +219,11 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s
|
||||
total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time;
|
||||
|
||||
if (total_cast_time > 0 && total_cast_time <= 2500)
|
||||
extra_spell_amt = extra_spell_amt*25/100;
|
||||
else if (total_cast_time > 2500 && total_cast_time < 7000)
|
||||
extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000;
|
||||
else
|
||||
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
|
||||
extra_spell_amt = extra_spell_amt*25/100;
|
||||
else if (total_cast_time > 2500 && total_cast_time < 7000)
|
||||
extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000;
|
||||
else
|
||||
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
|
||||
|
||||
if(extra_spell_amt*2 < base_spell_dmg)
|
||||
return 0;
|
||||
@@ -281,7 +281,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
|
||||
if (Critical) {
|
||||
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits,
|
||||
OTHER_CRIT_HEAL, GetName(), itoa(value));
|
||||
|
||||
|
||||
if (IsClient())
|
||||
Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value));
|
||||
}
|
||||
@@ -413,6 +413,10 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
|
||||
|
||||
int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
|
||||
{
|
||||
if ((aabonuses.IllusionPersistence || spellbonuses.IllusionPersistence || itembonuses.IllusionPersistence) &&
|
||||
IsEffectInSpell(spell_id, SE_Illusion))
|
||||
return 10000; // ~16h
|
||||
|
||||
if (spells[spell_id].not_extendable)
|
||||
return duration;
|
||||
|
||||
@@ -771,7 +775,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
|
||||
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
|
||||
}
|
||||
} else {
|
||||
if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets)
|
||||
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);
|
||||
@@ -859,7 +863,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff
|
||||
if (!center->CheckLosFN(curmob))
|
||||
continue;
|
||||
} else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
|
||||
// See notes in AESpell() above for more info.
|
||||
// See notes in AESpell() above for more info.
|
||||
if (caster->IsAttackAllowed(curmob, true))
|
||||
continue;
|
||||
if (caster->CheckAggro(curmob))
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ public:
|
||||
bool IsBeneficialAllowed(Mob *target);
|
||||
virtual int GetCasterLevel(uint16 spell_id);
|
||||
void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0,
|
||||
uint8 WornType = 0, uint32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10,
|
||||
uint8 WornType = 0, int32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10,
|
||||
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
|
||||
void NegateSpellsBonuses(uint16 spell_id);
|
||||
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
|
||||
|
||||
@@ -83,7 +83,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
if(c_override)
|
||||
{
|
||||
int durat = CalcBuffDuration(caster, this, spell_id, caster_level);
|
||||
if(durat > 0)
|
||||
if(durat) // negatives are perma buffs
|
||||
{
|
||||
buffslot = AddBuff(caster, spell_id, durat, caster_level);
|
||||
if(buffslot == -1) // stacking failure
|
||||
@@ -3366,7 +3366,7 @@ void Mob::BuffProcess()
|
||||
if(buffs[buffs_i].spellid == SPELL_UNKNOWN)
|
||||
continue;
|
||||
|
||||
if(spells[buffs[buffs_i].spellid].buffdurationformula != DF_Permanent)
|
||||
if(buffs[buffs_i].ticsremaining > 0) // perma buffs will either be -1 or -4
|
||||
{
|
||||
if(!zone->BuffTimersSuspended() || !IsSuspendableSpell(buffs[buffs_i].spellid))
|
||||
{
|
||||
|
||||
+62
-67
@@ -2630,80 +2630,75 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste
|
||||
Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d",
|
||||
spell_id, castlevel, formula, duration, res);
|
||||
|
||||
return(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// the generic formula calculations
|
||||
int CalcBuffDuration_formula(int level, int formula, int duration)
|
||||
{
|
||||
int i; // temp variable
|
||||
int temp;
|
||||
|
||||
switch(formula)
|
||||
{
|
||||
case 0: // not a buff
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
i = (int)ceil(level / 2.0f);
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 2:
|
||||
i = (int)ceil(level / 5.0f * 3);
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 3:
|
||||
i = level * 30;
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 4: // only used by 'LowerElement'
|
||||
return ((duration != 0) ? duration : 50);
|
||||
|
||||
case 5:
|
||||
i = duration;
|
||||
// 0 value results in a 3 tick spell, else its between 1-3 ticks.
|
||||
return i < 3 ? (i < 1 ? 3 : i) : 3;
|
||||
|
||||
case 6:
|
||||
i = (int)ceil(level / 2.0f);
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 7:
|
||||
i = level;
|
||||
return (duration == 0) ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 8:
|
||||
i = level + 10;
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 9:
|
||||
i = level * 2 + 10;
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 10:
|
||||
i = level * 3 + 10;
|
||||
return i < duration ? (i < 1 ? 1 : i) : duration;
|
||||
|
||||
case 11:
|
||||
return std::min((level + 3) * 30, duration);
|
||||
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15: // Don't know what the real formula for this should be. Used by Skinspikes potion.
|
||||
return duration;
|
||||
|
||||
case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse counters, etc.
|
||||
return 72000; // 5 days until better method to make permanent
|
||||
|
||||
//case 51: // Permanent. Cancelled when out of range of aura. Placeholder until appropriate duration identified.
|
||||
|
||||
case 3600:
|
||||
return duration ? duration : 3600;
|
||||
|
||||
default:
|
||||
Log.Out(Logs::General, Logs::None, "CalcBuffDuration_formula: unknown formula %d", formula);
|
||||
switch (formula) {
|
||||
case 1:
|
||||
temp = level > 3 ? level / 2 : 1;
|
||||
break;
|
||||
case 2:
|
||||
temp = level > 3 ? level / 2 + 5 : 6;
|
||||
break;
|
||||
case 3:
|
||||
temp = 30 * level;
|
||||
break;
|
||||
case 4: // only used by 'LowerElement'
|
||||
temp = 50;
|
||||
break;
|
||||
case 5:
|
||||
temp = 2;
|
||||
break;
|
||||
case 6:
|
||||
temp = level / 2 + 2;
|
||||
break;
|
||||
case 7:
|
||||
temp = level;
|
||||
break;
|
||||
case 8:
|
||||
temp = level + 10;
|
||||
break;
|
||||
case 9:
|
||||
temp = 2 * level + 10;
|
||||
break;
|
||||
case 10:
|
||||
temp = 3 * level + 10;
|
||||
break;
|
||||
case 11:
|
||||
temp = 30 * (level + 3);
|
||||
break;
|
||||
case 12:
|
||||
temp = level > 7 ? level / 4 : 1;
|
||||
break;
|
||||
case 13:
|
||||
temp = 4 * level + 10;
|
||||
break;
|
||||
case 14:
|
||||
temp = 5 * (level + 2);
|
||||
break;
|
||||
case 15:
|
||||
temp = 10 * (level + 10);
|
||||
break;
|
||||
case 50: // Permanent. Cancelled by casting/combat for perm invis, non-lev zones for lev, curing poison/curse
|
||||
// counters, etc.
|
||||
return -1;
|
||||
case 51: // Permanent. Cancelled when out of range of aura.
|
||||
return -4;
|
||||
default:
|
||||
// the client function has another bool parameter that if true returns -2 -- unsure
|
||||
if (formula < 200)
|
||||
return 0;
|
||||
temp = formula;
|
||||
break;
|
||||
}
|
||||
if (duration && duration < temp)
|
||||
temp = duration;
|
||||
return temp;
|
||||
}
|
||||
|
||||
// helper function for AddBuff to determine stacking
|
||||
@@ -3066,7 +3061,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
if (duration == 0) {
|
||||
duration = CalcBuffDuration(caster, this, spell_id);
|
||||
|
||||
if (caster)
|
||||
if (caster && duration > 0) // negatives are perma buffs
|
||||
duration = caster->GetActSpellDuration(spell_id, duration);
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -2504,7 +2504,7 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) {
|
||||
"TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, "
|
||||
"CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, "
|
||||
"caston_x, Persistent, caston_y, caston_z, ExtraDIChance) "
|
||||
"VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);",
|
||||
"VALUES (%u, %u, %u, %u, %u, %d, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);",
|
||||
merc->GetMercID(), buffs[buffCount].spellid, buffs[buffCount].casterlevel,
|
||||
spells[buffs[buffCount].spellid].buffdurationformula, buffs[buffCount].ticsremaining,
|
||||
CalculatePoisonCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0,
|
||||
@@ -2982,7 +2982,7 @@ void ZoneDatabase::SaveBuffs(Client *client) {
|
||||
"caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, "
|
||||
"magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance, "
|
||||
"instrument_mod) "
|
||||
"VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', "
|
||||
"VALUES('%u', '%u', '%u', '%u', '%s', '%d', '%u', '%u', '%u', '%u', '%u', '%u', "
|
||||
"'%i', '%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid,
|
||||
buffs[index].casterlevel, buffs[index].caster_name, buffs[index].ticsremaining,
|
||||
buffs[index].counters, buffs[index].numhits, buffs[index].melee_rune,
|
||||
@@ -3023,7 +3023,7 @@ void ZoneDatabase::LoadBuffs(Client *client)
|
||||
|
||||
Client *caster = entity_list.GetClientByName(row[3]);
|
||||
uint32 caster_level = atoi(row[2]);
|
||||
uint32 ticsremaining = atoul(row[4]);
|
||||
int32 ticsremaining = atoi(row[4]);
|
||||
uint32 counters = atoul(row[5]);
|
||||
uint32 numhits = atoul(row[6]);
|
||||
uint32 melee_rune = atoul(row[7]);
|
||||
@@ -3128,12 +3128,12 @@ void ZoneDatabase::SavePetInfo(Client *client)
|
||||
query = StringFormat("INSERT INTO `character_pet_buffs` "
|
||||
"(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, "
|
||||
"`ticsremaining`, `counters`) "
|
||||
"VALUES (%u, %u, %u, %u, %u, %u, %d)",
|
||||
"VALUES (%u, %u, %u, %u, %u, %d, %d)",
|
||||
client->CharacterID(), pet, index, petinfo->Buffs[index].spellid,
|
||||
petinfo->Buffs[index].level, petinfo->Buffs[index].duration,
|
||||
petinfo->Buffs[index].counters);
|
||||
else
|
||||
query += StringFormat(", (%u, %u, %u, %u, %u, %u, %d)",
|
||||
query += StringFormat(", (%u, %u, %u, %u, %u, %d, %d)",
|
||||
client->CharacterID(), pet, index, petinfo->Buffs[index].spellid,
|
||||
petinfo->Buffs[index].level, petinfo->Buffs[index].duration,
|
||||
petinfo->Buffs[index].counters);
|
||||
@@ -3238,7 +3238,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) {
|
||||
uint32 caster_level = atoi(row[3]);
|
||||
int caster_id = 0;
|
||||
// The castername field is currently unused
|
||||
uint32 ticsremaining = atoul(row[5]);
|
||||
int32 ticsremaining = atoi(row[5]);
|
||||
uint32 counters = atoul(row[6]);
|
||||
|
||||
pi->Buffs[slot_id].spellid = spell_id;
|
||||
|
||||
Reference in New Issue
Block a user