Skip to content

Commit dee7ea2

Browse files
committed
Fix: Regen, Implemented new Damage & Magic system
1 parent e2f6397 commit dee7ea2

File tree

9 files changed

+177
-317
lines changed

9 files changed

+177
-317
lines changed

Server.Configurations/ServerConfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"GlobalSpawnTimer": 3000.0,
118118
// Base damage modifier for monsters
119119
// Default: 1 (100%) - 1.2 (120%) Difficulty
120-
"BaseDamageMod": 1.2,
120+
"BaseDamageMod": 1.0,
121121

122122
// Players
123123
// Max level for players

Zolian.Server.Base/GameScripts/Formulas/Ac.cs

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,78 @@ public Ac(Sprite obj) { }
1212

1313
public override long Calculate(Sprite obj, long value)
1414
{
15-
var armor = obj.SealedAc;
16-
var dmgMitigation = armor / 100f;
17-
18-
if (obj.SealedAc < 0)
19-
{
20-
var dmgIncreasedByMitigation = Math.Abs(dmgMitigation) * value;
21-
value += (int)dmgIncreasedByMitigation;
15+
if (value <= 0)
16+
return 1;
2217

23-
if (value <= 0)
24-
value = 1;
18+
// Armor is clamped to [-200, 500] in Ac Property
19+
// SealedAc only reduces that range
20+
var armor = obj.SealedAc;
2521

26-
if (obj.Dmg <= 0) return value;
22+
// Sanitize armor value
23+
if (armor < -200)
24+
armor = -200;
2725

28-
var dmgModifier = obj.Dmg * 0.25;
29-
dmgModifier /= 100;
30-
var dmgBoost = dmgModifier * value;
31-
value += (int)dmgBoost;
26+
// -----------------------------------------------------
27+
// NEGATIVE AC → takes MORE damage, bounded (no Dmg use)
28+
// -----------------------------------------------------
29+
if (armor < 0)
30+
{
31+
// Every point below 0 AC is +1% damage taken.
32+
// -100 AC => +100% (2x total)
33+
// -200 AC => +200% (3x total)
34+
var penalty = Math.Min(System.Math.Abs(armor) / 100.0, 2.0); // 0..2
35+
var multiplier = 1.0 + penalty; // 1.0..3.0
3236

33-
if (value <= 0)
34-
value = 1;
37+
var increased = (long)(value * multiplier);
38+
return increased <= 0 ? 1 : increased;
39+
}
3540

41+
// No armor = no mitigation
42+
if (armor == 0)
3643
return value;
37-
}
44+
45+
// -----------------------------------------------------
46+
// POSITIVE AC → diminishing returns
47+
// Uses role-dependent caps for monsters
48+
// Uses 90% cap for players
49+
// -----------------------------------------------------
50+
double mitigationCurve;
51+
double maxCap;
3852

3953
if (obj is Monster monster)
4054
{
41-
dmgMitigation = monster.Template.MonsterArmorType switch
55+
// DR-style, role-based:
56+
(mitigationCurve, maxCap) = monster.Template.MonsterArmorType switch
4257
{
43-
MonsterArmorType.Caster when dmgMitigation >= 0.50f => 0.50f,
44-
MonsterArmorType.Common when dmgMitigation >= 0.75f => 0.75f,
45-
MonsterArmorType.Tank when dmgMitigation >= 0.98f => 0.98f,
46-
_ => dmgMitigation
58+
// Tanks: strong vs physical (70% cap, fast curve)
59+
MonsterArmorType.Tank => (120.0, 0.70),
60+
61+
// Common: balanced (55% cap, medium curve)
62+
MonsterArmorType.Common => (140.0, 0.55),
63+
64+
// Casters: weak vs physical (40% cap, slow curve)
65+
MonsterArmorType.Caster => (160.0, 0.40),
66+
_ => (140.0, 0.55)
4767
};
4868
}
4969
else
5070
{
51-
if (dmgMitigation >= 0.98f)
52-
dmgMitigation = 0.98f;
71+
// -----------------------------------------
72+
// PLAYER AC MODEL
73+
// -----------------------------------------
74+
mitigationCurve = 75.0;
75+
maxCap = 0.90; // 90% max physical mitigation
5376
}
5477

55-
var dmgReducedByMitigation = dmgMitigation * value;
56-
value -= (int)dmgReducedByMitigation;
78+
var mitigation = armor / (armor + mitigationCurve);
79+
if (mitigation < 0.0)
80+
mitigation = 0.0;
81+
if (mitigation > maxCap)
82+
mitigation = maxCap;
5783

58-
if (value <= 0)
59-
value = 1;
84+
var reduced = (long)(value * mitigation);
85+
var result = value - reduced;
6086

61-
return value;
87+
return result <= 0 ? 1 : result;
6288
}
6389
}

