You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/script/manager/EmolumentDataManager.ts

231 lines
8.5 KiB

import { UIID } from '../game/ConfigRes';
import { ConstNumType } from '../game/GameDataEnums';
import { DailyWinStats } from './DailyWinStats';
import { RankDataManager } from './RankDataManager';
/**
* 每日俸禄:仅用「待领星级 + 待领胜场 + 快照日期」驱动弹窗与领取。
* - 当日战斗累计待领(尚无待领时首胜新建);快照日期标为今日,当日不弹
* - 已有跨日未领待领则保留不覆盖、不继续累加(隔日不上线到第 N 天仍有效)
* - 跨天且待领为空时写入昨日星级与胜场(快照日期标为昨日)
* - 除账号首日外,每日首登进 Home 且快照早于今日、胜场 > 0 → 弹 PopEmolument
* - 领取后清空
*/
export class EmolumentDataManager {
/** 本进程是否已尝试过自动弹俸禄窗(防 MainUI / 大厅重复弹) */
private static _autoPopAttempted = false;
/**
* 跨天:待领为空时写入昨日星级与胜场;已有待领不覆盖(含隔日未上线)。
* 新号 / 清档首登、从未战斗的玩家不写入(避免默认 1 星误弹俸禄)。
*/
static onCrossDay(): void {
if (this.hasPending()) {
return;
}
if (gg.data.IsFirstLogin) {
return;
}
if (!this._hasBattleRecord()) {
return;
}
const stars = RankDataManager.getPlayerRankStars();
const wins = DailyWinStats.getYesterdayWins();
if (!(stars > 0)) return;
this._writePending(stars, wins, this._yesterdayKey());
}
/** 是否存在待领俸禄(以星级字段为准) */
static hasPending(): boolean {
return this.getSnapStars() > 0;
}
/** 当日首次登录是否应自动弹俸禄窗 */
static shouldPopOnFirstLoginToday(): boolean {
return this.shouldPopOnHomeEnter();
}
/**
* Home 进入时是否应弹俸禄窗:
* 非账号首日 + 每日首登 + 待领可领 + 胜场 > 0 + 快照日期早于今日;GM 待弹除外。
*/
static shouldPopOnHomeEnter(): boolean {
if (Number(gg.data.doc.gmAwaitEmolumentPop) === 1) return this.canClaim();
if (gg.data.IsFirstLogin) return false;
if (!gg.data.IsFirstLoginToday) return false;
if (!this.canClaim()) return false;
if (!(this.getSnapWins() > 0)) return false;
return this._isSnapReadyToPop();
}
/** 是否可领取俸禄 */
static canClaim(): boolean {
return this.hasPending();
}
/** Home 就绪:满足条件时弹 PopEmolument */
static tryPopPanelIfNeeded(): void {
if (this._autoPopAttempted) return;
if (!this.shouldPopOnHomeEnter()) return;
this._autoPopAttempted = true;
gg.data.doc.gmAwaitEmolumentPop = 0;
gg.data.saveLocal();
void gg.ui.popPanel(UIID.PopEmolument);
}
/** 待领星级(总星数,0=无) */
static getSnapStars(): number {
return Math.max(0, Math.floor(Number(gg.data.doc.emolumentSnapStars) || 0));
}
/** 待领胜场 */
static getSnapWins(): number {
return Math.max(0, Math.floor(Number(gg.data.doc.emolumentSnapWins) || 0));
}
/** 段位表 Rank.reward 金币(道具 id|数量) */
static getRankTierGold(stars?: number): number {
const totalStars = Math.max(1, Math.floor(Number(stars ?? this.getSnapStars()) || 0));
return RankDataManager.parseRankTierMoneyReward(totalStars);
}
/** 胜场奖励金币(Const 26 进度 + Const 27 系数,向下取整) */
static calcWinRewardGold(wins?: number): number {
const w = Math.max(0, Math.floor(Number(wins ?? this.getSnapWins()) || 0));
if (w <= 0) return 0;
const thresholds = gg.data.table.getConstArray(ConstNumType.DailyWinProgress);
const coefs = gg.data.table.getConstArray(ConstNumType.DailyWinRewardCoef);
const t1 = Math.floor(Number(thresholds[0]) || 0);
const t2 = Math.floor(Number(thresholds[1]) || 0);
const c1 = Number(coefs[0]) || 0;
const c2 = Number(coefs[1]) || 0;
if (!(t1 > 0) || !(c1 > 0)) {
console.warn('[Emolument] Const 26/27 配置无效', thresholds, coefs);
return 0;
}
if (!(t2 > t1)) {
console.warn('[Emolument] Const 26 第二档须大于第一档', t1, t2);
return 0;
}
if (!(c2 > 0)) {
console.warn('[Emolument] Const 27 第二系数无效', coefs);
return 0;
}
if (w < t1) {
return Math.floor(w * c1);
}
const cappedWins = w > t2 ? t2 : w;
return Math.floor(t1 * c1 + (cappedWins - t1) * c2);
}
/**
* 战斗结算后同步待领:须本局传星才新建待领;仅「当日快照」继续累加,跨日未领快照冻结。
* @param starsChanged 本局是否已传星(RankDataManager.applyBattleResult 为 true)
*/
static syncAfterBattle(playerWin: boolean, starsChanged: boolean): void {
const stars = RankDataManager.getPlayerRankStars();
if (!(stars > 0)) return;
const today = DailyWinStats.todayKey();
if (!this.hasPending()) {
if (!playerWin || !starsChanged) return;
this._writePending(stars, 1, today);
return;
}
if (this._getSnapDate() !== today) {
return;
}
if (starsChanged) {
gg.data.doc.emolumentSnapStars = stars;
}
if (playerWin) {
gg.data.doc.emolumentSnapWins = this.getSnapWins() + 1;
}
}
/** 领取俸禄:段位金币 + 胜场金币入账,成功后清空两字段 */
static claim(): number | null {
if (!this.canClaim()) return null;
const rankGold = this.getRankTierGold();
const winGold = this.calcWinRewardGold();
const total = rankGold + winGold;
if (total > 0) {
gg.data.addMoney(total);
}
this._clearPending();
gg.data.saveLocal();
return total;
}
static async ensureTable(): Promise<void> {
await RankDataManager.ensureTable();
}
/**
* GM:写入俸禄待领快照(日期标昨日)、标今日首次登录并重置自动弹窗(重新进 Home 弹 PopEmolument)。
* @returns 是否写入有效待领(stars > 0)
*/
static gmPrepareFirstLoginPopTest(stars: number, wins: number): boolean {
const snapStars = Math.max(0, Math.floor(Number(stars) || 0));
const snapWins = Math.max(0, Math.floor(Number(wins) || 0));
if (!(snapStars > 0)) {
console.warn('[Emolument] GM 待领星级须 > 0');
return false;
}
this._writePending(snapStars, snapWins, this._yesterdayKey());
this._autoPopAttempted = false;
gg.data.IsFirstLoginToday = true;
gg.data.doc.gmAwaitEmolumentPop = 1;
return true;
}
/** 快照是否已到可弹日(日期早于今日;旧档无日期视为可弹) */
private static _isSnapReadyToPop(): boolean {
const snapDate = this._getSnapDate();
if (!snapDate) return true;
return snapDate !== DailyWinStats.todayKey();
}
/** 待领快照日期 YYYYMMDD */
private static _getSnapDate(): string {
return String(gg.data.doc.emolumentSnapDate ?? '').trim();
}
/** 昨日日期键 YYYYMMDD */
private static _yesterdayKey(): string {
const d = new Date(gg.data.getCurentTime2());
d.setDate(d.getDate() - 1);
const y = d.getFullYear();
const m = `${d.getMonth() + 1}`.padStart(2, '0');
const day = `${d.getDate()}`.padStart(2, '0');
return `${y}${m}${day}`;
}
/** 是否有过任意一场匹配战斗(胜或负) */
private static _hasBattleRecord(): boolean {
const wins = Math.max(0, Math.floor(Number(gg.data.doc.matchWinCount) || 0));
const loses = Math.max(0, Math.floor(Number(gg.data.doc.matchLoseCount) || 0));
return wins + loses > 0;
}
/** 写入待领星级、胜场与快照日期 */
private static _writePending(stars: number, wins: number, date: string): void {
gg.data.doc.emolumentSnapStars = Math.max(0, Math.floor(Number(stars) || 0));
gg.data.doc.emolumentSnapWins = Math.max(0, Math.floor(Number(wins) || 0));
gg.data.doc.emolumentSnapDate = String(date ?? '').trim();
}
/** 领取后清空待领 */
private static _clearPending(): void {
gg.data.doc.emolumentSnapStars = 0;
gg.data.doc.emolumentSnapWins = 0;
gg.data.doc.emolumentSnapDate = '';
}
}