413 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			413 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名:Animation.nut
 | |
| 路径:User/Asset/Character/Animation.nut
 | |
| 创建日期:2024-12-12	16:43
 | |
| 文件用途:
 | |
| */
 | |
| class Character_Animation extends Actor {
 | |
| 
 | |
|     //角色对象
 | |
|     Parent = null;
 | |
|     //当前动画组
 | |
|     CurrentAni = null;
 | |
| 
 | |
|     //等待Ani
 | |
|     WaitingAni = null;
 | |
|     //移动Ani
 | |
|     MoveAni = null;
 | |
|     //蹲下Ani
 | |
|     SitAni = null;
 | |
|     //受伤Ani
 | |
|     DamageAni1 = null;
 | |
|     DamageAni2 = null;
 | |
|     //倒地Ani
 | |
|     DownAni = null;
 | |
|     //被击后退Ani
 | |
|     OverturnAni = null;
 | |
|     //跳跃Ani
 | |
|     JumoAni = null;
 | |
|     //跳跃攻击Ani
 | |
|     JumpAttackAni = null;
 | |
|     //站立Ani
 | |
|     RestAni = null;
 | |
|     //引导Ani
 | |
|     ThrowAni1_1 = null;
 | |
|     ThrowAni1_2 = null;
 | |
|     ThrowAni2_1 = null;
 | |
|     ThrowAni2_2 = null;
 | |
|     ThrowAni3_1 = null;
 | |
|     ThrowAni3_2 = null;
 | |
|     ThrowAni4_1 = null;
 | |
|     ThrowAni4_2 = null;
 | |
|     //奔跑Ani
 | |
|     DashAni = null;
 | |
|     //奔跑攻击Ani
 | |
|     DashAttackAni = null;
 | |
|     //拾取Ani
 | |
|     GetItemAni = null;
 | |
|     //释放BUFFAni
 | |
|     BuffAni = null;
 | |
|     //普通攻击Ani
 | |
|     AttackAni = null;
 | |
| 
 | |
|     //光环
 | |
|     AuroraAni = null;
 | |
| 
 | |
|     //名字
 | |
|     Name = null;
 | |
| 
 | |
|     ENUM_RINDRO_JOB_TITLE_HEIGHT = [
 | |
|         //男鬼剑士
 | |
|         {
 | |
|             x = -18,
 | |
|             y = -154
 | |
|         },
 | |
|         //女格斗
 | |
|         {
 | |
|             x = -18,
 | |
|             y = -140
 | |
|         },
 | |
|         //男神枪手
 | |
|         {
 | |
|             x = -20,
 | |
|             y = -168
 | |
|         },
 | |
|         //女魔法师
 | |
|         {
 | |
|             x = -22,
 | |
|             y = -126
 | |
|         },
 | |
|         //男圣职者
 | |
|         {
 | |
|             x = -22,
 | |
|             y = -166
 | |
|         },
 | |
|         //女神枪手
 | |
|         {
 | |
|             x = -18,
 | |
|             y = -156
 | |
|         },
 | |
|         //女暗夜使者
 | |
|         {
 | |
|             x = -20,
 | |
|             y = -154
 | |
|         },
 | |
|         //男格斗家
 | |
|         {
 | |
|             x = -21,
 | |
|             y = -160
 | |
|         },
 | |
|         //男魔法师
 | |
|         {
 | |
|             x = -21,
 | |
|             y = -140
 | |
|         },
 | |
|         //黑暗武士
 | |
|         {
 | |
|             x = -18,
 | |
|             y = -154
 | |
|         },
 | |
|         //缔造者
 | |
|         {
 | |
|             x = -22,
 | |
|             y = -126
 | |
|         },
 | |
|     ];
 | |
| 
 | |
|     constructor() {
 | |
|         base.constructor();
 | |
|     }
 | |
| 
 | |
|     //同步单部位动画
 | |
|     function SyncAnimationBySlot(Type, AniObj, Src) {
 | |
|         this[AniObj][Type] <- [];
 | |
| 
 | |
|         //如果有时装就初始化Ani
 | |
|         //除了皮肤 在没有的情况下初始化0
 | |
|         if (Type == "skin") {
 | |
|             local variation = [0, 0];
 | |
|             //如果存在皮肤就读取variation
 | |
|             if (Parent[Type] != null) {
 | |
|                 local AvaInfo = Parent[Type];
 | |
|                 local JobInfo = AvaInfo["Animation_Job"]["Ani_" + Parent.Info["job"]];
 | |
|                 variation = JobInfo["variation"];
 | |
|             }
 | |
|             local BufInfo = sq_DeepCopy(ScriptData.GetAni(Src));
 | |
|             local Ao = {
 | |
|                 ImgVariation = variation,
 | |
|                 ImgFormat = function(ImgPath) {
 | |
|                     if (ImgVariation[0] > 0) {
 | |
|                         local Pos = ImgPath.find("%04d");
 | |
|                         ImgPath = ImgPath.slice(0, Pos) + "%02d%02d" + ImgPath.slice(Pos + 4);
 | |
|                         return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                     } else {
 | |
|                         return format(ImgPath, ImgVariation[1]);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             local SkinAni = Animation(BufInfo, Ao);
 | |
|             //如果是皮肤Ani 绑定状态机 确保唯一性
 | |
|             SkinAni.BindenvStateMachine(Parent.StateMachine);
 | |
|             //将Ani类型设置为皮肤
 | |
|             SkinAni.Type = "skin";
 | |
|             //加入组
 | |
|             this[AniObj][Type].append(SkinAni);
 | |
|         } else {
 | |
|             //先判断类型
 | |
|             if (Parent[Type] != null) {
 | |
|                 local AvaInfo = Parent[Type];
 | |
|                 if (AvaInfo) {
 | |
|                     local JobInfo = AvaInfo["Animation_Job"]["Ani_" + Parent.Info["job"]];
 | |
|                     foreach(_index, value in JobInfo["layer_variation"]) {
 | |
|                         local BufInfo = sq_DeepCopy(ScriptData.GetAni(AvaInfo["DirPath"] + value["Path"] + Src.slice(Src.lastfind("/"))));
 | |
|                         local Ao = {
 | |
|                             ImgVariation = JobInfo["variation"],
 | |
|                             ImgFormat = function(ImgPath) {
 | |
|                                 return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                             }
 | |
|                         }
 | |
|                         local AniBuf = Animation(BufInfo, Ao);
 | |
|                         //设置Ani类型
 | |
|                         AniBuf.Type = Type;
 | |
|                         AniBuf.SetZOrder(value["Zorder"]);
 | |
|                         this[AniObj][Type].append(AniBuf);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //读取并设置Ani
 | |
|     function ReadAndSetAni(AniObj, Src, SlotType) {
 | |
|         //从父对象 也就是角色对象取得Info
 | |
|         local Info = Parent.Info;
 | |
|         //如果有这个标签Ani则初始化 获取ani路径
 | |
|         if (Info.rawin(Src)) Src = Info[Src];
 | |
|         else return;
 | |
| 
 | |
|         //如果不存在则构造
 | |
|         if (this[AniObj] == null) this[AniObj] = {};
 | |
| 
 | |
|         //如果没有传递装备类型就初始化所有
 | |
|         if (!SlotType) {
 | |
|             foreach(Type in getconsttable().AvatarType) {
 | |
|                 SyncAnimationBySlot(Type, AniObj, Src);
 | |
|             }
 | |
|         }
 | |
|         //否则只初始化这一件装备的
 | |
|         else {
 | |
|             //记录当前皮肤Ani的时间 确保唯一性
 | |
|             local AniTime = 0;
 | |
|             if (this.CurrentAni) AniTime = this.CurrentAni["skin"][0].CurrentIndexT;
 | |
|             //记录当前皮肤Ani的帧 确保唯一性
 | |
|             local AniFrameIndex = 0;
 | |
|             if (this.CurrentAni) AniFrameIndex = this.CurrentAni["skin"][0].CurrentFrameIndex;
 | |
|             //如果当前播放Ani是 构造的Ani 则移除 并清空
 | |
|             if (this.CurrentAni == this[AniObj]) {
 | |
|                 foreach(AniBuf in this.CurrentAni[SlotType]) {
 | |
|                     AniBuf.RemoveSelf();
 | |
|                 }
 | |
|             }
 | |
|             SyncAnimationBySlot(SlotType, AniObj, Src);
 | |
|             //如果当前播放Ani是 构造的Ani
 | |
|             if (this.CurrentAni == this[AniObj]) {
 | |
|                 //添加Ani 并设置为当前皮肤Ani的时间
 | |
|                 foreach(AniBuf in this.CurrentAni[SlotType]) {
 | |
|                     //一定要先添加 否则会导致动画时间混乱因为被添加时会刷新到0帧
 | |
|                     Addchild(AniBuf);
 | |
|                     AniBuf.CurrentIndexT = AniTime;
 | |
|                     AniBuf.FlushFrame(AniFrameIndex);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function ReadAndSetAttackAni() {
 | |
|         local AttackAniArrSrc = Info["attack_motion"];
 | |
|         AttackAni = array(AttackAniArrSrc.len());
 | |
|         foreach(_Index, Path in AttackAniArrSrc) {
 | |
|             local Src = Path;
 | |
|             AttackAni[_Index] = [];
 | |
|             foreach(Type in getconsttable().AvatarType) {
 | |
|                 //如果有时装就初始化Ani
 | |
|                 //除了皮肤 在没有的情况下初始化0
 | |
|                 if (Type == "skin") {
 | |
|                     local SkinAni;
 | |
|                     if (this[Type] == null) {
 | |
|                         local BufInfo = sq_DeepCopy(ScriptData.GetAni(Src));
 | |
|                         local Ao = {
 | |
|                             ImgVariation = [0, 0],
 | |
|                             ImgFormat = function(ImgPath) {
 | |
|                                 if (ImgVariation[0] > 0) {
 | |
|                                     local Pos = ImgPath.find("%04d");
 | |
|                                     ImgPath = ImgPath.slice(0, Pos) + "%02d%02d" + ImgPath.slice(Pos + 4);
 | |
|                                     return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                                 } else {
 | |
|                                     return format(ImgPath, ImgVariation[1]);
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                         SkinAni = Animation(BufInfo, Ao);
 | |
|                     } else {
 | |
|                         local AvaInfo = AssetManager.GetEquipment(this[Type]);
 | |
|                         local JobInfo = AvaInfo["Ani"]["Ani_" + Info["job"]];
 | |
|                         local BufInfo = sq_DeepCopy(ScriptData.GetAni(Src));
 | |
|                         local Ao = {
 | |
|                             ImgVariation = JobInfo["variation"],
 | |
|                             ImgFormat = function(ImgPath) {
 | |
|                                 return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                             }
 | |
|                         }
 | |
|                         SkinAni = Animation(BufInfo, Ao);
 | |
|                     }
 | |
|                     //如果是皮肤Ani 绑定状态机 确保唯一性
 | |
|                     SkinAni.BindenvStateMachine(StateMachine);
 | |
|                     //将Ani类型设置为皮肤
 | |
|                     SkinAni.Type = "skin";
 | |
|                     //加入组
 | |
|                     AttackAni[_Index].append(SkinAni);
 | |
|                 } else {
 | |
|                     if (this[Type] != null) {
 | |
| 
 | |
|                         local AvaInfo = AssetManager.GetEquipment(this[Type]);
 | |
|                         local JobInfo = AvaInfo["Ani"]["Ani_" + Info["job"]];
 | |
|                         foreach(_index, value in JobInfo["layer_variation"]) {
 | |
|                             local BufInfo = sq_DeepCopy(ScriptData.GetAni(AvaInfo["DirPath"] + value["Path"] + Src.slice(Src.lastfind("/"))));
 | |
|                             local Ao = {
 | |
|                                 ImgVariation = JobInfo["variation"],
 | |
|                                 ImgFormat = function(ImgPath) {
 | |
|                                     return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                                 }
 | |
|                             }
 | |
|                             local AniBuf = Animation(BufInfo, Ao);
 | |
|                             //设置Ani类型
 | |
|                             AniBuf.Type = Type;
 | |
|                             AniBuf.SetZOrder(value["Zorder"]);
 | |
|                             AttackAni[_Index].append(AniBuf);
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //初始化
 | |
|     function Init(SlotType = false) {
 | |
|         //初始化Ani
 | |
|         InitAni(SlotType);
 | |
|         //初始化名字
 | |
|         InitName();
 | |
|     }
 | |
| 
 | |
|     function InitAni(SlotType) {
 | |
|         //读取并设置 等待Ani
 | |
|         ReadAndSetAni("WaitingAni", "waiting motion", SlotType);
 | |
|         //读取并设置 移动Ani
 | |
|         ReadAndSetAni("MoveAni", "move motion", SlotType);
 | |
|         //读取并设置 蹲下Ani
 | |
|         ReadAndSetAni("SitAni", "sit motion", SlotType);
 | |
|         //读取并设置 受伤Ani
 | |
|         ReadAndSetAni("DamageAni1", "damage motion 1", SlotType);
 | |
|         //读取并设置 受伤Ani
 | |
|         ReadAndSetAni("DamageAni2", "damage motion 2", SlotType);
 | |
|         //读取并设置 倒地Ani
 | |
|         ReadAndSetAni("DownAni", "down motion", SlotType);
 | |
|         //读取并设置 被击后退Ani
 | |
|         ReadAndSetAni("OverturnAni", "overturn motion", SlotType);
 | |
|         //读取并设置 跳跃Ani
 | |
|         ReadAndSetAni("JumoAni", "jump motion", SlotType);
 | |
|         //读取并设置 跳跃攻击Ani
 | |
|         ReadAndSetAni("JumpAttackAni", "jumpattack motion", SlotType);
 | |
|         //读取并设置 站立Ani
 | |
|         ReadAndSetAni("RestAni", "rest motion", SlotType);
 | |
|         //读取并设置 引导Ani
 | |
|         ReadAndSetAni("ThrowAni1_1", "throw motion 1-1", SlotType);
 | |
|         ReadAndSetAni("ThrowAni1_2", "throw motion 1-2", SlotType);
 | |
|         ReadAndSetAni("ThrowAni2_1", "throw motion 2-1", SlotType);
 | |
|         ReadAndSetAni("ThrowAni2_2", "throw motion 2-2", SlotType);
 | |
|         ReadAndSetAni("ThrowAni3_1", "throw motion 3-1", SlotType);
 | |
|         ReadAndSetAni("ThrowAni3_2", "throw motion 3-2", SlotType);
 | |
|         ReadAndSetAni("ThrowAni4_1", "throw motion 4-1", SlotType);
 | |
|         ReadAndSetAni("ThrowAni4_2", "throw motion 4-2", SlotType);
 | |
|         //读取并设置 奔跑Ani
 | |
|         ReadAndSetAni("DashAni", "dash motion", SlotType);
 | |
|         //读取并设置 奔跑攻击Ani
 | |
|         ReadAndSetAni("DashAttackAni", "dashattack motion", SlotType);
 | |
|         //读取并设置 拾取Ani
 | |
|         ReadAndSetAni("GetItemAni", "getitem motion", SlotType);
 | |
|         //读取并设置 释放BUFFAni
 | |
|         ReadAndSetAni("BuffAni", "buff motion", SlotType);
 | |
| 
 | |
|         //读取并设置 AttackAni
 | |
|         // ReadAndSetAttackAni();
 | |
|     }
 | |
| 
 | |
|     function InitAuroa() {
 | |
|         //光环
 | |
|         local Info = Parent.aurora;
 | |
|         //如果有光环
 | |
|         if (AuroraAni) {
 | |
|             foreach(Ani in AuroraAni) {
 | |
|                 Removechild(Ani);
 | |
|             }
 | |
|         }
 | |
|         AuroraAni = [];
 | |
| 
 | |
|         foreach(Effect in Info.Aurora_effects) {
 | |
|             local AniBuf = Animation(Effect.path);
 | |
|             AuroraAni.append(AniBuf);
 | |
|             Addchild(AniBuf);
 | |
|             //front
 | |
|             if (Effect.type == 1) {
 | |
|                 AniBuf.SetZOrder(100000);
 | |
|             } else {
 | |
|                 AniBuf.SetZOrder(-100000);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //初始化名字
 | |
|     function InitName() {
 | |
|         //创建名字对象
 | |
|         Name = FontAssetManager.GenerateNormal("", false, {
 | |
|             color = sq_RGBA(209, 185, 148, 255),
 | |
|             alignment = TextAlign.Center
 | |
|         });
 | |
|         Name.SetPosition(ENUM_RINDRO_JOB_TITLE_HEIGHT[Parent.Job]);
 | |
|         Name.SetZOrder(80000);
 | |
|         Addchild(Name);
 | |
|     }
 | |
| 
 | |
|     //设置名字
 | |
|     function SetName(Name) {
 | |
|         this.Name.SetText(Name);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     //设置Ani
 | |
|     function SetAnimation(Ani) {
 | |
|         //因为是Ani组所以要foreach调用
 | |
|         //如果已经有Ani了
 | |
|         if (CurrentAni) {
 | |
|             //动作Ani组
 | |
|             foreach(AniGroup in CurrentAni) {
 | |
|                 //槽类型动画
 | |
|                 foreach(AniObj in AniGroup) {
 | |
|                     Removechild(AniObj);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         if (type(Ani) == "integer") {
 | |
|             //TODO 进阶ANI
 | |
|         } else {
 | |
|             CurrentAni = this[Ani];
 | |
|         }
 | |
|         //重置Ani 并添加子对象
 | |
|         foreach(Key, AniGroup in CurrentAni) {
 | |
|             foreach(AniObj in AniGroup) {
 | |
|                 AniObj.Reset();
 | |
|                 Addchild(AniObj);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |