home *** CD-ROM | disk | FTP | other *** search
Wrap
//============================================================================== // Scn09p2: AI Scenario Script for scenario 9 player 2 //============================================================================== /* AI owner: Dave Leary Scenario owner: Joe "the Golem" Gillum The AI for the enemy (Troy) in scenario 9. Maintains a mixture of units and sends attack groups based on scouts returning to Troy (called from an AI Func). The parameter sent in the AI Func determines composition and size of the attack. Also does some cleanup when the Trojan horse is built, killing maintain plans and deleting existing AI units near the gather points. This doesn't always catch everything (it doesn't handle units currently being trained), so it fires another function to delete units again. A little hack-er-ific, but it works. */ //============================================================================== // Set Town Location //============================================================================== void setTownLocation(void) { //Look for the "Town Location" marker. kbSetTownLocation(kbGetBlockPosition("3031")); } //============================================================================== // miscStartup //============================================================================== void miscStartup(void) { // Difficulty Level check. int difflevel=-1; difflevel=aiGetWorldDifficulty(); //Startup message(s). aiEcho(""); aiEcho(""); aiEcho("Scn09P2 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 by setting percentage of military/economy to 0. kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0 ); kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0 ); //Allocate all resources to the root escrow. kbEscrowAllocateCurrentResources(); // Drop the AI attack response distance for this player to 3 meters. We'll up it later. aiSetAttackResponseDistance(0.0); } //============================================================================== //============================================================================== // Attack stuff. //============================================================================== //============================================================================== //Shared variables. int numberAttacks=0; int attackPlayerID=-1; // Maintain plans int maintainPlan1ID=-1; int maintainPlan2ID=-1; int maintainPlan3ID=-1; int maintainPlan4ID=-1; int maintainPlan5ID=-1; //Attack 1 vars. int attackPlan1ID=-1; //Attack 2 vars. int attackPlan2ID=-1; // Route and path vars int attackRoute1ID=-1; int attackPath1ID=-1; int attackRoute2ID=-1; int attackPath2ID=-1; // Unit Types int attackerUnitTypeID1=cUnitTypeToxotes; int attackerUnitTypeID2=cUnitTypeHypaspist; int attackerUnitTypeID3=cUnitTypeHippikon; int attackerUnitTypeID4=cUnitTypeNemeanLion; int attackerUnitTypeID5=cUnitTypePetrobolos; int attackerUnitTypeID6=cUnitTypeShadeofHades; //========================================================================================= // 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); } //============================================================================== // 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("3031"); //Setup attack path 1 - go left attackPath1ID=kbPathCreate("Attack Path 1"); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3032")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3033")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3034")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3035")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3036")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3037")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3038")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3039")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3040")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3041")); //Create attack route 1. attackRoute1ID=kbCreateAttackRouteWithPath("Attack Route 1", gatherPoint, kbGetBlockPosition("3042")); if (attackRoute1ID >= 0) kbAttackRouteAddPath(attackRoute1ID, attackPath1ID); //Setup attack path 2 - go right attackPath2ID=kbPathCreate("Attack Path 2"); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3043")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3044")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3045")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3046")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3047")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3048")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3049")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("3050")); //Create attack route 2. attackRoute2ID=kbCreateAttackRouteWithPath("Attack Route 2", gatherPoint, kbGetBlockPosition("3051")); if (attackRoute2ID >= 0) kbAttackRouteAddPath(attackRoute2ID, attackPath2ID); } //============================================================================== // setupAttack //============================================================================== bool setupAttack(int playerID=-1, int whichAttack=-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("3031"); //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) { aiEcho("Attack going left."); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID); } else { aiEcho("Attack going right."); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute2ID); } //Set the gather point and gather point distance. aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPoint); aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 20.0); //Set up the attack route usage pattern. aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRoutePattern, 0, cAttackPlanAttackRoutePatternRandom); //Add the unit types to the plan. aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, 6, 6, 6); //Add some extra guys depending on which attack it is. switch(whichAttack) { // Basic case, toxotes plus hypaspists case 0: { aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 2, 2, 2); aiEcho("Attacking with toxotoes only."); break; } // Four hypaspists case 1: { aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 4, 4, 4); break; } // Four hypaspists, two hippikons. Shades of Hades if available. case 2: { aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 4, 4, 4); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID3, 2, 2, 2); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID6, 0, 2, 2); break; } // Everything from case 2, plus two Nemean Lions and a catapult. Shades of Hades if available. case 3: { aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 4, 4, 4); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID3, 2, 2, 2); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID4, 0, 2, 2); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID5, 0, 1, 1); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID6, 0, 2, 2); break; } } //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 Launcher. This is called from the scenario with an AI Func effect // when the player claims his first settlement. //===================================================================================== void attackLauncher(int whichAttack = -1) { aiEcho("*** SCOUT RETURNS - ATTACK LAUNCHER CALLED ***"); aiEcho("*** Attack Parameter: "+whichAttack+" ***"); //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; //Create a new attack plan. int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID1); aiEcho("There are "+numberAvailableUnits+" toxotes available for a new attack."); setupAttack(1, whichAttack); } //***************************************************************************** // horseBuiltCleanup - used to delete the fools near the gather point and // disable a bunch of functions. Called once the Trojan Horse is built. //***************************************************************************** void horseBuiltCleanup(int parameter = -1) { // Destroy existing maintain plans. aiPlanDestroy(maintainPlan1ID); aiPlanDestroy(maintainPlan2ID); aiPlanDestroy(maintainPlan3ID); aiPlanDestroy(maintainPlan4ID); aiPlanDestroy(maintainPlan5ID); int unassigned=0; // Number of unassigned units found by traversing the query results int query=-1; // Query to find the units of unitType within radius of center. int count=-1; // Number of units found by the query. int i=-1; vector center=kbGetBlockPosition("3031"); query = kbUnitQueryCreate("All Player 2 Units Near The Point"); aiEcho("*** ALL UNITS AT GATHER POINT DELETED (in theory) ***"); // Delete all existing military units near the gather point. if (query < 0) return(); configQuery(query, cUnitTypeUnit, -1, cUnitStateAlive, 2, center, true, 40.0); kbUnitQueryResetResults(query); count = kbUnitQueryExecute(query); aiEcho("There are "+count+" units to delete."); for (i=0; <count) { aiTaskUnitDelete(kbUnitQueryGetResult(query, i)); } // Drop the AI attack response distance for this player to 10 meters. aiSetAttackResponseDistance(5.0); } //***************************************************************************** // horseBuiltCleanup2 - we gotta do it again to make sure we're deleting // all the units left over from extra maintain plans. //***************************************************************************** void horseBuiltCleanup2(int parameter = -1) { int unassigned=0; // Number of unassigned units found by traversing the query results int query=-1; // Query to find the units of unitType within radius of center. int count=-1; // Number of units found by the query. int i=-1; vector center=kbGetBlockPosition("3031"); query = kbUnitQueryCreate("All Player 2 Units Near The Point"); aiEcho("*** DOING THE CLEANUP AGAIN ***"); // Delete all existing military units near the gather point. if (query < 0) return(); configQuery(query, cUnitTypeUnit, -1, cUnitStateAlive, 2, center, true, 40.0); kbUnitQueryResetResults(query); count = kbUnitQueryExecute(query); aiEcho("There are "+count+" units to delete."); for (i=0; <count) { aiTaskUnitDelete(kbUnitQueryGetResult(query, i)); } } //============================================================================== // Favor Cheat so he can afford an endless stream of Nemean Lions. //============================================================================== rule favorCheat minInterval 30 active { aiEcho("*** Favor +50 ***"); aiResourceCheat( 2, cResourceFavor, 50.0 ); } //============================================================================== // MAIN. //============================================================================== void main(void) { //Startup. miscStartup(); //Share a common gather point. vector gatherPoint=kbGetBlockPosition("3031"); vector gatherPoint1=kbGetBlockPosition("4887"); vector gatherPoint2=kbGetBlockPosition("4888"); //Create a simple plan to maintain 6 toxotes maintainPlan1ID=aiPlanCreate("Maintain 12 "+kbGetProtoUnitName(attackerUnitTypeID1), cPlanTrain); if (maintainPlan1ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanUnitType, 0, attackerUnitTypeID1); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanNumberToMaintain, 0, 12); //Don't train units faster than every 10 seconds aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 2); //Set a gather point. aiPlanSetVariableVector(maintainPlan1ID, cTrainPlanGatherPoint, 0, gatherPoint); //Activate the plan. aiPlanSetActive(maintainPlan1ID); } //Create a simple plan to maintain 4 hypaspists maintainPlan2ID=aiPlanCreate("Maintain 8 "+kbGetProtoUnitName(attackerUnitTypeID2), cPlanTrain); if (maintainPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanUnitType, 0, attackerUnitTypeID2); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanNumberToMaintain, 0, 8); //Don't train units faster than every 10 seconds aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanFrequency, 0, 2); //Set a gather point. aiPlanSetVariableVector(maintainPlan2ID, cTrainPlanGatherPoint, 0, gatherPoint1); //Activate the plan. aiPlanSetActive(maintainPlan2ID); } //Create a simple plan to maintain 2 hippikons maintainPlan3ID=aiPlanCreate("Maintain 4 "+kbGetProtoUnitName(attackerUnitTypeID3), cPlanTrain); if (maintainPlan3ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanUnitType, 0, attackerUnitTypeID3); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanNumberToMaintain, 0, 4); //Don't train units faster than every 10 seconds aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanFrequency, 0, 2); //Set a gather point. aiPlanSetVariableVector(maintainPlan3ID, cTrainPlanGatherPoint, 0, gatherPoint2); //Activate the plan. aiPlanSetActive(maintainPlan3ID); } //Create a simple plan to maintain 2 Nemean Lions maintainPlan4ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerUnitTypeID4), cPlanTrain); if (maintainPlan4ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanUnitType, 0, attackerUnitTypeID4); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanNumberToMaintain, 0, 2); //Don't train units faster than every 10 seconds aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanFrequency, 0, 2); //Set a gather point. aiPlanSetVariableVector(maintainPlan4ID, cTrainPlanGatherPoint, 0, gatherPoint); //Activate the plan. aiPlanSetActive(maintainPlan4ID); } //Create a simple plan to maintain 2 Petroboli maintainPlan5ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerUnitTypeID5), cPlanTrain); if (maintainPlan5ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanUnitType, 0, attackerUnitTypeID5); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanNumberToMaintain, 0, 2); //Don't train units faster than every 20 seconds aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanFrequency, 0, 5); //Set a gather point. aiPlanSetVariableVector(maintainPlan5ID, cTrainPlanGatherPoint, 0, gatherPoint1); //Activate the plan. aiPlanSetActive(maintainPlan5ID); } }