/* 文件名:Script_Class.nut 路径:Base/_Tool/Script_Class.nut 创建日期:2024-10-21 14:49 文件用途:PVF读取类 */ class BlobEx extends blob { constructor(BaseBlob) { blob.constructor(BaseBlob.len()); writeblob(BaseBlob); } function writeblob(B) { blob.writeblob(B); seek(0); } function GetUShort() { return readn('s'); } function GetShort() { return readn('w'); } function charPtrToInt(arr) { local value = ((arr[0]) << 0) | ((arr[1]) << 8) | ((arr[2]) << 16) | ((arr[3]) << 24); return value; } function GetInt() { local CurTPos = tell(); local Ret = charPtrToInt([this[CurTPos], this[CurTPos + 1], this[CurTPos + 2], this[CurTPos + 3]]); seek(4, 'c'); return Ret; } function Get256() { local Buf = readn('c'); return (256.0 + Buf.tofloat()) % 256.0; } function GetFloat() { return readn('f'); } function GetString(count) { local MBuf = Memory.alloc(count); local BlobBuf = readblob(count); local arr = []; foreach(value in BlobBuf) { arr.append(value); } MBuf.writeByteArray(arr); return MBuf.readUtf8String(count); } } Rindro_Script_Bin_Data <- []; class _PVF_Data_ { //数据 Data = null; //位置 Pos = 0; //最大值 Max = 0; function _typeof() { return "pvf_data"; } constructor(gData) { Data = gData; Max = gData.len(); } function Last() { if (Pos > 0) { Pos--; return Get(); } return null; } function Seek(i) { if (Pos > 0 && Pos<(Max - 1)) { Pos = i; } } function Get() { local Ret = Data[Pos]; if (Pos<(Max - 1)) { Pos++; } return Ret; } function Eof() { if (Pos == Max - 1) return true; } function Next() { if (Pos<(Max - 1)) { Pos++; return Get(); } return null; } } class Rindro_Script { function Get_Ani_Flip_Type(data) { switch (data) { case 1: return "HORIZON"; case 2: return "VERTICAL"; case 3: return "ALL"; default: return ""; } } function Get_Ani_Effect_Type(data) { switch (data) { case 0: return "NONE"; case 1: return "DODGE"; case 2: return "LINEARDODGE"; case 3: return "DARK"; case 4: return "XOR"; case 5: return "MONOCHROME"; case 6: return "SPACEDISTORT"; default: return ""; } } function Get_Ani_Damage_Type(data) { switch (data) { case 0: return "NORMAL"; case 1: return "SUPERARMOR"; case 2: return "UNBREAKABLE"; default: return ""; } } function Get_Ani_Flag(data) { switch (data) { case 0: return "LOOP"; case 1: return "SHADOW"; case 3: return "COORD"; case 7: return "IMAGE_RATE"; case 8: return "IMAGE_ROTATE"; case 9: return "RGBA"; case 10: return "INTERPOLATION"; case 11: return "GRAPHIC_EFFECT"; case 12: return "DELAY"; case 13: return "DAMAGE_TYPE"; case 14: return "DAMAGE_BOX"; case 15: return "ATTACK_BOX"; case 16: return "PLAY_SOUND"; case 17: return "PRELOAD"; case 18: return "SPECTRUM"; case 23: return "SET_FLAG"; case 24: return "FLIP_TYPE"; case 25: return "LOOP_START"; case 26: return "LOOP_END"; case 27: return "CLIP"; case 28: return "OPERATION"; default: return ""; } } function endswith(Str, cmp) { local len = cmp.len(); local EndStr = Str.slice(-len); if (EndStr == cmp) return true; return false; } function InitLoad_String() { if (getroottable().rawin("RindroLoadStringTable")) return; getroottable().RindroLoadStringTable <- {}; local N_String = R_Utils.GetScriptFileReader("n_string.lst"); if (N_String) { local IO = Sq_Point2Blob(L_sq_P2I(N_String.Buffer.C_Object), N_String.Size); local i = 2; while (i< N_String.Size) { if ((N_String.Size - i) >= 10) { IO.seek(i + 6); //内容指示位 local FindKey = IO.readn('i'); local Key = Rindro_Script.GetBinString(FindKey); if (Key) { local StrFilePath = Key.tolower(); local StrFile = R_Utils.GetScriptFileReader(StrFilePath, 10240000); if (StrFile) { local StrBuffer = StrFile.Buffer.readUtf8String(StrFile.Size); local StrArr = split(StrBuffer, "\r\n"); foreach(index, strobj in StrArr) { if (strobj.find(">") != null) { local strobjarr = split(strobj, ">"); if (strobjarr.len() > 1) { getroottable().RindroLoadStringTable.rawset(strobjarr[0], Sq_ConvertWideChar(strobjarr[1], "big5")); } } } } } } else break; i += 10; } } } function GetBin() { local BinFile = R_Utils.GetScriptFileReader("stringtable.bin", 40960000); if (BinFile) { local Ro = Sq_Point2Blob(L_sq_P2I(BinFile.Buffer.C_Object), BinFile.Size); Ro = BlobEx(Ro.readblob(Ro.len())); local Count = Ro.readn('i'); local CurrentIndex = 0; for (local i = 0; i< Count; i++) { Ro.seek(CurrentIndex * 4 + 4); local StartPos = Ro.readn('i'); local EndPos = Ro.readn('i'); local Len = EndPos - StartPos; Ro.seek(StartPos + 4); if (Len > 0) { local Str = Ro.GetString(Len); Rindro_Script_Bin_Data.append(Str); } else { Rindro_Script_Bin_Data.append(""); } CurrentIndex++; } } } function GetBinString(Index) { if (!(getroottable().rawin("ENUM_TW_GROWTYPE_VERS")) || ENUM_TW_GROWTYPE_VERS >= 24112901) //24112901更新了新的读取bin文件的方式 return L_sq_StringBinById(Index); else { if (Index< Rindro_Script_Bin_Data.len()) return Rindro_Script_Bin_Data[Index]; return ""; } } function GetLoadString(Key) { if (getroottable().RindroLoadStringTable.rawin(Key)) return getroottable().RindroLoadStringTable[Key]; else return ""; } function UnpackData(IO, i) { local out = ""; IO.seek(i); //内容指示位 local currentByte = IO.readn('c'); //内容指示位 local after = IO.GetInt(); switch (currentByte) { case 10: { IO.seek(i - 4); local Before = IO.readn('i'); local Buf = Rindro_Script.GetBinString(after); if (!Buf) { Buf = ""; } else { Buf = "<" + Before + "::" + Buf + "`" + Rindro_Script.GetLoadString(Buf) + "`>"; } Buf = Buf + "\r\n"; out += Buf; break; } case 2: { IO.seek(-4, 'c'); local ret = IO.readn('i'); return ret; } case 4: { local Bbuf = blob(4); Bbuf.writen(after, 'i'); Bbuf.seek(0); local Buf = Bbuf.readn('f'); out += after + '\t'; break; } case 6: case 8: case 7: case 5: { local Buf = Rindro_Script.GetBinString(after); if (!Buf) Buf = ""; return Buf; } case 9: { IO.seek(i + 6); local Before = IO.readn('i'); local Buf = Rindro_Script.GetBinString(Before); out += Rindro_Script.GetLoadString(Buf); } default: out += ""; break; } return out; } function ReadEquipment(ReadObject) { local EquipmentAtt = {}; if (ReadObject.Size >= 7) { //创建Blob对象 local IOBUF = Sq_Point2Blob(L_sq_P2I(ReadObject.Buffer.C_Object), ReadObject.Size); local IO = BlobEx(IOBUF.readblob(IOBUF.len())); //以5为单步从第二位开始遍历字节 local i = 2; while (true) { if (i< ReadObject.Size && ReadObject.Size - i >= 5) { local str = Rindro_Script.UnpackData(IO, i); i += 5; //名称 if (str == "[name]") { local RealKey = str.slice(1, str.len() - 1); EquipmentAtt[RealKey] <- Rindro_Script.UnpackData(IO, i); i += 5; } //装备类型 else if (str == "[equipment type]") { local Buf = Rindro_Script.UnpackData(IO, i); EquipmentAtt["equipment_type"] <- Buf.slice(1, -1); i += 5; } //称号动画 else if (str == "[custom animation]") { local Buf = Rindro_Script.UnpackData(IO, i).tolower(); EquipmentAtt["custom_animation"] <- Buf; i += 5; } //光环生成效果 else if (str == "[aurora graphic effects]") { EquipmentAtt["Aurora"] <- {}; EquipmentAtt["Aurora"].Back <- []; EquipmentAtt["Aurora"].Front <- []; local Count = Rindro_Script.UnpackData(IO, i); i += 5; for (local z = 0; z< Count; z++) { local Layer = Rindro_Script.UnpackData(IO, i); i += 5; local Path = Rindro_Script.UnpackData(IO, i).tolower(); i += 5; if (Layer == 0) EquipmentAtt["Aurora"].Back.append(Path); if (Layer == 1) EquipmentAtt["Aurora"].Front.append(Path); } i += 5; } //隐藏图层 else if (str == "[hide layer]") { EquipmentAtt["hidelayer"] <- []; while (true) { local Buffer = Rindro_Script.UnpackData(IO, i); i += 5; if (Buffer == "[/hide layer]") { break; } EquipmentAtt["hidelayer"].append(Buffer); } } //Ani else if (str == "[animation job]") { local Job = Rindro_Script.UnpackData(IO, i).slice(1, -1); local SpacePos = Job.find(" "); if (SpacePos) { Job = Job.slice(0, SpacePos) + Job.slice(SpacePos + 1); } i += 5; EquipmentAtt["Ani_" + Job] <- {}; i += 5; local Index1 = Rindro_Script.UnpackData(IO, i); i += 5; local Index2 = Rindro_Script.UnpackData(IO, i); i += 5; EquipmentAtt["Ani_" + Job].variation <- [Index1, Index2]; EquipmentAtt["Ani_" + Job].layer_variation <- []; while (true) { try { local Ret = Rindro_Script.UnpackData(IO, i); i += 5; if (Ret == "[animation job]" || (Rindro_Script.endswith(Ret, "]") && Ret != "[equipment ani script]" && Ret != "[layer variation]")) { i -= 5; break; } else if (Ret == "[layer variation]") { local InfoBuf = {}; InfoBuf.Zorder <- Rindro_Script.UnpackData(IO, i); i += 5; InfoBuf.Path <- Rindro_Script.UnpackData(IO, i); i += 5; EquipmentAtt["Ani_" + Job].layer_variation.append(InfoBuf); } } catch (exception) { break; } } } } else break; } } return EquipmentAtt; } function ReadAnimation(ReadObject) { local Ro = Sq_Point2Blob(L_sq_P2I(ReadObject.Buffer.C_Object), ReadObject.Size); Ro = BlobEx(Ro.readblob(Ro.len())); local AniObject = { Img_List = [], Frame = [], Flag = {} }; local Frame_Max = Ro.readn('s'); local Img_Count = Ro.readn('s'); //Img的路径读取 存入数组 for (local index = 0; index< Img_Count; index++) { local Buf = Ro.readn('i'); local ImgPath = Ro.GetString(Buf); //有可能Img有空路径 AniObject.Img_List.append(ImgPath); } //Ani头部标签数量 local Ani_H_Item_Count = Ro.readn('s'); //处理标签 for (local index = 0; index< Ani_H_Item_Count; index++) { //标签类型 local Type = Ro.readn('s'); switch (Type) { case 0: case 1: { local Key = Rindro_Script.Get_Ani_Flag(Type); local Value = Ro.readn('c'); AniObject.Flag.rawset(Key, Value); break; } case 3: case 28: { local Key = Rindro_Script.Get_Ani_Flag(Type); local Value = Ro.readn('s'); AniObject.Flag.rawset(Key, Value); break; } case 18: // print("残影解析"); //此处无解析 暂时先保证运行 残影功能暂时用不上 Ro.readn('c'); Ro.readn('i'); Ro.readn('i'); Ro.readn('i'); Ro.Get256(); Ro.Get256(); Ro.Get256(); Ro.Get256(); Ro.readn('s'); break; default: break; } } //读取每一个Img for (local index = 0; index< Frame_Max; index++) { //帧结构体对象 local FrameObject = { AttackBox = [], DamageBox = [], Flag = {}, }; //碰撞框项目数量 local Ani_Box_Item_Count = Ro.readn('s'); for (local _i = 0; _i< Ani_Box_Item_Count; _i++) { local Box_Type = Ro.readn('s'); local D_Box_b = []; for (local _k = 0; _k< 6; _k++) { D_Box_b.append(Ro.readn('i')); } if (Box_Type == 15) { FrameObject.AttackBox.append(D_Box_b); } else { FrameObject.DamageBox.append(D_Box_b); } // //0是攻击框 1是受击框 // FrameObject.Box.rawset(15 - Box_Type, D_Box_b); } //调用的第几个Img local Index_Buf = Ro.GetShort(); //如果等于-1说明是img路径为空 if (Index_Buf != 65535) { FrameObject.Img_Path <- AniObject.Img_List[Index_Buf].tolower(); //Img中的PNG下标 FrameObject.Img_Index <- Ro.readn('s'); } else { FrameObject.Img_Path <- ""; FrameObject.Img_Index <- 0; } //坐标 FrameObject.Pos <- { x = Ro.readn('i'), y = Ro.readn('i'), }; //Img中的项目数量 local Img_Flag_Count = Ro.readn('s'); for (local _o = 0; _o< Img_Flag_Count; _o++) { local Img_Flag_Type = Ro.readn('s'); local Key; local Value; switch (Img_Flag_Type) { case 0: case 1: case 10: Key = Rindro_Script.Get_Ani_Flag(Img_Flag_Type); Value = Ro.readn('c'); FrameObject.Flag.rawset(Key, Value); break; case 3: Key = "COORD"; Value = Ro.readn('s'); FrameObject.Flag.rawset(Key, Value); break; case 17: Key = "PRELOAD"; Value = 1; FrameObject.Flag.rawset(Key, Value); break; case 7: Key = "IMAGE_RATE"; Value = { x = Ro.GetFloat(), y = Ro.GetFloat() }; FrameObject.Flag.rawset(Key, Value); break; case 8: Key = "IMAGE_ROTATE"; Value = Ro.GetFloat(); FrameObject.Flag.rawset(Key, Value); break; case 9: Key = "RGBA"; Value = [ Ro.Get256(), Ro.Get256(), Ro.Get256(), Ro.Get256(), ]; FrameObject.Flag.rawset(Key, Value); break; case 11: local Effect_Type = Ro.readn('s'); Key = "GRAPHIC_EFFECT_" + Rindro_Script.Get_Ani_Effect_Type(Effect_Type); switch (Effect_Type) { case 5: Value = [Ro.Get256(), Ro.Get256(), Ro.Get256()]; break; case 6: Value = [Ro.GetShort(), Ro.GetShort()]; break; } FrameObject.Flag.rawset(Key, Value); break; case 12: Value = Ro.readn('i'); FrameObject.Delay <- Value; break; case 13: Key = "DAMAGE_TYPE"; Value = Rindro_Script.Get_Ani_Damage_Type(Ro.readn('s')); FrameObject.Flag.rawset(Key, Value); break; case 16: local SoundTempSize = Ro.readn('i'); Key = "PLAY_SOUND"; Value = Ro.GetString(SoundTempSize); FrameObject.Flag.rawset(Key, Value); break; case 23: Key = "SET_FLAG"; Value = Ro.readn('i'); FrameObject.Flag.rawset(Key, Value); break; case 24: Key = "FLIP_TYPE"; Value = Rindro_Script.Get_Ani_Flip_Type(Ro.readn('s')); FrameObject.Flag.rawset(Key, Value); break; case 25: Key = "LOOP_START"; FrameObject.Flag.rawset(Key, 1); break; case 26: Key = "LOOP_END"; Value = Ro.readn('i'); FrameObject.Flag.rawset(Key, Value); break; case 27: Key = "CLIP"; Value = [ Ro.GetShort(), Ro.GetShort(), Ro.GetShort(), Ro.GetShort(), ]; FrameObject.Flag.rawset(Key, Value); break; default: break; } } //每一帧都是一个结构体 存入数组中 AniObject.Frame.append(FrameObject); } return AniObject; } //获取文件并处理 function GetFileData(Path, Func) { local N_Buffer = R_Utils.GetScriptFileReader(Path); if (N_Buffer) { local IO = Sq_Point2Blob(L_sq_P2I(N_Buffer.Buffer.C_Object), N_Buffer.Size); IO = BlobEx(IO.readblob(IO.len())); return Rindro_Script.ResolvingData(IO, Func, Path); } else { print(Path + "找不到文件!"); return null; } } function ResolvingData(IO, Func, Path) { local DataTable = {}; DataTable.filepath <- Path; local DataArr = []; local Length = IO.len(); if (Length >= 7) { local i = 2; while (true) { if (i< Length && Length - i >= 5) { local str = Rindro_Script.UnpackData(IO, i); i += 5; DataArr.push(str); } else break; } Func(DataTable, _PVF_Data_(DataArr)); return DataTable; } return null; } } // Rindro_Script.GetBin(); Rindro_Script.InitLoad_String();