Benchmark v2 with real Lv90 stats, Shadow Veil removed, full-conservative defaults

Shadow Veil removed from BUFF_PRIORITY - was draining MP aggressively.
Player stats updated to match real character (effective values with gear).

Benchmark results (Lv90, Nightmare, 5 runs each):
1. full-conservative: 146 rounds, 4485 dmg/rd — WINNER
2. conservative-items: 143 rounds, 4468 dmg/rd
3. spirit-40: 136 rounds, 4457 dmg/rd

New defaults (full-conservative):
- cureHP: 0.45, cureItemHP: 0.50 (save items use cure)
- manaGemMP: 0.45, manaPotionMP: 0.25
- spiritPotionSP: 0.30, spiritStanceOC: 80
- skillOC: 75
This commit is contained in:
GaboGG 2026-07-21 14:00:44 -04:00
parent 4bc90d9332
commit 0ee31b7266
8 changed files with 172 additions and 153 deletions

View file

@ -30,14 +30,14 @@ const CFG = {
autoSpirit: false, autoSpirit: false,
// — Thresholds // — Thresholds
cureHP: 0.35, // Cast Cure below this HP cureHP: 0.45, // Cast Cure below this HP (save items, use Cure)
cureItemHP: 0.65, // Use health items at this HP cureItemHP: 0.50, // Use health items at this HP (conservative, let Cure carry)
cureRegenHP: 0.75, // Cast Regen below this HP cureRegenHP: 0.65, // Cast Regen below this HP
manaGemMP: 0.60, // Use mana gems below this MP (proactive) manaGemMP: 0.45, // Use mana gems below this MP (conservative)
manaPotionMP: 0.30, // Use mana potions at critical manaPotionMP: 0.25, // Use mana potions at critical
spiritPotionSP: 0.45, // Use spirit gems/potions below this SP spiritPotionSP: 0.30, // Use spirit gems/potions below this SP
spiritStanceOC: 60, // Activate Spirit Stance at this OC spiritStanceOC: 80, // Activate Spirit Stance late (save SP for skills)
skillOC: 70, // Use weapon skills at this OC (balance between spirit and damage) skillOC: 75, // Use weapon skills at this OC
// — Out of battle // — Out of battle
autoSell: true, autoSell: true,
@ -679,9 +679,10 @@ const BUFF_PRIORITY = [
{ icon: 'haste', spell: 'Haste', minTurns: 2 }, { icon: 'haste', spell: 'Haste', minTurns: 2 },
{ icon: 'protection', spell: 'Protection', minTurns: 2 }, { icon: 'protection', spell: 'Protection', minTurns: 2 },
{ icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 }, { icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 },
{ icon: 'shadow_veil', spell: 'Shadow Veil', minTurns: 2 },
{ icon: 'regen', spell: 'Regen', minTurns: 2 }, { icon: 'regen', spell: 'Regen', minTurns: 2 },
{ icon: 'absorb', spell: 'Absorb', minTurns: 2 }, { icon: 'absorb', spell: 'Absorb', minTurns: 2 },
// Shadow Veil excluded from auto-buff rotation — expensive and drains MP
// from Cure. Cast manually when MP is plentiful.
]; ];
// Known important monster names (bosses, legendaries, ultimates) // Known important monster names (bosses, legendaries, ultimates)

View file

