Make Scenario Triggers using PHP Script

Article written by AOHH
Published on 01-13-2014; updated on 08-22-2014
Tags: ,

I am working on my “PHP Genie” project which reads/edits/writes Scenarios and Saved-Games. Currently, I am starting version 2. I will however give a few snippets from version 1 which is still a beta. Version 3 will have a User-Interface. I also intend to make a mini-map viewer in version 3 or 4.

Because I am still working on reading scenario contents, I have used a method to skip to the scenario’s triggers using a Magic-Keyword. For now, here are the snippets…

STEP 1:

Download PHP 5.2 and place the files into a folder in your local disc.

STEP 2:

Download and install PHP Designer

STEP 3:

Run PHP Designer and set the Preferences for debugging to the “php.exe” file.

STEP 4:

Create “Index.php” with the following contents:


<?

# Extend limits for huge amounts of triggers:
ini_set ( 'memory_limit' , '1024M' ) ;
ini_set ( 'max_execution_time' , 300 ) ;

# Set class:
class Scenario
{
# The output variable:
static $O ;

# This function must be absolutely perfect.
# The slightest error is not at all acceptable.
# It writes all triggers into raw scenario data.
# I prefer the PACK function rather than SPRINTF.
function Write ( $I )
{
$W = 0 ;
self :: $X .= pack ( 'L1' , count ( $I ) ) ; #
foreach ( $I as $T )
{
$T [ 4 ] = substr ( $T [ 4 ] , 0 , 64 ) ; # Maximum length 64
$T [ 5 ] = substr ( $T [ 5 ] , 0 , 44 ) ; # Maximum length 44
self :: $X .= pack ( ‘L1’ , ( $T [ 0 ] ? 1 : 0 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( $T [ 1 ] ? 1 : 0 ) ) ; #
self :: $X .= pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘C1’ , ( $T [ 2 ] ? 1 : 0 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $T [ 3 ] ) ? $T [ 3 ] : 0 ) ) ; #
self :: $X .= pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘L1’ , strlen ( $T [ 4 ] ) + 1 ) ; #
self :: $X .= pack ( ‘A*’ , $T [ 4 ] ) . pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘L1’ , strlen ( $T [ 5 ] ) + 1 ) ; #
self :: $X .= pack ( ‘A*’ , $T [ 5 ] ) . pack ( ‘C1’ , 0 ) ; #
self :: $X .= pack ( ‘L1’ , count ( $T [ E ] ) ) ; #
if ( count ( $T [ E ] ) )
{
foreach ( $T [ E ] as $E )
{
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ 0 ] ) ? $E [ 0 ] : 0 ) ) ; #
self :: $X .= pack ( ‘L1’ , 23 ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ Z ] ) ? $E [ Z ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ Q ] ) ? $E [ Q ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ R ] ) ? $E [ R ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ M ] ) ? $E [ M ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( count ( $E [ S ] ) ? count ( $E [ S ] ) : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ O ] ) ? $E [ O ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ U ] ) ? $E [ U ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ P ] ) ? $E [ P ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ E ] ) ? $E [ E ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ H ] ) ? $E [ H ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ B ] ) ? $E [ B ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ K ] ) ? $E [ K ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ T ] ) ? $E [ T ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ I ] ) ? $E [ I ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ L ] ) ? $E [ L ] [ 0 ] : -1 ) ) ; # [X]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ L ] ) ? $E [ L ] [ 1 ] : -1 ) ) ; # [Y]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ A ] ) ? $E [ A ] [ 0 ] [ 0 ] : -1 ) ) ; # [0] [X]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ A ] ) ? $E [ A ] [ 0 ] [ 1 ] : -1 ) ) ; # [0] [Y]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ A ] ) ? $E [ A ] [ 1 ] [ 0 ] : -1 ) ) ; # [1] [X]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ A ] ) ? $E [ A ] [ 1 ] [ 1 ] : -1 ) ) ; # [1] [Y]
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ G ] ) ? $E [ G ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ Y ] ) ? $E [ Y ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $E [ N ] ) ? $E [ N ] : -1 ) ) ; #

