Elin:Code Analysis/Combat

From Ylvapedia


Evalue List

Value# Element Notes
(92) Penetration
(108) Throwing
(132) Tactics
(133) Marksman
(305) Magic Device
(411) Spell Enhance
(482) Force Weapon
(1400) Feat: Weapon Mastery 1, 2
(1404) Feat: Ranged Mastery 1, 2

Damage Reduction Scaling with Enemy Level

As of Beta version: 22.23. Last updated EA23.46

The following is how much damage reduction the enemy receives past level 50:

Firstly, enemies at or below level 50 have 0% DR.

Conversely, enemies at or above level 1024 have 80% DR.

if (!this.IsPCFaction && this.LV > 50)
{
    dmg = dmg * (100 - (int)Mathf.Min(80f, Mathf.Sqrt((float)(this.LV - 50)) * 2.5f)) / 100;
}


If it is the player character faction and the enemy's level is higher than lvl 51, then:

your damage is multiplied by * (100 - an integer that is the smallest of either (80, the sqrt of a float (the enemies level - 50) * 2.5) / 100)

so either your damage is reduced by 80% against enemies above 1024 or its  [sqrt(floor - 50) * 2.5] / 100 for enemies between lvl 51 and lvl 1023

DR at specified levels
Enemy Level: DR percentage (%)
51 2.50
100 17.67
150 25.00
200 30.61
250 35.35
300 39.53
350 43.30
400 46.77
450 50.00
500 53.03
550 55.90
600 58.63
650 61.24
700 63.74
750 66.14
800 68.47
850 70.71
900 72.89
950 75
1000 77.06

Weapon Hit Mechanics

Updated EA23.46

"Curve" refers to the game's method for adding a sliding curve to the effectiveness of skill values

CURVE( input, start, step, rate)
if input <= start
return input

repeat x10
{
 num = start + repeatindex * step
	if input <= num
	return input
else
	input = num + (input - num) * rate /100
}
return input

First the system evaluates the attacker's 'TO HIT' and the target's 'EVASION'

The TO HIT value will be calculated differently depending on the type of weapon used (thrown, range, melee, martial) and style

