//==============================================================================
// Scn04p2: AI Scenario Script for scenario 4 player 2
//==============================================================================
/*
   AI owner:  Dave Leary
   Scenario owner: Dave Leary

	This AI transports existing units to the mainland.
	  
	The player defends against waves of attacks from the water consisting of
	pirate ships and krakens.  The pirate ships should drop off several waves of
	land attackers (axemen mostly, one wave of slingers and anubites, and one
	scorpion man in the last group of axemen).  Most of the scenario is handled 
	via trigger, but the three landings are handled by a transport plan that is 
	called with	an AI Func (see "attackLauncher" below).
	
	Each wave is triggered by the destruction of the primary boat or kraken from
	the previous wave.

  								*** DIFFICULTY LEVEL NOTES ***

   Easy level - Additional resources provided.  Player starts with four extra
	toxotes.  Attack groups slightly reduced (no anubites).

   Moderate level - Base level.  No modifiers.

   Difficult level - Shore towers and armory removed.

   Nightmare - Shore towers and armory removed.  Many starting toxotes deleted.
	Additional "rearguard" Atlantis towers deleted.  Starting resources seriously
	reduced.

*/
//==============================================================================
// Set Town Location
//==============================================================================
void setTownLocation(void)
{
   //Look for the "Town Location" marker.
   kbSetTownLocation(kbGetBlockPosition("2639"));
}

//==============================================================================
// miscStartup
//==============================================================================
void miscStartup(void)
{
	// Difficulty Level check.
	int difflevel=-1;		
	difflevel=aiGetWorldDifficulty();

   //Startup message(s).
   aiEcho("");
   aiEcho("");
   aiEcho("Scn04P2 AI Start, filename='"+cFilename+"'.");
	aiEcho("Difficulty Level="+difflevel+".");
   //Spit out the map size.
   aiEcho("  Map size is ("+kbGetMapXSize()+", "+kbGetMapZSize()+").");
   //Cheat like a bastard.  Once only, though.
   kbLookAtAllUnitsOnMap();
   //Calculate some areas.
   kbAreaCalculate(1200.0);
   //Set our town location.
   setTownLocation();
	//Reset random seed
	aiRandSetSeed();
   //Allocate all resources to the root escrow.
   kbEscrowAllocateCurrentResources();
}

//==============================================================================
//==============================================================================
// Attack stuff.
//==============================================================================
//==============================================================================
//Shared variables.

int attackerUnitTypeIDSoldier=cUnitTypeAxeman;
int attackerUnitTypeIDTransport=cUnitTypePirateShip;

//=========================================================================================
// Kidd's cool configQuery function: used to create attack routes, etc.  Oooh, lovin' that!
//=========================================================================================
bool configQuery( int queryID = -1, int unitType = -1, int action = -1, int state = -1, int player = -1, vector center = vector(-1,-1,-1), bool sort = false, float radius = -1 )
{
   if ( queryID == -1)
   {
      return(false);
   }

   if (player != -1)
      kbUnitQuerySetPlayerID(queryID, player);
   
   if (unitType != -1)
      kbUnitQuerySetUnitType(queryID, unitType);

   if (action != -1)
      kbUnitQuerySetActionType(queryID, action);

   if (state != -1)
      kbUnitQuerySetState(queryID, state);

   if (center != vector(-1,-1,-1))
   {
      kbUnitQuerySetPosition(queryID, center);
      if (sort == true)
         kbUnitQuerySetAscendingSort(queryID, true);
      if (radius != -1)
         kbUnitQuerySetMaximumDistance(queryID, radius);
   }
   return(true);
}

