Finish companion sortie copy

This commit is contained in:
2026-07-05 06:00:56 +09:00
parent ba61e6ea72
commit fc81343f4f

View File

@@ -12391,6 +12391,8 @@ export class CampScene extends Phaser.Scene {
const displayAllies = this.sortieRosterDisplayUnits(rosterUnits);
const selectedCount = this.selectedSortieUnitIds.length;
const maxUnits = this.sortieMaxUnits();
const hasBattle = Boolean(this.nextSortieScenario());
const selectedLabel = hasBattle ? '출전' : '동행';
const reserveCount = Math.max(0, availableAllies.length - selectedCount);
const rosterView = this.sortieRosterViewState(rosterUnits.length, height);
const { denseRoster, rowGap, rowHeight, listTopOffset, listFooterHeight, maxVisibleRows, maxScroll } = rosterView;
@@ -12415,7 +12417,7 @@ export class CampScene extends Phaser.Scene {
bg.on('wheel', handleRosterWheel);
}
this.trackSortie(
this.add.text(x + 18, y + 14, `보유 무장 ${rosterUnits.length} · 출전 ${selectedCount}/${maxUnits}`, this.textStyle(17, '#f2e3bf', true))
this.add.text(x + 18, y + 14, `보유 무장 ${rosterUnits.length} · ${selectedLabel} ${selectedCount}/${maxUnits}`, this.textStyle(17, '#f2e3bf', true))
).setDepth(depth + 1);
this.trackSortie(this.add.text(x + width - 18, y + 17, `대기 ${reserveCount}`, this.textStyle(11, '#9fb0bf', true))).setOrigin(1, 0).setDepth(depth + 1);
@@ -12755,7 +12757,17 @@ export class CampScene extends Phaser.Scene {
this.renderSortieSupplyAssignment(unit, x + 18, y + 236, width - 36, depth + 1);
const actionLabel = selected ? (this.isRequiredSortieUnit(unit.id) ? '필수 출전' : '출전 해제') : '출전 등록';
const actionLabel = selected
? this.isRequiredSortieUnit(unit.id)
? hasBattle
? '필수 출전'
: '필수 동행'
: hasBattle
? '출전 해제'
: '동행 해제'
: hasBattle
? '출전 등록'
: '동행 등록';
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);
}
@@ -13308,7 +13320,7 @@ export class CampScene extends Phaser.Scene {
warnings.push('후원 담당이 없어 회복, 보급, 원거리 견제가 약합니다.');
}
if (activeBondCount <= 0 && selectedUnits.length > 1) {
warnings.push('함께 출전하는 공명 조합이 없습니다.');
warnings.push('함께하는 공명 조합이 없습니다.');
}
if (terrainScore > 0 && terrainScore < 98) {
warnings.push('선택 무장의 평균 지형 적성이 낮습니다.');
@@ -13333,7 +13345,7 @@ export class CampScene extends Phaser.Scene {
recruitedUnits.length > 0
? `합류 무장 ${selectedRecruitedCount}/${recruitedUnits.length} · 대기 ${reserveUnits.length}`
: '합류 무장 없음',
reserveLine: reserveUnits.length > 0 ? `대기 무장: ${reserveNames}` : '전원 출전 중입니다.',
reserveLine: reserveUnits.length > 0 ? `대기 무장: ${reserveNames}` : scenario ? '전원 출전 중입니다.' : '전원 동행 중입니다.',
reserveTrainingLine:
reserveUnits.length > 0
? `대기 훈련 ${reserveFocus.label}: 경험 +${reserveFocus.expGained}, 장비 +${reserveFocus.equipmentExpGained}${reserveFocus.bondExpGained ? `, 공명 +${reserveFocus.bondExpGained}` : ''}`
@@ -13375,7 +13387,8 @@ export class CampScene extends Phaser.Scene {
this.sortieFocusedUnitId = unit.id;
if (!this.isSortieSelected(unit.id)) {
this.showCampNotice(`${unit.name}을 먼저 출전 편성에 포함해야 역할을 바꿀 수 있습니다.`);
const hasBattle = Boolean(this.nextSortieScenario());
this.showCampNotice(`${unit.name}을 먼저 ${hasBattle ? '출전 편성' : '동행 명단'}에 포함해야 역할을 바꿀 수 있습니다.`);
return;
}
@@ -13525,10 +13538,11 @@ export class CampScene extends Phaser.Scene {
const reward = this.currentSortieFlow().rewardHint;
const sortieNote = this.nextSortieRule().note;
const recoveryHint = this.sortieRecoveryHint();
const hasBattle = Boolean(this.nextSortieScenario());
const readyLine = [
`대화 ${completedDialogues}/${availableDialogues.length}`,
`방문 ${completedVisits}/${availableVisits.length}`,
`출전 ${selectedSummary}`,
`${hasBattle ? '출전' : '동행'} ${selectedSummary}`,
`보유 ${inventorySummary}`
].join(' · ');
const rewardLine = recoveryHint ? `${reward} · ${recoveryHint}` : `${reward} · ${readyLine}`;
@@ -13637,7 +13651,7 @@ export class CampScene extends Phaser.Scene {
const recoveryDetail = recoveryTargets.length > 0
? `${recoveryTargets.map((unit) => `${unit.name} ${unit.hp}/${unit.maxHp}`).join(', ')} 회복 권장`
: injured.length > 0
? `${injured.length}명 경상 · 출전 가능`
? `${injured.length}명 경상 · ${hasBattle ? '출전' : '동행'} 가능`
: '전원 완전한 병력';
const supplyCount = campSupplies.reduce((total, supply) => total + this.inventoryAmount(supply.label), 0);
const assignedSupplyCount = campSupplies.reduce((total, supply) => total + this.totalAssignedSupplyCount(supply.usableId), 0);
@@ -14967,11 +14981,11 @@ export class CampScene extends Phaser.Scene {
return { available: false, label: '적', reason: '아군 명단에 포함되지 않습니다.', tone: 'disabled' };
}
if (unit.hp <= 0) {
return { available: false, label: '부상', reason: '병력이 0이라 출전할 수 없습니다. 보급 화면에서 회복이 필요합니다.', tone: 'disabled' };
return { available: false, label: '부상', reason: `병력이 0이라 ${hasBattle ? '출전' : '동행'}할 수 없습니다. 보급 화면에서 회복이 필요합니다.`, tone: 'disabled' };
}
const excludedUnitIds = new Set(rule.excludedUnitIds ?? []);
if (excludedUnitIds.has(unit.id)) {
return { available: false, label: '제외', reason: '이번 장면의 지휘 조건상 출전 후보에서 제외됩니다.', tone: 'disabled' };
return { available: false, label: '제외', reason: `이번 장면의 지휘 조건상 ${hasBattle ? '출전' : '동행'} 후보에서 제외됩니다.`, tone: 'disabled' };
}
const scenarioAllyIds = scenario
? new Set(scenario.units.filter((candidate) => candidate.faction === 'ally').map((candidate) => candidate.id))
@@ -14988,7 +15002,7 @@ export class CampScene extends Phaser.Scene {
};
}
if (this.sortieRecommendation(unit.id, scenario)) {
return { available: true, label: '추천', reason: this.sortieRecommendation(unit.id, scenario)?.reason ?? '이번 전투 추천 무장입니다.', tone: 'recommended' };
return { available: true, label: '추천', reason: this.sortieRecommendation(unit.id, scenario)?.reason ?? (hasBattle ? '이번 전투 추천 무장입니다.' : '이번 장면 추천 동행입니다.'), tone: 'recommended' };
}
return { available: true, label: '대기', reason: hasBattle ? '출전 가능한 후보입니다.' : '동행 가능한 후보입니다.', tone: 'reserve' };
}
@@ -15076,12 +15090,13 @@ export class CampScene extends Phaser.Scene {
}
this.sortieFocusedUnitId = unitId;
const availability = this.sortieUnitAvailability(unit);
const hasBattle = Boolean(this.nextSortieScenario());
if (!availability.available) {
this.showCampNotice(`${unit.name}: ${availability.reason}`);
return;
}
if (this.isRequiredSortieUnit(unitId)) {
this.showCampNotice(`${unit.name}는 반드시 출전해야 합니다.`);
this.showCampNotice(`${unit.name}는 반드시 ${hasBattle ? '출전' : '동행'}해야 합니다.`);
return;
}
@@ -15095,7 +15110,6 @@ export class CampScene extends Phaser.Scene {
delete nextItemAssignments[unitId];
this.sortieItemAssignments = nextItemAssignments;
} else if (selected.size >= this.sortieMaxUnits()) {
const hasBattle = Boolean(this.nextSortieScenario());
this.showCampNotice(`${hasBattle ? '이번 전투' : '이번 장면'}는 최대 ${this.sortieMaxUnits()}명까지 ${hasBattle ? '출전' : '동행'}할 수 있습니다.`);
return;
} else {
@@ -15103,7 +15117,6 @@ export class CampScene extends Phaser.Scene {
}
this.selectedSortieUnitIds = this.normalizedSortieUnitIds(Array.from(selected));
const hasBattle = Boolean(this.nextSortieScenario());
const selectionLabel = hasBattle ? '출전' : '동행';
this.sortiePlanFeedback = selected.has(unitId)
? `${unit.name} ${selectionLabel} 추가 · 직접 편성 중`
@@ -15159,7 +15172,8 @@ export class CampScene extends Phaser.Scene {
return;
}
if (!this.isSortieSelected(unitId)) {
this.showCampNotice(`${unit.name}는 출전 등록 후 보급을 배정할 수 있습니다.`);
const hasBattle = Boolean(this.nextSortieScenario());
this.showCampNotice(`${unit.name}${hasBattle ? '출전' : '동행'} 등록 후 보급을 배정할 수 있습니다.`);
return;
}