diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 090adf48..4343636b 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -192,13 +192,13 @@ export const SkillSet: Record = { buffs:[],debuffs:[],info:"对前方目标造成100%攻击的伤害", }, 6002: { - uuid:6002,name:"电击",sp_name:"atk_s3",icon:"1173",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"max",DTType:DTType.single, + uuid:6002,name:"电击",sp_name:"atk_s4",icon:"1173",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"max",DTType:DTType.single, ap:100,hit_count:1,hitcd:0.2,speed:720,with:0, ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.collision, buffs:[],debuffs:[],info:"对前方目标造成150%攻击的伤害", }, 6003: { - uuid:6003,name:"闪击",sp_name:"atk_s1",icon:"1173",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"max",DTType:DTType.single, + uuid:6003,name:"闪击",sp_name:"atk_s3",icon:"1173",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"max",DTType:DTType.single, ap:100,hit_count:1,hitcd:0.2,speed:720,with:0, ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, buffs:[],debuffs:[],info:"对前方目标造成150%攻击的伤害", @@ -226,39 +226,64 @@ export const SkillSet: Record = { ap:100,hit_count:1,hitcd:0.2,speed:720,with:0, ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", - }, + }, 6008: { - uuid:6008,name:"水球",sp_name:"ball_water",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + uuid:6008,name:"光箭",sp_name:"arrow_big_yellow",icon:"1135",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:1,hitcd:0.2,speed:720,with:0, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.animationEnd, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6009: { + uuid:6009,name:"冰球",sp_name:"ball_ice",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6010: { + uuid:6010,name:"冰锥",sp_name:"ball_forst",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6011: { + uuid:6011,name:"火球",sp_name:"ball_fire",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6012: { + uuid:6012,name:"光波",sp_name:"ball_guang",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6013: { + uuid:6013,name:"半月波",sp_name:"ball_light",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, + buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", + }, + 6014: { + uuid:6014,name:"月波",sp_name:"ball_gquan",icon:"1126",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, ap:100,hit_count:2,hitcd:0.3,speed:720,with:90, ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", }, //============================= ====== 基础buff ====== ========================== 6100-6199 - 6100: { - uuid:6100,name:"治疗",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Self,TType:TType.LowestHP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, - ap:30,hit_count:1,hitcd:0.2,speed:720,with:0, - ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - kind:SkillKind.Heal,buffs:[],debuffs:[],info:"治疗自己,回复30%最大生命值", - }, - 6101:{ - uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,TType:TType.LowestHP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + 6100:{ + uuid:6100,name:"魔法盾",sp_name:"buff_wind",icon:"1255",TGroup:TGroup.Self,TType:TType.LowestHP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, ap:30,hit_count:1,hitcd:0.2,speed:720,with:0, ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, kind:SkillKind.Shield,buffs:[],debuffs:[],info:"获得30%最大生命值的护盾,持续60秒", }, - 6102:{ - uuid:6102,name:"强壮",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Team,TType:TType.HighestAP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, + 6101: { + uuid:6101,name:"治疗",sp_name:"buff_wind",icon:"1292",TGroup:TGroup.Self,TType:TType.LowestHP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, ap:30,hit_count:1,hitcd:0.2,speed:720,with:0, ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - kind:SkillKind.Support,buffs:[10001],debuffs:[],info:"增加目标10%攻击力,持续30秒", - }, - 6103:{ - uuid:6103,name:"群体强壮",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Team,TType:TType.HighestAP,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.range, - ap:30,hit_count:1,hitcd:0.2,speed:720,with:0, - ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, - kind:SkillKind.Support,buffs:[10011],debuffs:[],info:"增加目标10%攻击力,持续30秒", + kind:SkillKind.Heal,buffs:[],debuffs:[],info:"治疗自己,回复30%最大生命值", }, + // ========== 怪物基础技能 ========== 6200-6299 6201: { uuid:6201, name:"怪物近战", sp_name:"atk_s1", icon:"3036", diff --git a/assets/script/game/common/config/heroSet.ts b/assets/script/game/common/config/heroSet.ts index 40690338..e51237fb 100644 --- a/assets/script/game/common/config/heroSet.ts +++ b/assets/script/game/common/config/heroSet.ts @@ -139,7 +139,6 @@ export interface heroInfo { // dis: number; // 攻击距离(像素) speed: number; // 移动速度(像素/秒) skills: number[]; // 携带技能ID列表 - buff: BuffConf[]; // 自带buff配置(通常为空,由技能动态添加) info: string; // 描述文案 } @@ -158,73 +157,52 @@ export const HeroInfo: Record = { // ========== 英雄角色 ========== 5001:{uuid:5001,name:"盾战士",icon:"1001",path:"hk1", fac:FacSet.HERO, kind:1,as:1,ss:5, - type:HType.Melee,lv:1,hp:300,ap:25,speed:120,skills:[6001,6004], - buff:[],info:"盾战士"}, + type:HType.Melee,lv:1,hp:300,ap:25,speed:120,skills:[6001,6004],info:"盾战士"}, 5002:{uuid:5002,name:"奥术法师",icon:"1001",path:"hm2", fac:FacSet.HERO, kind:2,as:1,ss:5, - type:HType.Long,lv:1,hp:150,ap:40,speed:95,skills:[6003,6101], - buff:[],info:"奥术法师"}, + type:HType.Long,lv:1,hp:150,ap:40,speed:95,skills:[6003,6101],info:"奥术法师"}, 5003:{uuid:5003,name:"射手",icon:"1001",path:"ha1", fac:FacSet.HERO, kind:2,as:1,ss:5, - type:HType.Long,lv:1,hp:180,ap:30,speed:140,skills:[6005,6006], - buff:[],info:"射手"}, + type:HType.Long,lv:1,hp:180,ap:30,speed:140,skills:[6005,6006],info:"射手"}, 5005:{uuid:5005,name:"牧师",icon:"1001",path:"hh1", fac:FacSet.HERO, kind:2,as:1,ss:5, - type:HType.Long,lv:1,hp:160,ap:25,speed:100,skills:[6003,6100], - buff:[],info:"牧师"}, + type:HType.Long,lv:1,hp:160,ap:25,speed:100,skills:[6003,6100],info:"牧师"}, 5004:{uuid:5004,name:"火焰法师",icon:"1001",path:"hm1", fac:FacSet.HERO, kind:2,as:1,ss:5, - type:HType.Long,lv:1,hp:150,ap:45,speed:90,skills:[6003,6101], - buff:[],info:"火焰法师"}, + type:HType.Long,lv:1,hp:150,ap:45,speed:90,skills:[6003,6101],info:"火焰法师"}, 5006:{uuid:5006,name:"召唤法师",icon:"1001",path:"hz1", fac:FacSet.HERO, kind:2,as:1,ss:5, - type:HType.Long,lv:1,hp:200,ap:20,speed:105,skills:[6003,6101], - buff:[],info:"召唤法师"}, + type:HType.Long,lv:1,hp:200,ap:20,speed:105,skills:[6003,6101],info:"召唤法师"}, 5007:{uuid:5007,name:"刺客",icon:"1001",path:"hc1", fac:FacSet.HERO, kind:1,as:1,ss:5, - type:HType.Melee,lv:1,hp:140,ap:50,speed:180,skills:[6001,6004], - buff:[],info:"刺客"}, + type:HType.Melee,lv:1,hp:140,ap:50,speed:180,skills:[6001,6004],info:"刺客"}, - // 1. 基础近战型 5201:{uuid:5201,name:"兽人战士",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Melee,lv:1,hp:60,ap:8,speed:180,skills:[6003], - buff:[],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"}, + type:HType.Melee,lv:1,hp:60,ap:8,speed:180,skills:[6001,6003],info:"标准炮灰:确保英雄能完成3次普攻积累天赋计数"}, // 2. 快速突击型 5301:{uuid:5301,name:"兽人斥候",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:1.2,ss:10, - type:HType.Melee,lv:1,hp:40,ap:12,speed:400,skills:[6003], - buff:[],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"}, + type:HType.Melee,lv:1,hp:40,ap:12,speed:400,skills:[6001,6003],info:"快速突击:极高移速贴脸,检测护盾(7102)刷新率"}, // 3. 重型坦克型 5401:{uuid:5401,name:"兽人卫士",icon:"1001",path:"mo3", fac:FacSet.MON, kind:1,as:5.0,ss:10, - type:HType.Melee,lv:1,hp:200,ap:15,speed:60,skills:[6003], - buff:[],info:"重型坦克:数值墙,检测玩家破甲(7008)与持续输出"}, + type:HType.Melee,lv:1,hp:200,ap:15,speed:60,skills:[6001,6003],info:"重型坦克:数值墙,检测玩家破甲(7008)与持续输出"}, // 4. 远程骚扰型 5501:{uuid:5501,name:"兽人射手",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Long,lv:1,hp:50,ap:10,speed:90,skills:[6203], - buff:[],info:"远程骚扰:跨屏打击,迫使阵地分散或移动英雄"}, + type:HType.Long,lv:1,hp:50,ap:10,speed:90,skills:[6001,6003],info:"远程骚扰:跨屏打击,迫使阵地分散或移动英雄"}, // 5. 特殊机制型 5601:{uuid:5601,name:"兽人自爆兵",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Melee,lv:1,hp:80,ap:200,speed:220,skills:[6003], - buff:[],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"}, - // 召唤师:持续召唤小怪(后续可在技能系统中实现 SType.zhaohuan) + type:HType.Melee,lv:1,hp:80,ap:200,speed:220,skills:[6001,6003],info:"特殊机制:极端伤害,漏怪即秒杀,检测减伤(7103)"}, 5602:{uuid:5602,name:"兽人召唤师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Long,lv:1,hp:150,ap:10,speed:100,skills:[6003], - buff:[],info:"战术目标:持续召唤小怪,检测英雄大招清场频率"}, - // 治疗者:为周围怪物回血(此处以提升治疗效果和生命回复为基础被动) + type:HType.Long,lv:1,hp:150,ap:10,speed:100,skills:[6001,6003],info:"战术目标:持续召唤小怪,检测英雄大招清场频率"}, 5603:{uuid:5603,name:"兽人祭司",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Long,lv:1,hp:150,ap:10,speed:105,skills:[6003], - buff:[],info:"战术目标:为怪群回血,检测玩家沉默(7006)覆盖率"}, - // 光环怪:为周围怪物提供增益(此处以Buff效果提升与移动速度提升为基础被动) - // Attrs.BUFF_UP=60 (RATIO=1),Attrs.SPEED=63 (RATIO=1) - 5604:{uuid:5604,name:"兽人图腾师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, - type:HType.Long,lv:1,hp:150,ap:10,speed:110,skills:[6003], - buff:[],info:"战术目标:提供加速光环,改变怪群推进节奏"}, + type:HType.Long,lv:1,hp:150,ap:10,speed:105,skills:[6001,6003],info:"战术目标:为怪群回血,检测玩家沉默(7006)覆盖率"}, + 5604:{uuid:5604,name:"兽人图腾师",icon:"1001",path:"mo1", fac:FacSet.MON, kind:1,as:3.0,ss:10, + type:HType.Long,lv:1,hp:150,ap:10,speed:110,skills:[6001,6003],info:"战术目标:提供加速光环,改变怪群推进节奏"}, // 6. 精英/BOSS型 5701:{uuid:5701,name:"兽人首领(BOSS)",icon:"1001",path:"mo4", fac:FacSet.MON, kind:1,as:2.5,ss:10, - type:HType.Melee,lv:3,hp:2000,ap:60,speed:120,skills:[6003], - buff:[],info:"终极考验:极高HP,检测大招重置与辐射协同输出"}, + type:HType.Melee,lv:3,hp:2000,ap:60,speed:120,skills:[6001,6003],info:"终极考验:极高HP,检测大招重置与辐射协同输出"}, }; diff --git a/assets/script/game/hero/Mon.ts b/assets/script/game/hero/Mon.ts index b15602a7..e1843d9e 100644 --- a/assets/script/game/hero/Mon.ts +++ b/assets/script/game/hero/Mon.ts @@ -6,7 +6,6 @@ import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet"; import { HeroInfo } from "../common/config/heroSet"; import { HeroAttrsComp } from "./HeroAttrsComp"; import { BuffConf, SkillSet } from "../common/config/SkillSet"; -import { getMonAttr, MonType } from "../map/RogueConfig"; import { HeroViewComp } from "./HeroViewComp"; import { MoveComp } from "./MoveComp"; import { mLogger } from "../common/Logger"; @@ -89,7 +88,7 @@ export class Monster extends ecs.Entity { } /** 加载角色 */ - load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001,lv:number=1,monType:MonType=MonType.NORMAL, buffs: BuffConf[] = [],is_call=false, lane: number = 0, spawnOrder: number = 0, gameTime: number = 0) { + load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001, is_boss:boolean=false) { scale=-1 let size=1 var scene = smc.map.MapView.scene; @@ -124,23 +123,18 @@ export class Monster extends ecs.Entity { // 设置 View 层属性(表现相关) view.scale = scale; view.box_group = BoxSet.MONSTER; - - // 设置 Model 层属性(数据相关) + // 设置 Model 层属性 基础属性 model.hero_uuid = uuid; model.hero_name = hero.name; - model.lv = lv; + model.hp = model.hp_max = hero.hp; + model.ap = hero.ap; + model.speed = hero.speed; // 使用成长后的速度 model.type = hero.type; model.fac = FacSet.MON; - model.is_boss = monType == MonType.BOSS; + model.is_boss =is_boss if(!model.is_boss){ model.is_kalami = true; } - // 根据等级和类型获取怪物属性(使用新的动态成长系统) - const {hp,ap, speed} = getMonAttr(lv, uuid, monType, gameTime); - // 初始化属性数组 - model.hp = model.hp_max = hp; - model.ap = ap; - model.speed = speed; // 使用成长后的速度 model.a_cd_max=hero.as model.s_cd_max=hero.ss model.back_chance=FightSet.BACK_CHANCE @@ -148,22 +142,20 @@ export class Monster extends ecs.Entity { if(hero.skills[0]) model.atk_id=hero.skills[0] if(hero.skills[1]) model.skill_id=hero.skills[1] model.updateSkillDistanceCache(model.skill_id || model.atk_id); - + //根据刷怪控制脚本对ap和hp进行加强 + + this.add(view); // 重置视图状态(对象池复用时必须) view.init(); - oops.message.dispatchEvent("monster_load",this) - // 初始化移动参数,包括线路和生成顺序 const move = this.get(MoveComp); move.reset(); move.direction = -1; // 向左移动 move.targetX = Math.max(-320, Math.min(320, pos.x)); move.baseY = pos.y; - move.lane = lane; // 设置线路标识 - move.spawnOrder = spawnOrder; // 设置生成顺序 smc.vmdata.mission_data.mon_num++ } diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index 3c63a721..3e0b8ed0 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -4,7 +4,6 @@ import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/modu import { smc } from "../common/SingletonModuleComp"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; -import { MonsterCost, MonType, calculateMonsterGold, getLevelExp, calculateMonsterExp, SpecialMonsterSchedule } from "./RogueConfig"; import { GameEvent } from "../common/config/GameEvent"; import { HeroViewComp } from "../hero/HeroViewComp"; import { UIID } from "../common/config/GameUIConfig"; @@ -69,7 +68,6 @@ export class MissionComp extends CCComp { private readonly skillViewMatcher = ecs.allOf(SkillView); // 记录已触发的特殊刷怪索引 - private spawnedSpecialIndices: Set = new Set(); onLoad(){ this.on(GameEvent.MissionStart,this.mission_start,this) @@ -86,9 +84,7 @@ export class MissionComp extends CCComp { if(smc.mission.stop_mon_action) return smc.vmdata.mission_data.fight_time+=dt this.FightTime-=dt - // 检查特殊刷怪时间 - this.checkSpecialSpawns(smc.vmdata.mission_data.fight_time); this.update_time(); this.updateMemoryPanel(dt); } @@ -106,90 +102,6 @@ export class MissionComp extends CCComp { this.lastTimeStr = str; } } - private checkSpecialSpawns(fightTime: number) { - SpecialMonsterSchedule.forEach((item, index) => { - if (!this.spawnedSpecialIndices.has(index) && fightTime >= item.time) { - this.spawnedSpecialIndices.add(index); - mLogger.log(this.debugMode, 'MissionComp', ` 触发特殊刷怪: ${item.desc}`); - oops.message.dispatchEvent("SpawnSpecialMonster", { - uuid: item.uuid, - type: item.type, - level: item.level - }); - } - }); - } - - private initMemoryPanel() { - if (!this.showMemoryPanel || !this.time_node) return; - let panel = this.time_node.getChildByName("mem_panel"); - if (!panel) { - panel = new Node("mem_panel"); - panel.parent = this.time_node; - panel.setPosition(0, -32, 0); - } - let label = panel.getComponent(Label); - if (!label) { - label = panel.addComponent(Label); - } - label.fontSize = 16; - label.lineHeight = 20; - this.memoryLabel = label; - } - - private updateMemoryPanel(dt: number) { - if (!this.showMemoryPanel || !this.memoryLabel) return; - this.perfDtAcc += dt; - this.perfFrameCount += 1; - this.memoryRefreshTimer += dt; - if (this.memoryRefreshTimer < 0.5) return; - this.memoryRefreshTimer = 0; - let heroCount = 0; - ecs.query(this.heroViewMatcher).forEach(() => { - heroCount++; - }); - let skillCount = 0; - ecs.query(this.skillViewMatcher).forEach(() => { - skillCount++; - }); - const monPool = Monster.getPoolStats(); - const skillPool = Skill.getPoolStats(); - const perf = (globalThis as any).performance; - const heapBytes = perf && perf.memory ? perf.memory.usedJSHeapSize : 0; - let heapMB = heapBytes > 0 ? heapBytes / 1024 / 1024 : -1; - if (heapMB > 0 && this.heapBaseMB < 0) { - this.heapBaseMB = heapMB; - this.heapPeakMB = heapMB; - this.heapTrendBaseMB = heapMB; - this.heapTrendTimer = 0; - } - if (heapMB > this.heapPeakMB) { - this.heapPeakMB = heapMB; - } - this.heapTrendTimer += 0.5; - if (heapMB > 0 && this.heapTrendBaseMB > 0 && this.heapTrendTimer >= 10) { - const deltaMB = heapMB - this.heapTrendBaseMB; - this.heapTrendPerMinMB = (deltaMB / this.heapTrendTimer) * 60; - this.heapTrendBaseMB = heapMB; - this.heapTrendTimer = 0; - } - const heapText = heapMB > 0 ? heapMB.toFixed(1) : "N/A"; - const heapDeltaText = this.heapBaseMB > 0 && heapMB > 0 ? (heapMB - this.heapBaseMB).toFixed(1) : "N/A"; - const heapPeakText = this.heapPeakMB > 0 ? this.heapPeakMB.toFixed(1) : "N/A"; - const avgDt = this.perfFrameCount > 0 ? this.perfDtAcc / this.perfFrameCount : 0; - const fps = avgDt > 0 ? 1 / avgDt : 0; - this.perfDtAcc = 0; - this.perfFrameCount = 0; - const text = - `Heap:${heapText}MB Δ:${heapDeltaText} Peak:${heapPeakText}\n` + - `Trend:${this.heapTrendPerMinMB.toFixed(2)}MB/min\n` + - `Perf dt:${(avgDt * 1000).toFixed(1)}ms fps:${fps.toFixed(1)}\n` + - `Ent H:${heroCount} S:${skillCount}\n` + - `Pool M:${monPool.total}(${monPool.paths}) K:${skillPool.total}(${skillPool.paths})`; - if (text === this.lastMemoryText) return; - this.lastMemoryText = text; - this.memoryLabel.string = text; - } //奖励发放 @@ -197,18 +109,7 @@ export class MissionComp extends CCComp { // 奖励发放 } - - cal_gold_reward(data: any, type: MonType) { - const cost = MonsterCost[data.uuid] || 1; - const level = data.lv || 1; - let add_gold = calculateMonsterGold(data.uuid, level, type); - smc.updateGold(add_gold, false); - } - - do_hero_dead(event:any,data:any){ - - } -do_ad(){ + do_ad(){ if(this.ad_back()){ oops.message.dispatchEvent(GameEvent.AD_BACK_TRUE) smc.vmdata.mission_data.refresh_count+=FightSet.MORE_RC @@ -216,11 +117,8 @@ do_ad(){ oops.message.dispatchEvent(GameEvent.AD_BACK_FALSE) } } - ad_back(){ - return true - } @@ -298,7 +196,6 @@ do_ad(){ this.FightTime=FightSet.FiIGHT_TIME this.rewards=[] // 改为数组,用于存储掉落物品列表 this.revive_times = 1; // 每次任务开始重置复活次数 - this.spawnedSpecialIndices.clear(); // 重置特殊刷怪记录 this.lastTimeStr = ""; this.lastTimeSecond = -1; this.memoryRefreshTimer = 0; @@ -336,8 +233,82 @@ do_ad(){ Skill.clearPools(); } + /** 性能监控相关代码 */ + + private initMemoryPanel() { + if (!this.showMemoryPanel || !this.time_node) return; + let panel = this.time_node.getChildByName("mem_panel"); + if (!panel) { + panel = new Node("mem_panel"); + panel.parent = this.time_node; + panel.setPosition(0, -32, 0); + } + let label = panel.getComponent(Label); + if (!label) { + label = panel.addComponent(Label); + } + label.fontSize = 16; + label.lineHeight = 20; + this.memoryLabel = label; + } + + + private updateMemoryPanel(dt: number) { + if (!this.showMemoryPanel || !this.memoryLabel) return; + this.perfDtAcc += dt; + this.perfFrameCount += 1; + this.memoryRefreshTimer += dt; + if (this.memoryRefreshTimer < 0.5) return; + this.memoryRefreshTimer = 0; + let heroCount = 0; + ecs.query(this.heroViewMatcher).forEach(() => { + heroCount++; + }); + let skillCount = 0; + ecs.query(this.skillViewMatcher).forEach(() => { + skillCount++; + }); + const monPool = Monster.getPoolStats(); + const skillPool = Skill.getPoolStats(); + const perf = (globalThis as any).performance; + const heapBytes = perf && perf.memory ? perf.memory.usedJSHeapSize : 0; + let heapMB = heapBytes > 0 ? heapBytes / 1024 / 1024 : -1; + if (heapMB > 0 && this.heapBaseMB < 0) { + this.heapBaseMB = heapMB; + this.heapPeakMB = heapMB; + this.heapTrendBaseMB = heapMB; + this.heapTrendTimer = 0; + } + if (heapMB > this.heapPeakMB) { + this.heapPeakMB = heapMB; + } + this.heapTrendTimer += 0.5; + if (heapMB > 0 && this.heapTrendBaseMB > 0 && this.heapTrendTimer >= 10) { + const deltaMB = heapMB - this.heapTrendBaseMB; + this.heapTrendPerMinMB = (deltaMB / this.heapTrendTimer) * 60; + this.heapTrendBaseMB = heapMB; + this.heapTrendTimer = 0; + } + const heapText = heapMB > 0 ? heapMB.toFixed(1) : "N/A"; + const heapDeltaText = this.heapBaseMB > 0 && heapMB > 0 ? (heapMB - this.heapBaseMB).toFixed(1) : "N/A"; + const heapPeakText = this.heapPeakMB > 0 ? this.heapPeakMB.toFixed(1) : "N/A"; + const avgDt = this.perfFrameCount > 0 ? this.perfDtAcc / this.perfFrameCount : 0; + const fps = avgDt > 0 ? 1 / avgDt : 0; + this.perfDtAcc = 0; + this.perfFrameCount = 0; + const text = + `Heap:${heapText}MB Δ:${heapDeltaText} Peak:${heapPeakText}\n` + + `Trend:${this.heapTrendPerMinMB.toFixed(2)}MB/min\n` + + `Perf dt:${(avgDt * 1000).toFixed(1)}ms fps:${fps.toFixed(1)}\n` + + `Ent H:${heroCount} S:${skillCount}\n` + + `Pool M:${monPool.total}(${monPool.paths}) K:${skillPool.total}(${skillPool.paths})`; + if (text === this.lastMemoryText) return; + this.lastMemoryText = text; + this.memoryLabel.string = text; + } + + - /** 视图层逻辑代码分离演示 */ /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { diff --git a/assets/script/game/map/MissionMonComp.ts b/assets/script/game/map/MissionMonComp.ts index f54131b6..7ca39dd1 100644 --- a/assets/script/game/map/MissionMonComp.ts +++ b/assets/script/game/map/MissionMonComp.ts @@ -7,11 +7,8 @@ import { MonStart } from "../common/config/heroSet"; import { smc } from "../common/SingletonModuleComp"; import { GameEvent } from "../common/config/GameEvent"; // 导入新的肉鸽配置 -import { getCurrentWave, MonType, WaveConfig } from "./RogueConfig"; import { BuffConf } from "../common/config/SkillSet"; -import { IndexSet, FacSet, BoxSet } from "../common/config/GameSet"; -import { HeroAttrsComp } from "../hero/HeroAttrsComp"; -import { Attrs } from "../common/config/HeroAttrs"; +import {BoxSet } from "../common/config/GameSet"; const { ccclass, property } = _decorator; /** 视图层对象 */ @@ -24,26 +21,18 @@ export class MissionMonCompComp extends CCComp { // 刷怪队列 (主要用于特殊事件插队) private MonQueue: Array<{ uuid: number, - position: number, - type: MonType, level: number, - buffs: BuffConf[] }> = []; private spawnCount: number = 0; // 召唤计数器 - /** 全局生成顺序计数器,用于层级管理 */ private globalSpawnOrder: number = 0; - /** 游戏进行时间(秒) */ private gameTime: number = 0; - /** 波次刷怪计时器 */ private waveTimer: number = 0; - /** 队列处理计时器 */ private queueTimer: number = 0; - onLoad(){ this.on(GameEvent.FightReady,this.fight_ready,this) this.on(GameEvent.NewWave,this.fight_ready,this) @@ -59,16 +48,11 @@ export class MissionMonCompComp extends CCComp { private onSpawnSpecialMonster(event: string, args: any) { if (!args) return; mLogger.log(this.debugMode, 'MissionMonComp', `[MissionMonComp] 收到特殊刷怪指令:`, args); - // 插入队列 this.MonQueue.push({ uuid: args.uuid, - position: args.position !== undefined ? args.position : 2, // 默认中间 - type: args.type, level: args.level, - buffs: args.buffs || [] }); - // 立即触发一次队列检查 (可选,让 update 尽快处理) this.queueTimer = 1.0; } @@ -98,112 +82,28 @@ export class MissionMonCompComp extends CCComp { // 累加游戏时间 this.gameTime += dt; - // 获取当前波次配置 - const currentWave = getCurrentWave(this.gameTime); - // 1. 优先处理特殊怪队列 - if (this.MonQueue.length > 0) { - this.queueTimer += dt; - // 队列出怪速度快于普通波次 (0.5秒一只) - if (this.queueTimer >= 0.5) { - this.spawnNextFromQueue(); - this.queueTimer = 0; - } - } - // 2. 处理波次自然刷怪 - this.waveTimer += dt; - if (this.waveTimer >= currentWave.spawnInterval) { - this.waveTimer = 0; - - // 检查同屏数量限制 - if (smc.vmdata.mission_data.mon_num < currentWave.maxActive) { - this.spawnWaveMonster(currentWave); - } - } - } - - /** - * 从当前波次配置生成并生成怪物 - */ - private spawnWaveMonster(wave: WaveConfig) { - if (!wave.weights || wave.weights.length === 0) return; - - // 权重随机算法 - const totalWeight = wave.weights.reduce((sum, item) => sum + item.weight, 0); - let random = Math.random() * totalWeight; - let selectedUuid = wave.weights[0].uuid; - let selectedType = wave.weights[0].type || MonType.NORMAL; - - for (const item of wave.weights) { - random -= item.weight; - if (random <= 0) { - selectedUuid = item.uuid; - selectedType = item.type || MonType.NORMAL; - break; - } - } - - // 随机位置 (0-4) - const position = Math.floor(Math.random() * 5); - - // 等级随时间增长 (每分钟+1级) - const level = Math.floor(this.gameTime / 60) + 1; - - this.addMonster( - selectedUuid, - position, - selectedType, - level, - [], - this.gameTime - ); - - this.spawnCount++; - } - - /** - * 从队列中生成下一个怪物 - */ - private spawnNextFromQueue() { - if (this.MonQueue.length === 0) return; - - const monsterData = this.MonQueue.shift(); - if (monsterData) { - this.addMonster( - monsterData.uuid, - monsterData.position, - monsterData.type, - monsterData.level, - monsterData.buffs, - this.gameTime - ); - this.spawnCount++; - } + } + private addMonster( uuid: number = 1001, i: number = 0, - monType: number = 0, - lv: number = 1, - buffs: BuffConf[] = [], - gameTime: number = 0 ) { let mon = ecs.getEntity(Monster); let scale = -1; - const x = MonStart.START_X + Math.floor(i / 4) * MonStart.START_I; let y = BoxSet.GAME_LINE; - let lane = 0; - + let pos: Vec3 = v3(x, y, 0); // 递增全局生成顺序 - 溢出保护 this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999; // 生成怪物 - mon.load(pos, scale, uuid, lv, monType, buffs, false, lane, this.globalSpawnOrder, gameTime); + mon.load(pos, scale, uuid, false); } /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ diff --git a/assets/script/game/map/RogueConfig.ts b/assets/script/game/map/RogueConfig.ts index f806f0de..8b137891 100644 --- a/assets/script/game/map/RogueConfig.ts +++ b/assets/script/game/map/RogueConfig.ts @@ -1,347 +1 @@ -/** - * 肉鸽模式配置脚本 - 增强版 (Wave System) - * - * 功能说明: - * - 采用 15 个小波次(每分钟 1 波) - * - 整合进 3 个大的节奏阶段:构筑期、磨合期、极限期 - * - 废弃动态预算,使用确定性波次配置 - * - * @author 游戏开发团队 - * @version 3.0 波次重构版 - * @date 2025-10-19 - */ -import { HeroInfo } from "../common/config/heroSet"; -import { mLogger } from "../common/Logger"; - -/** - * 怪物类型枚举 - */ -export enum MonType { - NORMAL = 0, // 普通怪物 - ELITE = 1, // 精英怪物 - BOSS = 2 // Boss怪物 -} - -/** - * 怪物配置接口 (用于生成实例) - */ -export interface IMonsConfig { - uuid: number; // 怪物ID - type: MonType; // 怪物类型 - level: number; // 等级 - position?: number; // 位置(可选) - buffs?: any[]; // buff列表(可选) -} - -/** - * 怪物属性接口 - */ -export interface MonAttrs { - hp: number; - ap: number; - speed: number; - exp?: number; - gold?: number; -} - -/** - * 成长类型枚举 - */ -enum GrowthType { - EXPONENTIAL = 1.15, // 指数级 - HP - LINEAR = 1.05, // 线性 - AP - LOGARITHMIC = 0.3 // 对数级 - Speed -} - -/** - * 刷怪权重接口 - */ -export interface SpawnWeight { - uuid: number; - weight: number; - type?: MonType; // 默认为 NORMAL -} - -/** - * 波次配置接口 - */ -export interface WaveConfig { - waveId: number; // 波次ID (1-15) - name: string; // 波次名称 - duration: number; // 持续时间 (秒),通常为60 - spawnInterval: number; // 刷怪间隔 (秒) - maxActive: number; // 同屏最大怪物数 - weights: SpawnWeight[]; // 怪物权重池 -} - -// 怪物ID映射 (方便阅读) -const MON_IDS = { - WARRIOR: 5201, // 战士 - ASSASSIN: 5301, // 斥候 - TANK: 5401, // 卫士 - ARCHER: 5501, // 射手 - BOMBER: 5601, // 自爆兵 - SUMMONER: 5602, // 召唤师 - HEALER: 5603, // 祭司 - TOTEM: 5604, // 图腾师 - BOSS: 5701 // 首领 -}; - -/** - * 全局波次配置表 (15波) - */ -export const RogueWaves: WaveConfig[] = [ - // --- 第一阶段:构筑期 (0-5min) --- - { - waveId: 1, name: "热身", duration: 60, spawnInterval: 2.0, maxActive: 5, - weights: [{ uuid: MON_IDS.WARRIOR, weight: 100 }] - }, - { - waveId: 2, name: "加速", duration: 60, spawnInterval: 1.8, maxActive: 6, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 80 }, - { uuid: MON_IDS.ASSASSIN, weight: 20 } - ] - }, - { - waveId: 3, name: "堆叠", duration: 60, spawnInterval: 1.6, maxActive: 7, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 60 }, - { uuid: MON_IDS.ASSASSIN, weight: 40 } - ] - }, - { - waveId: 4, name: "硬度测试", duration: 60, spawnInterval: 1.5, maxActive: 8, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 50 }, - { uuid: MON_IDS.ASSASSIN, weight: 30 }, - { uuid: MON_IDS.TANK, weight: 20 } - ] - }, - { - waveId: 5, name: "精英首秀", duration: 60, spawnInterval: 1.5, maxActive: 8, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 40 }, - { uuid: MON_IDS.ASSASSIN, weight: 40 }, - { uuid: MON_IDS.TANK, weight: 20 } - // 注意:第5分钟会触发固定事件刷精英怪,这里只配普通怪 - ] - }, - - // --- 第二阶段:磨合期 (5-10min) --- - { - waveId: 6, name: "远程威胁", duration: 60, spawnInterval: 1.4, maxActive: 10, - weights: [ - { uuid: MON_IDS.TANK, weight: 30 }, - { uuid: MON_IDS.ARCHER, weight: 40 }, - { uuid: MON_IDS.WARRIOR, weight: 30 } - ] - }, - { - waveId: 7, name: "铁桶阵", duration: 60, spawnInterval: 1.3, maxActive: 10, - weights: [ - { uuid: MON_IDS.TANK, weight: 50 }, - { uuid: MON_IDS.ARCHER, weight: 50 } - ] - }, - { - waveId: 8, name: "续航干扰", duration: 60, spawnInterval: 1.2, maxActive: 12, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 30 }, - { uuid: MON_IDS.TANK, weight: 20 }, - { uuid: MON_IDS.ARCHER, weight: 30 }, - { uuid: MON_IDS.HEALER, weight: 20 } - ] - }, - { - waveId: 9, name: "走位测试", duration: 60, spawnInterval: 1.2, maxActive: 12, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 40 }, - { uuid: MON_IDS.BOMBER, weight: 30 }, // 自爆兵 - { uuid: MON_IDS.ARCHER, weight: 30 } - ] - }, - { - waveId: 10, name: "中场Boss", duration: 60, spawnInterval: 5.0, maxActive: 3, - // Boss战期间,只刷少量护卫,Boss由事件触发 - weights: [ - { uuid: MON_IDS.TANK, weight: 100 } - ] - }, - - // --- 第三阶段:极限期 (10-15min) --- - { - waveId: 11, name: "混乱开端", duration: 60, spawnInterval: 1.0, maxActive: 15, - weights: [ - { uuid: MON_IDS.SUMMONER, weight: 20 }, - { uuid: MON_IDS.TOTEM, weight: 20 }, - { uuid: MON_IDS.WARRIOR, weight: 30 }, - { uuid: MON_IDS.ARCHER, weight: 30 } - ] - }, - { - waveId: 12, name: "全家桶", duration: 60, spawnInterval: 0.9, maxActive: 18, - weights: [ - { uuid: MON_IDS.WARRIOR, weight: 15 }, - { uuid: MON_IDS.ASSASSIN, weight: 15 }, - { uuid: MON_IDS.TANK, weight: 15 }, - { uuid: MON_IDS.ARCHER, weight: 15 }, - { uuid: MON_IDS.BOMBER, weight: 15 }, - { uuid: MON_IDS.HEALER, weight: 10 }, - { uuid: MON_IDS.SUMMONER, weight: 15 } - ] - }, - { - waveId: 13, name: "精英小队", duration: 60, spawnInterval: 1.0, maxActive: 15, - weights: [ - { uuid: MON_IDS.TANK, weight: 40 }, - { uuid: MON_IDS.ARCHER, weight: 40 }, - { uuid: MON_IDS.WARRIOR, weight: 20, type: MonType.ELITE } // 尝试混入精英 - ] - }, - { - waveId: 14, name: "绝地求生", duration: 60, spawnInterval: 0.6, maxActive: 20, - weights: [ - { uuid: MON_IDS.ASSASSIN, weight: 50 }, - { uuid: MON_IDS.BOMBER, weight: 50 } - ] - }, - { - waveId: 15, name: "终局", duration: 60, spawnInterval: 3.0, maxActive: 5, - // 最终Boss战,只刷少量精英护卫 - weights: [ - { uuid: MON_IDS.TANK, weight: 100, type: MonType.ELITE } - ] - } -]; - -// 精英怪和Boss刷新时间配置 (时间单位: 秒) -// 注意:这里的时间点应与波次结束/开始对应 -export const SpecialMonsterSchedule = [ - { time: 4 * 60 + 50, uuid: MON_IDS.WARRIOR, type: MonType.ELITE, level: 5, desc: "5分钟前夕: 精英战士" }, - { time: 9 * 60 + 55, uuid: MON_IDS.BOSS, type: MonType.BOSS, level: 15, desc: "10分钟: 兽人首领" }, - { time: 14 * 60 + 55, uuid: MON_IDS.BOSS, type: MonType.BOSS, level: 30, desc: "15分钟: 最终Boss" } -]; - -/** - * 获取当前时间的波次配置 - * @param timeInSeconds 游戏时间 (秒) - */ -export function getCurrentWave(timeInSeconds: number): WaveConfig { - const waveIndex = Math.min(Math.floor(timeInSeconds / 60), 14); - return RogueWaves[waveIndex]; -} - -/** - * 怪物消耗点数配置 (用于经验/金币计算) - */ -export const MonsterCost: Record = { - 5201: 1, // 兽人战士 (Warrior) - 5301: 3, // 兽人斥候 (Assassin) - 5401: 5, // 兽人卫士 (Tank) - 5501: 4, // 兽人射手 (Remote) - 5601: 10, // 兽人自爆兵 (Mechanic) - 5602: 8, // 兽人召唤师 - 5603: 6, // 兽人祭司 (Healer) - 5604: 6, // 兽人图腾师 - 5701: 50, // 兽人首领 (Elite/Boss) -}; - -/** - * 计算波次因子 - * @param stage 当前波次 - * @param timeInSeconds 游戏进行时间(秒) - * @returns 波次因子 (0-1之间,15分钟时达到最大) - */ -function calculateWaveFactor(stage: number, timeInSeconds: number = 0): number { - const MAX_GAME_TIME = 15 * 60; // 15分钟 = 900秒 - const effectiveTime = timeInSeconds || (stage * 60); - const factor = Math.min(effectiveTime / MAX_GAME_TIME, 1.0); - return factor; -} - -/** - * 应用成长公式到基础属性 - */ -function applyGrowthFormula(baseStat: number, waveFactor: number, growthType: GrowthType): number { - // 基础倍率:15分钟成长约 21 倍 (1 + 1.0 * 20) - const TIME_SCALING = 20; - const growthMultiplier = Math.pow(1 + waveFactor * TIME_SCALING, growthType); - return Math.floor(baseStat * growthMultiplier); -} - -/** - * 获取怪物动态成长属性 - * @param stage 当前波次 (这里复用为等级或忽略) - * @param uuid 怪物ID - * @param monType 怪物类型 - * @param timeInSeconds 游戏进行时间(秒) - * @returns 怪物属性 - */ -export function getMonAttr(stage: number, uuid: number, monType: MonType = MonType.NORMAL, timeInSeconds: number = 0): MonAttrs { - const baseMonster = HeroInfo[uuid]; - if (!baseMonster) { - mLogger.warn(true, 'RogueConfig', `[RogueConfig] 未找到怪物ID: ${uuid}`); - return { hp: 100, ap: 10, speed: 100 }; - } - - // 计算波次因子 - const waveFactor = calculateWaveFactor(0, timeInSeconds); - - // 动态质量系数:初始 1.5倍 -> 15分钟 6.0倍 - // 大幅降低初始强度(原固定5.0),随时间线性增强 - const qualityRatio = 1.5 + (4.5 * waveFactor); - - // 根据怪物类型应用额外的倍率 - let typeMultiplier = 1.0; - if (monType === MonType.ELITE) { - typeMultiplier = 2.0; // 精英怪2倍属性 - } else if (monType === MonType.BOSS) { - typeMultiplier = 5.0; // Boss 5倍属性 - } - - // 应用不同的成长类型 (应用质量系数) - const hp = applyGrowthFormula(baseMonster.hp, waveFactor, GrowthType.EXPONENTIAL) * typeMultiplier * qualityRatio; - const ap = applyGrowthFormula(baseMonster.ap, waveFactor, GrowthType.LINEAR) * typeMultiplier * qualityRatio; - const speed = applyGrowthFormula(baseMonster.speed, waveFactor, GrowthType.LOGARITHMIC); - - return { - hp: Math.floor(hp), - ap: Math.floor(ap), - speed: Math.floor(speed) - }; -} - -/** - * 无限等级经验配置 - */ -export function getLevelExp(level: number): number { - const baseExp = 100; - const growthFactor = 1.2; - return Math.floor(baseExp * Math.pow(growthFactor, level - 1)); -} - -/** - * 计算怪物掉落金币 - */ -export function calculateMonsterGold(uuid: number, level: number, type: MonType): number { - const cost = MonsterCost[uuid] || 1; - let danger_ratio = 1 + cost * 0.1; - - let type_ratio = 1; - if(type == MonType.BOSS) type_ratio = 10; - else if(type == MonType.ELITE) type_ratio = 3; - - const baseGold = 10; - let gold = Math.floor((baseGold * type_ratio * danger_ratio + level) * 8); - return gold; -} - -/** - * 计算怪物经验值 - */ -export function calculateMonsterExp(uuid: number, level: number): number { - const cost = MonsterCost[uuid] || 1; - return Math.max(1, Math.floor(cost * 1.0 * Math.pow(1.15, level - 1) * 8)); -}