From ae3231156d6c9c2290deea2e05ca3ff935bc3b41 Mon Sep 17 00:00:00 2001 From: walkpan Date: Mon, 16 Mar 2026 19:43:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8A=80=E8=83=BD):=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E6=8A=80=E8=83=BD=E7=9B=AE=E6=A0=87=E7=AD=9B=E9=80=89=E5=92=8C?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E7=B1=BB=E5=9E=8B=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除未使用的反伤技能配置 (5000) - 交换技能 6001 和 6002 的 EType 配置 (animationEnd/collision),使空挥技能在动画结束时触发,电击技能在碰撞时触发 - 将绿箭 (6006) 和红箭 (6007) 的 EType 从 animationEnd 改为 collision,使其在碰撞时触发 - 重构 SCastSystem 的目标查找逻辑,将候选目标收集与筛选分离,提高性能并修复可能的目标查找错误 --- assets/script/game/common/config/SkillSet.ts | 13 ++--- assets/script/game/hero/SCastSystem.ts | 53 ++++++++++---------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index d7f48b0c..af755b11 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -184,22 +184,17 @@ export interface SkillConfig { } export const SkillSet: Record = { - 5000:{uuid:5000,name:"反伤",sp_name:"thorns",icon:"1168",TGroup:TGroup.Enemy,TType:TType.Frontline,readyAnm:"",endAnm:"",act:"atk",DTType:DTType.single, - ap:0,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:"反伤", - }, // ========== 基础攻击 ========== 6001-6099 6001: { uuid:6001,name:"空挥",sp_name:"atk_s1",icon:"1026",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.fixed,EType:EType.collision, + ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd, buffs:[],debuffs:[],info:"对前方目标造成100%攻击的伤害", }, 6002: { 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.animationEnd, + ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.collision, buffs:[],debuffs:[],info:"对前方目标造成150%攻击的伤害", }, 6003: { @@ -223,13 +218,13 @@ export const SkillSet: Record = { 6006: { uuid:6006,name:"绿箭",sp_name:"arrow_green",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, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", }, 6007: { uuid:6007,name:"红箭",sp_name:"arrow_red",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, + ready:0,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision, buffs:[],debuffs:[],info:"对前方单个目标造成100%攻击的伤害", }, 6008: { diff --git a/assets/script/game/hero/SCastSystem.ts b/assets/script/game/hero/SCastSystem.ts index 27e0a619..247bcf63 100644 --- a/assets/script/game/hero/SCastSystem.ts +++ b/assets/script/game/hero/SCastSystem.ts @@ -26,6 +26,7 @@ import { GameConst } from "../common/config/GameConst"; export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { debugMode: boolean = false; // 是否启用调试模式 private readonly emptyCastPlan = { skillId: 0, targets: [] as HeroViewComp[] }; + private readonly emptyCandidates: { view: HeroViewComp; attrs: HeroAttrsComp; dis: number; lane: number; isSameFac: boolean }[] = []; filter(): ecs.IMatcher { return ecs.allOf(HeroAttrsComp, HeroViewComp); @@ -46,6 +47,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate } private pickCastSkill(heroAttrs: HeroAttrsComp, heroView: HeroViewComp): { skillId: number; targets: HeroViewComp[] } { + const range = heroAttrs.getCachedMaxSkillDistance() || GameConst.Battle.DEFAULT_SEARCH_RANGE; + const candidates = this.collectCandidates(heroView, heroAttrs, range); const skillCandidates = [heroAttrs.skill_id, heroAttrs.atk_id]; for (const s_uuid of skillCandidates) { if (!s_uuid) continue; @@ -54,7 +57,7 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate const isMainSkill = s_uuid === heroAttrs.skill_id; if (isMainSkill && !heroAttrs.can_skill) continue; if (!isMainSkill && !heroAttrs.can_atk) continue; - const targets = this.findTargets(heroView, heroAttrs, config); + const targets = this.findTargetsByCandidates(heroView, config, candidates); if (targets.length === 0) continue; return { skillId: s_uuid, targets }; } @@ -150,57 +153,53 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate }); } - private findTargets(caster: HeroViewComp, casterAttrs: HeroAttrsComp, config: SkillConfig): HeroViewComp[] { - const range = casterAttrs.getCachedMaxSkillDistance() || GameConst.Battle.DEFAULT_SEARCH_RANGE; - const isEnemy = config.TGroup === TGroup.Enemy; - const isSelf = config.TGroup === TGroup.Self; - const isTeam = config.TGroup === TGroup.Team || config.TGroup === TGroup.Ally; - const isAll = config.TGroup === TGroup.All; - if (isSelf) return [caster]; + private collectCandidates(caster: HeroViewComp, casterAttrs: HeroAttrsComp, range: number): { view: HeroViewComp; attrs: HeroAttrsComp; dis: number; lane: number; isSameFac: boolean }[] { + if (!caster || !caster.node || !caster.node.isValid) return this.emptyCandidates; const currentPos = caster.node.position; - const list: { view: HeroViewComp; attrs: HeroAttrsComp; dis: number; lane: number }[] = []; + const list: { view: HeroViewComp; attrs: HeroAttrsComp; dis: number; lane: number; isSameFac: boolean }[] = []; ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(ent => { const targetAttrs = ent.get(HeroAttrsComp); const targetView = ent.get(HeroViewComp); if (!targetAttrs || !targetView || !targetView.node || targetAttrs.is_dead) return; if (targetView === caster) return; - const isSameFac = targetAttrs.fac === casterAttrs.fac; - if (isEnemy && isSameFac) return; - if (isTeam && !isSameFac) return; - if (!isEnemy && !isTeam && !isAll) return; const dis = Math.abs(currentPos.x - targetView.node.position.x); if (dis > range) return; const lane = Math.abs(currentPos.y - targetView.node.position.y); - list.push({ view: targetView, attrs: targetAttrs, dis, lane }); + const isSameFac = targetAttrs.fac === casterAttrs.fac; + list.push({ view: targetView, attrs: targetAttrs, dis, lane, isSameFac }); + }); + return list; + } + + private findTargetsByCandidates(caster: HeroViewComp, config: SkillConfig, candidates: { view: HeroViewComp; attrs: HeroAttrsComp; dis: number; lane: number; isSameFac: boolean }[]): HeroViewComp[] { + const isEnemy = config.TGroup === TGroup.Enemy; + const isSelf = config.TGroup === TGroup.Self; + const isTeam = config.TGroup === TGroup.Team || config.TGroup === TGroup.Ally; + const isAll = config.TGroup === TGroup.All; + if (isSelf) return [caster]; + if (!isEnemy && !isTeam && !isAll) return this.emptyCastPlan.targets; + const list = candidates.filter(item => { + if (isEnemy && item.isSameFac) return false; + if (isTeam && !item.isSameFac) return false; + return true; }); - list.sort((a, b) => { - // 优先检查是否在同一行 (除了特殊目标类型) - // 如果是寻找特殊目标(如最低血量),通常忽略行优先,但在范围内全搜索 - // 但如果设计要求"最近的优先",则通常还是先看行。 - // 这里假设 TType 优先级高于 Lane 优先级,或者在 TType 相同情况下比较 Lane - const type = config.TType ?? TType.Frontline; switch (type) { case TType.Backline: - // 后排:距离最远优先 - if (a.lane !== b.lane) return a.lane - b.lane; // 先同行 + if (a.lane !== b.lane) return a.lane - b.lane; return b.dis - a.dis; case TType.LowestHP: - // 最低血量 if (a.attrs.hp !== b.attrs.hp) return a.attrs.hp - b.attrs.hp; - return a.dis - b.dis; // 血量相同选最近 + return a.dis - b.dis; case TType.HighestHP: - // 最高血量 if (a.attrs.hp !== b.attrs.hp) return b.attrs.hp - a.attrs.hp; return a.dis - b.dis; case TType.HighestAP: - // 最高攻击 if (a.attrs.ap !== b.attrs.ap) return b.attrs.ap - a.attrs.ap; return a.dis - b.dis; case TType.Frontline: default: - // 前排:距离最近优先 (默认) if (a.lane !== b.lane) return a.lane - b.lane; return a.dis - b.dis; }