📋 Damage Pipeline Overview

🔧 Implementation Ready

Dokumentasi ini berisi complete damage formula yang bisa langsung diimplementasikan ke dalam game code.

┌─────────────────────────────────────────────────────────────────┐ │ DAMAGE CALCULATION PIPELINE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. HIT CHECK → Miss / Hit / Critical │ │ ↓ │ │ 2. BASE DAMAGE → GATK + ATK (PATK or MATK) │ │ ↓ │ │ 3. SKILL MODIFIER → Skill multiplier & flat bonus │ │ ↓ │ │ 4. CRITICAL MODIFIER → Apply CDMG if critical │ │ ↓ │ │ 5. DEFENSE REDUCTION → Apply DEF with penetration │ │ ↓ │ │ 6. ELEMENT MODIFIER → Elemental weakness/resistance │ │ ↓ │ │ 7. PVE DAMAGE MOD → Monster type damage bonus (if vs mob) │ │ ↓ │ │ 8. DAMAGE MODIFIERS → Buffs, Debuffs, PvP reduction │ │ ↓ │ │ 9. BLOCK CHECK → Reduce if blocked │ │ ↓ │ │ 10. FINAL DAMAGE → Apply to target HP │ │ │ └─────────────────────────────────────────────────────────────────┘

Step 1: Hit Check