@ -30,14 +30,14 @@ const CFG = {
autoSpirit: false, autoSpirit: false,
// — Thresholds // — Thresholds
cureHP: 0.35, // Cast Cure below this HP cureHP: 0.45, // Cast Cure below this HP (save items, use Cure)
cureItemHP: 0.65, // Use health items at this HP cureItemHP: 0.50, // Use health items at this HP (conservative, let Cure carry)
cureRegenHP: 0.75, // Cast Regen below this HP cureRegenHP: 0.65, // Cast Regen below this HP
manaGemMP: 0.60, // Use mana gems below this MP (proactive) manaGemMP: 0.45, // Use mana gems below this MP (conservative)
manaPotionMP: 0.30, // Use mana potions at critical manaPotionMP: 0.25, // Use mana potions at critical
spiritPotionSP: 0.45, // Use spirit gems/potions below this SP spiritPotionSP: 0.30, // Use spirit gems/potions below this SP
spiritStanceOC: 60, // Activate Spirit Stance at this OC spiritStanceOC: 80, // Activate Spirit Stance late (save SP for skills)
skillOC: 70, // Use weapon skills at this OC (balance between spirit and damage) skillOC: 75, // Use weapon skills at this OC
// — Out of battle // — Out of battle
autoSell: true, autoSell: true,
@ -679,9 +679,10 @@ const BUFF_PRIORITY = [
{ icon: 'haste', spell: 'Haste', minTurns: 2 }, { icon: 'haste', spell: 'Haste', minTurns: 2 },
{ icon: 'protection', spell: 'Protection', minTurns: 2 }, { icon: 'protection', spell: 'Protection', minTurns: 2 },
{ icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 }, { icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 },
{ icon: 'shadow_veil', spell: 'Shadow Veil', minTurns: 2 },
{ icon: 'regen', spell: 'Regen', minTurns: 2 }, { icon: 'regen', spell: 'Regen', minTurns: 2 },
{ icon: 'absorb', spell: 'Absorb', minTurns: 2 }, { icon: 'absorb', spell: 'Absorb', minTurns: 2 },
// Shadow Veil excluded from auto-buff rotation — expensive and drains MP
// from Cure. Cast manually when MP is plentiful.
]; ];
// Known important monster names (bosses, legendaries, ultimates) // Known important monster names (bosses, legendaries, ultimates)

View file

