/*        INTRO                      V1.0t  1-26-2003
This document contains the methods, data and underlying concepts that 
the layout designer needs to know in order to create and manipulate 
layout script files for the Zono game engine.


NOTE: If you are reading this in Word, you will see some bad word
wraps (use NotePad instead). 
This cannot be avoided in order to properly format
the script examples for use in a programming editor.
This do not occur in the programming editor (SlickEdit) used 
to edit the scripts.

This file was primarily written for in house designers to use on any
Zono game. 
We are providing it here so you have more information to make maps,
but keep in mind some things here might be vague or not work the way
it does in 'Battle for Troy' because various customizations were
made in the engine for that game.
*/ 


/* 
SCRIPT FILE BASICS
Script files are text-only files with the extension of .kfc instead of 
.txt .

This document is written as a .txt file to allow easy copying and 
pasting of objects & examples from here into kfc files.  I didn't use 
Word to write this because copying text from a Word doc and pasting 
them into a kfc file can produce messy formatting results in the kfc 
(txt) file.

.kfc Script files may be edited with any text editor, such as NotePad, 
but a programming editor is highly recommended.  
Zono designers currently use SlickEdit to edit kfc files.  Among other 
things, SlickEdit allows you to see text onscreen in a color-coded 
format based on the text's function.
For example:  */ 

//  These three lines are typical parameter lines in an object

    float Locator.Position.X = 24.462795;
    float Locator.Position.Y = 21.539082;
    float Locator.Position.Z = -0.062496;

    char *pText = "And Text Strings will show up in a different color for easy identification";

// This text is a comment; it will be displayed in a yet another color in SlickEdit

   //Note: A 'comment' is text that is ignored when the script file is compiled.
    
    /* Comments can also be bookended with these
            _asterisk_and_slash_ special characters */ 

/* End of SCRIPT FILE BASICS ---------------------------------------*/ 



/* 
.kfc SCRIPT FILES   
The layout designer will be working mainly with these files:

HandLayout.kfc
DesignParams.kfc

We will give you these files 'empty' that contain a few header lines 
and miscellaneous objects needed to make them work properly.

This file:
LayoutParams.kfc 
also defines the layout of objects, but the layout designer will 
usually not be working with it because it contains decor objects 
(trees, walls, street lamps, boulders, etc) that are laid out by the 
artist who created the map.  These objects are laid out from Haus's 
'Layout Menu' (see HAUS below).

DesignParams.kfc 
contains objects (enemy units, player's starting units, tents, home-
base buildings, etc) that are laid down from Haus's 'Design Menu' and 
saved to your hard drive from within Haus (see HAUS below).
This 'Design Menu' is one of the major tools used by the layout 
designer to place mission-specific objects onto the playfield from 
within the game.

HandLayout.kfc 
contains special objects whose parameters the layout designer will need 
to edit a lot, "by hand".  These special objects include 'Triggers', 
'Actions' and objects that allow you to define and display text on the 
Intro screens.  (See Trigger / Action section below).

NOTE on Labels: To use Trigger and Actions you will be using 
Labels a lot.  
Any Label referred to in HandLayout.kfc MUST also be defined 
in HandLayout.kfc .


End of .kfc SCRIPT FILES ---------------------------------------- */ 



