step 10.18: wip (not ticked)

This commit is contained in:
bepis
2026-10-23 12:15:43 +11:00
parent b7ed4f9bbc
commit 394a055d2a
2 changed files with 61 additions and 27 deletions
+45 -11
View File
@@ -18,19 +18,19 @@ var SEED = 42;
// ─── Zone / monster definitions (MUST match 008_balance.sql) ────────────────
var ZONES = {
meadows: { slug: 'whispering-meadows', minLevel: 1, energyCost: 5, monsters: [
{ name: 'Giant Rat', level: 1, hp: 250, attack: 8, defense: 8, speed: 12, xp: 70, goldMin: 3, goldMax: 7 },
{ name: 'Meadow Wolf', level: 2, hp: 350, attack: 12, defense: 8, speed: 16, xp: 110, goldMin: 5, goldMax: 12 },
{ name: 'Goblin Scrapper', level: 3, hp: 300, attack: 18, defense: 8, speed: 11, xp: 180, goldMin: 8, goldMax: 18 },
{ name: 'Giant Rat', level: 1, hp: 50, attack: 16, defense: 8, speed: 12, xp: 25, goldMin: 3, goldMax: 7 },
{ name: 'Meadow Wolf', level: 2, hp: 60, attack: 18, defense: 8, speed: 16, xp: 35, goldMin: 5, goldMax: 12 },
{ name: 'Goblin Scrapper', level: 3, hp: 70, attack: 20, defense: 8, speed: 11, xp: 50, goldMin: 8, goldMax: 18 },
]},
forest: { slug: 'gloomroot-forest', minLevel: 5, energyCost: 8, monsters: [
{ name: 'Webspinner', level: 5, hp: 200, attack: 25, defense: 20, speed: 15, xp: 80, goldMin: 12, goldMax: 24 },
{ name: 'Bandit Cutthroat', level: 6, hp: 250, attack: 30, defense: 20, speed: 14, xp: 110, goldMin: 18, goldMax: 36 },
{ name: 'Mossback Treant', level: 8, hp: 350, attack: 35, defense: 30, speed: 7, xp: 160, goldMin: 22, goldMax: 44 },
{ name: 'Webspinner', level: 5, hp: 100, attack: 24, defense: 16, speed: 15, xp: 80, goldMin: 12, goldMax: 24 },
{ name: 'Bandit Cutthroat', level: 6, hp: 130, attack: 28, defense: 20, speed: 14, xp: 100, goldMin: 18, goldMax: 36 },
{ name: 'Mossback Treant', level: 8, hp: 180, attack: 30, defense: 22, speed: 7, xp: 150, goldMin: 22, goldMax: 44 },
]},
crags: { slug: 'ashfang-crag', minLevel: 10, energyCost: 12, monsters: [
{ name: 'Ember Imp', level: 10, hp: 200, attack: 30, defense: 20, speed: 20, xp: 300, goldMin: 30, goldMax: 55 },
{ name: 'Stone Golem', level: 12, hp: 600, attack: 40, defense: 30, speed: 5, xp: 420, goldMin: 40, goldMax: 75 },
{ name: 'Ashfang Drake', level: 14, hp: 450, attack: 45, defense: 25, speed: 18, xp: 600, goldMin: 55, goldMax: 110 },
{ name: 'Ember Imp', level: 10, hp: 150, attack: 30, defense: 18, speed: 20, xp: 200, goldMin: 30, goldMax: 55 },
{ name: 'Stone Golem', level: 12, hp: 300, attack: 38, defense: 28, speed: 5, xp: 280, goldMin: 40, goldMax: 75 },
{ name: 'Ashfang Drake', level: 14, hp: 150, attack: 38, defense: 22, speed: 18, xp: 350, goldMin: 55, goldMax: 110 },
]},
};
@@ -51,9 +51,21 @@ function pickMonster(zoneKey, rng) {
}
function simulateHunt(hero, monster, rng) {
// Build equip bonuses for resolveCombat (it passes hero as equipBonuses to calcDerived)
var eq = {
bonus_str: 0, bonus_agi: 0, bonus_int: 0, bonus_vit: 0,
bonus_attack: 0, bonus_defense: 0,
};
// Apply starter weapon bonuses based on class
if (hero.class === 'mage') { eq.bonus_int = 1; eq.bonus_attack = 2; }
else if (hero.class === 'ranger') { eq.bonus_agi = 2; eq.bonus_attack = 1; }
else if (hero.class === 'warrior') { eq.bonus_attack = 3; }
var fight = resolveCombat({
class: hero.class, level: hero.level, hpCurrent: hero.hp,
str: hero.str, agi: hero.agi, int: hero.int, vit: hero.vit,
bonus_str: eq.bonus_str, bonus_agi: eq.bonus_agi, bonus_int: eq.bonus_int, bonus_vit: eq.bonus_vit,
bonus_attack: eq.bonus_attack, bonus_defense: eq.bonus_defense,
}, monster, rng);
var xpGained = 0, goldGained = 0;
@@ -79,6 +91,15 @@ function simulateClass(className) {
gold: 50,
};
// Apply starter weapon bonuses (same as createCharacter)
if (className === 'warrior') {
hero.str += 0; hero.agi += 0; hero.int += 0; hero.vit += 0; // Rusty Sword: +3 atk only
} else if (className === 'mage') {
hero.int += 1; // Apprentice Staff: +1 int, +2 atk
} else if (className === 'ranger') {
hero.agi += 2; // Hunter's Shortbow: +2 agi, +1 atk
}
var derived = calcDerived({ str: hero.str, agi: hero.agi, int: hero.int, vit: hero.vit }, hero.level, className);
hero.hp = derived.maxHp;
hero.maxHp = derived.maxHp;
@@ -188,12 +209,18 @@ function simulateLevel1WinRate(zoneKey) {
var className = CLASS_KEYS[ci];
var cls = getClass(className);
var base = getBaseStats(className);
var derived = calcDerived({ str: base.str, agi: base.agi, int: base.int, vit: base.vit }, 1, className);
// Apply starter weapon bonuses (same as createCharacter)
var stats = { str: base.str, agi: base.agi, int: base.int, vit: base.vit };
if (className === 'mage') stats.int += 1; // +1 int, +2 atk
else if (className === 'ranger') stats.agi += 2; // +2 agi, +1 atk
var derived = calcDerived(stats, 1, className);
var monster = pickMonster(zoneKey, classRng);
var result = simulateHunt({
class: className, level: 1, hp: derived.maxHp, maxHp: derived.maxHp,
str: base.str, agi: base.agi, int: base.int, vit: base.vit,
str: stats.str, agi: stats.agi, int: stats.int, vit: stats.vit,
}, monster, classRng);
if (result.winner === 'hero') wins++;
@@ -217,7 +244,14 @@ function simulateLevel5ForestWinRate() {
var base = getBaseStats(className);
var primary = cls.primary;
var stats = { str: base.str, agi: base.agi, int: base.int, vit: base.vit };
// Apply starter weapon bonuses
if (className === 'mage') stats.int += 1;
else if (className === 'ranger') stats.agi += 2;
// Auto-allocate 15 points to primary stat (5 levels × 3 points)
stats[primary] += 15;
var derived = calcDerived(stats, 5, className);
var monster = pickMonster('forest', rng);