/// <summary> /// Write the animations into the VD file /// </summary> /// <param name="writer">binary writer attached to the file</param> private void WriteVDAnimations(BinaryWriter writer, List <int> toExport = null) { // initialize the animations array UOAnimation[] acts; // do we have the list of animations to export? if (toExport != null) { // get the amount of animations we need m_VDLength = toExport.Count; // initialize the array length acts = new UOAnimation[m_VDLength]; // copy the animations for (int i = 0; i < m_VDLength; i++) { // copy the animation only if we have the index (otherwise it will remain null) if (toExport[i] != -1) { acts[i] = Actions[toExport[i]]; } } } else // create a CC compatible list of actions of this mobile { acts = ConvertToCCAnimationsList(); } // current position inside the file long headerPos = writer.BaseStream.Position; // calculate the first animation position long animPos = writer.BaseStream.Position + (12 * m_VDLength * 5); // scan the animations count for (int i = 0; i < m_VDLength; i++) { // get the animation UOAnimation anim = acts[i]; // does the animation for this action exist? if (anim == null) { // make sure we're pointed to the headers position writer.BaseStream.Seek(headerPos, SeekOrigin.Begin); // we need to write 5 empty frameset to skip 1 full animation for (int direction = 0; direction < 5; direction++) { // store an empty start position writer.Write((int)-1); // store an empty size writer.Write((int)-1); // store the useless extra flag writer.Write((int)0); } // update the current position headerPos = writer.BaseStream.Position; } else // animation exist { // each animation in a VD file is a single direction, so we need to create 5 separate animations to make a complete set. for (int direction = 0; direction < 5; direction++) { // store the VD data for the current animation direction anim.ExportAnimationToVD(writer, direction, ref headerPos, ref animPos); // allow the form to update before we move to the next Application.DoEvents(); } // dispose of the frame images anim.DisposeFrames(); } // allow the form to update before we move to the next Application.DoEvents(); } }
/// <summary> /// Convert the EC animations list to a CC compatible one so it can be exported to a VD file /// </summary> /// <returns>CC compatible animations list</returns> private UOAnimation[] ConvertToCCAnimationsList() { // is the animation length unassigned? if (m_VDLength == 0) { // count the actions available int actionsCount = Actions.Where(c => c != null).ToArray().Count(); // more than 22 is people/equipment for sure if (actionsCount > 22) { m_VDLength = 35; } // less than 13 is low anim else if (actionsCount <= 13 && false) // disabled because low animations on CC have different actions set { m_VDLength = 13; } else // any other case is high anim { m_VDLength = 22; } } // initialize the animations array UOAnimation[] output = new UOAnimation[m_VDLength]; // people and equipment uses the same animations id (if it's originally from a VD file, we keep the animations list as it is) if (m_VDLength == 35 || m_VDOriginal) { // copy the animations for (int i = 0; i < m_VDLength; i++) { output[i] = Actions[i]; } } else // creatures uses different IDs { output[0] = GetAction(22); output[1] = GetAction(25); output[2] = GetAction(2); output[3] = GetAction(3); output[4] = GetAction(4); output[5] = GetAction(5); output[6] = GetAction(6); output[7] = GetAction(7); output[8] = GetAction(8); output[9] = GetAction(9); output[10] = GetAction(10); output[11] = GetAction(11); output[12] = GetAction(12); // only for high animations if (m_VDLength > 13) { output[13] = GetAction(13); output[14] = GetAction(14); output[15] = GetAction(15); output[16] = GetAction(16); output[17] = GetAction(28); output[18] = GetAction(26); output[19] = GetAction(19); output[20] = GetAction(20); output[21] = GetAction(21); } } return(output); }
/// <summary> /// Read VD animations /// </summary> /// <param name="reader">binary reader attached to the file</param> /// <returns></returns> private bool ReadVDAnimations(BinaryReader reader) { // initialize the action idex int actionIndex = -1; // scan the animations count for (int i = 0; i < m_VDLength; i++) { // temporary list containing all the frame sets List <byte[]> framesets = new List <byte[]>(); // each animation in a VD file is a single direction, so we need to load 5 in order to have a full animation for (int direction = 0; direction < 5; direction++) { // starting position of the animation int startPos = reader.ReadInt32(); // byte size of the animation int size = reader.ReadInt32(); // unused flag (is always 0) reader.ReadInt32(); // undefined animation data if (startPos <= -1 || startPos >= reader.BaseStream.Length || size == 0) { continue; } // store the current position (we'll go back here after we loaded the animation of this direction) long pos = (int)reader.BaseStream.Position; // move to the animation position reader.BaseStream.Seek(startPos, SeekOrigin.Begin); // add the frame set to the list framesets.Add(reader.ReadBytes(size)); // move the to the next animation header starting point reader.BaseStream.Seek(pos, SeekOrigin.Begin); // prevent the app from freezing Application.DoEvents(); } // increase the action index actionIndex++; // make sure we have 5 framesets or the animation is incomplete if (framesets.Count < 5) { continue; } // load the animation data UOAnimation anim = new UOAnimation(framesets); // store the animation Actions[actionIndex] = anim; // prevent the app from freezing Application.DoEvents(); } return(true); }