function checkHit(attacker, defender) { // Calculate hit chance let hitChance = 100 - calculateEvasionChance(attacker, defender); // Apply minimum/maximum hitChance = Math.max(5, Math.min(95, hitChance)); let roll = random(0, 100); if (roll > hitChance) { return "MISS"; } // Check for critical let critChance = calculateCritChance(attacker, defender); if (random(0, 100) < critChance) { return "CRITICAL"; } return "HIT"; } function calculateEvasionChance(attacker, defender) { let evasion = defender.EVA; let accuracy = attacker.ACC; let levelDiff = defender.level - attacker.level; // Level modifier let levelMod = 1 + (levelDiff * 0.05); levelMod = Math.max(0.5, Math.min(1.5, levelMod)); let evaChance = (evasion / (evasion + accuracy)) * 100 * levelMod; // Apply caps return Math.min(50, evaChance); // Hard cap 50% }

Step 2: Base Damage Calculation

function calculateBaseDamage(attacker, damageType) { let GATK = randomRange(attacker.weapon.minDmg, attacker.weapon.maxDmg); // Apply weapon enhancement GATK *= (1 + attacker.weapon.enhancement * 0.03); // Apply weapon quality GATK *= getQualityMultiplier(attacker.weapon.quality); let ATK; if (damageType === "PHYSICAL") { ATK = attacker.PATK; } else if (damageType === "MAGIC") { ATK = attacker.MATK; } return GATK + ATK; } function getQualityMultiplier(quality) { const multipliers = { "NORMAL": 1.0, "MAGIC": 1.1, "RARE": 1.25, "EPIC": 1.4, "LEGENDARY": 1.6 }; return multipliers[quality] || 1.0; }

Step 3: Skill Modifier

function applySkillModifier(baseDamage, skill, attacker) { // Skill has: multiplier (%), flatBonus, scalingStat let skillDamage = baseDamage * (skill.multiplier / 100); // Add flat bonus skillDamage += skill.flatBonus; // Add stat scaling if any if (skill.scalingStat === "STR") { skillDamage += attacker.STR * skill.statScaling; } else if (skill.scalingStat === "INT") { skillDamage += attacker.INT * skill.statScaling; } else if (skill.scalingStat === "DEX") { skillDamage += attacker.DEX * skill.statScaling; } return skillDamage; } // Example skill definition const powerStrike = { name: "Power Strike", multiplier: 150, // 150% of base damage flatBonus: 50, // +50 flat damage scalingStat: "STR", statScaling: 2.0, // +2 damage per STR damageType: "PHYSICAL" };

Step 4: Critical Damage Modifier

function applyCriticalModifier(damage, attacker, hitResult) { if (hitResult !== "CRITICAL") { return damage; } let critDamage = attacker.CDMG; // Percentage, e.g., 200 = 200% // Apply caps (soft cap handling) if (critDamage > 250) { let overCap = critDamage - 250; let diminished = overCap * 0.5; critDamage = Math.min(350, 250 + diminished); } return damage * (critDamage / 100); } function calculateCritChance(attacker, defender) { let baseCrit = 3; // Base 3% for all let dexBonus = attacker.DEX * 0.05; let equipBonus = attacker.critBonus || 0; let potionBonus = attacker.critPotion || 0; let totalCrit = baseCrit + dexBonus + equipBonus + potionBonus; // Level difference penalty let levelDiff = defender.level - attacker.level; if (levelDiff > 0) { totalCrit -= levelDiff * 4; // -4% per level } else if (levelDiff < 0) { totalCrit += Math.abs(levelDiff) * 2; // +2% per level totalCrit = Math.min(totalCrit, baseCrit + 10); // Cap bonus at +10% } // Apply soft cap if (totalCrit > 35) { let overCap = totalCrit - 35; let diminished = overCap * 0.5; totalCrit = Math.min(55, 35 + diminished); } return Math.max(0, totalCrit); }

Step 5: Defense Reduction

function applyDefenseReduction(damage, attacker, defender, damageType) { let defense; let penetration; if (damageType === "PHYSICAL") { defense = defender.PDEF; penetration = attacker.physicalPEN || 0; } else { defense = defender.MDEF; penetration = attacker.magicPEN || 0; } // Apply flat penetration first let flatPen = attacker.flatPEN || 0; defense = Math.max(0, defense - flatPen); // Apply percentage penetration penetration = Math.min(50, penetration); // Cap at 50% let effectiveDefense = defense * (1 - penetration / 100); // Calculate damage reduction const DEFENSE_CONSTANT = 350; let levelComponent = attacker.level * 10; let damageReduction = effectiveDefense / (effectiveDefense + DEFENSE_CONSTANT + levelComponent); // Cap damage reduction damageReduction = Math.min(0.75, damageReduction); // Max 75% reduction return damage * (1 - damageReduction); }

Defense Calculation Table

Defense vs Lv50 (no PEN) vs Lv50 (30% PEN)
30027.3% reduction20.2% reduction
50038.5% reduction29.8% reduction
70046.7% reduction37.5% reduction
100055.6% reduction46.7% reduction
150065.2% reduction56.8% reduction

Step 6: Elemental Modifier (Value Scale 0-100)

📖 New Elemental System

Uses affinity (0-100) and resistance (0-100) for dynamic scaling. Elemental Affinity scales with gear, skills, and leveling.

ELEMENT RELATIONSHIPS (Rock-Paper-Scissors): Water STRONG vs Fire Fire STRONG vs Earth Earth STRONG vs Wind Wind STRONG vs Water Damage Formula: Step 6a: Apply Attacker Affinity Elemental DMG = Base Damage × (1 + Affinity / 100) Step 6b: Apply Defender Resistance DMG After Resist = Elemental DMG × (1 - Resistance / 100) (Resistance soft cap: 40%, hard cap: 80%) Step 6c: Apply Element Relationship IF Strong vs Weak: Bonus = 1 + (Affinity / 100) × 0.25 Final = DMG After Resist × Bonus IF Weak vs Strong: Penalty = 1 - (Affinity / 100) × 0.25 Final = DMG After Resist × Math.max(0.75, Penalty) IF Neutral: Final = DMG After Resist (no modifier) Affinity Range: 0-100 (Soft Cap: 50, Hard Cap: 100) Resistance Range: 0-100 (Soft Cap: 40, Hard Cap: 80) Min Damage (Weak): 75% (cannot be reduced below 75%)
function applyElementalModifier_NEW(damage, skill, attacker, defender) { // If no elemental damage, return as-is if (!skill.element || skill.element === "NONE") { return damage; } let attackElement = skill.element; let attackerAffinity = attacker.elementalAffinity[attackElement] || 0; let defenderElement = defender.element; let defenderResistance = defender.elementalResistance[attackElement] || 0; // Step 6a: Apply Attacker's Elemental Affinity let elementalDamage = damage * (1 + attackerAffinity / 100); // Step 6b: Apply Defender's Elemental Resistance // Cap resistance: soft cap at 40%, hard cap at 80% let cappedResistance = Math.min(80, defenderResistance); let damageAfterResist = elementalDamage * (1 - cappedResistance / 100); // Step 6c: Apply Element Relationship (Strong/Weak) let relationshipBonus = getElementRelationshipBonus( attackElement, defenderElement, attackerAffinity ); let finalDamage = damageAfterResist * relationshipBonus; return finalDamage; } function getElementRelationshipBonus(attackElement, defenderElement, affinity) { // Define strong relationships const strongAgainst = { "WATER": "FIRE", "FIRE": "EARTH", "EARTH": "WIND", "WIND": "WATER" }; const weakAgainst = { "WATER": "WIND", "FIRE": "WATER", "EARTH": "FIRE", "WIND": "EARTH" }; // Check if attacker is strong vs defender if (strongAgainst[attackElement] === defenderElement) { // Strong vs Weak: Scale bonus based on affinity // Range: 1.0x (0 affinity) to 1.25x (100 affinity) let strongBonus = 1 + (affinity / 100) * 0.25; return strongBonus; } // Check if attacker is weak vs defender if (weakAgainst[attackElement] === defenderElement) { // Weak vs Strong: Scale penalty based on affinity // Range: 1.0x (0 affinity) to 0.75x (100 affinity) minimum let weakPenalty = 1 - (affinity / 100) * 0.25; // Cannot go below 0.75x (25% max damage reduction) return Math.max(0.75, weakPenalty); } // Neutral relationship return 1.0; }

Elemental Affinity & Resistance Table

Fire Affinity vs Water (Strong) vs Water Resist 30% Final DMG (1000 base)
0 (No Affinity)1.00x700700
251.0625x788838
501.125x875984
751.1875x9631145
100 (Max)1.25x10501312

Elemental Affinity Sources (INT-Based)

Base Affinity from INT (Primary): - Affinity% = INT / 4 - Example: INT 120 = 30% base affinity - Example: INT 100 = 25% base affinity Class Capability: ✨ SPIRITUALIST: INT 14-24+ (3.5-6% base, can reach 100% with gear) → PRIMARY elemental damage user 🔧 SPECIALIST: INT 10-20 (2.5-5% base, can reach 60-70% with gear) → SECONDARY elemental user → Built-in +5-10% all element resistance (UNIQUE!) ⚔️ WARRIOR: INT 6-14 (1.5-3.5% base - NOT viable) 🏹 RANGER: INT 4-10 (1-2.5% base - NOT viable) 🔫 LAUNCHER: INT 6-12 (1.5-3% base - NOT viable) Equipment (Additional): - Element-specific gear: +5-15% Affinity - Elemental Stone: +10-25% Affinity - Ancient Relic: +20-40% Affinity - Element Ring: +10% Affinity - Element Amulet: +12-15% Affinity Skills & Passives (Per-Skill): - Element Mastery: +10-15% Affinity (when using that element) - Element Attunement: +5-10% Affinity - Temporary buffs: +15-25% Affinity (duration) Total Affinity Formula: Affinity% = (INT / 4) + Equipment + Skills + Buffs Soft Cap: 50% | Hard Cap: 100% NOTE: NO class passive bonus needed. INT bonus already reflects design.

Elemental Resistance Sources

Equipment (Primary Source): - Element Armor Set: +20% Resistance - Element Ring: +10% Resistance - Element Pendant: +12% Resistance - Element Cape: +15% Resistance Class Bonus (Specialist Only): - Specialist: +5-10% ALL element resistance (UNIQUE!) Temporary Buffs: - Elemental Shield: +20-30% specific resistance - Protection Potion: +15-25% all resistances Total Resistance Formula: Resistance% = Equipment + ClassBonus + Buffs Soft Cap: 40% | Hard Cap: 80% IMPORTANT: SEPARATE FROM MDEF - MDEF (Step 5): Reduces all magic damage (general) - Resistance (Step 6c): Reduces specific element (specialized) - Both apply multiplicatively to elemental spells

Step 7: Damage Modifiers (Buffs/Debuffs)

function applyDamageModifiers(damage, attacker, defender, context) { let modifier = 1.0; // Attacker's damage increase buffs if (attacker.buffs.damageIncrease) { modifier *= (1 + attacker.buffs.damageIncrease / 100); } // Defender's damage taken increase (debuffs) if (defender.debuffs.damageTakenIncrease) { modifier *= (1 + defender.debuffs.damageTakenIncrease / 100); } // Defender's damage reduction buffs if (defender.buffs.damageReduction) { modifier *= (1 - defender.buffs.damageReduction / 100); } // PvP damage reduction if (context.isPvP) { modifier *= 0.7; // 30% reduction in PvP } // Race-specific modifiers modifier *= getRaceModifier(attacker.race, defender.race); // Chip War modifiers if (context.isChipWar) { if (attacker.isArchon) { modifier *= 1.2; // Archon deals 20% more } if (defender.hasArchonDebuff) { modifier *= 1.1; // Takes 10% more if archon died } } return damage * modifier; } function getRaceModifier(attackerRace, defenderRace) { // Rock-paper-scissors slight advantage const advantages = { "ACCRETIA": "CORA", // Accretia > Cora "BELLATO": "ACCRETIA", // Bellato > Accretia "CORA": "BELLATO" // Cora > Bellato }; if (advantages[attackerRace] === defenderRace) { return 1.05; // 5% bonus damage } return 1.0; }

Step 8: Block Check

function checkAndApplyBlock(damage, defender, damageType) { // Only physical damage can be blocked if (damageType !== "PHYSICAL") { return { damage: damage, blocked: false }; } // Must have shield equipped if (!defender.hasShield) { return { damage: damage, blocked: false }; } let blockChance = defender.blockRate; // Apply caps blockChance = Math.min(20, blockChance); // Hard cap 20% (Shield +10 max) if (random(0, 100) < blockChance) { // Block successful let blockValue = defender.shield.blockValue; // e.g., 50% let blockedDamage = damage * (1 - blockValue / 100); return { damage: blockedDamage, blocked: true, amountBlocked: damage - blockedDamage }; } return { damage: damage, blocked: false }; }

Step 9: Final Damage Application

function applyFinalDamage(damage, defender) { // Apply minimum damage (1) damage = Math.max(1, Math.floor(damage)); // Apply damage variance (±5%) let variance = 0.95 + random(0, 0.10); damage = Math.floor(damage * variance); // Subtract from HP defender.currentHP -= damage; // Check for death if (defender.currentHP <= 0) { defender.currentHP = 0; handleDeath(defender); } return damage; }

📊 Complete Calculation Example

📖 Scenario

Level 50 Striker (Bellato) attacks Level 50 Guardian (Accretia) with Power Strike skill.

=== ATTACKER (Striker) === Level: 50 Race: Bellato Weapon: Epic Dual Blades (+7) - Min Damage: 60 - Max Damage: 90 - Enhancement: +21% (7 × 3%) - Quality: Epic (×1.4) PATK: 280 Crit Rate: 30% Crit Damage: 205% Physical PEN: 25% Skill: Power Strike - Multiplier: 150% - Flat Bonus: 50 - STR Scaling: 2.0 × 70 STR = 140 === DEFENDER (Guardian) === Level: 50 Race: Accretia PDEF: 600 Evasion: 150 Block Rate: 45% Block Value: 55% HP: 5000 === CALCULATION === Step 1: Hit Check - Evasion Chance: (150 - 350) × 0.1 + 30% = 10% - Roll: 45 → HIT (not evaded) - Crit Check: 30% chance, Roll: 20 → CRITICAL! Step 2: Base Damage - GATK Roll: 75 (between 60-90) - With Enhancement: 75 × 1.21 = 90.75 - With Quality: 90.75 × 1.4 = 127.05 - Total Base: 127.05 + 280 (PATK) = 407.05 Step 3: Skill Modifier - Skill Damage: 407.05 × 1.5 = 610.58 - Flat Bonus: +50 = 660.58 - STR Scaling: +140 = 800.58 Step 4: Critical Modifier - CDMG: 205% - Crit Damage: 800.58 × 2.05 = 1641.19 Step 5: Defense Reduction - Defender PDEF: 600 - Attacker PEN: 25% - Effective DEF: 600 × 0.75 = 450 - DR%: 450 / (450 + 350 + 500) = 34.6% - After Defense: 1641.19 × 0.654 = 1073.34 Step 6: Elemental Modifier - No element on attack - Modifier: ×1.0 - Damage: 1127.22 Step 7: Damage Modifiers - Race Advantage (Bellato vs Accretia): ×1.05 - PvP Reduction: ×0.7 - Final Modifier: 0.735 - Damage: 1073.34 × 0.735 = 788.91 Step 8: Block Check - Block Rate: 17% (Shield +7) - Roll: 60 → NOT BLOCKED Step 9: Final Damage - Variance: ×0.97 (random) - Final: 788.91 × 0.97 = 765.24 → 765 damage === RESULT === Striker deals 765 CRITICAL damage to Guardian! Guardian HP: 5000 → 4235

🔧 Complete Damage Function

function calculateDamage(attacker, defender, skill, context) { // Step 1: Hit Check let hitResult = checkHit(attacker, defender); if (hitResult === "MISS") { return { damage: 0, result: "MISS" }; } // Step 2: Base Damage let damage = calculateBaseDamage(attacker, skill.damageType); // Step 3: Skill Modifier damage = applySkillModifier(damage, skill, attacker); // Step 4: Critical Modifier damage = applyCriticalModifier(damage, attacker, hitResult); // Step 5: Defense Reduction damage = applyDefenseReduction(damage, attacker, defender, skill.damageType); // Step 6: Elemental Modifier damage = applyElementalModifier(damage, skill.element, defender); // Step 7: Damage Modifiers damage = applyDamageModifiers(damage, attacker, defender, context); // Step 8: Block Check let blockResult = checkAndApplyBlock(damage, defender, skill.damageType); damage = blockResult.damage; // Step 9: Final Damage let finalDamage = applyFinalDamage(damage, defender); return { damage: finalDamage, result: hitResult, blocked: blockResult.blocked, blockedAmount: blockResult.amountBlocked || 0 }; }

📑 Quick Reference Card

⚔️ Offensive Formulas

  • PATK = STR × 2 + Equipment
  • MATK = INT × 3 + Equipment
  • Global ATK = +% to PATK & MATK
  • Crit Rate = 3% + DEX × 0.05
  • Crit DMG = 150% base
  • Soft Cap Crit: 35%

🛡️ Defensive Formulas

  • PDEF = Armor + STA × 0.3
  • MDEF = Armor + INT × 0.4
  • Global DEF = +% to PDEF & MDEF
  • DR = DEF / (DEF + 350 + Lv×10)
  • Evasion Max: 48%
  • Block Max: 20%

📊 Constants

  • DEFENSE_CONSTANT = 350
  • PVP_REDUCTION = 30%
  • MIN_HIT_CHANCE = 5%
  • MAX_HIT_CHANCE = 95%
  • DAMAGE_VARIANCE = ±5%

🔥 Element Bonus

  • Strong vs Weak: +25%
  • Max Resist: 75%
  • Min Resist: -50%