feat: upgrade combat and item icons
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import Phaser from 'phaser';
|
||||
import storyFirstSortieUrl from '../../assets/images/story/05-first-sortie.png';
|
||||
import { soundDirector } from '../audio/SoundDirector';
|
||||
import { battleUiIconFrames, battleUiIconTextureKey, loadBattleUiIcons, type BattleUiIconKey } from '../data/battleUiIcons';
|
||||
import { battleUiIconFrames, battleUiIconTextureForSize, loadBattleUiIcons, type BattleUiIconKey } from '../data/battleUiIcons';
|
||||
import { selectCampSkin, type CampSkinSelection } from '../data/campSkins';
|
||||
import {
|
||||
equipmentExpToNext,
|
||||
@@ -280,9 +280,11 @@ type SortiePortraitRosterLayout = {
|
||||
nextEnabled: boolean;
|
||||
};
|
||||
|
||||
type CampSupplyId = 'bean' | 'wine' | 'salve';
|
||||
|
||||
type CampSupplyDefinition = {
|
||||
label: string;
|
||||
usableId: string;
|
||||
usableId: CampSupplyId;
|
||||
title: string;
|
||||
description: string;
|
||||
healHp: number;
|
||||
@@ -290,6 +292,7 @@ type CampSupplyDefinition = {
|
||||
};
|
||||
|
||||
type MerchantItemDefinition = {
|
||||
usableId: CampSupplyId;
|
||||
label: string;
|
||||
title: string;
|
||||
description: string;
|
||||
@@ -780,18 +783,21 @@ const campSupplyByLabel = new Map(campSupplies.map((supply) => [supply.label, su
|
||||
|
||||
const merchantItems: MerchantItemDefinition[] = [
|
||||
{
|
||||
usableId: 'bean',
|
||||
label: '콩',
|
||||
title: '콩',
|
||||
description: '값싸고 가벼운 회복 도구입니다.',
|
||||
price: 40
|
||||
},
|
||||
{
|
||||
usableId: 'wine',
|
||||
label: '탁주',
|
||||
title: '탁주',
|
||||
description: '병력 회복과 작은 공명 상승에 유용합니다.',
|
||||
price: 70
|
||||
},
|
||||
{
|
||||
usableId: 'salve',
|
||||
label: '상처약',
|
||||
title: '상처약',
|
||||
description: '큰 부상을 빠르게 회복합니다.',
|
||||
@@ -15880,18 +15886,33 @@ export class CampScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private renderSortieBattleUiIcon(iconKey: BattleUiIconKey, x: number, y: number, size: number, depth: number, alpha = 1) {
|
||||
if (!this.textures.exists(battleUiIconTextureKey)) {
|
||||
const displaySize = this.campUiLength(size);
|
||||
const textureKey = battleUiIconTextureForSize(displaySize);
|
||||
if (!this.textures.exists(textureKey)) {
|
||||
const fallback = this.trackSortie(this.add.circle(x, y, size / 2, palette.gold, 0.18));
|
||||
fallback.setDepth(depth);
|
||||
return;
|
||||
}
|
||||
|
||||
const icon = this.trackSortie(this.add.image(x, y, battleUiIconTextureKey, battleUiIconFrames[iconKey]));
|
||||
icon.setDisplaySize(this.campUiLength(size), this.campUiLength(size));
|
||||
const icon = this.trackSortie(this.add.image(x, y, textureKey, battleUiIconFrames[iconKey]));
|
||||
icon.setDisplaySize(displaySize, displaySize);
|
||||
icon.setAlpha(alpha);
|
||||
icon.setDepth(depth);
|
||||
}
|
||||
|
||||
private renderCampBattleUiIcon(iconKey: BattleUiIconKey, x: number, y: number, size: number, alpha = 1) {
|
||||
const displaySize = this.campUiLength(size);
|
||||
const textureKey = battleUiIconTextureForSize(displaySize);
|
||||
if (!this.textures.exists(textureKey)) {
|
||||
return this.track(this.add.circle(x, y, size / 2, palette.gold, 0.18));
|
||||
}
|
||||
|
||||
const icon = this.track(this.add.image(x, y, textureKey, battleUiIconFrames[iconKey]));
|
||||
icon.setDisplaySize(displaySize, displaySize);
|
||||
icon.setAlpha(alpha);
|
||||
return icon;
|
||||
}
|
||||
|
||||
private unitClassIconKey(unit: UnitData): BattleUiIconKey {
|
||||
switch (unit.classKey) {
|
||||
case 'lord':
|
||||
@@ -16024,9 +16045,10 @@ export class CampScene extends Phaser.Scene {
|
||||
bg.setOrigin(0);
|
||||
bg.setDepth(depth);
|
||||
bg.setStrokeStyle(1, assigned > 0 ? palette.green : enabled ? palette.gold : 0x53606c, assigned > 0 ? 0.78 : enabled ? 0.5 : 0.28);
|
||||
this.renderSortieBattleUiIcon(supply.usableId, buttonX + 10, y + 10, 14, depth + 1, enabled ? 0.96 : 0.48);
|
||||
this.trackSortie(
|
||||
this.add.text(
|
||||
buttonX + (buttonWidth - 5) / 2,
|
||||
buttonX + (buttonWidth - 5) / 2 + 6,
|
||||
y + 5,
|
||||
`${supply.title} ${assigned}`,
|
||||
this.textStyle(9, assigned > 0 ? '#a8ffd0' : enabled ? '#c8d2dd' : '#77818c', true)
|
||||
@@ -21583,8 +21605,9 @@ export class CampScene extends Phaser.Scene {
|
||||
const bg = this.track(this.add.rectangle(x, y, width, 40, canBuy ? 0x151f2a : 0x111820, canBuy ? 0.94 : 0.76));
|
||||
bg.setOrigin(0);
|
||||
bg.setStrokeStyle(1, canBuy ? palette.gold : 0x53606c, canBuy ? 0.58 : 0.36);
|
||||
this.track(this.add.text(x + 10, y + 6, item.title, this.textStyle(13, canBuy ? '#f2e3bf' : '#7f8994', true)));
|
||||
this.track(this.add.text(x + 10, y + 23, `${item.price}금`, this.textStyle(11, canBuy ? '#d8b15f' : '#7f8994', true)));
|
||||
this.renderCampBattleUiIcon(item.usableId, x + 20, y + 20, 26, canBuy ? 1 : 0.5);
|
||||
this.track(this.add.text(x + 40, y + 6, item.title, this.textStyle(13, canBuy ? '#f2e3bf' : '#7f8994', true)));
|
||||
this.track(this.add.text(x + 40, y + 23, `${item.price}금`, this.textStyle(11, canBuy ? '#d8b15f' : '#7f8994', true)));
|
||||
|
||||
const button = this.track(this.add.rectangle(x + width - 42, y + 20, 60, 26, canBuy ? 0x1a2630 : 0x121922, canBuy ? 0.96 : 0.72));
|
||||
button.setStrokeStyle(1, canBuy ? palette.gold : 0x53606c, canBuy ? 0.72 : 0.4);
|
||||
@@ -21669,11 +21692,12 @@ export class CampScene extends Phaser.Scene {
|
||||
bg.setOrigin(0);
|
||||
bg.setStrokeStyle(1, enabled ? palette.gold : 0x53606c, enabled ? 0.62 : 0.38);
|
||||
|
||||
this.track(this.add.text(x + 14, y + 10, `${supply.title} x${amount}`, this.textStyle(16, amount > 0 ? '#f2e3bf' : '#7f8994', true)));
|
||||
this.renderCampBattleUiIcon(supply.usableId, x + 28, y + 31, 36, amount > 0 ? 1 : 0.46);
|
||||
this.track(this.add.text(x + 56, y + 10, `${supply.title} x${amount}`, this.textStyle(16, amount > 0 ? '#f2e3bf' : '#7f8994', true)));
|
||||
this.track(
|
||||
this.add.text(x + 14, y + 34, supply.description, {
|
||||
this.add.text(x + 56, y + 34, supply.description, {
|
||||
...this.textStyle(12, enabled ? '#c8d2dd' : '#77818c'),
|
||||
wordWrap: { width: width - 128, useAdvancedWrap: true }
|
||||
wordWrap: { width: width - 170, useAdvancedWrap: true }
|
||||
})
|
||||
);
|
||||
|
||||
@@ -22075,8 +22099,8 @@ export class CampScene extends Phaser.Scene {
|
||||
|
||||
private normalizedSortieItemAssignments(assignments?: CampaignSortieItemAssignments) {
|
||||
const selected = new Set(this.selectedSortieUnitIds);
|
||||
const validSupplyIds = new Set(campSupplies.map((supply) => supply.usableId));
|
||||
const remainingBySupply = new Map(campSupplies.map((supply) => [supply.usableId, this.inventoryAmount(supply.label)]));
|
||||
const validSupplyIds = new Set<string>(campSupplies.map((supply) => supply.usableId));
|
||||
const remainingBySupply = new Map<string, number>(campSupplies.map((supply) => [supply.usableId, this.inventoryAmount(supply.label)]));
|
||||
|
||||
return Object.entries(assignments ?? {}).reduce<CampaignSortieItemAssignments>((next, [unitId, stocks]) => {
|
||||
if (!selected.has(unitId)) {
|
||||
|
||||
Reference in New Issue
Block a user