Tune first battle pacing and events
This commit is contained in:
@@ -2074,8 +2074,11 @@ export class BattleScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
if (objective.kind === 'secure-terrain') {
|
||||
const terrain = objective.terrain ?? 'village';
|
||||
const secured = !this.hasEnemyOnTerrain(terrain);
|
||||
const terrain = (objective.terrain ?? 'village') as TerrainType;
|
||||
const secured =
|
||||
terrain === 'village'
|
||||
? !this.hasEnemyThreateningTerrain(terrain, 2)
|
||||
: !this.hasEnemyOnTerrain(terrain);
|
||||
const achieved = outcome ? outcome === 'victory' && secured : secured;
|
||||
return {
|
||||
id: objective.id,
|
||||
@@ -2901,25 +2904,98 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.triggerBattleEvent('leader-wavering', '두령 동요', [`${leader.name}의 기세가 꺾였습니다.`, '두령을 몰아붙이면 황건적의 전열이 무너집니다.']);
|
||||
}
|
||||
|
||||
if (!this.hasEnemyOnVillageTile()) {
|
||||
const endangeredAlly = this.endangeredAlly();
|
||||
if (endangeredAlly) {
|
||||
this.triggerBattleEvent('ally-danger', '아군 위기', [
|
||||
`${endangeredAlly.name}의 병력이 크게 줄었습니다.`,
|
||||
'유비가 퇴각하면 패배합니다. 마을과 성채 지형을 이용해 전열을 다시 잡으세요.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (this.isAnyAllyNearTerrain('village', 2)) {
|
||||
this.triggerBattleEvent('village-approach', '마을 어귀', [
|
||||
'마을 주변에 황건적이 몰려 있습니다.',
|
||||
'마을의 적을 몰아내면 승리 보상이 추가됩니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!this.hasEnemyThreateningVillage()) {
|
||||
this.triggerBattleEvent('village-secured', '마을 확보', ['마을 주변의 황건적을 몰아냈습니다.', '승리 시 마을 확보 보상이 추가됩니다.']);
|
||||
}
|
||||
|
||||
if (this.areUnitsDefeated(['rebel-a', 'rebel-b', 'rebel-c'])) {
|
||||
this.triggerBattleEvent('vanguard-broken', '선봉 격파', [
|
||||
'남쪽 길목의 황건 선봉이 무너졌습니다.',
|
||||
'이제 중앙 마을과 기병의 움직임을 경계하세요.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (this.isEnemyClassNearAlly('cavalry', 6)) {
|
||||
this.triggerBattleEvent('cavalry-approach', '기병 접근', [
|
||||
'황건 기병이 빠르게 압박해옵니다.',
|
||||
'위험 범위를 켜고 숲이나 마을 쪽으로 전선을 잡으세요.'
|
||||
]);
|
||||
}
|
||||
|
||||
if (this.turnNumber === 2 && this.activeFaction === 'ally') {
|
||||
this.triggerBattleEvent('enemy-posture', '적 전술 변화', ['기병은 계속 접근하고, 궁병은 자리를 지키며 사격합니다.', '숲과 마을 지형을 이용해 피해를 줄이세요.']);
|
||||
}
|
||||
}
|
||||
|
||||
private hasEnemyOnVillageTile() {
|
||||
return this.hasEnemyOnTerrain('village');
|
||||
private hasEnemyThreateningVillage() {
|
||||
return this.hasEnemyThreateningTerrain('village', 2);
|
||||
}
|
||||
|
||||
private hasEnemyOnTerrain(terrain: string) {
|
||||
private hasEnemyThreateningTerrain(terrain: TerrainType, distance: number) {
|
||||
return battleUnits.some((unit) => {
|
||||
return unit.faction === 'enemy' && unit.hp > 0 && this.isUnitNearTerrain(unit, terrain, distance);
|
||||
});
|
||||
}
|
||||
|
||||
private hasEnemyOnTerrain(terrain: TerrainType) {
|
||||
return battleUnits.some((unit) => {
|
||||
return unit.faction === 'enemy' && unit.hp > 0 && battleMap.terrain[unit.y][unit.x] === terrain;
|
||||
});
|
||||
}
|
||||
|
||||
private isAnyAllyNearTerrain(terrain: TerrainType, distance: number) {
|
||||
return battleUnits.some((unit) => {
|
||||
return unit.faction === 'ally' && unit.hp > 0 && this.isUnitNearTerrain(unit, terrain, distance);
|
||||
});
|
||||
}
|
||||
|
||||
private isUnitNearTerrain(unit: UnitData, terrain: TerrainType, distance: number) {
|
||||
return battleMap.terrain.some((row, y) => {
|
||||
return row.some((tile, x) => tile === terrain && this.tileDistanceTo(unit.x, unit.y, x, y) <= distance);
|
||||
});
|
||||
}
|
||||
|
||||
private areUnitsDefeated(unitIds: string[]) {
|
||||
return unitIds.every((unitId) => this.isUnitDefeated(unitId));
|
||||
}
|
||||
|
||||
private isEnemyClassNearAlly(classKey: UnitClassKey, distance: number) {
|
||||
return battleUnits.some((enemy) => {
|
||||
if (enemy.faction !== 'enemy' || enemy.hp <= 0 || enemy.classKey !== classKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return battleUnits.some((ally) => {
|
||||
return ally.faction === 'ally' && ally.hp > 0 && this.tileDistance(enemy, ally) <= distance;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private endangeredAlly() {
|
||||
return battleUnits.find((unit) => {
|
||||
return unit.faction === 'ally' && unit.hp > 0 && unit.hp <= Math.ceil(unit.maxHp * 0.35);
|
||||
});
|
||||
}
|
||||
|
||||
private tileDistanceTo(x1: number, y1: number, x2: number, y2: number) {
|
||||
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
|
||||
}
|
||||
|
||||
private isUnitAlive(unitId: string) {
|
||||
const unit = battleUnits.find((candidate) => candidate.id === unitId);
|
||||
return Boolean(unit && unit.hp > 0);
|
||||
|
||||
Reference in New Issue
Block a user