Our missions often depend on timing, and choosing good Delays is always difficult when you want to make IA a good opponent.
What makes a good opponent ? Synchronisation and planing are good clues.
Here is a generic script that intends to make missions design easier.
It has three purposes.
First : ordering several simultaneous actions using very little script, mostly copy/paste and form filling.
Second : if IA battle plan can be divided in 2 or more steps, it checks that step #1 is fully accomplished before ordering step #2, etc...
Third : it automatically controls everything about IA units movements : formations and attitudes (Position, Body & FireMode) while moving and when arrived on objective. It can use Points, Rects or Arrays as destinations.
This first version only deals with movements, but an area-attack trigger can be easily written using [Movement] as template.
So, how to use it ?
Your [init] trigger must include those lines amongst your own lines :
[init]
Set @@MovementNumber = 1
RunTrigger ( "Army_1_Step_1" ) //this will start the 1st serie of actions you planed for IA
//RunTrigger ( "Army_2_Step_1" )
...
//RunTrigger ( "Army_N_Step_1" ) //This script can control as many armies as you want
Halt
Those "steps", I mean the series of orders that have to be performed at the same time and all accomplished before starting the next serie are all built the same way :
Label Action3
Set @Group = "Group_1"
Set @InitialBodyMode = "Knee"
Set @InitialFireMode = "Hold"
Set @Point = "Point_1"
Set @Rect = "Rect_1"
Set @Array = "" //No array is used here
Set @Formation = "Wedge"
Set @Angle = 90
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = "Lay"
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
All you have to do is fill the variables with what you want, and add as many actions as you wish.
Of course, we need to add a little bit of code to make it work, but you don't have to pay interest to that. Just copy & paste as show in those examples.
-------------------------
[Army_1_Step_1]
// ARMY_1_STEP_1 - Check all variables looking like @@army_N_something
Set @Army = 1 //Please enter here the Army number
Set @@Army_1_Actions = 3 //Please enter here how many actions in this phase
SendMessage ( "ARMY_1_STEP_1 started" , 5000 )
Set @@Army_1_Actions_Completed = 0 //Don't change this
Label Action1
Set @Group = "Ger_Car_1" //required
Set @InitialBodyMode = "Knee" //facultative, leave "" if not used. Can be "Stay", "Knee" or "Lay", anything else will be considered as "Free".
Set @InitialFireMode = "Free" //required. Can be "Hold" or "Free", anything else will be considered as "Free".
Set @Point = "Ger_Car_1_1" //facultative, leave "" if not used
Set @Rect = "Ger_Car_1_1" //required : this Rect is used to check if Group reached its position. It should be at least a 10m square around the final destination point.
Set @Array = "" //facultative, leave "" if not used
Set @Formation = "Wedge" //facultative, leave "" if not used. Anything else than the regular formations will be considered as "Custom".
Set @Angle = 90 //facultative, leave "" if not used
Set @FinalPositionMode = "Hold" //facultative, leave "" if not used. Can be "Hold" or "Free", anything else will be considered as "Free".
Set @FinalBodyMode = "Knee" //facultative, leave "" if not used. Can be "Stay", "Knee" or "Lay", anything else will be considered as "Free".
Set @FinalFireMode = "Free" //facultative, leave "" if not used. Can be "Hold" or "Free", anything else will be considered as "Free".
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode ) //Don't change this
Add ( @@MovementNumber , 1 ) //Don't change this
Label Action2
Set @Group = "Ger_Flak_1" // you simply fill the form using your own names and modes
Set @InitialBodyMode = ""
Set @InitialFireMode = ""
Set @Point = "Ger_Flak_1" // the Flak truck will go to the point named "Ger_Flak_1"
Set @Rect = "Ger_Flak_1" // the script will watch when the flak truck reached the Rect named "Ger_Flak_1"
Set @Array = ""
Set @Formation = ""
Set @Angle = 90
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = ""
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Action3
Set @Group = "Ger_Tank_1"
Set @InitialBodyMode = ""
Set @InitialFireMode = "Hold"
Set @Point = ""
Set @Rect = "Ger_Tank_1"
Set @Array = "Ger_Tank_1" //The tank will follow an array of waypoints named "Ger_Tank_1"
Set @Formation = ""
Set @Angle = 90
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = ""
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Counts_Actions_Completed
If ( @@Army_1_Actions_Completed < @@Army_1_Actions ) Then
Delay ( 5000 )
Goto Counts_Actions_Completed
Else
RunTrigger ( "Army_1_Step_2" ) // The next serie of actions will start only when this one will be achieved
EndIf
Halt
-------------------------
At the same time, the 1st step for Army 2 will be running. It could look like this :
-------------------------
[Army_2_Step_1]
// ARMY_2_STEP_1 - Check all variables looking like @@army_N_something
Set @Army = 2 //Please enter here the Army number
Set @@Army_2_Actions = 3 //Please enter here how many actions in this phase
SendMessage ( "ARMY_2_STEP_1 started" , 5000 )
Set @@Army_2_Actions_Completed = 0 //Don't change this
Label Action1
Set @Group = "Fr_Inf_1"
Set @InitialBodyMode = "Knee"
Set @InitialFireMode = "Free"
Set @Point = "Fr_Inf_1"
Set @Rect = "Fr_Inf_1"
Set @Array = ""
Set @Formation = "Wedge"
Set @Angle = 270
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = "Lay"
Set @FinalFireMode = "Hold"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Action2
Set @Group = "Fr_Inf_2"
Set @InitialBodyMode = "Stay"
Set @InitialFireMode = "Free"
Set @Point = "Fr_Inf_2"
Set @Rect = "Fr_Inf_2"
Set @Array = ""
Set @Formation = "LineTankHuman"
Set @Angle = 270
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = "Knee"
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Action3
Set @Group = "Fr_ArmCar_1"
Set @InitialBodyMode = ""
Set @InitialFireMode = "Free"
Set @Point = "Fr_ArmCar_1"
Set @Rect = "Fr_ArmCar_1"
Set @Array = ""
Set @Formation = ""
Set @Angle = 270
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = ""
Set @FinalFireMode = ""
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Counts_Actions_Completed
If ( @@Army_2_Actions_Completed < @@Army_2_Actions ) Then
Delay ( 5000 )
Goto Counts_Actions_Completed
Else
RunTrigger ( "Army_2_Step_2" )
EndIf
Halt
-------------------------
The next step for army #1 can be like :
-------------------------
[Army_1_Step_2]
// ARMY_1_STEP_2 - Check all variables looking like @@army_N_something
Set @Army = 1 //Please enter here the Army number
Set @@Army_1_Actions = 1 //Please enter here how many actions in this phase
SendMessage ( "ARMY_1_STEP_2 started" , 5000 )
Set @@Army_1_Actions_Completed = 0 //Don't change this
Label Action1
Set @Group = "Ger_Car_1"
Set @InitialBodyMode = ""
Set @InitialFireMode = "Hold"
Set @Point = ""
Set @Rect = "Ger_Car_1_3" //The car will move to a Rect named "Ger_Car_1_3"
Set @Array = ""
Set @Formation = ""
Set @Angle = 90
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = ""
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Counts_Actions_Completed
If ( @@Army_1_Actions_Completed < @@Army_1_Actions ) Then
Delay ( 5000 )
Goto Counts_Actions_Completed
Else
RunTrigger ( "Army_1_Step_3" )
EndIf
Halt
[Army_1_Step_3]
// ARMY_1_STEP_3 - Check all variables looking like @@army_N_something
SendMessage ( "You can program anything you want, it will only be ordered when step 2 is done." , 5000 )
Halt
-------------------------
For army #2 :
-------------------------
[Army_2_Step_2]
// ARMY_2_STEP_2 - Check all variables looking like @@army_N_something
Set @Army = 2 //Please enter here the Army number
Set @@Army_2_Actions = 1 //Please enter here how many actions in this phase
SendMessage ( "ARMY_2_STEP_2 started" , 5000 )
Set @@Army_2_Actions_Completed = 0 //Don't change this
Label Action1
Set @Group = "Fr_Inf_1"
Set @InitialBodyMode = "Lay"
Set @InitialFireMode = "Free"
Set @Point = "Fr_Inf_1_2"
Set @Rect = "Rect_Fr_Inf_1"
Set @Array = ""
Set @Formation = "Gather"
Set @Angle = 0
Set @FinalPositionMode = "Hold"
Set @FinalBodyMode = "Stay"
Set @FinalFireMode = "Free"
RunTriggerInstance ( "Movement" , @@MovementNumber , @Army , @Group , @InitialBodyMode , @InitialFireMode , @Point , @Rect , @Array , @Formation , @Angle , @FinalPositionMode , @FinalBodyMode , @FinalFireMode )
Add ( @@MovementNumber , 1 )
Label Counts_Actions_Completed
If ( @@Army_2_Actions_Completed < @@Army_2_Actions ) Then
Delay ( 5000 )
Goto Counts_Actions_Completed
Else
// RunTrigger ( "Army_2_Step_3" )
EndIf
Halt
-------------------------
The third step for army 1 :
[Army_1_Step_3]
// ARMY_1_STEP_3 - Check all variables looking like @@army_N_something
SendMessage ( "You can program anything you want, it will only be ordered when step 2 is done." , 5000 )
Halt
-------------------------
Of course, there's a big machinery to make it work. But you don't even have to read it. Just copy and past the next [Movement] trigger :
[Movement]
PARAM IN @Army
PARAM IN @Group
PARAM IN @InitialBodyMode
PARAM IN @InitialFireMode
PARAM IN @Point
PARAM IN @Rect
PARAM IN @Array
PARAM IN @Formation
PARAM IN @Angle
PARAM IN @FinalPositionMode
PARAM IN @FinalBodyMode
PARAM IN @FinalFireMode
SetWorkArmy ( Army , @Army )
PositionMode ( Group , @Group , Free )
If ( @InitialBodyMode = "Stay" ) Then
BodyMode ( Group , @Group , Stay )
Else
If ( @InitialBodyMode = "Knee" ) Then
BodyMode ( Group , @Group , Knee )
Else
If ( @InitialBodyMode = "Lay" ) Then
BodyMode ( Group , @Group , Lay )
Else
BodyMode ( Group , @Group , Free )
Endif
Endif
Endif
If ( @InitialFireMode = "Hold" ) Then
FireMode ( Group , @Group , Hold )
Else
FireMode ( Group , @Group , Free )
Endif
If ( @Formation = "Gather" ) then
SetGroupFormation ( @Group , Gather )
Else
If ( @Formation = "Wedge" ) then
SetGroupFormation ( @Group , Wedge )
Else
If ( @Formation = "TrenchFormation" ) then
SetGroupFormation ( @Group , TrenchFormation )
Else
If ( @Formation = "LineTankHuman" ) then
SetGroupFormation ( @Group , LineTankHuman )
Else
If ( @Formation = "Column" ) then
SetGroupFormation ( @Group , Column )
Else
If ( @Formation = "Disperse" ) then
SetGroupFormation ( @Group , Disperse )
Else
SetGroupFormation ( @Group , Custom )
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
If ( @Point != "" AND @Array = "" ) Then
RunCommand ( Group , @Group , Move , Point , @Point , Angle , @Angle )
Else
If ( @Array != "" AND @Point = "" ) Then
RunCommand ( Group , @Group , Move , Array , @Array , Angle , @Angle )
Else
RunCommand ( Group , @Group , Move , Rect , @Rect , Angle , @Angle )
Endif
Endif
Label Check
Delay ( 10000 )
//Sendmessage ( "Checking if unit has finished moving." , 5000 )
Set @Test = GetNUnitsInArea ( Group , @Group , All , @Rect , No_Panic )
If ( @Test = 0 ) then
Goto Check
Endif
//Sendmessage ( "Movement completed, adopting P, B & F modes" , 5000 )
If ( @Army = 1 ) Then
Add ( @@Army_1_Actions_Completed , 1 )
Else
If ( @Army = 2 ) Then
Add ( @@Army_2_Actions_Completed , 1 )
//Else
//If ( @Army = N ) Then
// Add ( @@Army_N_Actions_Completed , 1 )
//Endif
EndIf
EndIf
Delay ( 10000 )
If ( @FinalPositionMode = "Hold" ) Then
PositionMode ( Group , @Group , Hold )
Else
PositionMode ( Group , @Group , Free )
Endif
If ( @FinalBodyMode = "Stay" ) Then
BodyMode ( Group , @Group , Stay )
Else
If ( @FinalBodyMode = "Knee" ) Then
BodyMode ( Group , @Group , Knee )
Else
If ( @FinalBodyMode = "Lay" ) Then
BodyMode ( Group , @Group , Lay )
Else
BodyMode ( Group , @Group , Free )
Endif
Endif
Endif
If ( @FinalFireMode = "Hold" ) Then
FireMode ( Group , @Group , Hold )
Else
FireMode ( Group , @Group , Free )
Endif
Halt
I will upload my test mission ASAP, so you'll see Frankenstein walking.
I hope you'll find that mess usefull
PS, for Sneaksie or 1C :
I do wish a new version of the scripting system was planed, in which the following points would be made available
- For ... To ... Next
- Functions that use constants such as "Hold", "Free", "Knee" could use variables too. For example, BodyMode ( @Variable1 , @Variable2 , @Variable3 ) would be legal according to @Variable1 being set to Army, Group or Unit, etc...
- SendMessage and Goto could use variables as arguments
- Distance () could handle groups
- Variables names could be incremented by triggers themselves, ie they could create @Variable(1), @Variable(2)... @Variable(n)
- Triggers such as RunCommand returns a signal when their instructions are completed.