
  Disclaimer
==============
These programs are not warranted to work at all, and any havoc
that occurs due to your using them is your own responsibility.
They were free from viruses when I distributed them.
If you are paranoid about such things, you can examine the
sources and/or rebuild the programs yourself.

ALWAYS make a backup copy of files before using these tools
on them.

  Introduction
================

This is a package of tools which convert files used in Warcraft 3
from binary to text and back again.

These tools need to be used together with an MPQ editor, such
as WinMPQ.  These tools do not include the ability to modify
MPQ (.w3m or .w3x) archive files directly.  If you don't know
what an MPQ editor is and how to use one, these tools are
definitely not for you.

These tools work with the following files:

war3map.w3u
  Custom units file - modifies existing unit types or defines new
  unit types in terms of modifications to existing types
  This tool can also be used with the following TFT files:
    war3map.w3b    destructables
    war3map.w3h    buffs
    war3map.w3t    items

war3map.w3r
  Regions file - defines rectangular regions used by triggers.

war3map.wtg
war3map.wct
  Triggers files - these files define all the custom triggers.

war3mapUnits.doo
  Map units file - this defines the position of units and buildings
  which were placed using the world editor.

war3map.w3a
  Abilities file - defines changes to abilities made in the TFT object editor
  This tool can also be used with the following TFT files:
    war3map.w3d    doodad customizations
    war3map.w3q    upgrades

war3map.w3i
  Info file - defines map name, author, titles, tech tree, upgrades,
  player names

war3map.doo
  Doodads file - defines positions of trees and other doodads

These tools aren't intended for helping you to rip off maps - there
are much better tools for that, such as unproteqtor or deprotect.
These tools are more useful in a small set of situations, including:

1) allowing a .w3m (Reign of Chaos) map which has custom unit
   definitions to be edited using the world editor without being
   forced to convert it to a .w3x (Frozen Throne) map

2) maintaining a set of maps which have different terrain but a common
   set of triggers and custom units

The text format used for the files is simple, and mostly is a reformatting
of the data in the files.  One exception is that the files usually have
an explicit count variable telling the number of triggers/regions/units,
the text format does not have them appear explicitly, since the correct
count can be calculated from the number of records.  Not having the
record count appear in the text form avoids errors where you add or delete
a record and forget to update the count.

A number of formats are used to handle string data:
- strings which are a single token with no spaces, such as the 4 character
  ID codes for units/items/abilities are represented as is without quotes:

    .mod uabi string 0 Sch2,Amel,Amed,Aexh

  In this example, "uabi" is the 4-char code for a units' intrinsic ability list.
  The string <NONE> is used to represent the 4 character ID code which
  is composed of 4 null bytes.

- strings which can have multiple tokens but only a single line are handled
  by making all of the text to the end of the current line be in the string:

    .mod unam string 0 Well of Mana

  In this example "Well of Mana" is the string.

- strings which can have multiple tokens but only a single line are also
  sometimes handled by just putting quotes around the string:

  .region 0 "Attack Point Center" -576.0 -2784.0 0.0 -1056.0 weather <NONE> sound "" color 128 128 255 255

- strings which can span multiple lines, such as custom text triggers, are
  handled by surrounding the string with quotes and having the .end delimiter
  token following the terminating quote:

  .description "this trigger description
has two lines" .end

There are many places where strings are followed by a 32-bit terminator
code, which is almost always 0.  These appear explicitly in the file
because there are many instances where these codes are non-zero.
For example, the sound field in custom units files is often non-zero:
    .mod usnd string 1886615397 Wisp
I included the terminator code because I wasn't sure that always using
a zero would work, and because I wanted the tools to be "reversible", 
in that converting any valid binary file to text and back again would
produce a binary file identical to the original.

