Guide

Guide

Requirements

Installation

  • Download and extract the tool anywhere in your filesystem.
  • Run 'Better Triggers.exe' to launch the program.
  • When launching for the first time it will ask you to locate your Warcraft III installation directory. Example: 'C:\User\Program Files\Warcraft III'.

You're now ready and set!

Create a project

To create a project select 'File -> New Project' in the top menu.

You have the option to create an empty project or copy all triggers from an existing map. Creating an empty map will generate a new map in the 'map' directory with empty triggers.

When creating a project with existing triggers from a map the tool will extract all folders, triggers, variables, and scripts into the 'src' folder in your project. Comments in the Trigger Explorer menu are ignored.

💡

NOTE: If you're copying triggers from a map that contains variables with upper-/lower case variations of the same name e.g. "myVar" and "MyVar" the latter ones will be renamed. This is because the filesystem isn't case sensitive by default and conflicts would occur.

As a result, you may experience compile errors after porting.



no image

Creating a new project generates a folder with a project file and three subfolders:


no image
  • The project file contains essential information about your project, and is the file you should point to when opening a project.
  • The 'map' folder is not required, but it is the default map location when creating a new project.
  • The 'src' folder contains all source files i.e. triggers, variables, scripts etc.
  • The 'dist' folder contains the final map when you click 'Export Map'.

Workflow

Trigger Explorer

The trigger explorer in this trigger editor works a lot different than the one in the World Editor, in the way that it's actually a live view of your filesystem from your src folder.

no image
💡

NOTE: While you can certainly copy-paste files and entire folders of content in Windows Explorer, it is recommended you do these operations through the trigger explorer in Better Triggers. The generated script will create triggers and variables with names based on filenames, and if two variables or triggers have the same name it will cause script errors. This will not happen when copy-pasting through Better Triggers, since the editor will properly rename your files.

However, script files (.j and .lua) are not affected by this.

The main benefit of this being a live filesystem view is that you can work directly in an external text/code editor without the need to copy-paste the contents into the editor like we are used to in the World Editor:


no image

External changes to your scripts are automatically picked up by the editor. This is exclusive to .j and .lua files. Content changes to trigger and variable files will not be picked up by the editor, but it's generally not recommended to edit those anyway.

Working between Better Triggers and the World Editor

Since Better Triggers is an external tool it only knows about map changes that you last saved. All changes in the World Editor must be saved before Better Triggers can detect the changes.


no image

Once the map has saved Better Triggers will reload all map data, and notify you if any triggers changed as a result of the updated map data.

Exporting the final map

When you're ready to export the final map you click the "Export Map" button. This will create a separate map file with the generated script in the 'dist' folder in your project.

no image

Expanded GUI Tips

Local Player

Better Triggers has implemented 'GetLocalPlayer' in GUI. This should only be used in if-then-else actions like so:


no image

It's generally not recommended to use 'Local Player' if you're unfamiliar with it, as it's the number 1 cause of desyncs. However, it enables you to do a lot of things, like displaying UI elements (frames) on a per player basis.

Frames

Since Blizzard has not implemented a generic event for frames, Better Triggers has done a workaround to bring frame natives to GUI triggers. The generic frame event actually uses 'TriggerRegisterVariableEvent' under the hood, but is made more user-friendly for GUI users. There are a few points to make about this:

When referring to the player that triggered the event you cannot use 'Triggering Player' or 'GetTriggerPlayer()'. You must use 'Triggering Frame Player' or 'GetTriggerFramePlayerBT()' as shown here:


no image

This is also the case for a number of other natives, though is mostly relevant for scripting:

  • 'GetTriggerFrame()' -> 'GetTriggerFrameBT()'
  • 'BlzGetTriggerFrameEvent()' -> 'GetTriggerFrameEventBT()'
  • 'BlzGetTriggerFrameValue()' -> 'GetTriggerFrameValueBT()'
  • 'BlzGetTriggerFrameText()' -> 'GetTriggerFrameTextBT()'

Other than that you use the frame natives in GUI just like you would in scripting.
E.g. you show/hide frames for individual players showing/hiding them inside a 'Local Player' if-statement:

no image

The above GUI trigger generates the following script:

//****************************************************************************
//*  Trigger Untitled_Trigger
//****************************************************************************
function If_Trig_Untitled_Trigger_0 takes nothing returns boolean
	if (not(GetTriggerFramePlayerBT() == GetLocalPlayer())) then
		return false
	endif
	return true
endfunction
 
function Trig_Untitled_Trigger_Conditions takes nothing returns boolean
	if (not(GetTriggerFrameBT() == udg_frameButton)) then 
		return false
	endif
	if (not(GetTriggerFramePlayerBT() == Player(0))) then 
		return false
	endif
	return true
endfunction
 
function Trig_Untitled_Trigger_Actions takes nothing returns nothing
	if (If_Trig_Untitled_Trigger_0()) then
		call BlzFrameSetVisibleBT(false, GetTriggerFrameBT())
	else
	endif
endfunction
 
//****************************************************************************
function InitTrig_Untitled_Trigger takes nothing returns nothing
	set gg_trg_Untitled_Trigger = CreateTrigger()
	call TriggerRegisterGenericFrameEventBT(gg_trg_Untitled_Trigger, 1.0, EQUAL, "bt_genericFrameEvent")
	call TriggerAddCondition(gg_trg_Untitled_Trigger, Condition(function Trig_Untitled_Trigger_Conditions))
	call TriggerAddAction(gg_trg_Untitled_Trigger, function Trig_Untitled_Trigger_Actions)
endfunction

For a more in-depth guide on how to use frames refer to Tasyen's tutorial: Types of Frames