@ -1,18 +1,25 @@
{ {
"player": { "player": {
"level": 64, "level": 90,
"style": "2H", "style": "2H",
"str": 95, "str": 155,
"dex": 40, "dex": 96,
"agi": 28, "agi": 36,
"end": 265, "end": 77,
"int": 8, "int": 32,
"wis": 35, "wis": 75,
"maxHp": 2672,
"maxMp": 232,
"maxSp": 122,
"difficulty": "Nightmare", "difficulty": "Nightmare",
"prof2h": 80, "prof2h": 107,
"profLight": 70, "profLight": 107,
"profSupportive": 68, "profSupportive": 107,
"profElemental": 50 "profElemental": 63,
"physMit": 31.5,
"magMit": 29.9,
"critDmg": 1.8,
"accuracy": 92.5
}, },
"runs": 5, "runs": 5,
"rounds": 1000, "rounds": 1000,
@ -20,143 +27,143 @@
{ {
"name": "full-conservative", "name": "full-conservative",
"desc": "Late spirit, save items, no attack spells", "desc": "Late spirit, save items, no attack spells",
"avgRounds": "225.6", "avgRounds": "146.0",
"avgKills": "1335.0", "avgKills": "809.2",
"avgDmgRatio": "3.1", "avgDmgRatio": "3.2",
"avgDmgPerRound": 3141, "avgDmgPerRound": 4485,
"avgExp": 10276480, "avgExp": 4388800,
"avgCredits": 132114, "avgCredits": 57381,
"maxRounds": 249, "maxRounds": 166,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 133500 "score": 80920
}, },
{ {
"name": "conservative-items", "name": "conservative-items",
"desc": "Save items, use Cure more", "desc": "Save items, use Cure more",
"avgRounds": "223.6", "avgRounds": "142.8",
"avgKills": "1330.8", "avgKills": "793.8",
"avgDmgRatio": "3.1", "avgDmgRatio": "3.1",
"avgDmgPerRound": 3128, "avgDmgPerRound": 4468,
"avgExp": 10058080, "avgExp": 4131520,
"avgCredits": 129729, "avgCredits": 53230,
"maxRounds": 232, "maxRounds": 154,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 133080 "score": 79380
},
{
"name": "attack-spells",
"desc": "Use cheap attack spells for channeling",
"avgRounds": "213.0",
"avgKills": "1248.2",
"avgDmgRatio": "3.4",
"avgDmgPerRound": 2974,
"avgExp": 9150160,
"avgCredits": 118907,
"maxRounds": 238,
"survivalRate": "0",
"deaths": 5,
"score": 124820
},
{
"name": "spirit-80",
"desc": "Spirit Stance at OC 80 (late, skills first)",
"avgRounds": "208.8",
"avgKills": "1218.0",
"avgDmgRatio": "3.4",
"avgDmgPerRound": 3024,
"avgExp": 8762480,
"avgCredits": 111455,
"maxRounds": 212,
"survivalRate": "0",
"deaths": 5,
"score": 121800
}, },
{ {
"name": "spirit-40", "name": "spirit-40",
"desc": "Spirit Stance at OC 40 (early)", "desc": "Spirit Stance at OC 40 (early)",
"avgRounds": "205.4", "avgRounds": "135.8",
"avgKills": "1201.4", "avgKills": "751.2",
"avgDmgRatio": "3.6", "avgDmgRatio": "3.4",
"avgDmgPerRound": 2990, "avgDmgPerRound": 4457,
"avgExp": 8509680, "avgExp": 3770560,
"avgCredits": 110122, "avgCredits": 47867,
"maxRounds": 223, "maxRounds": 152,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 120140 "score": 75120
},
{
"name": "spirit-80",
"desc": "Spirit Stance at OC 80 (late, skills first)",
"avgRounds": "128.8",
"avgKills": "703.6",
"avgDmgRatio": "3.6",
"avgDmgPerRound": 4398,
"avgExp": 3358160,
"avgCredits": 45813,
"maxRounds": 139,
"survivalRate": "0",
"deaths": 5,
"score": 70360
}, },
{ {
"name": "skills-at-60", "name": "skills-at-60",
"desc": "Skills fire at OC 60 instead of 80", "desc": "Skills fire at OC 60 instead of 80",
"avgRounds": "204.4", "avgRounds": "126.4",
"avgKills": "1185.8", "avgKills": "689.6",
"avgDmgRatio": "3.7", "avgDmgRatio": "3.6",
"avgDmgPerRound": 3006, "avgDmgPerRound": 4356,
"avgExp": 8400560, "avgExp": 3243600,
"avgCredits": 109924, "avgCredits": 42872,
"maxRounds": 213, "maxRounds": 143,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 118580 "score": 68960
}, },
{ {
"name": "baseline", "name": "baseline",
"desc": "Current v0.11.0 defaults", "desc": "Current v0.11.0 defaults",
"avgRounds": "203.8", "avgRounds": "126.4",
"avgKills": "1181.8", "avgKills": "688.8",
"avgDmgRatio": "3.7", "avgDmgRatio": "3.8",
"avgDmgPerRound": 3011, "avgDmgPerRound": 4340,
"avgExp": 8350320, "avgExp": 3272880,
"avgCredits": 113818, "avgCredits": 41772,
"maxRounds": 210, "maxRounds": 154,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 118180 "score": 68880
},
{
"name": "balanced",
"desc": "Mid spirit, moderate items, attack spells for chan",
"avgRounds": "200.2",
"avgKills": "1165.2",
"avgDmgRatio": "3.5",
"avgDmgPerRound": 2962,
"avgExp": 8100480,
"avgCredits": 107866,
"maxRounds": 217,
"survivalRate": "0",
"deaths": 5,
"score": 116520
}, },
{ {
"name": "full-aggressive", "name": "full-aggressive",
"desc": "Early spirit + aggressive items + attack spells", "desc": "Early spirit + aggressive items + attack spells",
"avgRounds": "194.2", "avgRounds": "126.0",
"avgKills": "1126.6", "avgKills": "688.8",
"avgDmgRatio": "3.7", "avgDmgRatio": "3.5",
"avgDmgPerRound": 2925, "avgDmgPerRound": 4162,
"avgExp": 7643120, "avgExp": 3215200,
"avgCredits": 99980, "avgCredits": 41874,
"maxRounds": 210, "maxRounds": 141,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 112660 "score": 68880
},
{
"name": "balanced",
"desc": "Mid spirit, moderate items, attack spells for chan",
"avgRounds": "125.8",
"avgKills": "686.4",
"avgDmgRatio": "3.6",
"avgDmgPerRound": 4124,
"avgExp": 3198880,
"avgCredits": 42626,
"maxRounds": 138,
"survivalRate": "0",
"deaths": 5,
"score": 68640
}, },
{ {
"name": "aggressive-items", "name": "aggressive-items",
"desc": "Use items very proactively", "desc": "Use items very proactively",
"avgRounds": "180.2", "avgRounds": "117.0",
"avgKills": "1027.4", "avgKills": "631.4",
"avgDmgRatio": "4.1", "avgDmgRatio": "4.0",
"avgDmgPerRound": 2963, "avgDmgPerRound": 4390,
"avgExp": 6639040, "avgExp": 2781760,
"avgCredits": 82094, "avgCredits": 36607,
"maxRounds": 208, "maxRounds": 129,
"survivalRate": "0", "survivalRate": "0",
"deaths": 5, "deaths": 5,
"score": 102740 "score": 63140
},
{
"name": "attack-spells",
"desc": "Use cheap attack spells for channeling",
"avgRounds": "113.4",
"avgKills": "607.8",
"avgDmgRatio": "3.9",
"avgDmgPerRound": 4036,
"avgExp": 2602480,
"avgCredits": 36235,
"maxRounds": 122,
"survivalRate": "0",
"deaths": 5,
"score": 60780
} }
], ],
"timestamp": "2026-07-20T23:52:13.366Z" "timestamp": "2026-07-21T18:00:29.218Z"
} }