One decision I made that I may change is that I sometimes represent
real data values as integers.  I did this because I wanted to avoid having
fields in the binary output be different from the binary input due to
inexact conversion between floating point and string representation.
UPDATE: I've changed the tools to represent reals as reals, it does lead
to differences in the binary files, but should make a difference in just
the least significant digits.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Usage
=========

  CustomUnits_To_Text [CUSTOM_UNITS_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.w3u and write CustomUnits.txt .

-=-=-=-
  Text_To_CustomUnits [TEXT_PATH] [CUSTOM_UNITS_PATH] [-dummy]

If you supply no command line arguments, this program
will read CustomUnits.txt and write war3map.w3u .
If you want to create a dummy custom units file, you must
specify both file names and the dummy switch, like this:

  Text_To_CustomUnits CustomUnits.txt war3map_dummy.w3u -dummy

-=-=-=-
  MapUnits_To_Text [MAP_UNITS_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3mapUnits.doo and write MapUnits.txt .

-=-=-=-
  Text_To_MapUnits [TEXT_PATH] [MAP_UNITS_PATH]

If you supply no command line arguments, this program
will read MapUnits.txt and write war3mapUnits.doo .

-=-=-=-
  Regions_To_Text [REGIONS_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.w3r and write Regions.txt .

-=-=-=-
  Text_To_Regions [TEXT_PATH] [REGIONS_PATH]

If you supply no command line arguments, this program
will read Regions.txt and write war3map.w3r .

-=-=-=-
  Triggers_To_Text [GUI_TRIGGERS_PATH] [CUSTOM_TEXT_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.wtg and war3map.wct, and write Triggers.txt .
You must have either 3 command line arguments or no arguments.

-=-=-=-
  Text_To_Triggers [TEXT_PATH] [GUI_TRIGGERS_PATH] [CUSTOM_TEXT_PATH]

If you supply no command line arguments, this program
will read Triggers.txt and write war3map.wtg and war3map.wct .
You must have either 3 command line arguments or no arguments.

-=-=-=-
  Abilities_To_Text [Abilities_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.w3u and write Abilities.txt .

-=-=-=-
  Text_To_Abilities [TEXT_PATH] [Abilities_PATH]

If you supply no command line arguments, this program
will read Abilities.txt and write war3map.w3u .

-=-=-=-
  Info_To_Text [Info_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.w3i and write Info.txt .

-=-=-=-
  Text_To_Info [TEXT_PATH] [Info_PATH]

If you supply no command line arguments, this program
will read Info.txt and write war3map.w3i .

-=-=-=-
  Doodads_To_Text [Doodads_PATH] [TEXT_PATH]

If you supply no command line arguments, this program
will read war3map.doo and write Doodads.txt .

-=-=-=-
  Text_To_Doodads [TEXT_PATH] [Doodads_PATH]

If you supply no command line arguments, this program
will read Doodads.txt and write war3map.doo .

-=-=-=-
  StringSubstitute [INPUT_FILE] [OUTPUT_FILE] [STRING_FILE]

If you supply no command line arguments, this program will
read from CustomUnits.txt, write to StringsOut.txt, and will
get its string definitions from war3map.wts .

This program is used to replace all occurences of trigger
string IDs (like TRIGSTR_001) with the actual string from
the string definition file (war3map.wts).  This can be useful
if you want to move the custom units file between maps which
have different string definitions files.

I originally wrote it when I somehow got world editor to
delete most of its string definitions and renumber the
rest while I was in the middle of a massive edit involving
many changes to both Triggers.txt and the custom units file.
At the end I was left with a Triggers.txt which had references
to the new renumbered strings and a war3map.w3u file which
referred to trigger strings which didn't exist, so I couldn't
back off to an earlier version of the map without throwing
out a lot of work.  I used StringSubstitute to replace all
the trigger string references in the custom units map with
the actual strings from the earlier version of the trigger
strings file (war3map.wts).
Moral of the story: Save often.  Duh.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Editing .w3m maps with custom units
=======================================

The current version of world editor will usually force you
to save a map with custom units as a .w3x map, even if you
open a .w3m map with custom units and save it before making
any changes.

One way to work around this is to use a dummy custom units
file. The dummy file has entries for all the custom units,
but the custom units all have 0 mods. This way the unit ID
codes for the custom heros & units are defined, but they have
no value changes which would force the file to be saved as
a .w3x file.
All of this assumes that you have an editable version of
the file you want to modify.

In my .w3m file I have a war3map.w3u and a war3map_dummy.w3u. 

Before starting world editor, in WinMPQ:
1) change the name of war3map.w3u to war3map_real.w3u
2) change the name of war3map_dummy.w3u to war3map.w3u

Run the world editor and when done, in WinMPQ, do:
1) delete (attributes) - otherwise you will get a "corrupt data"
   error on map load
2) change the name of war3map.w3u to war3map_dummy.w3u
3) change the name of war3map_real.w3u to war3map.w3u

If you want to actually change custom unit attributes,
the above doesn't help you.  In that case, do this:
1) open the .w3m with world editor & make your custom unit changes
2) save the map as a .w3x file
3) use WinMPQ to extract the war3map.w3u custom units file from .w3x file
4) use WinMPQ to insert the war3map.w3u file into the .w3m file
If you have added a new custom unit, you will need to add a
corresponding new unit to your war3map_dummy.w3u file.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Maintaining a set of related maps
=====================================

