Files
heros/assets/script/game/skills/SkillCom.ts
walkpan 6d5c768a30 refactor(game): 精简肉鸽模式关卡配置并优化怪物加载逻辑
- 调整SkillSet基础攻击技能参数,降低CD时间和技能消耗
- 更新HeroInfo中英雄和怪物的技能组合,替换为更合理的技能ID
- 注释掉部分法师及精英怪物的定义,简化怪物列表
- 优化Monster类load和hero_init方法,移除不再使用的增强属性和关卡倍数参数
- 精简MissionMonComp刷怪队列逻辑,移除增强属性和关卡倍数支持
- 调整RogueConfig,去除怪物增强属性相关代码,仅保留基础刷怪类型和数量配置
- 修正SkillCom中使用属性枚举的地方,使用统一Attrs枚举
- 清理代码注释和多余空行,提升代码规范性和可读性
2025-10-19 12:06:18 +08:00

274 lines
10 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 { _decorator,Collider2D ,Contact2DType,v3,IPhysics2DContact,Vec3, tween, math, RigidBody2D, Animation, Tween} from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { smc } from "../common/SingletonModuleComp";
import { GameEvent } from "../common/config/GameEvent";
import { Attrs, AType, DTType, EType, SkillSet, SType, TGroup } from "../common/config/SkillSet";
import { BoxSet, FacSet } from "../common/config/BoxSet";
import { HeroViewComp } from "../hero/HeroViewComp";
import { BezierMove } from "../BezierMove/BezierMove";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillCom')
@ecs.register('SkillCom')
export class SkillCom extends CCComp {
// 核心标识和配置
s_uuid:number = 0;
// 运行时状态(必须缓存的)
is_destroy:boolean = false;
startPos: Vec3 = v3(); // 起始位置
targetPos: Vec3 = v3(); // 目标位置
group:number = 0; //阵营
fac:number=0; //阵营
caster:any=null;
// 战斗相关运行时数据
ap:number=0;
burn_count:number=0;
burn_value:number=0;
stun_time:number=0;
stun_ratio:number=0;
frost_ratio:number=0;
frost_time:number=0;
run_time:number=0;
hited_time:number=0;
hit_count:number=0;
caster_crit:number=0;
caster_crit_d:number=0;
puncture:number=0;
puncture_damage:number=0;
debuff_up:number=0;
debuff_value:number=0;
debuff_count:number=0;
// 组件引用
anim:Animation=null;
tweenInstance:Tween<any> = null;
private moveDirection: Vec3 | null = null; // 添加一个属性来存储移动方向
// 缓存的配置对象(避免重复查找)
public skillConfig: any = null;
private isInitialized: boolean = false;
protected onLoad(): void {
}
private initializeSkillConfig() {
if (this.isInitialized) return;
// 缓存技能配置,避免重复查找
this.skillConfig = SkillSet[this.s_uuid];
if (!this.skillConfig) {
// console.error("[SkillCom] 技能配置不存在:", this.s_uuid);
return;
}
this.isInitialized = true;
// console.log("[SkillCom] 技能配置初始化完成:", this.s_uuid, this.skillConfig.name);
}
start() {
this.initializeSkillConfig();
if (!this.skillConfig) return;
this.node.setPosition(this.startPos.x,this.startPos.y,0)
this.anim=this.node.getComponent(Animation)
this.on(GameEvent.MissionEnd, this.doDestroy, this);
this.node.active = true;
let collider = this.getComponent(Collider2D);
if(collider) {
collider.group = this.group;
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
let bm=this.node.getComponent(BezierMove)
// //console.log(this.group +"技能 collider ",collider);
switch(this.skillConfig.AType){
case AType.parabolic:
this.node.angle +=10
// bm.speed=700
if(this.group==BoxSet.MONSTER) {bm.controlPointSide=-1 }
bm.rotationSmoothness=0.6
bm.moveTo(this.targetPos)
break;
case AType.linear:
let s_x=this.startPos.x
let s_y=this.startPos.y
let t_x=this.targetPos.x
let t_y=this.targetPos.y
// 设定目标x
this.targetPos.x = 400;
if(this.group == BoxSet.MONSTER) {
bm.controlPointSide = -1;
this.targetPos.x = -400;
}
// 计算斜率
const k = (t_y - s_y) / (t_x - s_x);
// 按直线公式计算新的y
this.targetPos.y = k * (this.targetPos.x - s_x) + s_y;
bm.controlPointOffset=0
bm.rotationSmoothness=0.6
bm.moveTo(this.targetPos);
break;
case AType.StartEnd:
// 2段位移先升高然后移到目的地
this.node.setPosition(this.startPos.x > 360?300:this.startPos.x,0,0)
this.do_anim()
break;
case AType.fixedEnd:
this.node.setPosition(this.targetPos.x > 360?300:this.targetPos.x,0,0)
this.do_anim()
break;
case AType.fixedStart: //
if(this.s_uuid==6001){
console.log("skillcom startPos",this.startPos)
}
this.node.setPosition(this.startPos.x > 360?300:this.startPos.x,0,0)
this.do_anim()
break;
}
}
do_anim(){
if(this.node.getComponent(Animation)){
let anim = this.node.getComponent(Animation);
//console.log("[SkillCom]:has anim",anim)
anim.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
}
}
onAnimationFinished(){
// console.log("[SkillCom]:onAnimationFinished",this.s_uuid)
if (!this.skillConfig) return;
if(this.skillConfig.EType==EType.timeEnd) return
if(this.skillConfig.SType!=SType.damage){
this.to_do_buff()
}
this.is_destroy=true
}
to_do_buff(){
if (!this.skillConfig) return;
switch(this.skillConfig.SType){
case SType.shield:
this.caster.add_shield(this.caster[Attrs.HP_MAX]*(100+this.skillConfig.buV/100))
break;
}
}
//单体伤害
single_damage(target:HeroViewComp,is_range:boolean=false){
// //console.log("[SkillCom]:onBeginContact hit_count:",this.hit_count,SkillSet[this.s_uuid].hit)
// if(this.hit_count > 0&&!is_range) this.ap=this.ap*(50+this.puncture_damage)/100 // 穿刺后 伤害减半,过滤范围伤害
if(target == null) return;
if (!this.skillConfig) return;
let ap=this.ap
if(this.hit_count > 0 &&!is_range ){
ap=ap*(50+this.puncture_damage)/100
}
target.do_atked(ap,this.caster_crit,this.caster_crit_d,
this.burn_count,this.burn_value,
this.stun_time,this.stun_ratio,
this.frost_time,this.frost_ratio,
this.skillConfig.AtkedType
) // ap 及暴击 属性已经在skill.ts 处理
// console.log("[SkillCom]:single_damage t:tp:rtp",this.node.position,this.targetPos,target.node.position)
if(this.skillConfig.debuff>0){
let debuff=this.skillConfig
let dev=debuff.deV*(100+this.debuff_value)/100
let deR=debuff.deR+this.debuff_up
dev=Math.round(dev*100)/100
let deC=debuff.deC+this.debuff_count //dec只作为次数叠加
// //console.log("[SkillCom]:debuff",this.skillConfig.name,debuff.debuff,deUP.deV,deUP.deC)
target.addDebuff(debuff.debuff)
}
this.hit_count++
// console.log("[SkillCom]:碰撞次数:技能次数:穿刺次数",this.hit_count,this.skillConfig.hit,this.puncture)
if(this.hit_count>=(this.skillConfig.hit+this.puncture)&&(this.skillConfig.DTType!=DTType.range)&&(this.skillConfig.EType!=EType.animationEnd)&&(this.skillConfig.EType!=EType.timeEnd)) this.is_destroy=true // 技能命中次数
}
onBeginContact (seCol: Collider2D, oCol: Collider2D) {
// console.log(this.scale+"碰撞开始 ",seCol,oCol);
if(seCol.node.position.x-oCol.node.position.x > 100 ) return
let target = oCol.getComponent(HeroViewComp)
if(oCol.group!=this.group){
if(target == null) return;
if (!this.skillConfig) return;
// console.log("[SkillCom]:onBeginContact oCol||seCol",oCol.node.position,seCol.node.position)
this.single_damage(target,this.skillConfig.DTType==DTType.range?true:false)
// this.ent.destroy()
}
}
update(deltaTime: number) {
// 确保配置已初始化(处理 update 可能先于 start 执行的情况)
if (!this.isInitialized) {
this.initializeSkillConfig();
if (!this.skillConfig) return;
}
if(smc.mission.pause) {
if(this.anim) this.anim.pause()
return;
}
if(this.anim) this.anim.resume()
if (!this.node || !this.node.isValid) return;
if(this.skillConfig.EType==EType.timeEnd){
this.run_time+=deltaTime
if(this.run_time>this.skillConfig.in){
// //console.log("[SkillCom]: timeEnd destroy",this.s_uuid,this.run_time)
this.is_destroy=true
}
}
//直线移动
// if(this.skillConfig.AType == AType.linear) this.startLinearMove(deltaTime);
this.toDestroy();
}
toDestroy() {
if(this.is_destroy){
if (this.ent) {
this.ent.destroy();
} else {
// 如果ent不存在直接销毁节点
if (this.node && this.node.isValid) {
this.node.destroy();
}
}
}
}
doDestroy(){
// //console.log("[SkillCom]:doDestroy")
this.is_destroy=true
}
to_console(value:any,value2:any=null,value3:any=null){
//console.log("[SkillCom]:["+this.s_name+this.s_uuid+"]:",value,value2,value3)
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.is_destroy = false;
this.startPos.set();
this.targetPos.set();
this.moveDirection = null; // 重置移动方向
this.skillConfig = null; // 清除配置缓存
this.isInitialized = false; // 重置初始化状态
// 先移除所有碰撞回调
const collider = this.getComponent(Collider2D);
if (collider) {
collider.off(Contact2DType.BEGIN_CONTACT);
}
this.scheduleOnce(() => {
this.node.destroy();
}, 0);
}
}