/*---------------------------------
"HAUS": ZONO'S IN-GAME LAYOUT EDITOR

Haus, pronounced 'hoss' or 'hawss', is short for 'Haus of Editing'.

Make sure to run the game with the /h and /d switches in order to 
be in haus and disable modes. You will break things if you dont!
Also remember to remove these switches when you want to actually
test your level. :)

When the game is running on your PC, pressing the H key pauses the game 
and brings up Haus.

Haus is used to 
--create and position game objects on the playfield, 
--edit the parameters of game objects on the playfield, 
  placed via the 'Design Menu',
--save these objects and their parameters to kfc files which can then 
be compiled into the game with TBDGEN.

Haus cannot be used to edit objects that are in HandLayout.kfc. Those 
must be edited by hand with a text editor.

Overlaid on the playfield, Haus has green boxes on the top left of the 
screen.  To activate their functions you can click on the box with the 
mouse or use a hotkey (see Haus Commands).
Don't mess with the green boxes on the top right of the screen (Start 
Recording, etc.), they are from an older project and dont really do anything
useful at this time.

1-ADD TEMPLATE        hotkey= 1
For addingn "decor" type objects such as trees, pillars, etc.
These items are saved in "LayoutParams.kfc"

2-ADD LAYOUT         hotkey= 2
These objects are also saved in LayoutParams, but generally you want
to use the ADD TEMPLATE menu instead, since the objects there are 
sort of "pre setup" for you. In almost all cases you will never
need to use the ADD LAYOUT menu. 

3-ADD DESIGN           hotkey= 3
Calls up 'Design Menu'.
Objects created with this 'Design Menu' will be saved to the file:
DesignParams.kfc
This is to keep mission specific objects separate from the decor 
objects residing in LayoutParams.kfc 

To lay out an object from the Design Menu, call up the menu by pressing 
3 or clicking on the ADD DESIGN box.
Select the object's name from the menu by highlighting it with the 
mouse cursor and Left-clicking.
This closes the menu and adds the word "Create" to the mouse cursor.
Right click on the playfield where you want to create the new object; 
you can do this many times to create multiple objects of the same type 
(but make sure the Player ID number is what you want before laying down 
a lot of objects at once, see PLAYER ID NUMBERS).
Left click an object to select it to edit its parameters or to move it 
somewhere else.


SAVE LAYOUT            hotkey= ctrl-S
This saves playfield objects to the appropriate kfc files.
Objects that were created by the 'Layout Menu' will be saved to the 
file:
LayoutParams.kfc

Objects that were created by the 'Design Menu' will be saved to the 
file:
DesignParams.kfc

You will be overwriting the existing local files and no overwrite 
warning is given. Backup your work-in-progress often!

When you want to end a layout session, typically you will first save 
the layout in Haus, then exit the game, then compile or 'build' the 
game to bring the saved layout into the game.  Then, when the game is 
launched, the game engine will now load your new layout objects into 
the game.
NOTE on saving frequency: As a rule of thumb you will want to save 
periodically during a session, not just at the end.  If you make big 
errors with the objects, you can always quit the game, and rebuild the 
most recent save. Or the software infrequently crashes, in which case 
you can recover if you save often.

NOTE on saving and building the game:
Merely Saving a layout to kfc files does not make the saved layout 
appear in the game the next time the game is launched.  A saved layout 
will ONLY appear in the game after TBDGEN has been run!
YOU WILL LOSE WORK IF YOU DO NOT UNDERSTAND AND FOLLOW THIS PROCEDURE! 


NOTE on saving and using the Command Line Switch to Disable everything:
Before launching the game to start a layout editing session where you 
will be saving the layout, you must use the command line switch to 
Disable unit AI, Triggers, Actions, etc.  
If you do not use the Disable switch prior to launching the game, the 
units on the playfield will be running around, trying to attack stuff, 
and the trigger and action objects will be processing.  If you save 
while the units are running around, their current locations will be 
saved, not their original mission-start positions.  After this save is 
built, this will result in units not starting at their start locations, 
but rather wherever they happened to be the instant you did the save.
Saving while Triggers and Actions are processing will most likely 
result in them being saved in a state that is not their start state 
(for example, a spawner Action could have output a dozen Archers onto 
the playfield, Archers that you don't want to be there at mission 
start).
So, to avoid saving a "live" layout, use the switch /d before the path 
of the map you want to load.
For example:
/d /h
where /d is the disable switch
where /h is "haus" switch


EDIT OBJECT blue box     hotkey= E
You must first select an object before you can edit its data.
Right click on an object to select it.
   To de-select hit, press D key or right click on unoccupied ground.
Once selected, click the EDIT box or pressing E brings up a menu 
containing all parameters of that object. 
Typically for units, there are a lot of parameters in there you won't 
care about.
Different object types have different lists of parameters.
If the menu has too many items to show on the screen, the menu can be 
scrolled with the arrow/bar on down the right side.
To edit a parameter, right click on the field.  The cursor will now be 
in the highlighted/selected field.  Use the Backspace key to delete any 
data that is in that field, then type in the new data.  Press ENTER, or 
click the Done Box when done.

EDITING the Player number has special considerations.
Usually this is the first field in an object's parameters.
The Player # is typically used to set a unit to friend or foe.  
Usually:
Player 0 is used for decor objects.
Player 1 is for the user's units (the player's guys)
Player 2 is for the enemy units.
Depending on the game you are working on, there might be special uses 
for # 3, 4, etc.
If one of your guys is attacking your other guys, it's because you 
inadvertently set him to Player 2.
Haus remembers the last Player # you set, and displays it at the top of 
the screen above the blue boxes.  
EVERY OBJECT YOU CREATE AND LAY DOWN WILL AUTOMATICALLY HAVE ITS PLAYER 
# SET TO THE PLAYER # SHOWN ON THE TOP OF THE SCREEN.  This is so you 
can lay down a bunch of enemy units, and they will all be set to Player 
2, so you don't have to edit each individually.  If you want to put 
down some Player 1's next, lay down one unit, then edit its Player 
parameter to 1, and from then on all new units will be Player 1.


CLONE OBJECT blue box
This feature is not fully implemented, use at your own risk!

REPOSITIONING an object in Haus.
Left click on an object to select it.
   To de-select hit, press D key or Left click on unoccupied ground.
You can move the object by Right clicking on the spot to move it to.
Hold down CTRL and use mouse to rotate it.
Hold down ALT and use mouse to pitch it (this is used rarely by 
designers).



HAUS KEYBOARD COMMANDS  ----------------------------------------------

H	Enter Haus when the game is running normally.
      Press H again to Exit Haus while Haus is running and resume game.

D    De-select current selected object
     Or Get rid of Create cursor, and get back to default crosshair cursor.

ARROW KEYS    Scroll playfield

CTRL + mouse  Rotate selected object.
ALT + mouse   Pitch selected object (this is used rarely by designers

Keypad Zero, 2    Pitch camera up/down
Keypad 7,9        Orbit camera
Keypad (minus)  (plus)   Zoom Camera

ESC	If a CANCEL box is present (like in Add Design menu), ESC key is 
same as clicking 'Cancel' 

ENTER  If a DONE box is present (like in an object's parameter list) , 
ENTER key is same as clicking 'Done'

E    Edit selected object.
1    Bring up Add Template menu
2    Bring up Add Layout menu
3    Bring up Add Design Menu

CTRL-S    Save layout to kfc files.

SPECIAL KEY SEQUENCE TO DISPLAY PLAYFIELD COLLISION:
(you don't have to be in Haus to do this)
Press Scroll-Lock  (no other keys or mouse will work except:)
Press CTRL-F1 to toggle visual indication of the map's collision.
Press Scroll-Lock to get out of this mode.

HAUS END --------------------------------------------------- */ 