View file

@ -6,16 +6,26 @@ const { simulateGrindfest } = require('./grindfest');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
// Player config matching current character (Lv65-ish 2H) // Player config matching your Lv90 character (effective stats from gear)
const PLAYER = { const PLAYER = {
level: 64, level: 90,
style: '2H', style: '2H',
str: 95, dex: 40, agi: 28, end: 265, int: 8, wis: 35, // Effective stats (from character page: attributes + equipment bonuses)
str: 155, dex: 96, agi: 36, end: 77, int: 32, wis: 75,
// Effective HP/MP/SP from character page
maxHp: 2672,
maxMp: 232,
maxSp: 122,
difficulty: 'Nightmare', difficulty: 'Nightmare',
prof2h: 80, prof2h: 107,
profLight: 70, profLight: 107,
profSupportive: 68, profSupportive: 107,
profElemental: 50, profElemental: 63,
// Derived from gear
physMit: 31.5,
magMit: 29.9,
critDmg: 1.80,
accuracy: 92.5,
}; };
// Strategy configs to test // Strategy configs to test

View file

@ -17,10 +17,10 @@ class SimPlayer {
this.int = config.int || 6; this.int = config.int || 6;
this.wis = config.wis || 31; // ~93 MP from gear this.wis = config.wis || 31; // ~93 MP from gear
// Derived stats // Derived stats (use effective values from config if provided)
this.maxHp = F.calcMaxHp(this.end, this.level); this.maxHp = config.maxHp || F.calcMaxHp(this.end, this.level);
this.maxMp = F.calcMaxMp(this.wis, this.level); this.maxMp = config.maxMp || F.calcMaxMp(this.wis, this.level);
this.maxSp = F.calcMaxSp(this.int, this.level); this.maxSp = config.maxSp || F.calcMaxSp(this.int, this.level);
this.hp = this.maxHp; this.hp = this.maxHp;
this.mp = this.maxMp; this.mp = this.maxMp;
this.sp = this.maxSp; this.sp = this.maxSp;
@ -35,13 +35,13 @@ class SimPlayer {
this.profElemental = config.profElemental || 42; this.profElemental = config.profElemental || 42;
// Damage stats // Damage stats
this.baseAtk = F.calcBasePhysDamage(this.str, this.dex, this.level, this.prof2h); this.baseAtk = config.baseAtk || F.calcBasePhysDamage(this.str, this.dex, this.level, this.prof2h);
this.critChance = F.calcCritChance(this.str, this.dex); this.critChance = config.critChance || F.calcCritChance(this.str, this.dex);
this.critDamage = F.calcCritDamage(68); // +68% from gear this.critDamage = config.critDmg || F.calcCritDamage(68); // +68% from gear
// Mitigation // Mitigation
this.physMit = 30; // ~30% from light armor this.physMit = (config.physMit / 100) || 0.315;
this.magMit = 23; this.magMit = (config.magMit / 100) || 0.299;
// Buffs // Buffs
this.buffs = {}; // { name: {turns: N} } this.buffs = {}; // { name: {turns: N} }

View file

@ -12,7 +12,6 @@ const BUFF_PRIORITY = [
{ icon: 'haste', spell: 'Haste', minTurns: 2 }, { icon: 'haste', spell: 'Haste', minTurns: 2 },
{ icon: 'protection', spell: 'Protection', minTurns: 2 }, { icon: 'protection', spell: 'Protection', minTurns: 2 },
{ icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 }, { icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 },
{ icon: 'shadow_veil', spell: 'Shadow Veil', minTurns: 2 },
{ icon: 'regen', spell: 'Regen', minTurns: 2 }, { icon: 'regen', spell: 'Regen', minTurns: 2 },
{ icon: 'absorb', spell: 'Absorb', minTurns: 2 }, { icon: 'absorb', spell: 'Absorb', minTurns: 2 },
]; ];

View file

@ -15,14 +15,14 @@ const CFG = {
autoSpirit: false, autoSpirit: false,
// — Thresholds // — Thresholds
cureHP: 0.35, // Cast Cure below this HP cureHP: 0.45, // Cast Cure below this HP (save items, use Cure)
cureItemHP: 0.65, // Use health items at this HP cureItemHP: 0.50, // Use health items at this HP (conservative, let Cure carry)
cureRegenHP: 0.75, // Cast Regen below this HP cureRegenHP: 0.65, // Cast Regen below this HP
manaGemMP: 0.60, // Use mana gems below this MP (proactive) manaGemMP: 0.45, // Use mana gems below this MP (conservative)
manaPotionMP: 0.30, // Use mana potions at critical manaPotionMP: 0.25, // Use mana potions at critical
spiritPotionSP: 0.45, // Use spirit gems/potions below this SP spiritPotionSP: 0.30, // Use spirit gems/potions below this SP
spiritStanceOC: 60, // Activate Spirit Stance at this OC spiritStanceOC: 80, // Activate Spirit Stance late (save SP for skills)
skillOC: 70, // Use weapon skills at this OC (balance between spirit and damage) skillOC: 75, // Use weapon skills at this OC
// — Out of battle // — Out of battle
autoSell: true, autoSell: true,

View file

@ -35,9 +35,10 @@ const BUFF_PRIORITY = [
{ icon: 'haste', spell: 'Haste', minTurns: 2 }, { icon: 'haste', spell: 'Haste', minTurns: 2 },
{ icon: 'protection', spell: 'Protection', minTurns: 2 }, { icon: 'protection', spell: 'Protection', minTurns: 2 },
{ icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 }, { icon: 'spark_of_life', spell: 'Spark of Life', minTurns: 1 },
{ icon: 'shadow_veil', spell: 'Shadow Veil', minTurns: 2 },
{ icon: 'regen', spell: 'Regen', minTurns: 2 }, { icon: 'regen', spell: 'Regen', minTurns: 2 },
{ icon: 'absorb', spell: 'Absorb', minTurns: 2 }, { icon: 'absorb', spell: 'Absorb', minTurns: 2 },
// Shadow Veil excluded from auto-buff rotation — expensive and drains MP
// from Cure. Cast manually when MP is plentiful.
]; ];
// Known important monster names (bosses, legendaries, ultimates) // Known important monster names (bosses, legendaries, ultimates)