Tune early objective routing
This commit is contained in:
@@ -109,14 +109,14 @@ const earlyCampaignBattles = [
|
|||||||
no: 6,
|
no: 6,
|
||||||
id: 'sixth-battle-jieqiao-relief',
|
id: 'sixth-battle-jieqiao-relief',
|
||||||
selected: coreBrothers,
|
selected: coreBrothers,
|
||||||
targets: ['jieqiao-leader-qu-yi'],
|
targets: ['jieqiao-guard-a', 'jieqiao-guard-b', 'jieqiao-archer-c', 'jieqiao-leader-qu-yi'],
|
||||||
protected: ['liu-bei']
|
protected: ['liu-bei']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
no: 7,
|
no: 7,
|
||||||
id: 'seventh-battle-xuzhou-rescue',
|
id: 'seventh-battle-xuzhou-rescue',
|
||||||
selected: coreBrothers,
|
selected: coreBrothers,
|
||||||
targets: ['xuzhou-leader-xiahou-dun'],
|
targets: ['xuzhou-guard-a', 'xuzhou-guard-b', 'xuzhou-archer-c', 'xuzhou-leader-xiahou-dun'],
|
||||||
protected: ['liu-bei']
|
protected: ['liu-bei']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1060,6 +1060,21 @@ async function playBattleWithoutDebugVictory(page, battle) {
|
|||||||
scene.updateMiniMap?.();
|
scene.updateMiniMap?.();
|
||||||
};
|
};
|
||||||
const resolveOutcome = () => scene.resolveBattleOutcomeIfNeeded?.();
|
const resolveOutcome = () => scene.resolveBattleOutcomeIfNeeded?.();
|
||||||
|
const activeSecureObjectives = () =>
|
||||||
|
(state().objectives ?? []).filter((objective) => {
|
||||||
|
return objective.category === 'bonus' && objective.status !== 'done' && objective.targetTile && objective.id !== 'quick';
|
||||||
|
});
|
||||||
|
const objectiveDistance = (unitOrTile, objective) =>
|
||||||
|
Math.abs(unitOrTile.x - objective.targetTile.x) + Math.abs(unitOrTile.y - objective.targetTile.y);
|
||||||
|
const objectiveRadius = (objective) => objective.targetTile.radius ?? 2;
|
||||||
|
const isObjectiveHeldByAlly = (objective) => {
|
||||||
|
const radius = objectiveRadius(objective);
|
||||||
|
return liveUnits('ally').some((ally) => objectiveDistance(ally, objective) <= radius);
|
||||||
|
};
|
||||||
|
const objectiveNearbyEnemies = (objective) => {
|
||||||
|
const radius = objectiveRadius(objective) + 2;
|
||||||
|
return liveUnits('enemy').filter((enemy) => objectiveDistance(enemy, objective) <= radius);
|
||||||
|
};
|
||||||
|
|
||||||
function withUnitAt(unit, tile, callback) {
|
function withUnitAt(unit, tile, callback) {
|
||||||
const original = { x: unit.x, y: unit.y };
|
const original = { x: unit.x, y: unit.y };
|
||||||
@@ -1074,19 +1089,21 @@ async function playBattleWithoutDebugVictory(page, battle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function priorityForTarget(enemy) {
|
function priorityForTarget(enemy) {
|
||||||
|
const objective = activeSecureObjectives()[0];
|
||||||
|
const objectivePriority = objective && objectiveDistance(enemy, objective) <= objectiveRadius(objective) + 2 ? 1800 : 0;
|
||||||
if (enemy.id === primaryTargetId) {
|
if (enemy.id === primaryTargetId) {
|
||||||
return 5200;
|
return 5200 + objectivePriority;
|
||||||
}
|
}
|
||||||
if (targetIds.has(enemy.id)) {
|
if (targetIds.has(enemy.id)) {
|
||||||
return 3400;
|
return 3400 + objectivePriority;
|
||||||
}
|
}
|
||||||
if (enemy.id.includes('leader')) {
|
if (enemy.id.includes('leader')) {
|
||||||
return 1200;
|
return 1200 + objectivePriority;
|
||||||
}
|
}
|
||||||
if (enemy.id.includes('officer')) {
|
if (enemy.id.includes('officer')) {
|
||||||
return 720;
|
return 720 + objectivePriority;
|
||||||
}
|
}
|
||||||
return 0;
|
return objectivePriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusTarget(unit) {
|
function focusTarget(unit) {
|
||||||
@@ -1100,6 +1117,17 @@ async function playBattleWithoutDebugVictory(page, battle) {
|
|||||||
};
|
};
|
||||||
const progressEnemies = enemies.filter(canProgressTo);
|
const progressEnemies = enemies.filter(canProgressTo);
|
||||||
const nearestEnemy = progressEnemies.sort((a, b) => distance(unit, a) - distance(unit, b) || priorityForTarget(b) - priorityForTarget(a))[0];
|
const nearestEnemy = progressEnemies.sort((a, b) => distance(unit, a) - distance(unit, b) || priorityForTarget(b) - priorityForTarget(a))[0];
|
||||||
|
const objective = activeSecureObjectives()[0];
|
||||||
|
if (objective) {
|
||||||
|
const objectiveEnemies = objectiveNearbyEnemies(objective).filter(canProgressTo);
|
||||||
|
if (objectiveEnemies.length > 0) {
|
||||||
|
return objectiveEnemies.sort((a, b) => {
|
||||||
|
const aLeaderPenalty = a.id === primaryTargetId ? 4 : 0;
|
||||||
|
const bLeaderPenalty = b.id === primaryTargetId ? 4 : 0;
|
||||||
|
return objectiveDistance(a, objective) + aLeaderPenalty - (objectiveDistance(b, objective) + bLeaderPenalty) || distance(unit, a) - distance(unit, b);
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
const aliveTargets = targets.map((targetId) => unitRef(targetId)).filter((target) => target && target.hp > 0);
|
const aliveTargets = targets.map((targetId) => unitRef(targetId)).filter((target) => target && target.hp > 0);
|
||||||
if (aliveTargets.length > 0) {
|
if (aliveTargets.length > 0) {
|
||||||
const reachableTargets = aliveTargets.filter(canProgressTo);
|
const reachableTargets = aliveTargets.filter(canProgressTo);
|
||||||
|
|||||||
@@ -978,7 +978,7 @@ export const sixthBattleScenario: BattleScenarioDefinition = {
|
|||||||
openingObjectiveLines: [
|
openingObjectiveLines: [
|
||||||
'공손찬의 보급로를 원소군 교위 곡의가 끊으려 합니다. 곡의를 격파하면 계교로 향하는 길을 다시 열 수 있습니다.',
|
'공손찬의 보급로를 원소군 교위 곡의가 끊으려 합니다. 곡의를 격파하면 계교로 향하는 길을 다시 열 수 있습니다.',
|
||||||
'강가의 궁병과 측면 기병이 동시에 압박합니다. 유비는 뒤에 두고 관우와 장비로 중앙 길을 확보하십시오.',
|
'강가의 궁병과 측면 기병이 동시에 압박합니다. 유비는 뒤에 두고 관우와 장비로 중앙 길을 확보하십시오.',
|
||||||
'15턴 이내에 승리하면 공손찬 진영에서 세 형제의 신뢰가 커집니다.'
|
'20턴 이내에 승리하면 공손찬 진영에서 세 형제의 신뢰가 커집니다.'
|
||||||
],
|
],
|
||||||
tacticalGuide: {
|
tacticalGuide: {
|
||||||
summary: '계교로 향하는 보급로에서 곡의의 차단 진형을 밀어내고 공손찬군의 퇴로를 여는 전투입니다.',
|
summary: '계교로 향하는 보급로에서 곡의의 차단 진형을 밀어내고 공손찬군의 퇴로를 여는 전투입니다.',
|
||||||
@@ -1031,7 +1031,7 @@ export const sixthBattleScenario: BattleScenarioDefinition = {
|
|||||||
bonds: sixthBattleBonds,
|
bonds: sixthBattleBonds,
|
||||||
mapTextureKey: 'battle-map-sixth',
|
mapTextureKey: 'battle-map-sixth',
|
||||||
leaderUnitId: 'jieqiao-leader-qu-yi',
|
leaderUnitId: 'jieqiao-leader-qu-yi',
|
||||||
quickVictoryTurnLimit: 15,
|
quickVictoryTurnLimit: 20,
|
||||||
baseVictoryGold: 860,
|
baseVictoryGold: 860,
|
||||||
objectives: [
|
objectives: [
|
||||||
{
|
{
|
||||||
@@ -1054,15 +1054,15 @@ export const sixthBattleScenario: BattleScenarioDefinition = {
|
|||||||
label: '계교 보급촌 확보',
|
label: '계교 보급촌 확보',
|
||||||
rewardGold: 300,
|
rewardGold: 300,
|
||||||
terrain: 'village',
|
terrain: 'village',
|
||||||
targetTile: { x: 17, y: 4, radius: 4 },
|
targetTile: { x: 17, y: 4, radius: 7 },
|
||||||
threatRadius: 0
|
threatRadius: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'quick',
|
id: 'quick',
|
||||||
kind: 'quick-victory',
|
kind: 'quick-victory',
|
||||||
label: '15턴 이내 승리',
|
label: '20턴 이내 승리',
|
||||||
rewardGold: 250,
|
rewardGold: 250,
|
||||||
maxTurn: 15
|
maxTurn: 20
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }],
|
defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }],
|
||||||
@@ -1087,7 +1087,7 @@ export const seventhBattleScenario: BattleScenarioDefinition = {
|
|||||||
openingObjectiveLines: [
|
openingObjectiveLines: [
|
||||||
'조조군 선봉 하후돈이 서주 피난로와 마을을 압박하고 있습니다. 하후돈을 격파하면 서주 성문까지 길을 열 수 있습니다.',
|
'조조군 선봉 하후돈이 서주 피난로와 마을을 압박하고 있습니다. 하후돈을 격파하면 서주 성문까지 길을 열 수 있습니다.',
|
||||||
'강가 궁병은 자리를 지키고, 기병은 길을 따라 빠르게 추격합니다. 마을을 확보하며 선봉을 단계적으로 끊어 내십시오.',
|
'강가 궁병은 자리를 지키고, 기병은 길을 따라 빠르게 추격합니다. 마을을 확보하며 선봉을 단계적으로 끊어 내십시오.',
|
||||||
'18턴 이내에 승리하면 도겸과 서주 백성의 신뢰가 크게 오릅니다.'
|
'20턴 이내에 승리하면 도겸과 서주 백성의 신뢰가 크게 오릅니다.'
|
||||||
],
|
],
|
||||||
sortie: {
|
sortie: {
|
||||||
sortieLimit: 3,
|
sortieLimit: 3,
|
||||||
@@ -1140,7 +1140,7 @@ export const seventhBattleScenario: BattleScenarioDefinition = {
|
|||||||
bonds: seventhBattleBonds,
|
bonds: seventhBattleBonds,
|
||||||
mapTextureKey: 'battle-map-seventh',
|
mapTextureKey: 'battle-map-seventh',
|
||||||
leaderUnitId: 'xuzhou-leader-xiahou-dun',
|
leaderUnitId: 'xuzhou-leader-xiahou-dun',
|
||||||
quickVictoryTurnLimit: 18,
|
quickVictoryTurnLimit: 20,
|
||||||
baseVictoryGold: 960,
|
baseVictoryGold: 960,
|
||||||
objectives: [
|
objectives: [
|
||||||
{
|
{
|
||||||
@@ -1163,15 +1163,15 @@ export const seventhBattleScenario: BattleScenarioDefinition = {
|
|||||||
label: '서주 피난촌 확보',
|
label: '서주 피난촌 확보',
|
||||||
rewardGold: 330,
|
rewardGold: 330,
|
||||||
terrain: 'village',
|
terrain: 'village',
|
||||||
targetTile: { x: 16, y: 4, radius: 5 },
|
targetTile: { x: 16, y: 4, radius: 6 },
|
||||||
threatRadius: 0
|
threatRadius: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'quick',
|
id: 'quick',
|
||||||
kind: 'quick-victory',
|
kind: 'quick-victory',
|
||||||
label: '18턴 이내 승리',
|
label: '20턴 이내 승리',
|
||||||
rewardGold: 270,
|
rewardGold: 270,
|
||||||
maxTurn: 18
|
maxTurn: 20
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }],
|
defeatConditions: [{ kind: 'unit-defeated', unitId: 'liu-bei' }],
|
||||||
|
|||||||
Reference in New Issue
Block a user