/* 
TRIGGER and ACTION OVERVIEW

Trigger and Action objects are text structures you'll copy from 
'templates' (listed below) and paste into HandLayout.kfc .  There you 
will edit their parameters with a text editor to make them behave the 
way you want.

Here is a bare-bones example of what a trigger looks like (there is 
much more on how to use Triggers below):
*/
LayoutParams     LABEL_of_this_Trigger    GTriggerTimer
{
    float Time               = 100.0;    //how many seconds timer will countdown

    CCRC32 ParentList[0]    = DoAmbush;  //label of action to execute
    char *pText             = "Time remaining:  %d:%.2d";		
                                         // optional countdown on screen
			
    float Locator.Position.X = 100;	     //position of optional countdown text
    float Locator.Position.Y = 100;

    char *pTextTriggerOn    = "TimerHasFinishedCountingDown"; // optional text to top of screen
}
/*
Where:
LayoutParams is a system identifier specifying the type of data this 
is.
LABEL_of_this_Trigger is the unique Label the layout designer names 
this instance of this Trigger type.
GTriggerTimer is the object type, i.e., a Trigger that has a timer 
functionality.

NOTE: The object's parameters are enclosed in brackets { }.  This is 
VERY IMPORTANT, don't miss both of them when you copy a layout object 
from a template.
NOTE: The semicolon ';' at the end of each line is also very important. 
A script will not build without them.


TRIGGER ---------
A Trigger looks for a certain condition to occur during gameplay, such 
as 'Have 100 seconds elapsed?' (as in the timer above), or 'Has the 
player killed all enemy units?'  
(The Trigger type that looks for this particular condition is called 
'GTriggerDeathAll')

Different Triggers looks for different conditions.
When a Trigger's condition is met, it changes its state from False to 
True.
When a Trigger goes True, all Actions linked to it are executed.  
A Trigger by itself does not 'do' anything other than look for a 
condition and change its True/False state (and optionally print text 
to the screen).


ACTION -----------
An Action is an object that does something during gameplay, such as 
make the player Win a mission.  (This Action type, that Wins the 
player, is called 'GActionWin')
The Action will not do anything until the Trigger (or Triggers, see 
notes on multiple Triggers below) it is linked to goes True.

So, using the above examples, if a GActionWin is linked to a 
GTriggerDeathAll, when the player kills all enemy units, the player 
will Win the mission. 


HOW TO LINK AN ACTION TO A TRIGGER ---------------
You link a Trigger to an Action with the Trigger's parameter of

   CCRC32 ParentList[0] = ActionToDo;

where " ActionToDo" is the Label of the Action you want to happen when 
the Trigger goes True.

The Trigger's ParentList is where all linking of Trigger and Actions is 
done. 
There is nothing in the Action, when you look at it by itself, that 
tells you which Trigger(s) the Action is linked to.  This makes 
commenting your scripts very important, in addition to naming the 
labels of Triggers and Actions with something meaningful and 
descriptive.


EXAMPLE:
This boneheaded example shows how to set up a very simple Trigger and 
Action.
When the Timer counts down its Seconds, it will execute its one Action.
So, after 30 seconds, the player will Win the mission.

*/
LayoutParams     ExampleOfTimerTrigger    GTriggerTimer
{
    float Time               = 30.0;    //how many seconds timer will last

    CCRC32 ParentList[0]    = ExampleOfWinAction;  //label of action to execute
}

