public static GonObject ArtAltsMerge(GonObject low, GonObject high)
            {
                // create new gonObject to return
                GonObject ret = new GonObject();

                ret.Type = FieldType.ARRAY;

                List <string[]> lowArr  = GonTo2DStringArray(low).ToList();
                List <string[]> highArr = GonTo2DStringArray(high).ToList();

                for (int i = 0; i < lowArr.Count(); i++)
                {
                    bool found = false;
                    for (int j = 0; j < highArr.Count(); j++)
                    {
                        if (lowArr[i][0] == highArr[j][0])
                        {
                            ret.InsertChild(FromStringArray(highArr[j]));
                            highArr.Remove(highArr[j]);
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        ret.InsertChild(FromStringArray(lowArr[i]));
                    }
                }
                foreach (var highItem in highArr)
                {
                    ret.InsertChild(FromStringArray(highItem));
                }

                return(ret);
            }
        static void remove_patch_suffixes_recursive(GonObject obj)
        {
            remove_suffix(ref obj.Name, ".overwrite");
            remove_suffix(ref obj.Name, ".append");
            remove_suffix(ref obj.Name, ".merge");
            remove_suffix(ref obj.Name, ".add");
            remove_suffix(ref obj.Name, ".multiply");

            if (obj.Type == FieldType.OBJECT)
            {
                obj.Children_Map.Clear();
                for (int i = 0; i < obj.size(); i++)
                {
                    remove_patch_suffixes_recursive(obj.Children_Array[i]);
                    obj.Children_Map[obj.Children_Array[i].Name] = i;
                }
            }
            else if (obj.Type == FieldType.ARRAY)
            {
                for (int i = 0; i < obj.size(); i++)
                {
                    remove_patch_suffixes_recursive(obj.Children_Array[i]);
                }
            }
        }
        // METHODS

        // resource loading functions
        static void LoadFunnyNames()
        {
            var gon = GonObject.Load("data/text/area_names.gon");

            LINames      = GonObject.Manip.GonToStringArray(gon["name"]);
            LILocations  = GonObject.Manip.GonToStringArray(gon["location"]);
            LIAdjectives = GonObject.Manip.GonToStringArray(gon["adjective"]);
            LINouns      = GonObject.Manip.GonToStringArray(gon["noun"]);
        }
 public static int[] GonToIntArray(GonObject gon)
 {
     int[] ret = new int[gon.Size()];
     for (int i = 0; i < gon.Size(); i++)
     {
         ret[i] = gon[i].Int();
     }
     return(ret);
 }
Beispiel #5
0
        public void Load()
        {
            var gon = GonObject.Load("data/text/settings.gon");    // open levelpool file

            NumLevels     = gon[nameof(NumLevels)].Int();
            NumAreas      = gon[nameof(NumAreas)].Int();
            DoMusic       = gon[nameof(DoMusic)].Bool();
            DoPalettes    = gon[nameof(DoPalettes)].Bool();
            MusicPerLevel = gon[nameof(MusicPerLevel)].Bool();
            //PalettePerLevel = gon[nameof(PalettePerLevel));
            DoShaders       = gon[nameof(DoShaders)].Bool();
            DoParticles     = gon[nameof(DoParticles)].Bool();
            DoOverlays      = gon[nameof(DoOverlays)].Bool();
            DoTileGraphics  = gon[nameof(DoTileGraphics)].Bool();
            DoNevermoreTilt = gon[nameof(DoNevermoreTilt)].Bool();
            DoExodusWobble  = gon[nameof(DoExodusWobble)].Bool();
            //DoArtAlts = gon[nameof(DoArtAlts));
            DoNPCs         = gon[nameof(DoNPCs)].Bool();
            UseAreaTileset = gon[nameof(UseAreaTileset)].Bool();
            CacheRuns      = gon[nameof(CacheRuns)].Int();
            //NumShuffles = gon[nameof(NumShuffles));
            AreaType        = gon[nameof(AreaType)].String();
            RepeatTolerance = gon[nameof(RepeatTolerance)].Int();
            AltLevel        = gon[nameof(AltLevel)].String();
            //AttachToTS = gon[nameof(AttachToTS));
            //AutoRefresh = gon[nameof(AutoRefresh));
            GenerateCustomParticles = gon[nameof(GenerateCustomParticles)].Bool();
            MaxParticles            = gon[nameof(MaxParticles)].Int();
            GameDirectory           = gon[nameof(GameDirectory)].String();
            //ModSaveDirectory = gon[nameof(ModSaveDirectory));
            MaxParticleEffects = gon[nameof(MaxParticleEffects)].Int();
            ManualLoad         = gon[nameof(ManualLoad)].Bool();
            DoCorruptions      = gon[nameof(DoCorruptions)].Bool();
            MirrorMode         = gon[nameof(MirrorMode)].Bool();
            DeadRacer          = gon[nameof(DeadRacer)].Bool();
            CartLives          = gon[nameof(CartLives)].Int();
            DoPhysics          = gon[nameof(DoPhysics)].Bool();
            PlatformPhysics    = gon[nameof(PlatformPhysics)].Bool();
            PlayerPhysics      = gon[nameof(PlayerPhysics)].Bool();
            WaterPhysics       = gon[nameof(WaterPhysics)].Bool();
            LowGravPhysics     = gon[nameof(LowGravPhysics)].Bool();
            LevelMerge         = gon[nameof(LevelMerge)].Bool();
            ToolsInDirectory   = gon[nameof(ToolsInDirectory)].String();
            ToolsOutDirectory  = gon[nameof(ToolsOutDirectory)].String();
            RandomizeAreaType  = gon[nameof(RandomizeAreaType)].Bool();
            CRSmart            = gon[nameof(CRSmart)].Bool();
            CROverlays         = gon[nameof(CROverlays)].Bool();
            CRTumors           = gon[nameof(CRTumors)].Bool();
            CRAddTiles         = gon[nameof(CRAddTiles)].Int();
            CRAddEnemies       = gon[nameof(CRAddEnemies)].Int();
            CRSpikeStrips      = gon[nameof(CRSpikeStrips)].Bool();
            CRCrumbles         = gon[nameof(CRCrumbles)].Bool();
            CRCrushers         = gon[nameof(CRCrushers)].Bool();
            CRChaos            = gon[nameof(CRChaos)].Bool();
            CRWaterLevels      = gon[nameof(CRWaterLevels)].Bool();
            UserName           = gon[nameof(UserName)].String();
        }
        static LevelCorruptors()
        {
            var gon = GonObject.Load($"data/text/corruptor_tiles.gon");

            ActiveTiles  = GonObject.Manip.GonToIntArray(gon["active"]);
            EntityTiles  = GonObject.Manip.GonToIntArray(gon["entity"]);
            OverlayTiles = GonObject.Manip.GonToIntArray(gon["overlay"]);
            SmartTiles   = LoadDictionary(gon["smart"]);
            ColorTiles   = LoadDictionary(gon["color"]);
        }
Beispiel #7
0
        public static void FixAltsFile()
        {
            var gon = GonObject.Load("data/text/art_alts.gon");

            string outFile = "";

            for (int i = 0; i < gon["safe"].Size(); i++)
            {
                var art = gon["safe"][i];
                outFile += $"{art.GetName()} [ ";

                for (int j = 0; j < art.Size(); j++)
                {
                    outFile += $"\"{art[j].String()}\", ";
                }
                outFile  = outFile.TrimEnd(' ', ',');
                outFile += "]\n";
            }

            for (int i = 0; i < gon["extended"].Size(); i++)
            {
                var art = gon["extended"][i];
                outFile += $"{art.GetName()} [ ";

                for (int j = 0; j < art.Size(); j++)
                {
                    outFile += $"\"{art[j].GetName()}\", ";
                }
                outFile  = outFile.TrimEnd(' ', ',');
                outFile += "]\n";
            }

            for (int i = 0; i < gon["crazy"].Size(); i++)
            {
                var art = gon["crazy"][i];
                outFile += $"{art.GetName()} [ ";

                for (int j = 0; j < art.Size(); j++)
                {
                    outFile += $"\"{art[j].GetName()}\", ";
                }
                outFile  = outFile.TrimEnd(' ', ',');
                outFile += "]\n";
            }

            for (int i = 0; i < gon["insane"].Size(); i++)
            {
                string name = gon["insane"][i].GetName();
                outFile += ($"\"{name}\", ");
            }
            outFile  = outFile.TrimEnd(' ', ',');
            outFile += "]\n";

            File.WriteAllText("art_alts.txt", outFile);
        }
Beispiel #8
0
        static TilesetManip()
        {
            // Load Resources
            var gon = GonObject.Load("data/text/tilesets_pools.gon");

            NumPalettes         = Convert.ToInt32(gon["palettes"].Int());
            TileGraphicsPool    = GonObject.Manip.GonToStringArray(gon["tile_graphics"]);
            OverlayGraphicsPool = GonObject.Manip.GonToStringArray(gon["overlay_graphics"]);
            ParticlePool        = GonObject.Manip.GonToStringArray(gon["particles"]);
            MusicPool           = GonObject.Manip.GonToStringArray(gon["music"]);
        }
            public static GonObject FromString(string val, string name = "")
            {
                GonObject gon = new GonObject();

                gon.Name = name;
                gon.Type = FieldType.STRING;

                gon.String_Data = val;

                return(gon);
            }
            // Custom Gon Object Constructors)
            public static GonObject FromBool(bool val, string name = "")
            {
                GonObject gon = new GonObject();

                gon.Name = name;
                gon.Type = FieldType.BOOL;

                gon.Bool_Data = val;

                return(gon);
            }
Beispiel #11
0
        public void Save()
        {
            var gon = new GonObject();

            gon.InsertChild(nameof(NumLevels), GonObject.Manip.FromInt(NumLevels));
            gon.InsertChild(nameof(NumAreas), GonObject.Manip.FromInt(NumAreas));
            gon.InsertChild(nameof(DoMusic), GonObject.Manip.FromBool(DoMusic));
            gon.InsertChild(nameof(DoPalettes), GonObject.Manip.FromBool(DoPalettes));
            gon.InsertChild(nameof(MusicPerLevel), GonObject.Manip.FromBool(MusicPerLevel));
            gon.InsertChild(nameof(DoShaders), GonObject.Manip.FromBool(DoShaders));
            gon.InsertChild(nameof(DoParticles), GonObject.Manip.FromBool(DoParticles));
            gon.InsertChild(nameof(DoOverlays), GonObject.Manip.FromBool(DoOverlays));
            gon.InsertChild(nameof(DoTileGraphics), GonObject.Manip.FromBool(DoTileGraphics));
            gon.InsertChild(nameof(DoNevermoreTilt), GonObject.Manip.FromBool(DoNevermoreTilt));
            gon.InsertChild(nameof(DoExodusWobble), GonObject.Manip.FromBool(DoExodusWobble));
            gon.InsertChild(nameof(DoNPCs), GonObject.Manip.FromBool(DoNPCs));
            gon.InsertChild(nameof(UseAreaTileset), GonObject.Manip.FromBool(UseAreaTileset));
            gon.InsertChild(nameof(CacheRuns), GonObject.Manip.FromInt(CacheRuns));
            gon.InsertChild(nameof(AreaType), GonObject.Manip.FromString(AreaType));
            gon.InsertChild(nameof(RepeatTolerance), GonObject.Manip.FromInt(RepeatTolerance));
            gon.InsertChild(nameof(AltLevel), GonObject.Manip.FromString(AltLevel));
            gon.InsertChild(nameof(GenerateCustomParticles), GonObject.Manip.FromBool(GenerateCustomParticles));
            gon.InsertChild(nameof(MaxParticles), GonObject.Manip.FromInt(MaxParticles));
            gon.InsertChild(nameof(GameDirectory), GonObject.Manip.FromString(GameDirectory));
            gon.InsertChild(nameof(MaxParticleEffects), GonObject.Manip.FromInt(MaxParticleEffects));
            gon.InsertChild(nameof(ManualLoad), GonObject.Manip.FromBool(ManualLoad));
            gon.InsertChild(nameof(DoCorruptions), GonObject.Manip.FromBool(DoCorruptions));
            gon.InsertChild(nameof(MirrorMode), GonObject.Manip.FromBool(MirrorMode));
            gon.InsertChild(nameof(DeadRacer), GonObject.Manip.FromBool(DeadRacer));
            gon.InsertChild(nameof(CartLives), GonObject.Manip.FromInt(CartLives));
            gon.InsertChild(nameof(DoPhysics), GonObject.Manip.FromBool(DoPhysics));
            gon.InsertChild(nameof(PlatformPhysics), GonObject.Manip.FromBool(PlatformPhysics));
            gon.InsertChild(nameof(PlayerPhysics), GonObject.Manip.FromBool(PlayerPhysics));
            gon.InsertChild(nameof(WaterPhysics), GonObject.Manip.FromBool(WaterPhysics));
            gon.InsertChild(nameof(LowGravPhysics), GonObject.Manip.FromBool(LowGravPhysics));
            gon.InsertChild(nameof(LevelMerge), GonObject.Manip.FromBool(LevelMerge));
            gon.InsertChild(nameof(ToolsInDirectory), GonObject.Manip.FromString(ToolsInDirectory));
            gon.InsertChild(nameof(ToolsOutDirectory), GonObject.Manip.FromString(ToolsOutDirectory));
            gon.InsertChild(nameof(RandomizeAreaType), GonObject.Manip.FromBool(RandomizeAreaType));
            gon.InsertChild(nameof(CRSmart), GonObject.Manip.FromBool(CRSmart));
            gon.InsertChild(nameof(CROverlays), GonObject.Manip.FromBool(CROverlays));
            gon.InsertChild(nameof(CRTumors), GonObject.Manip.FromBool(CRTumors));
            gon.InsertChild(nameof(CRAddTiles), GonObject.Manip.FromInt(CRAddTiles));
            gon.InsertChild(nameof(CRAddEnemies), GonObject.Manip.FromInt(CRAddEnemies));
            gon.InsertChild(nameof(CRSpikeStrips), GonObject.Manip.FromBool(CRSpikeStrips));
            gon.InsertChild(nameof(CRCrumbles), GonObject.Manip.FromBool(CRCrumbles));
            gon.InsertChild(nameof(CRCrushers), GonObject.Manip.FromBool(CRCrushers));
            gon.InsertChild(nameof(CRChaos), GonObject.Manip.FromBool(CRChaos));
            gon.InsertChild(nameof(CRWaterLevels), GonObject.Manip.FromBool(CRWaterLevels));
            gon.InsertChild(nameof(UserName), GonObject.Manip.FromString(UserName));

            gon.Save("data/text/settings.gon");
        }
            public static GonObject PriorityMerge(GonObject low, GonObject high)
            {
                // create new gonObject to return
                GonObject ret = new GonObject();

                // iterate over the low-priority object's children
                for (int i = 0; i < low.Size(); i++)
                {
                    string childName = low[i].Name;
                    var    lowChild  = low[childName];

                    // step into if the same child exists in high priority object
                    if (high[childName] != null)
                    {
                        var highChild = high[childName];

                        // special case for art_alts
                        if (childName == "art_alts")
                        {
                            ret.InsertChild("art_alts", ArtAltsMerge(lowChild, highChild));
                        }

                        // recurse if type is object
                        else if (lowChild.Type == FieldType.OBJECT && highChild.Type == FieldType.OBJECT)
                        {
                            ret.InsertChild(PriorityMerge(lowChild, highChild));
                        }

                        // otherwise just use the high-priority child
                        else
                        {
                            ret.InsertChild(highChild);
                        }
                    }
                    else
                    {
                        ret.InsertChild(lowChild);  // if no high-priority child available, use low-priority child
                    }
                }

                // iterate over high-priority object's children
                // copy those that do not already exist in low-priority object to return object
                for (int i = 0; i < high.Size(); i++)
                {
                    string childName = high[i].Name;

                    if (low[childName] == null)
                    {
                        ret.InsertChild(high[childName]);
                    }
                }
                return(ret);
            }
            public static GonObject FromInt(int val, string name = "")
            {
                GonObject gon = new GonObject();

                gon.Name = name;
                gon.Type = FieldType.NUMBER;

                gon.Int_Data   = val;
                gon.Float_Data = val;

                return(gon);
            }
Beispiel #14
0
        public static void TilesetTest()
        {
            var gon = GonObject.Load("testin.txt");

            var ts1 = gon["1"];
            var ts2 = gon["2"];

            var ts3 = GonObject.Manip.PriorityMerge(ts1, ts2);

            ts1.Save("testout1.txt");
            ts2.Save("testout2.txt");
            ts3.Save("testout3.txt");
        }
            public static GonObject FromStringArray(string[] arr, string name = "")
            {
                GonObject gon = new GonObject();

                gon.Name = name;
                gon.Type = FieldType.ARRAY;

                foreach (string s in arr)
                {
                    gon.InsertChild(FromString(s));
                }

                return(gon);
            }
            public static GonObject FromIntArray(int[] arr, string name = "")
            {
                GonObject gon = new GonObject();

                gon.Name = name;
                gon.Type = FieldType.ARRAY;

                foreach (int i in arr)
                {
                    gon.InsertChild(FromInt(i));
                }

                return(gon);
            }
        static Dictionary <int, int[]> LoadDictionary(GonObject gon)
        {
            var dict = new Dictionary <int, int[]>();

            for (int i = 0; i < gon.Size(); i++)
            {
                var   item = gon[i];
                int   id   = item["id"].Int();
                int[] alts = GonObject.Manip.GonToIntArray(item["alts"]);

                dict.Add(id, alts);
            }
            return(dict);
        }
        static void LoadNPCs()
        {
            var gon = GonObject.Load($"data/text/npcs.gon");    // open npcs file

            NPCMovieClips = GonObject.Manip.GonToStringArray(gon["movieclips"]);
            NPCSoundIDs   = GonObject.Manip.GonToStringArray(gon["movieclips"]);
            NPCTexts      = new List <string[]>();

            var text = gon["text"];

            for (int i = 0; i < text.Size(); i++)
            {
                NPCTexts.Add(GonObject.Manip.GonToStringArray(text[i]));
            }
        }
        public static void SaveShadersList(List <Shader> ShadersList)
        {
            if (ShadersList != null)
            {
                var gon = new GonObject();
                foreach (var shader in ShadersList)
                {
                    var item = new GonObject();
                    item.InsertChild(GonObject.Manip.FromBool(shader.Enabled, "enabled"));
                    item.InsertChild(GonObject.Manip.FromString(shader.Content, "content"));
                    gon.InsertChild(shader.Name, item);
                }

                gon.Save($"data/text/shaders.gon");
            }
        }
 public static string[][] GonTo2DStringArray(GonObject gon)
 {
     try
     {
         string[][] ret = new string[gon.Size()][];
         for (int i = 0; i < gon.Size(); i++)
         {
             ret[i] = GonToStringArray(gon[i]);
         }
         return(ret);
     }
     catch (GonException ge)
     {
         Console.Write(ge);
         throw;
     }
 }
Beispiel #21
0
        static LevelManip()
        {
            // load flips dictionary in constructor
            HFlipIndex = new List <Pair> {
            };
            VFlipIndex = new List <Pair> {
            };
            var  gon = GonObject.Load("data/text/tile_flips.gon");
            Pair pair;

            // load horizontal flips
            var child = gon["horz"];

            for (int i = 0; i < child.Size(); i++)
            {
                // We can safely index both the first and second item directly since we know they will always be present
                pair.First  = child[i][0].Int();
                pair.Second = child[i][1].Int();
                HFlipIndex.Add(pair);
            }

            // load vertical flips
            child = gon["vert"];
            for (int i = 0; i < child.Size(); i++)
            {
                pair.First  = child[i][0].Int();
                pair.Second = child[i][1].Int();
                VFlipIndex.Add(pair);
            }

            // load rotations
            gon           = GonObject.Load("data/text/tile_rotations.gon");
            RotationIndex = new List <Pair> {
            };
            child         = gon["rotate"];
            for (int i = 0; i < child.Size(); i++)
            {
                pair.First  = child[i][0].Int();
                pair.Second = child[i][1].Int();
                RotationIndex.Add(pair);
            }
        }
        // METHODS

        // Resource loading functions
        static void LoadShadersList()
        {
            ShadersList = new List <Shader>()
            {
            };

            var gon = GonObject.Load($"data/text/shaders.gon");    // open levelpool file

            for (int i = 0; i < gon.Size(); i++)
            {
                var shader = new Shader()
                {
                };
                var item = gon[i];

                shader.Name    = item.GetName();
                shader.Enabled = item["enabled"].Bool();
                shader.Content = item["content"].String();

                ShadersList.Add(shader);
            }
        }
Beispiel #23
0
        private static string GetArtAlts(SettingsFile settings)
        {
            string ArtAlts = "";

            try
            {
                var gon = GonObject.Load("data/text/art_alts.gon");
                if (settings.AltLevel == "Safe")
                {
                    for (int i = 0; i < gon["safe"].Size(); i++)
                    {
                        var art = gon["safe"][i];

                        for (int j = 0; j < art.Size(); j++)
                        {
                            var alts = GonObject.Manip.GonToStringArray(art);
                            ArtAlts += "[" + art.GetName() + "," + alts[RNG.random.Next(0, alts.Length)].Trim() + "]";
                        }
                    }
                }
                else if (settings.AltLevel == "Extended")
                {
                    for (int i = 0; i < gon["extended"].Size(); i++)
                    {
                        var art = gon["extended"][i];

                        for (int j = 0; j < art.Size(); j++)
                        {
                            var alts = GonObject.Manip.GonToStringArray(art);
                            ArtAlts += "[" + art.GetName() + "," + alts[RNG.random.Next(0, alts.Length)].Trim() + "]";
                        }
                    }
                }
                else if (settings.AltLevel == "Crazy")
                {
                    for (int i = 0; i < gon["crazy"].Size(); i++)
                    {
                        var art = gon["crazy"][i];

                        for (int j = 0; j < art.Size(); j++)
                        {
                            var alts = GonObject.Manip.GonToStringArray(art);
                            ArtAlts += "[" + art.GetName() + "," + alts[RNG.random.Next(0, alts.Length)].Trim() + "]";
                        }
                    }
                }
                else if (settings.AltLevel == "Insane")
                {
                    var art = gon["insane"];
                    for (int i = 0; i < art.Size(); i++)
                    {
                        var alts = GonObject.Manip.GonToStringArray(gon["insane"]);
                        ArtAlts += "[" + art[i].String() + "," + alts[RNG.random.Next(0, alts.Length)].Trim() + "]";
                    }
                    //ArtAlts += "[ChainLink, None][ChainLink2, None]";
                }
            }
            catch (Exception)
            {
                MessageBox.Show(
                    "Art Alt Error",
                    "Warning",
                    MessageBoxButton.OK,
                    MessageBoxImage.Information,
                    MessageBoxResult.OK
                    );
                throw;
            }
            return(ArtAlts);
        }
        public static string MistParticle(SettingsFile settings)
        {
            string particle_name = "MistParticle" + RNG.GetUInt32().ToString();

            int layer      = 4;
            int base_speed = 3;

            // can be anything
            double alpha_start = 1;
            double alpha_end   = 0;
            string movieclip;
            int    max_particles     = settings.MaxParticles;
            int    emit_spread       = 0;
            string rotation_speed    = "0";
            string initial_rotation  = "0";
            double particle_lifetime = RNG.random.Next(1, 5);
            string size_start;
            int    size_end = RNG.random.Next(50, 101);

            string emit_direction = $"[{RNG.random.Next(-10, 11) / 10},{RNG.random.Next(-10, 11) / 10}]";

            if (emit_direction == "[0,0]")
            {
                emit_direction = "[0,-1]";
            }
            //string emit_box = "";
            //string emit_offset = "";

            string force = "0";
            int    emit_rate;
            int    emit_amount;
            double initial_speed = RNG.random.Next(0, 20);
            double friction      = 1;

            // open particles file
            var    gon      = GonObject.Load($"data/text/particles_templates.gon"); // open particle file
            string template = gon["templates"]["MistParticle"].String();            // load particle template

            // select particle from pool
            var particles = gon["particles"];
            var chosen    = particles[RNG.random.Next(0, particles.Size())];

            // get particle variables from file
            movieclip = chosen["name"].String();
            string face_moving_direction = chosen["face_moving_direction"].String();

            alpha_start = chosen["alpha"].Number();
            double size = chosen["size"].Number() * .03;

            size_start = $"[{size * .75},{size * 1.25}]";
            layer      = chosen["layer"].Int();
            double density     = chosen["density"].Number();
            double speed_scale = chosen["speed_scale"].Number();

            // calculate emitter properties
            int emit_density = (int)(64 * density);

            emit_rate   = RNG.random.Next(1, emit_density);
            emit_amount = emit_density / emit_rate;
            if (RNG.CoinFlip())
            {
                emit_spread = RNG.random.Next(0, 46);
            }
            if (RNG.random.Next(0, 10) == 0)
            {
                emit_spread = 360;
            }

            if (!Convert.ToBoolean(face_moving_direction))
            {
                int temp = RNG.random.Next(0, 251);
                rotation_speed   = $"[{temp},{temp * 1.5}]";
                initial_rotation = "[0, 359]";
            }

            template = template.Replace("PARTICLE_NAME", particle_name);
            template = template.Replace("LAYER", layer.ToString());
            template = template.Replace("MOVIECLIP", movieclip);
            template = template.Replace("MAX_PARTICLES", max_particles.ToString());
            template = template.Replace("EMIT_RATE", emit_rate.ToString());
            template = template.Replace("EMIT_AMOUNT", emit_amount.ToString());
            template = template.Replace("EMIT_DIRECTION", emit_direction);
            template = template.Replace("EMIT_SPREAD", emit_spread.ToString());
            //template = template.Replace("EMIT_BOX", emit_box);
            //template = template.Replace("EMIT_OFFSET", emit_offset);
            template = template.Replace("PARTICLE_LIFETIME", particle_lifetime.ToString());
            template = template.Replace("INITIAL_SPEED", $"[{initial_speed},{initial_speed * 2}]");
            template = template.Replace("INITIAL_ROTATION", initial_rotation.ToString());
            template = template.Replace("ROTATION_SPEED", rotation_speed.ToString());
            template = template.Replace("FORCE", force);
            template = template.Replace("FRICTION", friction.ToString());
            template = template.Replace("ALPHA_START", alpha_start.ToString());
            template = template.Replace("ALPHA_END", alpha_end.ToString());
            template = template.Replace("SIZE_START", size_start);
            template = template.Replace("SIZE_END", size_end.ToString());
            template = template.Replace("FACE_MOVING_DIRECTION", face_moving_direction);
            template = template.Replace("SPEED_SCALE", speed_scale.ToString());

            using (StreamWriter sw = File.AppendText(Randomizer.saveDir + "data/particles.txt.append"))
            {
                sw.WriteLine(template);
            }
            return(particle_name);
        }
        static GonObject LoadFromTokens(GonTokenStream Tokens)
        {
            GonObject ret = new GonObject();

            if (Tokens.Peek() == "{")
            {         //read object
                ret.Type = FieldType.OBJECT;

                Tokens.Consume(); //consume '{'
                while (Tokens.Peek() != "}")
                {
                    string name = Tokens.Read();

                    ret.Children_Array.Add(LoadFromTokens(Tokens));
                    ret.Children_Map[name] = (int)ret.Children_Array.Count() - 1;
                    ret.Children_Array[ret.Children_Array.Count() - 1].Name = name;

                    if (Tokens.error)
                    {
                        throw new GonException("GON ERROR: missing a '}' somewhere");
                    }
                }
                Tokens.Consume(); //consume '}'

                return(ret);
            }
            else if (Tokens.Peek() == "[")
            {  //read array
                ret.Type = FieldType.ARRAY;

                Tokens.Consume(); //consume '['
                while (Tokens.Peek() != "]")
                {
                    ret.Children_Array.Add(LoadFromTokens(Tokens));

                    if (Tokens.error)
                    {
                        throw new GonException("GON ERROR: missing a ']' somewhere");
                        return(null);
                    }
                }
                Tokens.Consume(); //consume ']'

                return(ret);
            }
            else
            {
                //read data value
                ret.Type        = FieldType.STRING;
                ret.String_Data = Tokens.Read();

                //if string data can be converted to a number, do so
                if (ret.String_Data.All(Char.IsDigit))
                {
                    ret.Int_Data = Convert.ToInt32(ret.String_Data);
                    ret.Type     = FieldType.NUMBER;
                }

                /*char* endptr;
                 * ret.int_data = strtol(ret.string_data.c_str(), &endptr, 0);
                 * if (*endptr == 0)
                 * {
                 *  ret.type = FieldType.NUMBER;
                 * }*/

                if (IsStringFloat(ret.String_Data))
                {
                    ret.Float_Data = Convert.ToDouble(ret.String_Data);
                    ret.Type       = FieldType.NUMBER;
                }

                /*ret.float_data = strtod(ret.string_data.c_str(), &endptr);
                 * if (*endptr == 0)
                 * {
                 *  ret.type = FieldType.NUMBER;
                 * }*/

                //if string data can be converted to a bool or null, convert
                if (ret.String_Data == "null")
                {
                    ret.Type = FieldType.NULLGON;
                }
                if (ret.String_Data == "true")
                {
                    ret.Type      = FieldType.BOOL;
                    ret.Bool_Data = true;
                }
                if (ret.String_Data == "false")
                {
                    ret.Type      = FieldType.BOOL;
                    ret.Bool_Data = false;
                }

                return(ret);
            }
        }
        public static string DirectionParticle(SettingsFile settings)
        {
            string particle_name = "DirectionParticle" + RNG.GetUInt32().ToString();

            int    layer      = 4;
            double base_speed = 3;
            double base_force = 1;
            string notes      = "#";

            // can be anything
            double alpha_start = 1;
            double alpha_end   = 1;
            string movieclip;
            int    max_particles     = settings.MaxParticles;
            int    emit_spread       = 0;
            string rotation_speed    = "0";
            string initial_rotation  = "0";
            double particle_lifetime = 80;
            string size_start;

            // establish direction
            string emit_direction = "";
            string emit_box       = "";
            string emit_offset    = "";

            // dependent on eachother
            int    emit_rate;
            int    emit_amount;
            double initial_speed;
            double friction = 1;
            string force;

            // open particles file
            var    gon      = GonObject.Load($"data/text/particles_templates.gon"); // open particle file
            string template = gon["templates"]["DirectionParticle"].String();       // load particle template

            // select particle from pool
            var particles = gon["particles"];
            var chosen    = particles[RNG.random.Next(0, particles.Size())];

            // get particle variables from file
            movieclip = chosen["name"].String();
            string face_moving_direction = chosen["face_moving_direction"].String();

            alpha_start = chosen["alpha"].Number();
            double size = chosen["size"].Number();

            size_start = $"[{size * .75},{size * 1.25}]";
            layer      = chosen["layer"].Int();
            double density     = chosen["density"].Number();
            double speed_scale = chosen["speed_scale"].Number();

            speed_scale += RNG.random.Next(-2, 3) / 10;

            int speed_scalar = 1, force_scalar = 1;
            // set moving direction
            bool force_neg = false;
            int  direction = RNG.random.Next(0, 4);

            switch (direction)
            {
            case 0:     // up
                emit_direction = $"[{RNG.random.Next(-3, 4) / 10},1]";
                emit_box       = "[54,1]";
                emit_offset    = "[27,-3]";
                break;

            case 1:     // down
                emit_direction = $"[{RNG.random.Next(-3, 4) / 10},-1]";
                emit_box       = "[54,1]";
                emit_offset    = "[27,35]";
                force_neg      = true;
                break;

            case 2:     // right
                emit_direction = $"[1,{RNG.random.Next(-3, 4) / 10}]";
                emit_box       = "[1,32]";
                emit_offset    = "[-3,16]";
                base_speed    *= 1.2;
                base_force    *= .8;
                break;

            case 3:     // left
                emit_direction = $"[-1,{RNG.random.Next(-3, 4) / 10}]";
                emit_box       = "[1,32]";
                emit_offset    = "[57,16]";
                base_speed    *= 1.2;
                base_force    *= .8;
                force_neg      = true;
                break;
            }

            //int particle_density = 100;

            int emit_density = (int)(RNG.random.Next(5, 16) * density);

            speed_scalar = RNG.random.Next(1, 5);

            if (RNG.CoinFlip())   // decide whether to accelerate, slow down, or no force
            {
                force_scalar = speed_scalar * speed_scalar;
                if (RNG.CoinFlip() && direction < 2)   // gravity
                {
                    //force_scalar = speed_scalar * speed_scalar;
                    force_neg     = !force_neg;
                    emit_density *= Math.Max(speed_scalar / 2, 1);
                    notes        += "gravity, ";
                }
                else    // accelerate
                {
                    //force_scalar = speed_scalar * speed_scalar;
                    emit_density *= speed_scalar;
                    notes        += "accelerate, ";
                }
            }
            else
            {
                force_scalar  = 0;
                emit_density *= speed_scalar;
            }

            notes += $"force scalar: {force_scalar}, speed scalar: {speed_scalar}, ";

            initial_speed = base_speed * speed_scalar;                                              // set initial speed
            double parallel_force      = base_force * force_scalar * -(Convert.ToInt32(force_neg)); // set force
            double perpendicular_force = base_force * force_scalar * RNG.random.Next(-10, 11) / 10;

            //perpendicular_force = 0;

            if (RNG.random.Next(0, 3) == 0)   // decide if particle fades out
            {
                alpha_end         = 0;
                particle_lifetime = (float)RNG.random.Next(2, 4) * (float)base_speed / (float)speed_scalar;
            }

            if (direction > 1)  // if right or left
            {
                force              = $"[{parallel_force},{perpendicular_force}]";
                particle_lifetime *= 2;
            }
            else
            {
                force = $"[{perpendicular_force},{parallel_force}]";
            }

            emit_rate   = RNG.random.Next(1, emit_density);
            emit_amount = emit_density / emit_rate;
            if (RNG.CoinFlip())
            {
                emit_spread = RNG.random.Next(0, 46);
            }

            if (!Convert.ToBoolean(face_moving_direction))
            {
                int temp = RNG.random.Next(0, 251);
                rotation_speed   = $"[{temp},{temp * 1.5}]";
                initial_rotation = "[0, 359]";
            }

            // write all values to template
            template = template.Replace("PARTICLE_NAME", particle_name);
            template = template.Replace("LAYER", layer.ToString());
            template = template.Replace("MOVIECLIP", movieclip);
            template = template.Replace("MAX_PARTICLES", max_particles.ToString());
            template = template.Replace("EMIT_RATE", emit_rate.ToString());
            template = template.Replace("EMIT_AMOUNT", emit_amount.ToString());
            template = template.Replace("EMIT_DIRECTION", emit_direction);
            template = template.Replace("EMIT_SPREAD", emit_spread.ToString());
            template = template.Replace("EMIT_BOX", emit_box);
            template = template.Replace("EMIT_OFFSET", emit_offset);
            template = template.Replace("PARTICLE_LIFETIME", particle_lifetime.ToString());
            template = template.Replace("INITIAL_SPEED", $"[{initial_speed},{initial_speed * 2}]");
            template = template.Replace("INITIAL_ROTATION", initial_rotation.ToString());
            template = template.Replace("ROTATION_SPEED", rotation_speed.ToString());
            template = template.Replace("FORCE", force);
            template = template.Replace("FRICTION", friction.ToString());
            template = template.Replace("ALPHA_START", alpha_start.ToString());
            template = template.Replace("ALPHA_END", alpha_end.ToString());
            template = template.Replace("SIZE_START", size_start);
            //template = template.Replace("SIZE_END", size_end.ToString());
            template  = template.Replace("FACE_MOVING_DIRECTION", face_moving_direction);
            template  = template.Replace("SPEED_SCALE", speed_scale.ToString());
            template += notes;

            using (StreamWriter sw = File.AppendText(Randomizer.saveDir + "data/particles.txt.append"))
            {
                sw.WriteLine(template);
            }
            return(particle_name);
        }