static void AddScriptFromFile(string path)
        {
            string scriptSource = File.ReadAllText(path);
            string gmlWeirdName = "gml_Script_" + Path.GetFileNameWithoutExtension(path);

            // Make a code entry.
            UndertaleCode codeEntry = new UndertaleCode
            {
                Name = Data.Strings.MakeString(gmlWeirdName)
            };

            Data.Code.Add(codeEntry);

            // Make a code locals entry.
            UndertaleCodeLocals locals = new UndertaleCodeLocals
            {
                Name = codeEntry.Name
            };

            // Make a `var arguments;` entry.
            UndertaleCodeLocals.LocalVar argsLocal = new UndertaleCodeLocals.LocalVar
            {
                Name  = Data.Strings.MakeString("arguments"),
                Index = 0
            };

            // Glue everything together.
            locals.Locals.Add(argsLocal);
            Data.CodeLocals.Add(locals);

            // Set code locals entry for the code entry.
            codeEntry.LocalsCount = 1;
            //codeEntry.GenerateLocalVarDefinitions(codeEntry.FindReferencedLocalVars(), locals); // fails here.

            // FINALLY compile our script.
            Data.Code.ByName(gmlWeirdName).ReplaceGML(scriptSource, Data);

            // ... and actually add it like a script...
            var scr = new UndertaleScript
            {
                Code = Data.Code.ByName(gmlWeirdName),
                Name = Data.Strings.MakeString(Path.GetFileNameWithoutExtension(path))
            };

            Data.Scripts.Add(scr);

            // ... oh, and don't forget to add a *function* reference.
            var funcentry = new UndertaleFunction
            {
                Name = Data.Strings.MakeString(Path.GetFileNameWithoutExtension(path))
            };

            Data.Functions.Add(funcentry);
        }