Zolian.Server.Base/GameScripts/Formulas/Damage.cs

Lines changed: 0 additions & 58 deletions
This file was deleted.

Zolian.Server.Base/GameScripts/Formulas/WillSavingThrow.cs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,57 @@ public WillSavingThrow(Sprite obj) { }
1212

1313
public override long Calculate(Sprite obj, long value)
1414
{
15-
var armor = obj.Will;
16-
var dmgMitigation = armor / 100f;
17-
18-
if (obj.Will < 0)
19-
{
20-
var dmgIncreasedByMitigation = Math.Abs(dmgMitigation) * value;
21-
value += (int)dmgIncreasedByMitigation;
22-
23-
if (value <= 0)
24-
value = 1;
25-
26-
if (obj.Dmg <= 0) return value;
27-
28-
var dmgModifier = obj.Dmg * 0.25;
29-
dmgModifier /= 100;
30-
var dmgBoost = dmgModifier * value;
31-
value += (int)dmgBoost;
15+
if (value <= 0)
16+
return 1;
3217

33-
if (value <= 0)
34-
value = 1;
18+
// Will is clamped to [0, 90] in Sprite
19+
var will = obj.Will;
3520

21+
// Zero Will = no mitigation
22+
if (will <= 0)
3623
return value;
37-
}
24+
25+
// -----------------------------------------------------
26+
// POSITIVE WILL -> diminishing returns
27+
// Uses role-dependent caps for monsters
28+
// -----------------------------------------------------
29+
double mitigationCurve;
30+
double maxCap;
3831

3932
if (obj is Monster monster)
4033
{
41-
dmgMitigation = monster.Template.MonsterArmorType switch
34+
// DR-style, role-based:
35+
(mitigationCurve, maxCap) = monster.Template.MonsterArmorType switch
4236
{
43-
MonsterArmorType.Caster when dmgMitigation >= 0.98f => 0.98f,
44-
MonsterArmorType.Common when dmgMitigation >= 0.75f => 0.75f,
45-
MonsterArmorType.Tank when dmgMitigation >= 0.50f => 0.50f,
46-
_ => dmgMitigation
37+
// Casters: strong vs magic (90% cap, leans on Will more)
38+
MonsterArmorType.Caster => (40.0, 0.90),
39+
40+
// Commons: balanced (75% cap, medium curve)
41+
MonsterArmorType.Common => (60.0, 0.75),
42+
43+
// Tanks: weak vs magic (50% cap, leans less on Will)
44+
MonsterArmorType.Tank => (75.0, 0.50),
45+
_ => (60.0, 0.75)
4746
};
4847
}
4948
else
5049
{
51-
if (dmgMitigation >= 0.85f)
52-
dmgMitigation = 0.85f;
50+
// -----------------------------------------
51+
// PLAYER Will MODEL
52+
// -----------------------------------------
53+
mitigationCurve = 60.0;
54+
maxCap = 0.85; // 85% max magical mitigation
5355
}
54-
55-
var dmgReducedByMitigation = dmgMitigation * value;
56-
value -= (int)dmgReducedByMitigation;
5756

58-
if (value <= 0)
59-
value = 1;
57+
var mitigation = will / (will + mitigationCurve);
58+
if (mitigation < 0.0)
59+
mitigation = 0.0;
60+
if (mitigation > maxCap)
61+
mitigation = maxCap;
62+
63+
var reduced = (long)(value * mitigation);
64+
var result = value - reduced;
6065

61-
return value;
66+
return result <= 0 ? 1 : result;
6267
}
6368
}

Zolian.Server.Base/GameScripts/Spells/GlobalSpellMethods.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ public static long WeaponDamageElementalProc(Sprite sprite, int weaponProc)
8282
return dmg;
8383
}
8484

