diff --git a/scripts/qa-representative-battles.mjs b/scripts/qa-representative-battles.mjs index 912d970..d4c90f2 100644 --- a/scripts/qa-representative-battles.mjs +++ b/scripts/qa-representative-battles.mjs @@ -109,7 +109,7 @@ const earlyCampaignBattles = [ no: 6, id: 'sixth-battle-jieqiao-relief', selected: coreBrothers, - targets: ['jieqiao-guard-a', 'jieqiao-guard-b', 'jieqiao-archer-c', 'jieqiao-leader-qu-yi'], + targets: ['jieqiao-leader-qu-yi'], protected: ['liu-bei'] }, { @@ -1210,6 +1210,13 @@ async function playBattleWithoutDebugVictory(page, battle) { function canTakeAttack(unit, attack, threat = protectedIds.has(unit.id) ? incomingThreat(unit, unit) : 0) { if (!protectedIds.has(unit.id)) { + const kill = attack.preview.damage >= attack.target.hp; + if (unit.hp <= Math.ceil(unit.maxHp * 0.35)) { + return kill && threat <= Math.floor(unit.hp * 0.4); + } + if (unit.hp <= Math.ceil(unit.maxHp * 0.55)) { + return kill || threat <= Math.floor(unit.hp * 0.5); + } return true; } const pressProtected = shouldPressProtected(unit); @@ -1253,14 +1260,13 @@ async function playBattleWithoutDebugVictory(page, battle) { .map((tile) => withUnitAt(unit, tile, () => { const attack = attackChoice(unit); - return attack ? { tile, attack, threat: protectedIds.has(unit.id) ? incomingThreat(unit, tile) : 0 } : undefined; + const needsThreatCheck = protectedIds.has(unit.id) || unit.hp <= Math.ceil(unit.maxHp * 0.55); + return attack ? { tile, attack, threat: needsThreatCheck ? incomingThreat(unit, tile) : 0 } : undefined; }) ) .filter(Boolean); - const preferredAttackingTiles = protectedIds.has(unit.id) - ? attackingTiles.filter((entry) => canTakeAttack(unit, entry.attack, entry.threat)) - : attackingTiles; + const preferredAttackingTiles = attackingTiles.filter((entry) => canTakeAttack(unit, entry.attack, entry.threat)); if (preferredAttackingTiles.length > 0 && (!protectedIds.has(unit.id) || unit.hp >= Math.ceil(unit.maxHp * 0.45))) { return preferredAttackingTiles.sort((a, b) => { diff --git a/src/game/data/battles.ts b/src/game/data/battles.ts index 45e01ad..575cb0a 100644 --- a/src/game/data/battles.ts +++ b/src/game/data/battles.ts @@ -869,7 +869,7 @@ export const fifthBattleScenario: BattleScenarioDefinition = { openingObjectiveLines: [ '반동탁 연합으로 향하는 길목을 동탁군 장수 호진이 막고 있습니다. 호진을 격파하면 사수관 앞 전초 진지가 흔들립니다.', '중앙 길은 빠르지만 궁병과 기병의 반격을 받기 쉽습니다. 숲길 척후를 처리하고 요새 주변을 차근히 압박하십시오.', - '14턴 이내에 승리하면 공손찬 진영에서 세 형제의 무공이 더 크게 알려집니다.' + '16턴 이내에 승리하면 공손찬 진영에서 세 형제의 무공이 더 크게 알려집니다.' ], tacticalGuide: { summary: '반동탁 연합으로 향하는 길목에서 호진의 전초 진지를 무너뜨리는 전투입니다.', @@ -922,7 +922,7 @@ export const fifthBattleScenario: BattleScenarioDefinition = { bonds: fifthBattleBonds, mapTextureKey: 'battle-map-fifth', leaderUnitId: 'sishui-leader-hu-zhen', - quickVictoryTurnLimit: 14, + quickVictoryTurnLimit: 16, baseVictoryGold: 760, objectives: [ { @@ -951,9 +951,9 @@ export const fifthBattleScenario: BattleScenarioDefinition = { { id: 'quick', kind: 'quick-victory', - label: '14턴 이내 승리', + label: '16턴 이내 승리', rewardGold: 230, - maxTurn: 14 + maxTurn: 16 } ], defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }], @@ -1020,9 +1020,9 @@ export const sixthBattleScenario: BattleScenarioDefinition = { { label: '안전 지휘', classKeys: ['lord'], reason: '유비는 후방 배치로 생존과 지휘를 동시에 챙깁니다.' } ], deploymentSlots: [ - { role: 'front', unitId: 'guan-yu', x: 3, y: 16, label: '강가 전열' }, - { role: 'flank', unitId: 'zhang-fei', x: 2, y: 17, label: '측면 대응' }, - { role: 'support', unitId: 'liu-bei', x: 2, y: 16, label: '후방 지휘' } + { role: 'front', unitId: 'guan-yu', x: 3, y: 15, label: '강가 전열' }, + { role: 'flank', unitId: 'zhang-fei', x: 2, y: 16, label: '측면 대응' }, + { role: 'support', unitId: 'liu-bei', x: 2, y: 15, label: '후방 지휘' } ], note: '계교 원군로는 빠른 압박보다 길목 안정이 중요합니다. 유비를 보호하고 관우와 장비로 먼저 맞받으십시오.' }, diff --git a/src/game/data/scenario.ts b/src/game/data/scenario.ts index 5ccd0dc..7c5f2a3 100644 --- a/src/game/data/scenario.ts +++ b/src/game/data/scenario.ts @@ -6373,9 +6373,9 @@ export const fifthBattleUnits: UnitData[] = [ ]; const sixthBattleAllyPositions: Record = { - 'liu-bei': { x: 2, y: 16 }, - 'guan-yu': { x: 3, y: 16 }, - 'zhang-fei': { x: 2, y: 17 } + 'liu-bei': { x: 2, y: 15 }, + 'guan-yu': { x: 3, y: 15 }, + 'zhang-fei': { x: 2, y: 16 } }; export const sixthBattleUnits: UnitData[] = [ @@ -6453,11 +6453,11 @@ export const sixthBattleUnits: UnitData[] = [ classKey: 'cavalry', level: 7, exp: 40, - hp: 37, - maxHp: 37, - attack: 12, - move: 5, - stats: { might: 78, intelligence: 42, leadership: 60, agility: 78, luck: 52 }, + hp: 35, + maxHp: 35, + attack: 11, + move: 4, + stats: { might: 76, intelligence: 42, leadership: 59, agility: 76, luck: 52 }, equipment: { weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 18 }, armor: { itemId: 'rebel-vest', level: 2, exp: 8 }, @@ -6516,11 +6516,11 @@ export const sixthBattleUnits: UnitData[] = [ classKey: 'cavalry', level: 7, exp: 42, - hp: 38, - maxHp: 38, - attack: 12, - move: 5, - stats: { might: 79, intelligence: 42, leadership: 61, agility: 79, luck: 52 }, + hp: 35, + maxHp: 35, + attack: 10, + move: 4, + stats: { might: 76, intelligence: 42, leadership: 60, agility: 76, luck: 52 }, equipment: { weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 20 }, armor: { itemId: 'rebel-vest', level: 2, exp: 8 }, @@ -6558,11 +6558,11 @@ export const sixthBattleUnits: UnitData[] = [ classKey: 'cavalry', level: 7, exp: 44, - hp: 34, - maxHp: 34, - attack: 10, - move: 5, - stats: { might: 80, intelligence: 43, leadership: 62, agility: 80, luck: 53 }, + hp: 31, + maxHp: 31, + attack: 9, + move: 4, + stats: { might: 77, intelligence: 43, leadership: 61, agility: 77, luck: 53 }, equipment: { weapon: { itemId: 'yellow-turban-saber', level: 2, exp: 22 }, armor: { itemId: 'rebel-vest', level: 2, exp: 10 }, diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 8a0414f..21367b0 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -1708,6 +1708,18 @@ const enemyAiByUnitId: Record = { 'xuzhou-guard-b': 'guard', 'xuzhou-archer-c': 'hold', 'xuzhou-leader-xiahou-dun': 'guard', + 'jieqiao-skirmisher-a': 'aggressive', + 'jieqiao-infantry-a': 'guard', + 'jieqiao-archer-a': 'hold', + 'jieqiao-cavalry-a': 'aggressive', + 'jieqiao-skirmisher-b': 'guard', + 'jieqiao-archer-b': 'hold', + 'jieqiao-cavalry-b': 'hold', + 'jieqiao-guard-a': 'guard', + 'jieqiao-cavalry-c': 'guard', + 'jieqiao-guard-b': 'guard', + 'jieqiao-archer-c': 'hold', + 'jieqiao-leader-qu-yi': 'guard', 'xiaopei-raider-a': 'guard', 'xiaopei-raider-b': 'guard', 'xiaopei-infantry-a': 'guard',