Compare commits
11 Commits
oh/10171
...
oh/0_7_251
| Author | SHA1 | Date | |
|---|---|---|---|
| 03a8a41980 | |||
| 91c18004eb | |||
| 6df4abadd1 | |||
| 8d2ec76b01 | |||
| 4ed531e100 | |||
| aefe3d6d06 | |||
| 2dc43b5b81 | |||
| 58fa6527ee | |||
| df23e3787d | |||
| 8a0cfb78dd | |||
| 3990799046 |
11
assets/script/ecs.md.meta
Normal file
11
assets/script/ecs.md.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"importer": "text",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "1f3ba9b7-02ad-406f-86b3-895009bcb3e7",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -89,6 +89,8 @@ export enum FightSet {
|
|||||||
ATK_ADD_COUNT=4,//伙伴攻击力增加
|
ATK_ADD_COUNT=4,//伙伴攻击力增加
|
||||||
ATK_ADD_GLOD=1,//金币增加
|
ATK_ADD_GLOD=1,//金币增加
|
||||||
CRIT_DAMAGE=50,//暴击伤害
|
CRIT_DAMAGE=50,//暴击伤害
|
||||||
|
DEF_C=100,//物理防御常数C
|
||||||
|
MDEF_C=100,//魔法防御常数C
|
||||||
DOUBLE_ATK_RATE=100,//额外攻击默认概率
|
DOUBLE_ATK_RATE=100,//额外攻击默认概率
|
||||||
GREEN_GOLD=1,//绿色金币
|
GREEN_GOLD=1,//绿色金币
|
||||||
BLUE_GOLD=2,//蓝色金币
|
BLUE_GOLD=2,//蓝色金币
|
||||||
|
|||||||
@@ -17,18 +17,7 @@ export enum NeAttrs {
|
|||||||
IN_BURN = 2,
|
IN_BURN = 2,
|
||||||
IN_POISON = 3,
|
IN_POISON = 3,
|
||||||
}
|
}
|
||||||
export const getNeAttrs = () => {
|
|
||||||
let reAttrs = {};
|
|
||||||
Object.keys(NeAttrs).forEach(key => {
|
|
||||||
if (!isNaN(Number(key))) {
|
|
||||||
reAttrs[Number(key)] = {
|
|
||||||
value: 0,
|
|
||||||
time: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return reAttrs;
|
|
||||||
}
|
|
||||||
// ========== 属性枚举 ==========
|
// ========== 属性枚举 ==========
|
||||||
/**
|
/**
|
||||||
* 英雄属性枚举
|
* 英雄属性枚举
|
||||||
@@ -65,7 +54,6 @@ export enum Attrs {
|
|||||||
THORNS = 25, // 反伤
|
THORNS = 25, // 反伤
|
||||||
CRITICAL_RESIST = 26, // 暴击抗性
|
CRITICAL_RESIST = 26, // 暴击抗性
|
||||||
CON_RES = 27, // 控制抗性
|
CON_RES = 27, // 控制抗性
|
||||||
MAGIC_RES = 28, // 魔法抗性
|
|
||||||
|
|
||||||
// ========== 暴击与命中属性 (30-39) ==========
|
// ========== 暴击与命中属性 (30-39) ==========
|
||||||
CRITICAL = 30, // 暴击率
|
CRITICAL = 30, // 暴击率
|
||||||
@@ -76,9 +64,13 @@ export enum Attrs {
|
|||||||
ICE_RES = 40, // 冰冻抗性
|
ICE_RES = 40, // 冰冻抗性
|
||||||
FIRE_RES = 41, // 火焰抗性
|
FIRE_RES = 41, // 火焰抗性
|
||||||
WIND_RES = 42, // 自然抗性
|
WIND_RES = 42, // 自然抗性
|
||||||
ICE_POWER = 43, // 冰冻伤害加成
|
PHYS_RES = 43, // 物理抗性
|
||||||
FIRE_POWER = 44, // 火焰伤害加成
|
MAGIC_RES = 44, // 魔法抗性
|
||||||
WIND_POWER = 45, // 自然伤害加成
|
ICE_POWER = 45, // 冰冻伤害加成
|
||||||
|
FIRE_POWER = 46, // 火焰伤害加成
|
||||||
|
WIND_POWER = 47, // 自然伤害加成
|
||||||
|
PHYS_POWER = 48, // 物理伤害加成
|
||||||
|
MAGIC_POWER= 49,
|
||||||
|
|
||||||
|
|
||||||
// ========== 特殊效果属性 (50-59) ==========
|
// ========== 特殊效果属性 (50-59) ==========
|
||||||
@@ -140,6 +132,18 @@ export const getAttrs = () => {
|
|||||||
return reAttrs;
|
return reAttrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getNeAttrs = () => {
|
||||||
|
let reAttrs = {};
|
||||||
|
Object.keys(NeAttrs).forEach(key => {
|
||||||
|
if (!isNaN(Number(key))) {
|
||||||
|
reAttrs[Number(key)] = {
|
||||||
|
value: 0,
|
||||||
|
time: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return reAttrs;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 属性类型配置表
|
* 属性类型配置表
|
||||||
* 用于区分每个属性是数值型还是百分比型
|
* 用于区分每个属性是数值型还是百分比型
|
||||||
@@ -182,15 +186,19 @@ export const AttrsType: Record<Attrs, BType> = {
|
|||||||
[Attrs.HIT]: BType.RATIO, // 命中率 - 百分比型
|
[Attrs.HIT]: BType.RATIO, // 命中率 - 百分比型
|
||||||
[Attrs.CRITICAL_RESIST]: BType.RATIO, // 暴击抗性 - 百分比型
|
[Attrs.CRITICAL_RESIST]: BType.RATIO, // 暴击抗性 - 百分比型
|
||||||
[Attrs.CON_RES]: BType.RATIO, // 控制抗性 - 百分比型
|
[Attrs.CON_RES]: BType.RATIO, // 控制抗性 - 百分比型
|
||||||
[Attrs.MAGIC_RES]: BType.RATIO, // 魔法抗性 - 百分比型
|
|
||||||
|
|
||||||
// ========== 元素属性(百分比型) ==========
|
// ========== 元素属性(百分比型) ==========
|
||||||
[Attrs.ICE_RES]: BType.RATIO, // 冰冻抗性 - 百分比型
|
[Attrs.ICE_RES]: BType.RATIO, // 冰冻抗性 - 百分比型
|
||||||
[Attrs.FIRE_RES]: BType.RATIO, // 火焰抗性 - 百分比型
|
[Attrs.FIRE_RES]: BType.RATIO, // 火焰抗性 - 百分比型
|
||||||
[Attrs.WIND_RES]: BType.RATIO, // 风抗性 - 百分比型
|
[Attrs.WIND_RES]: BType.RATIO, // 风抗性 - 百分比型
|
||||||
|
[Attrs.PHYS_RES]: BType.RATIO, // 物理抗性 - 百分比型
|
||||||
|
[Attrs.MAGIC_RES]:BType.RATIO,
|
||||||
[Attrs.ICE_POWER]: BType.RATIO, // 冰冻伤害加成 - 百分比型
|
[Attrs.ICE_POWER]: BType.RATIO, // 冰冻伤害加成 - 百分比型
|
||||||
[Attrs.FIRE_POWER]: BType.RATIO, // 火焰伤害加成 - 百分比型
|
[Attrs.FIRE_POWER]: BType.RATIO, // 火焰伤害加成 - 百分比型
|
||||||
[Attrs.WIND_POWER]: BType.RATIO, // 风伤害加成 - 百分比型
|
[Attrs.WIND_POWER]: BType.RATIO, // 风伤害加成 - 百分比型
|
||||||
|
[Attrs.PHYS_POWER]: BType.RATIO, // 物理伤害加成 - 百分比型
|
||||||
|
[Attrs.MAGIC_POWER]: BType.RATIO, // 物理伤害加成 - 百分比型
|
||||||
|
|
||||||
// ========== 特殊效果属性(百分比型) ==========
|
// ========== 特殊效果属性(百分比型) ==========
|
||||||
[Attrs.LIFESTEAL]: BType.RATIO, // 吸血比率 - 百分比型
|
[Attrs.LIFESTEAL]: BType.RATIO, // 吸血比率 - 百分比型
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ export enum EType {
|
|||||||
//debuff类型
|
//debuff类型
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=== 技能配置系统使用说明 ===
|
=== 技能配置系统使用说明 ===
|
||||||
|
|
||||||
@@ -115,7 +114,9 @@ export enum EType {
|
|||||||
*/
|
*/
|
||||||
export enum DType {
|
export enum DType {
|
||||||
ATK= 0, // 物理
|
ATK= 0, // 物理
|
||||||
MAGE=1, // 魔法
|
ICE=1, // 冰元素
|
||||||
|
FIRE=2, // 火元素
|
||||||
|
WIND=3, // 风元素
|
||||||
}
|
}
|
||||||
export const HeroSkillList = [6001,6001,6001,6001,6001,6001]
|
export const HeroSkillList = [6001,6001,6001,6001,6001,6001]
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ interface IEndAnm {
|
|||||||
// 技能配置接口 - 按照6001格式排列
|
// 技能配置接口 - 按照6001格式排列
|
||||||
export interface SkillConfig {
|
export interface SkillConfig {
|
||||||
uuid:number,name:string,sp_name:string,icon:string,TGroup:TGroup,SType:SType,act:string,DTType:DTType,DType:DType,
|
uuid:number,name:string,sp_name:string,icon:string,TGroup:TGroup,SType:SType,act:string,DTType:DTType,DType:DType,
|
||||||
ap:number,cd:number,t_num:number,hit_num:number,hit:number,hitcd:number,speed:number,cost:number,with:number,dis:Number,ready:number,EAnm:number,DAnm:number,RType:RType,EType:EType,
|
ap:number,map:number,cd:number,t_num:number,hit_num:number,hit:number,hitcd:number,speed:number,cost:number,with:number,dis:Number,ready:number,EAnm:number,DAnm:number,RType:RType,EType:EType,
|
||||||
buffs:BuffConf[],neAttrs:NeAttrsConf[],info:string,hero?:number ,
|
buffs:BuffConf[],neAttrs:NeAttrsConf[],info:string,hero?:number ,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,18 +161,18 @@ export const SkillSet: Record<number, SkillConfig> = {
|
|||||||
// ========== 基础攻击 ========== 6001-6099
|
// ========== 基础攻击 ========== 6001-6099
|
||||||
6001: {
|
6001: {
|
||||||
uuid:6001,name:"挥击",sp_name:"atk_s1",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK,
|
uuid:6001,name:"挥击",sp_name:"atk_s1",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK,
|
||||||
ap:100,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,
|
ap:100,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:"向最前方敌人扔出石斧,造成100%攻击的伤害",
|
buffs:[],neAttrs:[],info:"向最前方敌人扔出石斧,造成100%攻击的伤害",
|
||||||
},
|
},
|
||||||
6002: {
|
6002: {
|
||||||
uuid:6002,name:"挥砍",sp_name:"atk_s4",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK,
|
uuid:6002,name:"挥砍",sp_name:"atk_s4",icon:"3036",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ATK,
|
||||||
ap:100,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,
|
ap:100,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:"向最前方敌人扔出石斧,造成100%攻击的伤害",
|
buffs:[],neAttrs:[],info:"向最前方敌人扔出石斧,造成100%攻击的伤害",
|
||||||
},
|
},
|
||||||
6005: {
|
6005: {
|
||||||
uuid:6005,name:"水球",sp_name:"m_water_ball_1",icon:"3039",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.MAGE,
|
uuid:6005,name:"水球",sp_name:"m_water_ball_1",icon:"3039",TGroup:TGroup.Enemy,SType:SType.damage,act:"atk",DTType:DTType.single,DType:DType.ICE,
|
||||||
ap:100,cd:5,t_num:1,hit_num:1,hit:2,hitcd:0.3,speed:720,cost:0,with:90,dis:360,ready:8001,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision,
|
ap:0,map:100,cd:5,t_num:1,hit_num:1,hit:2,hitcd:0.3,speed:720,cost:0,with:90,dis:360,ready:8001,EAnm:0,DAnm:9001,RType:RType.linear,EType:EType.collision,
|
||||||
buffs:[],neAttrs:[],info:"召唤大火球攻击前方所有敌人,造成300%攻击的伤害,有一定几率施加灼烧",
|
buffs:[],neAttrs:[],info:"召唤水球攻击前方敌人,造成100%魔法攻击的伤害",
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,28 +9,30 @@ export enum TriType {
|
|||||||
ATK = 2, //普通攻击触发
|
ATK = 2, //普通攻击触发
|
||||||
DMG = 3, // 受伤触发
|
DMG = 3, // 受伤触发
|
||||||
SKILL = 4, // 技能触发
|
SKILL = 4, // 技能触发
|
||||||
HPL = 5, // 失去生命值触发
|
MAX = 5, // 必杀触发
|
||||||
HPA = 6, // 获得生命值触发
|
HPL = 6, // 失去生命值触发
|
||||||
INIT = 7, // 初始触发,如:多1个技能
|
HPA = 7, // 获得生命值触发
|
||||||
DEAD = 8 // 基于死亡触发
|
INIT = 8, // 初始触发,如:多1个技能
|
||||||
|
DEAD = 9, // 基于死亡触发
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export enum TalEffet {
|
export enum TalEffet {
|
||||||
DMG=1, // 伤害
|
ATK_DMG=1, // 伤害
|
||||||
HP=2, // 回血 百分比
|
SKILL_DMG=2, // 技能伤害
|
||||||
MP=3, //回蓝 百分比
|
HP=3, // 回血 百分比
|
||||||
BUFF = 4, // 暴击率,闪避率等,可叠加的触发后清零
|
MP=4, //回蓝 百分比
|
||||||
STATS=5, // 状态
|
BUFF = 5, // 暴击率,闪避率等,可叠加的触发后清零
|
||||||
WFUNY=6, // 风怒
|
STATS=6, // 状态
|
||||||
SPLASH=7, // 溅射
|
WFUNY=7, // 风怒
|
||||||
D_SKILL=8, //两次技能
|
SPLASH=8, // 溅射
|
||||||
SHIELD=9, // 护盾
|
D_SKILL=9, //两次技能
|
||||||
LDMG=10, // 减伤
|
SHIELD=10, // 护盾
|
||||||
C_ATK=11, // 普工必爆
|
LDMG=11, // 减伤
|
||||||
C_SKILL=12, // 一般技能必暴
|
C_ATK=12, // 普工必爆
|
||||||
C_MSKILL=13, // 必杀技能必暴
|
C_SKILL=13, // 一般技能必暴
|
||||||
|
C_MSKILL=14, // 必杀技能必暴
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TalTarget {
|
export enum TalTarget {
|
||||||
@@ -107,7 +109,7 @@ export const talConf: Record<number, ItalConf> = {
|
|||||||
desc:"普通攻击10次后, 下次一般技能额外释放1次,伤害100%"},
|
desc:"普通攻击10次后, 下次一般技能额外释放1次,伤害100%"},
|
||||||
|
|
||||||
/*** 受伤触发 ***/
|
/*** 受伤触发 ***/
|
||||||
7101:{uuid:7101,name:"反击",triType:TriType.DMG,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.DMG,vType:BType.RATIO, value:50,attrs:TalAttrs.NON,
|
7101:{uuid:7101,name:"反击",triType:TriType.DMG,Trigger:3,count:1,target:TalTarget.ENEMY,effet:TalEffet.ATK_DMG,vType:BType.RATIO, value:50,attrs:TalAttrs.NON,
|
||||||
desc:"被攻击3次后, 给于目标50%的伤害"},
|
desc:"被攻击3次后, 给于目标50%的伤害"},
|
||||||
7102:{uuid:7102,name:"护盾",triType:TriType.DMG,Trigger:3,count:1,target:TalTarget.SELF,effet:TalEffet.SHIELD,vType:BType.RATIO, value:20,attrs:TalAttrs.NON,
|
7102:{uuid:7102,name:"护盾",triType:TriType.DMG,Trigger:3,count:1,target:TalTarget.SELF,effet:TalEffet.SHIELD,vType:BType.RATIO, value:20,attrs:TalAttrs.NON,
|
||||||
desc:"被攻击3次后, 获得20%的生命值护盾"},
|
desc:"被攻击3次后, 获得20%的生命值护盾"},
|
||||||
|
|||||||
@@ -2,20 +2,37 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec
|
|||||||
import { FacSet } from "../common/config/GameSet";
|
import { FacSet } from "../common/config/GameSet";
|
||||||
import { Attrs } from "../common/config/HeroAttrs";
|
import { Attrs } from "../common/config/HeroAttrs";
|
||||||
import { FightSet } from "../common/config/GameSet";
|
import { FightSet } from "../common/config/GameSet";
|
||||||
import { SkillSet } from "../common/config/SkillSet";
|
import { SkillSet, DType } from "../common/config/SkillSet";
|
||||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||||
import { HeroViewComp } from "./HeroViewComp";
|
import { HeroViewComp } from "./HeroViewComp";
|
||||||
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
|
|
||||||
|
|
||||||
/** 最终伤害数据接口 */
|
/** 最终伤害数据接口
|
||||||
|
* 用于封装一次攻击计算的所有结果数据
|
||||||
|
* @property damage - 最终造成的伤害值(已考虑所有加成和减免)
|
||||||
|
* @property isCrit - 是否为暴击攻击
|
||||||
|
* @property isDodge - 是否被闪避(闪避时damage为0)
|
||||||
|
*/
|
||||||
interface FinalData {
|
interface FinalData {
|
||||||
damage: number;
|
damage: number;
|
||||||
isCrit: boolean;
|
isCrit: boolean;
|
||||||
isDodge: boolean;
|
isDodge: boolean;
|
||||||
}
|
}
|
||||||
/** 业务层业务逻辑处理对象 伤害处理系统 */
|
/**
|
||||||
|
* 英雄攻击系统 - 伤害处理核心系统
|
||||||
|
*
|
||||||
|
* 职责:
|
||||||
|
* 1. 处理所有伤害事件的计算和分发
|
||||||
|
* 2. 管理伤害队列的处理流程
|
||||||
|
* 3. 协调视图层的表现更新
|
||||||
|
*
|
||||||
|
* 重要概念:
|
||||||
|
* - damageEvent.Attrs: 施法者属性快照(创建技能时保存)
|
||||||
|
* - targetAttrs: 被攻击者实时属性
|
||||||
|
* - 属性来源规范:攻击判定用施法者,防御判定用被攻击者
|
||||||
|
*/
|
||||||
@ecs.register('HeroAtkSystem')
|
@ecs.register('HeroAtkSystem')
|
||||||
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||||
|
|
||||||
@@ -81,10 +98,30 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行攻击计算
|
* 执行攻击计算 - 核心伤害计算逻辑
|
||||||
* @param target 目标实体
|
*
|
||||||
* @param damageEvent 伤害事件数据
|
* 属性使用规范(重要!):
|
||||||
* @returns 最终伤害数据
|
*
|
||||||
|
* ✅ 正确使用施法者属性(damageEvent.Attrs - 快照):
|
||||||
|
* - CRITICAL: 暴击率判定
|
||||||
|
* - CRITICAL_DMG: 暴击伤害加成
|
||||||
|
* - BACK_CHANCE: 击退概率
|
||||||
|
* - HIT: 命中率(用于闪避计算)
|
||||||
|
* - AP/MAP: 攻击力(基础伤害计算)
|
||||||
|
*
|
||||||
|
* ✅ 正确使用被攻击者属性(targetAttrs - 实时):
|
||||||
|
* - DODGE: 闪避率(用于闪避计算)
|
||||||
|
* - SHIELD_MAX: 护盾最大值(护盾吸收)
|
||||||
|
* - hp: 当前生命值(伤害应用)
|
||||||
|
* - 各种抗性属性(预留扩展)
|
||||||
|
*
|
||||||
|
* ❌ 错误使用案例(已修复):
|
||||||
|
* - 不要混用施法者和被攻击者的属性进行同一计算
|
||||||
|
* - 暴击伤害应该基于施法者的暴击伤害属性
|
||||||
|
*
|
||||||
|
* @param target 目标实体(被攻击者)
|
||||||
|
* @param damageEvent 伤害事件数据(包含施法者信息和属性快照)
|
||||||
|
* @returns 最终伤害数据(包含伤害值、暴击标记、闪避标记)
|
||||||
*/
|
*/
|
||||||
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
||||||
const targetAttrs = target.get(HeroAttrsComp);
|
const targetAttrs = target.get(HeroAttrsComp);
|
||||||
@@ -106,20 +143,28 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
// 触发被攻击事件
|
// 触发被攻击事件
|
||||||
this.onAttacked(target);
|
this.onAttacked(target);
|
||||||
|
|
||||||
// 闪避判定
|
// 闪避判定
|
||||||
const isDodge =this.checkChance(targetAttrs.Attrs[Attrs.DODGE] || 0);
|
// 闪避成功概率 = 被攻击者闪避率 - 施法者命中率
|
||||||
|
// targetAttrs.Attrs[Attrs.DODGE]: 被攻击者的实时闪避属性
|
||||||
|
// damageEvent.Attrs[Attrs.HIT]: 施法者在技能创建时的命中属性快照
|
||||||
|
const isDodge =this.checkChance((targetAttrs.Attrs[Attrs.DODGE]-damageEvent.Attrs[Attrs.HIT]) || 0);
|
||||||
if (isDodge) {
|
if (isDodge) {
|
||||||
// TODO: 触发闪避视图表现
|
// TODO: 触发闪避视图表现
|
||||||
reDate.isDodge=true;
|
reDate.isDodge=true;
|
||||||
return reDate;
|
return reDate;
|
||||||
}
|
}
|
||||||
// 暴击判定
|
// 暴击判定
|
||||||
|
// 使用施法者的暴击率属性(damageEvent.Attrs 快照)
|
||||||
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]);
|
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]);
|
||||||
if (isCrit) attackerModel?.clearTalBuffByAttr(Attrs.CRITICAL);
|
if (isCrit) attackerModel?.useValueTalByAttr(Attrs.CRITICAL); // 清除施法者的暴击buff
|
||||||
// 计算伤害
|
// 计算伤害
|
||||||
let damage = this.dmgCount(damageEvent.Attrs,damageEvent.s_uuid);
|
let damage = this.dmgCount(damageEvent,targetAttrs.Attrs);
|
||||||
if (isCrit) {
|
if (isCrit) {
|
||||||
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetAttrs.Attrs[Attrs.CRITICAL_DMG]) / 100));
|
// 暴击伤害计算
|
||||||
|
// 使用施法者的暴击伤害加成属性(damageEvent.Attrs 快照)
|
||||||
|
// 公式:最终伤害 = 基础伤害 * (1 + 系统暴击倍率 + 施法者暴击伤害加成)
|
||||||
|
const casterCritDmg = damageEvent.Attrs[Attrs.CRITICAL_DMG] || 0;
|
||||||
|
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + casterCritDmg) / 100));
|
||||||
reDate.isCrit=true;
|
reDate.isCrit=true;
|
||||||
}
|
}
|
||||||
// 伤害计算(考虑易伤等debuff)
|
// 伤害计算(考虑易伤等debuff)
|
||||||
@@ -130,9 +175,11 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
// 应用伤害到数据层
|
// 应用伤害到数据层
|
||||||
targetAttrs.hp -= damage;
|
targetAttrs.hp -= damage;
|
||||||
targetAttrs.atked_count++;
|
targetAttrs.atked_count++;
|
||||||
//击退判定
|
// 击退判定
|
||||||
|
// 使用施法者的击退概率属性(damageEvent.Attrs 快照)
|
||||||
|
// 击退成功后需要清理施法者的相关天赋buff
|
||||||
const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0);
|
const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0);
|
||||||
if (isBack) attackerModel?.clearTalBuffByAttr(Attrs.BACK_CHANCE);
|
if (isBack) attackerModel?.useValueTalByAttr(Attrs.BACK_CHANCE);
|
||||||
|
|
||||||
|
|
||||||
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
||||||
@@ -155,15 +202,139 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
reDate.damage=damage;
|
reDate.damage=damage;
|
||||||
return reDate;
|
return reDate;
|
||||||
}
|
}
|
||||||
//伤害计算,暂时简单计算
|
/**
|
||||||
private dmgCount(CAttrs:any,s_uuid:number){
|
* 详细伤害计算核心方法
|
||||||
let sConf = SkillSet[s_uuid];
|
*
|
||||||
|
* 这是整个战斗系统中最核心的伤害计算方法,负责根据施法者属性、目标属性和技能配置
|
||||||
|
* 计算最终的基础伤害值。该方法采用多阶段的伤害计算公式,综合考虑了物理和魔法伤害
|
||||||
|
* 以及各种属性加成和抗性减免。
|
||||||
|
*
|
||||||
|
* 计算流程:
|
||||||
|
* 1. 获取技能配置
|
||||||
|
* 2. 计算原始物理伤害和魔法伤害
|
||||||
|
* 3. 应用防御减免
|
||||||
|
* 4. 应用物理/魔法攻击力和抗性修正
|
||||||
|
* 5. 应用元素属性加成和抗性修正
|
||||||
|
* 6. 应用最终伤害减免
|
||||||
|
* 7. 确保伤害值非负
|
||||||
|
*
|
||||||
|
* @param CAttrs 施法者属性快照对象,包含所有攻击力、属性加成等战斗属性
|
||||||
|
* @param TAttrs 目标属性对象,包含所有防御力、抗性等防御属性
|
||||||
|
* @param s_uuid 技能ID,用于获取技能配置信息和伤害类型
|
||||||
|
* @returns 经过完整计算后的最终伤害值(未考虑暴击)
|
||||||
|
*
|
||||||
|
* @important 注意事项:
|
||||||
|
* - 此方法计算的是基础伤害,暴击计算在外部处理
|
||||||
|
* - 所有除法和乘法计算后都进行取整操作,确保游戏中的伤害值为整数
|
||||||
|
* - 元素伤害只应用于魔法伤害部分
|
||||||
|
*/
|
||||||
|
private dmgCount(damageEvent:any,TAttrs:any){
|
||||||
|
// 1. 获取技能配置 - 如果技能不存在,直接返回0伤害
|
||||||
|
const CAttrs=damageEvent.Attrs;
|
||||||
|
let sConf = SkillSet[damageEvent.s_uuid];
|
||||||
if (!sConf) return 0;
|
if (!sConf) return 0;
|
||||||
let AP = sConf.ap*CAttrs[Attrs.AP]/100;
|
|
||||||
return AP;
|
// 2. 计算原始物理伤害和魔法伤害
|
||||||
|
// 物理伤害基础值 = 技能物理倍率 * (施法者物理攻击力 + 额外物理伤害) / 100 * 伤害比例
|
||||||
|
let apBase = (sConf.ap||0)*(CAttrs[Attrs.AP]+damageEvent.ext_dmg)/100*damageEvent.dmg_ratio;
|
||||||
|
// 魔法伤害基础值 = 技能魔法倍率 * (施法者魔法攻击力 + 额外魔法伤害) / 100 * 伤害比例
|
||||||
|
let mapBase = (sConf.map||0)*(CAttrs[Attrs.MAP]+damageEvent.ext_dmg)/100*damageEvent.dmg_ratio;
|
||||||
|
|
||||||
|
// 3. 获取目标防御属性
|
||||||
|
const def = (TAttrs[Attrs.DEF]||0); // 目标物理防御
|
||||||
|
const mdef = (TAttrs[Attrs.MDEF]||0); // 目标魔法防御
|
||||||
|
|
||||||
|
// 4. 计算防御减免系数(采用公式:防御/(防御+常数),确保防御值不会导致伤害减到0)
|
||||||
|
const apRed = def / (def + FightSet.DEF_C); // 物理防御减免系数
|
||||||
|
const mapRed = mdef / (mdef + FightSet.MDEF_C); // 魔法防御减免系数
|
||||||
|
|
||||||
|
// 5. 应用防御减免到基础伤害,向下取整
|
||||||
|
let apAfter = Math.floor(apBase * (1 - apRed)); // 物理伤害 - 防御减免
|
||||||
|
let mapAfter = Math.floor(mapBase * (1 - mapRed)); // 魔法伤害 - 防御减免
|
||||||
|
|
||||||
|
// 6. 应用物理/魔法攻击力和抗性修正
|
||||||
|
// 物理伤害修正:基础伤害 * (1 + 物理攻击力加成%) * (1 - 目标物理抗性%)
|
||||||
|
apAfter = this.applyPR(apAfter, CAttrs[Attrs.PHYS_POWER]||0, TAttrs[Attrs.PHYS_RES]||0);
|
||||||
|
// 魔法伤害修正:基础伤害 * (1 + 魔法攻击力加成%) * (1 - 目标魔法抗性%)
|
||||||
|
mapAfter = this.applyPR(mapAfter, CAttrs[Attrs.MAGIC_POWER]||0, TAttrs[Attrs.MAGIC_RES]||0);
|
||||||
|
|
||||||
|
// 7. 根据技能元素类型,应用元素属性加成和抗性修正
|
||||||
|
switch (sConf.DType) {
|
||||||
|
case DType.ICE:
|
||||||
|
// 冰系伤害修正:魔法伤害 * (1 + 冰系攻击力加成%) * (1 - 目标冰系抗性%)
|
||||||
|
mapAfter = this.applyPR(mapAfter, CAttrs[Attrs.ICE_POWER]||0, TAttrs[Attrs.ICE_RES]||0);
|
||||||
|
break;
|
||||||
|
case DType.FIRE:
|
||||||
|
// 火系伤害修正:魔法伤害 * (1 + 火系攻击力加成%) * (1 - 目标火系抗性%)
|
||||||
|
mapAfter = this.applyPR(mapAfter, CAttrs[Attrs.FIRE_POWER]||0, TAttrs[Attrs.FIRE_RES]||0);
|
||||||
|
break;
|
||||||
|
case DType.WIND:
|
||||||
|
// 风系伤害修正:魔法伤害 * (1 + 风系攻击力加成%) * (1 - 目标风系抗性%)
|
||||||
|
mapAfter = this.applyPR(mapAfter, CAttrs[Attrs.WIND_POWER]||0, TAttrs[Attrs.WIND_RES]||0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 计算最终总伤害(物理伤害 + 魔法伤害)
|
||||||
|
let total = apAfter + mapAfter;
|
||||||
|
|
||||||
|
// 9. 应用最终伤害减免效果(如特殊天赋、buff等提供的减免)
|
||||||
|
total = Math.floor(total * (1 - ((TAttrs[Attrs.DAMAGE_REDUCTION]||0)/100)));
|
||||||
|
|
||||||
|
// 10. 确保伤害值非负,返回最终伤害
|
||||||
|
return Math.max(0,total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用攻击力加成和抗性减免的通用计算方法
|
||||||
|
*
|
||||||
|
* 这是一个核心的伤害修正计算方法,用于处理各种类型的攻击力加成和抗性减免。
|
||||||
|
* 该方法采用乘法叠加的方式,分别应用攻击者的加成属性和目标的抗性属性。
|
||||||
|
*
|
||||||
|
* 计算公式:
|
||||||
|
* 最终值 = 基础值 × (1 + 攻击力加成% / 100) × (1 - 抗性% / 100)
|
||||||
|
*
|
||||||
|
* 适用场景:
|
||||||
|
* - 物理攻击力加成和物理抗性减免
|
||||||
|
* - 魔法攻击力加成和魔法抗性减免
|
||||||
|
* - 元素攻击力加成和元素抗性减免
|
||||||
|
* - 其他需要同时考虑加成和减免的属性修正
|
||||||
|
*
|
||||||
|
* 计算逻辑说明:
|
||||||
|
* 1. 首先将百分比转换为小数形式(除以100)
|
||||||
|
* 2. 应用攻击者的加成:基础值 × (1 + 加成系数)
|
||||||
|
* 3. 应用目标的抗性:上一步结果 × (1 - 抗性系数)
|
||||||
|
* 4. 向下取整,确保结果为整数
|
||||||
|
*
|
||||||
|
* @param base 基础值(通常是经过防御减免后的伤害值)
|
||||||
|
* @param power 攻击者的攻击力加成值(百分比形式,如50表示50%)
|
||||||
|
* @param res 目标的抗性值(百分比形式,如30表示30%)
|
||||||
|
* @returns 经过攻击力加成和抗性减免后的最终值(向下取整)
|
||||||
|
*
|
||||||
|
* @important 注意事项:
|
||||||
|
* - 当抗性值大于100时,可能导致最终值为负数或零
|
||||||
|
* - 所有计算结果会向下取整,确保游戏中的数值为整数
|
||||||
|
* - 此方法可以被多次调用,以叠加不同类型的加成和减免
|
||||||
|
*/
|
||||||
|
private applyPR(base: number, power: number, res: number): number {
|
||||||
|
// 计算公式:基础值 × (1 + 攻击力加成%) × (1 - 抗性%)
|
||||||
|
// 1. 将百分比转换为小数:power/100 和 res/100
|
||||||
|
// 2. 应用攻击力加成:1 + (power/100)
|
||||||
|
// 3. 应用抗性减免:1 - (res/100)
|
||||||
|
// 4. 最终计算并向下取整
|
||||||
|
return Math.floor(base * (1 + (power/100)) * (1 - (res/100)));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 处理角色死亡
|
* 处理角色死亡
|
||||||
|
*
|
||||||
|
* 死亡处理流程:
|
||||||
|
* 1. 标记死亡状态(is_dead = true)
|
||||||
|
* 2. 触发死亡事件(onDeath)
|
||||||
|
* 3. 记录调试信息(如启用调试模式)
|
||||||
|
*
|
||||||
|
* @param entity 死亡的实体
|
||||||
|
*
|
||||||
|
* @important 死亡状态一旦设置,该实体将不再处理新的伤害事件
|
||||||
|
* 这确保了死亡逻辑的单一性和一致性
|
||||||
*/
|
*/
|
||||||
private doDead(entity: ecs.Entity): void {
|
private doDead(entity: ecs.Entity): void {
|
||||||
const model = entity.get(HeroAttrsComp);
|
const model = entity.get(HeroAttrsComp);
|
||||||
@@ -182,7 +353,26 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暴击判定
|
* 统一概率判定方法
|
||||||
|
*
|
||||||
|
* 用于所有概率相关的判定:
|
||||||
|
* - 暴击率判定
|
||||||
|
* - 闪避率判定
|
||||||
|
* - 击退概率判定
|
||||||
|
* - 其他特殊效果概率
|
||||||
|
*
|
||||||
|
* @param rate 概率值(0-100的百分比)
|
||||||
|
* @returns true-判定成功,false-判定失败
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* // 10%概率触发
|
||||||
|
* if (this.checkChance(10)) {
|
||||||
|
* // 触发特殊效果
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @important 概率为0或负数时直接返回false,避免不必要的随机数计算
|
||||||
*/
|
*/
|
||||||
private checkChance(rate: number): boolean {
|
private checkChance(rate: number): boolean {
|
||||||
if (rate <= 0) return false;
|
if (rate <= 0) return false;
|
||||||
@@ -192,6 +382,16 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 伤害计算(考虑易伤等debuff)
|
* 伤害计算(考虑易伤等debuff)
|
||||||
|
*
|
||||||
|
* 预留的伤害计算扩展点,用于处理:
|
||||||
|
* - 被攻击者的易伤状态(增加受到伤害)
|
||||||
|
* - 被攻击者的伤害减免状态(减少受到伤害)
|
||||||
|
* - 元素抗性计算
|
||||||
|
* - 真实伤害/魔法伤害/物理伤害的类型区分
|
||||||
|
*
|
||||||
|
* @param model 被攻击者的属性组件(包含抗性、易伤等状态)
|
||||||
|
* @param baseDamage 基础伤害值
|
||||||
|
* @returns 最终伤害值(经过各种加成和减免后的结果)
|
||||||
*/
|
*/
|
||||||
private calculateDamage(model: HeroAttrsComp, baseDamage: number): number {
|
private calculateDamage(model: HeroAttrsComp, baseDamage: number): number {
|
||||||
// 这里可以添加易伤等debuff的计算逻辑
|
// 这里可以添加易伤等debuff的计算逻辑
|
||||||
@@ -201,6 +401,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 护盾吸收伤害
|
* 护盾吸收伤害
|
||||||
|
*
|
||||||
|
* 护盾吸收逻辑:
|
||||||
|
* 1. 如果护盾值 >= 伤害值:完全吸收,剩余伤害为0
|
||||||
|
* 2. 如果护盾值 < 伤害值:部分吸收,剩余伤害 = 原伤害 - 护盾值
|
||||||
|
* 3. 护盾被击破时,重置护盾最大值属性
|
||||||
|
*
|
||||||
|
* @param model 被攻击者的属性组件(包含当前护盾值)
|
||||||
|
* @param damage 原始伤害值
|
||||||
|
* @returns 剩余伤害值(护盾吸收后的结果)
|
||||||
*/
|
*/
|
||||||
private absorbShield(model: HeroAttrsComp, damage: number): number {
|
private absorbShield(model: HeroAttrsComp, damage: number): number {
|
||||||
if (model.shield <= 0) return damage;
|
if (model.shield <= 0) return damage;
|
||||||
@@ -222,6 +431,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 被攻击时触发的事件
|
* 被攻击时触发的事件
|
||||||
|
*
|
||||||
|
* 预留的扩展点,用于处理被攻击时的特殊逻辑:
|
||||||
|
* - 触发反伤效果(荆棘光环等)
|
||||||
|
* - 触发被攻击天赋(如受击回血、受击反击等)
|
||||||
|
* - 触发特殊状态(如受伤狂暴、受伤护盾等)
|
||||||
|
*
|
||||||
|
* @param entity 被攻击的实体
|
||||||
|
*
|
||||||
|
* @todo 当前对怪物实体直接返回,后续可以根据需求扩展怪物的被攻击逻辑
|
||||||
*/
|
*/
|
||||||
private onAttacked(entity: ecs.Entity): void {
|
private onAttacked(entity: ecs.Entity): void {
|
||||||
const model = entity.get(HeroAttrsComp);
|
const model = entity.get(HeroAttrsComp);
|
||||||
@@ -235,6 +453,21 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 死亡时触发的事件
|
* 死亡时触发的事件
|
||||||
|
*
|
||||||
|
* 根据实体阵营类型处理不同的死亡逻辑:
|
||||||
|
*
|
||||||
|
* - FacSet.MON(怪物):触发掉落逻辑
|
||||||
|
* - 延迟执行掉落,避免阻塞主逻辑
|
||||||
|
* - 可以扩展:经验值计算、任务进度等
|
||||||
|
*
|
||||||
|
* - FacSet.HERO(英雄):触发英雄死亡特殊处理
|
||||||
|
* - 游戏结束判定
|
||||||
|
* - 复活机制检查
|
||||||
|
* - 死亡惩罚/奖励
|
||||||
|
*
|
||||||
|
* @param entity 死亡的实体
|
||||||
|
*
|
||||||
|
* @important 死亡事件应该幂等,避免重复触发
|
||||||
*/
|
*/
|
||||||
private onDeath(entity: ecs.Entity): void {
|
private onDeath(entity: ecs.Entity): void {
|
||||||
const model = entity.get(HeroAttrsComp);
|
const model = entity.get(HeroAttrsComp);
|
||||||
@@ -251,6 +484,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟执行掉落逻辑
|
* 延迟执行掉落逻辑
|
||||||
|
*
|
||||||
|
* 采用延迟执行的原因:
|
||||||
|
* 1. 避免在伤害计算过程中阻塞主线程
|
||||||
|
* 2. 给死亡动画播放留出时间
|
||||||
|
* 3. 可以批量处理多个掉落,优化性能
|
||||||
|
*
|
||||||
|
* @param entity 死亡的怪物实体
|
||||||
|
*
|
||||||
|
* @todo 具体实现可以包括:
|
||||||
|
* - 根据怪物等级计算基础掉落
|
||||||
|
* - 幸运值影响掉落品质
|
||||||
|
* - 特殊事件(双倍掉落、稀有掉落等)
|
||||||
|
* - 掉落物在场景中的生成位置计算
|
||||||
*/
|
*/
|
||||||
private scheduleDrop(entity: ecs.Entity): void {
|
private scheduleDrop(entity: ecs.Entity): void {
|
||||||
// 这里可以添加掉落逻辑
|
// 这里可以添加掉落逻辑
|
||||||
@@ -259,6 +505,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟执行英雄死亡逻辑
|
* 延迟执行英雄死亡逻辑
|
||||||
|
*
|
||||||
|
* 英雄死亡的特殊处理,比普通怪物复杂:
|
||||||
|
*
|
||||||
|
* 处理内容包括:
|
||||||
|
* - 检查复活次数和复活条件
|
||||||
|
* - 触发游戏结束界面(如适用)
|
||||||
|
* - 记录死亡统计信息
|
||||||
|
* - 处理死亡惩罚(经验损失、装备损坏等)
|
||||||
|
*
|
||||||
|
* @param entity 死亡的英雄实体
|
||||||
|
*
|
||||||
|
* @important 英雄死亡通常需要玩家交互,所以必须延迟处理
|
||||||
|
* 给玩家足够的反馈时间和操作空间
|
||||||
*/
|
*/
|
||||||
private scheduleHeroDeath(entity: ecs.Entity): void {
|
private scheduleHeroDeath(entity: ecs.Entity): void {
|
||||||
// 这里可以添加英雄死亡的特殊处理
|
// 这里可以添加英雄死亡的特殊处理
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"ver": "4.0.24",
|
"ver": "4.0.24",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"imported": true,
|
"imported": true,
|
||||||
"uuid": "85d8a2e5-f2a1-49b0-9439-fe9e1e98b7d9",
|
"uuid": "bffb52f1-1843-437d-82ef-88d2d7ee2ec5",
|
||||||
"files": [],
|
"files": [],
|
||||||
"subMetas": {},
|
"subMetas": {},
|
||||||
"userData": {}
|
"userData": {}
|
||||||
@@ -35,7 +35,9 @@ export class HeroAttrsComp extends ecs.Comp {
|
|||||||
shield: number = 0; // 当前护盾
|
shield: number = 0; // 当前护盾
|
||||||
Attrs: any = []; // 最终属性数组(经过Buff计算后)
|
Attrs: any = []; // 最终属性数组(经过Buff计算后)
|
||||||
NeAttrs: any = []; // 负面状态数组
|
NeAttrs: any = []; // 负面状态数组
|
||||||
Talents: Record<number, talTrigger> = {};
|
//计数型天赋buff
|
||||||
|
Talents: Record<number, talTrigger> = {};
|
||||||
|
//数值型天赋buff
|
||||||
BUFFS_TAL: Record<number, {count:number,BType:BType,attrIndex:number,value: number}> = {};
|
BUFFS_TAL: Record<number, {count:number,BType:BType,attrIndex:number,value: number}> = {};
|
||||||
|
|
||||||
// ==================== 技能距离缓存 ====================
|
// ==================== 技能距离缓存 ====================
|
||||||
@@ -407,7 +409,7 @@ export class HeroAttrsComp extends ecs.Comp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addTalBuff(t_uuid: number, attrIndex?: number, bType?: BType, value: number = 0) {
|
addValueTal(t_uuid: number, attrIndex?: number, bType?: BType, value: number = 0) {
|
||||||
if (attrIndex === undefined || bType === undefined) return;
|
if (attrIndex === undefined || bType === undefined) return;
|
||||||
const buff = this.BUFFS_TAL[t_uuid];
|
const buff = this.BUFFS_TAL[t_uuid];
|
||||||
if (!buff) {
|
if (!buff) {
|
||||||
@@ -418,14 +420,33 @@ export class HeroAttrsComp extends ecs.Comp {
|
|||||||
}
|
}
|
||||||
this.recalculateSingleAttr(attrIndex);
|
this.recalculateSingleAttr(attrIndex);
|
||||||
}
|
}
|
||||||
clearTalBuff(t_uuid: number) {
|
addCountTal(eff: number, value: number) {
|
||||||
|
const t = this.Talents[eff] || { value: 0, count: 0 };
|
||||||
|
t.value = value;
|
||||||
|
t.count += 1;
|
||||||
|
this.Talents[eff] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
useCountTal(eff: number): boolean {
|
||||||
|
const t = this.Talents[eff];
|
||||||
|
if (!t || t.count <= 0) return false;
|
||||||
|
t.count -= 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
useCountValTal(eff: number): number {
|
||||||
|
const t = this.Talents[eff];
|
||||||
|
if (!t || t.value <= 0) return 0;
|
||||||
|
t.count -= 1;
|
||||||
|
return t.value;
|
||||||
|
}
|
||||||
|
useValueTalByUuid(t_uuid: number) {
|
||||||
const buff = this.BUFFS_TAL[t_uuid];
|
const buff = this.BUFFS_TAL[t_uuid];
|
||||||
if (!buff) return;
|
if (!buff) return;
|
||||||
const attrIndex = buff.attrIndex;
|
const attrIndex = buff.attrIndex;
|
||||||
delete this.BUFFS_TAL[t_uuid];
|
delete this.BUFFS_TAL[t_uuid];
|
||||||
this.recalculateSingleAttr(attrIndex);
|
this.recalculateSingleAttr(attrIndex);
|
||||||
}
|
}
|
||||||
clearTalBuffByAttr(attrIndex: number) {
|
useValueTalByAttr(attrIndex: number) {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for (const key in this.BUFFS_TAL) {
|
for (const key in this.BUFFS_TAL) {
|
||||||
const b = this.BUFFS_TAL[Number(key)];
|
const b = this.BUFFS_TAL[Number(key)];
|
||||||
@@ -436,20 +457,7 @@ export class HeroAttrsComp extends ecs.Comp {
|
|||||||
}
|
}
|
||||||
if (changed) this.recalculateSingleAttr(attrIndex);
|
if (changed) this.recalculateSingleAttr(attrIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
addTalent(eff: number, value: number) {
|
|
||||||
const t = this.Talents[eff] || { value: 0, count: 0 };
|
|
||||||
t.value = value;
|
|
||||||
t.count += 1;
|
|
||||||
this.Talents[eff] = t;
|
|
||||||
}
|
|
||||||
consumeTalent(eff: number): boolean {
|
|
||||||
const t = this.Talents[eff];
|
|
||||||
if (!t || t.count <= 0) return false;
|
|
||||||
t.count -= 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
// 重置为初始状态
|
// 重置为初始状态
|
||||||
this.hero_uuid = 1001;
|
this.hero_uuid = 1001;
|
||||||
|
|||||||
@@ -143,11 +143,12 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
|||||||
// 1. 播放施法动画
|
// 1. 播放施法动画
|
||||||
heroView.playSkillEffect(s_uuid);
|
heroView.playSkillEffect(s_uuid);
|
||||||
/**********************天赋处理*************************************************************************/
|
/**********************天赋处理*************************************************************************/
|
||||||
// 2. 更新攻击类型的天赋触发值
|
// 2. 更新攻击类型的天赋触发值,技能和必杀级
|
||||||
if(casterEntity.has(TalComp)){
|
if(casterEntity.has(TalComp)){
|
||||||
const talComp = casterEntity.get(TalComp);
|
const talComp = casterEntity.get(TalComp);
|
||||||
if (hset === HSSet.atk) talComp.updateCur(TriType.ATK);
|
if (hset === HSSet.atk) talComp.updateCur(TriType.ATK);
|
||||||
if (hset != HSSet.atk) talComp.updateCur(TriType.SKILL);
|
if (hset === HSSet.skill) talComp.updateCur(TriType.SKILL);
|
||||||
|
if (hset === HSSet.max) talComp.updateCur(TriType.MAX);
|
||||||
}
|
}
|
||||||
/**********************天赋处理*************************************************************************/
|
/**********************天赋处理*************************************************************************/
|
||||||
// 获取目标位置
|
// 获取目标位置
|
||||||
@@ -156,31 +157,54 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
|||||||
console.warn("[SACastSystem] 没有找到有效目标");
|
console.warn("[SACastSystem] 没有找到有效目标");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 2. 延迟创建技能实体(等待动画)
|
// 2.1 普通攻击逻辑
|
||||||
const delay = 0.3
|
if (hset === HSSet.atk){
|
||||||
heroView.scheduleOnce(() => {
|
let delay = 0.3
|
||||||
this.createSkill(s_uuid, heroView,targets);
|
let ext_dmg = heroAttrs.useCountValTal(TalEffet.ATK_DMG);
|
||||||
}, delay);
|
let splash = heroAttrs.useCountValTal(TalEffet.SPLASH);
|
||||||
|
heroView.scheduleOnce(() => {
|
||||||
//风怒wfuny 只针对 普通攻击起效
|
this.createSkill(s_uuid, heroView,targets,ext_dmg,splash);
|
||||||
if (hset === HSSet.atk && heroAttrs.consumeTalent(TalEffet.WFUNY)){
|
}, delay);
|
||||||
heroView.playSkillEffect(s_uuid);
|
//风怒wfuny 只针对 普通攻击起效
|
||||||
//需要再添加 风怒动画
|
if (heroAttrs.useCountTal(TalEffet.WFUNY)){
|
||||||
this.createSkill(s_uuid, heroView,targets);
|
let ext2_dmg = heroAttrs.useCountValTal(TalEffet.ATK_DMG);
|
||||||
}
|
let splash2 = heroAttrs.useCountValTal(TalEffet.SPLASH);
|
||||||
// 双技能 只针对 技能起效
|
let delay = 0.3
|
||||||
if(hset === HSSet.skill && heroAttrs.consumeTalent(TalEffet.D_SKILL)){
|
heroView.playSkillEffect(s_uuid);
|
||||||
targets = this.sTargets(heroView, s_uuid);
|
//需要再添加 风怒动画
|
||||||
if (targets.length === 0) {
|
heroView.scheduleOnce(() => {
|
||||||
console.warn("[SACastSystem] 没有找到有效目标");
|
this.createSkill(s_uuid, heroView,targets,ext2_dmg,splash2);
|
||||||
return false;
|
},delay);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// 2.2 技能攻击逻辑
|
||||||
|
if(hset === HSSet.skill){
|
||||||
|
let delay = 0.3
|
||||||
|
let ext_dmg = heroAttrs.useCountValTal(TalEffet.SKILL_DMG);
|
||||||
|
heroView.scheduleOnce(() => {
|
||||||
|
this.createSkill(s_uuid, heroView,targets,ext_dmg);
|
||||||
|
}, delay);
|
||||||
|
// 双技能 只针对 技能起效
|
||||||
|
if(heroAttrs.useCountTal(TalEffet.D_SKILL)){
|
||||||
|
let ext2_dmg = heroAttrs.useCountValTal(TalEffet.SKILL_DMG);
|
||||||
|
let delay = 0.3
|
||||||
|
heroView.playSkillEffect(s_uuid);
|
||||||
|
//需要再添加 双技能动画
|
||||||
|
heroView.scheduleOnce(() => {
|
||||||
|
this.createSkill(s_uuid, heroView,targets,ext2_dmg);
|
||||||
|
},delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2.3 必杀技能逻辑
|
||||||
|
if(hset === HSSet.max){
|
||||||
|
let delay = 0.3
|
||||||
heroView.playSkillEffect(s_uuid);
|
heroView.playSkillEffect(s_uuid);
|
||||||
//需要再添加 双技能动画
|
//需要再添加 最大伤害动画
|
||||||
heroView.scheduleOnce(() => {
|
heroView.scheduleOnce(() => {
|
||||||
this.createSkill(s_uuid, heroView,targets);
|
this.createSkill(s_uuid, heroView,targets);
|
||||||
}, delay);
|
},delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -190,7 +214,7 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
|||||||
/**
|
/**
|
||||||
* 创建技能实体
|
* 创建技能实体
|
||||||
*/
|
*/
|
||||||
private createSkill(s_uuid: number, caster: HeroViewComp,targets:Vec3[]=[],ext_dmg:number=0) {
|
private createSkill(s_uuid: number, caster: HeroViewComp,targets:Vec3[]=[],ext_dmg:number=0,splash:number=0) {
|
||||||
// 检查节点有效性
|
// 检查节点有效性
|
||||||
if (!caster.node || !caster.node.isValid) {
|
if (!caster.node || !caster.node.isValid) {
|
||||||
console.warn("[SACastSystem] 施法者节点无效");
|
console.warn("[SACastSystem] 施法者节点无效");
|
||||||
@@ -215,7 +239,7 @@ export class SACastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdat
|
|||||||
const targetPos = targets[0]; // 使用第一个目标位置
|
const targetPos = targets[0]; // 使用第一个目标位置
|
||||||
// console.log(`[SACastSystem]: ${s_uuid}, 起始位置: ${startPos}, 目标位置: ${targetPos}`);
|
// console.log(`[SACastSystem]: ${s_uuid}, 起始位置: ${startPos}, 目标位置: ${targetPos}`);
|
||||||
// 加载技能实体(包括预制体、组件初始化等)
|
// 加载技能实体(包括预制体、组件初始化等)
|
||||||
skill.load(startPos, parent, s_uuid, targetPos, caster,ext_dmg);
|
skill.load(startPos, parent, s_uuid, targetPos, caster,ext_dmg,splash);
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ export class TalComp extends ecs.Comp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//执行天赋触发效果
|
//执行天赋触发效果
|
||||||
|
// 功能:
|
||||||
|
// - 根据天赋类型执行相应的效果
|
||||||
|
// - 支持计数型和数值型天赋
|
||||||
|
// --heroAttrs.addTalent 是计数型天赋buff heroAttrs.addTalBuff 是数值型天赋buff
|
||||||
doTriggerTal(uuid: number) {
|
doTriggerTal(uuid: number) {
|
||||||
// 检查天赋是否存在
|
// 检查天赋是否存在
|
||||||
if (!this.Tals[uuid]) {
|
if (!this.Tals[uuid]) {
|
||||||
@@ -198,23 +202,38 @@ export class TalComp extends ecs.Comp {
|
|||||||
const talent = this.Tals[uuid];
|
const talent = this.Tals[uuid];
|
||||||
const heroAttrs=this.ent.get(HeroAttrsComp);
|
const heroAttrs=this.ent.get(HeroAttrsComp);
|
||||||
switch(talent.effet){
|
switch(talent.effet){
|
||||||
|
case TalEffet.ATK_DMG:
|
||||||
|
heroAttrs.addCountTal(TalEffet.ATK_DMG, talent.value + talent.value_add);
|
||||||
|
break;
|
||||||
|
case TalEffet.SKILL_DMG:
|
||||||
|
heroAttrs.addCountTal(TalEffet.SKILL_DMG, talent.value + talent.value_add);
|
||||||
|
break;
|
||||||
|
case TalEffet.LDMG:
|
||||||
|
heroAttrs.addCountTal(TalEffet.LDMG, talent.value + talent.value_add);
|
||||||
|
break;
|
||||||
|
// case TalEffet.HP:
|
||||||
|
// heroAttrs.addCountTal(TalEffet.HP, talent.value + talent.value_add);
|
||||||
|
// break;
|
||||||
|
// case TalEffet.MP:
|
||||||
|
// heroAttrs.addCountTal(TalEffet.MP, talent.value + talent.value_add);
|
||||||
|
// break;
|
||||||
case TalEffet.WFUNY:
|
case TalEffet.WFUNY:
|
||||||
heroAttrs.addTalent(TalEffet.WFUNY, talent.value + talent.value_add);
|
heroAttrs.addCountTal(TalEffet.WFUNY, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
case TalEffet.D_SKILL:
|
case TalEffet.D_SKILL:
|
||||||
heroAttrs.addTalent(TalEffet.D_SKILL, talent.value + talent.value_add);
|
heroAttrs.addCountTal(TalEffet.D_SKILL, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
case TalEffet.C_ATK:
|
case TalEffet.C_ATK:
|
||||||
heroAttrs.addTalent(TalEffet.C_ATK, talent.value + talent.value_add);
|
heroAttrs.addCountTal(TalEffet.C_ATK, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
case TalEffet.C_SKILL:
|
case TalEffet.C_SKILL:
|
||||||
heroAttrs.addTalent(TalEffet.C_SKILL, talent.value + talent.value_add);
|
heroAttrs.addCountTal(TalEffet.C_SKILL, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
case TalEffet.C_MSKILL:
|
case TalEffet.C_MSKILL:
|
||||||
heroAttrs.addTalent(TalEffet.C_MSKILL, talent.value + talent.value_add);
|
heroAttrs.addCountTal(TalEffet.C_MSKILL, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
case TalEffet.BUFF:
|
case TalEffet.BUFF:
|
||||||
heroAttrs.addTalBuff(talent.uuid, talent.attrs, talent.vType, talent.value + talent.value_add);
|
heroAttrs.addValueTal(talent.uuid, talent.attrs, talent.vType, talent.value + talent.value_add);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ export class SDataCom extends ecs.Comp {
|
|||||||
group:BoxSet=BoxSet.HERO
|
group:BoxSet=BoxSet.HERO
|
||||||
fac: number = 0; // 0:hero 1:monster
|
fac: number = 0; // 0:hero 1:monster
|
||||||
s_uuid:number=0
|
s_uuid:number=0
|
||||||
|
ext_dmg:number=0 //额外伤害
|
||||||
|
splash:number=0 //溅射伤害
|
||||||
|
dmg_ratio:number=1 //伤害比例
|
||||||
hit_count:number=0 //击中数量
|
hit_count:number=0 //击中数量
|
||||||
reset() {
|
reset() {
|
||||||
this.Attrs=null
|
this.Attrs=null
|
||||||
@@ -20,6 +23,9 @@ export class SDataCom extends ecs.Comp {
|
|||||||
this.s_uuid=0
|
this.s_uuid=0
|
||||||
this.caster=null
|
this.caster=null
|
||||||
this.hit_count=0
|
this.hit_count=0
|
||||||
|
this.ext_dmg=0
|
||||||
|
this.splash=0
|
||||||
|
this.dmg_ratio=1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class Skill extends ecs.Entity {
|
|||||||
this.addComponents<SMoveDataComp>(SMoveDataComp);
|
this.addComponents<SMoveDataComp>(SMoveDataComp);
|
||||||
}
|
}
|
||||||
load(startPos: Vec3, parent: Node, s_uuid: number, targetPos: Vec3,
|
load(startPos: Vec3, parent: Node, s_uuid: number, targetPos: Vec3,
|
||||||
caster:HeroViewComp,ext_dmg:number=0) {
|
caster:HeroViewComp,ext_dmg:number=0,splash:number=0) {
|
||||||
const config = SkillSet[s_uuid];
|
const config = SkillSet[s_uuid];
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
@@ -93,6 +93,8 @@ export class Skill extends ecs.Entity {
|
|||||||
sDataCom.Attrs={...cAttrsComp.Attrs}
|
sDataCom.Attrs={...cAttrsComp.Attrs}
|
||||||
sDataCom.s_uuid=s_uuid
|
sDataCom.s_uuid=s_uuid
|
||||||
sDataCom.fac=cAttrsComp.fac
|
sDataCom.fac=cAttrsComp.fac
|
||||||
|
sDataCom.ext_dmg=ext_dmg
|
||||||
|
sDataCom.splash=splash
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 模块资源释放 */
|
/** 模块资源释放 */
|
||||||
|
|||||||
@@ -201,10 +201,10 @@ console.log("道具1001数量:", itemInfo.result.data.count);
|
|||||||
const talents = await WxCloudApi.getTalents();
|
const talents = await WxCloudApi.getTalents();
|
||||||
|
|
||||||
// 添加天赋点
|
// 添加天赋点
|
||||||
const result = await WxCloudApi.addTalent(1001, 1);
|
const result = await WxCloudApi.addCountTal(1001, 1);
|
||||||
|
|
||||||
// 消耗天赋点
|
// 消耗天赋点
|
||||||
const result = await WxCloudApi.consumeTalent(1001, 1);
|
const result = await WxCloudApi.useCountTal(1001, 1);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 装备操作
|
### 装备操作
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
md extensions
|
|
||||||
cd extensions
|
|
||||||
|
|
||||||
IF EXIST oops-plugin-framework (
|
|
||||||
goto update
|
|
||||||
) ELSE (
|
|
||||||
goto clone
|
|
||||||
)
|
|
||||||
|
|
||||||
:clone
|
|
||||||
git clone -b master https://gitee.com/dgflash/oops-plugin-framework.git
|
|
||||||
|
|
||||||
:update
|
|
||||||
cd oops-plugin-framework
|
|
||||||
git pull
|
|
||||||
Reference in New Issue
Block a user