//=====================================================================================
// Attack Launcher.  This is called from the scenario with an AI Func effect
//=====================================================================================
void attackLauncher(int whichAttack = -1)
{
	int transportPlanID=aiPlanCreate("Transport Group", cPlanTransport);
	// "whichTransport" adds a specific transport to the plans.  Victory conditions, chats, etc.
	// are tied to the concept of the main transport getting whacked.
	int whichTransport=-1;

	// Difficulty Level check.
	int difflevel=-1;		
	difflevel=aiGetWorldDifficulty();

	vector gatherPoint=kbGetBlockPosition("2638");
	vector targetPoint=kbGetBlockPosition("2642");
	vector initialPosition=kbGetBlockPosition("2639");

	int baseID = kbBaseCreate( 2, "mainBase", initialPosition, 50.0);
		
	if (transportPlanID >= 0)
   {
		aiEcho("*** ATTACK LAUNCHER SENDING TRANSPORT ***");
		
		// Different composition depending on which attack.
		switch(whichAttack)
		{	
			case 0:
	      {

				whichTransport = kbGetBlockID("2632");
				aiPlanAddUnitType(transportPlanID, cUnitTypePirateShip, 1, 1, 1);
				aiPlanAddUnitType(transportPlanID, cUnitTypeAxeman, 5, 5, 5);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportTypeID, 0, cUnitTypePirateShip);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportID, 0, whichTransport);
				break;
			}

			case 1:
			{
				whichTransport = kbGetBlockID("2637");
				gatherPoint=kbGetBlockPosition("2640");
				targetPoint=kbGetBlockPosition("2643");

				aiPlanAddUnitType(transportPlanID, cUnitTypePirateShip, 1, 1, 1);
				aiPlanAddUnitType(transportPlanID, cUnitTypeAxeman, 5, 5, 5);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportTypeID, 0, cUnitTypePirateShip);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportID, 0, whichTransport);
				break;
			}

			case 2:
			{
				whichTransport = kbGetBlockID("2633");
				gatherPoint=kbGetBlockPosition("2658");
				targetPoint=kbGetBlockPosition("2641");

				aiPlanAddUnitType(transportPlanID, cUnitTypePirateShip, 1, 1, 1);
				aiPlanAddUnitType(transportPlanID, cUnitTypeAxeman, 6, 6, 6);
				
				if ( difflevel > 0 )
				{
					aiPlanAddUnitType(transportPlanID, cUnitTypeSlinger, 2, 2, 2);
				}

				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportTypeID, 0, cUnitTypePirateShip);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportID, 0, whichTransport);
				break;
			}

			case 3:
			{
				whichTransport = kbGetBlockID("2788");
				gatherPoint=kbGetBlockPosition("2640");
				targetPoint=kbGetBlockPosition("2641");

				aiPlanAddUnitType(transportPlanID, cUnitTypePirateShip, 1, 1, 1);
				aiPlanAddUnitType(transportPlanID, cUnitTypeSlinger, 6, 6, 6);
				
				if ( difflevel > 0 )
				{
					aiPlanAddUnitType(transportPlanID, cUnitTypeAnubite, 2, 2, 2);
				}
				
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportTypeID, 0, cUnitTypePirateShip);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportID, 0, whichTransport);
				break;
			}

			case 4:
			{
				whichTransport = kbGetBlockID("2634");
				gatherPoint=kbGetBlockPosition("2639");
				targetPoint=kbGetBlockPosition("2785");

				aiPlanAddUnitType(transportPlanID, cUnitTypePirateShip, 1, 1, 1);
				aiPlanAddUnitType(transportPlanID, cUnitTypeAxeman, 7, 7, 7);
				aiPlanAddUnitType(transportPlanID, cUnitTypeScorpionMan, 1, 1, 1);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportTypeID, 0, cUnitTypePirateShip);
				aiPlanSetVariableInt(transportPlanID, cTransportPlanTransportID, 0, whichTransport);
				break;
			}
		}

		aiPlanSetVariableBool(transportPlanID, cTransportPlanMaximizeXportMovement, 0, true);
		aiPlanSetVariableVector(transportPlanID, cTransportPlanGatherPoint, 0, gatherPoint);
      aiPlanSetVariableVector(transportPlanID, cTransportPlanTargetPoint, 0, targetPoint);

		// Setting the base.
		aiPlanSetBaseID( transportPlanID, baseID );

		// Don't return when finished.
		aiPlanSetVariableBool(transportPlanID, cTransportPlanReturnWhenDone, 0, false);

		// Initial Position
		aiPlanSetInitialPosition( transportPlanID, initialPosition );
		
		aiPlanAddUnit(transportPlanID, whichTransport);
      aiPlanSetActive(transportPlanID);
   }
}

//==============================================================================
// initAttack: Creates attack routes, etc.
//==============================================================================
/*
void initAttack(int playerID=-1)
{
   //Destroy all previous attacks (if this isn't the player we're already attacking.
   if (playerID != attackPlayerID)
   {
      //Reset the attack player ID.
      attackPlayerID=-1;
      //Destroy any previous attack plan.
      aiPlanDestroy(attackPlan1ID);
      attackPlan1ID=-1;
      aiPlanDestroy(attackPlan2ID);
      attackPlan2ID=-1;
  
      //Destroy our previous attack paths.
      kbPathDestroy(attackPath1ID);
      attackPath1ID=-1;
      kbPathDestroy(attackPath2ID);
      attackPath2ID=-1;

      //Destroy our previous attack routes.
      attackRoute1ID=-1;
      attackRoute2ID=-1;

      //Reset the number of attacks.
      numberAttacks=0;
   }

   //Save the player to attack.
   attackPlayerID=playerID;

   vector gatherPoint=kbGetBlockPosition("3989");
	   
	//Setup attack path 1 - go left
   attackPath1ID=kbPathCreate("Attack Path 1");
   kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3990"));
	kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3991"));
	kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3992"));
   //Create attack route 1.
   attackRoute1ID=kbCreateAttackRouteWithPath("Attack Route 1", gatherPoint, kbGetBlockPosition("3995"));
   
	if (attackRoute1ID >= 0)
      kbAttackRouteAddPath(attackRoute1ID, attackPath1ID);

   //Setup attack path 2 - go right
   attackPath2ID=kbPathCreate("Attack Path 2");
   kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3990"));
	kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3991"));
	kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3993"));
	kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3994"));
   //Create attack route 2.
   attackRoute2ID=kbCreateAttackRouteWithPath("Attack Route 2", gatherPoint, kbGetBlockPosition("3995"));
   
	if (attackRoute2ID >= 0)
      kbAttackRouteAddPath(attackRoute2ID, attackPath2ID);
}
*/

