source: OniSplit/Xml/ObjcXmlExporter.cs@ 1148

Last change on this file since 1148 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 17.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Xml;
5using Oni.Metadata;
6
7namespace Oni.Xml
8{
9 internal class ObjcXmlExporter : RawXmlExporter
10 {
11 private readonly Dictionary<ObjectMetadata.TypeTag, Action> typeWriters = new Dictionary<ObjectMetadata.TypeTag, Action>();
12 private int objectEndPosition;
13
14 private ObjcXmlExporter(BinaryReader reader, XmlWriter xml)
15 : base(reader, xml)
16 {
17 InitTypeWriters(typeWriters);
18 }
19
20 public static void Export(BinaryReader reader, XmlWriter xml)
21 {
22 var exporter = new ObjcXmlExporter(reader, xml);
23 exporter.Export();
24 }
25
26 private void Export()
27 {
28 int size = Reader.ReadInt32();
29 int version = Reader.ReadInt32();
30
31 Xml.WriteStartElement("Objects");
32
33 while (true)
34 {
35 int objectSize = Reader.ReadInt32();
36
37 if (objectSize == 0)
38 break;
39
40 int readerPosition = Reader.Position;
41 objectEndPosition = readerPosition + objectSize;
42
43 BeginStruct(Reader.Position);
44
45 var objectType = (ObjectMetadata.TypeTag)Reader.ReadInt32();
46 int objectId = Reader.ReadInt32();
47
48 Xml.WriteStartElement(objectType.ToString());
49 Xml.WriteAttributeString("Id", XmlConvert.ToString(objectId));
50
51 Xml.WriteStartElement("Header");
52 ObjectMetadata.Header.Accept(this);
53 Xml.WriteEndElement();
54
55 Xml.WriteStartElement("OSD");
56 typeWriters[objectType]();
57 Xml.WriteEndElement();
58
59 Xml.WriteEndElement();
60
61 Reader.Position = objectEndPosition;
62 }
63
64 Xml.WriteEndElement();
65 }
66
67 private void WriteCharacter()
68 {
69 ObjectMetadata.Character.Accept(this);
70 }
71
72 private void WriteCombatProfile()
73 {
74 ObjectMetadata.CombatProfile.Accept(this);
75 }
76
77 private void WriteConsole()
78 {
79 ObjectMetadata.Console.Accept(this);
80 WriteEventList();
81 }
82
83 private void WriteDoor()
84 {
85 ObjectMetadata.Door.Accept(this);
86 WriteEventList();
87 }
88
89 private void WriteFlag()
90 {
91 ObjectMetadata.Flag.Accept(this);
92 }
93
94 private void WriteFurniture()
95 {
96 ObjectMetadata.Furniture.Accept(this);
97 }
98
99 private void WriteMeleeProfile()
100 {
101 ObjectMetadata.MeleeProfile.Accept(this);
102
103 int attackCount = Reader.ReadInt32();
104 int evadeCount = Reader.ReadInt32();
105 int maneuverCount = Reader.ReadInt32();
106 int moveCount = Reader.ReadInt32();
107
108 int moveTablePosition = Reader.Position + (attackCount + evadeCount + maneuverCount) * 88;
109
110 Xml.WriteStartElement("Attacks");
111 for (int i = 0; i < attackCount; i++)
112 WriteMeleeTechnique(moveTablePosition);
113 Xml.WriteEndElement();
114
115 Xml.WriteStartElement("Evades");
116 for (int i = 0; i < evadeCount; i++)
117 WriteMeleeTechnique(moveTablePosition);
118 Xml.WriteEndElement();
119
120 Xml.WriteStartElement("Maneuvers");
121 for (int i = 0; i < maneuverCount; i++)
122 WriteMeleeTechnique(moveTablePosition);
123 Xml.WriteEndElement();
124 }
125
126 private void WriteMeleeTechnique(int moveTablePosition)
127 {
128 Xml.WriteStartElement("Technique");
129
130 ObjectMetadata.MeleeTechnique.Accept(this);
131
132 int moveCount = Reader.ReadInt32();
133 int moveStart = Reader.ReadInt32();
134
135 int oldPosition = Reader.Position;
136 Reader.Position = moveTablePosition + moveStart * 16;
137
138 Xml.WriteStartElement("Moves");
139
140 for (int j = 0; j < moveCount; j++)
141 WriteMeleeMove();
142
143 Xml.WriteEndElement();
144 Xml.WriteEndElement();
145
146 Reader.Position = oldPosition;
147 }
148
149 private void WriteMeleeMove()
150 {
151 int categoryType = Reader.ReadInt32();
152 float[] moveParams = Reader.ReadSingleArray(3);
153
154 var category = (ObjectMetadata.MeleeMoveCategory)(categoryType >> 24);
155 Xml.WriteStartElement(category.ToString());
156
157 switch (category)
158 {
159 default:
160 case ObjectMetadata.MeleeMoveCategory.Attack:
161 Xml.WriteAttributeString("Type", ((ObjectMetadata.MeleeMoveAttackType)(categoryType & 0xffffff)).ToString());
162 break;
163
164 case ObjectMetadata.MeleeMoveCategory.Evade:
165 Xml.WriteAttributeString("Type", ((ObjectMetadata.MeleeMoveEvadeType)(categoryType & 0xffffff)).ToString());
166 break;
167
168 case ObjectMetadata.MeleeMoveCategory.Throw:
169 Xml.WriteAttributeString("Type", ((ObjectMetadata.MeleeMoveThrowType)(categoryType & 0xffffff)).ToString());
170 break;
171
172 case ObjectMetadata.MeleeMoveCategory.Maneuver:
173 ObjectMetadata.MeleeMoveTypeInfo typeInfo = ObjectMetadata.MeleeMoveManeuverTypeInfo[categoryType & 0xffffff];
174 Xml.WriteAttributeString("Type", typeInfo.Type.ToString());
175
176 for (int k = 0; k < typeInfo.ParamNames.Length; k++)
177 Xml.WriteAttributeString(typeInfo.ParamNames[k], XmlConvert.ToString(moveParams[k]));
178
179 break;
180
181 case ObjectMetadata.MeleeMoveCategory.Position:
182 ObjectMetadata.MeleeMovePositionType moveType = (ObjectMetadata.MeleeMovePositionType)(categoryType & 0xffffff);
183 Xml.WriteAttributeString("Type", moveType.ToString());
184
185 if ((ObjectMetadata.MeleeMovePositionType.RunForward <= moveType && moveType <= ObjectMetadata.MeleeMovePositionType.RunBack)
186 || ObjectMetadata.MeleeMovePositionType.CloseForward <= moveType)
187 {
188 Xml.WriteAttributeString("MinRunInDist", XmlConvert.ToString(moveParams[0]));
189 Xml.WriteAttributeString("MaxRunInDist", XmlConvert.ToString(moveParams[1]));
190 Xml.WriteAttributeString("ToleranceRange", XmlConvert.ToString(moveParams[2]));
191 }
192
193 break;
194 }
195
196 Xml.WriteEndElement();
197 }
198
199 private void WriteNeutralBehavior()
200 {
201 ObjectMetadata.NeutralBehavior.Accept(this);
202 int lineCount = Reader.ReadInt16();
203 ObjectMetadata.NeutralBehaviorParams.Accept(this);
204
205 Xml.WriteStartElement("DialogLines");
206 MetaType.Array(lineCount, ObjectMetadata.NeutralBehaviorDialogLine).Accept(this);
207 Xml.WriteEndElement();
208 }
209
210 private void WriteParticle()
211 {
212 ObjectMetadata.Particle.Accept(this);
213 }
214
215 private void WritePatrolPath()
216 {
217 ObjectMetadata.PatrolPath.Accept(this);
218 int length = Reader.ReadInt32();
219 ObjectMetadata.PatrolPathInfo.Accept(this);
220
221 int startPosition = Reader.Position;
222 int loopStartPoint = -1;
223
224 var pointType = (ObjectMetadata.PatrolPathPointType)Reader.ReadInt32();
225
226 for (int i = 0; i < length; i++)
227 {
228 if (pointType == ObjectMetadata.PatrolPathPointType.Loop)
229 loopStartPoint = 0;
230 else if (pointType == ObjectMetadata.PatrolPathPointType.LoopFrom)
231 loopStartPoint = Reader.ReadInt32();
232 else
233 Reader.Position += ObjectMetadata.GetPatrolPathPointSize(pointType);
234
235 pointType = (ObjectMetadata.PatrolPathPointType)Reader.ReadInt32();
236 }
237
238 Reader.Position = startPosition;
239
240 Xml.WriteStartElement("Points");
241
242 for (int i = 0; i < length; i++)
243 {
244 if (loopStartPoint == i)
245 Xml.WriteStartElement("Loop");
246
247 WritePatrolPathPoint();
248 }
249
250 if (loopStartPoint != -1)
251 Xml.WriteEndElement();
252
253 Xml.WriteEndElement();
254 }
255
256 private void WritePatrolPathPoint()
257 {
258 var pointType = (ObjectMetadata.PatrolPathPointType)Reader.ReadInt32();
259
260 switch (pointType)
261 {
262 case ObjectMetadata.PatrolPathPointType.Loop:
263 return;
264
265 case ObjectMetadata.PatrolPathPointType.LoopFrom:
266 Reader.Skip(4);
267 return;
268 }
269
270 Xml.WriteStartElement(pointType.ToString());
271
272 switch (pointType)
273 {
274 case ObjectMetadata.PatrolPathPointType.Stop:
275 case ObjectMetadata.PatrolPathPointType.StopLooking:
276 case ObjectMetadata.PatrolPathPointType.StopScanning:
277 case ObjectMetadata.PatrolPathPointType.FreeFacing:
278 break;
279
280 case ObjectMetadata.PatrolPathPointType.IgnorePlayer:
281 Xml.WriteAttributeString("Value", Reader.ReadBoolean() ? "Yes" : "No");
282 break;
283
284 case ObjectMetadata.PatrolPathPointType.MoveToFlag:
285 case ObjectMetadata.PatrolPathPointType.LookAtFlag:
286 case ObjectMetadata.PatrolPathPointType.MoveAndFaceFlag:
287 Xml.WriteAttributeString("FlagId", XmlConvert.ToString(Reader.ReadInt16()));
288 break;
289
290 case ObjectMetadata.PatrolPathPointType.ForkScript:
291 case ObjectMetadata.PatrolPathPointType.CallScript:
292 Xml.WriteAttributeString("ScriptId", XmlConvert.ToString(Reader.ReadInt16()));
293 break;
294
295 case ObjectMetadata.PatrolPathPointType.Pause:
296 Xml.WriteAttributeString("Frames", XmlConvert.ToString(Reader.ReadInt32()));
297 break;
298
299 case ObjectMetadata.PatrolPathPointType.MovementMode:
300 Xml.WriteAttributeString("Mode", ((ObjectMetadata.PatrolPathMovementMode)Reader.ReadInt32()).ToString());
301 break;
302
303 case ObjectMetadata.PatrolPathPointType.LockFacing:
304 Xml.WriteAttributeString("Facing", ((ObjectMetadata.PatrolPathFacing)Reader.ReadInt32()).ToString());
305 break;
306
307 case ObjectMetadata.PatrolPathPointType.MoveThroughFlag:
308 case ObjectMetadata.PatrolPathPointType.MoveNearFlag:
309 Xml.WriteAttributeString("FlagId", XmlConvert.ToString(Reader.ReadInt16()));
310 Xml.WriteAttributeString("Distance", XmlConvert.ToString(Reader.ReadSingle()));
311 break;
312
313 case ObjectMetadata.PatrolPathPointType.GlanceAtFlagFor:
314 Xml.WriteAttributeString("FlagId", XmlConvert.ToString(Reader.ReadInt16()));
315 Xml.WriteAttributeString("Frames", XmlConvert.ToString(Reader.ReadInt32()));
316 break;
317
318 case ObjectMetadata.PatrolPathPointType.Scan:
319 Xml.WriteAttributeString("Frames", XmlConvert.ToString(Reader.ReadInt16()));
320 Xml.WriteAttributeString("Rotation", XmlConvert.ToString(Reader.ReadSingle()));
321 break;
322
323 case ObjectMetadata.PatrolPathPointType.MoveToFlagLookAndWait:
324 Xml.WriteAttributeString("Frames", XmlConvert.ToString(Reader.ReadInt16()));
325 Xml.WriteAttributeString("FlagId", XmlConvert.ToString(Reader.ReadInt16()));
326 Xml.WriteAttributeString("Rotation", XmlConvert.ToString(Reader.ReadSingle()));
327 break;
328
329 case ObjectMetadata.PatrolPathPointType.FaceToFlagAndFire:
330 Xml.WriteAttributeString("FlagId", XmlConvert.ToString(Reader.ReadInt16()));
331 Xml.WriteAttributeString("Frames", XmlConvert.ToString(Reader.ReadInt16()));
332 Xml.WriteAttributeString("Spread", XmlConvert.ToString(Reader.ReadSingle()));
333 break;
334
335 case ObjectMetadata.PatrolPathPointType.LookAtPoint:
336 case ObjectMetadata.PatrolPathPointType.MoveToPoint:
337 Xml.WriteAttributeString("X", XmlConvert.ToString(Reader.ReadSingle()));
338 Xml.WriteAttributeString("Y", XmlConvert.ToString(Reader.ReadSingle()));
339 Xml.WriteAttributeString("Z", XmlConvert.ToString(Reader.ReadSingle()));
340 break;
341
342 case ObjectMetadata.PatrolPathPointType.MoveThroughPoint:
343 Xml.WriteAttributeString("X", XmlConvert.ToString(Reader.ReadSingle()));
344 Xml.WriteAttributeString("Y", XmlConvert.ToString(Reader.ReadSingle()));
345 Xml.WriteAttributeString("Z", XmlConvert.ToString(Reader.ReadSingle()));
346 Xml.WriteAttributeString("Distance", XmlConvert.ToString(Reader.ReadSingle()));
347 break;
348
349 default:
350 throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Unsupported path point type {0}", pointType));
351 }
352
353 Xml.WriteEndElement();
354 }
355
356 private void WritePowerUp()
357 {
358 ObjectMetadata.PowerUp.Accept(this);
359 }
360
361 private void WriteSound()
362 {
363 ObjectMetadata.Sound.Accept(this);
364
365 var volumeType = (ObjectMetadata.SoundVolumeType)Reader.ReadInt32();
366
367 switch (volumeType)
368 {
369 case ObjectMetadata.SoundVolumeType.Box:
370 Xml.WriteStartElement("Box");
371 MetaType.BoundingBox.Accept(this);
372 Xml.WriteEndElement();
373 break;
374
375 case ObjectMetadata.SoundVolumeType.Sphere:
376 Xml.WriteStartElement("Sphere");
377 ObjectMetadata.SoundSphere.Accept(this);
378 Xml.WriteEndElement();
379 break;
380 }
381
382 ObjectMetadata.SoundParams.Accept(this);
383 }
384
385 private void WriteTriggerVolume()
386 {
387 ObjectMetadata.TriggerVolume.Accept(this);
388 }
389
390 private void WriteTrigger()
391 {
392 ObjectMetadata.Trigger.Accept(this);
393 WriteEventList();
394 }
395
396 private void WriteTurret()
397 {
398 ObjectMetadata.Turret.Accept(this);
399 }
400
401 private void WriteWeapon()
402 {
403 ObjectMetadata.Weapon.Accept(this);
404 }
405
406 private void WriteEventList()
407 {
408 Xml.WriteStartElement("Events");
409
410 int count = Reader.ReadInt16();
411
412 for (int i = 0; i < count; i++)
413 {
414 var eventType = (ObjectMetadata.EventType)Reader.ReadInt16();
415
416 Xml.WriteStartElement(eventType.ToString());
417
418 switch (eventType)
419 {
420 case ObjectMetadata.EventType.None:
421 break;
422 case ObjectMetadata.EventType.Script:
423 Xml.WriteAttributeString("Function", Reader.ReadString(32));
424 break;
425 default:
426 Xml.WriteAttributeString("TargetId", XmlConvert.ToString(Reader.ReadInt16()));
427 break;
428 }
429
430 Xml.WriteEndElement();
431 }
432
433 Xml.WriteEndElement();
434 }
435
436 private void InitTypeWriters(Dictionary<ObjectMetadata.TypeTag, Action> typeWriters)
437 {
438 typeWriters.Add(ObjectMetadata.TypeTag.CHAR, WriteCharacter);
439 typeWriters.Add(ObjectMetadata.TypeTag.CMBT, WriteCombatProfile);
440 typeWriters.Add(ObjectMetadata.TypeTag.CONS, WriteConsole);
441 typeWriters.Add(ObjectMetadata.TypeTag.DOOR, WriteDoor);
442 typeWriters.Add(ObjectMetadata.TypeTag.FLAG, WriteFlag);
443 typeWriters.Add(ObjectMetadata.TypeTag.FURN, WriteFurniture);
444 typeWriters.Add(ObjectMetadata.TypeTag.MELE, WriteMeleeProfile);
445 typeWriters.Add(ObjectMetadata.TypeTag.NEUT, WriteNeutralBehavior);
446 typeWriters.Add(ObjectMetadata.TypeTag.PART, WriteParticle);
447 typeWriters.Add(ObjectMetadata.TypeTag.PATR, WritePatrolPath);
448 typeWriters.Add(ObjectMetadata.TypeTag.PWRU, WritePowerUp);
449 typeWriters.Add(ObjectMetadata.TypeTag.SNDG, WriteSound);
450 typeWriters.Add(ObjectMetadata.TypeTag.TRGV, WriteTriggerVolume);
451 typeWriters.Add(ObjectMetadata.TypeTag.TRIG, WriteTrigger);
452 typeWriters.Add(ObjectMetadata.TypeTag.TURR, WriteTurret);
453 typeWriters.Add(ObjectMetadata.TypeTag.WEAP, WriteWeapon);
454 }
455 }
456}
Note: See TracBrowser for help on using the repository browser.