Clarify camp companion role labels
This commit is contained in:
@@ -586,6 +586,12 @@ const sortieFormationSlotDefinitions: Omit<SortieFormationSlot, 'unitNames'>[] =
|
||||
{ role: 'support', label: '후원', description: '원거리, 책략, 보급 지원' },
|
||||
{ role: 'reserve', label: '예비', description: '빈틈 보강과 공명 연결' }
|
||||
];
|
||||
const campCompanionRoleDefinitions: Omit<SortieFormationSlot, 'unitNames'>[] = [
|
||||
{ role: 'front', label: '대표', description: '대화의 중심과 군영 결정을 맡음' },
|
||||
{ role: 'flank', label: '현장', description: '다음 장면의 현장 판단과 증언 담당' },
|
||||
{ role: 'support', label: '보좌', description: '문서, 보급, 책략 기록을 보탬' },
|
||||
{ role: 'reserve', label: '기록', description: '남은 기록과 공명 정리 담당' }
|
||||
];
|
||||
|
||||
const defaultSortieRule: SortieRuleDefinition = {
|
||||
maxUnits: maxSortieUnits,
|
||||
@@ -12640,11 +12646,11 @@ export class CampScene extends Phaser.Scene {
|
||||
this.trackSortie(this.add.text(slotX + 8, slotY + 5, `${index + 1}`, this.textStyle(10, labelColor, true))).setDepth(depth + 1);
|
||||
if (unit && role) {
|
||||
this.renderSortieBattleUiIcon(this.formationRoleIconKey(role), slotX + 28, slotY + slotHeight / 2, 18, depth + 1, 0.96);
|
||||
const roleLabel = this.sortieFormationRoleLabel(role);
|
||||
const roleLabel = this.sortieFormationRoleLabel(role, hasBattle);
|
||||
this.trackSortie(this.add.text(slotX + 42, slotY + 4, this.compactText(unit.name, 8), this.textStyle(11, '#f2e3bf', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(slotX + 42, slotY + 17, roleLabel, this.textStyle(8, '#9fb0bf', true))).setDepth(depth + 1);
|
||||
} else {
|
||||
this.trackSortie(this.add.text(slotX + 28, slotY + 8, '빈 슬롯', this.textStyle(10, '#7f8994', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(slotX + 28, slotY + 8, hasBattle ? '빈 슬롯' : '빈 동행', this.textStyle(10, '#7f8994', true))).setDepth(depth + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -12652,18 +12658,20 @@ export class CampScene extends Phaser.Scene {
|
||||
private renderSortieRoleQuickButtons(x: number, y: number, width: number, height: number, depth: number) {
|
||||
const focusedUnit = this.sortieFocusedUnit();
|
||||
const enabled = Boolean(focusedUnit && this.isSortieSelected(focusedUnit.id));
|
||||
const hasBattle = Boolean(this.nextSortieScenario());
|
||||
const gap = 6;
|
||||
const buttonWidth = Math.floor((width - gap * (sortieFormationSlotDefinitions.length - 1)) / sortieFormationSlotDefinitions.length);
|
||||
sortieFormationSlotDefinitions.forEach((slot, index) => {
|
||||
const buttonX = x + index * (buttonWidth + gap);
|
||||
const active = Boolean(focusedUnit && this.sortieFormationRole(focusedUnit) === slot.role);
|
||||
const roleCopy = this.sortieFormationRoleCopy(slot.role, hasBattle);
|
||||
const bg = this.trackSortie(this.add.rectangle(buttonX, y, buttonWidth, height, active ? 0x263a2d : 0x111922, enabled ? 0.94 : 0.58));
|
||||
bg.setOrigin(0);
|
||||
bg.setDepth(depth);
|
||||
bg.setStrokeStyle(1, active ? palette.green : 0x53606c, active ? 0.78 : 0.36);
|
||||
bg.setInteractive({ useHandCursor: true });
|
||||
bg.on('pointerdown', () => this.assignFocusedSortieRole(slot.role));
|
||||
this.trackSortie(this.add.text(buttonX + buttonWidth / 2, y + 5, slot.label, this.textStyle(9, active ? '#a8ffd0' : enabled ? '#c8d2dd' : '#77818c', true))).setOrigin(0.5, 0).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(buttonX + buttonWidth / 2, y + 5, roleCopy.label, this.textStyle(9, active ? '#a8ffd0' : enabled ? '#c8d2dd' : '#77818c', true))).setOrigin(0.5, 0).setDepth(depth + 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12716,7 +12724,7 @@ export class CampScene extends Phaser.Scene {
|
||||
const availability = this.sortieUnitAvailability(unit);
|
||||
const recommendation = this.sortieRecommendation(unit.id);
|
||||
const hasBattle = Boolean(this.nextSortieScenario());
|
||||
const roleLabel = this.sortieFormationRoleLabel(this.sortieFormationRole(unit));
|
||||
const roleLabel = this.sortieFormationRoleLabel(this.sortieFormationRole(unit), hasBattle);
|
||||
const terrainScore = this.sortieTerrainScore(unit, this.nextSortieScenario());
|
||||
const terrainGrade = this.sortieTerrainGrade(terrainScore);
|
||||
const statusColor = status.tone === 'disabled' ? '#77818c' : status.tone === 'selected' ? '#a8ffd0' : status.tone === 'recommended' ? '#ffdf7b' : '#9fb0bf';
|
||||
@@ -12778,7 +12786,7 @@ export class CampScene extends Phaser.Scene {
|
||||
? '출전 등록'
|
||||
: '동행 등록';
|
||||
this.renderSortiePanelButton(actionLabel, x + 18, y + height - 28, 108, 22, availability.available, selected, () => this.toggleSortieUnit(unit.id), depth + 1);
|
||||
this.trackSortie(this.add.text(x + 140, y + height - 24, `${roleLabel} · 역할은 중앙 버튼으로 변경`, this.textStyle(10, selected ? '#a8ffd0' : '#9fb0bf', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(x + 140, y + height - 24, hasBattle ? `${roleLabel} · 역할은 중앙 버튼으로 변경` : `${roleLabel} · 의정 역할은 중앙 버튼으로 변경`, this.textStyle(10, selected ? '#a8ffd0' : '#9fb0bf', true))).setDepth(depth + 1);
|
||||
}
|
||||
|
||||
private renderSortieBattleUiIcon(iconKey: BattleUiIconKey, x: number, y: number, size: number, depth: number, alpha = 1) {
|
||||
@@ -12832,8 +12840,13 @@ export class CampScene extends Phaser.Scene {
|
||||
return 'focus';
|
||||
}
|
||||
|
||||
private sortieFormationRoleLabel(role: SortieFormationRole) {
|
||||
return sortieFormationSlotDefinitions.find((slot) => slot.role === role)?.label ?? '예비';
|
||||
private sortieFormationRoleCopy(role: SortieFormationRole, hasBattle = Boolean(this.nextSortieScenario())) {
|
||||
const definitions = hasBattle ? sortieFormationSlotDefinitions : campCompanionRoleDefinitions;
|
||||
return definitions.find((slot) => slot.role === role) ?? definitions[definitions.length - 1];
|
||||
}
|
||||
|
||||
private sortieFormationRoleLabel(role: SortieFormationRole, hasBattle = Boolean(this.nextSortieScenario())) {
|
||||
return this.sortieFormationRoleCopy(role, hasBattle).label;
|
||||
}
|
||||
|
||||
private sortieRecommendationHint(recommendation: SortieRecommendation, unit?: UnitData, maxReasonLength = 20) {
|
||||
@@ -13190,8 +13203,8 @@ export class CampScene extends Phaser.Scene {
|
||||
frame.setStrokeStyle(1, palette.blue, 0.48);
|
||||
|
||||
if (!scenario) {
|
||||
this.trackSortie(this.add.text(x + 14, y + 22, '전투 배치 없음', this.textStyle(12, '#d8b15f', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(x + 14, y + 40, '다음 장면에 함께할 동행 명단을 확인합니다.', this.textStyle(11, '#9fb0bf'))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(x + 14, y + 20, '군영 동행 확인', this.textStyle(12, '#d8b15f', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(x + 14, y + 38, '전투 배치 없이 의정에 함께할 무장을 정리합니다.', this.textStyle(11, '#9fb0bf'))).setDepth(depth + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13303,8 +13316,9 @@ export class CampScene extends Phaser.Scene {
|
||||
},
|
||||
{ front: 0, flank: 0, support: 0, reserve: 0 } as Record<SortieFormationRole, number>
|
||||
);
|
||||
const hasBattle = Boolean(scenario);
|
||||
const formationSlots = sortieFormationSlotDefinitions.map((slot) => ({
|
||||
...slot,
|
||||
...this.sortieFormationRoleCopy(slot.role, hasBattle),
|
||||
unitNames: selectedUnits.filter((unit) => this.sortieFormationRole(unit) === slot.role).map((unit) => unit.name)
|
||||
}));
|
||||
const warnings: string[] = [];
|
||||
@@ -13319,21 +13333,36 @@ export class CampScene extends Phaser.Scene {
|
||||
if (missingClassRecommendations.length > 0) {
|
||||
warnings.push(`추천 병종 ${missingClassRecommendations.map((entry) => entry.label).join(', ')} 부족.`);
|
||||
}
|
||||
if (roleCounts.front <= 0) {
|
||||
warnings.push('전열 담당이 없어 길목을 버티기 어렵습니다.');
|
||||
}
|
||||
if (roleCounts.flank <= 0) {
|
||||
warnings.push('돌파 담당이 없어 추격과 측면 압박이 느릴 수 있습니다.');
|
||||
}
|
||||
if (roleCounts.support <= 0) {
|
||||
warnings.push('후원 담당이 없어 회복, 보급, 원거리 견제가 약합니다.');
|
||||
if (hasBattle) {
|
||||
if (roleCounts.front <= 0) {
|
||||
warnings.push('전열 담당이 없어 길목을 버티기 어렵습니다.');
|
||||
}
|
||||
if (roleCounts.flank <= 0) {
|
||||
warnings.push('돌파 담당이 없어 추격과 측면 압박이 느릴 수 있습니다.');
|
||||
}
|
||||
if (roleCounts.support <= 0) {
|
||||
warnings.push('후원 담당이 없어 회복, 보급, 원거리 견제가 약합니다.');
|
||||
}
|
||||
} else {
|
||||
if (roleCounts.front <= 0) {
|
||||
warnings.push('대표 동행이 없어 의정의 중심이 약합니다.');
|
||||
}
|
||||
if (roleCounts.flank <= 0) {
|
||||
warnings.push('현장 증언을 맡을 동행이 부족합니다.');
|
||||
}
|
||||
if (roleCounts.support <= 0) {
|
||||
warnings.push('보좌 기록을 맡을 동행이 부족합니다.');
|
||||
}
|
||||
}
|
||||
if (activeBondCount <= 0 && selectedUnits.length > 1) {
|
||||
warnings.push('함께하는 공명 조합이 없습니다.');
|
||||
}
|
||||
if (terrainScore > 0 && terrainScore < 98) {
|
||||
if (hasBattle && terrainScore > 0 && terrainScore < 98) {
|
||||
warnings.push('선택 무장의 평균 지형 적성이 낮습니다.');
|
||||
}
|
||||
const roleLine = hasBattle
|
||||
? `전열 ${roleCounts.front} · 돌파 ${roleCounts.flank} · 후원 ${roleCounts.support} · 예비 ${roleCounts.reserve}`
|
||||
: `대표 ${roleCounts.front} · 현장 ${roleCounts.flank} · 보좌 ${roleCounts.support} · 기록 ${roleCounts.reserve}`;
|
||||
|
||||
return {
|
||||
selectedCount: selectedUnits.length,
|
||||
@@ -13346,7 +13375,7 @@ export class CampScene extends Phaser.Scene {
|
||||
reserveCount: reserveUnits.length,
|
||||
recommendedSelectedCount,
|
||||
recommendedTotal: recommended.length,
|
||||
deploymentLine: `전열 ${roleCounts.front} · 돌파 ${roleCounts.flank} · 후원 ${roleCounts.support} · 예비 ${roleCounts.reserve}`,
|
||||
deploymentLine: roleLine,
|
||||
recommendationLine: recommended.length > 0
|
||||
? `추천 무장 ${recommendedSelectedCount}/${recommended.length} · 병종 ${this.sortieRecommendedClassLine(scenario)}`
|
||||
: `추천 병종 ${this.sortieRecommendedClassLine(scenario)}`,
|
||||
@@ -13366,7 +13395,7 @@ export class CampScene extends Phaser.Scene {
|
||||
reserveTrainingBondPreview: reserveFocus.bondExpGained,
|
||||
objectiveLine: scenario ? `${scenario.title} · ${scenario.victoryConditionLabel}` : `${flow.title} · 군영 의정`,
|
||||
formationSlots,
|
||||
warningLine: warnings[0] ?? '배치 균형 양호',
|
||||
warningLine: warnings[0] ?? (hasBattle ? '배치 균형 양호' : '동행 균형 양호'),
|
||||
warnings
|
||||
};
|
||||
}
|
||||
@@ -13477,7 +13506,10 @@ export class CampScene extends Phaser.Scene {
|
||||
);
|
||||
const names = unitIds.slice(0, 3).map((id) => this.unitName(id)).join(', ');
|
||||
const extra = unitIds.length > 3 ? ` 외 ${unitIds.length - 3}명` : '';
|
||||
return `${hasBattle ? '추천 편성' : '추천 동행'} 적용 · ${names}${extra} · 전열 ${roleCounts.front} / 돌파 ${roleCounts.flank} / 후원 ${roleCounts.support}`;
|
||||
const roleLine = hasBattle
|
||||
? `전열 ${roleCounts.front} / 돌파 ${roleCounts.flank} / 후원 ${roleCounts.support}`
|
||||
: `대표 ${roleCounts.front} / 현장 ${roleCounts.flank} / 보좌 ${roleCounts.support}`;
|
||||
return `${hasBattle ? '추천 편성' : '추천 동행'} 적용 · ${names}${extra} · ${roleLine}`;
|
||||
}
|
||||
|
||||
private sortieTerrainScore(unit: UnitData, scenario: BattleScenarioDefinition | undefined) {
|
||||
|
||||
Reference in New Issue
Block a user