Beispiel #1
0
        /// <summary>
        /// Handles a decorate entry, or throws if it cannot parse it.
        /// </summary>
        /// <param name="entry">The decorate base entry. This should have the
        /// name 'decorate' (case insensitive).</param>
        /// <param name="archive">The archive to look up definitions from.
        /// </param>
        /// <exception cref="Exception">If parsing fails.</exception>
        public static void HandleDefinitionsOrThrow(IEntry entry, IArchive archive)
        {
            DecorateParser parser = new DecorateParser(archive);

            bool success = parser.Parse(entry);

            if (!success)
            {
                throw new Exception("Unable to parse decorate entries");
            }

            AddDefinitions(parser.Definitions);
        }
Beispiel #2
0
        // Constructor
        internal StateGoto(ActorStructure actor, DecorateParser parser)
        {
            string firsttarget    = "";
            string secondtarget   = "";
            bool   commentreached = false;
            bool   offsetreached  = false;
            string offsetstr      = "";
            int    cindex         = 0;

            // This is a bitch to parse because for some bizarre reason someone thought it
            // was funny to allow quotes here. Read the whole line and start parsing this manually.
            string line = parser.ReadLine();

            // Skip whitespace
            while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t')))
            {
                cindex++;
            }

            // Parse first target
            while ((cindex < line.Length) && (line[cindex] != ':'))
            {
                // When a comment is reached, we're done here
                if (line[cindex] == '/')
                {
                    if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*')))
                    {
                        commentreached = true;
                        break;
                    }
                }

                // Whitespace ends the string
                if ((line[cindex] == ' ') || (line[cindex] == '\t'))
                {
                    break;
                }

                // + sign indicates offset start
                if (line[cindex] == '+')
                {
                    cindex++;
                    offsetreached = true;
                    break;
                }

                // Ignore quotes
                if (line[cindex] != '"')
                {
                    firsttarget += line[cindex];
                }

                cindex++;
            }

            if (!commentreached && !offsetreached)
            {
                // Skip whitespace
                while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t')))
                {
                    cindex++;
                }

                // Parse second target
                while (cindex < line.Length)
                {
                    // When a comment is reached, we're done here
                    if (line[cindex] == '/')
                    {
                        if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*')))
                        {
                            commentreached = true;
                            break;
                        }
                    }

                    // Whitespace ends the string
                    if ((line[cindex] == ' ') || (line[cindex] == '\t'))
                    {
                        break;
                    }

                    // + sign indicates offset start
                    if (line[cindex] == '+')
                    {
                        cindex++;
                        offsetreached = true;
                        break;
                    }

                    // Ignore quotes and semicolons
                    if ((line[cindex] != '"') && (line[cindex] != ':'))
                    {
                        secondtarget += line[cindex];
                    }

                    cindex++;
                }
            }

            // Try to find the offset if we still haven't found it yet
            if (!offsetreached)
            {
                // Skip whitespace
                while ((cindex < line.Length) && ((line[cindex] == ' ') || (line[cindex] == '\t')))
                {
                    cindex++;
                }

                if ((cindex < line.Length) && (line[cindex] == '+'))
                {
                    cindex++;
                    offsetreached = true;
                }
            }

            if (offsetreached)
            {
                // Parse offset
                while (cindex < line.Length)
                {
                    // When a comment is reached, we're done here
                    if (line[cindex] == '/')
                    {
                        if ((cindex + 1 < line.Length) && ((line[cindex + 1] == '/') || (line[cindex + 1] == '*')))
                        {
                            commentreached = true;
                            break;
                        }
                    }

                    // Whitespace ends the string
                    if ((line[cindex] == ' ') || (line[cindex] == '\t'))
                    {
                        break;
                    }

                    // Ignore quotes and semicolons
                    if ((line[cindex] != '"') && (line[cindex] != ':'))
                    {
                        offsetstr += line[cindex];
                    }

                    cindex++;
                }
            }

            // We should now have a first target, optionally a second target and optionally a sprite offset

            // Check if we don't have the class specified
            if (string.IsNullOrEmpty(secondtarget))
            {
                // First target is the state to go to
                classname = actor.ClassName;
                statename = firsttarget.ToLowerInvariant().Trim();
            }
            else
            {
                // First target is the base class to use
                // Second target is the state to go to
                classname = firsttarget.ToLowerInvariant().Trim();
                statename = secondtarget.ToLowerInvariant().Trim();
            }

            if (offsetstr.Length > 0)
            {
                int.TryParse(offsetstr, out spriteoffset);
            }

            if ((classname == "super") && (actor.BaseClass != null))
            {
                classname = actor.BaseClass.ClassName;
            }
        }
        public static int Main(string[] args)
        {
            DateTime startTime = DateTime.Now;

            try
            {
                // parse command line options
                List <string> decoratePaths     = new List <string>();
                List <string> acsFiles          = new List <string>();
                string        otputDecorateFile = "decorate.txt";
                string        otputAcsFile      = "acs.txt";
                string        libraryName       = "DEFAULTLIB";
                string        mode    = "zdoom";
                OptionSet     options = new OptionSet()
                {
                    {
                        "a|acs=", "ACS source files.", p => acsFiles.Add(p)
                    },
                    {
                        "d|decorate=", "Directory with user DECORATE files.", p => decoratePaths.Add(p)
                    },
                    {
                        "o|acsOut=", "Output ACS file. acs.txt is default.", p => otputAcsFile = p
                    },
                    {
                        "p|decorateOut=", "Output DECORATE file. decorate.txt is default.", p => otputDecorateFile = p
                    },
                    {
                        "m|mode=", "Mode (ZDoom or Skulltag), ZDoom is default.", p => mode = p
                    },
                    {
                        "l|library=", "Name of the ACS library.", p => libraryName = p
                    }
                };

                options.Parse(args);

                if (decoratePaths.Count == 0)
                {
                    throw new ArgumentException("No input decorate path specified.");
                }

                if (acsFiles.Count == 0)
                {
                    throw new ArgumentException("No input ACS file specified.");
                }

                DecorateParser parser = new DecorateParser();

                // add native decorate files
                string applicationDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "/";
                if (mode.Equals("ZDoom", StringComparison.OrdinalIgnoreCase))
                {
                    parser.AddFiles(new DirectoryInfo(applicationDirectory + "decorate/zdoom").GetFilesRecursive(), DecorateFileType.Native);
                }
                else
                {
                    parser.AddFiles(new DirectoryInfo(applicationDirectory + "decorate/skulltag").GetFilesRecursive(), DecorateFileType.Native);
                }

                // add user decorate files
                var files =
                    from path in decoratePaths
                    from file in new DirectoryInfo(path).GetFilesRecursive()
                    select file;

                parser.AddFiles(files, DecorateFileType.User);

                Console.WriteLine("Parsing DECORATE files...");

                // parse the files
                var actors = parser.GetActors();

                // print some stats
                var localActors = from actor in actors where !actor.IsFromNativeFile select actor;
                Console.WriteLine("Found " + actors.Count() + " actors (" + localActors.Count() + " user + " + (actors.Count() - localActors.Count()) + " native)");

                // add the classId actor to each monster
                Actor classIdActor = new Actor()
                {
                    Name   = "__classId",
                    Parent = actors.OfName("inventory").First()
                };

                actors = actors.Append(classIdActor);

                var monsters =
                    from actor in actors
                    where actor.HasFlagEnabled("ISMONSTER")
                    select actor;

                foreach (var monster in monsters)
                {
                    monster.StateMachine.InsertStatesBeforeState(
                        new List <State>
                    {
                        new FrameState()
                        {
                        },
                        new FrameState()
                        {
                            CodePointer = "A_TakeInventory(\"__classId\", 9999)"
                        },
                        new FrameState()
                        {
                            CodePointer = "A_GiveInventory(\"__classId\", " + monster.ID + ")"
                        }
                    },
                        monster.StateMachine.Labels["spawn"]);
                }

                // generate ACS
                Console.WriteLine("Generating output ACS...");

                using (var textWriter = new StreamWriter(otputAcsFile))
                {
                    var writer = new AcsWriter(textWriter, libraryName);
                    writer.WriteCheckActorClass2(actors);
                    writer.WriteGetWeapon(actors);
                    writer.WriteGetCustomProperty(actors);
                    writer.WriteGetWeaponCustomProperty(actors);
                    writer.WriteOriginalContent(File.ReadAllText(acsFiles[0]));
                }

                // generate DECORATE
                Console.WriteLine("Generating output DECORATE...");

                using (var textWriter = new StreamWriter(otputDecorateFile))
                {
                    var writer = new DecorateWriter(textWriter);
                    writer.WriteActors(actors);
                }

                // print time stat
                TimeSpan timeDelta = DateTime.Now - startTime;
                Console.WriteLine("Done after " + Math.Round((double)timeDelta.TotalMilliseconds / 1000d, 2) + " seconds!");

                return(0);
            }
            catch (IOException e)
            {
                Console.WriteLine(e.GetType().Name + ": " + e.Message);
                Console.WriteLine(string.Empty);
                Console.WriteLine("Stack trace:");
                Console.WriteLine(e.StackTrace);

                return(-1);
            }
        }