If you have a set of related maps, which share custom unit
and trigger definitions but have different terrain, these
tools can be used to cut down on the amount of work needed
to keep those maps up to date.  For this to work, the
following restrictions need to be met:

- the number and type of buildings which are referenced
  by triggers must be the same on all maps
- the number of regions must be the same on all maps

If you are working with a set of maps which were not
created with this in mind, the variable names assigned to
corresponding units will be different on the different
maps.  There are 2 ways I can think of to deal with this:

1) Use multiple Triggers.txt files
   Make up a list of corresponding units on the different
   maps and use a text editor to create different versions
   of the Triggers.txt file.
2) Use a single Triggers.txt file
   Change the variable names which will be assigned to units
   on the different maps to match, by modifying the "creation"
   field for units in the MapUnits.txt files.

The world editor creates unit variables for any unit which
is referenced by a trigger.  The names are like gg_unit_TTTT_NNNN,
where TTTT is replaced by the four letter unit type ID, and
NNNN is the unit creation number, which is just a number that
starts at 1 and goes up each time you add a unit in the world
editor.  You can find out the four letter unit type ID by
either hitting control-D in the world editor Object module,
or by looking it up in units\unitdata.slk file (using Excel)
which is in the war3.mpq file in your Warcraft 3 directory.

Method 1 has the advantage of being quicker initially, but
the disadvantage that at the end you have multiple Triggers.txt
files that you have to maintain in parallel.
Method 2 probably takes a little longer than method 1, but
after that you have just one Triggers.txt file to maintain.

I have used method 1 on a set of 3 related maps.  If I ever
plan on making a huge change to the triggers of the maps, I
will probably switch over to method 2.

For example, the Necropolis might be named gg_unit_unpl_0002
on one map and gg_unit_unpl_0100 on another map.
With method 1 you would use a mass string replace of
gg_unit_unpl_0002 with gg_unit_unpl_0100 in Triggers.txt.
With method 2 you would go into MapUnits.txt and change the
"creation" field of the unit of type unpl from 100 to 2.
You would also have to change the creation number of whatever
unit currently has creation number 2 to something else - a
good choice would be to set the creation number of the displaced
unit to one more than the number of the last unit in MapUnit.txt,
or to just always swap numbers.

As you do the text replacements using method 1 be wary of
accidental name collisions.  These are unlikely - they can
only happen if you have units which have the same type and
creation number in both maps.

