public static void ExportCharacterNewFormat(Character character, string fileName, Game game) { if (File.Exists(fileName)) { File.Delete(fileName); } XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.Default); writer.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"" + Encoding.Default.WebName + "\""); writer.WriteComment("AGS Exported Character file. DO NOT EDIT THIS FILE BY HAND, IT IS GENERATED AUTOMATICALLY BY THE AGS EDITOR."); writer.WriteStartElement(CHARACTER_XML_ROOT_NODE); writer.WriteAttributeString(CHARACTER_XML_VERSION_ATTRIBUTE, CHARACTER_XML_CURRENT_VERSION); character.ToXml(writer); writer.WriteStartElement(CHARACTER_XML_VIEWS_NODE); Dictionary<int, object> spritesWritten = new Dictionary<int, object>(); writer.WriteStartElement("NormalView"); WriteNewStyleView(writer, game.FindViewByID(character.NormalView), spritesWritten); writer.WriteEndElement(); if (character.SpeechView > 0) { writer.WriteStartElement("SpeechView"); WriteNewStyleView(writer, game.FindViewByID(character.SpeechView), spritesWritten); writer.WriteEndElement(); } if (character.IdleView > 0) { writer.WriteStartElement("IdleView"); WriteNewStyleView(writer, game.FindViewByID(character.IdleView), spritesWritten); writer.WriteEndElement(); } if (character.ThinkingView > 0) { writer.WriteStartElement("ThinkingView"); WriteNewStyleView(writer, game.FindViewByID(character.ThinkingView), spritesWritten); writer.WriteEndElement(); } if (character.BlinkingView > 0) { writer.WriteStartElement("BlinkingView"); WriteNewStyleView(writer, game.FindViewByID(character.BlinkingView), spritesWritten); writer.WriteEndElement(); } writer.WriteEndElement(); game.WritePaletteToXML(writer); writer.WriteEndElement(); writer.Close(); }
public static void ExportCharacterNewFormat(Character character, string fileName, Game game) { if (File.Exists(fileName)) { File.Delete(fileName); } XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.Default); writer.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"" + Encoding.Default.WebName + "\""); writer.WriteComment("Fichier de Personnage AGS Exporté. N'ÉDITEZ PAS CE FICHIER MANUELLEMENT, IL EST AUTOMATIQUEMENT GÉNÉRÉ PAR L'ÉDITEUR AGS."); writer.WriteStartElement(CHARACTER_XML_ROOT_NODE); writer.WriteAttributeString(CHARACTER_XML_VERSION_ATTRIBUTE, CHARACTER_XML_CURRENT_VERSION); character.ToXml(writer); writer.WriteStartElement(CHARACTER_XML_VIEWS_NODE); Dictionary<int, object> spritesWritten = new Dictionary<int, object>(); writer.WriteStartElement("NormalView"); WriteNewStyleView(writer, game.FindViewByID(character.NormalView), spritesWritten); writer.WriteEndElement(); if (character.SpeechView > 0) { writer.WriteStartElement("SpeechView"); WriteNewStyleView(writer, game.FindViewByID(character.SpeechView), spritesWritten); writer.WriteEndElement(); } if (character.IdleView > 0) { writer.WriteStartElement("IdleView"); WriteNewStyleView(writer, game.FindViewByID(character.IdleView), spritesWritten); writer.WriteEndElement(); } if (character.ThinkingView > 0) { writer.WriteStartElement("ThinkingView"); WriteNewStyleView(writer, game.FindViewByID(character.ThinkingView), spritesWritten); writer.WriteEndElement(); } if (character.BlinkingView > 0) { writer.WriteStartElement("BlinkingView"); WriteNewStyleView(writer, game.FindViewByID(character.BlinkingView), spritesWritten); writer.WriteEndElement(); } writer.WriteEndElement(); game.WritePaletteToXML(writer); writer.WriteEndElement(); writer.Close(); }
/// <summary> /// Export a 2.72-compatible CHA file. This code is horrid, but it's /// backwards compatible!! /// </summary> public static void ExportCharacter272(Character character, string fileName, Game game) { BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create, FileAccess.Write)); writer.Write(Encoding.ASCII.GetBytes(CHARACTER_FILE_SIGNATURE)); writer.Write((int)6); for (int i = 0; i < 256; i++) { writer.Write((byte)(game.Palette[i].Colour.R / 4)); writer.Write((byte)(game.Palette[i].Colour.G / 4)); writer.Write((byte)(game.Palette[i].Colour.B / 4)); writer.Write((byte)0); } WriteZeros(writer, 4); writer.Write(character.SpeechView); WriteZeros(writer, 4); writer.Write(character.StartingRoom); WriteZeros(writer, 4); writer.Write(character.StartX); writer.Write(character.StartY); WriteZeros(writer, 12); writer.Write(character.IdleView); WriteZeros(writer, 12); writer.Write(character.SpeechColor); writer.Write(character.ThinkingView); writer.Write((short)character.BlinkingView); WriteZeros(writer, 42); writer.Write((short)character.MovementSpeed); writer.Write((short)character.AnimationDelay); WriteZeros(writer, 606); writer.Write(Encoding.Default.GetBytes(character.RealName)); WriteZeros(writer, 40 - character.RealName.Length); string scriptName = character.ScriptName; if (scriptName.StartsWith("c")) { scriptName = scriptName.Substring(1).ToUpper(); } writer.Write(Encoding.Default.GetBytes(scriptName)); WriteZeros(writer, 20 - scriptName.Length); writer.Write((short)0); try { WriteOldStyleView(writer, game.FindViewByID(character.NormalView)); if (character.SpeechView > 0) { WriteOldStyleView(writer, game.FindViewByID(character.SpeechView)); } if (character.IdleView > 0) { WriteOldStyleView(writer, game.FindViewByID(character.IdleView)); } if (character.ThinkingView > 0) { WriteOldStyleView(writer, game.FindViewByID(character.ThinkingView)); } if (character.BlinkingView > 0) { WriteOldStyleView(writer, game.FindViewByID(character.BlinkingView)); } writer.Close(); } catch (Exception ex) { writer.Close(); File.Delete(fileName); throw ex; } }
public static bool SaveThisGameToFile(string fileName, Game game, CompileMessages errors) { FileStream ostream = File.Create(fileName); if (ostream == null) { errors.Add(new CompileError(string.Format("Cannot open file {0} for writing", fileName))); return false; } BinaryWriter writer = new BinaryWriter(ostream); WriteString(NativeConstants.GAME_FILE_SIG, NativeConstants.GAME_FILE_SIG.Length, writer); writer.Write(NativeConstants.GAME_DATA_VERSION_CURRENT); writer.Write(AGS.Types.Version.AGS_EDITOR_VERSION.Length); WriteString(AGS.Types.Version.AGS_EDITOR_VERSION, AGS.Types.Version.AGS_EDITOR_VERSION.Length, writer); // Write extended engine caps; none for this version writer.Write((int)0); // An example of writing caps (pseduo-code): // writer.Write(caps.Count); // foreach (cap in caps) // FilePutString(cap.Name); // WriteGameSetupStructBase_Aligned(writer, game); WriteString(game.Settings.GUIDAsString, NativeConstants.MAX_GUID_LENGTH, writer); WriteString(game.Settings.SaveGameFileExtension, NativeConstants.MAX_SG_EXT_LENGTH, writer); WriteString(game.Settings.SaveGameFolderName, NativeConstants.MAX_SG_FOLDER_LEN, writer); if (game.Fonts.Count > NativeConstants.MAX_FONTS) { errors.Add(new CompileError("Too many fonts")); return false; } for (int i = 0; i < game.Fonts.Count; ++i) { writer.Write((byte)(game.Fonts[i].PointSize & NativeConstants.FFLG_SIZEMASK)); } for (int i = 0; i < game.Fonts.Count; ++i) { if (game.Fonts[i].OutlineStyle == FontOutlineStyle.None) { writer.Write((sbyte)-1); } else if (game.Fonts[i].OutlineStyle == FontOutlineStyle.Automatic) { writer.Write(NativeConstants.FONT_OUTLINE_AUTO); } else { writer.Write((byte)game.Fonts[i].OutlineFont); } } for (int i = 0; i < game.Fonts.Count; ++i) { writer.Write(game.Fonts[i].VerticalOffset); } writer.Write(NativeConstants.MAX_SPRITES); byte[] spriteFlags = new byte[NativeConstants.MAX_SPRITES]; UpdateSpriteFlags(game.RootSpriteFolder, spriteFlags); for (int i = 0; i < NativeConstants.MAX_SPRITES; ++i) { writer.Write(spriteFlags[i]); } if (game.InventoryItems.Count > NativeConstants.MAX_INV) { errors.Add(new CompileError("Too many inventory items")); return false; } writer.Write(new byte[68]); // inventory item slot 0 is unused for (int i = 0; i < game.InventoryItems.Count; ++i) { WriteString(game.InventoryItems[i].Description, 24, writer); writer.Write(new byte[4]); // null terminator plus 3 bytes padding writer.Write(game.InventoryItems[i].Image); writer.Write(game.InventoryItems[i].CursorImage); writer.Write(game.InventoryItems[i].HotspotX); writer.Write(game.InventoryItems[i].HotspotY); for (int j = 0; j < 5; ++j) // write "reserved", currently unused { writer.Write(0); } writer.Write(game.InventoryItems[i].PlayerStartsWithItem ? NativeConstants.IFLG_STARTWITH : (char)0); writer.Write(new byte[3]); // 3 bytes padding } if (game.Cursors.Count > NativeConstants.MAX_CURSOR) { errors.Add(new CompileError("Too many cursors")); return false; } for (int i = 0; i < game.Cursors.Count; ++i) { char flags = (char)0; writer.Write(game.Cursors[i].Image); writer.Write((short)game.Cursors[i].HotspotX); writer.Write((short)game.Cursors[i].HotspotY); if (game.Cursors[i].Animate) { writer.Write((short)(game.Cursors[i].View - 1)); if (game.Cursors[i].AnimateOnlyOnHotspots) flags |= NativeConstants.MCF_HOTSPOT; if (game.Cursors[i].AnimateOnlyWhenMoving) flags |= NativeConstants.MCF_ANIMMOVE; } else writer.Write((short)-1); WriteString(game.Cursors[i].Name, 9, writer); writer.Write((byte)0); // null terminator if (game.Cursors[i].StandardMode) flags |= NativeConstants.MCF_STANDARD; writer.Write(flags); writer.Write(new byte[3]); // 3 bytes padding } for (int i = 0; i < game.Characters.Count; ++i) { SerializeInteractionScripts(game.Characters[i].Interactions, writer); } for (int i = 1; i <= game.InventoryItems.Count; ++i) { SerializeInteractionScripts(game.InventoryItems[i - 1].Interactions, writer); } writer.Write(game.TextParser.Words.Count); for (int i = 0; i < game.TextParser.Words.Count; ++i) { WriteStringEncrypted(writer, SafeTruncate(game.TextParser.Words[i].Word, NativeConstants.MAX_PARSER_WORD_LENGTH)); writer.Write((short)game.TextParser.Words[i].WordGroup); } if (!WriteCompiledScript(ostream, game.ScriptsToCompile.GetScriptByFilename(Script.GLOBAL_SCRIPT_FILE_NAME), errors) || !WriteCompiledScript(ostream, game.ScriptsToCompile.GetScriptByFilename(Script.DIALOG_SCRIPTS_FILE_NAME), errors)) { return false; } // Extract all the scripts we want to persist (all the non-headers, except // the global script which was already written) List<Script> scriptsToWrite = new List<Script>(); foreach (ScriptAndHeader scriptAndHeader in game.ScriptsToCompile) { Script script = scriptAndHeader.Script; if (script != null) { if ((!script.FileName.Equals(Script.GLOBAL_SCRIPT_FILE_NAME)) && (!script.FileName.Equals(Script.DIALOG_SCRIPTS_FILE_NAME))) { scriptsToWrite.Add(script); } } } writer.Write(scriptsToWrite.Count); foreach (Script script in scriptsToWrite) { if (!WriteCompiledScript(ostream, script, errors)) { return false; } } ViewsWriter viewsWriter = new ViewsWriter(writer, game); if (!viewsWriter.WriteViews(FolderHelper.GetRootViewFolder(game), game, errors)) { return false; } foreach (Character character in game.Characters) { int flags = 0; if (character.AdjustSpeedWithScaling) flags |= NativeConstants.CHF_SCALEMOVESPEED; if (character.AdjustVolumeWithScaling) flags |= NativeConstants.CHF_SCALEVOLUME; if (!character.Clickable) flags |= NativeConstants.CHF_NOINTERACT; if (!character.DiagonalLoops) flags |= NativeConstants.CHF_NODIAGONAL; if (character.MovementLinkedToAnimation) flags |= NativeConstants.CHF_ANTIGLIDE; if (!character.Solid) flags |= NativeConstants.CHF_NOBLOCKING; if (!character.TurnBeforeWalking) flags |= NativeConstants.CHF_NOTURNING; if (!character.UseRoomAreaLighting) flags |= NativeConstants.CHF_NOLIGHTING; if (!character.UseRoomAreaScaling) flags |= NativeConstants.CHF_MANUALSCALING; writer.Write(character.NormalView - 1); // defview writer.Write(character.SpeechView - 1); // talkview writer.Write(character.NormalView - 1); // view writer.Write(character.StartingRoom); // room writer.Write(0); // prevroom writer.Write(character.StartX); // x writer.Write(character.StartY); // y writer.Write(0); // wait writer.Write(flags); // flags writer.Write((short)0); // following writer.Write((short)0); // followinfo writer.Write(character.IdleView - 1); // idleview writer.Write((short)0); // idletime writer.Write((short)0); // idleleft writer.Write((short)0); // transparency writer.Write((short)0); // baseline writer.Write(0); // activeinv writer.Write(character.SpeechColor); // talkcolor writer.Write(character.ThinkingView - 1); // thinkview writer.Write((short)(character.BlinkingView - 1)); // blinkview writer.Write((short)0); // blinkinterval writer.Write((short)0); // blinktimer writer.Write((short)0); // blinkframe writer.Write(character.UniformMovementSpeed ? // walkspeed_y NativeConstants.UNIFORM_WALK_SPEED : (short)character.MovementSpeedY); writer.Write((short)0); // pic_yoffs writer.Write(0); // z writer.Write(0); // walkwait writer.Write((short)character.SpeechAnimationDelay); // speech_anim_speed writer.Write((short)0); // reserved1 writer.Write((short)0); // blocking_width writer.Write((short)0); // blocking_height writer.Write(0); // index_id writer.Write((short)0); // pic_xoffs writer.Write((short)0); // walkwaitcounter writer.Write((short)0); // loop writer.Write((short)0); // frame writer.Write((short)0); // walking writer.Write((short)0); // animating writer.Write(character.UniformMovementSpeed ? // walkspeed (short)character.MovementSpeed : (short)character.MovementSpeedX); writer.Write((short)character.AnimationDelay); // animspeed bool isPlayer = (character == game.PlayerCharacter); foreach (InventoryItem invItem in game.InventoryItems) // inv[MAX_INV] { if ((isPlayer) && (invItem.PlayerStartsWithItem)) writer.Write((short)1); else writer.Write((short)0); } if (game.InventoryItems.Count < NativeConstants.MAX_INV) { writer.Write(new byte[(NativeConstants.MAX_INV - game.InventoryItems.Count) * sizeof(short)]); } writer.Write((short)0); // actx writer.Write((short)0); // acty WriteString(character.RealName, 40, writer); // name WriteString(character.ScriptName, NativeConstants.MAX_SCRIPT_NAME_LEN, writer); // scrname writer.Write((char)1); // on writer.Write((byte)0); // alignment padding } for (int i = 0; i < NativeConstants.MAXLIPSYNCFRAMES; ++i) { WriteString(game.LipSync.CharactersPerFrame[i], 50, writer); } for (int i = 0; i < NativeConstants.MAXGLOBALMES; ++i) { if (string.IsNullOrEmpty(game.GlobalMessages[i])) continue; WriteStringEncrypted(writer, game.GlobalMessages[i]); } if (game.Dialogs.Count > NativeConstants.MAX_DIALOG) { errors.Add(new CompileError("Too many dialogs")); return false; } foreach (Dialog curDialog in game.Dialogs) { for (int i = 0; (i < NativeConstants.MAXTOPICOPTIONS) && (i < curDialog.Options.Count); ++i) { WriteString(curDialog.Options[i].Text, 150, writer); // optionnames } for (int i = curDialog.Options.Count; i < NativeConstants.MAXTOPICOPTIONS; ++i) { WriteString("", 150, writer); } for (int i = 0; (i < NativeConstants.MAXTOPICOPTIONS) && (i < curDialog.Options.Count); ++i) { DialogOption option = curDialog.Options[i]; int flags = 0; if (!option.Say) flags |= NativeConstants.DFLG_NOREPEAT; if (option.Show) flags |= NativeConstants.DFLG_ON; writer.Write(flags); // optionflags } for (int i = curDialog.Options.Count; i < NativeConstants.MAXTOPICOPTIONS; ++i) { writer.Write(0); } writer.Write(new byte[4]); // optionscripts writer.Write(new byte[NativeConstants.MAXTOPICOPTIONS * sizeof(short)]); // entrypoints writer.Write((short)0); // startupentrypoint writer.Write((short)0); // codesize writer.Write(curDialog.Options.Count); // numoptions writer.Write(curDialog.ShowTextParser ? NativeConstants.DTFLG_SHOWPARSER : 0); // topicflags } GUIsWriter guisWriter = new GUIsWriter(writer, game); guisWriter.WriteAllGUIs(); if (!WritePluginsToDisk(writer, game, errors)) { return false; } writer.Write(NativeConstants.CustomPropertyVersion.Current); writer.Write(game.PropertySchema.PropertyDefinitions.Count); foreach (CustomPropertySchemaItem schemaItem in game.PropertySchema.PropertyDefinitions) { FilePutString(schemaItem.Name, writer); writer.Write((int)schemaItem.Type); FilePutString(schemaItem.Description, writer); FilePutString(schemaItem.DefaultValue, writer); } for (int i = 0; i < game.Characters.Count; ++i) { CustomPropertiesWriter.Write(writer, game.Characters[i].Properties); } writer.Write(1); // inv slot 0 is unused, write the property header (int 1) writer.Write(0); // then write the number of props used by this inv item (int 0) for (int i = 0; i < game.InventoryItems.Count; ++i) { CustomPropertiesWriter.Write(writer, game.InventoryItems[i].Properties); } for (int i = 0; i < game.ViewCount; ++i) // ViewCount is highest numbered view { View view = game.FindViewByID(i + 1); if (view != null) FilePutNullTerminatedString(view.Name, view.Name.Length + 1, writer); else writer.Write((byte)0); // view is null, so its name is just a single NUL byte } writer.Write((byte)0); // inventory slot 0 is unused, so its name is just a single NUL byte for (int i = 0; i < game.InventoryItems.Count; ++i) { string buffer = game.InventoryItems[i].Name; FilePutNullTerminatedString(buffer, buffer.Length + 1, writer); } for (int i = 0; i < game.Dialogs.Count; ++i) { string buffer = game.Dialogs[i].Name; FilePutNullTerminatedString(buffer, buffer.Length + 1, writer); } writer.Write(game.AudioClipTypes.Count + 1); // hard coded SPEECH audio type 0 writer.Write(0); // id writer.Write(1); // reservedChannels writer.Write(0); // volume_reduction_while_speech_playing writer.Write(0); // crossfadeSpeed writer.Write(0); // reservedForFuture for (int i = 1; i < (game.AudioClipTypes.Count + 1); ++i) { writer.Write(i); // id writer.Write(game.AudioClipTypes[i - 1].MaxChannels); // reservedChannels writer.Write(game.AudioClipTypes[i - 1].VolumeReductionWhileSpeechPlaying); // volume_reduction_while_speech_playing writer.Write((int)game.AudioClipTypes[i - 1].CrossfadeClips); // crossfadeSpeed writer.Write(0); } IList<AudioClip> allClips = game.CachedAudioClipListForCompile; writer.Write(allClips.Count); for (int i = 0; i < allClips.Count; ++i) { AudioClip clip = allClips[i]; writer.Write(0); // id WriteString(SafeTruncate(clip.ScriptName, 29), 30, writer); // scriptName WriteString(SafeTruncate(clip.CacheFileNameWithoutPath, 14), 15, writer); // fileName writer.Write((byte)clip.BundlingType); // bundlingType writer.Write((byte)clip.Type); // type writer.Write((byte)clip.FileType); // fileType writer.Write(clip.ActualRepeat ? (byte)1 : (byte)0); // defaultRepeat writer.Write((byte)0); // struct alignment padding writer.Write((short)clip.ActualPriority); // defaultPriority writer.Write((short)clip.ActualVolume); // defaultVolume writer.Write(new byte[2]); // struct alignment padding writer.Write(0); // reserved } writer.Write(game.GetAudioArrayIndexFromAudioClipIndex(game.Settings.PlaySoundOnScore)); if (game.Settings.DebugMode) { writer.Write(game.Rooms.Count); for (int i = 0; i < game.Rooms.Count; ++i) { IRoom room = game.Rooms[i]; writer.Write(room.Number); if (room.Description != null) { FilePutNullTerminatedString(room.Description, 500, writer); } else writer.Write((byte)0); } } writer.Close(); GC.Collect(); return true; }