LayoutParams   ExampleOfWinAction  GActionWin
{
	int bStartActive		= 1;
	char *pTextTriggerOn	= "MISSION SUCCESSFUL\nNew Record Time!";
        id ActionWinSoundId     = WinSound;
}
/*
Side NOTE: The code '\n' is used to insert a carriage return (new line) 
into a text string.


MULTIPLE ACTIONS LINKED TO 1 TRIGGER   --------------------------------
--
A single Trigger may be linked to up to 6 multiple Actions.
When the Trigger goes True, all the Actions linked to it will execute 
simultaneously.
Thus, the ParentList within a Trigger has 6 'slots' that look like 
this:

   CCRC32 ParentList[0] = ActionToDo_MarkMiniMapInEast;
   CCRC32 ParentList[1] = ActionToDo_MarkMiniMapInWest;
   CCRC32 ParentList[2] = ActionToDo_MarkMiniMapInNorth;
   CCRC32 ParentList[3] = ActionToDo_MarkMiniMapInSouth;
   CCRC32 ParentList[4] = NULL;
   CCRC32 ParentList[5] = NULL;

Assuming you've defined the Actions and labeled them with the labels 
entered into the ParentList,
when this Trigger goes True, 4 Actions will execute, each placing a 
marker on the player's minimap.
Note that slot [4] and [5] are made to be empty (the default) by having 
the label NULL in its parameter field.


'AND' --  MULTIPLE TRIGGERS LINKED TO 1 ACTION  --------------------
A single Action may be linked to multiple Triggers.
If you link multiple Triggers to a single Action, ALL Triggers must be 
True at the same time for the Action to execute.
This is 'AND' logic (Trigger1 AND Trigger2 AND Trigger3 must be True 
for Action to execute)

To Link multiple Triggers to one action, you set a 'ParentList' 
parameter in each of the Triggers' to point to the label of the single 
Action.


'OR' GOrTrigger  --  MULTIPLE TRIGGERS LINKED TO 1 ACTION  ------------
--------
There is an GOrTrigger that allows you to make an Action(s) execute if 
ONE of MANY Triggers go True.
This is 'OR' logic (Trigger1 OR Trigger2 OR Trigger3 only have to be 
True for the single Action to execute)

To set up an OR function, you set a ParentList parameter in the 
multiple Triggers to have the GOrTrigger as their parent Action.
And in turn you set the GOrTrigger's ParentList parameter to contain 
the single Action's label.

LayoutParams OrExampleTrigger GOrTrigger
{
    CCRC32 ParentList[0]  = ThePlayerWins;   //label of Action(s) to execute 

    char *pTextTriggerOn  = NULL;  //OPTIONAL text when trigger is TRUE
    char *pTextTriggerOff = NULL;  //OPTIONAL text when trigger is FALSE
}


ALL TRIGGERS CAN DISPLAY TEXT MESSAGES   ------------------------
If you want any Trigger to display text on the player's screen, there 
are two parameter fields you can use:
*/    
    char *pTextTriggerOn    = "I am True";    //OPTIONAL text displayed if trigger is TRUE

    char *pTextTriggerOff    = "I am False";  //OPTIONAL text displayed if trigger is FALSE