These restrictions can be relaxed some of the time.  For
example, if you are willing to do a little more work, you
could have some of the maps have more buildings or regions
referenced by triggers.  The easiest way to work this would
be to have one master set of sources which included all the
units or regions referenced by any map, and turn off
triggers which reference units or regions which do not
exist in a particular map.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Dealing with "Unknown function" errors
==========================================
The programs which deal with triggers have a built-in
list of the predefined functions which can appear in a JASS
program, which tells how many parameters each function takes.
This is needed to parse the GUI trigger file.
When Blizzard makes new patches they usually include some
new function definitions which will not be in the built-in
list.  If you run Triggers_To_Text and get an "Unknown function"
error, it is probably one of these new functions.

Triggers_To_Text and Text_To_Triggers have a method which
allows you to add new function definitions.  Take the new
function definitions from the common.j and blizzard.j files
in the patch .mpq file and put them in a file named extraFunctionsIn.txt
in the folder you run the programs from.  The programs will
parse this file and create a file extraFunctionsOut.txt which
has the function name and the parameter count.  When you
change extraFunctionsIn.txt, you must delete the existing
extraFunctionsOut.txt, so that the programs will know that
they need to recreate extraFunctionsOut.txt.  Blizzard patch
1.17 came out between when I wrote these programs and now, so
there are examples of extraFunctionsIn.txt and extraFunctionsOut.txt
in the zip file which have the new functions from patch 1.17.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Rescuing abandoned maps
===========================

If you want to make an unprotected and/or editable version of
a map, the best way to do so is to contact the author(s) of the
map and convince them to share their map or knowledge with you.

If this is impossible, the next best way is to use a tool such
as unproteqtor or deprotect to unprotect the map.  Neither of
these tools can completely defeat every map protection, so here
are some steps you can use if you really need to make a map
editable, and enjoy boredom and wasting lots of time.

To make a map editable, what you are mainly trying to do is
recreate the following files:

war3map.wtg         normal triggers
war3map.wct         triggers defined in JASS
war3map.w3r         regions
war3map.imp         imported file list
war3mapUnits.doo    statically placed units

These files are needed by world editor, but are not needed by
the game.  The information needed to recreate the triggers and
regions files can be recreated from the war3map.j file, which
may also be called Scripts\war3map.j file in the mpq archive.

NOTE: I will use forward slash (/) as a string delimiter in the
      below examples.

-=-=-=-

  The Regions File
--------------------

To recreate the regions file, in war3map.j, find the CreateRegions
function.  This will have a bunch of lines like:

    set gg_rct_Attack_Point_Center = Rect( -576.0, -2784.0, 0.0, -1056.0 )
    set gg_rct_Attack_Point_E = Rect( 1376.0, 3200.0, 2240.0, 4096.0 )
    set gg_rct_Attack_Point_N = Rect( -2336.0, -5120.0, -1472.0, -4224.0 )

Create a text file named Regions.txt, and copy in the lines like the above
one and do this in a text editor:

- paste in these lines at the top of the file:
.section Regions (war3map.w3r)
.version 5
- substitute space for all underscores
- substitute /.region NN "/ for all occurences of /set gg_rct_/
- substitute /"/ for all occurences of / = Rect(/
- substitute space for all commas
- substitute /weather <NONE> sound "" color 128 128 255 255/ for all occurences of /)/
- paste in this line at the bottom of the file:
.endSection Regions (war3map.w3r)
- save the file

At the end, the 3 lines above would become:

.section Regions (war3map.w3r)
.version 5
.region 0 "Attack Point Center" -576.0 -2784.0 0.0 -1056.0 weather <NONE> sound "" color 128 128 255 255
.region 1 "Attack Point E" 1376.0 3200.0 2240.0 4096.0 weather <NONE> sound "" color 128 128 255 255
.region 2 "Attack Point N" -2336.0 -5120.0 -1472.0 -4224.0 weather <NONE> sound "" color 128 128 255 255
.endSection Regions (war3map.w3r)

