Compare commits

...

11 commits

Author SHA1 Message Date
81e89b84fc Update to work with UTMT 0.8.x 2025-05-14 02:55:12 +03:00
ithinkandicode
6ec4691448 fix: Fix room view setting for width (was set to ViewHeight) 2025-05-14 02:55:12 +03:00
ithinkandicode
349983498b fix: Write room view setting for height (hview) 2025-05-14 02:55:12 +03:00
ithinkandicode
74e8f74385 fix: Write room setting for "Draw background color" (showColour) 2025-05-14 02:55:12 +03:00
ithinkandicode
90bf7f24f3 feat: Add variable to set EOL character (LF or CRLF) - use eol variable 2025-05-14 02:55:12 +03:00
ithinkandicode
f26c349ed9 feat: Add variable to set EOL character (LF or CRLF) 2025-05-14 02:55:12 +03:00
ithinkandicode
39b8958d9c fix: Remove repeated bbox_right in sprite export (minor) 2020-05-17 10:51:23 +01:00
Cube
c0ca4e1adc Fix background export 2020-03-24 21:58:55 +08:00
Cube
e3c753b664 fix sprite border 2020-01-28 19:45:54 +08:00
Cube
a107b80c1d
Merge pull request #6 from nkrapivin/master
Implement Physics, makerSettings, and got rid of all TODOs
2020-01-26 16:14:35 +08:00
Nikita Krapivin
47174b0e2f
Implement Physics, makerSettings, and got rid of all TODOs
hooray!
2020-01-13 22:22:38 +05:00
2 changed files with 110 additions and 49 deletions

View file

