/// <summary>Read Effect from string array, as in ini files, /// optionally starting from specified index /// <remarks>Does not check if correct format</remarks></summary> /// <param name="str">Array of strings, one for each line</param> /// <param name="i">Optional, Array index to start reading from /// by default is zero</param> public int ReadFromArray(String[] str, int i = 0) { // Check here if there are comments PARSE_COMMENTS_STATE commentsState = PARSE_COMMENTS_STATE.NotCommentLine; while (i < str.Length && (commentsState = IniCommon.ParseLineComments(str[i], commentsState)) >= 0) { // Store comments if (!String.IsNullOrEmpty(Comments)) Comments += "\r\n" + str[i]; else Comments = str[i]; i++; } // Read AniTitle and Amount AniTitle = str[i].Substring(1, str[0].Length - 2); i++; Amount = UInt16.Parse(str[i].Split('=')[1]); i++; if (Amount > 0x0FFF) throw new ArgumentOutOfRangeException("Amount", "cannot fit in a signed short, while should be 16 or lower"); // Check if remaining lines are enough for the amount of parts if (str.Length - i < Amount * 4 + 7) throw new ArgumentOutOfRangeException("str", "there are too few lines to read Effect, expected at least " + (4 * Amount + 7).ToString() + ", while remaining " + (str.Length - i).ToString()); Part = new List<EffectPart>(Amount); // Read every Part for (int j = 0; j < Amount; j++) { EffectPart ep = new EffectPart(); i += ep.ReadFromArray(str, i); Part.Add(ep); } // Read the rest of data Delay = UInt32.Parse(str[i].Substring(1, str[0].Length - 2)); i++; LoopTime = UInt32.Parse(str[i].Substring(1, str[0].Length - 2)); i++; FrameInterval = UInt32.Parse(str[i].Substring(1, str[0].Length - 2)); i++; LoopInterval = UInt32.Parse(str[i].Substring(1, str[0].Length - 2)); i++; OffsetX = float.Parse(str[i].Substring(1, str[0].Length - 2)); i++; OffsetY = float.Parse(str[i].Substring(1, str[0].Length - 2)); i++; OffsetZ = float.Parse(str[i].Substring(1, str[0].Length - 2)); i++; if (i < str.Length && str[i].StartsWith("Billboard")) { Billboard = (Byte.Parse(str[i].Split('=')[1]) != 0); i++; } if (i < str.Length && str[i].StartsWith("ColorEnable")) { ColorEnable = (COLOR_ENABLE)Byte.Parse(str[i].Split('=')[1]); i++; } if (i < str.Length && str[i].StartsWith("Lev")) { Level = Byte.Parse(str[i].Split('=')[1]); i++; } if (i < str.Length && !String.IsNullOrWhiteSpace(str[i]) && str[i].Contains("=")) { Unknown = Byte.Parse(str[i].Split('=')[1]); i++; } return i; }
/// <summary>New Effect from provided fields, all fields /// but Comments is optional</summary> /// <param name="AT">Effect animation title, in 3DEffect.ini</param> /// <param name="Am">Amount of frames</param> /// <param name="P">List of Effect Parts (frames)</param> /// <param name="D">Delay after animation, in milliseconds</param> /// <param name="LT">How much to repeat the loop, 99999999 means forever</param> /// <param name="FI">Frame duration in milliseconds</param> /// <param name="LI">Time between loops in milliseconds</param> /// <param name="X">X Axis coord</param> /// <param name="Y">Y Axis coord</param> /// <param name="Z">Z Axis coord</param> /// <param name="B">Billboard type</param> /// <param name="CE">Show colors or just light /// <see cref="COLOR_ENABLE"/></param> /// <param name="L">Priority Level</param> /// <param name="U">"Unknown" property</param> /// <param name="C">Optional, Comments as in ini file</param> // New instance from provided fields public Effect(String AT, UInt16 Am, List<EffectPart> P, UInt32 D, UInt32 LT, UInt32 FI, UInt32 LI, float X, float Y, float Z, Boolean B, COLOR_ENABLE CE, Byte L, Byte U, String C = null) { AniTitle = AT; Amount = Am; Part = P; Delay = D; LoopTime = LT; FrameInterval = FI; LoopInterval = LI; OffsetX = X; OffsetY = Y; OffsetZ = Z; Billboard = B; ColorEnable = CE; Level = L; Unknown = U; Comments = C; }
/// <summary>New instance from byte array, as in dbc Effe binary file /// </summary> /// <param name="b">Data read from binary dbc file</param> public Effect(Byte[] b) { if (b.Length < 34) // Bytes 32 and 33 contains the amount { new Effect(); } else { Amount = BitConverter.ToUInt16(b, 32); Part = new List<EffectPart>(Amount); if (b.Length < 66 + 16 * Amount) { new Effect(); } else { // Check AniTitle length int c = 0; while (b[c] != 0 & c < 32) c++; // Read AniTitle AniTitle = Common.enc.GetString(b, 0, c); // Read all fixed lenght fields Delay = BitConverter.ToUInt32(b, 34); LoopTime = BitConverter.ToUInt32(b, 38); FrameInterval = BitConverter.ToUInt32(b, 42); LoopInterval = BitConverter.ToUInt32(b, 46); OffsetX = BitConverter.ToSingle(b, 50); OffsetY = BitConverter.ToSingle(b, 54); OffsetZ = BitConverter.ToSingle(b, 58); Billboard = (b[62] != 0); ColorEnable = (COLOR_ENABLE)b[63]; Level = b[64]; Unknown = b[65]; Byte[] be = new Byte[16]; for (int i = 0; i < Amount; i++) { Buffer.BlockCopy(b, 66 + i * 16, be, 0, 16); EffectPart e = new EffectPart(be); Part.Add(e); } } } }
/// <summary>Default Constructor: New Effect empty instance /// <remarks>Does not handle the file, just the data</remarks></summary> public Effect() { AniTitle = ""; Amount = 0; Part = new List<EffectPart>(Amount); Delay = 0; LoopTime = 1; FrameInterval = 33; LoopInterval = 0; OffsetX = 0; OffsetY = 0; OffsetZ = 0; Billboard = false; ColorEnable = COLOR_ENABLE._SHOWWAY_NORMAL; Level = 1; Unknown = 0; }