514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名:Animation_Class.nut
 | |
| 路径:Base/_Tool/Animation_Class.nut
 | |
| 创建日期:2024-10-21	16:57
 | |
| 文件用途:动画类
 | |
| */
 | |
| class Rindro_Animation {
 | |
| 
 | |
|     //Ani是否可用
 | |
|     IsUsability = true;
 | |
| 
 | |
|     //当前帧数
 | |
|     CurrentFrameIndex = 0;
 | |
|     //当前帧时间
 | |
|     CurrentIndexT = 0;
 | |
|     //当前帧
 | |
|     CurrentFrame = null;
 | |
| 
 | |
|     //Ani的标签
 | |
|     AnimationFlag = null;
 | |
|     //图片对象数组
 | |
|     PngList = null;
 | |
|     //帧对象数组
 | |
|     FrameList = null;
 | |
| 
 | |
|     //附加选项
 | |
|     AdditionalOptions = null;
 | |
| 
 | |
|     //角度
 | |
|     Angle = 0;
 | |
| 
 | |
| 
 | |
|     constructor(Data, ...) {
 | |
|         PngList = [];
 | |
|         FrameList = [];
 | |
| 
 | |
|         //附加选项
 | |
|         if (vargc > 0) AdditionalOptions = vargv[0];
 | |
| 
 | |
|         //初始化数据
 | |
|         InitData(Data);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     function InitData(Data) {
 | |
|         local Buf;
 | |
| 
 | |
|         if (type(Data) == "table") {
 | |
|             Buf = Data;
 | |
|         }
 | |
|         //从PVF数据加载
 | |
|         else if (type(Data) == "string") {
 | |
|             local ReadObject = R_Utils.GetScriptFileReader(Data);
 | |
|             if (ReadObject) {
 | |
|                 Buf = Rindro_Script.ReadAnimation(ReadObject);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (Buf) {
 | |
|             AnimationFlag = Buf.Flag;
 | |
|             FrameList = Buf.Frame;
 | |
|             foreach(FrameObj in FrameList) {
 | |
|                 //如果有附加处理 格式化
 | |
|                 if (AdditionalOptions && AdditionalOptions.rawin("ImgFormat")) FrameObj.Img_Path = AdditionalOptions["ImgFormat"](FrameObj.Img_Path);
 | |
|                 local Png = Rindro_Image.Load(FrameObj.Img_Path);
 | |
|                 // Png.Draw(-500, -500);
 | |
| 
 | |
|                 //如果有附加处理 坐标
 | |
|                 if (AdditionalOptions && AdditionalOptions.rawin("Pos")) {
 | |
|                     FrameObj.Pos.x += AdditionalOptions["Pos"].x;
 | |
|                     FrameObj.Pos.y += AdditionalOptions["Pos"].y;
 | |
|                 }
 | |
|                 // Spritebuf.SetPosition(FrameObj.Pos);
 | |
| 
 | |
|                 PngList.append(Png);
 | |
|             }
 | |
|         } else {
 | |
|             AnimationFlag = {};
 | |
|             FrameList.append({
 | |
|                 AttackBox = [],
 | |
|                 DamageBox = [],
 | |
|                 Delay = 800,
 | |
|                 Flag = {},
 | |
|                 Img_Index = 0,
 | |
|                 Img_Path = "",
 | |
|                 Pos = {
 | |
|                     x = -248,
 | |
|                     y = -331
 | |
|                 }
 | |
|             })
 | |
| 
 | |
|             // print(Data);
 | |
|             // print("创建Ani失败,找不到Ani数据");
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     //重置Ani
 | |
|     function Reset() {
 | |
|         IsUsability = true;
 | |
|         FlushFrame(0);
 | |
|     }
 | |
| 
 | |
|     //获取当前帧信息
 | |
|     function GetCurrentFrameInfo() {
 | |
|         return FrameList[CurrentFrameIndex];
 | |
|     }
 | |
| 
 | |
|     function FlushFrame(Index) {
 | |
|         if (PngList.len() <= 0) return;
 | |
|         //同步当前帧
 | |
|         CurrentFrameIndex = Index;
 | |
|         //当前帧更换为本帧
 | |
|         CurrentFrame = PngList[CurrentFrameIndex];
 | |
| 
 | |
|         local FlagBuf = FrameList[CurrentFrameIndex].Flag;
 | |
|         //关键帧
 | |
|         if ("SET_FLAG" in FlagBuf) {
 | |
|             // if (StateMachine && StateMachine.State != -1) StateMachine.ChangeAniKeyFlag(FlagBuf.SET_FLAG);
 | |
|         }
 | |
|         //播放音效
 | |
|         if ("PLAY_SOUND" in FlagBuf) {
 | |
|             R_Utils.PlaySound(FlagBuf.PLAY_SOUND);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //绘制
 | |
|     function DrawFrame(X, Y) {
 | |
| 
 | |
|         // local NowDrawPng = CurrentFrame;
 | |
|         if (FrameList.len() <= 0) return;
 | |
|         local FrameObj = FrameList[CurrentFrameIndex];
 | |
|         // printT(FrameObj);
 | |
| 
 | |
| 
 | |
|         //坐标偏移
 | |
|         local XOffset = FrameObj.Pos.x;
 | |
|         local YOffset = FrameObj.Pos.y;
 | |
| 
 | |
|         //染色
 | |
|         local RGBA = sq_RGBA(255, 255, 255, 255);
 | |
|         if ("RGBA" in FrameObj.Flag) {
 | |
|             local Fbuf = FrameObj.Flag.RGBA;
 | |
|             RGBA = sq_RGBA(Fbuf[0].tointeger(), Fbuf[1].tointeger(), Fbuf[2].tointeger(), Fbuf[3].tointeger());
 | |
|         }
 | |
| 
 | |
|         //缩放
 | |
|         local XRate = 1.0;
 | |
|         local YRate = 1.0;
 | |
|         if ("IMAGE_RATE" in FrameObj.Flag) {
 | |
|             local Fbuf = FrameObj.Flag.IMAGE_RATE;
 | |
|             XRate = Fbuf.x;
 | |
|             YRate = Fbuf.y;
 | |
|         }
 | |
| 
 | |
|         //线性减淡
 | |
|         if ("GRAPHIC_EFFECT_LINEARDODGE" in FrameObj.Flag) {
 | |
|             L_sq_SetDrawImgModel(2, 0);
 | |
|         }
 | |
| 
 | |
|         if (CurrentFrame) CurrentFrame.DrawExPng(FrameObj.Img_Index, X + XOffset, Y + YOffset, Angle, RGBA, XRate, YRate);
 | |
| 
 | |
|         //线性减淡
 | |
|         if ("GRAPHIC_EFFECT_LINEARDODGE" in FrameObj.Flag) {
 | |
|             L_sq_ReleaseDrawImgModel();
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     function Draw(X, Y) {
 | |
|         //可用性检查
 | |
|         if (IsUsability) {
 | |
|             DrawFrame(X, Y);
 | |
|             //累加当前帧时间
 | |
|             CurrentIndexT += Rindro_Duration;
 | |
| 
 | |
|             //当前帧时间 超过 当前帧延迟就需要切换帧了
 | |
|             if ("Delay" in FrameList[CurrentFrameIndex] && CurrentIndexT >= FrameList[CurrentFrameIndex].Delay) {
 | |
|                 CurrentIndexT = 0;
 | |
|                 //如果当前帧小于总帧数就切换
 | |
|                 if (CurrentFrameIndex<(FrameList.len() - 1)) {
 | |
|                     FlushFrame(CurrentFrameIndex + 1);
 | |
|                 }
 | |
|                 //说明播放完毕了
 | |
|                 else {
 | |
|                     //如果有循环
 | |
|                     if ("LOOP" in AnimationFlag) {
 | |
|                         FlushFrame(0);
 | |
|                     }
 | |
|                     //没有循环触发状态机回调
 | |
|                     else {
 | |
|                         //将不再可用
 | |
|                         IsUsability = false;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function DrawIndex(X, Y, Index) {
 | |
|         // return;
 | |
|         if (IsUsability) {
 | |
|             FlushFrame(Index);
 | |
|             DrawFrame(X, Y);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| //绘制角色类
 | |
| class Rindro_Draw_Character {
 | |
| 
 | |
|     //名字
 | |
|     Name = null;
 | |
|     //职业
 | |
|     Job = null;
 | |
| 
 | |
|     //绘制体信息
 | |
|     DrawInfo = null;
 | |
| 
 | |
| 
 | |
|     ENUM_RINDRO_JOB_NAME = ["swordman", "fighter", "gunner", "mage", "priest", "atgunner", "thief", "atfighter", "atmage", "demonicswordman", "creatormage"];
 | |
|     ENUM_RINDRO_JOB_TITLE_HEIGHT = [
 | |
|         //男鬼剑士
 | |
|         {
 | |
|             x = -42,
 | |
|             y = -154
 | |
|         },
 | |
|         //女格斗
 | |
|         {
 | |
|             x = -42,
 | |
|             y = -140
 | |
|         },
 | |
|         //男神枪手
 | |
|         {
 | |
|             x = -44,
 | |
|             y = -168
 | |
|         },
 | |
|         //女魔法师
 | |
|         {
 | |
|             x = -46,
 | |
|             y = -126
 | |
|         },
 | |
|         //男圣职者
 | |
|         {
 | |
|             x = -46,
 | |
|             y = -166
 | |
|         },
 | |
|         //女神枪手
 | |
|         {
 | |
|             x = -42,
 | |
|             y = -156
 | |
|         },
 | |
|         //女暗夜使者
 | |
|         {
 | |
|             x = -44,
 | |
|             y = -154
 | |
|         },
 | |
|         //男格斗家
 | |
|         {
 | |
|             x = -45,
 | |
|             y = -160
 | |
|         },
 | |
|         //男魔法师
 | |
|         {
 | |
|             x = -45,
 | |
|             y = -140
 | |
|         },
 | |
|         //黑暗武士
 | |
|         {
 | |
|             x = -42,
 | |
|             y = -154
 | |
|         },
 | |
|         //缔造者
 | |
|         {
 | |
|             x = -46,
 | |
|             y = -126
 | |
|         },
 | |
|     ];
 | |
| 
 | |
|     ENUM_RINDRO_JOB_FACE_HEIGHT = [
 | |
|         //男鬼剑士
 | |
|         {
 | |
|             x = 11,
 | |
|             y = 111
 | |
|         },
 | |
|         //女格斗
 | |
|         {
 | |
|             x = 9,
 | |
|             y = 103
 | |
|         },
 | |
|         //男神枪手
 | |
|         {
 | |
|             x = 13,
 | |
|             y = 131
 | |
|         },
 | |
|         //女魔法师
 | |
|         {
 | |
|             x = 14,
 | |
|             y = 87
 | |
|         },
 | |
|         //男圣职者
 | |
|         {
 | |
|             x = 16,
 | |
|             y = 126
 | |
|         },
 | |
|         //女神枪手
 | |
|         {
 | |
|             x = 11,
 | |
|             y = 119
 | |
|         },
 | |
| 
 | |
|         //女暗夜使者
 | |
|         {
 | |
|             x = 12,
 | |
|             y = 115
 | |
|         },
 | |
|         //男格斗家
 | |
|         {
 | |
|             x = 13,
 | |
|             y = 119
 | |
|         },
 | |
|         //男魔法师
 | |
|         {
 | |
|             x = 13,
 | |
|             y = 101
 | |
|         },
 | |
|         //黑暗武士
 | |
|         {
 | |
|             x = -42,
 | |
|             y = -154
 | |
|         },
 | |
|         //缔造者
 | |
|         {
 | |
|             x = -46,
 | |
|             y = -126
 | |
|         },
 | |
|     ];
 | |
| 
 | |
| 
 | |
|     //获取角色AniBy装备
 | |
|     function GetCharacAniByEqu(Job, Equ, AniName) {
 | |
|         local AniList = [];
 | |
|         foreach(value in Equ) {
 | |
|             if (value > 0) {
 | |
|                 local ListBuf = CreateEquipmentAni(value, Job, AniName);
 | |
|                 AniList.extend(ListBuf);
 | |
|             }
 | |
|         }
 | |
|         local n = AniList.len();
 | |
|         for (local i = 0; i< n - 1; i++) {
 | |
|             for (local j = i + 1; j< n; j++) {
 | |
|                 if (AniList[i].Layer > AniList[j].Layer) {
 | |
|                     // 交换两个元素
 | |
|                     local temp = AniList[i];
 | |
|                     AniList[i] = AniList[j];
 | |
|                     AniList[j] = temp;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return AniList;
 | |
|     }
 | |
| 
 | |
|     function CreateEquipmentAni(Index, Job, AniName) {
 | |
|         local AniList = [];
 | |
|         //获取装备或时装的文件路径
 | |
|         local FilePath = R_Utils.GetEquPath(Index);
 | |
|         if (FilePath) {
 | |
|             local ReadObject = R_Utils.GetScriptFileReader("equipment/" + FilePath);
 | |
|             if (ReadObject) {
 | |
|                 local Equ = Rindro_Script.ReadEquipment(ReadObject);
 | |
|                 //职业名字
 | |
|                 local JobName = ENUM_RINDRO_JOB_NAME[Job];
 | |
|                 //没有装备类型
 | |
|                 if (!(Equ.rawin("equipment_type"))) Equ.equipment_type <- "normal";
 | |
|                 //光环单独处理 其他的在下面处理
 | |
|                 if (Equ.equipment_type == "aurora avatar") {
 | |
|                     foreach(Path in Equ.Aurora.Back) {
 | |
|                         local AniBuf = Rindro_Animation(Path);
 | |
|                         AniList.append({
 | |
|                             Ani = AniBuf,
 | |
|                             Layer = -10000,
 | |
|                         });
 | |
|                     }
 | |
|                     foreach(Path in Equ.Aurora.Front) {
 | |
|                         local AniBuf = Rindro_Animation(Path);
 | |
|                         AniList.append({
 | |
|                             Ani = AniBuf,
 | |
|                             Layer = 10000,
 | |
|                         });
 | |
|                     }
 | |
|                 }
 | |
|                 //称号
 | |
|                 else if (Equ.equipment_type == "title name") {
 | |
|                     local PathBuf = "equipment/" + FilePath;
 | |
|                     PathBuf = PathBuf.slice(0, R_Utils.String.FindLastSubstring(PathBuf, "/"));
 | |
|                     local Path = PathBuf + "/" + Equ.custom_animation;
 | |
|                     local Ao = {
 | |
|                         Pos = ENUM_RINDRO_JOB_TITLE_HEIGHT[Job]
 | |
|                     }
 | |
|                     local AniBuf = Rindro_Animation(Path, Ao);
 | |
|                     AniList.append({
 | |
|                         Ani = AniBuf,
 | |
|                         Layer = 10001,
 | |
|                     });
 | |
|                 }
 | |
| 
 | |
|                 //没有Ani  就那种透明时装
 | |
|                 if (!(Equ.rawin("Ani_" + JobName))) return AniList;
 | |
| 
 | |
|                 //读取Ani配置
 | |
|                 local AniScript = Equ["Ani_" + JobName];
 | |
|                 if (Equ.equipment_type == "skin avatar") {
 | |
|                     local Path;
 | |
|                     if (JobName.find("at") >= 0) {
 | |
|                         Path = format("character/%s/atanimation/%s", JobName.slice(2), AniName);
 | |
|                     } else Path = format("character/%s/animation/%s", JobName, AniName);
 | |
|                     local Ao = {
 | |
|                         ImgVariation = AniScript.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 AniBuf = Rindro_Animation(Path, Ao);
 | |
|                     AniList.append({
 | |
|                         Ani = AniBuf,
 | |
|                         Layer = 0,
 | |
|                     });
 | |
|                 } else {
 | |
|                     foreach(Info in AniScript.layer_variation) {
 | |
|                         local PathBuf = "equipment/" + FilePath;
 | |
|                         PathBuf = PathBuf.slice(0, R_Utils.String.FindLastSubstring(PathBuf, "/"));
 | |
|                         local Path = PathBuf + "/" + Info.Path + "/" + AniName;
 | |
|                         local Ao = {
 | |
|                             ImgVariation = AniScript.variation,
 | |
|                             ImgFormat = function(ImgPath) {
 | |
|                                 return format(ImgPath, ImgVariation[0], ImgVariation[1]);
 | |
|                             }
 | |
|                         }
 | |
|                         local AniBuf = Rindro_Animation(Path, Ao);
 | |
|                         AniList.append({
 | |
|                             Ani = AniBuf,
 | |
|                             Layer = Info.Zorder,
 | |
|                         });
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return AniList;
 | |
|     }
 | |
| 
 | |
|     constructor(Job, EquipmentArr, Action, Name) {
 | |
|         DrawInfo = GetCharacAniByEqu(Job, EquipmentArr, Action);
 | |
|         this.Job = Job;
 | |
|         this.Name = Name;
 | |
|     }
 | |
| 
 | |
|     function Draw(X, Y) {
 | |
|         foreach(AniInfo in DrawInfo) {
 | |
|             AniInfo.Ani.Draw(X, Y);
 | |
|         }
 | |
| 
 | |
|         if (Name) {
 | |
|             L_sq_DrawCode(Name, 44 + X + ENUM_RINDRO_JOB_TITLE_HEIGHT[Job].x - (LenheartTextClass.GetStringLength(Name) / 2), Y + ENUM_RINDRO_JOB_TITLE_HEIGHT[Job].y + 24, sq_RGBA(255, 255, 255, 250), 1, 1);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function DrawFace(X, Y) {
 | |
|         setClip(X, Y, X + 22, Y + 18); //开始裁切
 | |
|         foreach(AniInfo in DrawInfo) {
 | |
|             AniInfo.Ani.DrawIndex(X + ENUM_RINDRO_JOB_FACE_HEIGHT[Job].x, Y + ENUM_RINDRO_JOB_FACE_HEIGHT[Job].y, 0);
 | |
|         }
 | |
|         releaseClip(); //裁切结束
 | |
|     }
 | |
| }
 | |
| //鬼剑士
 | |
| //601580026 101550559
 | |
| // Sassq <- {};
 | |
| // Sassq[0] <- Rindro_Draw_Character(0, [
 | |
| //     601550071,
 | |
| //     601560067,
 | |
| //     601570062,
 | |
| //     601500069,
 | |
| //     601510068,
 | |
| //     601540069,
 | |
| //     601520061,
 | |
| //     601530060,
 | |
| //     601580026,
 | |
| //     0,
 | |
| //     27610,
 | |
| //     26058
 | |
| // ], "rest.ani", "鬼剑士-Kina")
 | |
| // //格斗家
 | |
| // Sassq[1] <- Rindro_Draw_Character(1, [26373, 102550540, 102560700, 102570504, 102520514, 102500742, 102510739, 102540664, 102580139, 102530474], "rest.ani", "Kina")
 | |
| // //神枪手
 | |
| // Sassq[2] <- Rindro_Draw_Character(2, [26373, 104550553, 104560725, 104570492, 104520541, 104500750, 104510913, 104540671, 104580148, 104530494], "rest.ani", "Kina")
 | |
| // //魔法师
 | |
| // Sassq[3] <- Rindro_Draw_Character(3, [26373, 106550521, 106560580, 106570446, 106520529, 106500603, 106510607, 106540583, 106580143, 106530461], "rest.ani", "Kina")
 | |
| // //圣职者
 | |
| // Sassq[4] <- Rindro_Draw_Character(4, [26373, 108550600, 108560591, 108570687, 108520580, 108500587, 108510590, 108540562, 108580138, 108530560], "rest.ani", "Kina")
 | |
| // //女枪
 | |
| // Sassq[5] <- Rindro_Draw_Character(5, [26373, 105550431, 105560424, 105570386, 105520415, 105500424, 105510429, 105540408, 105580144, 105530361], "rest.ani", "Kina")
 | |
| // //暗夜
 | |
| // Sassq[6] <- Rindro_Draw_Character(6, [26373, 109550385, 109560393, 109570369, 109520406, 109500402, 109510414, 109540389, 109580134, 109530355], "rest.ani", "Kina")
 | |
| // //男格斗
 | |
| // Sassq[7] <- Rindro_Draw_Character(7, [26373, 103550302, 103560311, 103570274, 103520297, 103500297, 103510301, 103540284, 103580128, 103530246], "rest.ani", "Kina")
 | |
| // //男法
 | |
| // Sassq[8] <- Rindro_Draw_Character(8, [26373, 107550220, 107560223, 107570188, 107520224, 107500233, 107510231, 107540209, 107580129, 107530192], "rest.ani", "Kina") |