@ -10,12 +10,15 @@ using System.Reflection;
using UndertaleModLib.Models; using UndertaleModLib.Models;
using UndertaleModLib.Util; using UndertaleModLib.Util;
using UndertaleModLib.Decompiler; using UndertaleModLib.Decompiler;
using Underanalyzer.Decompiler;
string GameName = Data.GeneralInfo.Name.ToString().Replace(@"""",""); //Name == "Project" -> Project
int progress = 0; int progress = 0;
string projFolder = GetFolder(FilePath) + "Export_Project" + Path.DirectorySeparatorChar; string projFolder = GetFolder(FilePath) + GameName + ".gmx" + Path.DirectorySeparatorChar;
TextureWorker worker = new TextureWorker(); TextureWorker worker = new();
ThreadLocal<DecompileContext> DECOMPILE_CONTEXT = new ThreadLocal<DecompileContext>(() => new DecompileContext(Data, false)); GlobalDecompileContext decompileContext = new(Data);
string gmxDeclaration = "This Document is generated by GameMaker, if you edit it by hand then you do so at your own risk!"; string gmxDeclaration = "This Document is generated by GameMaker, if you edit it by hand then you do so at your own risk!";
string eol = "\n"; // Linux: "\n", Windows: "\r\n"
if (Directory.Exists(projFolder)) if (Directory.Exists(projFolder))
{ {
@ -68,7 +71,7 @@ await ExportTimelines();
GenerateProjectFile(); GenerateProjectFile();
// --------------- Export completed --------------- // --------------- Export completed ---------------
worker.Cleanup(); worker.Dispose(); // worker.Cleanup()?
HideProgressBar(); HideProgressBar();
ScriptMessage("Export Complete.\n\nLocation: " + projFolder); ScriptMessage("Export Complete.\n\nLocation: " + projFolder);
@ -115,8 +118,7 @@ void ExportSprite(UndertaleSprite sprite)
new XElement("For3D", "0"), new XElement("For3D", "0"),
new XElement("width", sprite.Width.ToString()), new XElement("width", sprite.Width.ToString()),
new XElement("height", sprite.Height.ToString()), new XElement("height", sprite.Height.ToString()),
new XElement("frames"), new XElement("frames")
new XElement("bbox_right", sprite.MarginRight.ToString())
) )
); );
@ -134,22 +136,14 @@ void ExportSprite(UndertaleSprite sprite)
} }
} }
File.WriteAllText(projFolder + "/sprites/" + sprite.Name.Content + ".sprite.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/sprites/" + sprite.Name.Content + ".sprite.gmx", gmx.ToString() + eol);
// Save sprite images // Save sprite images
for (int i = 0; i < sprite.Textures.Count; i++) for (int i = 0; i < sprite.Textures.Count; i++)
{ {
if (sprite.Textures[i]?.Texture != null) if (sprite.Textures[i]?.Texture != null)
{ {
// Fix sprite size worker.ExportAsPNG(sprite.Textures[i].Texture, projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png", null, true);
var bitmapNew = new Bitmap((int)sprite.Width, (int)sprite.Height);
var bitmapOrigin = worker.GetTextureFor(sprite.Textures[i].Texture, Path.GetFileNameWithoutExtension(projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png"));
//worker.ExportAsPNG(sprite.Textures[i].Texture, projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png");
var g = Graphics.FromImage(bitmapNew);
g.DrawImage(bitmapOrigin, (int)sprite.Textures[i].Texture.TargetX, (int)sprite.Textures[i].Texture.TargetY);
bitmapNew.Save(projFolder + "/sprites/images/" + sprite.Name.Content + "_" + i + ".png");
bitmapNew.Dispose();
bitmapOrigin.Dispose();
} }
} }
} }
@ -169,8 +163,8 @@ void ExportBackground(UndertaleBackground background)
new XComment(gmxDeclaration), new XComment(gmxDeclaration),
new XElement("background", new XElement("background",
new XElement("istileset", "-1"), new XElement("istileset", "-1"),
new XElement("tilewidth", background.Texture.BoundingWidth.ToString()), new XElement("tilewidth", background.Texture == null ? "0" : background.Texture.BoundingWidth.ToString()),
new XElement("tileheight", background.Texture.BoundingHeight.ToString()), new XElement("tileheight", background.Texture == null ? "0" : background.Texture.BoundingHeight.ToString()),
new XElement("tilexoff", "0"), new XElement("tilexoff", "0"),
new XElement("tileyoff", "0"), new XElement("tileyoff", "0"),
new XElement("tilehsep", "0"), new XElement("tilehsep", "0"),
@ -181,15 +175,16 @@ void ExportBackground(UndertaleBackground background)
new XElement("TextureGroup0", "0") new XElement("TextureGroup0", "0")
), ),
new XElement("For3D", "0"), new XElement("For3D", "0"),
new XElement("width", background.Texture.BoundingWidth.ToString()), new XElement("width", background.Texture == null ? "0" : background.Texture.BoundingWidth.ToString()),
new XElement("height", background.Texture.BoundingHeight.ToString()), new XElement("height",background.Texture == null ? "0" : background.Texture.BoundingHeight.ToString()),
new XElement("data", "images\\" + background.Name.Content + ".png") new XElement("data", "images\\" + background.Name.Content + ".png")
) )
); );
File.WriteAllText(projFolder + "/background/" + background.Name.Content + ".background.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/background/" + background.Name.Content + ".background.gmx", gmx.ToString() + eol);
// Save background images // Save background images
if (background.Texture != null)
worker.ExportAsPNG(background.Texture, projFolder + "/background/images/" + background.Name.Content + ".png"); worker.ExportAsPNG(background.Texture, projFolder + "/background/images/" + background.Name.Content + ".png");
} }
// --------------- Export Object --------------- // --------------- Export Object ---------------
@ -213,10 +208,36 @@ void ExportGameObject(UndertaleGameObject gameObject)
new XElement("persistent", BoolToString(gameObject.Persistent)), new XElement("persistent", BoolToString(gameObject.Persistent)),
new XElement("parentName", gameObject.ParentId is null ? "<undefined>" : gameObject.ParentId.Name.Content), new XElement("parentName", gameObject.ParentId is null ? "<undefined>" : gameObject.ParentId.Name.Content),
new XElement("maskName", gameObject.TextureMaskId is null ? "<undefined>" : gameObject.TextureMaskId.Name.Content), new XElement("maskName", gameObject.TextureMaskId is null ? "<undefined>" : gameObject.TextureMaskId.Name.Content),
new XElement("events") new XElement("events"),
//Physics
new XElement("PhysicsObject", BoolToString(gameObject.UsesPhysics)),
new XElement("PhysicsObjectSensor", BoolToString(gameObject.IsSensor)),
new XElement("PhysicsObjectShape", (uint)gameObject.CollisionShape),
new XElement("PhysicsObjectDensity", gameObject.Density),
new XElement("PhysicsObjectRestitution", gameObject.Restitution),
new XElement("PhysicsObjectGroup", gameObject.Group),
new XElement("PhysicsObjectLinearDamping", gameObject.LinearDamping),
new XElement("PhysicsObjectAngularDamping", gameObject.AngularDamping),
new XElement("PhysicsObjectFriction", gameObject.Friction),
new XElement("PhysicsObjectAwake", BoolToString(gameObject.Awake)),
new XElement("PhysicsObjectKinematic", BoolToString(gameObject.Kinematic)),
new XElement("PhysicsShapePoints")
) )
); );
// Loop through PhysicsShapePoints List
for (int _point = 0; _point < gameObject.PhysicsVertices.Count; _point++)
{
var _x = gameObject.PhysicsVertices[_point].X;
var _y = gameObject.PhysicsVertices[_point].Y;
var physicsPointsNode = gmx.Element("object").Element("PhysicsShapePoints");
physicsPointsNode.Add(new XElement("points",_x.ToString() + "," + _y.ToString()));
}
// Traversing the event type list // Traversing the event type list
for (int i = 0; i < gameObject.Events.Count; i++) for (int i = 0; i < gameObject.Events.Count; i++)
{ {
@ -249,6 +270,13 @@ void ExportGameObject(UndertaleGameObject gameObject)
// Traversing the action list // Traversing the action list
foreach (var k in j.Actions) foreach (var k in j.Actions)
{ {
DecompileContext dec_context = new(decompileContext, k.CodeId, Data.ToolInfo.DecompilerSettings);
XElement act_string = null;
try {
act_string = new XElement("string", (k.CodeId != null && dec_context != null) ? dec_context.DecompileToString() : "");
} catch (DecompilerException) {
act_string = new XElement("string", "");
}
actionNode.Add( actionNode.Add(
new XElement("libid", k.LibID.ToString()), new XElement("libid", k.LibID.ToString()),
new XElement("id", k.ID.ToString()), new XElement("id", k.ID.ToString()),
@ -257,7 +285,7 @@ void ExportGameObject(UndertaleGameObject gameObject)
new XElement("isquestion", BoolToString(k.IsQuestion)), new XElement("isquestion", BoolToString(k.IsQuestion)),
new XElement("useapplyto", BoolToString(k.UseApplyTo)), new XElement("useapplyto", BoolToString(k.UseApplyTo)),
new XElement("exetype", k.ExeType.ToString()), new XElement("exetype", k.ExeType.ToString()),
new XElement("functionname", k.ActionName.Content), new XElement("functionname", k.ActionName != null ? k.ActionName.Content : ""),
new XElement("codestring", ""), new XElement("codestring", ""),
new XElement("whoName", "self"), new XElement("whoName", "self"),
new XElement("relative", BoolToString(k.Relative)), new XElement("relative", BoolToString(k.Relative)),
@ -265,7 +293,7 @@ void ExportGameObject(UndertaleGameObject gameObject)
new XElement("arguments", new XElement("arguments",
new XElement("argument", new XElement("argument",
new XElement("kind", "1"), new XElement("kind", "1"),
new XElement("string", k.CodeId != null ? Decompiler.Decompile(k.CodeId, DECOMPILE_CONTEXT.Value) : "") act_string
) )
) )
); );
@ -273,12 +301,11 @@ void ExportGameObject(UndertaleGameObject gameObject)
eventNode.Add(actionNode); eventNode.Add(actionNode);
eventsNode.Add(eventNode); eventsNode.Add(eventNode);
// TODOPhysics
} }
} }
} }
File.WriteAllText(projFolder + "/objects/" + gameObject.Name.Content + ".object.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/objects/" + gameObject.Name.Content + ".object.gmx", gmx.ToString() + eol);
} }
// --------------- Export Room --------------- // --------------- Export Room ---------------
@ -304,13 +331,29 @@ void ExportRoom(UndertaleRoom room)
new XElement("speed", room.Speed.ToString()), new XElement("speed", room.Speed.ToString()),
new XElement("persistent", BoolToString(room.Persistent)), new XElement("persistent", BoolToString(room.Persistent)),
new XElement("colour", room.BackgroundColor.ToString()), new XElement("colour", room.BackgroundColor.ToString()),
new XElement("code", room.CreationCodeId != null ? Decompiler.Decompile(room.CreationCodeId, DECOMPILE_CONTEXT.Value) : ""), new XElement("showcolour", BoolToString(room.DrawBackgroundColor)),
new XElement("code", room.CreationCodeId != null ? new DecompileContext(decompileContext, room.CreationCodeId).DecompileToString() : ""),
new XElement("enableViews", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.EnableViews))), new XElement("enableViews", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.EnableViews))),
new XElement("clearViewBackground", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ShowColor))), new XElement("clearViewBackground", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ShowColor))),
new XElement("clearDisplayBuffer", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ClearDisplayBuffer))) //new XElement("clearDisplayBuffer", BoolToString(room.Flags.HasFlag(UndertaleRoom.RoomEntryFlags.ClearDisplayBuffer))),
new XElement("makerSettings",
new XElement("isSet", 0),
new XElement("w", 0),
new XElement("h", 0),
new XElement("showGrid", 0),
new XElement("showObjects", 0),
new XElement("showTiles", 0),
new XElement("showBackgrounds", 0),
new XElement("showForegrounds", 0),
new XElement("showViews", 0),
new XElement("deleteUnderlyingObj", 0),
new XElement("deleteUnderlyingTiles", 0),
new XElement("page", 0),
new XElement("xoffset", 0),
new XElement("yoffset", 0)
)
) )
); );
// TODOMakerSettings
// Room backgrounds // Room backgrounds
var backgroundsNode = new XElement("backgrounds"); var backgroundsNode = new XElement("backgrounds");
@ -322,8 +365,8 @@ void ExportRoom(UndertaleRoom room)
new XAttribute("name", i.BackgroundDefinition is null ? "" : i.BackgroundDefinition.Name.Content), new XAttribute("name", i.BackgroundDefinition is null ? "" : i.BackgroundDefinition.Name.Content),
new XAttribute("x", i.X.ToString()), new XAttribute("x", i.X.ToString()),
new XAttribute("y", i.Y.ToString()), new XAttribute("y", i.Y.ToString()),
new XAttribute("htiled", i.TileX.ToString()), new XAttribute("htiled", i.X.ToString()),
new XAttribute("vtiled", i.TileY.ToString()), new XAttribute("vtiled", i.Y.ToString()),
new XAttribute("hspeed", i.SpeedX.ToString()), new XAttribute("hspeed", i.SpeedX.ToString()),
new XAttribute("vspeed", i.SpeedY.ToString()), new XAttribute("vspeed", i.SpeedY.ToString()),
new XAttribute("stretch", "0") new XAttribute("stretch", "0")
@ -341,7 +384,8 @@ void ExportRoom(UndertaleRoom room)
new XAttribute("objName", i.ObjectId is null ? "<undefined>" : i.ObjectId.Name.Content), new XAttribute("objName", i.ObjectId is null ? "<undefined>" : i.ObjectId.Name.Content),
new XAttribute("xview", i.ViewX.ToString()), new XAttribute("xview", i.ViewX.ToString()),
new XAttribute("yview", i.ViewY.ToString()), new XAttribute("yview", i.ViewY.ToString()),
new XAttribute("wview", i.ViewHeight.ToString()), new XAttribute("wview", i.ViewWidth.ToString()),
new XAttribute("hview", i.ViewHeight.ToString()),
new XAttribute("xport", i.PortX.ToString()), new XAttribute("xport", i.PortX.ToString()),
new XAttribute("yport", i.PortY.ToString()), new XAttribute("yport", i.PortY.ToString()),
new XAttribute("wport", i.PortWidth.ToString()), new XAttribute("wport", i.PortWidth.ToString()),
@ -365,7 +409,7 @@ void ExportRoom(UndertaleRoom room)
new XAttribute("y", i.Y.ToString()), new XAttribute("y", i.Y.ToString()),
new XAttribute("name", "inst_" + i.InstanceID.ToString("X")), new XAttribute("name", "inst_" + i.InstanceID.ToString("X")),
new XAttribute("locked", "0"), new XAttribute("locked", "0"),
new XAttribute("code", i.CreationCode != null ? Decompiler.Decompile(i.CreationCode, DECOMPILE_CONTEXT.Value) : ""), new XAttribute("code", i.CreationCode != null ? new DecompileContext(decompileContext, i.CreationCode).DecompileToString() : ""),
new XAttribute("scaleX", i.ScaleX.ToString()), new XAttribute("scaleX", i.ScaleX.ToString()),
new XAttribute("scaleY", i.ScaleY.ToString()), new XAttribute("scaleY", i.ScaleY.ToString()),
new XAttribute("colour", i.Color.ToString()), new XAttribute("colour", i.Color.ToString()),
@ -399,9 +443,20 @@ void ExportRoom(UndertaleRoom room)
} }
gmx.Element("room").Add(tilesNode); gmx.Element("room").Add(tilesNode);
// TODORoom physics //Room Physics
File.WriteAllText(projFolder + "/rooms/" + room.Name.Content + ".room.gmx", gmx.ToString()); gmx.Element("room").Add(
new XElement("PhysicsWorld", room.World),
new XElement("PhysicsWorldTop", room.Top),
new XElement("PhysicsWorldLeft", room.Left),
new XElement("PhysicsWorldRight", room.Right),
new XElement("PhysicsWorldBottom", room.Bottom),
new XElement("PhysicsWorldGravityX", room.GravityX),
new XElement("PhysicsWorldGravityY", room.GravityY),
new XElement("PhysicsWorldPixToMeters", room.MetersPerPixel)
);
File.WriteAllText(projFolder + "/rooms/" + room.Name.Content + ".room.gmx", gmx.ToString() + eol);
} }
// --------------- Export Sound --------------- // --------------- Export Sound ---------------
@ -422,9 +477,13 @@ void ExportSound(UndertaleSound sound)
new XElement("extension", Path.GetExtension(sound.File.Content)), new XElement("extension", Path.GetExtension(sound.File.Content)),
new XElement("origname", "sound\\audio\\" + sound.File.Content), new XElement("origname", "sound\\audio\\" + sound.File.Content),
new XElement("effects", sound.Effects.ToString()), new XElement("effects", sound.Effects.ToString()),
new XElement("volume", sound.Volume.ToString()), new XElement("volume",
new XElement("volume", sound.Volume.ToString())
),
new XElement("pan", "0"), new XElement("pan", "0"),
new XElement("bitRates", "192"), new XElement("bitRates",
new XElement("bitRate", "192")
),
new XElement("sampleRates", new XElement("sampleRates",
new XElement("sampleRate", "44100") new XElement("sampleRate", "44100")
), ),
@ -443,7 +502,7 @@ void ExportSound(UndertaleSound sound)
) )
); );
File.WriteAllText(projFolder + "/sound/" + sound.Name.Content + ".sound.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/sound/" + sound.Name.Content + ".sound.gmx", gmx.ToString() + eol);
// Save sound files // Save sound files
if (sound.AudioFile != null) if (sound.AudioFile != null)
@ -461,7 +520,7 @@ void ExportScript(UndertaleScript script)
UpdateProgressBar(null, $"Exporting script: {script.Name.Content}", progress++, resourceNum); UpdateProgressBar(null, $"Exporting script: {script.Name.Content}", progress++, resourceNum);
// Save GML files // Save GML files
File.WriteAllText(projFolder + "/scripts/" + script.Name.Content + ".gml", (script.Code != null ? Decompiler.Decompile(script.Code, DECOMPILE_CONTEXT.Value) : "")); File.WriteAllText(projFolder + "/scripts/" + script.Name.Content + ".gml", script.Code != null ? new DecompileContext(decompileContext, script.Code).DecompileToString() : "");
} }
// --------------- Export Font --------------- // --------------- Export Font ---------------
@ -513,7 +572,7 @@ void ExportFont(UndertaleFont font)
glyphsNode.Add(glyphNode); glyphsNode.Add(glyphNode);
} }
File.WriteAllText(projFolder + "/fonts/" + font.Name.Content + ".font.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/fonts/" + font.Name.Content + ".font.gmx", gmx.ToString() + eol);
// Save font textures // Save font textures
worker.ExportAsPNG(font.Texture, projFolder + "/fonts/" + font.Name.Content + ".png"); worker.ExportAsPNG(font.Texture, projFolder + "/fonts/" + font.Name.Content + ".png");
@ -550,7 +609,7 @@ void ExportPath(UndertalePath path)
); );
} }
File.WriteAllText(projFolder + "/paths/" + path.Name.Content + ".path.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/paths/" + path.Name.Content + ".path.gmx", gmx.ToString() + eol);
} }
// --------------- Export Timelines --------------- // --------------- Export Timelines ---------------
@ -571,9 +630,9 @@ void ExportTimeline(UndertaleTimeline timeline)
foreach (var i in timeline.Moments) foreach (var i in timeline.Moments)
{ {
var entryNode = new XElement("entry"); var entryNode = new XElement("entry");
entryNode.Add(new XElement("step", i.Item1)); entryNode.Add(new XElement("step", i.Step));
entryNode.Add(new XElement("event")); entryNode.Add(new XElement("event"));
foreach (var j in i.Item2) foreach (var j in i.Event)
{ {
entryNode.Element("event").Add( entryNode.Element("event").Add(
new XElement("action", new XElement("action",
@ -592,7 +651,7 @@ void ExportTimeline(UndertaleTimeline timeline)
new XElement("arguments", new XElement("arguments",
new XElement("argument", new XElement("argument",
new XElement("kind", "1"), new XElement("kind", "1"),
new XElement("string", j.CodeId != null ? Decompiler.Decompile(j.CodeId, DECOMPILE_CONTEXT.Value) : "") new XElement("string", j.CodeId != null ? new DecompileContext(decompileContext, j.CodeId).DecompileToString() : "")
) )
) )
) )
@ -601,7 +660,7 @@ void ExportTimeline(UndertaleTimeline timeline)
gmx.Element("timeline").Add(entryNode); gmx.Element("timeline").Add(entryNode);
} }
File.WriteAllText(projFolder + "/timelines/" + timeline.Name.Content + ".timeline.gmx", gmx.ToString()); File.WriteAllText(projFolder + "/timelines/" + timeline.Name.Content + ".timeline.gmx", gmx.ToString() + eol);
} }
@ -626,7 +685,7 @@ void GenerateProjectFile()
WriteIndexes<UndertalePath>(gmx.Element("assets"), "paths", "paths", Data.Paths, "path", "paths\\"); WriteIndexes<UndertalePath>(gmx.Element("assets"), "paths", "paths", Data.Paths, "path", "paths\\");
WriteIndexes<UndertaleTimeline>(gmx.Element("assets"), "timelines", "timelines", Data.Timelines, "timeline", "timelines\\"); WriteIndexes<UndertaleTimeline>(gmx.Element("assets"), "timelines", "timelines", Data.Timelines, "timeline", "timelines\\");
File.WriteAllText(projFolder + "Export_Project.project.gmx", gmx.ToString()); File.WriteAllText(projFolder + GameName + ".project.gmx", gmx.ToString() + eol);
} }
void WriteIndexes<T>(XElement rootNode, string elementName, string attributeName, IList<T> dataList, string oneName, string resourcePath, string fileExtension = "") void WriteIndexes<T>(XElement rootNode, string elementName, string attributeName, IList<T> dataList, string oneName, string resourcePath, string fileExtension = "")

View file

@ -3,3 +3,5 @@
This is a script for UndertaleModTool, which can export game files as project files of GameMaker Studio. This is a script for UndertaleModTool, which can export game files as project files of GameMaker Studio.
Currently compatible with gms1.4, will support gms2 in the future. Currently compatible with gms1.4, will support gms2 in the future.
Original repo: https://github.com/cubeww/UndertaleModTool-ExportToProjectScript