Files
heros/assets/script/game/hero/HeroViewComp.ts
panw 4706a128f3 refactor(buff): 统一buff和debuff属性结构及类型区分
- 新增Buff类型枚举BType,区分数值型与百分比型属性
- 定义AttrsType,映射每个属性的类型(数值或百分比)
- 添加辅助方法isRatioAttr和getAttrType用于属性类型判断
- HeroViewComp中buff和debuff相关属性名称重新命名,区分持久型和临时型及属性类型
- 修改buff/debuff的加载、应用、更新逻辑,适配新的属性结构
- 新增HeroViewComp的isStun和isFrost方法判断状态
- BattleMoveSystem中使用新判断方法替代旧列表遍历
- 移除SkillCom中未使用的BuffAttr导入项,优化依赖关系
2025-10-17 18:41:54 +08:00

829 lines
27 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. 系统架构:
* - BUFF_V/BUFFS_V: 数值型 buff持久/临时)
* - BUFF_R/BUFFS_R: 百分比型 buff持久/临时)
* - DBUFF_V/DBUFFS_V: 数值型 debuff持久/临时)
* - DBUFF_R/DBUFFS_R: 百分比型 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;
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;
base_speed: number = 100; /** 角色移动速度 */
Attrs:any=[]
//数值型debuff
DBUFF_V:any[]=[] //持久
DBUFF_R:any[]=[] //持久
BUFF_V:any[]=[] //持久
BUFF_R:any[]=[] //持久
DBUFFS_V:any[]=[] //临时 带时间
DBUFFS_R:any[]=[] //临时 带时间
BUFFS_V:any[]=[] //临时 带时间
BUFFS_R: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.BUFF_V = [];
this.BUFFS_V = [];
this.BUFF_R = [];
this.BUFFS_R = [];
this.DBUFF_V = [];
this.DBUFFS_V = [];
this.DBUFF_R = [];
this.DBUFFS_R = [];
// 加载初始 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) {
// 基于类型和持续时间分类存储
if (buffConf.BType === BType.VALUE) {
// 数值型 buff
if (buffConf.buC === 0) {
// 持久型
this.BUFF_V.push({...buffConf});
} else {
// 临时型 - 添加剩余时间属性
this.BUFFS_V.push({
...buffConf,
remainTime: buffConf.buC
});
}
} else {
// 百分比型 buff
if (buffConf.buC === 0) {
// 持久型
this.BUFF_R.push({...buffConf});
} else {
// 临时型 - 添加剩余时间属性
this.BUFFS_R.push({
...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);
// 基于类型和持续时间分类存储
if (dbuffConf.BType === BType.VALUE) {
// 数值型 debuff
if (dbuffConf.deC === 0) {
// 持久型
this.DBUFF_V.push({
...dbuffConf,
attrField: attrField
});
} else {
// 临时型 - 添加剩余时间属性
this.DBUFFS_V.push({
...dbuffConf,
attrField: attrField,
remainTime: dbuffConf.deC
});
}
} else {
// 百分比型 debuff
if (dbuffConf.deC === 0) {
// 持久型
this.DBUFF_R.push({
...dbuffConf,
attrField: attrField
});
} else {
// 临时型 - 添加剩余时间属性
this.DBUFFS_R.push({
...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.SPEED] = this.base_speed;
this.Attrs[Attrs.SHIELD_MAX] = 0; // 护盾默认为 0
// 2. 初始化其他属性(无初始值的)
let length = Object.keys(this.Attrs).length;
for (let i = 0; i < length; 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&&13 && i !== Attrs.SPEED)) {
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 buff of this.BUFF_V) {
if (buff.buff !== undefined) {
this.Attrs[buff.buff] += buff.buV;
}
}
// 临时型 buff
for (const buff of this.BUFFS_V) {
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;
baseValues[Attrs.SPEED] = this.base_speed;
// 持久型 buff
for (const buff of this.BUFF_R) {
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 buff of this.BUFFS_R) {
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 debuff of this.DBUFF_V) {
// 跳过状态类 debuffattrField === -1
if (debuff.attrField !== undefined && debuff.attrField >= 0) {
this.Attrs[debuff.attrField] -= debuff.deV;
}
}
// 临时型 debuff
for (const debuff of this.DBUFFS_V) {
// 跳过状态类 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;
this.Attrs[Attrs.SPEED] = this.base_speed;
// 持久型 debuff
for (const debuff of this.DBUFF_R) {
// 跳过状态类 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 debuff of this.DBUFFS_R) {
// 跳过状态类 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 (let i = this.BUFFS_V.length - 1; i >= 0; i--) {
this.BUFFS_V[i].remainTime -= dt;
if (this.BUFFS_V[i].remainTime <= 0) {
this.BUFFS_V.splice(i, 1);
needRecalculate = true;
}
}
// 更新临时型百分比 buff
for (let i = this.BUFFS_R.length - 1; i >= 0; i--) {
this.BUFFS_R[i].remainTime -= dt;
if (this.BUFFS_R[i].remainTime <= 0) {
this.BUFFS_R.splice(i, 1);
needRecalculate = true;
}
}
// 更新临时型数值 debuff
for (let i = this.DBUFFS_V.length - 1; i >= 0; i--) {
this.DBUFFS_V[i].remainTime -= dt;
if (this.DBUFFS_V[i].remainTime <= 0) {
this.DBUFFS_V.splice(i, 1);
needRecalculate = true;
}
}
// 更新临时型百分比 debuff
for (let i = this.DBUFFS_R.length - 1; i >= 0; i--) {
this.DBUFFS_R[i].remainTime -= dt;
if (this.DBUFFS_R[i].remainTime <= 0) {
this.DBUFFS_R.splice(i, 1);
needRecalculate = true;
}
}
// 如果有 buff/debuff 过期,重新计算属性
if (needRecalculate) {
this.recalculateAttrs();
}
}
public isStun() {
return this.DBUFF_V.some(d => d.debuff === DBuff.STUN)
}
public isFrost() {
return this.DBUFF_V.some(d => d.debuff === DBuff.FROST)
}
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);
}
}
}