Files
heros/assets/script/game/hero/HeroViewComp.ts
walkpan 94f83482fa refactor(config): 修改 Buff/Debuff 接口字段命名
- 将 DbuffConf 中的属性 deV, deC, deR 重命名为 value, time, chance
- 将 BuffConf 中的属性 buV, buC, buR 重命名为 value, time, chance
- 统一代码中 Buff 和 Debuff 配置的字段命名,提升可读性和一致性
2025-10-17 19:46:31 +08:00

767 lines
26 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(æŒ<C3A6>ï¿?临时ï¿?
* - BUFF_R/BUFFS_R: 百分比型 buff(æŒ<C3A6>ï¿?临时ï¿?
* - DBUFF_V/DBUFFS_V: 数值型 debuff(æŒ<C3A6>ï¿?临时ï¿?
* - DBUFF_R/DBUFFS_R: 百分比型 debuff(æŒ<C3A6>ï¿?临时ï¿?
*
* 2. 智能覆盖规则�
* - 值æ´å°<C3A5>:ä¸<C3A4>添加(弱效果ä¸<C3A4>覆ç强效果)
* - 值ç¸å<C2B8>Œä¸”临时:å<C5A1> åŠ æ—¶ï¿?
* - 值更大:更新为新值(临时则更新值和时间�
*
* 3. 性能优化�
* - 增é‡<C3A9>计算:添ï¿?删除时å<C2B6>ªé‡<C3A9>ç®—å<E28094>—å½±å“<C3A5>的属�?
* - 批é‡<C3A9>计算:initBuffsDebuffs() 中使ï¿?recalculateAttrs() 一次性计算所ï¿?
*/
/** 角色显示组件 */
@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; /** è§è‰²é˜µè<C2B5>¥ 1:hero -1 :mon */
type: number = 0; /**角色类型 0è¿æˆ˜-需è¦<C3A8>è´´ï¿?1远ç¨-ä¿<C3A4>æŒ<C3A6>è·<C3A8>离 2辅助 */
fac:number=0; //阵è<C2B5>¥ 0:hero 1:monster
box_group:number = BoxSet.HERO;
is_dead:boolean = false; //是å<C2AF>¦æ§æ¯<C3A6>
is_count_dead:boolean = false; //是å<C2AF>¦è®¡æ•°æ­»äº¡
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; //当å‰<C3A5>护甲ï¿?
/** 基础属�?有åˆ<C3A5>å§å€¼çš„基础属�?å<>Žç»­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=[]
// Buff/Debuff 字典结构,通过属性索引直接访�
// 结构: { [attrIndex: number]: { value: number, remainTime?: number } }
DBUFF_V: Record<number, {value: number}> = {} // æŒ<C3A6>ä¹…åžæ•°ï¿?debuff
DBUFF_R: Record<number, {value: number}> = {} // æŒ<C3A6>ä¹…åžç™¾åˆ†æ¯” debuff
BUFF_V: Record<number, {value: number}> = {} // æŒ<C3A6>ä¹…åžæ•°ï¿?buff
BUFF_R: Record<number, {value: number}> = {} // æŒ<C3A6>ä¹…åžç™¾åˆ†æ¯” buff
DBUFFS_V: Record<number, {value: number, remainTime: number}> = {} // 临时型数�debuff
DBUFFS_R: Record<number, {value: number, remainTime: number}> = {} // 临时型百分比 debuff
BUFFS_V: Record<number, {value: number, remainTime: number}> = {} // 临时型数�buff
BUFFS_R: Record<number, {value: number, remainTime: number}> = {} // 临时型百分比 buff
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; // å…ˆç¦<C3A7>ï¿?
},1)
// let anm = this.node.getChildByName("anm")
// anm.setScale(anm.scale.x*0.8,anm.scale.y*0.8);
}
/** 视å¾å±é€»è¾ä»£ç <C3A7>分离演示 */
start () {
this.as.idle()
this.BUFFCOMP=this.node.getComponent(BuffComp);
// console.log("[HeroViewComp]:heroview"+this.hero_name,this.Attrs)
/** æ¹å<C2B9> */
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系统åˆ<C3A5>å§ï¿?====================
/**
* åˆ<C3A5>å§åŒè§è‰²çš„ buff ï¿?debuff
* ï¿?HeroInfo 读å<C2BB>åˆ<C3A5>å§é…<C3A9>置,建ç«å±žæ€§ç³»ï¿?
*/
initBuffsDebuffs() {
// 清空现有 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 = {};
// 获å<C2B7>è±é„é…<C3A9>ç½®
const heroInfo = HeroInfo[this.hero_uuid];
if (!heroInfo) return;
// 1. é‡<C3A9>置为基础ï¿?
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. åˆ<C3A5>å§åŒå…¶ä»å±žæ€§ï¼ˆæ— åˆ<C3A5>å§å€¼çš„ï¿?
for (const attrKey in this.Attrs) {
const attrIndex = parseInt(attrKey);
if(attrIndex !== Attrs.HP_MAX && attrIndex !== Attrs.MP_MAX && attrIndex !== Attrs.DEF && attrIndex !== Attrs.AP && attrIndex !== Attrs.MAP && attrIndex !== Attrs.SPEED) {
this.Attrs[attrIndex] = 0;
}
}
// 加载åˆ<C3A5>å§ buff
if (heroInfo.buff && heroInfo.buff.length > 0) {
for (const buffConf of heroInfo.buff) {
this.addBuff(buffConf);
}
}
// 加载åˆ<C3A5>å§ debuff
if (heroInfo.debuff && heroInfo.debuff.length > 0) {
for (const dbuffConf of heroInfo.debuff) {
this.addDebuff(dbuffConf);
}
}
}
// ==================== BUFF管ç<C2A1>† ====================
/**
* 添加 buff 效果(智能覆盖)
* @param buffConf buff é…<C3A9>ç½® (æ<>¥è‡ª SkillSet.BuffConf ï¿?heroSet.buff)
*
* 智能覆盖规则�
* 1. 值æ´å°<C3A5>:ä¸<C3A4>æ·»ï¿?
* 2. 值ç¸å<C2B8>Œä¸”都是临时:å<C5A1> åŠ æ—¶ï¿?
* 3. 值更大:更新为新值(临时则更新值和时间�
*/
addBuff(buffConf: BuffConf) {
const isValue = buffConf.BType === BType.VALUE;
const isPermanent = buffConf.time === 0;
const attrIndex = buffConf.buff;
// æ ¹æ<C2B9>®ç±»åžé€‰æ©å¯¹åº”ï¿?buff å­—å…¸
const permanentBuffs = isValue ? this.BUFF_V : this.BUFF_R;
const temporaryBuffs = isValue ? this.BUFFS_V : this.BUFFS_R;
if (isPermanent) {
// 添加æŒ<C3A6>ä¹…ï¿?buff
const existing = permanentBuffs[attrIndex];
if (existing) {
// 值æ´å°<C3A5>,ä¸<C3A4>æ·»ï¿?
if (buffConf.value <= existing.value) {
return;
}
// 值更大,更新
existing.value = buffConf.value;
} else {
// 没有å<E280B0>Œç±»åžï¼Œç´æŽ¥æ·»åŠ 
permanentBuffs[attrIndex] = { value: buffConf.value };
}
} else {
// 添加临时�buff
const existing = temporaryBuffs[attrIndex];
if (existing) {
if (buffConf.value < existing.value) {
// 值æ´å°<C3A5>,ä¸<C3A4>æ·»ï¿?
return;
} else if (buffConf.value === existing.value) {
// 值ç¸å<C2B8>Œï¼Œå<C592> åŠ æ—¶é—´
existing.remainTime += buffConf.time;
return; // æ—¶é—´å<C2B4> åŠ ä¸<C3A4>需è¦<C3A8>é‡<C3A9>算属ï¿?
} else {
// 值更大,更新值和时间
existing.value = buffConf.value;
existing.remainTime = buffConf.time;
}
} else {
// 没有å<E280B0>Œç±»åžï¼Œç´æŽ¥æ·»åŠ 
temporaryBuffs[attrIndex] = {
value: buffConf.value,
remainTime: buffConf.time
};
}
}
// å<>ªé‡<C3A9>æ°è®¡ç®—å<E28094>—å½±å“<C3A5>的属ï¿?
this.recalculateSingleAttr(buffConf.buff);
}
// ==================== DEBUFF管ç<C2A1>† ====================
/**
* 添加 debuff 效果(智能覆盖)
* @param dbuffConf debuff é…<C3A9>ç½® (æ<>¥è‡ª SkillSet.DbuffConf ï¿?heroSet.debuff)
*
* 支æŒ<C3A6>两ç§<C3A7> debuffï¿?
* 1. 属性型 debuffï¼šç´æŽ¥ä¿®æ”¹å±žæ€§å€¼ï¼ˆæœ‰å¯¹åº”çš„ Attrsï¿?
* 2. 状æ€<C3A6>åž debuff:å<C5A1>ªç¼“存状æ€<C3A6>(无对应的 Attrs,用于状æ€<C3A6>检查)
*
* 智能覆盖规则�
* 1. 值æ´å°<C3A5>:ä¸<C3A4>æ·»ï¿?
* 2. 值ç¸å<C2B8>Œä¸”都是临时:å<C5A1> åŠ æ—¶ï¿?
* 3. 值更大:更新为新值(临时则更新值和时间�
*/
addDebuff(dbuffConf: DbuffConf) {
// 获å<C2B7> debuff 对应的属性字ï¿?
// attrField = -1 表示状æ€<C3A6>ç±» debuff(å<CB86>ªç¼“存,ä¸<C3A4>修改属性)
// attrField >= 0 表示属性类 debuff(会修改属性)
const attrField = getAttrFieldFromDebuff(dbuffConf.debuff);
const isValue = dbuffConf.BType === BType.VALUE;
const isPermanent = dbuffConf.time === 0;
// æ ¹æ<C2B9>®ç±»åžé€‰æ©å¯¹åº”ï¿?debuff å­—å…¸
const permanentDebuffs = isValue ? this.DBUFF_V : this.DBUFF_R;
const temporaryDebuffs = isValue ? this.DBUFFS_V : this.DBUFFS_R;
// 状æ€<C3A6>ç±» debuff 使用 debuff 类型作为 key,属性类 debuff 使用 attrField 作为 key
const key = attrField >= 0 ? attrField : dbuffConf.debuff;
if (isPermanent) {
// 添加æŒ<C3A6>ä¹…ï¿?debuff
const existing = permanentDebuffs[key];
if (existing) {
// 值æ´å°<C3A5>,ä¸<C3A4>æ·»ï¿?
if (dbuffConf.value <= existing.value) {
return;
}
// 值更大,更新
existing.value = dbuffConf.value;
} else {
// 没有å<E280B0>Œç±»åžï¼Œç´æŽ¥æ·»åŠ 
permanentDebuffs[key] = { value: dbuffConf.value };
}
} else {
// 添加临时�debuff
const existing = temporaryDebuffs[key];
if (existing) {
if (dbuffConf.value < existing.value) {
// 值æ´å°<C3A5>,ä¸<C3A4>æ·»ï¿?
return;
} else if (dbuffConf.value === existing.value) {
// 值ç¸å<C2B8>Œï¼Œå<C592> åŠ æ—¶é—´
existing.remainTime += dbuffConf.time;
return; // æ—¶é—´å<C2B4> åŠ ä¸<C3A4>需è¦<C3A8>é‡<C3A9>算属ï¿?
} else {
// 值更大,更新值和时间
existing.value = dbuffConf.value;
existing.remainTime = dbuffConf.time;
}
} else {
// 没有å<E280B0>Œç±»åžï¼Œç´æŽ¥æ·»åŠ 
temporaryDebuffs[key] = {
value: dbuffConf.value,
remainTime: dbuffConf.time
};
}
}
// å<>ªé‡<C3A9>æ°è®¡ç®—å<E28094>—å½±å“<C3A5>的属性(状æ€<C3A6>ç±» debuff ä¸<C3A4>需è¦<C3A8>计算)
if (attrField >= 0) {
this.recalculateSingleAttr(attrField);
}
}
// ==================== 属性计算系�====================
/**
* é‡<C3A9>æ°è®¡ç®—å<E28094>•个属�?
* @param attrIndex 属性索�
*/
private recalculateSingleAttr(attrIndex: number) {
// 1. é‡<C3A9>置为基础ï¿?
const baseValues: Record<number, number> = {
[Attrs.HP_MAX]: this.base_hp,
[Attrs.MP_MAX]: this.base_mp,
[Attrs.DEF]: this.base_def,
[Attrs.AP]: this.base_ap,
[Attrs.MAP]: this.base_map,
[Attrs.SPEED]: this.base_speed,
[Attrs.SHIELD_MAX]: 0
};
this.Attrs[attrIndex] = baseValues[attrIndex] !== undefined ? baseValues[attrIndex] : 0;
// 2. 应用数值型 buff - 直接访问
if (this.BUFF_V[attrIndex]) {
this.Attrs[attrIndex] += this.BUFF_V[attrIndex].value;
}
if (this.BUFFS_V[attrIndex]) {
this.Attrs[attrIndex] += this.BUFFS_V[attrIndex].value;
}
// 3. 应用百分比型 buff - 直接访问
const baseVal = baseValues[attrIndex] !== undefined ? baseValues[attrIndex] : this.Attrs[attrIndex];
if (this.BUFF_R[attrIndex]) {
this.Attrs[attrIndex] += Math.floor(baseVal * (this.BUFF_R[attrIndex].value / 100));
}
if (this.BUFFS_R[attrIndex]) {
this.Attrs[attrIndex] += Math.floor(baseVal * (this.BUFFS_R[attrIndex].value / 100));
}
// 4. 应用数值型 debuff - 直接访问
if (this.DBUFF_V[attrIndex]) {
this.Attrs[attrIndex] -= this.DBUFF_V[attrIndex].value;
}
if (this.DBUFFS_V[attrIndex]) {
this.Attrs[attrIndex] -= this.DBUFFS_V[attrIndex].value;
}
// 5. 应用百分比型 debuff - 直接访问
if (this.DBUFF_R[attrIndex]) {
this.Attrs[attrIndex] -= Math.floor(baseVal * (this.DBUFF_R[attrIndex].value / 100));
}
if (this.DBUFFS_R[attrIndex]) {
this.Attrs[attrIndex] -= Math.floor(baseVal * (this.DBUFFS_R[attrIndex].value / 100));
}
// 6. ç¡®ä¿<C3A4>属性值å<C2BC>ˆï¿?
this.clampSingleAttr(attrIndex);
}
/**
* ç¡®ä¿<C3A4>å<EFBFBD>•个属性值å<C2BC>ˆï¿?
*/
private clampSingleAttr(attrIndex: number) {
switch(attrIndex) {
case Attrs.HP_MAX:
case Attrs.MP_MAX:
this.Attrs[attrIndex] = Math.max(1, this.Attrs[attrIndex]);
break;
case Attrs.DEF:
case Attrs.AP:
case Attrs.MAP:
this.Attrs[attrIndex] = Math.max(0, this.Attrs[attrIndex]);
break;
case Attrs.CRITICAL:
case Attrs.DODGE:
case Attrs.HIT:
this.Attrs[attrIndex] = Math.max(0, Math.min(85, this.Attrs[attrIndex]));
break;
}
}
// ==================== 临时 BUFF/DEBUFF 更新 ====================
/**
* 更新临时 buff/debuff 的剩余时�
* 应在 update 中定期调�
* @param dt æ—¶é—´ï¿?
*/
updateTemporaryBuffsDebuffs(dt: number) {
const affectedAttrs = new Set<number>();
// 更新临时型数�buff
for (const attrIndex in this.BUFFS_V) {
const buff = this.BUFFS_V[attrIndex];
buff.remainTime -= dt;
if (buff.remainTime <= 0) {
delete this.BUFFS_V[attrIndex];
affectedAttrs.add(parseInt(attrIndex));
}
}
// 更新临时型百分比 buff
for (const attrIndex in this.BUFFS_R) {
const buff = this.BUFFS_R[attrIndex];
buff.remainTime -= dt;
if (buff.remainTime <= 0) {
delete this.BUFFS_R[attrIndex];
affectedAttrs.add(parseInt(attrIndex));
}
}
// 更新临时型数�debuff
for (const key in this.DBUFFS_V) {
const debuff = this.DBUFFS_V[key];
debuff.remainTime -= dt;
if (debuff.remainTime <= 0) {
delete this.DBUFFS_V[key];
affectedAttrs.add(parseInt(key));
}
}
// 更新临时型百分比 debuff
for (const key in this.DBUFFS_R) {
const debuff = this.DBUFFS_R[key];
debuff.remainTime -= dt;
if (debuff.remainTime <= 0) {
delete this.DBUFFS_R[key];
affectedAttrs.add(parseInt(key));
}
}
// å<>ªé‡<C3A9>æ°è®¡ç®—å<E28094>—å½±å“<C3A5>的属ï¿?
affectedAttrs.forEach(attrIndex => {
this.recalculateSingleAttr(attrIndex);
});
}
public isStun() {
return this.DBUFF_V[DBuff.STUN] !== undefined || this.DBUFFS_V[DBuff.STUN] !== undefined
}
public isFrost() {
return this.DBUFF_V[DBuff.FROST] !== undefined || this.DBUFFS_V[DBuff.FROST] !== undefined
}
update(dt: number){
if(!smc.mission.play||smc.mission.pause) return
// if(this.is_dead) {
// this.ent.destroy();
// return
// }
this.BaseUp(dt)
// æ´æ°æ‰€æœ‰æŒ‰æ—¶é—´å‡<C3A5>å°çš„buffåŒdebuff
this.in_stop(dt);
// 处ç<E2809E>†ä¼¤å®³é˜Ÿåˆ
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;
}
//状æ€<C3A6>切ï¿?
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,"*é—ªé<C2AA>¿*");
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(){ //死亡特殊处ç<E2809E>
if(this.is_dead||this.fac==FacSet.MON) return
}
do_atked_trigger(){ //å<>—伤特殊处ç<E2809E>
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
}
}
/** 处ç<E2809E>†ä¼¤å®³é˜Ÿåˆ— */
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);
// 设置延时处ç<E2809E>†ä¸ä¸€ä¸ªä¼¤ï¿?
this.scheduleOnce(() => {
this.isProcessingDamage = false;
}, this.damageInterval);
}
/** ç«å<E280B9>³æ˜¾ç¤ºä¼¤å®³æ•ˆæžœ */
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);
}
}
}