//==============================================================================
// setupAttack
//==============================================================================
/*
bool setupAttack(int playerID=-1)
{
	int randomPath=aiRandInt(2);
   
	//Info.
	aiEcho("Attacking Player "+playerID+".");

   //If the player to attack doesn't match, init the attack.
   if (attackPlayerID != playerID)
   {
      initAttack(playerID);
      if (attackPlayerID < 0)
         return(false);
   }

   //Create an attack plan.
   int newAttackPlanID=aiPlanCreate("Attack Player"+attackPlayerID+" Attempt"+numberAttacks, cPlanAttack);
   if (newAttackPlanID < 0)
      return(false);

   //Target player (required).  This must work.
   if (aiPlanSetVariableInt(newAttackPlanID, cAttackPlanPlayerID, 0, attackPlayerID) == false)
      return(false);

   //Gather point.
	vector gatherPoint=kbGetBlockPosition("3989");

	//Set the target type.  This must work.
   if (aiPlanSetNumberVariableValues(newAttackPlanID, cAttackPlanTargetTypeID, 2, true) == false)
      return(false);

   //Unit types to attack.
   aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
	aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);

   //Attack route.
   if (randomPath == 0)
	{
      aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID);
	}
   else
	{
      aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute2ID);
	}

   //Set the gather point and gather point distance.
   aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPoint);
   aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 10.0);

   //Set up the attack route usage pattern.
   aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRoutePattern, 0, cAttackPlanAttackRoutePatternRandom);
   
	//Add the unit types to the plan.
   aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, attackMinimumGroupSize, attackMaximumGroupSize, attackMaximumGroupSize);
	
   //Set the initial position.
   aiPlanSetInitialPosition(newAttackPlanID, gatherPoint);
   //Plan requires all need units to work (can be false).
   aiPlanSetRequiresAllNeedUnits(newAttackPlanID, true);
   //Activate the plan.
   aiPlanSetActive(newAttackPlanID);

   //Now, save the attack plan ID appropriately.
   aiPlanSetOrphan(attackPlan1ID, true);
   attackPlan1ID=newAttackPlanID;

   //Increment our overall number of attacks.
   numberAttacks++;
}
*/

//==============================================================================
// Attack Generator 1 - Axemen and friends
//==============================================================================
/*
rule attackGenerator1
   minInterval 75
   inactive
   group AttackRules
   runImmediately
{
   //See how many "idle" attack plans we have.  Don't create any more if we have
   //idle plans.
   int numberIdleAttackPlans=aiGetNumberIdlePlans(cPlanAttack);

   if (numberIdleAttackPlans > 0)
      return;

   //If we have enough unassigned military units, create a new attack plan.
   int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID1);
   aiEcho("There are "+numberAvailableUnits+" axemen available for a new attack.");
   
	if (numberAvailableUnits >= attackMinimumGroupSize)
		setupAttack(1);
}
*/


//==============================================================================
// Attack enablers - enable attacks after initial timers expire
//==============================================================================
/*
// Axemen
rule attack1Enabler
   minInterval 240
   active
   group AttackRules
{
   xsEnableRule("attackGenerator1");
   xsDisableSelf();
}
*/

//==============================================================================
// Tech Researching Rules - medium axemen, medium slingers, medium spearmen
//==============================================================================
/*
rule researchMediumAxemen
   minInterval 600
   active
{
   int planID=aiPlanCreate("Medium Axemen research at ten minutes.", cPlanResearch);
   if (planID < 0)
      return;

   aiPlanSetVariableInt(planID, cResearchPlanTechID, 0, cTechMediumAxemen);
   aiPlanSetVariableInt(planID, cResearchPlanBuildingTypeID, 0, cUnitTypeBarracks);
   aiPlanSetActive(planID);
   
	//Done.
   xsDisableSelf();
}
*/

//==============================================================================
// MAIN.
//==============================================================================
void main(void)
{
   //Startup.
   miscStartup();
}
