Esempio n. 1
0
        // Constructor
        internal ActorStructure(DecorateParser parser)
        {
            // Initialize
            flags  = new Dictionary <string, bool>();
            props  = new Dictionary <string, List <string> >();
            states = new Dictionary <string, StateStructure>();

            // Always define a game property, but default to 0 values
            props["game"] = new List <string>();

            inheritclass = "actor";
            replaceclass = null;
            baseclass    = null;
            skipsuper    = false;

            // First next token is the class name
            parser.SkipWhitespace(true);
            classname = parser.StripTokenQuotes(parser.ReadToken());
            if (string.IsNullOrEmpty(classname))
            {
                parser.ReportError("Expected actor class name");
                return;
            }

            // Parse tokens before entering the actor scope
            while (parser.SkipWhitespace(true))
            {
                string token = parser.ReadToken();
                if (!string.IsNullOrEmpty(token))
                {
                    token = token.ToLowerInvariant();
                    if (token == ":")
                    {
                        // The next token must be the class to inherit from
                        parser.SkipWhitespace(true);
                        inheritclass = parser.StripTokenQuotes(parser.ReadToken());
                        if (string.IsNullOrEmpty(inheritclass) || parser.IsSpecialToken(inheritclass))
                        {
                            parser.ReportError("Expected class name to inherit from");
                            return;
                        }
                        else
                        {
                            // Find the actor to inherit from
                            baseclass = parser.GetArchivedActorByName(inheritclass);
                            if (baseclass == null)
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + inheritclass + "' to inherit from, while parsing '" + classname + "'");
                            }
                        }
                    }
                    else if (token == "replaces")
                    {
                        // The next token must be the class to replace
                        parser.SkipWhitespace(true);
                        replaceclass = parser.StripTokenQuotes(parser.ReadToken());
                        if (string.IsNullOrEmpty(replaceclass) || parser.IsSpecialToken(replaceclass))
                        {
                            parser.ReportError("Expected class name to replace");
                            return;
                        }
                    }
                    else if (token == "native")
                    {
                        // Igore this token
                    }
                    else if (token == "{")
                    {
                        // Actor scope begins here,
                        // break out of this parse loop
                        break;
                    }
                    else if (token == "-")
                    {
                        // This could be a negative doomednum (but our parser sees the - as separate token)
                        // So read whatever is after this token and ignore it (negative doomednum indicates no doomednum)
                        parser.ReadToken();
                    }
                    else
                    {
                        // Check if numeric
                        if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out doomednum))
                        {
                            // Not numeric!
                            parser.ReportError("Expected numeric editor thing number or start of actor scope");
                            return;
                        }
                    }
                }
                else
                {
                    parser.ReportError("Unexpected end of structure");
                    return;
                }
            }

            // Now parse the contents of actor structure
            string previoustoken = "";

            while (parser.SkipWhitespace(true))
            {
                string token = parser.ReadToken();
                token = token.ToLowerInvariant();

                if ((token == "+") || (token == "-"))
                {
                    // Next token is a flag (option) to set or remove
                    bool flagvalue = (token == "+");
                    parser.SkipWhitespace(true);
                    string flagname = parser.ReadToken();
                    if (!string.IsNullOrEmpty(flagname))
                    {
                        // Add the flag with its value
                        flagname        = flagname.ToLowerInvariant();
                        flags[flagname] = flagvalue;
                    }
                    else
                    {
                        parser.ReportError("Expected flag name");
                        return;
                    }
                }
                else if ((token == "action") || (token == "native"))
                {
                    // We don't need this, ignore up to the first next ;
                    while (parser.SkipWhitespace(true))
                    {
                        string t = parser.ReadToken();
                        if ((t == ";") || (t == null))
                        {
                            break;
                        }
                    }
                }
                else if (token == "skip_super")
                {
                    skipsuper = true;
                }
                else if (token == "states")
                {
                    // Now parse actor states until we reach the end of the states structure
                    while (parser.SkipWhitespace(true))
                    {
                        string statetoken = parser.ReadToken();
                        if (!string.IsNullOrEmpty(statetoken))
                        {
                            // Start of scope?
                            if (statetoken == "{")
                            {
                                // This is fine
                            }
                            // End of scope?
                            else if (statetoken == "}")
                            {
                                // Done with the states,
                                // break out of this parse loop
                                break;
                            }
                            // State label?
                            else if (statetoken == ":")
                            {
                                if (!string.IsNullOrEmpty(previoustoken))
                                {
                                    // Parse actor state
                                    StateStructure st = new StateStructure(this, parser, previoustoken);
                                    if (parser.HasError)
                                    {
                                        return;
                                    }
                                    states[previoustoken.ToLowerInvariant()] = st;
                                }
                                else
                                {
                                    parser.ReportError("Unexpected end of structure");
                                    return;
                                }
                            }
                            else
                            {
                                // Keep token
                                previoustoken = statetoken;
                            }
                        }
                        else
                        {
                            parser.ReportError("Unexpected end of structure");
                            return;
                        }
                    }
                }
                else if (token == "}")
                {
                    // Actor scope ends here,
                    // break out of this parse loop
                    break;
                }
                // Monster property?
                else if (token == "monster")
                {
                    // This sets certain flags we are interested in
                    flags["shootable"]      = true;
                    flags["countkill"]      = true;
                    flags["solid"]          = true;
                    flags["canpushwalls"]   = true;
                    flags["canusewalls"]    = true;
                    flags["activatemcross"] = true;
                    flags["canpass"]        = true;
                    flags["ismonster"]      = true;
                }
                // Projectile property?
                else if (token == "projectile")
                {
                    // This sets certain flags we are interested in
                    flags["noblockmap"]     = true;
                    flags["nogravity"]      = true;
                    flags["dropoff"]        = true;
                    flags["missile"]        = true;
                    flags["activateimpact"] = true;
                    flags["activatepcross"] = true;
                    flags["noteleport"]     = true;
                }
                // Clearflags property?
                else if (token == "clearflags")
                {
                    // Clear all flags
                    flags.Clear();
                }
                // Game property?
                else if (token == "game")
                {
                    // Include all tokens on the same line
                    List <string> games = new List <string>();
                    while (parser.SkipWhitespace(false))
                    {
                        string v = parser.ReadToken();
                        if (v == null)
                        {
                            parser.ReportError("Unexpected end of structure");
                            return;
                        }
                        if (v == "\n")
                        {
                            break;
                        }
                        if (v != ",")
                        {
                            games.Add(v.ToLowerInvariant());
                        }
                    }
                    props[token] = games;
                }
                // Property
                else
                {
                    // Property begins with $? Then the whole line is a single value
                    if (token.StartsWith("$"))
                    {
                        // This is for editor-only properties such as $sprite and $category
                        List <string> values = new List <string>();
                        if (parser.SkipWhitespace(false))
                        {
                            values.Add(parser.ReadLine());
                        }
                        else
                        {
                            values.Add("");
                        }
                        props[token] = values;
                    }
                    else
                    {
                        // Next tokens up until the next newline are values
                        List <string> values = new List <string>();
                        while (parser.SkipWhitespace(false))
                        {
                            string v = parser.ReadToken();
                            if (v == null)
                            {
                                parser.ReportError("Unexpected end of structure");
                                return;
                            }
                            if (v == "\n")
                            {
                                break;
                            }
                            if (v != ",")
                            {
                                values.Add(v);
                            }
                        }
                        props[token] = values;
                    }
                }

                // Keep token
                previoustoken = token;
            }
        }