This document contains the 100% IDA-verified magic damage formula for MapleStory v40, reverse engineered from sub_515307 (CalcMagicDamagePerHit).
BaseDamage = (INT × 0.5 + (Magic × 0.058)² + MagicInterp × 3.3) × EffectiveSkillMAD × 0.01
FinalDamage = Floor(BaseDamage) - DefenseSub
| Variable | Description | Source |
|---|---|---|
INT |
Character's INT stat | GetSecureValue(a4+15) |
Magic |
INT + MATK (total magic power) | GetSecureValue(a5+96) + GetSecureValue(a5+108) |
MagicInterp |
Interpolated magic (min to max via RNG) | See Mastery Interpolation |
EffectiveSkillMAD |
SkillMAD × AmpMultiplier |
Amp is integrated into skill damage |
DefenseSub |
Monster defense reduction | Interpolated MDD × [0.5, 0.6] |
| Address | Name | Value | Usage |
|---|---|---|---|
0x6295C8 |
dbl_6295C8 |
0.5 | INT coefficient |
0x62BD30 |
dbl_62BD30 |
0.058 | Magic quadratic coefficient |
0x62BD28 |
dbl_62BD28 |
3.3 | Magic linear coefficient |
0x62B6D0 |
dbl_62B6D0 |
0.01 | Skill scale factor |
0x62BD08 |
dbl_62BD08 |
5.0 | Mastery calculation |
0x62BD18 |
dbl_62BD18 |
10.0 | Mastery base value |
0x62BD00 |
dbl_62BD00 |
0.009 | Mastery scale |
0x62BC80 |
dbl_62BC80 |
99999.0 | Damage cap |
0x62BCE8 |
dbl_62BCE8 |
1e-7 | RNG normalization |
The mastery factor determines the minimum damage range:
// IDA Line 103
v52 = (skillMastery × 5.0 + 10.0) × 0.009| Skill Mastery | v52 Result | Min Damage % |
|---|---|---|
| 0 | 0.09 | 9% |
| 10 | 0.54 | 54% |
| 20 | 0.99 | 99% |
v35 = Magic; // Start at max
v59 = Magic × v52; // Calculate min
if (v59 < v35) {
Swap(v35, v59); // v35=min, v59=max
}
v35 = v35 + (v59 - v35) × rngFactor; // InterpolateCalcMagicDamagePerHit pre-generates 7 random values ONCE at the start, then cycles through them for all hits:
// Lines 76-84: Pre-generate 7 randoms
uint v51[7];
v62 = 0;
do {
v51[v62++] = CRand32::Random();
} while (v62 < 7);
// In the hit loop (for each hit):
accRandom = v51[v62 % 7]; v62++; // Accuracy
dmgRandom = v51[v62 % 7]; v62++; // Damage
defRandom = v51[v62 % 7]; v62++; // Defense| Hit | Acc Index | Dmg Index | Def Index |
|---|---|---|---|
| 1 | 0 | 1 | 2 |
| 2 | 3 | 4 | 5 |
Amp is integrated INTO the skill damage, not applied after defense:
EffectiveSkillMAD = SkillMAD × (AmpY / 100)
// Example: 55 × 1.35 = 74.25Important: The amp multiplier uses the skill's
yproperty (e.g., y=135 → 1.35×)
// IDA Constants
const double INT_COEFF = 0.5; // dbl_6295C8
const double MAGIC_QUAD_COEFF = 0.058; // dbl_62BD30
const double MAGIC_LINEAR_COEFF = 3.3; // dbl_62BD28
const double SKILL_SCALE = 0.01; // dbl_62B6D0
const double MASTERY_MULT = 5.0; // dbl_62BD08
const double MASTERY_ADD = 10.0; // dbl_62BD18
const double MASTERY_SCALE = 0.009; // dbl_62BD00
public int CalculateMagicDamage(
int intStat, int matk, int skillMastery, int skillMad,
double ampMultiplier, double dmgRngFactor)
{
int totalMagic = intStat + matk;
// Step 1: Calculate mastery factor (IDA line 103)
double v52 = (skillMastery * MASTERY_MULT + MASTERY_ADD) * MASTERY_SCALE;
// Step 2: Interpolate Magic stat (IDA lines 220-238)
double v35 = totalMagic;
double v59 = v35 * v52;
if (v59 < v35) {
(v35, v59) = (v59, v35); // Swap for min/max
}
v35 = v35 + (v59 - v35) * dmgRngFactor; // Interpolate
// Step 3: Apply formula (IDA lines 240-242)
// Amp is integrated into skillMad
double effectiveSkillMad = skillMad * ampMultiplier;
double intTerm = intStat * INT_COEFF;
double quadTerm = Math.Pow(totalMagic * MAGIC_QUAD_COEFF, 2);
double linearTerm = v35 * MAGIC_LINEAR_COEFF;
double damage = (intTerm + quadTerm + linearTerm) * effectiveSkillMad * SKILL_SCALE;
return (int)Math.Floor(damage);
}| Finding | Description |
|---|---|
| v64 = INT | Initially assumed to be LUK, but GetSecureValue(a4+15) returns INT |
| Skill Mastery | Read from skill data offset 268, not a fixed 60% |
| Amp Integration | Applied inside formula, NOT after defense subtraction |
| 7 Random Cycle | All hits share the same 7 pre-generated randoms, cycled with modulo 7 |
| Mastery Formula | (mastery × 5 + 10) × 0.009 converts skill mastery to interpolation factor |