Files
pixelheros/assets/script/game/common/SingletonModuleComp.ts
walkpan 1cce4ce361 feat(英雄系统): 添加英雄复活机制并控制怪物行为
实现英雄复活功能,当英雄死亡且有复活次数时延迟复活
新增is_reviving状态标记复活中状态
英雄死亡或复活时通过stop_mon_action控制怪物停止刷新和移动
2026-01-03 11:17:04 +08:00

295 lines
9.2 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 { 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 } from "./config/HeroAttrs";
import { time } from "console";
import { getLevelExp } from "../map/RogueConfig";
/**
* 用远程数据覆盖本地数据(统一方法)
* @param remoteData 远程数据(云端或本地调试)
*/
interface GameDate{
gold:number,
heros:any,
fight_hero:number
}
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,
};
guides:any=[0,0,0,0,0]
current_guide:number=0
data:any={
score:0,
mission:1,
diamond:100, //商店购买 及 双倍奖励资源
meat:0,
exp:0,
task: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,//游戏时间
},
hero:{
name:'',
path:'',
as:0,
type:0,
lv:0,
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:'',
},
gold: 200, // 金币数据MVVM绑定字段
};
/**
* 更新英雄经验
* @param exp 获得的经验值
*/
updateHeroExp(exp: number) {
if (!this.vmdata.hero) return;
this.vmdata.hero.exp += exp;
// 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;
}
}
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
}
} catch (error) {
console.error(`[SMC]: 数据覆盖失败:`, error);
}
}
getGameDate(){
return {gold:this.vmdata.gold,heros:this.heros,fight_hero:this.fight_hero}
}
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);