QA representative battles and tune balance

This commit is contained in:
2026-06-27 05:56:45 +09:00
parent d10cd6319d
commit 23f734b35c
4 changed files with 723 additions and 38 deletions

View File

@@ -1407,6 +1407,7 @@ const unitStrategyIds: Record<string, string[]> = {
'jian-yong': ['aid', 'encourage', 'fireTactic'],
'mi-zhu': ['aid', 'encourage'],
'sun-qian': ['aid', 'encourage', 'fireTactic'],
'zhao-yun': ['encourage'],
'zhuge-liang': ['aid', 'encourage', 'fireTactic'],
'ma-liang': ['aid', 'encourage', 'fireTactic'],
'yi-ji': ['aid', 'encourage'],
@@ -1415,7 +1416,14 @@ const unitStrategyIds: Record<string, string[]> = {
'wei-yan': ['roar'],
'pang-tong': ['aid', 'encourage', 'fireTactic'],
'fa-zheng': ['aid', 'encourage', 'fireTactic'],
'wu-yi': ['encourage']
'wu-yi': ['encourage'],
'yan-yan': ['encourage'],
'li-yan': ['aid', 'encourage'],
'huang-quan': ['aid', 'encourage'],
'ma-chao': ['roar', 'encourage'],
'ma-dai': ['encourage'],
'wang-ping': ['aid', 'encourage'],
'jiang-wei': ['aid', 'encourage', 'fireTactic']
};
const initialItemStocks: Record<string, Record<string, number>> = {
@@ -1423,18 +1431,25 @@ const initialItemStocks: Record<string, Record<string, number>> = {
'guan-yu': { bean: 1 },
'zhang-fei': { bean: 1, wine: 1 },
'jian-yong': { bean: 1 },
'mi-zhu': { bean: 2, salve: 1 },
'mi-zhu': { bean: 3, salve: 2 },
'sun-qian': { bean: 1, salve: 1 },
'zhao-yun': { bean: 1, wine: 1 },
'zhuge-liang': { bean: 1, wine: 1 },
'ma-liang': { bean: 1, salve: 1 },
'zhao-yun': { bean: 2, salve: 1, wine: 1 },
'zhuge-liang': { bean: 2, salve: 1, wine: 1 },
'ma-liang': { bean: 2, salve: 2 },
'yi-ji': { bean: 2, salve: 1 },
'gong-zhi': { bean: 2 },
'huang-zhong': { bean: 1, wine: 1 },
'huang-zhong': { bean: 2, salve: 1, wine: 1 },
'wei-yan': { bean: 2 },
'pang-tong': { bean: 1, salve: 1, wine: 1 },
'fa-zheng': { bean: 1, salve: 1, wine: 1 },
'wu-yi': { bean: 2, wine: 1 }
'fa-zheng': { bean: 2, salve: 2, wine: 1 },
'wu-yi': { bean: 2, wine: 1 },
'yan-yan': { bean: 2 },
'li-yan': { bean: 2, salve: 2 },
'huang-quan': { bean: 2, salve: 2 },
'ma-chao': { bean: 2, salve: 1, wine: 1 },
'ma-dai': { bean: 2, salve: 1, wine: 1 },
'wang-ping': { bean: 3, salve: 1 },
'jiang-wei': { bean: 2, salve: 1, wine: 1 }
};
const attackRangeByClass: Partial<Record<UnitClassKey, number>> = {
@@ -2728,6 +2743,49 @@ function cloneBattleBond(bond: BattleBond): BattleBond {
};
}
function scenarioReadinessAnchor() {
return (
initialBattleUnits.find((unit) => unit.id === leaderUnitId && unit.faction === 'enemy') ??
initialBattleUnits
.filter((unit) => unit.faction === 'enemy')
.sort((a, b) => b.level - a.level || b.maxHp - a.maxHp || b.attack - a.attack)[0]
);
}
function applyScenarioAllyReadiness(unit: UnitData) {
if (unit.faction !== 'ally') {
return unit;
}
const anchor = scenarioReadinessAnchor();
if (!anchor) {
return unit;
}
const enemyCount = initialBattleUnits.filter((candidate) => candidate.faction === 'enemy').length;
const densityFactor = 1 + Math.max(0, enemyCount - 18) * 0.035;
const attackDensityFactor = 1 + Math.max(0, enemyCount - 18) * 0.018;
const hpRatio = unit.maxHp > 0 ? unit.hp / unit.maxHp : 1;
const minimumLevel = Math.max(unit.level, Math.min(99, Math.round(anchor.level * 0.72)));
const minimumMaxHp = Math.max(unit.maxHp, Math.round(anchor.maxHp * 1.15 * densityFactor));
const minimumAttack = Math.max(unit.attack, Math.round(anchor.attack * 0.72 * attackDensityFactor));
const equipmentLevelFloor = Math.max(1, Math.min(9, Math.floor(anchor.level / 28) + 1));
const next = cloneUnitData(unit);
next.level = minimumLevel;
next.maxHp = minimumMaxHp;
next.hp = minimumMaxHp > unit.maxHp ? Math.max(unit.hp, Math.ceil(minimumMaxHp * hpRatio)) : Math.min(unit.hp, minimumMaxHp);
next.attack = minimumAttack;
(Object.keys(next.stats) as Array<keyof UnitStats>).forEach((key) => {
next.stats[key] = Math.max(next.stats[key], Math.round(anchor.stats[key] * 0.78));
});
equipmentSlots.forEach((slot) => {
next.equipment[slot].level = Math.max(next.equipment[slot].level, equipmentLevelFloor);
});
return next;
}
function configureBattleScenario(scenario: BattleScenarioDefinition) {
battleScenario = scenario;
battleMap = scenario.map;
@@ -2939,7 +2997,7 @@ export class BattleScene extends Phaser.Scene {
const hasSelection = selected.size > 0;
const nextUnits = initialBattleUnits
.filter((unit) => unit.faction === 'enemy' || !hasSelection || selected.has(unit.id) || forcedAllyIds.has(unit.id))
.map((unit) => this.applyCampaignUnitProgress(unit, campaign));
.map((unit) => applyScenarioAllyReadiness(this.applyCampaignUnitProgress(unit, campaign)));
battleUnits.splice(0, battleUnits.length, ...nextUnits);
battleBonds.splice(0, battleBonds.length, ...initialBattleBonds.map((bond) => this.applyCampaignBondProgress(bond, campaign)));
initialBattleUnits = battleUnits.map(cloneUnitData);
@@ -5546,7 +5604,9 @@ export class BattleScene extends Phaser.Scene {
: getItem(user.equipment.accessory.itemId).id === 'peach-charm'
? 2
: 0;
return Math.min(target.maxHp - target.hp, Math.max(1, usable.power + bonus + equipmentBonus));
const flatAmount = usable.power + bonus + equipmentBonus;
const percentFloor = Math.ceil(target.maxHp * (usable.command === 'item' ? 0.24 : 0.18));
return Math.min(target.maxHp - target.hp, Math.max(1, flatAmount, percentFloor));
}
private combatEquipmentEffect(