$Y = ( $E [ 0 ] == 3 || $E [ 0 ] == 20 || $E [ 0 ] == 26 ? 1 : 0 ) ;

self :: $X .= pack ( ‘L1’ , strlen ( $E [ X ] ) + $Y ) ; #
self :: $X .= $E [ X ] ; #
if ( $Y ) self :: $X .= pack ( ‘C1’ , 0 ) ;

self :: $X .= pack ( ‘L1’ , strlen ( $E [ D ] ) + $Y ) ; #
self :: $X .= $E [ D ] ; #
if ( $Y ) self :: $X .= pack ( ‘C1’ , 0 ) ;

if ( count ( $E [ S ] ) )
{
foreach ( $E [ S ] as $S )
{
self :: $X .= pack ( ‘L1’ , $S ) ; #
}
}
}
}
if ( count ( $T [ E ] ) )
{
$Z = 0 ;
foreach ( $T [ E ] as $E )
{
self :: $X .= pack ( ‘L1’ , $Z ) ; #
$Z ++ ;
}
}
self :: $X .= pack ( ‘L1’ , count ( $T [ C ] ) ) ; #
if ( count ( $T [ C ] ) )
{
foreach ( $T [ C ] as $C )
{
self :: $X .= pack ( ‘L1’ , ( $C [ 0 ] ? $C [ 0 ] : 0 ) ) ; #
self :: $X .= pack ( ‘L1’ , 16 ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ Q ] ) ? $C [ Q ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ R ] ) ? $C [ R ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ S ] ) ? $C [ S ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ O ] ) ? $C [ O ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ U ] ) ? $C [ U ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ P ] ) ? $C [ P ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ H ] ) ? $C [ H ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ T ] ) ? $C [ T ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ K ] ) ? $C [ K ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ A ] ) ? $C [ A ] [ 0 ] [ 0 ] : -1 ) ) ; # [0] [X]
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ A ] ) ? $C [ A ] [ 0 ] [ 1 ] : -1 ) ) ; # [0] [Y]
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ A ] ) ? $C [ A ] [ 1 ] [ 0 ] : -1 ) ) ; # [1] [X]
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ A ] ) ? $C [ A ] [ 1 ] [ 1 ] : -1 ) ) ; # [1] [Y]
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ G ] ) ? $C [ G ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ Y ] ) ? $C [ Y ] : -1 ) ) ; #
self :: $X .= pack ( ‘L1’ , ( isset ( $C [ Z ] ) ? $C [ Z ] : -1 ) ) ; #
}
}
if ( count ( $T [ C ] ) )
{
$Z = 0 ;
foreach ( $T [ C ] as $C )
{
self :: $X .= pack ( ‘L1’ , $Z ) ; #
$Z ++ ;
}
}
$W ++ ;
}

$Z = 0 ;
foreach ( $I as $T )
{
self :: $X .= pack ( ‘L1’ , $Z ) ; #
$Z ++ ;
}

# Write the end:
self :: $X .= pack ( ‘L1’ , 0 ) ; #
self :: $X .= pack ( ‘L1’ , 0 ) ; #
}

}

# Scenario:
$Scen = ‘YourScenario.scx’ ;

# Keyword:
$Word = ‘TRIGGER_START’ ;

# Get scenario’s data:
$Cont = file_get_contents ( $Scen ) ;

# Skip 4 bits:
$Head [ ‘Version’ ] [ 1 ] = substr ( $Cont , 0 , 4 ) ;

# Get length:
$Head [ ‘Length’ ] = implode ( ” , unpack ( ‘L1’ , substr ( $Cont , 4 ) ) ) ;

# Start of body:
$Line = $Head [ ‘Length’ ] + 8 ;

