Files
heros/assets/script/game/hero/HeroViewComp.ts
2025-06-17 10:58:13 +08:00

411 lines
13 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} 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 { SkillSet, TargetGroup, TargetType } from "../common/config/SkillSet";
import { BuffComp } from "./BuffComp";
import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { FightConComp } from "../map/FightConComp";
import { EquipSpecialAttr } from "../common/config/Equips";
import { FightSet } from "../common/config/Mission";
import { HeroPos } from "../common/config/heroSet";
const { ccclass, property } = _decorator;
/** 角色显示组件 */
@ccclass('HeroViewComp') // 定义为 Cocos Creator 组件
@ecs.register('HeroView', false) // 定义为 ECS 组件
export class HeroViewComp extends CCComp {
FIGHTCON:FightConComp=null!
BUFFCOMP:BuffComp=null!
as: HeroSpine = null!
status:String = "idle"
hero_uuid:number = 1001;
hero_name : string = "hero";
fight_pos:number=0;
lv:number =1;
slv:number =1;
scale: number = 1; /** 角色阵营 1hero -1 :mon */
type: number = 0; /**角色类型 0近战-需要贴身 1远程-保持距离 2辅助 */
fac:number=0; //阵营 0hero 1monster
atk_range:number = 150;
box_group:number = BoxSet.HERO;
is_dead:boolean = false; //是否摧毁
is_stop:boolean = false;
is_atking:boolean = false;
is_boss:boolean = false;
is_big_boss:boolean = false;
is_master:boolean =false;
ap_u:number=0;
ap_ur:number=0;
hp_up:number=0;
hp: number = 100; /** 血量 */
hp_max: number = 100; /** 最大血量 */
hp_speed: number = 0; //每秒回复量
pwt:Timer = new Timer(1); //计时器
ap: number = 10; /**攻击力 */
// atk_speed: number = 1;
cd: number = 1.3; /**攻击速度 攻击间隔 */
dis: number = 80;
at: number = 0; /** 冷却时间 */
atk_skill:number=0;
def: number = 0; //防御
vun: number = 0; //易伤
dodge: number = 10; //闪避率
shield:number = 0; //护盾,免伤1次减1
speed: number = 100; /** 角色移动速度 */
ospeed: number = 100; /** 角色初始速度 */
atk_count: number = 0;
atked_count: number = 0;
stop_cd: number = 0; /*停止倒计时*/
yun_cd: number = 0; //眩晕倒计时
ice_cd: number = 0; //冰冻倒计时
dir_y:number = 0;
speek_time:number = 0;
is_stop_temp:boolean = false;i
Friend_alive_cd:Timer=new Timer(10)
private damageQueue: Array<{
damage: number,
isCrit: boolean,
delay: number
}> = [];
private isProcessingDamage: boolean = false;
private damageInterval: number = 0.2; // 伤害数字显示间隔
private timer:Timer=new Timer(1);
onLoad() {
this.as = this.getComponent(HeroSpine);
this.FIGHTCON=this.node.parent.getComponent(FightConComp);
console.log("hero view comp ",this.FIGHTCON)
this.on(GameEvent.ChangeATK,this.change_atk,this)
this.on(GameEvent.ChangeATK_EQUIP_SPECIAL_ATTR,this.change_equip_special_attr,this)
// 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);
/** 方向 */
this.node.setScale(this.scale,1);
this.node.getChildByName("top").setScale(this.scale,1);
if(this.is_boss){
this.node.setScale(this.node.scale.x*1.5,this.node.scale.y*1.5);
this.node.getChildByName("top").getChildByName("sboss").active = true;
}
/* 显示角色血量 */
this.node.getChildByName("top").getChildByName("hp").active = true;
this.Friend_alive_cd=new Timer(FightSet.FRIEND_LIVE_CD)
}
update(dt: number){
if(!smc.mission.play||smc.mission.pause) return
// if(this.is_dead) {
// this.ent.destroy();
// return
// }
if(this.is_dead) {
if(this.Friend_alive_cd.update(dt)){
console.log("alive friend")
this.to_alive()
}
}
if(this.timer.update(dt)){
// this.add_ap(10)
};
if(this.ice_cd > 0){
this.ice_cd -=dt;
return
}
if(this.yun_cd > 0){
this.yun_cd -=dt;
return
}
this.in_stop(dt);
// 处理伤害队列
this.processDamageQueue();
}
change_equip_special_attr(e:GameEvent,data:any){
console.log("change_equip_special_attr",data)
this.up_friend_alive_cd(data.friend_live_cd_less)
}
up_friend_alive_cd(less:number){
this.Friend_alive_cd=new Timer(FightSet.FRIEND_LIVE_CD-less)
}
change_atk(e:GameEvent,data:any){
switch(data){
case EquipSpecialAttr.ICE:
this.atk_skill=6001
break
case EquipSpecialAttr.FIRE:
this.atk_skill=6002
break
case EquipSpecialAttr.WIND:
this.atk_skill=6003
break
default:
this.atk_skill=6001
break
}
}
get isActive() {
return this.ent.has(HeroViewComp) && this.node?.isValid;
}
hide_info(){
this.node.getChildByName("top").getChildByName("ihp").active = false;
this.node.getChildByName("top").getChildByName("iap").active = false;
}
//状态切换
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 =shield
if(this.shield>0) this.BUFFCOMP.show_shield(true)
}
// add_cd(cd: number){
// this.cd += this.cd*((100-cd)/100);
// this.BUFFCOMP.buff_get("cd")
// }
/**
* 增加英雄的攻击AP
* @param ap 要增加的攻击。
*/
add_ap(ap: number,is_num:boolean=true){
if(is_num){
this.ap += Math.floor(ap);
}else{
this.ap += Math.floor(ap/100*this.ap);
}
this.BUFFCOMP.update_info_ap()
}
de_ap(ap: number,is_num:boolean=true){
if(is_num){
this.ap -= Math.floor(ap);
}else{
this.ap -= Math.floor(ap/100*this.ap);
}
this.BUFFCOMP.update_info_ap()
}
add_hp_max(hp: number=0,is_num:boolean=true){
if(is_num){
this.hp_max += Math.floor(hp) ;
this.hp += Math.floor(hp) ;
}else{
this.hp_max += Math.floor(hp/100*this.hp_max);
this.hp += Math.floor(hp/100*this.hp_max);
}
this.BUFFCOMP.update_info_hp()
}
de_hp_max(hp: number=0,is_num:boolean=true){
if(is_num){
this.hp_max -= Math.floor(hp) ;
}else{
this.hp_max -= Math.floor(hp/100*this.hp_max);
}
this.BUFFCOMP.update_info_hp()
}
add_hp(hp: number = 0,is_num:boolean=true) {
this.BUFFCOMP.heathed();
if(is_num){
this.hp+=Math.floor(hp);
}else{
this.hp+=Math.floor(hp/100*this.hp_max);
}
if(this.hp > this.hp_max){
this.hp = this.hp_max;
}
this.BUFFCOMP.tooltip(2,hp.toFixed(0));
}
/** 静止时间 */
in_stop (dt: number) {
if(this.stop_cd > 0){
this.stop_cd -= dt;
if(this.stop_cd <= 0){
this.stop_cd = 0;
this.is_atking = false;
}
}
}
do_change(){
this.BUFFCOMP.update_info_ap()
this.BUFFCOMP.update_info_hp()
this.BUFFCOMP.update_info_lv()
}
do_update(){
this.BUFFCOMP.update_info_ap()
this.BUFFCOMP.update_info_hp()
this.BUFFCOMP.update_info_lv()
}
do_dead(){
console.log("角色死亡",this.hero_uuid)
if(this.is_master){
console.log("英雄死亡")
oops.message.dispatchEvent(GameEvent.FightEnd,{victory:false})
}
}
do_atked(remainingDamage:number){
if (this.shield > 0) {
this.shield -= 1
this.BUFFCOMP.tooltip(5,"*吸收*");
remainingDamage = 0
if (this.shield <= 0) {
if(this == null) return;
this.BUFFCOMP.show_shield(false);
}
}else{
if(this == null) return;
this.hp -= remainingDamage;
if(this.hp <= 0) {
if(this == null) return;
this.is_dead=true
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.BUFFCOMP.update_info_hp()
this.showDamage(remainingDamage, true);
}
}
dead(){
this.BUFFCOMP.dead()
this.to_drop()
}
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.hp=this.hp_max
this.BUFFCOMP.update_info_hp()
this.node.setPosition(HeroPos[this.fight_pos].pos)
this.BUFFCOMP.heathed()
}
//掉落物品
to_drop(){
// let Drops = getMonsterDrops(1, MonsterType.Normal, 1.2);
// if(this.is_boss) Drops =getMonsterDrops(1, MonsterType.Elite, 1.2);
// if(this.is_big_boss) Drops =getMonsterDrops(1, MonsterType.Boss, 1.2);
}
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.max_show(skill.fname)
this.BUFFCOMP.tooltip(3,skill.name,skill_id)
break
case "atk":
this.as.atk()
break
}
}
to_update(){
this.ap=this.ap*this.lv
}
/** 显示伤害数字 */
showDamage(damage: number, isCrit: boolean) {
this.damageQueue.push({
damage,
isCrit,
delay: this.damageInterval
});
}
/** 处理伤害队列 */
private processDamageQueue() {
if (this.isProcessingDamage || this.damageQueue.length === 0) return;
this.isProcessingDamage = true;
const damageInfo = this.damageQueue.shift()!;
this.showDamageImmediate(damageInfo.damage, damageInfo.isCrit);
// 设置延时处理下一个伤害
this.scheduleOnce(() => {
this.isProcessingDamage = false;
}, this.damageInterval);
}
/** 立即显示伤害效果 */
private showDamageImmediate(damage: number, isCrit: boolean) {
this.BUFFCOMP.in_atked();
this.atked_count++;
if (isCrit) {
this.BUFFCOMP.tooltip(4, damage.toFixed(0), damage);
// console.log("暴击伤害:" + damage);
} else {
this.BUFFCOMP.tooltip(1, damage.toFixed(0), damage);
// console.log("普通伤害:" + damage);
}
}
}