feat(技能系统): 添加治疗和护盾技能支持
实现治疗和护盾技能的基础功能,包括: 1. 在SACastSystem中添加对治疗和护盾技能类型的支持 2. 新增技能目标选择逻辑,根据技能类型选择敌人或友军 3. 添加buff动画效果和技能提示 4. 更新刘邦的技能配置为护盾技能 5. 移除不再使用的EndAnm相关文件
This commit is contained in:
@@ -29,10 +29,13 @@
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
},
|
||||
{
|
||||
"__id__": 12
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 12
|
||||
"__id__": 14
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -259,6 +262,24 @@
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "c6LOemuvJKyYCqlF/yUJcr"
|
||||
},
|
||||
{
|
||||
"__type__": "0f3c4JhFbFO2rEFqBJJ7hFv",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "5dZdUy5cVPjLHtC1SlLIIB"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
|
||||
@@ -185,7 +185,7 @@ export const SkillSet: Record<number, SkillConfig> = {
|
||||
buffs:[],neAttrs:[],info:"治疗自己,回复30%最大生命值",
|
||||
},
|
||||
6101:{
|
||||
uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Self,SType:SType.buff,act:"buff",DTType:DTType.single,DType:DType.WIND,
|
||||
uuid:6101,name:"魔法盾",sp_name:"buff_wind",icon:"3036",TGroup:TGroup.Self,SType:SType.shield,act:"buff",DTType:DTType.single,DType:DType.WIND,
|
||||
ap:30,map:0,cd:1,t_num:1,hit_num:1,hit:1,hitcd:0.2,speed:720,cost:0,with:0,dis:80,ready:0,EAnm:0,DAnm:9001,RType:RType.fixed,EType:EType.animationEnd,
|
||||
buffs:[],neAttrs:[],info:"获得30%最大生命值的护盾",
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ export const HeroInfo: Record<number, heroInfo> = {
|
||||
|
||||
// 刘邦 - 领导型战士(善于用人,知人善任)
|
||||
5001:{uuid:5001,name:"刘邦",path:"hk1", fac:FacSet.HERO, kind:1,as:1.5,
|
||||
type:HType.warrior,lv:1,hp:1000,mp:85,map:10,def:9,mdef:0,ap:15,dis:100,speed:120,skills:[6002,6001],
|
||||
type:HType.warrior,lv:1,hp:1000,mp:85,map:10,def:9,mdef:0,ap:15,dis:100,speed:120,skills:[6002,6101],
|
||||
buff:[],tal:[7101,7201,7301],info:"楚汉争霸领袖,领导统御型战士"},
|
||||
|
||||
// 荆轲 - 刺客(敏捷型,高速度和暴击率)
|
||||
|
||||
@@ -76,6 +76,9 @@ export class HeroSpine extends Component {
|
||||
do_buff(){
|
||||
this.anm.buff()
|
||||
}
|
||||
buff(){
|
||||
this.anm.buff()
|
||||
}
|
||||
move(){
|
||||
// console.log("change to move",this.status);
|
||||
if(this.status=="move") return
|
||||
|
||||
@@ -438,6 +438,10 @@ export class HeroViewComp extends CCComp {
|
||||
case "atk":
|
||||
this.as.atk()
|
||||
break
|
||||
case "buff":
|
||||
this.as.buff()
|
||||
this.tooltip(TooltipTypes.skill, skill.name)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,20 +49,24 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
||||
const readySkills = skills.getReadySkills(heroAttrs.mp);
|
||||
if (readySkills.length === 0) return;
|
||||
|
||||
// 选择第一个可施放的伤害技能
|
||||
for (const s_uuid of readySkills) {
|
||||
// 选择第一个可施放的技能(支持伤害/治疗/护盾)
|
||||
for (const s_uuid of readySkills) {
|
||||
const skill = skills.getSkill(s_uuid);
|
||||
if (!skill) continue;
|
||||
if (skill.hset === HSSet.max && !skills.max_auto) continue;
|
||||
|
||||
const config = SkillSet[skill.s_uuid];
|
||||
if (!config || config.SType !== SType.damage) continue;
|
||||
if (!config) continue;
|
||||
|
||||
// 检查是否有敌人在技能攻击范围内
|
||||
if (!this.hasEnemyInSkillRange(heroView, heroAttrs, skill.dis)) continue;
|
||||
// 根据技能类型检查目标
|
||||
if (config.SType === SType.damage) {
|
||||
if (!this.hasEnemyInSkillRange(heroView, heroAttrs, skill.dis)) continue;
|
||||
} else if (config.SType === SType.heal || config.SType === SType.shield) {
|
||||
if (!this.hasAllyInSkillRange(heroView, heroAttrs, skill.dis)) continue;
|
||||
}
|
||||
|
||||
// ✅ 开始执行施法
|
||||
this.startCast(e,skill,skill.hset);
|
||||
this.startCast(e, skill, skill.hset);
|
||||
|
||||
// 一次只施放一个技能
|
||||
break;
|
||||
@@ -151,8 +155,15 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
||||
if (hset === HSSet.max) talComp.updateCur(TriType.MAX);
|
||||
}
|
||||
/**********************天赋处理*************************************************************************/
|
||||
// 获取目标位置
|
||||
let targets = this.sTargets(heroView, s_uuid);
|
||||
// 根据技能类型执行不同逻辑
|
||||
if (config.SType === SType.heal) {
|
||||
return this.executeHealSkill(casterEntity, s_uuid, heroView, hset);
|
||||
} else if (config.SType === SType.shield) {
|
||||
return this.executeShieldSkill(casterEntity, s_uuid, heroView, hset);
|
||||
}
|
||||
|
||||
// 获取目标位置(伤害技能)
|
||||
let targets = this.sTargets(heroView, s_uuid);
|
||||
if (targets.length === 0) {
|
||||
console.warn("[SACastSystem] 没有找到有效目标");
|
||||
return false;
|
||||
@@ -348,6 +359,159 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查技能范围内是否有友军
|
||||
*/
|
||||
private hasAllyInSkillRange(heroView: HeroViewComp, heroAttrs: HeroAttrsComp, skillDistance: number): boolean {
|
||||
if (!heroView || !heroView.node) return false;
|
||||
|
||||
const currentPos = heroView.node.position;
|
||||
const team = heroAttrs.fac;
|
||||
|
||||
let found = false;
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => {
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!view || !view.node) return false;
|
||||
const distance = Math.abs(currentPos.x - view.node.position.x);
|
||||
if (model.fac === team && !model.is_dead) {
|
||||
if (distance <= skillDistance) {
|
||||
found = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行治疗技能
|
||||
*/
|
||||
private executeHealSkill(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp, hset: HSSet): boolean {
|
||||
const heroAttrs = casterEntity.get(HeroAttrsComp);
|
||||
const config = SkillSet[s_uuid];
|
||||
if (!config) return false;
|
||||
|
||||
const targets = this.sHealTargets(heroView, heroAttrs, config);
|
||||
if (targets.length === 0) return false;
|
||||
|
||||
const healAmount = config.ap;
|
||||
const delay = 0.3;
|
||||
|
||||
heroView.scheduleOnce(() => {
|
||||
for (const targetEntity of targets) {
|
||||
const targetAttrs = targetEntity.get(HeroAttrsComp);
|
||||
const targetView = targetEntity.get(HeroViewComp);
|
||||
if (!targetAttrs || !targetView) continue;
|
||||
|
||||
targetAttrs.add_hp(healAmount, false);
|
||||
targetView.health(healAmount);
|
||||
}
|
||||
}, delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行护盾技能
|
||||
*/
|
||||
private executeShieldSkill(casterEntity: ecs.Entity, s_uuid: number, heroView: HeroViewComp, hset: HSSet): boolean {
|
||||
const heroAttrs = casterEntity.get(HeroAttrsComp);
|
||||
const config = SkillSet[s_uuid];
|
||||
if (!config) return false;
|
||||
|
||||
const targets = this.sShieldTargets(heroView, heroAttrs, config);
|
||||
if (targets.length === 0) return false;
|
||||
|
||||
const shieldAmount = config.ap;
|
||||
const delay = 0.3;
|
||||
|
||||
heroView.scheduleOnce(() => {
|
||||
for (const targetEntity of targets) {
|
||||
const targetAttrs = targetEntity.get(HeroAttrsComp);
|
||||
const targetView = targetEntity.get(HeroViewComp);
|
||||
if (!targetAttrs || !targetView) continue;
|
||||
|
||||
targetAttrs.add_shield(shieldAmount, false);
|
||||
targetView.add_shield(shieldAmount);
|
||||
}
|
||||
}, delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择治疗目标
|
||||
*/
|
||||
private sHealTargets(caster: HeroViewComp, heroAttrs: HeroAttrsComp, config: any): ecs.Entity[] {
|
||||
const targets: ecs.Entity[] = [];
|
||||
const maxTargets = Math.max(1, Number(config.t_num ?? 1));
|
||||
const range = Number(config.dis ?? 300);
|
||||
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => {
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!model || !view || !view.node) return;
|
||||
if (model.fac !== heroAttrs.fac) return;
|
||||
if (model.is_dead) return;
|
||||
|
||||
const distance = Math.abs(caster.node.position.x - view.node.position.x);
|
||||
if (distance <= range) {
|
||||
targets.push(e);
|
||||
}
|
||||
});
|
||||
|
||||
targets.sort((a, b) => {
|
||||
const attrsA = a.get(HeroAttrsComp);
|
||||
const attrsB = b.get(HeroAttrsComp);
|
||||
if (!attrsA || !attrsB) return 0;
|
||||
return attrsA.hp - attrsB.hp;
|
||||
});
|
||||
|
||||
return targets.slice(0, maxTargets);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择护盾目标
|
||||
*/
|
||||
private sShieldTargets(caster: HeroViewComp, heroAttrs: HeroAttrsComp, config: any): ecs.Entity[] {
|
||||
const targets: ecs.Entity[] = [];
|
||||
const maxTargets = Math.max(1, Number(config.t_num ?? 1));
|
||||
const range = Number(config.dis ?? 300);
|
||||
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).forEach(e => {
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!model || !view || !view.node) return;
|
||||
if (model.fac !== heroAttrs.fac) return;
|
||||
if (model.is_dead) return;
|
||||
|
||||
const distance = Math.abs(caster.node.position.x - view.node.position.x);
|
||||
if (distance <= range) {
|
||||
targets.push(e);
|
||||
}
|
||||
});
|
||||
|
||||
return targets.slice(0, maxTargets);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据位置查找实体
|
||||
*/
|
||||
private findEntityAtPosition(pos: Vec3): ecs.Entity | null {
|
||||
let foundEntity: ecs.Entity | null = null;
|
||||
ecs.query(ecs.allOf(HeroAttrsComp, HeroViewComp)).some(e => {
|
||||
const view = e.get(HeroViewComp);
|
||||
if (!view || !view.node) return false;
|
||||
const distance = Vec3.distance(pos, view.node.position);
|
||||
if (distance < 50) {
|
||||
foundEntity = e;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return foundEntity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
|
||||
/** EndAnm 模块 */
|
||||
@ecs.register(`EndAnm`)
|
||||
export class EndAnm extends ecs.Entity {
|
||||
/** ---------- 数据层 ---------- */
|
||||
// EndAnmModel!: EndAnmModelComp;
|
||||
|
||||
/** ---------- 业务层 ---------- */
|
||||
// EndAnmBll!: EndAnmBllComp;
|
||||
|
||||
/** ---------- 视图层 ---------- */
|
||||
// EndAnmView!: EndAnmViewComp;
|
||||
|
||||
/** 实始添加的数据层组件 */
|
||||
protected init() {
|
||||
// this.addComponents<ecs.Comp>();
|
||||
}
|
||||
|
||||
/** 模块资源释放 */
|
||||
destroy() {
|
||||
// 注: 自定义释放逻辑,视图层实现 ecs.IComp 接口的 ecs 组件需要手动释放
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/** EndAnm 模块业务逻辑系统组件,如无业务逻辑处理可删除此对象 */
|
||||
export class EcsEndAnmSystem extends ecs.System {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// this.add(new ecs.ComblockSystem());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1262d5a7-b1a1-49dc-9715-b7e28619304f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
|
||||
/** 业务层对象 */
|
||||
@ecs.register('EndAnmCom')
|
||||
export class EndAnmComComp extends ecs.Comp {
|
||||
/** 业务层组件移除时,重置所有数据为默认值 */
|
||||
reset() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** 业务层业务逻辑处理对象 */
|
||||
export class EndAnmComSystem extends ecs.ComblockSystem implements ecs.IEntityEnterSystem {
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(EndAnmComComp);
|
||||
}
|
||||
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
// 注:自定义业务逻辑
|
||||
if(!smc.mission.play || smc.mission.pause) return;
|
||||
e.remove(EndAnmComComp);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e0728072-f94e-4741-b172-4157e7a3b335",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user