Spell Resist calculation

A place to submit .patch fixes for the DOL SVN

Moderator: Developer Team

Spell Resist calculation

Postby Kakuri » Tue Mar 17, 2009 7:04 am

Currently, there is no consistent approach to calculating spell resists - there are two methods in SpellHandler.cs that address the task. One is CalculateToHitChance() and the other is CalculateSpellResistChance(). In SpellHandler.cs, CalculateSpellResistChance is defined as:
Code: Select all
public virtual int CalculateSpellResistChance(GameLiving target)
{
if (m_spellLine.KeyName == GlobalSpellsLines.Combat_Styles_Effect)
return 0;
if (HasPositiveEffect)
return 0;
return 100 - CalculateToHitChance(target);
}
Considering that this method does so little and turns over the bulk of the work to CalculateToHitChance, it seems reasonable to me to get rid of CalculateToHitChance and move its logic into CalculateSpellResistChance (CalcSRC is also currently used in other code more than CalcTHC).

The inconsistency problem is that some inheriting classes choose to override CalcTHC and some choose to override CalcSRC. You can see there are two checks in the above method that should always be applied - these checks should not have to be duplicated in other code that decided to ignore CalcSRC and only utilize CalcTHC, but they are. Or they're ignored when they shouldn't be. This stands out as a bug to me which should be fixed, but fixing it would have a side-effect necessitating other fixes - since it's been in place so long, people have adopted the habit of assigning all style effect entries in the database to the "Combat Style Effects" spell line. I believe in fact we need two combat style effect lines - one for resistable effects, one for non-resistable. Or are all style effects supposed to be non-resistable (including Reaver Leviathan, Valewalker Blizzard Blade)?

After re-reading this, it occurred to me that the current system may have been intentional, but it strikes me as an odd (and undesirable) approach:
1. Set the base behavior to give Combat Style Effects 0% chance of being resisted.
2. In all inheriting spell handlers that want to adhere to 0% resist chance for combat style effects, use default CalcTHC/CalcSRC, or override CalcTHC for customized resist calcs.
3. In all inheriting spell handlers that don't want a 0% resist chance for combat style effects, override CalcSRC and possibly CalcTHC for customized resist calcs.
If this was intentional, it strikes me as a poor use of OOP and creates confusing code. Better to explicitly state in the style definition "this is a non-resistable style effect" or "this is a resistable style effect."
User avatar
Kakuri
Developer
 
Posts: 803
Joined: Tue Oct 28, 2008 10:40 pm
Website: http://enlight.hostrator.com/

Re: Spell Resist calculation

Postby Graveen » Tue Mar 17, 2009 8:32 am

I suppose the tohitchance is based of the target's level and by extension resistchances are indirectly related to target's level. Also, HitChance in my mind is not related to spell. Is there any case where spells can't hit ? bolt (=blocked??) ? arrows ?

In all case, light me where hitchance is necessary in spell. If used, if think we should use CalculateLandingChance(), rather than 2 imprecises formulaes.
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France

Re: Spell Resist calculation

Postby Kakuri » Tue Mar 17, 2009 10:13 am

I shudder to think of adding more colums to tables... but should we add an "IsResistable" column in the spell table? This would make it very clear which spells should have the possibility of being resisted and which should not. The current check for if the spell belongs to the "Combat Style Effects" spell line is not done consistently, because some style effects should be resistable while others should not. It's also a cleaner approach than checking for special spell lines whose behavior isn't even clearly defined. Just think if you're new to DOL and you see some spells are in "CombatStyleEffects1" spell line and others are in "CombatStyleEffects2" spell line (and some might have no spell line at all!). It's not clear what the purpose of everything is. But if each spell has an IsResistable field then it's very clear. It would also of course be a huge boon to custom servers so they can easily configure which spells can't be resisted.
User avatar
Kakuri
Developer
 
Posts: 803
Joined: Tue Oct 28, 2008 10:40 pm
Website: http://enlight.hostrator.com/

Re: Spell Resist calculation

