1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Participate in Blizzard's Public Test Realm to give them feedback on the upcoming patches. Info is here.
    Dismiss Notice
  3. Take part in forum poll and decide the winner of Icon Contest #16!
    Dismiss Notice
  4. Congratulate the winners of the first ATC contest!
    Dismiss Notice
  5. Zwiebelchen is hosting a special UI texturing contest. Whomever wins will get a $150 reward through paypal! Come along and draw your texturing tools for the Fantastic Adventurer UI contest.
    Dismiss Notice
  6. Sneak, pickpocket and assassinate! Create a stealth map in Mini-Mapping Contest #14!
    Dismiss Notice
  7. Music Contest #8 - Hive Soundtrack is up! Create the soundtrack for the upcoming videos of Hive Workshop's YouTube Channel.
    Dismiss Notice

Warcraft 3 Trigger Format Specification (WTG!)

Discussion in 'Programming' started by Ralle, Jun 11, 2017.

  1. Ralle

    Ralle

    Owner

    Joined:
    Oct 6, 2004
    Messages:
    10,800
    Resources:
    8
    Tools:
    3
    Maps:
    5
    Resources:
    8
    Warcraft 3 Trigger Format Specification (WTG!)

    The past few weeks I have been working on a tool to display the triggers of any map on the site. As some of you know, we had a similar system on the old site. The most difficult task in the creation of this tool is the parsing of the file "war3map.wtg" inside any (unprotected) Warcraft 3 map. It's problematic because it is a binary file format undocumented by Blizzard. There exist unofficial specifications but most of them are incomplete and incorrect.
    Many years ago when I built the parsing used on the site it was not perfect either but better than the existing documentation. Today I am happy to say that I have written a parser that successfully parses a little over 16,000 maps uploaded to the site. The only cases where it fails to parse are cases where World Editor fails similarly.

    Today I am sharing my improvements to the existing specifications in the hopes of furthering the third party tools for WC3. There are still some values which are not explained but everything needed to parse the whole structure succesfully every time is there.

    The incomplete documentation used to get started is this frequently reposted W3M/W3X specification:

    TriggerData.txt

    To begin parsing this format you will need the latest version of TriggerData.txt (UI\TriggerData.txt) which can be extracted from the MPQs. We need this file because we must setup a mapping between functions and their number of arguments. It is assumed that we have this mapping prior to parsing WTG files.

    This is a standard INI file (I expect that you can parse those, if not, Google it), we are interested in the following groups:
    Code (Text):
    [TriggerActions]
    ...
    [TriggerEvents]
    ...
    [TriggerConditions]
    ...
    [TriggerCalls]
    ...
    Iterate over each key-value item (where the key does not start with '_') in these groups and count the number of arguments but filter out empty strings, numbers and the string 'nothing'.

    For the group called 'TriggerCalls' one of the types is a return value, so the resulting count must be deducted by one.

    Here is sample code for the setup of my mapping:
    Code (PHP):
    $areas = [
        'TriggerActions',
        'TriggerEvents',
        'TriggerConditions',
        'TriggerCalls',
    ];
    $lookup = [];
    foreach ($areas as $area)
    {
        foreach ($iniParser->data->groups[$area] as $key => $argsString)
        {
            if ($key[0] == '_')
            {
                continue;
            }
            $args = explode(',', $argsString);
            $args = array_filter($args, function($arg) {
                return $arg != '0' && $arg != '1' && $arg != 'nothing' && trim($arg) != '';
            });
            $r = count($args);
            if ($area == 'TriggerCalls')
            {
                $r--;
            }
            $lookup[$key] = $r;
        }
    }


    war3map.wtg

    In the coming structures, the type 'string' is referenced. A string is a sequence of bytes terminated by a null (0x00).

    The file is defined by the 'Root' structure as seen below. Everything else is nested within that. Some values display as 'Unknown'. If you can figure out what they are for, I'd love to update this specification to reach perfection some day.

    Structure: Root
    Code (Text):
    char[4]: File id (WTG!)
    int32: File format version: 4 for Reign of Chaos, 7 for Frozen Throne (very important later on)
    int32: Number "x" of trigger categories
    struct TriggerCategory[x]: Repeat the TriggerCategory structure x times
    int32: Unknown (always 0)
    int32: Number "y" of variables
    struct Variable[y]: Repeat the Variable structure y times
    int32: Number "z" of triggers
    struct Trigger[z]: Repeat the Trigger structure z times

    Structure: TriggerCategory
    Code (Text):
    int32: Id of the category
    string: Name
    int32: Is comment (1 = yes, 0 = no) (Version 7 only)

    Structure: Variable
    Code (Text):
    string: Name
    string: Type
    int32: Unknown (always 1)
    int32: Is array (1 = yes, 0 = no)
    int32: Array size (Version 7 only)
    int32: Is initialized (1 = yes, 0 = no)
    string: Initial value

    Structure: Trigger
    Code (Text):
    string: Name
    string: Description
    int32: Is comment (Version 7 only, 0 = no, any other = yes)
    int32: Is enabled (1 = yes, 0 = no)
    int32: Is custom (1 = yes, 0 = no)
    int32: Is initially off (1 = yes, 0 = no)
    int32: Run on initialization (1 = yes, 0 = no)
    int32: Trigger category id
    int32: Total number "x" of events/conditions/actions
    struct ECA[x]: Repeat the ECA structure x times

    Structure: ECA
    Code (Text):
    int32: Type (0 = event, 1 = condition, 2 = action)
    int32: Group for if-then-else (0 = condition, 1 = then action, 2 = else action) (Only exists if it is a child-ECA)
    string: Name "x"
    int32: Is enabled (1 = yes, 0 = no)
    struct Parameter[y]: Repeat the Parameter structure y times (where y is found in our lookup table for the key x)
    int32: Number "z" of child events/conditions/actions (Version 7 only)
    struct ECA[z]: Repeat the ECA structure z times (these are child ECAs) (Version 7 only)

    The parameter structure will be divided into separate versions for 4 and 7 because of slight nuances in whether various values exist or not.

    Structure: Parameter (Version 4)
    Code (Text):
    int32: Type "x" (0 = PRESET, 1 = VARIABLE, 2 = FUNCTION, 3 = STRING, -1 = INVALID)
    string: Value
    int32: Has sub parameters "y" (1 = yes, 0 = no)
    struct SubParameters: (Only exists if y = yes)
    int32: Unknown (Always 0, Only exists if "x" = FUNCTION)
    int32: Is array "z" (1 = yes, 0 = no) (Only exists if "x" != 2)
    struct Parameter: Array index (Only exists if z = yes)

    Structure: Parameter (Version 7)
    Code (Text):
    int32: Type "x" (0 = PRESET, 1 = VARIABLE, 2 = FUNCTION, 3 = STRING, -1 = INVALID)
    string: Value
    int32: Has sub parameters "y" (1 = yes, 0 = no)
    struct SubParameters: (Only exists if y = yes)
    int32: Unknown (Always 0, Only exists if "y" = yes)
    int32: Is array "z" (1 = yes, 0 = no)
    struct Parameter: Array index (Only exists if z = yes)

    Structure: SubParameters
    Code (Text):
    int32: Type
    string: Name "x"
    int32: Begin parameters "y" (0 = no, any other = yes)
    struct Parameter[z]: Repeat the Parameter structure z times (where z is found in our lookup table for the key x)
     
    Last edited: Jul 7, 2017
  2. Trigger.edge

    Trigger.edge

    Joined:
    Jun 21, 2012
    Messages:
    408
    Resources:
    0
    Resources:
    0
    Interesting. :ogre_haosis:
     
  3. MindWorX

    MindWorX

    Tool Moderator

    Joined:
    Aug 3, 2004
    Messages:
    626
    Resources:
    2
    Tools:
    2
    Resources:
    2
    Man, that's some good work Ralle. I'm proud of you ... son.
     
  4. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,214
    Resources:
    5
    Icons:
    1
    Spells:
    4
    Resources:
    5
    Awesome, love seeing more detailed specs come out. Approved.
     
  5. Ralle

    Ralle

    Owner

    Joined:
    Oct 6, 2004
    Messages:
    10,800
    Resources:
    8
    Tools:
    3
    Maps:
    5
    Resources:
    8
    Thanks guys :).
     
  6. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    3,882
    Resources:
    1
    Maps:
    1
    Resources:
    1
    You know you could have asked for a bit here and there since others like myself were also digging into file formats and parsers as the various uploaded tools hint at. Still, thanks for the specs :)
     
  7. Ralle

    Ralle

    Owner

    Joined:
    Oct 6, 2004
    Messages:
    10,800
    Resources:
    8
    Tools:
    3
    Maps:
    5
    Resources:
    8
    I guess I have been a bit of a hermit then. Anyway, if you have any feedback on values that actually mean something else, feel free to comment :).
     
  8. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    3,882
    Resources:
    1
    Maps:
    1
    Resources:
    1
    What's the difference between 'integer' and 'integervar' as variable type?
     
  9. GhostWolf

    GhostWolf

    Joined:
    Jul 29, 2007
    Messages:
    4,487
    Resources:
    1
    Tools:
    1
    Resources:
    1
    You are free to write your own specs or contribute to existing ones. I encourage you to do both. It's nice to have a repository of specs that are more-or-less updated compared to all of the specs posted elsewhere.
    So far every time I tried implementing anything, it required cross-referencing multiple specs, and usually fixing errors. Even in the most finalized and accepted specs (specifically for me MDX and BLP).
     
  10. Ralle

    Ralle

    Owner

    Joined:
    Oct 6, 2004
    Messages:
    10,800
    Resources:
    8
    Tools:
    3
    Maps:
    5
    Resources:
    8
    Where do you see that? Integervar?
     
  11. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    3,882
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Zangarmarsh [v1.2]

    My tool says the same, just curious how Blizzard made a difference there.

    @GhostWolf: Not active anymore, but yeah, would be nice to collect/maintain the specs somewhere on Hive, so we are all on the same page.
     
  12. GhostWolf

    GhostWolf

    Joined:
    Jul 29, 2007
    Messages:
    4,487
    Resources:
    1
    Tools:
    1
    Resources:
    1
    That variable has no type selected in WE. No idea how that's possible.
     
  13. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    469
    Resources:
    4
    Maps:
    2
    Spells:
    2
    Resources:
    4
    There are some cope paste bugs (Autogenerating, over two maps) which removes/hides types this two i know:
    Strings picking Models; new in 1.28.5 I never seen that in other versions.
    Integers beeing loop variables and never be set.; but kb is set here?


    Unbenannt.png
     
    Last edited: Jul 18, 2017