# Save head without body:
file_put_contents ( ‘Head.hex’ , substr ( $Cont , 0 , $Line ) ) ;

# GZ-Inflate the body:
$Cont = gzinflate ( substr ( $Cont , $Line ) ) ;

# Find start of triggers by keyword:
$Line = strpos ( $Cont , $Word ) – 26 ;

# Save body without triggers:
file_put_contents ( ‘Body.hex’ , substr ( $Cont , 0 , $Line ) ) ;

# Import new triggers:
if ( file_exists ( ‘Triggers.php’ ) ) include ‘Triggers.php’ ; else die ( ‘Triggers.php file does not exist !’ ) ;

# Write new triggers:
Scenario :: Write_Triggers ( $I ) ;

# Write the end:
Scenario :: $O .= pack ( ‘L1’ , 0 ) ; #
Scenario :: $O .= pack ( ‘L1’ , 0 ) ; #

# Remove extention:
$Scen = str_replace ( ‘.scn’ , ” , $Scen ) ;
$Scen = str_replace ( ‘.scx’ , ” , $Scen ) ;

# Loop 100 times:
foreach ( range ( 1 , 100 ) as $J )
{
# Set new filename:
$File = $Scen . ‘[‘ . $J . ‘].scx’ ; $J ++ ;

# Check for incremented filenames:
if ( ! file_exists ( $File ) )
{
# Deflate body with triggers and merge head with deflation:
file_put_contents ( $File , file_get_contents ( ‘Head.hex’ ) . gzdeflate ( file_get_contents ( ‘Body.hex’ ) . Scenario :: $O ) ) ; break ;
}
}

# Write results:
echo ‘

' . $File . '

‘ ;

?>

STEP 5:

Make sure to specify your scenario’s name to the “$Scen” variable and Magic-Keyword to the “$Word” variable (refer to Step 6 for clarification).

STEP 6:

Make sure that the first trigger from your scenario has the Magic-Keyword at the absolute start of the Trigger-Description (a keyword such as “TRIGGER_START”).

STEP 7:

Create “Triggers.php” with the following contents:


<?

# Trigger 0 …
$I[0][0]=1;#
$I[0][1]=0;#
$I[0][2]=0;#
$I[0][3]=0;#
$I[0][4]=”This is the trigger’s description”;#
$I[0][5]=”New Trigger 1″;#

$I[0][E][0][0]=20;# Display-Instructions
$I[0][E][0][T]=0;#
$I[0][E][0][N]=0;#
$I[0][E][0][X]=”Yo yo, hello…”;
$I[0][E][0][D]=”Age Up”;

# Or you can skip directly to trigger 1 effect without specifying trigger 1:
$I[1][E][0][X]=”This is the second trigger’s effect text…”;

?>

STEP 8:

Open the 2 .php files in PHP Designer. From the “triggers.php”, use the example triggers as a format sample to make your own triggers. After making your triggers, save “triggers.php” and Debug “index.php”. This will create “YourScenario[1].scx” … and “YourScenario[2].scx” (increment) each time you Debug.

FURTHER INFO:

  • Note that the AI Script data are contained at the end of the scenario. Any AI Script data will be delimited since I have used a series of 0000 to skip AI Scripts and end the scenario .
  • I intend to give the trigger Reader for the scenario’s triggers.
  • I intend to give the XML importer/exporter for triggers. It will be the same XML format as AoK:TS for the convenience of those who wish AoK:TS XML import worked.
  • When I release version 2, web admins (such as you Leif Ericson, or Voobly.com, AoC-Zone) with a server that supports PHP will find PHP-Genie an excellent tool to read and view information about Scenarios or Saved-Games. Including a mini-map viewer (Version 3 only).

Do you want to comment on this article? Thank the author? Tribute resources for its improvement? Raze it to the ground?

Come by and visit its thread in the University Forum!