-=-=-=-

  The Map Units File
-------------------------

Ugh, I don't have a good way to recreate this file.  One way to do this
would be to use the world editor to place units of the right types in
roughly the right spots, convert the war3mapUnits.doo to MapUnits.txt
using MapUnits_To_Text, then get the exact position information from
the war3map.j script file and plug it into the corresponding field in
MapUnits.txt.

For example, if the war3map.j file had a line like:

    set u = CreateUnit( p, 'UUUU', XXXX, YYYY, 270.0 )

you would find a unit of type UUUU in MapUnits.txt and plug in the X & Y
coordinates like so:

.unit UUUU variation 0
.loc XXXX YYYY 1536.000000 angle 4.712389
.scale 1.000000 1.000000 1.000000
.flags 2 player PPPP b1 0 b2 0 hp -1 mana -1
.gold 12500 type 0 1 color -1 gate -1 creation CCCC unknown -1.000000 1 0 0

The owning player field PPPP can be found by looking at the war3map.j file,
and find the player by looking for lines like:
    local player p = Player(6)
before the CreateUnit call.

The creation field CCCC is a simple index that tells the order that units
were placed in the game, the first unit placed by the editor has creation
number 0, the next has number 1 and so on.  These fields must be unique, and
are used by the editor whenever a trigger directly references a specific
statically placed unit - for example if you had a trigger that was meant to
run whenever a specific building took damaged or was destroyed.

Example:
// in war3map.j
function CreateBuildingsForPlayer6 takes nothing returns nothing
    local player p = Player(6)
... lotsa other junk ...
    set u = CreateUnit( p, 'uzg1', 4256.0, 5600.0, 270.000 )
    set gg_unit_unpl_0113 = CreateUnit( p, 'unpl', 4480.0, 4736.0, 270.000 )
... lotsa other junk ...
endfunction

// in MapUnits.txt
.unit uzg1 variation 0
.loc 4256.000000 5600.000000 1530.406250 angle 4.712389
.scale 1.000000 1.000000 1.000000
.flags 2 player 6 b1 0 b2 0 hp -1 mana -1
.gold 12500 type 0 1 color -1 gate -1 creation 97 unknown -1.000000 1 0 0

.unit unpl variation 0
.loc 4480.000000 4736.000000 1504.656250 angle 4.712389
.scale 1.000000 1.000000 1.000000
.flags 2 player 6 b1 0 b2 0 hp -1 mana -1
.gold 12500 type 0 1 color -1 gate -1 creation 113 unknown -1.000000 1 0 0

Notice that the unpl unit was created with a variable named gg_unit_unpl_0113.
This means that the unpl unit has creation number 113, and there is a trigger
in the game that specifically references this unpl unit.

To deal with creation numbers, you can either force your MapUnits.txt file to
have the same creation numbers as the existing triggers, or assign creation
numbers and go back and change references in the triggers to match the new
numbers.  Either way is a manual pain in the ass.

Convert the MapUnits.txt back into war3mapUnits.doo using Text_To_MapUnits,
and insert the war3mapUnits.doo into your map file.

The angle field in the MapUnits.txt file is in radians, I used this because
that is how it is represented in the war3mapUnits.doo file, while the war3map.j
file specifies angles in radians.

I'm sorry this section sucks so bad, I'm out of time to work on this.
-=-=-=-

  The Triggers Files
----------------------

The process for recreating the triggers files is somewhat long,
and has 2 sections, variables and triggers.  You should start
out be creating a simple map in world editor, and doing:
- Add a few variables, some initialized and some uninitialized
- Add a simple trigger that has one event, one condition and
  one action
- Make a copy of the simple trigger, and convert that to
  a custom text trigger.
- Save the simple map
- Extract the war3map.wtg and war3map.wct using an MPQ editor
- Use Triggers_To_Text to create a Triggers.txt file.