Postby Tolakram » Tue Mar 17, 2009 3:04 pm

Standard spell hitchance is always 85% and then modified by level. PvP hitchance is not modified by level but the spell strength is. The big complaint of casters is that on high level mobs the hit chance is insanely low, which is why focus level abilities were added to the game. As far as I know a spell is either subject to resist chance (all or nothing) or it is non resistible. All spells are subject to hitchance and damage resists ... as far as I know anyway, needs to be verified.

I think a resist flag should be in the DB, it just makes sense. I think a lot more spell information should be in the db and the spell code should be limited to just the basic handlers required to execute all the various types of spells. In the end a spell is simply some kind of casting animation, client graphical effect(s), and some sort of outcome in life/mana/endurance change, stat changes, or buff change (I'm sure there are others). In the end the only time the spell code should be changed is if Mythic adds some combination that's not currently handled.

Of course that would require a pretty radical re-design. :(

Un oh, rant ...

On the other hand, because of the way handlers exist for just about everything (including class specific handlers) why have anything in the DB? I personally prefer scripting to SQL, but I suppose more are comfortable with SQL than with C# (which I work in every day). Hard to imagine. If things are to be kept in the DB then the DB should be read and cached as needed, and not everything read at startup. Just imagine if you could test by changing db entries on the fly, execute a cache clear command in game and test the changes.

Just a silly rant, don't take me too seriously. :)

Back to the code.

From my older version of spellhandler:
Code: Select all
/// <summary>
/// Calculates the chance that the spell lands on target
/// can be negative or above 100%
/// </summary>
/// <param name="target">spell target</param>
/// <returns>chance that the spell lands on target</returns>
public virtual int CalculateToHitChance(GameLiving target)
{
int spellLevel = Spell.Level;
GameLiving caster = null;
if (m_caster is GameNPC && (m_caster as GameNPC).Brain is ControlledNpc)
caster = ((ControlledNpc)((GameNPC)m_caster).Brain).Owner;
else caster = m_caster;
int spellbonus = caster.GetModified(eProperty.SpellLevel);
spellLevel += spellbonus;
//Cap on lvl 50 for spell level
if (spellLevel > 50)
spellLevel = 50;

int speclevel = 1;
int manastat = 0;
int bonustohit = m_caster.GetModified(eProperty.ToHitBonus);
if (caster is GamePlayer)
{
GamePlayer player = caster as GamePlayer;
speclevel = player.GetBaseSpecLevel(m_spellLine.Spec);
if (player.CharacterClass.ManaStat != eStat.UNDEFINED)
manastat = player.GetModified((eProperty)player.CharacterClass.ManaStat);
bonustohit += (int)(speclevel * 0.1 + manastat * 0.01);
}
//Piercing Magic affects to-hit bonus too
GameSpellEffect resPierce = SpellHandler.FindEffectOnTarget(m_caster, "PenetrateResists");
if (resPierce != null)
bonustohit += (int)resPierce.Spell.Value;
int hitchance = 85 + ((spellLevel - target.Level) >> 1) + bonustohit;
if (!(caster is GamePlayer && target is GamePlayer))
{
// level mod
hitchance -= (int)(m_caster.GetConLevel(target) * 10);
}
return hitchance;
}
One of the many issues I have with spellhandler is the need to override entire methods like this rather than simple overriding attributes that define how a spell works. In my opinion the above code should check to see if the spell is resistible before it runs the chance code. A spell that is non resistible should not execute half the checks above.
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: Spell Resist calculation

Postby Graveen » Tue Mar 17, 2009 3:41 pm

Mark, i don't understand the resist chance vs to hit chance. AFAIK, a spell ever hit, then get resisted or not.

I don't think a IsResistable is good. If we need to handle this per DB (and i like the way to do - i simply think it is not a quickfix, but a redesign. We 'll talk about simple redesign for the db soon, as i'm integrating Alex_Speed pkey integer chanegs, and perhaps it can be the time to do substancial changes in DB, as i need to write a converter :D), it must cover the entire specter of use, so a ResistChances field in the db seems more appropriate:

* -1 or null: defaut value, builtin resist calc (according to level, etc...)
* > -1: % chances to have the spell resisted

if we add a SP adding to the built in calc a % chance to have the spell landed (ie if you want 10% more chances to land spell, you can specify this via the SP modificator - do same for melee to hit), i think we cover the entire problem, allowing both flexibility and coherence.
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France

Re: Spell Resist calculation

Postby Tolakram » Tue Mar 17, 2009 4:01 pm

Mark, i don't understand the resist chance vs to hit chance. AFAIK, a spell ever hit, then get resisted or not.
It's the same thing. A spell has a chance to hit a player, the base chance is 85% before level modification. If the spell does not hit then instead of calling it a miss Mythic called it a resist (and the sparkle graphic plays above your head). This is often confused with damage resists, which are completely different.

Some spells can not be resisted (miss) and there may be some spells that are not effected by damage resists, but I'm not aware of any. The spells used for styles, like stun and bleed are non-resistible. In other words if the style lands the spell attached to the style will always land. Most weapon procs are resistible, while fighting you may see ____ resisted the effect, which simply means the proc went off but the spell was resisted (missed).

I think there are ML spells that are not resistible (can't miss).

It really helps to think of spell resists as misses to keep from confusing them with damage resists. :)

In both cases above if the spell lands the damage IS modified by damage resists, but damage resists do nothing to effect the spell resist (miss) chance. The only thing that effects spell resist (miss) chances are the spells level, the Mastery of Focus ability (which raises the level, capped at 50) and the penetrate resists skill, which reduces the chance of a spell resisting (missing).

Clear as mud?

player.Out.SendSpellEffectAnimation(client.Player, target, spellID, 0, fNoSound, fResist ? (byte)0 : (byte)1);

As you can see above the client even accepts a resist flag. All you have to do is set the resist flag to 1 and instead of the pretty graphic playing you'll get the miss sparkle graphic.

By the way, if anyone wants to play around with all the various effects I wrote (or took, I can't remember) this lame little script so I could see and hear the ones that looked interesting off of Metty's ID list page.
Code: Select all
using System;
using DOL.GS.PacketHandler;
using DOL.GS.Spells;
using DOL.GS.Commands;
namespace DOL.GS.Scripts
{
[CmdAttribute(
"&effect",
ePrivLevel.GM,
"play a client effect",
"/effect [resist] [nosound] <ClientEffectID>")]
public class EffectyCommandHandler : ICommandHandler
{
public void OnCommand(GameClient client, string[] args)
{
if (args.Length < 2)
{
client.Out.SendMessage("Usage: /effect [resist] [nosound] <ClientEffectID>", eChatType.CT_System, eChatLoc.CL_SystemWindow);
return;
}
ushort spellID = 0;
bool fNoSound = false;
bool fResist = false;
try
{
string param1 = args[1];

if (param1.ToLower() == "nosound")
{
if (args.Length < 3)
{
client.Out.SendMessage("Usage: /effect [resist] [nosound] <ClientEffectID>", eChatType.CT_System, eChatLoc.CL_SystemWindow);
return;
}

fNoSound = true;
spellID = Convert.ToUInt16(args[2]);
}
else if (param1.ToLower() == "resist")
{
if (args.Length < 3)
{
client.Out.SendMessage("Usage: /effect [resist] [nosound] <ClientEffectID>", eChatType.CT_System, eChatLoc.CL_SystemWindow);
return;
}

fResist = true;
spellID = Convert.ToUInt16(args[2]);
}
else
{
spellID = Convert.ToUInt16(args[1]);
}

GameObject target = client.Player.TargetObject;

if (target == null)
target = client.Player;

foreach (GamePlayer player in target.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE))
{
player.Out.SendSpellEffectAnimation(client.Player, target, spellID, 0, fNoSound, fResist ? (byte)0 : (byte)1);
}
}
catch(Exception ex)
{
client.Out.SendMessage(ex.Message, eChatType.CT_System, eChatLoc.CL_SystemWindow);
return;
}
return;
}
}
}
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: Spell Resist calculation

Postby Graveen » Tue Mar 17, 2009 5:09 pm

Ok, we are talking of the same things, the 2 methods CalcCTH and CalcSRC should lead to an unique methods ChanceToLand() :p

For the effect reduced by the player's resists, i see in the code above, that piercing influence both damage and chance to land. I was not aware of this :)
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France

Re: Spell Resist calculation

Postby Tolakram » Tue Mar 17, 2009 5:56 pm

For the effect reduced by the player's resists, i see in the code above, that piercing influence both damage and chance to land. I was not aware of this :)
Uh yea, I wasn't either. I think this is wrong and I think I am wrong on what it does.

According to archived patch notes found here:

http://www.gatecentral.com/daoc/doc/pat ... ?mode=0406

Spell Piercing bonuses now correctly modifies resistances downward instead of upward, for direct damage spells, debuffs and damage over time spells. A level 50 character can not have more than 10% Spell Piercing effect up at any one time (from items or spells); any Spell Piercing over 10% is ignored (previously Spell Piercing was "capped" at 25% for a level 50 character).

This seems to indicate that spell piercing reduces damage resists and does not increase the chance of landing the spell.
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: Spell Resist calculation

Postby Kakuri » Tue Mar 17, 2009 6:16 pm

I've always understood that spell piercing was Mythic's (stupid!) response to resists. First caster damage was too high and everyone was pissed because as soon as a caster saw you it was BAM!BAM!BAM! dead HAHAHA! So instead of balancing casters they added more gear with resists. And then resist buffs. And then resist RAs. And then casters were like "WTF, I hit for 100(-700)?!" And so Mythic said, hey, we should add bonuses that casters can get that reduce enemy resists! Yeah, that's the way to go!

So if you have 30% Heat resist and a caster with 10% pierce bonus casts a heat spell on you, the effect is as if you only have 20% Heat resist. Spell Pierce should have nothing to do with whether the spell hits or not. That's a separate calculation performed before resists come into play, and is affected by MoFocus and +SpellLevel bonus (stupidly capped at 50, making it useless for PvE).
User avatar
Kakuri
Developer
 
Posts: 803
Joined: Tue Oct 28, 2008 10:40 pm
Website: http://enlight.hostrator.com/

Re: Spell Resist calculation

Postby Tolakram » Tue Mar 17, 2009 6:46 pm

Well that means this code is wrong (checked and it's still in the latest version)

//Piercing Magic affects to-hit bonus too
GameSpellEffect resPierce = SpellHandler.FindEffectOnTarget(m_caster, "PenetrateResists");
if (resPierce != null)
bonustohit += (int)resPierce.Spell.Value;
int hitchance = 85 + ((spellLevel - target.Level) >> 1) + bonustohit;

and should be removed.
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: Spell Resist calculation

Postby Kakuri » Tue Mar 17, 2009 9:52 pm

You know, I wonder if that code is buggy, or just poorly named...

There are spells that increase the caster's effective spell level (like Heretic's poorly named Piercing Magic). That code chunk is checking for a spell effect, a buff, on the caster, not item bonuses (only item bonuses give you +Resist Pierce AFAIK). So the correct behavior in that case is to increase the spell's effective level.
User avatar
Kakuri
Developer
 
Posts: 803
Joined: Tue Oct 28, 2008 10:40 pm
Website: http://enlight.hostrator.com/

Re: Spell Resist calculation

Postby Tolakram » Tue Mar 17, 2009 11:06 pm

Good point. I'm not familiar with all the latest buffs and effects.
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: Spell Resist calculation

Postby Graveen » Wed Mar 18, 2009 7:34 am

why not call the code from Mastery of focus with a suitable parameter ? this is not identical ?
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France


Return to “%s” DOL Code Contributions

Who is online

Users browsing this forum: No registered users and 0 guests