step 10.2: done

This commit is contained in:
bepis
2026-10-22 22:22:44 +11:00
parent 120cf88015
commit 37e2219d32
6 changed files with 216 additions and 27 deletions
+19 -1
View File
@@ -93,4 +93,22 @@ function allocatePoints(currentStr, currentAgi, currentInt, currentVit, points,
};
}
module.exports = { xpToNext, checkLevelUp, allocatePoints };
/**
* Apply XP gain to a character: add XP, check for level-up, accumulate stat points.
* Shared function used by BOTH huntService and expeditionService.
* @param {number} currentLevel
* @param {number} currentXp
* @param {number} currentUnspentPoints
* @param {number} xpGained
* @returns {object} { xp, level, unspentPoints }
*/
function applyXpGain(currentLevel, currentXp, currentUnspentPoints, xpGained) {
const lv = checkLevelUp(currentLevel, currentXp, xpGained);
return {
xp: lv.totalXp,
level: lv.newLevel,
unspentPoints: currentUnspentPoints + lv.unspentPoints,
};
}
module.exports = { xpToNext, checkLevelUp, allocatePoints, applyXpGain };
+5 -1
View File
@@ -3,6 +3,7 @@
const { getDb } = require('../db');
const { AppError } = require('../utils/errors');
const { computeEnergy } = require('../game/energy');
const { applyXpGain } = require('../game/leveling');
const { now, setNow } = require('../utils/time');
// Prepared statements cached per DB handle (WeakMap).
@@ -241,6 +242,9 @@ function claimExpedition(characterId, expeditionId) {
const goldGained = def.gold_min + Math.floor(Math.random() * (def.gold_max - def.gold_min + 1));
const newGold = ch.gold + goldGained;
// Apply XP gain (adds to current, handles level-up, accumulates stat points).
const xpResult = applyXpGain(ch.level, ch.xp, ch.unspent_points, xpGained);
// Execute inside a transaction: claim + grant rewards.
const doClaim = db.transaction((eat, eid, ng, cid, xp, lvl, pts) => {
s.claimExpedition.run(eat, eid);
@@ -248,7 +252,7 @@ function claimExpedition(characterId, expeditionId) {
s.updateCharacterXp.run(xp, lvl, pts, cid);
});
doClaim(nowMs, expeditionId, newGold, characterId, xpGained, ch.level, ch.unspent_points);
doClaim(nowMs, expeditionId, newGold, characterId, xpResult.xp, xpResult.level, xpResult.unspentPoints);
return {
xpGained,
+7 -7
View File
@@ -9,7 +9,7 @@ const { computeEnergy } = require('../game/energy');
const { calcDerived } = require('../game/stats');
const { resolveCombat } = require('../game/combat');
const { calculateRewards, rollLoot } = require('../game/rewards');
const { checkLevelUp } = require('../game/leveling');
const { checkLevelUp, applyXpGain } = require('../game/leveling');
const MIN_HP_PCT_TO_HUNT = 0.2;
const DEFEAT_GOLD_LOSS_PCT = 0.10;
@@ -133,13 +133,13 @@ function hunt(characterId, zoneId, opts = {}) {
loot.push({ slug: item.slug, name: item.name, type: item.type, rarity: item.rarity, quantity: drop.quantity });
}
// `xp` is progress WITHIN the current level; checkLevelUp returns the leftover.
const lv = checkLevelUp(ch.level, ch.xp, xpGained);
xp = lv.totalXp;
if (lv.leveledUp) {
// `xp` is progress WITHIN the current level; applyXpGain handles leftover, level-up, and stat points.
const xpResult = applyXpGain(ch.level, ch.xp, ch.unspent_points, xpGained);
xp = xpResult.xp;
if (xpResult.level > ch.level) {
leveledUp = true;
level = lv.newLevel;
unspent += lv.unspentPoints;
level = xpResult.level;
unspent += xpResult.unspentPoints - ch.unspent_points;
hp = calcDerived(baseStats, level, ch.class).maxHp; // full heal at the NEW max HP
}
} else {