The variables section
---------------------

Identify the variables by looking in the "globals" section at the
start of war3map.j.  If you see an array variable like this:

integer array udg_SaveMe

add a line like this to Triggers.txt in the .variables section:
  .variable SaveMe type integer u1 1 isArray 1 isInited 0 value 

If you see a non-array variable like this:

real udg_MyGold = 0

add a line like this to Triggers.txt in the .variables section:

  .variable MyGold type real u1 1 isArray 0 size 1 isInited 1 value 1000.0

The isInited field is set to 1 for variables which are initialized
in the function InitGlobals.  The above example would be correct if
InitGlobals included the line:

  set udg_MyGold = 1000.0

Some of the variables in the global section are generated by
the world editor, and may appear after a comment line like:
    // Generated
In general, you shouldn't create .variable entries for
generated variables.  These variables generally begin with
the suffix "gg_".

Some maps have been processed with optimizer programs, which will
rename variables to be shorter, so you can't always rely on all
user defined globals starting with "udg_" and all generated globals
starting with "gg_".


The triggers section
--------------------

To recreate the triggers section you have two main approaches:

1) attempt to recreate the GUI triggers
2) create custom text triggers

You can use both GUI and custom text triggers.  The method I use
is this:

- take the custom text trigger you created in Triggers.txt, and
  remove the existing JASS code which is the text starting after
  the double quote after the ".customText" string and ends before
  the double quote before the ".end" string.  Make copies of the
  remaining text, you will use these as a template in the following steps.

- look through the war3map.j file, identifying the JASS code
  which corresponds to each trigger.  In this example, the trigger
  is named XXX.
  - each trigger should have a corresponding trigger variable in the
    globals section:
    trigger                 gg_trg_XXX        = null
  - there should also be code which accesses this variable, like this:
//===========================================================================
// Trigger: XXX
//===========================================================================
function Trig_XXX_Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_XXX_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_001" )
endfunction

//===========================================================================
function InitTrig_XXX takes nothing returns nothing
    set gg_trg_XXX = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEventSimple( gg_trg_XXX, Player(0), EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_XXX, Condition( function Trig_XXX_Conditions ) )
    call TriggerAddAction( gg_trg_XXX, function Trig_XXX_Actions )
endfunction

  - there should also be a line in InitCustomTriggers like this:
    call InitTrig_XXX(  )

- put the JASS code for each trigger into a copy of the custom
  text trigger template.  The above example would become:

  .trigger "XXX" comment 0 enable 1 custom 1 initiallyOff 0 mapInit 0 category 1
  .description "" .end
  .customText "//===========================================================================
// Trigger: XXX
//===========================================================================
function Trig_XXX_Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_XXX_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "You call this action?" )
endfunction

//===========================================================================
function InitTrig_XXX takes nothing returns nothing
    set gg_trg_XXX = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEventSimple( gg_trg_XXX, Player(0), EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_XXX, Condition( function Trig_XXX_Conditions ) )
    call TriggerAddAction( gg_trg_XXX, function Trig_XXX_Actions )
endfunction

" .end


- after all the custom text triggers are defined this way, convert
  the Triggers.txt file back into war3map.wtg & war3map.wct using
  Text_To_Triggers and re-insert those files into the empty map.

- Edit the empty map using world editor, and where possible replace
  custom text triggers with the corresponding GUI triggers.
  There is no easy way to learn how to do this - you just have to
  look at the names of the JASS functions and figure out which
  GUI functions most closely correspond to them.  When you have
  created a GUI trigger, make a copy of it and convert that into
  JASS, and compare it with the original JASS code to see if you
  got it right.  It gets easier quickly with practice.   The GUI
  trigger corresponding to our XXX trigger example is:

XXX
    Events
        Unit - A unit owned by Player 1 (Red) Dies
    Conditions
        ((Triggering unit) is A Hero) Equal to True
    Actions
        Game - Display to (All players) the text: You call this action

