using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace LD31 { public static partial class Main { private enum ScriptLoadMode { None, Object, Tile, Creature, Properties, UseScript, CombinationScript, UpdateScript, NamedScript, Spawn } private static void LoadScripts() { //=======================TILES AND OBJECTS=========================== for (int i = 0; i < 2; i++) { FileInfo[] files = null; //TILES if (i == 0) { Tile.baseTiles = new Dictionary(); DirectoryInfo di = new DirectoryInfo("Data/scripts/tiles/"); files = di.GetFiles(); } //OBJECTS else if (i == 1) { Object.baseObjects = new Dictionary(); DirectoryInfo di = new DirectoryInfo("Data/scripts/objects/"); files = di.GetFiles(); } foreach (FileInfo file in files) { if (file.Name.EndsWith(".dat")) { StreamReader sr = new StreamReader(file.FullName); TileOrObject torO = null; //TILES if (i == 0) { torO = new Tile(); } //OBJECTS if (i == 1) { torO = new Object(); } Script currentScript = null; ScriptLoadMode loadMode = ScriptLoadMode.None; while (!sr.EndOfStream) { string line = sr.ReadLine(); string firstWord = FW(line); //Empty line/comment check if (firstWord != "" && (!firstWord.StartsWith("//"))) { switch (loadMode) { //------------------------------- case ScriptLoadMode.None: switch (firstWord) { case "[tile]": loadMode = ScriptLoadMode.Tile; break; case "[object]": loadMode = ScriptLoadMode.Object; break; case "[properties]": loadMode = ScriptLoadMode.Properties; break; case "[use]": loadMode = ScriptLoadMode.UseScript; currentScript = new Script(); break; case "[combination]": loadMode = ScriptLoadMode.CombinationScript; currentScript = new Script(); break; case "[update]": loadMode = ScriptLoadMode.UpdateScript; currentScript = new Script(); break; case "[namedscript]": loadMode = ScriptLoadMode.NamedScript; currentScript = new Script(); break; } break; //------------------------------- case ScriptLoadMode.Tile: case ScriptLoadMode.Object: switch (firstWord) { case "[/tile]": case "[/object]": loadMode = ScriptLoadMode.None; break; case "name": torO.name = RBQ(line); break; case "sprite": torO.possibleSprites = RBQM(line, sr); break; } break; //------------------------------- case ScriptLoadMode.Properties: switch (firstWord) { case "[/properties]": loadMode = ScriptLoadMode.None; break; default: torO.AddProperty(firstWord); break; } break; //------------------------------ case ScriptLoadMode.UpdateScript: case ScriptLoadMode.CombinationScript: case ScriptLoadMode.UseScript: case ScriptLoadMode.NamedScript: switch (FW(line)) { case "name": currentScript.name = RBQ(line); break; case "target": currentScript.target = RBQ(line); break; case "[/combination]": torO.combinationScripts.Add(currentScript.target, currentScript); currentScript = null; loadMode = ScriptLoadMode.None; break; case "[/namedscript]": torO.namedScripts.Add(currentScript.name, currentScript); currentScript = null; loadMode = ScriptLoadMode.None; break; case "[/update]": torO.updateScript = currentScript; currentScript = null; loadMode = ScriptLoadMode.None; break; case "[/use]": torO.useScript = currentScript; currentScript = null; loadMode = ScriptLoadMode.None; break; default: currentScript.commandLines.Add(line); break; } break; } } } sr.Close(); //TILES if (i == 0) { //Add tile to tiles list Tile.baseTiles.Add(torO.name, (Tile)torO); } //OBJECTS else if (i == 1) { //Add object to object list Object.baseObjects.Add(torO.name, (Object)torO); } } } } //==================CREATURES================== //New scope to not share variables { FileInfo[] files = null; Creature.baseCreatures = new Dictionary(); DirectoryInfo di = new DirectoryInfo("Data/scripts/creatures/"); files = di.GetFiles(); foreach (FileInfo file in files) { if (file.Name.EndsWith(".dat")) { StreamReader sr = new StreamReader(file.FullName); Script currentScript = null; ScriptLoadMode loadMode = ScriptLoadMode.None; Creature currentCreature = new Creature(); while (!sr.EndOfStream) { string line = sr.ReadLine(); string firstWord = FW(line); //Empty line/comment check if (firstWord != "" && (!firstWord.StartsWith("//"))) { switch (loadMode) { //------------------------------- case ScriptLoadMode.None: switch (firstWord) { case "[combination]": loadMode = ScriptLoadMode.CombinationScript; currentScript = new Script(); break; case "[creature]": loadMode = ScriptLoadMode.Creature; break; case "[namedscript]": loadMode = ScriptLoadMode.NamedScript; currentScript = new Script(); break; case "[properties]": loadMode = ScriptLoadMode.Properties; break; case "[update]": currentScript = new Script(); loadMode = ScriptLoadMode.UpdateScript; break; } break; //------------------------------- case ScriptLoadMode.Creature: switch (firstWord) { case "name": currentCreature.name = RBQ(line); break; case "sprites": currentCreature.spriteNames = RBQM(line, sr); break; case "[/creature]": loadMode = ScriptLoadMode.None; break; } break; //------------------------------- case ScriptLoadMode.Properties: switch (firstWord) { case "[/properties]": loadMode = ScriptLoadMode.None; break; default: currentCreature.AddProperty(firstWord); break; } break; //------------------------------ case ScriptLoadMode.CombinationScript: case ScriptLoadMode.NamedScript: case ScriptLoadMode.UpdateScript: switch (FW(line)) { case "name": currentScript.name = RBQ(line); break; case "target": currentScript.target = RBQ(line); break; case "[/combination]": currentCreature.combinationScripts.Add(currentScript.target, currentScript); currentScript = null; loadMode = ScriptLoadMode.None; break; case "[/namedscript]": currentCreature.namedScripts.Add(currentScript.name, currentScript); currentScript = null; loadMode = ScriptLoadMode.None; break; case "[/update]": currentCreature.updateScript = currentScript; currentScript = null; loadMode = ScriptLoadMode.None; break; default: currentScript.commandLines.Add(line); break; } break; } } } sr.Close(); Creature.baseCreatures.Add(currentCreature.name, currentCreature); } } } } //===================WORLD GENERATION=========== private struct Spawn { public string spawnCreature; public string spawnObject; public string spawnTile; public int min; public int max; public List acceptedTiles; public int spreadtilesMin; public int spreadtilesMax; } private static void GenerateWorld() { string baseTile = "void"; Spawn currentSpawn = new Spawn(); List spawns = new List(); ScriptLoadMode loadMode = ScriptLoadMode.None; string outlineTile = "Void"; List outlineExceptions = new List(); StreamReader sr = new StreamReader("Data/scripts/system/worldgeneration.dat"); while (!sr.EndOfStream) { string line = sr.ReadLine(); switch (loadMode) { case ScriptLoadMode.None: switch (FW(line)) { case "[spawn]": currentSpawn = new Spawn(); currentSpawn.acceptedTiles = new List(); currentSpawn.spreadtilesMin = 0; currentSpawn.spreadtilesMax = 0; currentSpawn.spawnCreature = ""; currentSpawn.spawnObject = ""; currentSpawn.spawnTile = ""; loadMode = ScriptLoadMode.Spawn; break; case "basetile": string[] possibilities = RBQM(line, sr); baseTile = possibilities[random.Next(possibilities.Length)]; //Base tile everywhere for (int iy = 0; iy < WORLD_SIZE_Y; iy++) { for (int ix = 0; ix < WORLD_SIZE_X; ix++) { Main.CreateTile(ix, iy, baseTile); } } break; case "outline": { string tileToOutline = RBQ(line); if (!outlineExceptions.Contains(tileToOutline)) { outlineExceptions.Add(tileToOutline); } for (int iy = 0; iy < WORLD_SIZE_Y; iy++) { for (int ix = 0; ix < WORLD_SIZE_X; ix++) { bool goOutline = false; //Super tedious check to see if tile is part of outline if (!outlineExceptions.Contains(tiles[ix, iy].name)) { for (int jy = -1; jy < 2; jy++) { for (int jx = -1; jx < 2; jx++) { //Check only horizontally and vertically bool canCheck = false; if (jy == 0) { if (jx != 0) { canCheck = true; } } else if (jx == 0) canCheck = true; if (canCheck) { int tx = ix + jx; int ty = iy + jy; if (tx >= 0 && tx < WORLD_SIZE_X && ty >= 0 && ty < WORLD_SIZE_Y) { //Everything's okay, we can check the tile for reals now if (tiles[tx, ty].name == tileToOutline) goOutline = true; } } } } } //And we're back. Great code up there. if (goOutline) { Main.CreateTile(ix, iy, outlineTile); } } } } break; case "setoutlineexception": outlineExceptions.Add(RBQ(line)); break; case "setoutlinetile": outlineTile = RBQ(line); break; } break; case ScriptLoadMode.Spawn: switch (FW(line)) { case "accept": currentSpawn.acceptedTiles.Add(RBQ(line)); break; case "min": currentSpawn.min = Convert.ToInt32(RBQ(line)); break; case "max": currentSpawn.max = Convert.ToInt32(RBQ(line)); break; case "spawncreature": { string[] possibilities = RBQM(line, sr); currentSpawn.spawnCreature = possibilities[random.Next(possibilities.Length)]; } break; case "spawnobject": { string[] possibilities = RBQM(line, sr); currentSpawn.spawnObject = possibilities[random.Next(possibilities.Length)]; } break; case "spawntile": { string[] possibilities = RBQM(line, sr); currentSpawn.spawnTile = possibilities[random.Next(possibilities.Length)]; } break; case "spreadtilesmin": currentSpawn.spreadtilesMin = Convert.ToInt32(RBQ(line)); break; case "spreadtilesmax": currentSpawn.spreadtilesMax = Convert.ToInt32(RBQ(line)); break; case "[/spawn]": //=========================SPAWN================== int num_spawns = currentSpawn.min + random.Next((currentSpawn.max - currentSpawn.min) + 1); for (int ii = 0; ii < num_spawns; ii++) { bool success = false; while (!success) { int targetX = random.Next(WORLD_SIZE_X); int targetY = random.Next(WORLD_SIZE_Y); //------OBJECT---------- if (currentSpawn.spawnObject != "") { //No object yet if (objects[targetX, targetY] == null) { //Check for fitting tiletype if (currentSpawn.acceptedTiles.Contains(tiles[targetX, targetY].name)) { success = true; } } if (success) { Object theObject = new Object(currentSpawn.spawnObject); SetSpritePosition(theObject.sprite, targetX, targetY); objects[targetX, targetY] = theObject; } } //------TILE---------- else if (currentSpawn.spawnTile != "") { if (tiles[targetX, targetY].name != currentSpawn.spawnTile) { success = true; } if (success) { Main.CreateTile(targetX, targetY, currentSpawn.spawnTile); //------Spreading----------- if (currentSpawn.spreadtilesMax > 0) { int num_spread = random.Next((currentSpawn.spreadtilesMax - currentSpawn.spreadtilesMin) + 1) + currentSpawn.spreadtilesMin; for (int spreading = 0; spreading < num_spread; spreading++) { int currentX = targetX; int currentY = targetY; success = false; while (!success) { currentX += random.Next(3) - 1; //-1 to +1 currentY += random.Next(3) - 1; //-1 to +1 if (currentX < 0 || currentX >= WORLD_SIZE_X || currentY < 0 || currentY >= WORLD_SIZE_Y) { currentX = targetX; currentY = targetY; } else { if (tiles[currentX, currentY].name != currentSpawn.spawnTile) { Main.CreateTile(currentX, currentY, currentSpawn.spawnTile); success = true; } } } } } //------------------------ } } //------CREATURE---------- else if (currentSpawn.spawnCreature != "") { //Check for fitting tiletype if (currentSpawn.acceptedTiles.Contains(tiles[targetX, targetY].name)) { if (!CheckAllSolid(targetX, targetY, null)) { success = true; } } if (success) { SpawnCreature(currentSpawn.spawnCreature, targetX, targetY); } } } } //========================================== loadMode = ScriptLoadMode.None; break; } break; } } } //===================HELPER FUNCTIONS============ //Comma split private static string[] CS(string inputline) { return inputline.Split(new string[] { "," }, StringSplitOptions.None); } //Get first word private static string FW(string inputline) { //Remove leading spaces while (inputline.StartsWith(" ")) inputline = inputline.Substring(1); //Split into space-separated words string[] words = inputline.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); //Check if there's any text if (words.Length == 0) return ""; //Return first word return words[0]; } //Read between quotes private static string RBQ(string inputline) { if (inputline.Contains("\"")) { int firstIndex = inputline.IndexOf("\""); int lastIndex = inputline.LastIndexOf("\""); if (firstIndex != lastIndex) { return inputline.Substring(firstIndex + 1, lastIndex - firstIndex - 1); } } return ""; } //Read between quotes - Multiple private static string[] RBQM(string inputline, StreamReader sr) { string[] toReturn = new string[] { RBQ(inputline) }; if (toReturn[0] == "{") { List possibilities = new List(); bool ended = false; while (!ended) { string newLine = RBQ(sr.ReadLine()); if (newLine == "}") { ended = true; } else { possibilities.Add(newLine); } } //Return all possible choices return (possibilities.ToArray()); } return toReturn; } //Read between quotes - Multiple (list version) private static string[] RBQM(string inputline, List fullText, int location) { string[] toReturn = new string[] { RBQ(inputline) }; if (toReturn[0] == "{") { List possibilities = new List(); bool ended = false; while (!ended) { location++; string newLine = RBQ(fullText[location]); if (newLine == "}") { ended = true; } else { possibilities.Add(newLine); } } //Return all possible choices return (possibilities.ToArray()); } return toReturn; } } }