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 * as exp from "constants"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; import { Attrs, GameScoreStats } from "./config/HeroAttrs"; import { count, time } from "console"; import { getLevelExp } from "../map/RogueConfig"; /** * 用远程数据覆盖本地数据(统一方法) * @param remoteData 远程数据(云端或本地调试) */ interface GameDate{ gold:number, heros:any, fight_hero:number, collection?: { talents: Record, skills: {uuid:0,count:0}, friend:{uuid:0,count:0}, } } interface CloudData { openid: string; data: GameDate; } /** 游戏模块 */ @ecs.register('SingletonModule') export class SingletonModuleComp extends ecs.Comp { /** 游戏初始化模块 */ 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, //商店购买 及 双倍奖励资源 meat:0, exp:0, task:0, noStop:false, } guides:any=[0,0,0,0,0] current_guide:number=0 fight_hero: number = 5001; // 单个出战英雄 heros:any= [5001,5002] monsters:any = []; vmdata: any = { game_over:false, game_pause:false, mission_data:{ mon_num:0,//怪物数量 hero_num:0,//英雄数量 wave_time_num:0,//波次时间 in_fight:false, fight_time:0,//战斗时间 level:1,//关卡等级 max_mission:4,//最大关卡 coin:0, time:15*60,//游戏时间 unlockCoin: 20, }, 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, // 吸血总量 // 资源统计 exp_total: 0, // 经验总数 gold_total: 0, // 金币总数 // 击杀统计 melee_kill_count: 0, // 近战怪击杀数量 remote_kill_count: 0, // 远程怪击杀数量 elite_kill_count: 0, // 精英怪击杀数量 boss_kill_count: 0, // Boss击杀数 } as GameScoreStats, hero:{ name:'', path:'', as:0, type:0, lv:1, exp:0, exp_max:100, exp_pre:0, hp:50, hp_max:100, mp:50, mp_max:100, def:0, ap:0, dis:0, crt:0, speed:0, skills:[], buff:[], tal:[], info:'', }, // 收集记录 collection: { talents: {} as Record, skill: {uuid:0,count:0}, friend:{uuid:0,count:0}, }, gold: 200, // 金币数据(MVVM绑定字段) }; /** * 更新英雄经验 * @param exp 获得的经验值 */ updateHeroExp(exp: number) { if (!this.vmdata.hero) return; this.vmdata.hero.exp += exp*20; // console.log('[smc] 英雄升级 经验:' + this.vmdata.hero.exp + ' 等级:' + this.vmdata.hero.lv + ' 上限:' + this.vmdata.hero.exp_max); // 确保 exp_max 初始化 if (this.vmdata.hero.exp_max <= 0) { this.vmdata.hero.exp_max = getLevelExp(this.vmdata.hero.lv || 1); } while (this.vmdata.hero.exp >= this.vmdata.hero.exp_max) { this.vmdata.hero.exp -= this.vmdata.hero.exp_max; this.vmdata.hero.lv++; // 更新下一级所需经验 this.vmdata.hero.exp_max = getLevelExp(this.vmdata.hero.lv); // 触发升级事件 oops.message.dispatchEvent(GameEvent.CanUpdateLv, { lv: this.vmdata.hero.lv }); } // 更新进度条显示 (0-1) if (this.vmdata.hero.exp_max > 0) { this.vmdata.hero.exp_pre = Math.floor(this.vmdata.hero.exp / this.vmdata.hero.exp_max * 100); } else { this.vmdata.hero.exp_pre = 0; } } /** * 记录天赋获取 * @param id 天赋ID */ addTalentRecord(id: number) { if (!this.vmdata.collection.talents[id]) { this.vmdata.collection.talents[id] = 0; } this.vmdata.collection.talents[id]++; console.log(`[SMC] 记录天赋获取: ID=${id}, 次数=${this.vmdata.collection.talents[id]}`); oops.message.dispatchEvent(GameEvent.UpdateCollection); } /** * 记录技能获取 * @param id 技能ID */ addSkillRecord(id: number) { if (!this.vmdata.collection.skill.uuid) { this.vmdata.collection.skill.uuid = id; } this.vmdata.collection.skill.count++; console.log(`[SMC] 记录技能获取: ID=${id}, 次数=${this.vmdata.collection.skill.count}`); oops.message.dispatchEvent(GameEvent.UpdateCollection); } /** * 记录好友获取 * @param id 好友ID */ addFriendHero(id: number) { if (!this.vmdata.collection.friend.uuid) { this.vmdata.collection.friend.uuid = id; } this.vmdata.collection.friend.count++; console.log(`[SMC] 记录好友获取: ID=${id}, 次数=${this.vmdata.collection.friend.count}`); oops.message.dispatchEvent(GameEvent.UpdateCollection); } vmAdd() { VM.add(this.vmdata, "data"); } reset() { for (var key in this.vmdata) { delete this.vmdata[key]; } } // ==================== 数据管理方法 ==================== /** * 判断是否为微信客户端 */ private isWxClient(): boolean { // 检查是否存在微信API return typeof wx !== 'undefined' && typeof (wx as any).getSystemInfoSync === 'function'; } finishGuide(index:number){ smc.guides[index]=1 //存储到远程服务器 后续再添加 } updateCloudData(){ let gemeDate=this.getGameDate() WxCloudApi.save(gemeDate).then((result) => { console.log('云端保存') if(result.result.code === 200) { console.log("保存成功",result.result) return true } else { console.warn(`[SMC]: 游戏数据增加失败: ${result.result.msg}`); return false } }).catch((error) => { console.error(`[SMC]: 增加游戏数据异常:`, error); return false }); return true } getCloudData(){ WxCloudApi.get().then(async (result) => { if(result.result.code === 200) { let data=result.result.data console.log(`[SMC]: 获取游戏数据成功:`, result.result); this.overrideLocalDataWithRemote(data) return true } else { console.warn(`[SMC]: 游戏数据增加失败`); return false } }).catch((error) => { console.error(`[SMC]: 获取游戏数据异常:`, error); }); } public async overrideLocalDataWithRemote(CloudData) { try { // 直接覆盖基础游戏数据 if (CloudData.openid) { this.openid=CloudData.openid } // 直接覆盖出战英雄配置 if (CloudData.data) { if(CloudData.data.gold) this.vmdata.gold=CloudData.data.gold if(CloudData.data.heros) this.heros=CloudData.data.heros if(CloudData.data.fight_hero) this.fight_hero=CloudData.data.fight_hero // 恢复收集记录 if(CloudData.data.collection) { this.vmdata.collection = CloudData.data.collection; } } } catch (error) { console.error(`[SMC]: 数据覆盖失败:`, error); } } getGameDate(){ return { gold:this.vmdata.gold, heros:this.heros, fight_hero:this.fight_hero, collection: this.vmdata.collection } } addHero(hero_uuid:number){ if(this.heros.indexOf(hero_uuid)==-1){ this.heros.push(hero_uuid) } if(this.isWxClient()){ let res = this.updateCloudData() if (res){ return true }else{ // 同步不成功,删除uuid this.heros.splice(this.heros.indexOf(hero_uuid), 1); oops.gui.toast("数据同步失败,已回滚操作"); return false } } return true } // 设置单个出战英雄 updateFihgtHero(heroId: number) { this.fight_hero = heroId; if(this.isWxClient()){ let res = this.updateCloudData() if (res){ return true }else{ return false } } return true } updateGold(gold:number){ this.vmdata.gold += gold; if(this.isWxClient()){ let res = this.updateCloudData() if (res){ oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) return true }else{ this.vmdata.gold -= gold return false } } oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) return true } /** * 更新主角英雄数据到 VM * @param heroAttrs 英雄属性组件 */ updateHeroInfo(heroAttrs: HeroAttrsComp) { if (!heroAttrs || !heroAttrs.is_master) return; const h = this.vmdata.hero; // 基础信息 h.name = heroAttrs.hero_name; h.type = heroAttrs.type; // 防止 ECS 旧数据覆盖 VM 新数据 (如果 VM 里的等级更高,说明刚升级还没同步到 ECS) if (heroAttrs.lv > h.lv) { h.lv = heroAttrs.lv; } else if (h.lv > heroAttrs.lv) { // 此时应该反向同步?或者等待 CanUpdateLv 事件处理 // 这里暂时保持 VM 的高等级,不被 ECS 覆盖 } else { h.lv = heroAttrs.lv; } // 动态属性 h.hp = Math.floor(heroAttrs.hp); h.mp = Math.floor(heroAttrs.mp); // 计算属性 h.hp_max = Math.floor(heroAttrs.Attrs[Attrs.HP_MAX] || 0); h.mp_max = Math.floor(heroAttrs.Attrs[Attrs.MP_MAX] || 0); h.def = Math.floor(heroAttrs.Attrs[Attrs.DEF] || 0); h.ap = Math.floor(heroAttrs.Attrs[Attrs.AP] || 0); h.dis = Math.floor(heroAttrs.Attrs[Attrs.DIS] || 0); h.speed = Math.floor(heroAttrs.Attrs[Attrs.SPEED] || 0); h.crt = Math.floor(heroAttrs.Attrs[Attrs.CRITICAL] || 0); h.as = Math.floor(heroAttrs.Attrs[Attrs.AS] || 0); } error(){ oops.gui.toast("数据处理异常,请重试或重新登录") } } export var smc: SingletonModuleComp = ecs.getSingleton(SingletonModuleComp);