예제 #2
0
        void ImportCode(string codeName, string gmlCode, bool IsGML = true, bool doParse = true, bool destroyASM = true, bool CheckDecompiler = false)
        {
            bool          SkipPortions = false;
            UndertaleCode code         = Data.Code.ByName(codeName);

            if (Data.Code.ByName(codeName) == null)
            {
                code      = new UndertaleCode();
                code.Name = Data.Strings.MakeString(codeName);
                Data.Code.Add(code);
            }
            if (Data?.GeneralInfo.BytecodeVersion > 14 && Data.CodeLocals.ByName(codeName) == null)
            {
                UndertaleCodeLocals locals = new UndertaleCodeLocals();
                locals.Name = code.Name;

                UndertaleCodeLocals.LocalVar argsLocal = new UndertaleCodeLocals.LocalVar();
                argsLocal.Name  = Data.Strings.MakeString("arguments");
                argsLocal.Index = 0;

                locals.Locals.Add(argsLocal);

                code.LocalsCount = 1;
                code.GenerateLocalVarDefinitions(code.FindReferencedLocalVars(), locals); // Dunno if we actually need this line, but it seems to work?
                Data.CodeLocals.Add(locals);
            }
            if (doParse)
            {
                // This portion links code.
                if (codeName.Substring(0, 10).Equals("gml_Script"))
                {
                    // Add code to scripts section.
                    if (Data.Scripts.ByName(codeName.Substring(11)) == null)
                    {
                        UndertaleScript scr = new UndertaleScript();
                        scr.Name = Data.Strings.MakeString(codeName.Substring(11));
                        scr.Code = code;
                        Data.Scripts.Add(scr);
                    }
                    else
                    {
                        UndertaleScript scr = Data.Scripts.ByName(codeName.Substring(11));
                        scr.Code = code;
                    }
                }
                else if (codeName.Substring(0, 16).Equals("gml_GlobalScript"))
                {
                    // Add code to global init section.
                    UndertaleGlobalInit init_entry = null;
                    // This doesn't work, have to do it the hard way: UndertaleGlobalInit init_entry = Data.GlobalInitScripts.ByName(scr_dup_code_name_con);
                    foreach (UndertaleGlobalInit globalInit in Data.GlobalInitScripts)
                    {
                        if (globalInit.Code.Name.Content == codeName)
                        {
                            init_entry = globalInit;
                            break;
                        }
                    }
                    if (init_entry == null)
                    {
                        UndertaleGlobalInit NewInit = new UndertaleGlobalInit();
                        NewInit.Code = code;
                        Data.GlobalInitScripts.Add(NewInit);
                    }
                    else
                    {
                        UndertaleGlobalInit NewInit = init_entry;
                        NewInit.Code = code;
                    }
                }
                else if (codeName.Substring(0, 10).Equals("gml_Object"))
                {
                    string afterPrefix = codeName.Substring(11);
                    int    underCount = 0;
                    string methodNumberStr = "", methodName = "", objName = "";
                    for (int i = afterPrefix.Length - 1; i >= 0; i--)
                    {
                        if (afterPrefix[i] == '_')
                        {
                            underCount++;
                            if (underCount == 1)
                            {
                                methodNumberStr = afterPrefix.Substring(i + 1);
                            }
                            else if (underCount == 2)
                            {
                                objName    = afterPrefix.Substring(0, i);
                                methodName = afterPrefix.Substring(i + 1, afterPrefix.Length - objName.Length - methodNumberStr.Length - 2);
                                break;
                            }
                        }
                    }
                    int methodNumber = 0;
                    try
                    {
                        methodNumber = int.Parse(methodNumberStr);
                        if (methodName == "Collision" && (methodNumber >= Data.GameObjects.Count || methodNumber < 0))
                        {
                            bool doNewObj = ScriptQuestion("Object of ID " + methodNumber.ToString() + " was not found.\nAdd new object?");
                            if (doNewObj)
                            {
                                UndertaleGameObject gameObj = new UndertaleGameObject();
                                gameObj.Name = Data.Strings.MakeString(SimpleTextInput("Enter object name", "Enter object name", "This is a single text line input box test.", false));
                                Data.GameObjects.Add(gameObj);
                            }
                            else
                            {
                                // It *needs* to have a valid value, make the user specify one.
                                List <uint> possible_values = new List <uint>();
                                possible_values.Add(uint.MaxValue);
                                methodNumber = (int)ReduceCollisionValue(possible_values);
                            }
                        }
                    }
                    catch
                    {
                        if (afterPrefix.LastIndexOf("_Collision_") != -1)
                        {
                            string s2 = "_Collision_";
                            objName         = afterPrefix.Substring(0, (afterPrefix.LastIndexOf("_Collision_")));
                            methodNumberStr = afterPrefix.Substring(afterPrefix.LastIndexOf("_Collision_") + s2.Length, afterPrefix.Length - (afterPrefix.LastIndexOf("_Collision_") + s2.Length));
                            methodName      = "Collision";
                            // GMS 2.3+ use the object name for the one colliding, which is rather useful.
                            if (Data.GMS2_3)
                            {
                                if (Data.GameObjects.ByName(methodNumberStr) != null)
                                {
                                    for (var i = 0; i < Data.GameObjects.Count; i++)
                                    {
                                        if (Data.GameObjects[i].Name.Content == methodNumberStr)
                                        {
                                            methodNumber = i;
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    bool doNewObj = ScriptQuestion("Object " + objName + " was not found.\nAdd new object called " + objName + "?");
                                    if (doNewObj)
                                    {
                                        UndertaleGameObject gameObj = new UndertaleGameObject();
                                        gameObj.Name = Data.Strings.MakeString(objName);
                                        Data.GameObjects.Add(gameObj);
                                    }
                                }
                                if (Data.GameObjects.ByName(methodNumberStr) != null)
                                {
                                    // It *needs* to have a valid value, make the user specify one, silly.
                                    List <uint> possible_values = new List <uint>();
                                    possible_values.Add(uint.MaxValue);
                                    ReassignGUIDs(methodNumberStr, ReduceCollisionValue(possible_values));
                                }
                            }
                            else
                            {
                                // Let's try to get this going
                                methodNumber = (int)ReduceCollisionValue(GetCollisionValueFromCodeNameGUID(codeName));
                                ReassignGUIDs(methodNumberStr, ReduceCollisionValue(GetCollisionValueFromCodeNameGUID(codeName)));
                            }
                        }
                    }
                    UndertaleGameObject obj = Data.GameObjects.ByName(objName);
                    if (obj == null)
                    {
                        bool doNewObj = ScriptQuestion("Object " + objName + " was not found.\nAdd new object called " + objName + "?");
                        if (doNewObj)
                        {
                            UndertaleGameObject gameObj = new UndertaleGameObject();
                            gameObj.Name = Data.Strings.MakeString(objName);
                            Data.GameObjects.Add(gameObj);
                        }
                        else
                        {
                            SkipPortions = true;
                        }
                    }

                    if (!(SkipPortions))
                    {
                        obj = Data.GameObjects.ByName(objName);
                        int  eventIdx  = (int)Enum.Parse(typeof(EventTypes), methodName);
                        bool duplicate = false;
                        try
                        {
                            foreach (UndertaleGameObject.Event evnt in obj.Events[eventIdx])
                            {
                                foreach (UndertaleGameObject.EventAction action in evnt.Actions)
                                {
                                    if (action.CodeId?.Name?.Content == codeName)
                                    {
                                        duplicate = true;
                                    }
                                }
                            }
                        }
                        catch
                        {
                            // Something went wrong, but probably because it's trying to check something non-existent
                            // Just keep going
                        }
                        if (duplicate == false)
                        {
                            UndertalePointerList <UndertaleGameObject.Event> eventList = obj.Events[eventIdx];
                            UndertaleGameObject.EventAction action = new UndertaleGameObject.EventAction();
                            UndertaleGameObject.Event       evnt   = new UndertaleGameObject.Event();

                            action.ActionName = code.Name;
                            action.CodeId     = code;
                            evnt.EventSubtype = (uint)methodNumber;
                            evnt.Actions.Add(action);
                            eventList.Add(evnt);
                        }
                    }
                }
            }
            SafeImport(codeName, gmlCode, IsGML, destroyASM, CheckDecompiler);
        }
예제 #3
0
        public static void SpeedrunPatches(UndertaleData data)
        {
            UndertaleScript setboi = new UndertaleScript();

            setboi.Name      = data.Strings.MakeString("set_speedrun_category");
            setboi.Code      = new UndertaleCode();
            setboi.Code.Name = data.Strings.MakeString("gml_Script_set_speedrun_category");
            setboi.Code.ReplaceGML(RabbitRunCode.set_speedrun_category, data);
            data.Code.Add(setboi.Code);
            data.Scripts.Add(setboi);

            UndertaleScript sprun = new UndertaleScript();

            sprun.Name = new UndertaleString("menu_speedrun_script");
            data.Strings.Add(sprun.Name);
            sprun.Code = new UndertaleCode();
            data.Code.Add(sprun.Code);
            sprun.Code.Name = new UndertaleString("gml_Script_menu_speedrun_script");
            data.Strings.Add(sprun.Code.Name);
            sprun.Code.ReplaceGML(RabbitRunCode.menu_speedrun_script, data);
            sprun.Code.UpdateAddresses();
            data.Scripts.Add(sprun);

            UndertaleCode ae = data.Code.ByName("gml_Script_setfile");

            ae.AppendGML(RabbitRunCode.gml_Script_setfile, data);
            ae.UpdateAddresses();

            UndertaleCode ee = data.Code.ByName("gml_Object_obj_mainmenus_Create_0");

            ReplaceInGML("GAME\", 1, 8],", "GAME\", 1, 8], [\"SPEEDBUN\", 1, 19], ", ee, data);
            ee.UpdateAddresses();
            ReplaceInGML("i = 0", RabbitRunCode.speedrunMenuInit, ee, data);

            UndertaleCode ie = data.Code.ByName("gml_Script_cKeys_beginstep");

            ie.AppendGML(RabbitRunCode.tasBeginStepInput, data);

            UndertaleCode oe = data.Code.ByName("gml_Object_obj_init_Create_0");

            oe.AppendGML(@"global.playRun = false;
global.watchRun = false;
global.speedrunning = true;
global.inrun = false;
global.onehun = false;//one hundred percent
global.allbun = false;//all cuties
global.anyper = false;//any percent", data);

            UndertaleCode ue = data.Code.ByName("gml_Script_SaveStringToFile");

            ue.ReplaceGML(RabbitRunCode.saveStringFile, data);

            UndertaleSprite mico = data.Sprites.ByName("spr_menuicons");

            UndertaleSprite.TextureEntry te = new UndertaleSprite.TextureEntry();
            UndertaleTexturePageItem     ti = mico.Textures[1].Texture;
            UndertaleTexturePageItem     to = data.Sprites.ByName("spr_antibunidle").Textures[0].Texture;

            te.Texture                = new UndertaleTexturePageItem();
            te.Texture.TargetX        = ti.TargetX;
            te.Texture.TargetY        = ti.TargetY;
            te.Texture.SourceX        = to.SourceX;
            te.Texture.SourceY        = to.SourceY;
            te.Texture.BoundingHeight = ti.BoundingHeight;
            te.Texture.BoundingWidth  = ti.BoundingWidth;
            te.Texture.SourceWidth    = 16;
            te.Texture.TargetWidth    = 16;
            te.Texture.SourceHeight   = 15;
            te.Texture.TargetHeight   = 15;
            te.Texture.TexturePage    = to.TexturePage;
            data.TexturePageItems.Add(te.Texture);
            mico.Textures.Insert(2, te);
        }