Files
MatchMaster/assets/pyramid/scripts/PyramidSettlement.ts
T
2026-10-12 15:00:49 +08:00

81 lines
4.5 KiB
TypeScript

const { ccclass, property } = cc._decorator;
const ICONS = { 1001: "coin", 2001: "freeze", 2002: "hammer", 2003: "magic", 2005: "infinite_health" };
const REWARD_ORDER = [1001, 2001, 2003, 2002, 2005];
/** An unclaimed settlement list. Only the claim button requests a deposit. */
@ccclass
export default class PyramidSettlement extends cc.Component {
@property(cc.SpriteAtlas) numberAtlas: cc.SpriteAtlas = null;
private finished: (claim: boolean) => void | Promise<void> = null;
private claiming = false;
show(notice: any, done: (claim: boolean) => void | Promise<void>): void {
this.finished = done;
const panel = this.node.getChildByName("panel"), host = this.node.parent;
const fit = Math.min(host.width / this.node.width, host.height / this.node.height);
panel.setScale(fit);
const claim = panel.getChildByName("claim"), rewards = claim.getChildByName("rewards");
const slots = rewards.getChildByName("topRow").children.concat(rewards.getChildByName("bottomRow").children);
const goods = notice.goods.slice().sort((a, b) => REWARD_ORDER.indexOf(a.id) - REWARD_ORDER.indexOf(b.id));
slots.forEach((slot, index) => {
const good = goods[index]; slot.active = !!good; if (!good) return;
const item = slot.getChildByName("item");
item.getChildByName("icon").children.forEach(icon => { icon.active = icon.name === ICONS[good.id]; });
this.amount(item.getChildByName("amount"), good);
});
claim.getChildByName("closeButton").on("click", this.close, this);
claim.getChildByName("claimButton").on("click", this.claim, this);
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.back, this);
}
private amount(target: cc.Node, good: any): void {
target.removeAllChildren();
const lines: string[][] = [];
const append = (value: number, unit?: string) => {
const names = String(value).split("").map(digit => "big_" + digit);
if (good.id !== 1001 && good.id !== 2005) names.unshift("big_cheng");
if (unit) names.push(unit);
lines.push(names);
};
if (good.id === 2005) {
const minutes = Math.floor(good.count / 60), hours = Math.floor(minutes / 60);
if (hours) append(hours, "big_xiaoshi");
if (minutes % 60 || !hours) append(minutes % 60, "big_fenzhong");
} else append(good.count);
target.x = 0;
const icon = target.parent.getChildByName("icon").getChildByName("infinite_health");
icon.y = lines.length === 2 ? 58 : 0;
let maxWidth = 0;
const height = good.id === 2005 ? 45 : 54;
lines.forEach((names, row) => {
const frames = names.map(name => this.numberAtlas.getSpriteFrame(name));
const widths = frames.map(frame => height * frame.getRect().width / frame.getRect().height);
const width = widths.reduce((sum, n) => sum + n, 0) + (widths.length - 1) * 2;
maxWidth = Math.max(maxWidth, width);
let x = -width / 2;
frames.forEach((frame, index) => {
const digit = new cc.Node(names[index]); target.addChild(digit);
const sprite = digit.addComponent(cc.Sprite); sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM; sprite.spriteFrame = frame;
digit.setContentSize(widths[index], height); digit.x = x + widths[index] / 2; x += widths[index] + 2;
digit.y = ((lines.length - 1) / 2 - row) * 50;
});
});
// Parent item is scaled to 0.7: allow 180 visible pixels inside the 206px card.
// This keeps five-digit coins and three-digit tool counts at the same font size.
target.setScale(Math.min(1, (180 / target.parent.scaleX) / maxWidth));
}
private back = (event: cc.Event.EventKeyboard): void => {
if (event.keyCode === cc.macro.KEY.escape || event.keyCode === 6) this.close();
};
private close(): void {
if (this.claiming) return;
const done = this.finished; this.finished = null; if (done) void done(false);
}
private async claim(): Promise<void> {
if (this.claiming || !this.finished) return;
this.claiming = true;
try { await this.finished(true); this.finished = null; }
catch (_) { /* The host shows the error and retains the list for another claim attempt. */ }
finally { this.claiming = false; }
}
onDestroy(): void { cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.back, this); }
}