Files
heros/assets/script/game/skill/SkillView.ts
panw 8e0d09fc98 refactor(战斗系统): 优化伤害计算与技能释放逻辑,下一步 将伤害信标处理,改为队列处理
- 移除HeroViewComp中的调试日志
- 缩短技能释放前摇时间从0.3秒到0.1秒
- 重构Skill类,清理无用导入并优化属性传递
- 改进HeroAtkSystem,添加伤害数据深拷贝避免重复处理
- 完善SkillView,增加技能结束类型处理并优化伤害应用逻辑
2025-10-31 16:43:27 +08:00

195 lines
7.7 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, Animation, CCInteger, Collider2D, Contact2DType, UITransform, v3, Vec3 } 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 { HeroViewComp } from "../hero/HeroViewComp";
import { DTType, EType, RType, SkillConfig, SkillSet } from "../common/config/SkillSet";
import { BezierMove } from "../BezierMove/BezierMove";
import { BoxSet, FacSet } from "../common/config/BoxSet";
import { DmgDataCom, SDataCom } from "./SDataCom";
import { SMoveDataComp } from "./SMoveComp";
import { Attrs } from "../common/config/HeroAttrs";
import { MonMoveComp } from "../hero/MonMove";
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { HeroMoveComp } from "../hero/HeroMove";
const { ccclass, property } = _decorator;
/** 视图层对象 */
@ccclass('SkillViewComp')
@ecs.register('SkillView', false)
export class SkillView extends CCComp {
/** 视图层逻辑代码分离演示 */
@property({ type: CCInteger })
atk_x: number = 0
@property({ type: CCInteger })
atk_y: number = 0
@property({ type: CCInteger })
runType: RType = 0 //技能运行类型 0-线性 1-贝塞尔 2-开始位置固定 3-目标位置固定
@property({ type: CCInteger })
endType: EType = 0 //
anim:Animation=null;
group:number=0;
SConf:SkillConfig=null;
sData:SDataCom=null;
s_uuid:number=1001
start() {
this.SConf = SkillSet[this.s_uuid]
this.sData=this.ent.get(SDataCom)
this.anim=this.node.getComponent(Animation)
this.node.active = true;
let collider = this.getComponent(Collider2D);
if(collider) {
collider.group = this.group;
collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
}
const SMove=this.ent.get(SMoveDataComp)
// 计算延长后的目标点坐标
switch(this.runType){
case RType.linear:
SMove.rePos(v3(this.node.position.x + this.atk_x, this.node.position.y + this.atk_y))
this.do_linear(SMove.startPos,SMove.targetPos)
break
case RType.bezier:
SMove.rePos(v3(this.node.position.x + this.atk_x, this.node.position.y + this.atk_y))
this.do_bezier(SMove.startPos,SMove.targetPos)
break
case RType.fixed:
this.do_fixedStart(SMove.startPos,SMove.targetPos)
break
case RType.fixedEnd:
this.do_fixedEnd(SMove.startPos,SMove.targetPos)
break
}
}
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.SConf) return;
if(this.endType==EType.collision){
this.apply_damage(target)
}
}
}
do_bezier(startPos:Vec3,targetPos:Vec3){
let bm=this.node.getComponent(BezierMove)
this.node.angle +=10
// bm.speed=700
if(this.group==BoxSet.MONSTER) {bm.controlPointSide=-1 }
bm.rotationSmoothness=0.6
bm.moveTo(targetPos)
}
do_linear(startPos:Vec3,targetPos:Vec3){
let bm=this.node.getComponent(BezierMove)
let s_x=startPos.x
let s_y=startPos.y
let t_x=targetPos.x
let t_y=targetPos.y
// 设定目标x
targetPos.x = 400;
if(this.group == BoxSet.MONSTER) {
bm.controlPointSide = -1;
targetPos.x = -400;
}
// 计算斜率
const k = (t_y - s_y) / (t_x - s_x);
// 按直线公式计算新的y
targetPos.y = k * (targetPos.x - s_x) + s_y;
bm.controlPointOffset=0
bm.rotationSmoothness=0.6
bm.moveTo(targetPos);
}
do_fixedEnd(startPos:Vec3,targetPos:Vec3){
this.node.setPosition(targetPos.x > 360?300:targetPos.x,this.node.position.y,0)
this.do_anim()
}
do_fixedStart(startPos:Vec3,targetPos:Vec3){
// console.log("do_fixedStart",startPos,targetPos)
this.node.setPosition(startPos.x,this.node.position.y,0)
this.do_anim()
}
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(){
if(this.endType==EType.animationEnd){
this.ent.destroy()
}
}
//动画帧事件 atk 触发
public atk(args:any){
let dis=this.node.getComponent(UITransform).width/2
let enemys:any=[]
if( this.sData.fac==FacSet.HERO){
enemys=ecs.query(ecs.allOf(MonMoveComp))
}else{
enemys=ecs.query(ecs.allOf(HeroMoveComp))
}
let IRTargets: HeroViewComp[] = []
// 收集范围内所有敌方目标
enemys.some(e => {
const view = e.get(HeroViewComp);
const distance = Math.abs(this.node.position.x - view.node.position.x);
if(distance <= dis) {
IRTargets.push(view);
}
});
// 根据配置的hit_num决定攻击模式
const hitNum = SkillSet[this.s_uuid].hit_num || 0;
if(hitNum > 0) {
// 限制目标数量按距离排序选择最近的N个目标
if(IRTargets.length > 0) {
// 按距离排序(从近到远)
IRTargets.sort((a, b) => {
const distanceA = Math.abs(this.node.position.x - a.node.position.x);
const distanceB = Math.abs(this.node.position.x - b.node.position.x);
return distanceA - distanceB;
});
// 限制目标数量
const maxTargets = Math.min(hitNum, IRTargets.length);
const sTargets = IRTargets.slice(0, maxTargets);
sTargets.forEach(target => {
this.apply_damage(target, false);
});
}
} else {
// 范围伤害:对所有范围内目标造成伤害
if(IRTargets.length > 0) {
IRTargets.forEach(target => {
this.apply_damage(target, true);
});
}
}
}
//伤害应用
apply_damage(target:HeroViewComp,is_range:boolean=false){
if(target == null) return;
if (!this.SConf) return;
//伤害处理
target.ent.addComponents<DmgDataCom>(DmgDataCom)
let dmgData=target.ent.get(DmgDataCom)
dmgData.Attrs= this.sData.Attrs
dmgData.caster= this.sData.caster
dmgData.s_uuid= this.sData.s_uuid
// console.log(`[SkillCom]: ${this.sData.caster.ent.get(HeroAttrsComp).hero_name}[${this.sData.caster.ent.get(HeroAttrsComp).fac}:${ this.sData.fac}:${target.ent.get(HeroAttrsComp).fac}] 对 ${target.ent.get(HeroAttrsComp).hero_name} 释放技能 ${this.SConf.name}`)
this.sData.hit_count++
if( this.sData.hit_count>=(this.SConf.hit+ this.sData.Attrs[Attrs.PUNCTURE])&&(this.SConf.DTType!=DTType.range)&&(this.endType!=EType.animationEnd)&&(this.endType!=EType.timeEnd)) this.ent.destroy// 技能命中次数
}
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
reset() {
this.node.destroy();
}
}