using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SnakeRPG { public class Command { public string command = ""; public string[] parameters = null; } public static partial class Main { public static bool HandleScript(string[] script, Entity source = null, Entity trigger = null) { bool toReturn = false; bool lastConditionMet = false; if (script != null) { for (int i = 0; i < script.Length; i++) { string line = ApplyMacros(script[i], source, trigger); Command command = ReadCommand(line); switch (command.command) { case "attack": Attack(snake, source); break; case "block": toReturn = true; break; case "changeimage": source.sprite.currentImage = Convert.ToInt32(command.parameters[0]); break; case "die": source.Die(); break; case "else": if (lastConditionMet) { i += 2; //Own line + { int depth = 1; while (depth > 0) { Command checkForClose = ReadCommand(script[i]); if (checkForClose.command == "{") depth++; if (checkForClose.command == "}") depth--; if (depth > 0) i++; } } break; case "freeze": movementFreeze = (float)Convert.ToInt32(command.parameters[0]) / 1000f; break; case "fullheal": snake.health = snake.maxHealth; break; case "gaingold": snake.gold += Convert.ToInt32(command.parameters[0]); break; case "if": bool conditionMet = EvaluateStatement(command.parameters[0], source, trigger); lastConditionMet = conditionMet; if (!conditionMet) { i += 2; //Own line + { int depth = 1; while (depth > 0) { Command checkForClose = ReadCommand(script[i]); if (checkForClose.command == "{") depth++; if (checkForClose.command == "}") depth--; if (depth > 0) i++; } } break; case "hit": if (command.parameters[0] == "player") { Main.Attack(source, snake); } break; case "hitself": Main.Attack(snake, snake); break; case "instantdeath": Main.PlayerDies(); break; case "message": Main.Message(command.parameters[0]); break; case "percentualdamage": float percentage = Convert.ToSingle(command.parameters[0]); snake.ReceiveDamage(Convert.ToInt32(Math.Ceiling((float)snake.maxHealth * (percentage / 100f)))); break; case "randommove": int relX = Entity.random.Next(-1, 2); int relY = Entity.random.Next(-1, 2); int targetX = source.x + relX; int targetY = source.y + relY; if (targetX > 0 && targetX < MAP_WIDTH - 1 && targetY > 0 && targetY < MAP_HEIGHT - 1) { if (GetEntityAtLocation(targetX, targetY) == null) { source.SetPosition(targetX, targetY); } } break; case "setspawnpoint": LogVerbose("Spawn point set!"); spawnMap = map.filename; spawnX = source.x; spawnY = source.y; spawnDirection = trigger.direction; break; case "sound": Audio.Play(command.parameters[0]); break; case "upgradehealth": if (upgradePoints < 1) { Message("You need upgrade points to upgrade."); } else { Audio.Play("powerup"); upgradePoints--; snake.maxHealth += 25; snake.health += 25; Message("Health upgraded!"); } break; case "upgradespeed": if (upgradePoints < 1) { Message("You need upgrade points to upgrade."); } else { Audio.Play("powerup"); upgradePoints--; snake.speed += 1.0f; Message("Speed upgraded!"); } break; case "upgradestrength": if (upgradePoints < 1) { Message("You need upgrade points to upgrade."); } else { Audio.Play("powerup"); upgradePoints--; snake.strength += 7; Message("Strength upgraded!"); } break; } } } return toReturn; } static Command ReadCommand(string source) { Command toReturn = new Command(); //Remove comments if (source.Length > 1) { for (int i = 0; i < source.Length - 2; i++) { string twoChars = source.Substring(i, 2); if (twoChars == "//") { source = source.Substring(0, i); i = source.Length - 2; //End for loop } } } //Remove leading spaces bool leadingSpacesPresent = true; while (leadingSpacesPresent) { leadingSpacesPresent = false; if (source.StartsWith(" ") || source.StartsWith(" ")) { leadingSpacesPresent = true; source = source.Substring(1); } } //Remove trailing spaces bool trailingSpacesPresent = true; while (trailingSpacesPresent) { trailingSpacesPresent = false; if (source.EndsWith(" ") || source.EndsWith(" ")) { trailingSpacesPresent = true; source = source.Substring(0, source.Length - 1); } } if (!source.Contains("(")) { toReturn.command = source; } else { toReturn.command = source.Substring(0, source.IndexOf("(")); StringBuilder stringBuilder = new StringBuilder(); List parameters = new List(); int stringIndex = source.IndexOf("(") + 1; bool reading = true; bool readingString = false; int depth = 1; while (reading) { bool keepReading = true; string character = source.Substring(stringIndex, 1); if (depth == 1) { if ((character == ")" || character == ",") && !readingString) //Parse parameter { keepReading = false; string toAdd = stringBuilder.ToString(); toAdd = toAdd.Replace("\"", ""); //Strip quotation marks parameters.Add(toAdd); stringBuilder.Clear(); if (character == ")") //Stop parsing { reading = false; } } } if (keepReading) { if (character == "(" && !readingString) depth++; if (character == ")" && !readingString) depth--; stringBuilder.Append(character); if (character == "\"") readingString = !readingString; } stringIndex++; } toReturn.parameters = parameters.ToArray(); } return toReturn; } public static bool EvaluateStatement(string statement, Entity source = null, Entity trigger = null) { string baseStatement = statement; string parameter = ""; if (statement.Contains("(")) { baseStatement = statement.Substring(0, statement.IndexOf("(")); int startPos = statement.IndexOf("(") + 1; parameter = statement.Substring(startPos, statement.LastIndexOf(")") - startPos); } switch (baseStatement) //Best if implementation ever { case "notwallhack": return !wallhack; case "paymoney": int amount = Convert.ToInt32(parameter); if (snake.gold < amount) return false; else { snake.gold -= amount; return true; } case "playerpresent": int distance = Math.Abs(source.x - snake.x) + Math.Abs(source.y - snake.y); for (int i = 0; i < snake.tail.Count; i++) { int newDistance = Math.Abs(source.x - snake.tail[i].x) + Math.Abs(source.y - snake.tail[i].y); if (newDistance < distance) distance = newDistance; } if (distance < 2) return true; break; } return false; } public static string ApplyMacros(string line, Entity source = null, Entity trigger = null) { line = line.Replace("$PARAMETER_STRING$", source.parameterString); line = line.Replace("$PARAMETER_INT$", Convert.ToString(source.parameterInt)); return line; } } }