/* 文件名: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 JumpAni = 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; SMap = { WaitingAni = "waiting motion", MoveAni = "move motion", SitAni = "sit motion", DamageAni1 = "damage motion 1", DamageAni2 = "damage motion 2", DownAni = "down motion", OverturnAni = "overturn motion", JumpAni = "jump motion", JumpAttackAni = "jumpattack motion", RestAni = "rest motion", ThrowAni1_1 = "throw motion 1-1", ThrowAni1_2 = "throw motion 1-2", ThrowAni2_1 = "throw motion 2-1", ThrowAni2_2 = "throw motion 2-2", ThrowAni3_1 = "throw motion 3-1", ThrowAni3_2 = "throw motion 3-2", ThrowAni4_1 = "throw motion 4-1", ThrowAni4_2 = "throw motion 4-2", DashAni = "dash motion", DashAttackAni = "dashattack motion", GetItemAni = "getitem motion", BuffAni = "buff motion", } //默认的Ani Default_Avatar = null; //隐藏图层 HideLayer = null; //使用武器装扮 UseWeaponAvatar = false; constructor() { base.constructor(); } //根据Ani路径和格式化数组来创建Ani ImgVariation Ani对应的格式化的数组 | Src Ani路径 function CreateAni(ImgVariation, Src) { //拷贝Ani的信息 local AniInfo = sq_DeepCopy(ScriptData.GetAni(Src)); //构造Ani的处理函数 local Ao = { //传递Img的格式化方法 ImgFormat = function(ImgPath) { //如果是皮肤这里会是"%04d" 这里要格式化成"%02d%02d" if (ImgPath.find("%04d")) { local Pos = ImgPath.find("%04d"); ImgPath = ImgPath.slice(0, Pos) + "%02d%02d" + ImgPath.slice(Pos + 4); } //替换掉Img的索引编号 return format(ImgPath, ImgVariation[0], ImgVariation[1]); } } //构造Ani local Ani = Animation(AniInfo, Ao); return Ani; } //同步单部位动画 Type 时装的类型名字 "hair" | Src Ani的路径 function SyncAnimationBySlot(Type, Src) { //单部位的动画组 local AniList = []; //如果有时装就初始化Ani //除了皮肤 在没有的情况下初始化0 if (Type == "skin_avatar") { 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 SkinAni = CreateAni(variation, Src); //如果是皮肤Ani 绑定状态机 确保唯一性 SkinAni.BindenvStateMachine(Parent.StateMachine); //将Ani类型设置为皮肤 SkinAni.Type = "skin"; //加入组 AniList.append(SkinAni); } else { //先判断 时装类型 角色有没有穿戴这个类型的时装 if (Parent[Type] != null) { //获取对应装备或时装的信息 local AvaInfo = Parent[Type]; if (AvaInfo) { //获取对应职业对应的格式化信息 local JobInfo = AvaInfo["Animation_Job"]["Ani_" + Parent.Info["job"]]; local variation = JobInfo["variation"]; //非皮肤的时装 会有多个层 foreach(_index, value in JobInfo["layer_variation"]) { local RealAniPath; //如果有指定Ani Path 就使用指定的Ani Path if (AvaInfo["ExpandPath"]) RealAniPath = AvaInfo["ExpandPath"] + value["Path"] + Src.slice(Src.lastfind("/")); //否则 拼接真实的Ani路径 else RealAniPath = AvaInfo["DirPath"] + value["Path"] + Src.slice(Src.lastfind("/")); local AniBuf = CreateAni(variation, RealAniPath); //设置Ani类型 AniBuf.Type = Type; //设置Ani的ZOrder AniBuf.SetZOrder(value["Zorder"]); //加入组 AniList.append(AniBuf); } } } } return AniList; } //根据动画组名称构造AniMap AniObj 角色类的动画组名称 Src Ani代表的标签 “sit motion” SlotType 装备类型 function StructureAniMap(Src) { //初始化所有时装部位 local AniObjectMap = {}; foreach(Type, NString in getconsttable().AvatarType) { local AniList = SyncAnimationBySlot(Type, Src); AniObjectMap[Type] <- AniList; } return AniObjectMap; } //切换装备的刷新Ani function RefreshAni(AniObj, Src, SlotType) { //记录当前皮肤Ani的时间 确保唯一性 local AniTime = 0; if (this.CurrentAni) AniTime = this.CurrentAni["skin_avatar"][0].CurrentIndexT; //记录当前皮肤Ani的帧 确保唯一性 local AniFrameIndex = 0; if (this.CurrentAni) AniFrameIndex = this.CurrentAni["skin_avatar"][0].CurrentFrameIndex; //如果当前播放Ani是 构造的Ani 则移除 并清空 if (this.CurrentAni == this[AniObj]) { foreach(AniBuf in this.CurrentAni[SlotType]) { AniBuf.RemoveSelf(); } } local AniList = SyncAnimationBySlot(SlotType, Src); this[AniObj][SlotType] <- AniList; //如果当前播放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 Init(SlotType = false) { //遍历所有Ani类型并构造 foreach(ChrAniObj, InfoSrc in SMap) { //从父对象 角色对象取得Info 判断其中有没有这个Ani标签 如果有 取得路径 if (Parent.Info.rawin(InfoSrc)) InfoSrc = Parent.Info[InfoSrc]; else continue; if (!SlotType) { this[ChrAniObj] = StructureAniMap(InfoSrc); } else { RefreshAni(ChrAniObj, InfoSrc, SlotType); } } //将默认时装类型存储起来 因为脱下时装的时候要恢复默认时装的设定 if (!Default_Avatar) { Default_Avatar = {}; foreach(EquiId in Parent.Info.default_avatar) { local EquBuffer = GameItem.Equipment(EquiId); Default_Avatar[EquBuffer.SlotType] <- EquBuffer; } } } //构造临时Ani function CreateTempAni(AniName) { local InfoSrc = SMap[AniName]; //从父对象 角色对象取得Info 判断其中有没有这个Ani标签 如果有 取得路径 if (Parent.Info.rawin(InfoSrc)) InfoSrc = Parent.Info[InfoSrc]; else return; local Ani = Actor(); foreach(Key, AniGroup in StructureAniMap(InfoSrc)) { //如果是皮肤Ani 则设置Ani的大小 if (Key == "skin_avatar") Ani.SetSize(AniGroup[0].GetSize()); //如果使用了武器装扮 不加入武器的Ani if (Key == "weapon" && UseWeaponAvatar) continue; foreach(AniObj in AniGroup) { //如果AniObj的ZOrder在隐藏图层中 则隐藏 if (HideLayer.rawin(AniObj.GetZOrder())) { } else { Ani.Addchild(AniObj); } } } return Ani; } //处理隐藏图层 function HandlingHideLayers() { //遍历全部时装计算隐藏图层 HideLayer = {}; UseWeaponAvatar = false; foreach(Type, NString in getconsttable().AvatarType) { local Equip = Parent[Type]; if (Equip) { //如果装备有隐藏图层 则加入隐藏图层 if (Equip.HideLayer) { foreach(layer in Equip.HideLayer) { HideLayer[layer] <- true; } } //如果有佩戴武器装扮 if (Type == "weapon_avatar") { UseWeaponAvatar = true; } } } //遍历全部Ani foreach(ChrAniObj, InfoSrc in SMap) { //取得Ani组 if (this[ChrAniObj]) { foreach(Key, AniGroup in this[ChrAniObj]) { //如果使用了武器装扮 则隐藏武器Ani if (Key == "weapon" && UseWeaponAvatar) { foreach(AniObj in AniGroup) { AniObj.SetVisible(false); } } else { //遍历Ani组 foreach(AniObj in AniGroup) { //如果AniObj的ZOrder在隐藏图层中 则隐藏 if (HideLayer.rawin(AniObj.GetZOrder())) { AniObj.SetVisible(false); } else { AniObj.SetVisible(true); } } } } } } } //设置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); } } } //设置方向 function SetDirection(D) { if (D == DIRECTION.RIGHT) { SetScale(fabs(GetScale().x), GetScale().y); } else if (D == DIRECTION.LEFT) { SetScale(-fabs(GetScale().x), GetScale().y); } } }