/*
Side NOTE: The code '\n' is used to insert a carriage return (new line) 
into a text string.


INVERT A TRIGGER'S TRUE/FALSE STATE     -------------------------------
------
Up until now, we've been talking about a Trigger executing an Action 
when it goes True.  There will be times when you want a Trigger to 
execute an Action when the Trigger is Not-True (i.e., when it is 
FALSE).

For example, we have a Population Trigger that normally goes True when 
a certain item(s) gets near it.  If you want the Population Trigger to 
execute its Actions when an item is NOT near it (like when the player 
takes the Holy Cross away from the Altar), you use the 'bInverted' 
parameter.

The default value for bInverted is 0 (zero), meaning the Trigger is not 
inverted (it executes Actions when it is TRUE).
To make the Trigger executes Actions when it goes FALSE, set bInverted 
to 1:

    int bInverted = 1;



HOW TO TURN OFF A TRIGGER (stop a Trigger from processing)
Sometimes you'll want a Trigger to stop looking for the condition it's 
looking for.  
For example, say you want to Trigger an ambush only the first time the 
player enters a certain narrow passage.  Normally the Population 
Trigger will execute its Actions (the ambush) every time the player 
goes thru the passage.
To make the Trigger only execute its Actions once, set bSelfDestruct to 
1:

    int bSelfDestruct = 1;      //1=change False/True state only once


HOW TO TURN OFF A TRIGGER OR ACTION WITH ANOTHER TRIGGER
For example, say you want to turn off a Tent (to stop it from spawning 
enemy units when a timer times out).

In the Trigger/Action that you want to turn off, fill in this parameter 
with the label of the Trigger that, when it goes True, it will turn off 
this Trigger/Action:

    CCRC32 ShutOffTrigger    = TriggerThatTurnsOffThisTrigger;        

Where 'TriggerThatTurnsOffThisTrigger' is the label of a Trigger.

NOTE: Be aware that whatever the trigger/action's state is when it is 
turned off, it will stay in that state.


TO CHANGE HOW OFTEN A TRIGGER CHECKS FOR ITS CONDITION
Some Triggers can be processing hogs, such as a Population Trigger that 
is (example) constantly looking at the whole map to see how many 
Archers there are.
This might be important where frame rate is a key consideration, such 
as a PS2 game.
To alter how much time a Trigger waits before checking for the 
condition again, set this:

    float CheckFrequency    =     10.0    // number of seconds 
                            


///////////////////////////////////////////////
GOAL and WIN Actions  
Every mission must have at least 1 way for the player to Win it.

One or more Triggers are used to look for a mission's particular win 
condition(s).
What the player has to do to win a particular mission is described in 
the game  design.  It's from the design doc the layout designer figures 
out what Trigger(s) will be needed to satisfy (or execute) the Goal Action.
The Triggers link to the GGoalAction.

When the player pauses the game, the 'Pause Menu' is displayed that 
shows the player what the mission objectives are.

The GGoalAction puts the actual text in the Pause Menu via 
the *pPauseText field.

GGoalAction also supports chaining multiple sequential Goals 


/* ////////////////////////////////////////////
//
// LOSE a Mission
Every mission must have a way for the player to Lose.

In past games we used a variety of triggers to detect when the 
player has lost because of the more complicated missions 
in 'full production' games, where the player could lose in a 
variety of ways within a single mission.

The lose condition for Crusades was so simple (you lose when 
all your guys are dead) that it was just built into the 
Lose Trigger, and we kept the Lose Action a separate action 
to be flexible and consistent with the system in case we had 
to change the Lose conditions during development.

There's an option to limit the area (Radius) the Trigger is 
looking at to make it consistent with the way the population 
trigger works (actually this is a population trigger that 
has been streamlined for performance sake)
*/ 

LayoutParams LoseTrigger GTriggerLose
{                                                   //trigger goes True when there are no player units left
	float Locator.Position.X = 0.0f;				//position - only useful if we're using Radius
	float Locator.Position.Y = 0.0f;	

	float Radius            = 0.0f;					//radius we're checking against (0.0f means look at entire map)
					                                //if "float Radius" is set to a value, then we only check against that radius
	char *pTextTriggerOn    = "NULL";		//message for when this trigger goes off

	CCRC32 ParentList[0]	= LOSE_Mission01;    // action to execute
}