Not all JASS custom text triggers code can be converted back to GUI
triggers.

Map Initialization Triggers
---------------------------
Any triggers that are referenced from RunInitializationTriggers in
war3map.j are initialization triggers, and should have its mapInit field
in Triggers.txt set to 1.

-=-=-=-

  The Imports File
--------------------

The imports file war3map.imp tells world editor about all the
non-standard files you have added to your map, such as models,
skins and button icons.  Any files which are not listed in
the imports file will not be included in your map when you
save with world editor.

To recreate the imports file is a major pain, the only way
I know how to do it is to extract all the files from the
map archive and search them for any filename strings which
end in .blp, .mdx, .mdl and .tga.  Add these filename strings
to your (listfile), insert (listfile) back into the map
archive and reopen the map archive.  There are 

One shortcut is to open the map in world editor, save a
temporary copy of the map and reopen the temporary, looking
for any models that are listed as missing on reload.  Add these
to the (listfile) and see if the named file appears when
you reopen the archive.

Model files are usually referred to with strings with the
extension .mdl, but the files in the archive have the
extension .mdx, so if you find the string Splooge.mdl
you should add Splooge.mdx to your (listfile).

If you are using WinXP, be aware that the file search function
in Windows Explorer is extremely broken, it will only search
in a restricted set of filetypes that doesn't include the
filetypes used in Warcraft 3 maps.  You will need to use a
3rd party search tool on WinXP.  I recommend Agent Ransack.

An alternative to recreating the imports file is to use the
original map file as a container - that file already contains
all the extra files needed by the map.  The painful part of
this alternative is that you have to keep taking any files
which are modified as a result of your editing changes,
extracting them from the edited file, and re-inserting them
back into the original map file.  This also doesn't always
work - I have seen map files that are corrupted in a way
that makes them unable to have files written to them.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  Modifying the programs
==========================
Feel free to modify or extend these programs in any way that
you see fit, with the only requirement that you not distribute
modified versions of them without taking blame/credit for them
yourself.  If you change them, stick your name on them with my
blessing.

If you want to modify these tools, you will probably need info on
the format of the files inside a .w3m/.w3x file.  In making these
tools, I used a file by Zepir.
One of these links should get you to Zepir's document:

http://umswe.wc3campaigns.com/specs/insidethew3m.html
http://www.wc3campaigns.com/showthread.php?t=937

These tools were made using Microsoft Developers Studio
version 6 on a Windows 2000 system.

  Acknowledgements
====================
Pretty much all the knowledge I used in making these tools
is from Zepir's document referenced above.

  Peace,
    gnosys


SillyTrigger
    Events
        Unit - A unit owned by Player 1 (Red) Dies
    Conditions
        ((Playable map area) contains (Triggering unit)) Equal to True
        ((Triggering unit) is A Hero) Equal to True
        ((Triggering unit) is A structure) Equal to False
    Actions
        Game - Display to (All players) the text: You call this actio...


function Trig_SillyTrigger_Copy_Conditions takes nothing returns boolean
    if ( not ( RectContainsUnit(GetPlayableMapRect(), GetTriggerUnit()) == true ) ) then
        return false
    endif
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == false ) ) then
        return false
    endif
    return true
endfunction

function Trig_SillyTrigger_Copy_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_002" )
endfunction

//===========================================================================
function InitTrig_SillyTrigger_Copy takes nothing returns nothing
    set gg_trg_SillyTrigger_Copy = CreateTrigger(  )
    call TriggerRegisterPlayerUnitEventSimple( gg_trg_SillyTrigger_Copy, Player(0), EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_SillyTrigger_Copy, Condition( function Trig_SillyTrigger_Copy_Conditions ) )
    call TriggerAddAction( gg_trg_SillyTrigger_Copy, function Trig_SillyTrigger_Copy_Actions )
endfunction

