335 lines
12 KiB
Plaintext
335 lines
12 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
|
|
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);
|
|
}
|
|
}
|
|
} |