QA representative battles and tune balance
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user