LayoutParams  LOSE_Mission01 GActionLose
{
	int bStartActive		= 1;    // Action is ready (on) at mission start
	char *pTextTriggerOn	= "Thy Crusade hath FAILED!\nAll your men are DEAD!";
        id ActionLoseSoundId     = LoseSound;
}


/* 
// RUSH Action
When executed, GActionRush makes all the units of the 
set PlayerNumber forget what they are doing and attack 
the player's units, no matter what.
*/ 

LayoutParams LABEL GActionRush
{
	int PlayerNumber        = 2;    // player # that will rush player1
}


/*
GActionMarker
When executed, this Action places a box, or marker, on the minimap.
There is also an option to put a marker on the playfield itself (bShowOnGround) 
*/

LayoutParams    DrawMarker    GActionMarker
{
    int bStartActive    = 0;    // set to 1 if you want marker to be there at mission start

    float Locator.Position.X = 10.0;    // XY coordinates of spot on playfield map
    float Locator.Position.Y = 10.0;   
    
    CPresetFillData *pOwner = TEST_WEST_ARCHER;	//Label of a moving object to mark on minimap
                                                // NULL is default
    int bShowOnGround  = 0;    //1= also puts marker on playfield
}



////  THE DESCRIPTIVE TEXT BEFORE THE MISSION START
LayoutParams GBriefingScreen 
{
	embedded = ObjectiveText;
}

EmbeddedParams ObjectiveText GMenuTextPage 
{
    float IdleTextColor.Red        =0.82;
    float IdleTextColor.Green      =0.82;
    float IdleTextColor.Blue       =0.82;

    float FocusedTextColor.Red     =0.6;
    float FocusedTextColor.Green   =0.6;
    float FocusedTextColor.Blue    =1.0;

    float DisabledTextColor.Red    =0.6;
    float DisabledTextColor.Green  =0.6;
    float DisabledTextColor.Blue   =0.6

    float Size.X = 275
    float Size.Y = 375
	float TextPos.X = 45;
	float TextPos.Y = 35;
	CFont *pFont = TheFont;
    char *pText = "PUT_TEXT_HERE";
}
// Mision Start Text End


// DEATH ALL
// Goes True when all   'PlayerNumber' are dead

LayoutParams TriggerKillAllEnemies GTriggerDeathAll
{
	int PlayerNumber    = 2;					//who all we're looking to be killed
	int RushLimiter     = 10;					//how many units before the rest of these units rush
	float RushDelay     = 3.0;					//how long after the start of the game, before we're allowed to rush
	float Radius        = 0.0;					//distance from this object we're checking (area that we're checking)
                                                // 0=whole world
	CCRC32 ParentList[0] = GoalKillAllWesterners;

	char *pTextTriggerOn = NULL;
}


// POPULATION TRIGGER
// Goes True when the parametized conditions are met
// The way it's set below, it looks for a single player unit to get
// with 5 meters of map position 25,25;  When a player unit gets there,
// it will print to the screen 'YouAreHere' 
LayoutParams PopTrigger GTriggerPopulation
{   
    int bCountTent              = 0;            // 1 = count Tents;  0=default DoNOT count Tents
    int bInverted = 0;                          // 1=to invert the Truth result 
    
    float Locator.Position.X    = 25;			//where we're looking at
	float Locator.Position.Y    = 25;		

	int PlayerNumber            = 1;		   	//the player number we're looking for	
	float Radius                = 5.0;			//the radius we're looking within (use 0.0  for whole map)
	
    CPresetFillData *pOwner     = NULL;			//label of the object if we're tracking down an object
	
    int CountLimit              = 1;			//the number we want within the radius

	CCRC32 ParentList[0] = Some_BIG_Action;          //

	char *pTextTriggerOn        = "YouAreHere";
}


// DEATH TRIGGER - GTriggerDeath
// look for the death of a specific thing

LayoutParams TriggerKillAchilles GTriggerDeath
{
	CPresetFillData *pOwner = Achilles;		//label of who we're looking at

	char *pTextTriggerOn = "Achilles is dead!";	//something to print out when this trigger turns on

	CCRC32 ParentList[0] = GoalKillAchilles;	//action I'm tied to
}


////////////////////////////////////////////
// SPAWNERS
//
// Spawners are now broken up into two parts:
// 1. Objects that can spawn stuff (Tents in this case)
// 2. GSpawnerData objects which control the spawn paramaters


