Files
heros/assets/script/game/hero/HeroViewComp.ts
panw 6386d6bd80 refactor(hero): 优化Buff和Debuff的数据结构及处理逻辑
- 新增移动速度相关属性:DBuff.SPEED和Attrs.SPEED
- 修改BattleMoveSystem中移动速度计算,支持速度百分比加成
- Buff和Debuff由数组改为基于属性键的对象存储,方便访问和合并处理
- 持久型Buff/Debuff累加数值或百分比,临时型则累加并刷新剩余时间
- 重新计算属性时遍历键值对,跳过状态类debuff(attrField=-1)
- 更新临时型Buff/Debuff剩余时间,过期时从对象中删除
- 代码结构更清晰,访问及更新性能提升
2025-10-17 10:27:21 +08:00

869 lines
30 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 { Vec3, _decorator , v3,Collider2D,Contact2DType,Label ,Node,Prefab,instantiate,ProgressBar, Component, Material, Sprite, math, clamp, Game, tween, Color, BoxCollider2D} 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 { HeroSpine } from "./HeroSpine";
import { BoxSet, FacSet } from "../common/config/BoxSet";
import { smc } from "../common/SingletonModuleComp";
import { Timer } from "../../../../extensions/oops-plugin-framework/assets/core/common/timer/Timer";
import { Attrs, DBuff, SkillSet, BType, BuffConf, DbuffConf, getAttrFieldFromDebuff } from "../common/config/SkillSet";
import { BuffComp } from "./BuffComp";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { FightSet, TooltipTypes } from "../common/config/Mission";
import { RandomManager } from "db://oops-framework/core/common/random/RandomManager";
import { HeroInfo, HeroUpSet } from "../common/config/heroSet";
const { ccclass, property } = _decorator;
/**
* ==================== BUFF 系统使用说明 ====================
*
* 1. 系统架构:
* - V_BUFF/V_BUFFS: 数值型 buff持久/临时)
* - R_BUFF/R_BUFFS: 百分比型 buff持久/临时)
* - V_DBUFF/V_DBUFFS: 数值型 debuff持久/临时)
* - R_DBUFF/R_DBUFFS: 百分比型 debuff持久/临时)
*
* 2. 初始化(在英雄加载时自动调用):
* - initBuffsDebuffs(): 从 HeroInfo 读取初始配置
*
* 3. 添加 buff技能调用:
* const buffConf: BuffConf = {
* buff: Attrs.AP, // 增加攻击力
* BType: BType.VALUE, // 数值型
* buV: 10, // 增加值
* buC: 0, // 持久(0=持久, >0=持续时间)
* buR: 100 // 触发概率(100%)
* };
* heroView.addBuff(buffConf);
*
* 4. 添加 debuff技能调用:
* const dbuffConf: DbuffConf = {
* debuff: DBuff.STUN, // 眩晕
* BType: BType.VALUE, // 数值型
* dev: 20, // 减少值
* deC: 3, // 持续3秒
* deR: 100 // 触发概率(100%)
* };
* heroView.addDebuff(dbuffConf);
*
* 5. 百分比型示例:
* // 增加20%攻击力
* heroView.addBuff({
* buff: Attrs.AP,
* BType: BType.RATIO, // 百分比型
* buV: 20, // 20%
* buC: 5, // 持续5秒
* buR: 100
* });
*
* 6. 移除 buff/debuff:
* heroView.removeBuff(Attrs.AP, false); // 移除持久 AP buff
* heroView.removeDebuff(DBuff.STUN, true); // 移除临时眩晕
*
* 7. 属性计算:
* - 每次 buff/debuff 变动时自动调用 recalculateAttrs()
* - 重新计算基础属性 + 所有 buff/debuff 的结果
* - 临时 buff/debuff 在 update 中按时间递减
*
* 8. 初始值属性:
* - base_hp, base_mp, base_def, base_ap, base_map 是初始值
* - 百分比 buff/debuff 基于这些初始值计算
* - 其他属性默认为 0无初始值
*/
/** 角色显示组件 */
@ccclass('HeroViewComp') // 定义为 Cocos Creator 组件
@ecs.register('HeroView', false) // 定义为 ECS 组件
export class HeroViewComp extends CCComp {
BUFFCOMP:BuffComp=null!
as: HeroSpine = null!
status:String = "idle"
hero_uuid:number = 1001;
hero_name : string = "hero";
lv:number =1;
scale: number = 1; /** 角色阵营 1hero -1 :mon */
type: number = 0; /**角色类型 0近战-需要贴身 1远程-保持距离 2辅助 */
fac:number=0; //阵营 0hero 1monster
box_group:number = BoxSet.HERO;
is_dead:boolean = false; //是否摧毁
is_count_dead:boolean = false; //是否计数死亡
is_stop:boolean = false;
is_atking:boolean = false;
is_boss:boolean = false;
is_big_boss:boolean = false;
is_master:boolean =false;
is_friend:boolean =false;
is_kalami:boolean =false;
speed: number = 100; /** 角色移动速度 */
mp: number = 100;
hp: number = 100; /** 血量 */
shield:number=0; //当前护甲值
/** 基础属性 有初始值的基础属性,后续Attrs 属性计算时用到*/
base_ap: number = 0; //基础攻击力
base_map: number = 0;
base_def: number = 5;
base_hp: number = 100;
base_mp: number = 100;
Attrs:any=[]
//数值型debuff - 改为键值对形式,可通过 V_DBUFF[Attrs.HP_MAX] 直接访问
V_DBUFF:Record<number, any> = {} //持久
R_DBUFF:Record<number, any> = {} //持久
V_BUFF:Record<number, any> = {} //持久
R_BUFF:Record<number, any> = {} //持久
V_DBUFFS:Record<number, any> = {} //临时 带时间
R_DBUFFS:Record<number, any> = {} //临时 带时间
V_BUFFS:Record<number, any> = {} //临时 带时间
R_BUFFS:Record<number, any> = {} //临时 带时间
atk_count: number = 0;
atked_count: number = 0;
speek_time:number = 0;
private damageQueue: Array<{
damage: number,
isCrit: boolean,
delay: number,
anm:string,
}> = [];
private isProcessingDamage: boolean = false;
private damageInterval: number = 0.01; // 伤害数字显示间隔
onLoad() {
this.as = this.getComponent(HeroSpine);
//console.log("[HeroViewComp]:hero view comp ",this.FIGHTCON)
this.on(GameEvent.FightEnd,this.do_fight_end,this)
const collider = this.node.getComponent(BoxCollider2D);
this.scheduleOnce(()=>{
if (collider) collider.enabled = true; // 先禁用
},1)
// let anm = this.node.getChildByName("anm")
// anm.setScale(anm.scale.x*0.8,anm.scale.y*0.8);
}
/** 视图层逻辑代码分离演示 */
start () {
this.as.idle()
this.BUFFCOMP=this.node.getComponent(BuffComp);
// console.log("[HeroViewComp]:heroview"+this.hero_name,this.Attrs)
/** 方向 */
this.node.setScale(this.scale,1);
this.node.getChildByName("top").setScale(this.scale,1);
if(this.is_boss){
this.node.getChildByName("top").position=v3(this.node.position.x,this.node.position.y+100,0)
}
/* 显示角色血量 */
this.node.getChildByName("top").getChildByName("hp").active = true;
this.BUFFCOMP.show_shield(this.shield,this.Attrs[Attrs.SHIELD_MAX])
}
// ==================== BUFF系统初始化 ====================
/**
* 初始化角色的 buff 和 debuff
* 从 HeroInfo 读取初始配置,建立属性系统
*/
initBuffsDebuffs() {
// 获取英雄配置
const heroInfo = HeroInfo[this.hero_uuid];
if (!heroInfo) return;
// 清空现有 buff/debuff
this.V_BUFF = {};
this.V_BUFFS = {};
this.R_BUFF = {};
this.R_BUFFS = {};
this.V_DBUFF = {};
this.V_DBUFFS = {};
this.R_DBUFF = {};
this.R_DBUFFS = {};
// 加载初始 buff
if (heroInfo.buff && heroInfo.buff.length > 0) {
for (const buffConf of heroInfo.buff) {
this.addBuff(buffConf);
}
}
// 加载初始 debuff
if (heroInfo.debuff && heroInfo.debuff.length > 0) {
for (const dbuffConf of heroInfo.debuff) {
this.addDebuff(dbuffConf);
}
}
// 重新计算所有属性
this.recalculateAttrs();
}
// ==================== BUFF管理 ====================
/**
* 添加 buff 效果
* @param buffConf buff 配置 (来自 SkillSet.BuffConf 或 heroSet.buff)
*/
addBuff(buffConf: BuffConf) {
// 基于类型和持续时间分类存储,使用属性作为键
const attrKey = buffConf.buff;
if (buffConf.BType === BType.VALUE) {
// 数值型 buff
if (buffConf.buC === 0) {
// 持久型 - 如果已存在,累加数值
if (this.V_BUFF[attrKey]) {
this.V_BUFF[attrKey].buV += buffConf.buV;
} else {
this.V_BUFF[attrKey] = {...buffConf};
}
} else {
// 临时型 - 如果已存在,累加数值并重置时间
if (this.V_BUFFS[attrKey]) {
this.V_BUFFS[attrKey].buV += buffConf.buV;
this.V_BUFFS[attrKey].remainTime = Math.max(this.V_BUFFS[attrKey].remainTime, buffConf.buC);
} else {
this.V_BUFFS[attrKey] = {
...buffConf,
remainTime: buffConf.buC
};
}
}
} else {
// 百分比型 buff
if (buffConf.buC === 0) {
// 持久型 - 如果已存在,累加百分比
if (this.R_BUFF[attrKey]) {
this.R_BUFF[attrKey].buV += buffConf.buV;
} else {
this.R_BUFF[attrKey] = {...buffConf};
}
} else {
// 临时型 - 如果已存在,累加百分比并重置时间
if (this.R_BUFFS[attrKey]) {
this.R_BUFFS[attrKey].buV += buffConf.buV;
this.R_BUFFS[attrKey].remainTime = Math.max(this.R_BUFFS[attrKey].remainTime, buffConf.buC);
} else {
this.R_BUFFS[attrKey] = {
...buffConf,
remainTime: buffConf.buC
};
}
}
}
// 立即重新计算属性
this.recalculateAttrs();
}
// ==================== DEBUFF管理 ====================
/**
* 添加 debuff 效果
* @param dbuffConf debuff 配置 (来自 SkillSet.DbuffConf 或 heroSet.debuff)
*
* 支持两种 debuff
* 1. 属性型 debuff直接修改属性值有对应的 Attrs
* 2. 状态型 debuff只缓存状态无对应的 Attrs用于状态检查
*/
addDebuff(dbuffConf: DbuffConf) {
// 获取 debuff 对应的属性字段
// attrField = -1 表示状态类 debuff只缓存不修改属性
// attrField >= 0 表示属性类 debuff会修改属性
const attrField = getAttrFieldFromDebuff(dbuffConf.debuff);
// 使用 debuff 类型作为键(支持状态类 debuffattrField = -1
const debuffKey = dbuffConf.debuff;
// 基于类型和持续时间分类存储
if (dbuffConf.BType === BType.VALUE) {
// 数值型 debuff
if (dbuffConf.deC === 0) {
// 持久型 - 如果已存在,累加数值
if (this.V_DBUFF[debuffKey]) {
this.V_DBUFF[debuffKey].dev += dbuffConf.dev;
} else {
this.V_DBUFF[debuffKey] = {
...dbuffConf,
attrField: attrField
};
}
} else {
// 临时型 - 如果已存在,累加数值并重置时间
if (this.V_DBUFFS[debuffKey]) {
this.V_DBUFFS[debuffKey].dev += dbuffConf.dev;
this.V_DBUFFS[debuffKey].remainTime = Math.max(this.V_DBUFFS[debuffKey].remainTime, dbuffConf.deC);
} else {
this.V_DBUFFS[debuffKey] = {
...dbuffConf,
attrField: attrField,
remainTime: dbuffConf.deC
};
}
}
} else {
// 百分比型 debuff
if (dbuffConf.deC === 0) {
// 持久型 - 如果已存在,累加百分比
if (this.R_DBUFF[debuffKey]) {
this.R_DBUFF[debuffKey].dev += dbuffConf.dev;
} else {
this.R_DBUFF[debuffKey] = {
...dbuffConf,
attrField: attrField
};
}
} else {
// 临时型 - 如果已存在,累加百分比并重置时间
if (this.R_DBUFFS[debuffKey]) {
this.R_DBUFFS[debuffKey].dev += dbuffConf.dev;
this.R_DBUFFS[debuffKey].remainTime = Math.max(this.R_DBUFFS[debuffKey].remainTime, dbuffConf.deC);
} else {
this.R_DBUFFS[debuffKey] = {
...dbuffConf,
attrField: attrField,
remainTime: dbuffConf.deC
};
}
}
}
// 立即重新计算属性
this.recalculateAttrs();
}
// ==================== 属性计算系统 ====================
/**
* 重新计算所有角色属性
* 基于基础属性 + 所有有效的 buff/debuff 计算
* 注意某些属性有初始值HP_MAX, MP_MAX, DEF, AP, MAP
*/
recalculateAttrs() {
// 1. 重置为基础值
this.Attrs[Attrs.HP_MAX] = this.base_hp;
this.Attrs[Attrs.MP_MAX] = this.base_mp;
this.Attrs[Attrs.DEF] = this.base_def;
this.Attrs[Attrs.AP] = this.base_ap;
this.Attrs[Attrs.MAP] = this.base_map;
this.Attrs[Attrs.SHIELD_MAX] = 0; // 护盾默认为 0
// 2. 初始化其他属性(无初始值的)
for (let i = 0; i <= 26; i++) {
if (!(i in this.Attrs) ||
(i !== Attrs.HP_MAX && i !== Attrs.MP_MAX && i !== Attrs.DEF &&
i !== Attrs.AP && i !== Attrs.MAP && i !== Attrs.SHIELD_MAX)) {
this.Attrs[i] = 0;
}
}
// 3. 应用数值型 buff (持久 + 临时)
this.applyValueBuffs();
// 4. 应用百分比型 buff (持久 + 临时)
this.applyRatioBuffs();
// 5. 应用数值型 debuff (持久 + 临时)
this.applyValueDebuffs();
// 6. 应用百分比型 debuff (持久 + 临时)
this.applyRatioDebuffs();
// 7. 确保关键属性不为负数
this.clampAttrs();
}
/**
* 应用数值型 buff
*/
private applyValueBuffs() {
// 持久型 buff
for (const attrKey in this.V_BUFF) {
const buff = this.V_BUFF[attrKey];
if (buff.buff !== undefined) {
this.Attrs[buff.buff] += buff.buV;
}
}
// 临时型 buff
for (const attrKey in this.V_BUFFS) {
const buff = this.V_BUFFS[attrKey];
if (buff.buff !== undefined) {
this.Attrs[buff.buff] += buff.buV;
}
}
}
/**
* 应用百分比型 buff
* 百分比型 buff 是基于基础属性的百分比增加
*/
private applyRatioBuffs() {
// 获取基础值映射
const baseValues: Record<number, number> = {};
baseValues[Attrs.HP_MAX] = this.base_hp;
baseValues[Attrs.MP_MAX] = this.base_mp;
baseValues[Attrs.DEF] = this.base_def;
baseValues[Attrs.AP] = this.base_ap;
baseValues[Attrs.MAP] = this.base_map;
// 持久型 buff
for (const attrKey in this.R_BUFF) {
const buff = this.R_BUFF[attrKey];
if (buff.buff !== undefined) {
const baseVal = baseValues[buff.buff] || this.Attrs[buff.buff];
this.Attrs[buff.buff] += Math.floor(baseVal * (buff.buV / 100));
}
}
// 临时型 buff
for (const attrKey in this.R_BUFFS) {
const buff = this.R_BUFFS[attrKey];
if (buff.buff !== undefined) {
const baseVal = baseValues[buff.buff] || this.Attrs[buff.buff];
this.Attrs[buff.buff] += Math.floor(baseVal * (buff.buV / 100));
}
}
}
/**
* 应用数值型 debuff
*/
private applyValueDebuffs() {
// 持久型 debuff
for (const debuffKey in this.V_DBUFF) {
const debuff = this.V_DBUFF[debuffKey];
// 跳过状态类 debuffattrField === -1
if (debuff.attrField !== undefined && debuff.attrField >= 0) {
this.Attrs[debuff.attrField] -= debuff.dev;
}
}
// 临时型 debuff
for (const debuffKey in this.V_DBUFFS) {
const debuff = this.V_DBUFFS[debuffKey];
// 跳过状态类 debuffattrField === -1
if (debuff.attrField !== undefined && debuff.attrField >= 0) {
this.Attrs[debuff.attrField] -= debuff.dev;
}
}
}
/**
* 应用百分比型 debuff
* 百分比型 debuff 是基于基础属性的百分比减少
*/
private applyRatioDebuffs() {
// 获取基础值映射
const baseValues: Record<number, number> = {};
baseValues[Attrs.HP_MAX] = this.base_hp;
baseValues[Attrs.MP_MAX] = this.base_mp;
baseValues[Attrs.DEF] = this.base_def;
baseValues[Attrs.AP] = this.base_ap;
baseValues[Attrs.MAP] = this.base_map;
// 持久型 debuff
for (const debuffKey in this.R_DBUFF) {
const debuff = this.R_DBUFF[debuffKey];
// 跳过状态类 debuffattrField === -1
if (debuff.attrField !== undefined && debuff.attrField >= 0) {
const baseVal = baseValues[debuff.attrField] || this.Attrs[debuff.attrField];
this.Attrs[debuff.attrField] -= Math.floor(baseVal * (debuff.dev / 100));
}
}
// 临时型 debuff
for (const debuffKey in this.R_DBUFFS) {
const debuff = this.R_DBUFFS[debuffKey];
// 跳过状态类 debuffattrField === -1
if (debuff.attrField !== undefined && debuff.attrField >= 0) {
const baseVal = baseValues[debuff.attrField] || this.Attrs[debuff.attrField];
this.Attrs[debuff.attrField] -= Math.floor(baseVal * (debuff.dev / 100));
}
}
}
/**
* 确保关键属性不为负数
*/
private clampAttrs() {
// HP_MAX 最少 1
this.Attrs[Attrs.HP_MAX] = Math.max(1, this.Attrs[Attrs.HP_MAX]);
// MP_MAX 最少 1
this.Attrs[Attrs.MP_MAX] = Math.max(1, this.Attrs[Attrs.MP_MAX]);
// DEF 最少 0
this.Attrs[Attrs.DEF] = Math.max(0, this.Attrs[Attrs.DEF]);
// AP 最少 0
this.Attrs[Attrs.AP] = Math.max(0, this.Attrs[Attrs.AP]);
// MAP 最少 0
this.Attrs[Attrs.MAP] = Math.max(0, this.Attrs[Attrs.MAP]);
// 百分比属性限制在 0-100 之间
this.Attrs[Attrs.CRITICAL] = Math.max(0, Math.min(85, this.Attrs[Attrs.CRITICAL]));
this.Attrs[Attrs.DODGE] = Math.max(0, Math.min(85, this.Attrs[Attrs.DODGE]));
this.Attrs[Attrs.HIT] = Math.max(0, Math.min(85, this.Attrs[Attrs.HIT]));
}
// ==================== 临时 BUFF/DEBUFF 更新 ====================
/**
* 更新临时 buff/debuff 的剩余时间
* 应在 update 中定期调用
* @param dt 时间差
*/
updateTemporaryBuffsDebuffs(dt: number) {
let needRecalculate = false;
// 更新临时型数值 buff
for (const attrKey in this.V_BUFFS) {
this.V_BUFFS[attrKey].remainTime -= dt;
if (this.V_BUFFS[attrKey].remainTime <= 0) {
delete this.V_BUFFS[attrKey];
needRecalculate = true;
}
}
// 更新临时型百分比 buff
for (const attrKey in this.R_BUFFS) {
this.R_BUFFS[attrKey].remainTime -= dt;
if (this.R_BUFFS[attrKey].remainTime <= 0) {
delete this.R_BUFFS[attrKey];
needRecalculate = true;
}
}
// 更新临时型数值 debuff
for (const debuffKey in this.V_DBUFFS) {
this.V_DBUFFS[debuffKey].remainTime -= dt;
if (this.V_DBUFFS[debuffKey].remainTime <= 0) {
delete this.V_DBUFFS[debuffKey];
needRecalculate = true;
}
}
// 更新临时型百分比 debuff
for (const debuffKey in this.R_DBUFFS) {
this.R_DBUFFS[debuffKey].remainTime -= dt;
if (this.R_DBUFFS[debuffKey].remainTime <= 0) {
delete this.R_DBUFFS[debuffKey];
needRecalculate = true;
}
}
// 如果有 buff/debuff 过期,重新计算属性
if (needRecalculate) {
this.recalculateAttrs();
}
}
update(dt: number){
if(!smc.mission.play||smc.mission.pause) return
// if(this.is_dead) {
// this.ent.destroy();
// return
// }
this.BaseUp(dt)
// 更新所有按时间减少的buff和debuff
this.in_stop(dt);
// 处理伤害队列
this.processDamageQueue();
// 更新临时 buff/debuff 时间
this.updateTemporaryBuffsDebuffs(dt);
}
BaseUp(dt:number){
this.mp += HeroUpSet.MP*dt
this.hp += HeroUpSet.HP*dt
if(this.mp > this.Attrs[Attrs.MP_MAX]) this.mp = this.Attrs[Attrs.MP_MAX]
if(this.hp > this.Attrs[Attrs.HP_MAX]) this.hp = this.Attrs[Attrs.HP_MAX]
}
do_fight_end(){
this.as.do_buff()
}
get isActive() {
return this.ent.has(HeroViewComp) && this.node?.isValid;
}
//状态切换
status_change(type:string){
this.status=type
if(type == "idle"){
this.as.idle()
// this.as.change_default("idle")
}
if(type == "move"){
this.as.move()
// this.as.change_default("move")
}
}
add_shield(shield:number){
this.shield = this.Attrs[Attrs.SHIELD_MAX] +=shield
if(this.shield>0) this.BUFFCOMP.show_shield(this.shield,this.Attrs[Attrs.SHIELD_MAX])
}
health(hp: number = 0,is_num:boolean=true) {
this.BUFFCOMP.heathed();
let real_hp=0
let hp_max=this.Attrs[Attrs.HP_MAX]
let lost_hp=hp_max-this.hp
if(is_num){
if(lost_hp > hp){
real_hp=Math.floor(hp);
}else{
real_hp=lost_hp;
}
}else{
if(lost_hp > hp/100*hp_max){
real_hp=Math.floor(hp/100*hp_max);
}else{
real_hp=lost_hp;
}
}
if(real_hp > 0){
this.hp+=real_hp;
this.BUFFCOMP.tooltip(TooltipTypes.health,real_hp.toFixed(0));
}
this.BUFFCOMP.hp_show(this.hp,this.Attrs[Attrs.HP_MAX])
// this.update_vm
}
/** 静止时间 */
in_stop (dt: number) {
}
count_atk_count(){ //主将攻击
if(this.fac==FacSet.MON) return
this.atk_count+=1
}
do_dead(){
this.do_dead_trigger()
//console.log("[HeroViewComp]:角色死亡",this.hero_uuid)
if(this.is_count_dead) return
this.is_count_dead=true
if(this.fac==FacSet.MON){
this.scheduleOnce(()=>{
this.do_drop()
},0.1)
}
if(this.fac==FacSet.HERO){
this.scheduleOnce(()=>{
oops.message.dispatchEvent(GameEvent.HeroDead,{hero_uuid:this.hero_uuid})
},0.1)
}
if(this.fac==FacSet.HERO){
//console.log("[HeroViewComp]:英雄死亡")
// oops.message.dispatchEvent(GameEvent.FightEnd,{victory:false})
}
}
do_drop(){
}
do_atked(remainingDamage:number,
crit:number=0,crit_d:number=0,
burn_count:number=0,burn_value:number=0,
stun_time:number=0,stun_ratio:number=0,
frost_time:number=0,frost_ratio:number=0,
atked_anm:string="atked"
){
this.do_atked_trigger()
if(this.check_dodge()) return
let is_crit = this.check_crit(crit)
if(this == null) return;
let damage = this.count_damage(remainingDamage)
if(is_crit) {
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE+crit_d)/100))
}
// console.log(this.hero_name+"[HeroViewComp]:heroview :damage|hp|hp_max",damage,this.hp,this.Attrs[BuffAttr.HP_MAX])
damage=this.check_shield(damage)
if(damage <= 0) return
this.hp -= damage;
if(this.hp <= 0) {
if(this == null) return;
this.is_dead=true
if(this.BUFFCOMP){
this.BUFFCOMP.dead()
}
this.do_dead()
//console.log("[HeroViewComp]:dead,fac => "+(this.fac==FacSet.HERO?"hero":"monster"))
if(this.ent == null) return;
if(this.fac ==FacSet.HERO){
this.to_grave()
}else{
this.ent.destroy();
}
}
// this.update_vm
this.back()
this.showDamage(damage, is_crit,atked_anm);
}
//后退
back(){
if(this.fac==FacSet.MON) {
let tx=this.node.position.x+5
if(tx > 320) tx=320
tween(this.node).to(0.1, { position:v3(tx,this.node.position.y,0)}).start()
}
if(this.fac==FacSet.HERO) {
let tx=this.node.position.x-5
if(tx < -320) tx=-320
tween(this.node).to(0.1, { position:v3(tx,this.node.position.y,0)}).start()
}
}
//伤害计算 debuff 易伤
count_damage(remainingDamage:number){
return remainingDamage
}
check_shield(damage:number){
if(this.shield <= 0 ) return damage
if(this.shield >= damage){
this.shield -= damage
this.BUFFCOMP.tooltip(TooltipTypes.uskill,"*吸收*");
if(this.shield <= 0){
this.shield=this.Attrs[Attrs.SHIELD_MAX]=0
}
damage = 0
}
if(this.shield < damage){
damage=damage-this.shield
this.shield=0
this.Attrs[Attrs.SHIELD_MAX]=0
}
this.BUFFCOMP.show_shield(this.shield,this.Attrs[Attrs.SHIELD_MAX])
return damage
}
check_dodge(){
if(this.Attrs[Attrs.DODGE] > 0){
let random = Math.random()*100
if(random < this.Attrs[Attrs.DODGE]) {
this.BUFFCOMP.tooltip(TooltipTypes.uskill,"*闪避*");
return true
}
}
return false
}
check_crit(crit:number=0){
if(crit > 0){
let random = Math.random()*100
if(random < crit) {
//console.log("[HeroViewComp]:crit",crit,random)
return true
}
}
//console.log("[HeroViewComp]:crit",crit)
return false
}
do_dead_trigger(){ //死亡特殊处理
if(this.is_dead||this.fac==FacSet.MON) return
}
do_atked_trigger(){ //受伤特殊处理
if(this.is_dead||this.fac==FacSet.MON) return
}
to_grave(){
tween(this.node).to(0.5, { position:v3(-900,this.node.position.y+300,0)},{
onComplete: (target?: object) => {
this.node.setPosition(-900,this.node.position.y-300,0)
}
}).start()
}
// to_alive(){
// this.is_dead=false
// this.currentHp=this.currentHpMax*(100+this.hp_buff)/100
// this.BUFFCOMP.vmdata_update(true)
// this.node.setPosition(HeroPos[this.fight_pos].pos)
// this.BUFFCOMP.heathed()
// }
to_console(value:any,value2:any=null,value3:any=null){
//console.log("["+this.scale+this.hero_name+']'+value,value2,value3)
}
reset() {
this.is_dead = false;
const collider = this.getComponent(Collider2D);
if (collider) {
collider.off(Contact2DType.BEGIN_CONTACT);
}
this.scheduleOnce(() => {
this.node.destroy();
}, 0.1);
}
playSkillEffect(skill_id:number) {
let skill = SkillSet[skill_id]
switch(skill.act){
case "max":
this.as.max()
this.BUFFCOMP.tooltip(TooltipTypes.skill,skill.name,skill_id)
break
case "atk":
this.as.atk()
break
}
}
/** 显示伤害数字 */
showDamage(damage: number, isCrit: boolean,anm:string="atked") {
this.damageQueue.push({
damage,
isCrit,
delay: this.damageInterval,
anm
});
}
ex_show(text:string){
switch(text){
case "blue":
this.BUFFCOMP.max_show("mr_blue")
break
case "red":
this.BUFFCOMP.max_show("mr_red")
break
}
}
/** 处理伤害队列 */
private processDamageQueue() {
if (this.isProcessingDamage || this.damageQueue.length === 0) return;
this.isProcessingDamage = true;
const damageInfo = this.damageQueue.shift()!;
this.showDamageImmediate(damageInfo.damage, damageInfo.isCrit,damageInfo.anm);
// 设置延时处理下一个伤害
this.scheduleOnce(() => {
this.isProcessingDamage = false;
}, this.damageInterval);
}
/** 立即显示伤害效果 */
private showDamageImmediate(damage: number, isCrit: boolean,anm:string="atked") {
// this.as.atked()
this.BUFFCOMP.hp_show(this.hp,this.Attrs[Attrs.HP_MAX])
this.BUFFCOMP.in_atked(anm,this.fac==FacSet.HERO?1:-1)
this.atked_count++;
if (isCrit) {
this.BUFFCOMP.hp_tip(TooltipTypes.crit, damage.toFixed(0), damage);
// //console.log("暴击伤害:" + damage);
} else {
this.BUFFCOMP.hp_tip(TooltipTypes.life, damage.toFixed(0), damage);
// //console.log("普通伤害:" + damage);
}
}
}