85-
public static long AislingSpellDamageCalc(Sprite sprite, long baseDmg, Spell spell, double exp)
85+
public static long AislingSpellDamageCalc(Sprite sprite, Spell spell, double exp)
8686
{
8787
const int dmg = 0;
8888
if (sprite is not Aisling damageDealingAisling) return dmg;
8989
var spellLevelOffset = spell.Level + 1;
9090
var client = damageDealingAisling.Client;
91-
var bonus = baseDmg + 2.0 * spellLevelOffset;
91+
var bonus = ServerSetup.Instance.Config.BaseDamageMod + 2.0 * spellLevelOffset;
9292
var amp = client.Aisling.Int / 2.0 * exp;
9393
var final = (int)(amp + bonus);
9494
var crit = CritStrike();
@@ -101,10 +101,10 @@ public static long AislingSpellDamageCalc(Sprite sprite, long baseDmg, Spell spe
101101
return final;
102102
}
103103

104-
public static long MonsterElementalDamageProc(Sprite sprite, long baseDmg, Spell spell, double exp)
104+
public static long MonsterElementalDamageProc(Sprite sprite, Spell spell, double exp)
105105
{
106106
if (sprite is not Monster damageMonster) return 0;
107-
var imp = baseDmg + 2.0;
107+
var imp = ServerSetup.Instance.Config.BaseDamageMod + 2.0;
108108
var level = damageMonster.Level;
109109

110110
var amp = damageMonster.Int / 2.0 * exp;
@@ -125,7 +125,7 @@ public static void ElementalOnSuccess(Sprite sprite, Sprite target, Spell spell,
125125
if (sprite is Aisling aisling)
126126
{
127127
var levelSeed = (long)((aisling.ExpLevel + aisling.AbpLevel) * 0.10 * spell.Level);
128-
var dmg = AislingSpellDamageCalc(sprite, levelSeed, spell, exp);
128+
var dmg = AislingSpellDamageCalc(sprite, spell, exp);
129129

130130
if (target.CurrentHp > 0)
131131
{
@@ -139,8 +139,7 @@ public static void ElementalOnSuccess(Sprite sprite, Sprite target, Spell spell,
139139
}
140140
else
141141
{
142-
var dmg = (long)damageable.GetBaseDamage(sprite, sprite.Target, MonsterEnums.Elemental);
143-
dmg = MonsterElementalDamageProc(sprite, dmg, spell, exp);
142+
var dmg = MonsterElementalDamageProc(sprite, spell, exp);
144143
damageable.ApplyElementalSpellDamage(sprite, dmg, spell.Template.ElementalProperty, spell);
145144

146145
if (target is Aisling targetAisling)
@@ -260,7 +259,7 @@ public static void ElementalNecklaceOnSuccess(Sprite sprite, Sprite target, Spel
260259
if (sprite is not Aisling aisling) return;
261260
if (target is not Damageable damageable) return;
262261
var levelSeed = (long)((aisling.ExpLevel + aisling.AbpLevel) * 0.10 * spell.Level);
263-
var dmg = AislingSpellDamageCalc(sprite, levelSeed, spell, exp);
262+
var dmg = AislingSpellDamageCalc(sprite, spell, exp);
264263

265264
if (target.CurrentHp > 0)
266265
{

Zolian.Server.Base/GameScripts/Spells/RacialSpellTree.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,7 @@ public override void OnSuccess(Sprite sprite, Sprite target)
293293
{
294294
if (sprite is not Aisling aisling) return;
295295
if (target is not Damageable damageable) return;
296-
var dmg = (long)aisling.GetBaseDamage(aisling, target, MonsterEnums.Elemental);
297-
dmg = GlobalSpellMethods.AislingSpellDamageCalc(sprite, dmg, Spell, 95);
296+
var dmg = GlobalSpellMethods.AislingSpellDamageCalc(sprite, Spell, 95);
298297
var randomEle = Generator.RandomEnumValue<ElementManager.Element>();
299298

300299
if (target.CurrentHp > 0)

Zolian.Server.Base/Network/Components/PlayerRegenerationComponent.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,19 @@ private static void ProcessUpdates(Aisling player)
8181
player.CurrentMp == player.MaximumMp)
8282
return;
8383

84+
var performedRegen = false;
85+
8486
// Clamp overflows
85-
if (player.CurrentHp > player.MaximumHp || player.CurrentMp > player.MaximumMp)
87+
if (player.CurrentHp > player.MaximumHp)
8688
{
8789
player.CurrentHp = player.MaximumHp;
90+
performedRegen = true;
91+
}
92+
93+
if (player.CurrentMp > player.MaximumMp)
94+
{
8895
player.CurrentMp = player.MaximumMp;
89-
player.Client.SendAttributes(StatUpdateType.Vitality);
96+
performedRegen = true;
9097
}
9198

9299
// Special-case: peasants / GMs
@@ -104,7 +111,6 @@ private static void ProcessUpdates(Aisling player)
104111
var hpHardCap = Math.Abs(player.BaseHp / 3.00);
105112
var mpHardCap = Math.Abs(player.BaseMp / 3.00);
106113

107-
var performedRegen = false;
108114

109115
if (player.CurrentHp < player.MaximumHp)
110116
{

0 commit comments

Comments
 (0)