// Example spawner:

// Laid out in DesignParams.kfc are normal player2 tents, but some extra data is added:

/* === GTentTrojanBarracks_00E1E694_3FB4076C === */

LayoutParams GTentTrojanBarracks15 GTentTrojanBarracks  // It's a normal tent
{                                                       //
	Player = 2;                                         // Player 2 ONLY for spawning
    float Locator.Position.X = 116.226860;              // Position
    float Locator.Position.Y = 159.369446;              // Position...
    float Locator.Position.Z = 3.812504;                // Position...
    int TrackId = 1;                                    // Used for moving on waypoints, otherwise ignored
    CCRC32 SpawnerID = AttackWaveSpawner1;              // This must match what it's called in Handlayout
}


// In handlayout you add custom GSpawnerData objects which control what gets spawned and when.
// NOTE: This is the BEST PART - Many tents can be tied to the same SpawnerData,
// but they still function independently! So setup a nice spawner config ONCE, and have lots of tents
// use it!

// NOTE: You do not HAVE to use all these values, they are simply all listed here for documentation.
// Most spawners will not use nearly this many values!

// - Spawns waves of guys to attack the player
LayoutParams AttackWaveSpawner1 GSpawnerData   // The name of the Spawner, which the Tent refers to
{                                              //
    tbdlabel SpawnerID;                        // This must be here for it to work
                                               //
    float Locator.Position.X = 5;              // Position (has no meaning though, spawning is from the Tent position)
    float Locator.Position.Y = 5;              // Position...
    float Locator.Position.Z = 5;              // Position...
    float Spawn.StartTime    = 5.0;            // How many seconds after the level starts before it begins spawning
    float Spawn.EnablePos.X  = 0;              // Scans this position for enemies which triggers off
    float Spawn.EnablePos.Y  = 0;              //      the start of this spawner (relative to actual Tent's position)
    float Spawn.EnableRadius = 15;             // 0 means no enabling needed; scan radius otherwise
    int Spawn.bEnableDisplacement = 1;         // 1 - EnablePos is a displacement
    int Spawn.bEnableIdle =1;                  // Spawner will return to dormant state if player 1 leaves the enable radius
    float Spawn.MaxPopThreshold = 60;          // If max population for player 2 is hit, wait this long and just send what you have
    float Spawn.BuildTimeOverride = 1;         // override the normal build time with this time
    float Spawn.RoamPos.X;                     // center point of the roaming area
    float Spawn.RoamPos.Y;                     // 
    float Spawn.RoamRadius;                    // the area size in which to roam
    int Spawn.bRoamDisplacement =1;            // 1- RoamPos is a displacement from the tent
    float Spawn.RoamExpiration = 60;           // When to stop roaming and proceed with the Command (its given CommandType) 
    int Spawn.WaveCountPerRank = 3;            // How many "groups" are sent out before rank of spawned guys increases
    int Spawn.SelfDestructCountLimit = 0;      // maximum number of spawns before I quit  (0 means never quit)
       
    // Note that there are multiple data sets, marked by the [n] at
    // the end of each value name. This allows for one tent to spawn
    // different types of units at different intervals, with different
    // orders, group quantities, etc. Handy!!!!
    
    id Spawn.BuildID[0]        = GUnitTrojanSpearman;   // Type of unit to spawn. MAKE SURE the TENT you tie to this is the
                                                        //      right kind of tent!
    int Spawn.Quantity[0]       = 3;                    // How many guys to spawn in thise group. 
                                                        //     After this amount, dataset [+1] is used
    id Spawn.CommandType[0]    = Waypoint;              // What this groups orders will be. In this case, they will follow 
                                                        //      the waypoint route defined by the actual tent
                                                        //      The full list of possible options is:
                                                        //      Closest;              // nearest enemy unit                               
                                                        //      ClosestTent          // nearest enemy tent                                
                                                        //      ClosestFriendTower   // nearest friendly held tower (village)             
                                                        //      ClosestEnemyTower    // nearest enemy held tower (village)                
                                                        //      ClosestTower         // nearest tower (village)                           
                                                        //      Waypoint             // waypoint route (trackID is set on the tent itself)
    float Spawn.Frequency[0]      = 15;                 // How often a unit is spawned
    float Spawn.TimeDeviation[0]  = 5.0;                // Used to randomize spawn time, in this case up to 5 seconds + or -
    

    // This is the second dataset for this spawner. Since it's the last one,
    // it will go back to the first once this group is spawned.
    
    id Spawn.BuildID[1]        = GUnitTrojanSwordsman;  // Type of unit to spawn.
    int Spawn.Quantity[1]       = 4;                    // How many guys to spawn in thise group.
    id Spawn.CommandType[1]    = NearestTent;           // Orders for this group, in this case attack nearest player 1 tent
    float Spawn.Frequency[1]      = 5;                  // How often a unit is spawned                                      
    float Spawn.TimeDeviation[1]  = 3.0;                // Used to randomize spawn time, in this case up to 3 seconds + or -

    // Note: you can have up to 5 datasets per Spawner (0 through 4)
}