TO HIT
Weapon Type Calculation
Thrown Curve([attacker's DEX]/4 + [attacker's STR]/2 + [attacker's weapon skill], 50, 25, 75) + 75 (250 if not PC Faction)
Martial (No Shield) Curve([attacker's DEX]/3 + [attacker's STR]/3 + [attacker's weapon skill], 50, 25, 75) + 50
Martial (With Shield) 75% of Curve([attacker's DEX]/3 + [attacker's STR]/3 + [attacker's weapon skill], 50, 25, 75) + 50
Cane Curve([attacker's WIL]/4 + [attacker's weapon's primary attribute]/3 [attacker's weapon skill], 50, 25, 75) + 100
All Others Curve([attacker's DEX]/4 + [attacker's weapon's primary attribute]/3 [attacker's weapon skill], 50, 25, 75) + 50

Your Hit modifier from gear and the weapon are then added to the above (a distance modifier is then applied for Ranged weapons)

EVASION is calculated on a Curve([target's PER] / 3 + [target's evasion skill], 50, 10, 75) + [target's DV] + 25


These values are then modified in the following order with compounding effect:

MODIFIERS
Condition Effect
Attacker has Bane TO HIT = 75%
Attacker has HigherGround TO HIT +20%
Attacker is Riding TO HIT = TO HIT * 100 / (100 + 500 / higher of(5 or 10 + [attacker's riding skill]))
Attacker is Hosting TO HIT = TO HIT * 100 / (100 + 1000 / higher of(5 or 10 + [attacker's symbiosis skill]))
Attacker is Being Ridden TO HIT = TO HIT * 100 / (100 + 1000 / higher of(5 or 10 + [attacker's STR]))
Attacker is a Parasite TO HIT = TO HIT * 100 / (100 + 1000 / higher of(5 or 10 + [attacker's DEX]))
Attack is Two Handed TO HIT = TO HIT + 25 + sqrt([attacker's two handed skill] * 2)
Attack is Dual Wield ^ TO HIT(DW) = TO HIT * 100 / (115 + Slot# * 15 + Slot# * (2000/(20+ attacker's dual wield skill)) [Clamped to 1-100]
Attacker is Blind TO HIT = 33.33% (or 10% if ranged/throwing)
Target is Blind EVASION = 50%
Target is Dim EVASION = 50%
Target has Higher Ground EVASION + 20%

^ Where Slot# represents the main hand / off hand and any indexed hand after two. Only the (2000/(20 + attacker's dual wielding skill)) is clamped between 1-100. This means optimally the best dual wielding scenario occurs when you have 1980 dual wielding.

Now the system has the TO HIT and EVASION values, it uses these to calculate if an attack was a hit, miss, or crit in this order

IF Target is Dim & 1 in 4 chance
   CRIT
IF Target is Dead or Sleeping
   CRIT
IF [target's Greater Evasion] * 10 > TO HIT
   num = EVASION * 100 / TO HIT
   IF 'num2' > 300 & random 0 to ([target's Greater Evasion]+250) > 100
	MISS
   IF 'num2' > 200 & random 0 to ([target's Greater Evasion]+250) > 150
	MISS
   IF 'num2' > 150 & random 0 to ([target's Greater Evasion]+250) > 200
	MISS
IF [target's Perfect Evasion] > random 0 - 99
   MISS
IF 1 in 20
   HIT
IF 1 in 20
   MISS
IF TO HIT < 1
   MISS
IF EVASION < 1
   HIT
IF random 0 - TO HIT < random 0 - (EVASION * 125 (150 if ranged attack) / 100)
   MISS
IF random 0 - 5000 < [attacker's PER]
   CRIT
IF [attacker's Critical skill] + sqrt([attacker's Eye of Mind skill]) > random 0 -200
   CRIT
IF attacker has [Heart of Death]
   num = 100 - [attacker's current HP] * 100 / [attacker's Max HP]
   IF num >= 50 & (num^3 / 3) > random 0 - 100000000
      CRIT
HIT

Martial Arts

else if (this.IsMartial || this.IsMartialWeapon)
{
    this.weaponSkill = this.CC.elements.GetOrCreateElement(100);
    this.attackType = (this.CC.race.meleeStyle.IsEmpty() ? ((EClass.rnd(2) == 0) ? AttackType.Kick : AttackType.Punch) : this.CC.race.meleeStyle.ToEnum(true));
    this.dBonus = this.CC.DMG + this.CC.encLV + (int)Mathf.Sqrt((float)(this.CC.STR / 5 + this.weaponSkill.Value / 4));
    this.dNum = 2 + Mathf.Min(this.weaponSkill.Value / 10, 4);
    this.dDim = 5 + (int)Mathf.Sqrt((float)(this.weaponSkill.Value / 3));
    this.dMulti = 0.6f + (float)(this.CC.STR / 2 + this.weaponSkill.Value / 2 + this.CC.Evalue(132) / 2) / 50f;
    this.dMulti += 0.05f * (float)this.CC.Evalue(1400);
    this.toHitBase = EClass.curve(this.CC.DEX / 3 + this.CC.STR / 3 + this.weaponSkill.Value, 50, 25, 75) + 50;
    this.toHitFix = this.CC.HIT;
    if (this.attackStyle == AttackStyle.Shield)
    {
        this.toHitBase = this.toHitBase * 75 / 100;
    }
    this.penetration = Mathf.Clamp(this.weaponSkill.Value / 10 + 5, 5, 20) + this.CC.Evalue(92);
    if (this.IsMartialWeapon)
    {
        this.dBonus += this.weapon.DMG;
        this.dNum += this.weapon.source.offense[0];
        this.dDim = Mathf.Max(this.dDim / 2 + this.weapon.c_diceDim, 1);
        this.toHitFix += this.weapon.HIT;
        this.penetration += this.weapon.Penetration;
        if (!this.weapon.source.attackType.IsEmpty())
        {
            this.attackType = this.weapon.source.attackType.ToEnum(true);
        }
    }
}

The player kicks or punches using the Martial Arts skill. The player will kick or punch based on melee style or character specifications.

Damage is determined by Martial Arts, Strength, Dexterity, Enchantment Value

Damage dice is 2+(Martial Arts / 10), to a maximum of d6.

The damage value of the dice is 5+√(Martial Arts / 3).

Damage multiplier is 0.6 + ((Strength / 2 + Martial Arts / 2 + Tactics / 2) / 50.0).

If the player has the Weapon Mastery feat, additional damage is provided at a rate of 0.05x(Weapon Mastery Rank). (Effectively, +0.05 or +0.10)

Accuracy is ((Strength /3 + Dexterity /3 + Martial Arts)+50)), with a minimum value of 25+50 and a maximum of 75+50. If the player is wielding a Shield, there is a -25% downward adjustment.

Penetration is calculated at (Martial Arts/10)+5, with a minimum of 5% and a maximum of 20% + Penetration.

If wielding Martial Art Weapon:

Damage Bonus is your empty hand Damage Bonus + Weapon's Damage Bonus

Dice Number is your empty hand Dice Number + Weapon's Dice Number

Dice Face is your empty hand Dice Face / 2 + Weapon's Dice Face

Dice Number is your empty hand Dice Number + Weapon's Dice Number

To Hit Bonus is your empty hand To Hit Bonus + Weapon's To Hit Bonus

Penetration is your empty hand Penetration + Weapon's Penetration

Throwing

if (this.isThrow)
{
    bool flag = this.weapon.HasTag(CTAG.throwWeapon) || this.weapon.HasTag(CTAG.throwWeaponEnemy);
    int num2 = (int)Mathf.Clamp(Mathf.Sqrt((float)(this.weapon.SelfWeight + this.weapon.ChildrenWeight)) * 3f + 25f + (float)(flag ? 75 : 0), 10f, 400f + Mathf.Sqrt((float)this.CC.STR) * 50f);
    int num3 = Mathf.Clamp(this.weapon.material.hardness, flag ? 40 : 20, 200);
    this.weaponSkill = this.CC.elements.GetOrCreateElement(108);
    this.attackType = AttackType.Blunt;
    this.dBonus = (this.CC.IsPCParty ? 3 : 7);
    this.dNum = 2;
    this.dDim = ((this.CC.IsPCParty ? 0 : this.CC.LV) + this.CC.STR + this.CC.Evalue(108)) * num2 * num3 / 10000 / 2;
    this.dMulti = 1f;
    this.toHitBase = EClass.curve(this.CC.DEX / 4 + this.CC.STR / 2 + this.weaponSkill.Value, 50, 25, 75) + (this.CC.IsPC ? 75 : 250);
    this.toHitFix = this.CC.HIT + this.weapon.HIT;
    this.penetration = 25;
}

The player throw the item from hand returning or not using the Throwing skill.

Attack Type is always Blunt

Weight Value is √Throwing Item Weight x 3 + if is Throwing Weapon: 75 else 0, with floor of 10 to ceiling of 400 + √(Strength x 50)

Material Value is Material Hardness, with floor of if is Throwing Weapon: 40 else 0 to ceiling of 200

Dice Number is always 2

Dice Face is (if isn't Player Character: Character Level + Strength + Throwing ) x Weight Value x Material Value / 10000 / 2

Accuracy is (Dexterity / 4 + Strength / 2 + Throwing) with a minimum value of 25+50 and a maximum of 75+50 + (if is Player Character: 75 else 250 )

To Hit bonus is Character To Hit Bonus + Weapon's To Hit Bonus

Damage bonus is if is Player Character: 3 else 7

Damage Multiplier is always 1

Penetration is always 25

Melee & Ranged

else
{
    if (this.IsRanged)
    {
        this.weaponSkill = this.CC.elements.GetOrCreateElement(this.toolRange.WeaponSkill);
    }
    else
    {
        this.weaponSkill = this.CC.elements.GetOrCreateElement(this.weapon.category.skill);
    }
    if (!this.weapon.source.attackType.IsEmpty())
    {
        this.attackType = this.weapon.source.attackType.ToEnum(true);
    }
    bool flag2 = this.IsCane || this.weapon.Evalue(482) > 0;
    if (flag2)
    {
        this.weaponSkill = this.CC.elements.GetOrCreateElement(305);
    }
    this.dBonus = this.CC.DMG + this.CC.encLV + this.weapon.DMG;
    this.dNum = this.weapon.source.offense[0];
    this.dDim = this.weapon.c_diceDim;
    this.dMulti = 0.6f + (float)(this.weaponSkill.GetParent(this.CC).Value + this.weaponSkill.Value / 2 + this.CC.Evalue(flag2 ? 304 : (this.IsRanged ? 133 : 132))) / 50f;
    this.dMulti += 0.05f * (float)this.CC.Evalue(this.IsRanged ? 1404 : 1400);
    this.toHitBase = EClass.curve((this.IsCane ? this.CC.WIL : this.CC.DEX) / 4 + this.weaponSkill.GetParent(this.CC).Value / 3 + this.weaponSkill.Value, 50, 25, 75) + 50;
    this.toHitFix = this.CC.HIT + this.weapon.HIT;
    this.penetration = this.weapon.Penetration + this.CC.Evalue(92);
    if (this.IsCane)
    {
        this.toHitBase += 50;
    }
}
if (this.ammo != null)
{
    this.dNumAmmo = ((this.ammo.source.offense.Length != 0) ? this.ammo.source.offense[0] : 0);
    this.dDimAmmo = this.ammo.c_diceDim;
    this.dBonusAmmo = this.ammo.DMG;
    if (this.dNumAmmo < 1)
    {
        this.dNumAmmo = 1;
    }
    if (this.dDimAmmo < 1)
    {
        this.dDimAmmo = 1;
    }
    this.dBonus += this.ammo.DMG;
    this.toHitFix += this.ammo.HIT;
}
else
{
    this.dNumAmmo = 0;
    this.dDimAmmo = 0;
}

The player swing thier melee weapon using the Tactics skill or shoot ranged weapon using the Marksman skill

If the weapon is Cane or it has Force Weapon enchantment it uses Magic Device skill instead of Tactics or Marksman skill

Damage Bonus is Player Character Damage Bonus + Weapon Mod Tool Damage Bonus + Weapon Damage Bonus

Damage Multiplier is 0.6 + (Weapon Main Stat + Weapon Skill / 2 + (If Melee Weapon Tactics, if Ranged Weapon Marksman, if Cane or Force Weapon Magic Device)) / 50

If the player has the Weapon/Ranged Mastery feat, additional damage is provided at a rate of 0.05 x (Weapon/Ranged Mastery Rank). (Effectively, +0.05 or +0.10)

Accuracy is (Dexterty or Will if Cane) / 4 + Weapon Skill Attribute / 3 + (If Melee Weapon Tactics, if Ranged Weapon Marksman, if Cane or Force Weapon Magic Device) with a minimum value of 25+50 and a maximum of 75+50

If it's Cane accuracy addtional + 50

To Hit Bonus is Character To Hit Bonus + Weapon To Hit Bonus + Ammo To Hit Bonus (if load with ammo)

Damage Bonus is Character Damage Bonus + Weapon Damage Bonus + Ammo Damage Bonus (if load with ammo)

Penetration is Character Penetration + Weapon Penetration

Spellcasting/Spellpower

public override int GetPower(Card c)
{
    int num = base.Value * 8 + 50;
    if (!c.IsPC)
    {
        num = Mathf.Max(num, c.LV * 6 + 30);
    }
    num = EClass.curve(num, 400, 100, 75);
    if (this is Spell)
    {
        num = num * (100 + c.Evalue(411)) / 100;
    }
    return num;
}
public static int curve(int a, int start, int step, int rate = 75)
{
    if (a <= start)
    {
        return a;
    }
    for (int i = 0; i < 10; i++)
    {
        int num = start + i * step;
        if (a <= num)
        {
            return a;
        }
        a = num + (a - num) * rate / 100;
    }
    return a;
}

Spellpower is curve( (Spell Level x 8 + 50), 400, 100, 75 ) x (100 + Spell Enhance Enchanement) / 100 if it's Player Character

Spellpower is the larger one between Spell Level x 8 + 50 or Char Level x 6 + 30 it's not Player Character

About curve function: curve(a, start, step, rate)

Set i = 0. Calculate num = start + i * step. When a exceeds num, the excess portion needs to be multiplied by rate / 100. Then increment i by 1. Repeat the above steps 10 times

In simple terms, this function is used to compress numerical values. The slope of the function's curve gradually decreases to (rate / 100)^10

Spellcasting/Damaging Spells

Type Dice Number Dice Sides Damage Bonus Notes
Touch 1+Spellpower/100+Attribute/10 3+Spellpower/50 Melee range
Arrow 1+Spellpower/160+Attribute/30 8+Spellpower/12 Spellpower/25 Single target
Bolt 1+Spellpower/120+Attribute/20 4+Spellpower/20 Damage all targets in a 10 tiles long straight line
Ball 1+Spellpower/70+Attribute/20 2+Spellpower/35 Damage all targets in a 5 tiles radius ball from the caster

Damage = Damage x 100 / (90 + range x 10)

Miasma 2+Spellpower/150 5+Spellpower/80 Damage once per turn
Breath 1+Spellpower/80+Attribute/20 6+Spellpower/100 Attribute/4 Damage all targets in a 7 tiles long 35° cone from the caster
Meteor 1+Spellpower/150 4+Attribute*3 Always Fire element

Damage all targets in a 10 tiles radius ball from the caster Can be blocked by walls Also damage the caster

Earthquake 5+Spellpower/30 10+Attribute/3 Always Imapct element

Damage all targets in a 12 tiles radius ball from the caster Deal double max dice damage to enemies with Gravity debuff Deal half damage to enemies with floating effect

Shatter Hex 1+Spellpower/160+Attribute/30 8+Spellpower/12 Spellpower/25 Removes all hexes on target and damages surrounding enemies.

Requires at least one hex on target to work.

Spellcasting/Healing Spells

Type Dice Number Dice Sides Healing Bonus Notes
Cure Minor Wounds 1+Spellpower/50+Will/30 5+Spellpower/40 Spellpower/30
Cure Heavy Wounds 2+Spellpower/40+Will/25 6+Spellpower/30 Spellpower/25
Cure Critical Wounds 3+Spellpower/35+Will/20 7+Spellpower/25 Spellpower/20
Healing 4+Spellpower/30+Will/15 8+Spellpower/20 Spellpower/15
Healing of 《Eris》 5+Spellpower/25+Will/10 9+Spellpower/15 Spellpower/10
Healing of 《Odina》 6+Spellpower/20+Will/5 10+Spellpower/10 Spellpower/5
Healing of 《Jure》 8+Spellpower/10+Will 15+Spellpower/5 Spellpower
Nature's Embrace 1+Spellpower/125 4+Spellpower/75

Spellcasting/Summoning Spells

case EffectId.Funnel:
{
    if (EClass._zone.CountMinions(CC) > CC.MaxSummon || CC.c_uidMaster != 0)
    {
        CC.Say("summon_ally_fail", CC, null, null);
        return;
    }
    CC.Say("spell_funnel", CC, element.Name.ToLower(), null);
    CC.PlaySound("spell_funnel", 1f, true);
    Chara chara = CharaGen.Create("bit", -1);
    chara.SetMainElement(element.source.alias, element.Value, true);
    chara.SetSummon(20 + power / 20 + EClass.rnd(10));
    chara.SetLv(power / 15);
    EClass._zone.AddCard(chara, tp.GetNearestPoint(false, false, true, false));
    chara.PlayEffect("teleport", true, 0f, default(Vector3));
    chara.MakeMinion(CC, MinionType.Default);
    return;
}
Type Duration Level Notes
Summon Bits 20 + rnd (20) + Spellpower / 20 Spellpower / 15
Summon Animal Until it dies Spell Level * (100 + Spellpower / 10) / 100 + Spellpower / 30
Summon Undead Younger Sisters Until it dies Spell Level * (100 + Spellpower / 10) / 100 + Spellpower / 30
Summon Shadow Until it dies Spellpower / 10 + 1 Use Suicide Explostion attack

Note that summons other than Bits has infinite duration