using System; using System.Collections.Generic; using System.Xml; using Oni.Metadata; namespace Oni.Objects { internal class PatrolPath : ObjectBase { private string name; private PatrolPathPoint[] points; private int patrolId; private int returnToNearest; public PatrolPath() { TypeId = ObjectType.PatrolPath; } protected override void WriteOsd(BinaryWriter writer) { writer.Write(name, 32); writer.Write(points.Length); writer.WriteUInt16(patrolId); writer.WriteUInt16(returnToNearest); foreach (var point in points) { writer.Write((int)point.Type); switch (point.Type) { case PatrolPathPointType.Loop: case PatrolPathPointType.Stop: case PatrolPathPointType.StopLooking: case PatrolPathPointType.StopScanning: case PatrolPathPointType.FreeFacing: break; case PatrolPathPointType.LoopFrom: writer.Write((int)point.Attributes["From"]); break; case PatrolPathPointType.IgnorePlayer: writer.WriteByte((byte)point.Attributes["Value"]); break; case PatrolPathPointType.ForkScript: case PatrolPathPointType.CallScript: writer.Write((short)point.Attributes["ScriptId"]); break; case PatrolPathPointType.MoveToFlag: case PatrolPathPointType.LookAtFlag: case PatrolPathPointType.MoveAndFaceFlag: writer.Write((short)point.Attributes["FlagId"]); break; case PatrolPathPointType.MovementMode: writer.Write((int)(PatrolPathMovementMode)point.Attributes["Mode"]); break; case PatrolPathPointType.LockFacing: writer.Write((int)(PatrolPathFacing)point.Attributes["Facing"]); break; case PatrolPathPointType.Pause: writer.Write((int)point.Attributes["Frames"]); break; case PatrolPathPointType.GlanceAtFlagFor: writer.Write((short)point.Attributes["FlagId"]); writer.Write((int)point.Attributes["Frames"]); break; case PatrolPathPointType.Scan: writer.Write((short)point.Attributes["Frames"]); writer.Write((float)point.Attributes["Rotation"]); break; case PatrolPathPointType.MoveThroughFlag: case PatrolPathPointType.MoveNearFlag: writer.Write((short)point.Attributes["FlagId"]); writer.Write((float)point.Attributes["Distance"]); break; case PatrolPathPointType.MoveToFlagLookAndWait: writer.Write((short)point.Attributes["Frames"]); writer.Write((short)point.Attributes["FlagId"]); writer.Write((float)point.Attributes["Rotation"]); break; case PatrolPathPointType.FaceToFlagAndFire: writer.Write((short)point.Attributes["FlagId"]); writer.Write((short)point.Attributes["Frames"]); writer.Write((float)point.Attributes["Spread"]); break; case PatrolPathPointType.LookAtPoint: case PatrolPathPointType.MoveToPoint: writer.Write((Vector3)point.Attributes["Point"]); break; case PatrolPathPointType.MoveThroughPoint: writer.Write((Vector3)point.Attributes["Point"]); writer.Write((float)point.Attributes["Distance"]); break; default: throw new NotSupportedException(string.Format("Unsupported path point type {0}", point.Type)); } } } protected override void ReadOsd(BinaryReader reader) { throw new NotImplementedException(); } protected override void WriteOsd(XmlWriter xml) { throw new NotImplementedException(); } protected override void ReadOsd(XmlReader xml, ObjectLoadContext context) { name = xml.ReadElementContentAsString("Name", ""); patrolId = xml.ReadElementContentAsInt("PatrolId", ""); returnToNearest = xml.ReadElementContentAsInt("ReturnToNearest", ""); bool isEmpty = xml.IsEmptyElement; xml.ReadStartElement("Points"); if (isEmpty) { points = new PatrolPathPoint[0]; return; } var pointList = new List(); int loopStart = -1; bool inLoop = false; for (int index = 0; xml.IsStartElement() || inLoop; index++) { if (!xml.IsStartElement()) { xml.ReadEndElement(); inLoop = false; continue; } if (xml.LocalName == "Loop") { if (xml.SkipEmpty()) continue; inLoop = true; loopStart = index; xml.ReadStartElement(); continue; } var point = new PatrolPathPoint(MetaEnum.Parse(xml.LocalName)); switch (point.Type) { case PatrolPathPointType.Stop: case PatrolPathPointType.StopLooking: case PatrolPathPointType.StopScanning: case PatrolPathPointType.FreeFacing: break; case PatrolPathPointType.IgnorePlayer: point.Attributes["Value"] = (byte)(xml.GetAttribute("Value") == "Yes" ? 1 : 0); break; case PatrolPathPointType.ForkScript: case PatrolPathPointType.CallScript: point.Attributes["ScriptId"] = XmlConvert.ToInt16(xml.GetAttribute("ScriptId")); break; case PatrolPathPointType.MoveToFlag: case PatrolPathPointType.LookAtFlag: case PatrolPathPointType.MoveAndFaceFlag: point.Attributes["FlagId"] = XmlConvert.ToInt16(xml.GetAttribute("FlagId")); break; case PatrolPathPointType.MovementMode: point.Attributes["Mode"] = Convert.ToInt32(MetaEnum.Parse(xml.GetAttribute("Mode"))); break; case PatrolPathPointType.LockFacing: point.Attributes["Facing"] = Convert.ToInt32(MetaEnum.Parse(xml.GetAttribute("Facing"))); break; case PatrolPathPointType.Pause: point.Attributes["Frames"] = XmlConvert.ToInt32(xml.GetAttribute("Frames")); break; case PatrolPathPointType.GlanceAtFlagFor: point.Attributes["FlagId"] = XmlConvert.ToInt16(xml.GetAttribute("FlagId")); point.Attributes["Frames"] = XmlConvert.ToInt32(xml.GetAttribute("Frames")); break; case PatrolPathPointType.Scan: point.Attributes["Frames"] = XmlConvert.ToInt16(xml.GetAttribute("Frames")); point.Attributes["Rotation"] = XmlConvert.ToSingle(xml.GetAttribute("Rotation")); break; case PatrolPathPointType.MoveThroughFlag: case PatrolPathPointType.MoveNearFlag: point.Attributes["FlagId"] = XmlConvert.ToInt16(xml.GetAttribute("FlagId")); point.Attributes["Distance"] = XmlConvert.ToSingle(xml.GetAttribute("Distance")); break; case PatrolPathPointType.MoveToFlagLookAndWait: point.Attributes["Frames"] = XmlConvert.ToInt16(xml.GetAttribute("Frames")); point.Attributes["FlagId"] = XmlConvert.ToInt16(xml.GetAttribute("FlagId")); point.Attributes["Rotation"] = XmlConvert.ToSingle(xml.GetAttribute("Rotation")); break; case PatrolPathPointType.FaceToFlagAndFire: point.Attributes["FlagId"] = XmlConvert.ToInt16(xml.GetAttribute("FlagId")); point.Attributes["Frames"] = XmlConvert.ToInt16(xml.GetAttribute("Frames")); point.Attributes["Spread"] = XmlConvert.ToSingle(xml.GetAttribute("Spread")); break; case PatrolPathPointType.LookAtPoint: case PatrolPathPointType.MoveToPoint: point.Attributes["Point"] = new Vector3( XmlConvert.ToSingle(xml.GetAttribute("X")), XmlConvert.ToSingle(xml.GetAttribute("Y")), XmlConvert.ToSingle(xml.GetAttribute("Z"))); break; case PatrolPathPointType.MoveThroughPoint: point.Attributes["Point"] = new Vector3( XmlConvert.ToSingle(xml.GetAttribute("X")), XmlConvert.ToSingle(xml.GetAttribute("Y")), XmlConvert.ToSingle(xml.GetAttribute("Z"))); point.Attributes["Distance"] = XmlConvert.ToSingle(xml.GetAttribute("Distance")); break; default: throw new NotSupportedException(string.Format("Unsupported path point type {0}", point.Type)); } xml.Skip(); pointList.Add(point); } xml.ReadEndElement(); if (loopStart == 0) { pointList.Add(new PatrolPathPoint(PatrolPathPointType.Loop)); } else if (loopStart > 0) { var point = new PatrolPathPoint(PatrolPathPointType.LoopFrom); point.Attributes["From"] = loopStart; pointList.Add(point); } points = pointList.ToArray(); } } }