Files
pixelheros/assets/script/game/common/SingletonModuleComp.ts
walkpan 2ee8eb097e feat(talent): 引入天赋碎片系统替换通用天赋点
- 新增 TalentFragmentType 枚举和 TalentFragmentInfo 接口定义碎片类型
- 在 SingletonModuleComp 中新增 talent_fragments 字段存储碎片库存,talent_points 改为可选字段以兼容旧存档
- 为每个天赋配置 fragmentType 指定升级所需的具体碎片类型
- 修改 TalentsComp 升级逻辑,从消耗天赋点改为扣除对应类型的碎片
- 重置天赋功能现在返还已消耗的碎片而非天赋点
- 更新界面显示,展示碎片库存摘要和具体消耗
2026-05-08 08:38:01 +08:00

278 lines
8.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { sys } from "cc";
import { VM } from "../../../../extensions/oops-plugin-framework/assets/libs/model-view/ViewModel";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { Initialize } from "../initialize/Initialize";
import { GameMap } from "../map/GameMap";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi";
import { GameEvent } from "./config/GameEvent";
import { GameScoreStats } from "./config/HeroAttrs";
import { mLogger } from "./Logger";
import { TalentFragmentType, TalentType } from "./config/TalentSet";
import { gameDataSync } from "./GameDataSync";
import { FightSet } from "./config/GameSet";
/**
* 用远程数据覆盖本地数据(统一方法)
* @param remoteData 远程数据(云端或本地调试)
*/
export interface GameDate{
gold:number,
timestamp?: number, // 用于比对本地与云端数据的最新状态
collection?: {
talents: Partial<Record<TalentType, number>>,
player_level: number,
player_exp: number,
talent_fragments: Partial<Record<TalentFragmentType, number>>,
talent_points?: number,
}
}
export interface CloudData {
openid: string;
data: GameDate;
}
/** 游戏模块 */
@ecs.register('SingletonModule')
export class SingletonModuleComp extends ecs.Comp {
private debugMode: boolean = false;
/** 游戏初始化模块 */
initialize: Initialize = null!;
/** 游戏地图 */
map: GameMap = null!;
openid:string=''
mission:any={
status:0, //0:未开始 1:进行中 2:胜利 3:失败
play:false,
pause:false,
in_select:false,
in_fight:false,
stop_mon_action:false,
};
data:any={
score:0,
mission:1,
diamond:100, //商店购买 及 双倍奖励资源
gold:1000,
task:0,
noStop:false,
showInfo:true,
}
guides:any=[0,0,0,0,0]
current_guide:number=0
collection: {
talents: Partial<Record<TalentType, number>>;
player_level: number;
player_exp: number;
talent_fragments: Partial<Record<TalentFragmentType, number>>;
talent_points?: number;
} = {
talents: {}, // 存储各个天赋的等级: { talent_id: level }
player_level: 1, // 玩家等级
player_exp: 0, // 玩家当前经验
talent_fragments: {}, // 当前拥有的天赋碎片库存
talent_points: 0, // 兼容旧存档的历史字段
};
vmdata: any = {
game_over:false,
game_pause:false,
mission_data:{
mon_num:0,//怪物数量
hero_num:0,//英雄数量
hero_max_num:FightSet.HERO_MAX_NUM,//英雄可召唤上限
hero_extend_max_num:FightSet.HERO_MAX_NUM + 1,//英雄可拓展上限
wave_time_num:0,//波次时间
in_fight:false,
fight_time:0,//战斗时间
level:1,//关卡等级
max_mission:4,//最大关卡
coin:0,
time:15*60,//游戏时间
},
scores: {
score: 0, // 基础得分
// 战斗统计
crt_count: 0, // 暴击次数
wf_count: 0, // 风怒次数
dod_count: 0, // 闪避次数
back_count: 0, // 击退次数
stun_count: 0, // 击晕次数
freeze_count: 0, // 冰冻次数
// 伤害统计
total_dmg: 0, // 总伤害
atk_count: 0, // 攻击次数
avg_dmg: 0, // 平均伤害
thorns_dmg: 0, // 反伤伤害
crit_dmg_total: 0, // 暴击伤害总额
// 生存统计
heal_total: 0, // 治疗总量
lifesteal_total: 0, // 吸血总量
shield_block_count: 0,
dead_trigger_count: 0,
// 资源统计
exp_total: 0, // 经验总数
gold_total: 0, // 金币总数
gold_earned: 0,
gold_spent: 0,
refresh_count: 0,
refresh_hit_count: 0,
// 击杀统计
melee_kill_count: 0, // 近战怪击杀数量
remote_kill_count: 0, // 远程怪击杀数量
elite_kill_count: 0, // 精英怪击杀数量
boss_kill_count: 0, // Boss击杀数
// 战绩统计
wave_win_count: 0,
wave_remain_monsters: 0,
wave_all_alive_count: 0,
passed_wave_20: false,
highest_dmg: 0,
score_combat: 0,
score_output: 0,
score_defense: 0,
score_build: 0,
score_efficiency: 0,
achieved_highlights: [],
} as GameScoreStats,
gold: 0, // 金币数据MVVM绑定字段
};
vmAdd() {
VM.add(this.vmdata, "data");
// mLogger.log(this.debugMode, 'SMC', "[MissionComp]局内数据初始化",smc.vmdata.mission_data)
}
reset() {
for (var key in this.vmdata) {
delete this.vmdata[key];
}
}
/**
* 重置单局评分数据
* 在每次新战斗开始时调用,确保上一局的得分不会带入新一局
*/
resetScores() {
this.vmdata.scores = {
score: 0,
crt_count: 0,
wf_count: 0,
dod_count: 0,
back_count: 0,
stun_count: 0,
freeze_count: 0,
total_dmg: 0,
atk_count: 0,
avg_dmg: 0,
thorns_dmg: 0,
crit_dmg_total: 0,
heal_total: 0,
lifesteal_total: 0,
shield_block_count: 0,
dead_trigger_count: 0,
exp_total: 0,
gold_total: 0,
gold_earned: 0,
gold_spent: 0,
refresh_count: 0,
refresh_hit_count: 0,
melee_kill_count: 0,
remote_kill_count: 0,
elite_kill_count: 0,
boss_kill_count: 0,
wave_win_count: 0,
wave_remain_monsters: 0,
wave_all_alive_count: 0,
passed_wave_20: false,
highest_dmg: 0,
score_combat: 0,
score_output: 0,
score_defense: 0,
score_build: 0,
score_efficiency: 0,
achieved_highlights: [],
} as GameScoreStats;
}
// ==================== 数据管理方法 ====================
/**
* 判断是否为微信客户端
*/
isWxClient(): boolean {
return gameDataSync.isWxClient();
}
updateCloudData(){
return gameDataSync.updateCloudData();
}
getCloudData(){
gameDataSync.getCloudData();
}
public async overrideLocalDataWithRemote(cloudData: any) {
try {
// 直接覆盖基础游戏数据
if (cloudData.openid) {
this.openid = cloudData.openid;
}
// 直接覆盖出战英雄配置
if (cloudData.data) {
const data = cloudData.data;
// 同步金币
if (data.gold !== undefined) {
this.vmdata.gold = data.gold;
}
// 恢复收集记录
if (data.collection) {
const remoteCol = data.collection;
if (remoteCol.talents) this.collection.talents = remoteCol.talents;
if (typeof remoteCol.player_level === 'number') this.collection.player_level = remoteCol.player_level;
if (typeof remoteCol.player_exp === 'number') this.collection.player_exp = remoteCol.player_exp;
if (remoteCol.talent_fragments) this.collection.talent_fragments = remoteCol.talent_fragments;
if (typeof remoteCol.talent_points === 'number') this.collection.talent_points = remoteCol.talent_points;
}
}
// 触发UI更新
oops.message.dispatchEvent(GameEvent.GOLD_UPDATE);
} catch (error) {
mLogger.error(this.debugMode, 'SMC', `[SMC]: 数据覆盖失败:`, error);
}
}
getGameDate(){
let data: GameDate = {
gold: this.vmdata.gold,
collection: this.collection,
timestamp: Date.now() // 每次获取当前数据结构时都附带最新的时间戳
};
return data;
}
updateGold(gold:number, is_sync: boolean = true){
this.vmdata.gold += gold;
if (is_sync) {
gameDataSync.markDataDirty();
}
oops.message.dispatchEvent(GameEvent.GOLD_UPDATE)
return true
}
}
export var smc: SingletonModuleComp = ecs.getSingleton(SingletonModuleComp);