///////////////////////////////////////////////////////////////
// Example of a real spawner from "Battle for Troy"
///////////////////////////////////////////////////////////////

LayoutParams Siege1 GSpawnerData  // Spawns waves of Swordsmen and Spearmen to attack closest enemy
{
        Player = 2;
        tbdlabel SpawnerID;                                 // This must be here for it to work
        float Locator.Position.X = 5;
        float Locator.Position.Y = 5;
        float Locator.Position.Z = 5;
        int SpawnerID = 1;
        float   Spawn.StartTime         = 1.0;                   // Start 1 second into level
        
        // Wave 1
        id      Spawn.BuildID[0]        = GUnitTrojanSwordsman;  // First "group" is Swordsmen
        int     Spawn.Quantity[0]       = 3;                     // Spawn 3 guys for this group
        id      Spawn.CommandType[0]    = Closest;               // Going to attack closest enemy
        float   Spawn.Frequency[0]      = 20.0;                  // Take 20 seconds to spawn
        float   Spawn.TimeDeviation[0]  = 10.0;                  // Randomly deviate by 10 seconds

        // Wave 2
        id      Spawn.BuildID[1]        = GUnitTrojanSpearman;   // Now some spearmen    
        int     Spawn.Quantity[1]       = 4;                     // Spawn 4 guys for this group    
        id      Spawn.CommandType[1]    = Closest;               // Going to attack closest enemy 
        float   Spawn.Frequency[1]      = 60;                    // Take 60 seconds to spawn      
        float   Spawn.TimeDeviation[1]  = 5.0;                   // Randomly deviate by 5 seconds
}


// Now you would just layout a player 2 Trojan Barracks Tent and set its SpawnerID to "Siege1".


/////////////////////////////////////////////////////////////////
// SPAWN SKELETONS - GActionSpawn
// Example of a Skeleton Generator as seen in many of the "Ruins"
// missions in Battle for Troy.
// Since skeletons arent made by tents, we needed a special
// object to create them. 
// In this example, we have laid out a Healer to be standing 
// where the skeletons will spawn. This is just for the coolness
// factor, no Healer is required.
/////////////////////////////////////////////////////////////////

//////////////// X29 Y27 ///////////////////
LayoutParams GUnitGreekHealer_00EDFD64_3FFCB76E GUnitGreekHealer
{
	Player = 2;
	float Locator.Position.X = 29.479162;
	float Locator.Position.Y = 27.930708;
	float Locator.Position.Z = 6.800000;
	float Locator.Rotation.Z = 2.600000;
	DWORD PassibilityIndex = 7;
	DWORD StatsID = 1212098054;
}

// Now we setup a Population Trigger to know when player 1 gets close
LayoutParams TriggerSpawnSkellys_AT_X29Y27 GTriggerPopulation
{
	float Locator.Position.X = 29.479162;
	float Locator.Position.Y = 27.930708;
	int PlayerNumber            = 1;
	float Radius                = 15.0;
        CPresetFillData *pOwner     = NULL;
        int CountLimit              = 1;
        int bInverted		    = 0;
	CCRC32 ParentList[0]        = SpawnSkellys_AT_X29Y27;
	char *pTextTriggerOn        = NULL;
}

// Player 1 is close, so lets spawn some skeletons
LayoutParams SpawnSkellys_AT_X29Y27 GActionSpawn
{
	float Locator.Position.X = 29.479162;
	float Locator.Position.Y = 27.930708;
	int bStartActive	    = 1;
   	int bSelfDestruct 	    = 1;
        int PlayerNumber            = 2;
        id CreationID               = GUnitMaker;
}


---END OF DOCUMENT

