home *** CD-ROM | disk | FTP | other *** search
Wrap
//============================================================================== // Scn35p2: AI Scenario Script for scenario 35 player 2 //============================================================================== /* AI owner: Dave Leary Scenario owner: Joe "the Golem" Gillum Handles the rearguard forces of Gargarensis in the finale. Creates defend plans of hypaspists and peltasts for the choke points leading to the enemy base. Periodically generates heroes (Atalanta and Polyphemus) and includes them in attack groups. Also sets up a defend plan that includes "one bad titan" so the titan sticks around the "endgame" area. After the HP owns two plenty vaults, an AI Func starts the AI attacking. Attacks are composed of strong myth-centric armies, and choose an attack route based on which fortress was destroyed first. Gargarensis' scary god power actions are handled by scenario triggers. */ //============================================================================== // Set Town Location. //============================================================================== void setTownLocation(void) { //Look for the "Town Location" marker. kbSetTownLocation(kbGetBlockPosition("3989")); } //============================================================================== // miscStartup //============================================================================== void miscStartup(void) { // Difficulty Level check. int difflevel=-1; difflevel=aiGetWorldDifficulty(); //Startup message(s). aiEcho(""); aiEcho(""); aiEcho("Scn35P2 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 kbEscrowAllocateCurrentResources(); } //============================================================================== //============================================================================== // Attack stuff //============================================================================== //============================================================================== //Shared variables. int numberAttacks=0; int attackPlayerID=-1; //TODO: Decide how to rep attack group size. int attackMinimumGroupSize=8; int attackMaximumGroupSize=12; //Attack vars. int attackPlan1ID=-1; int attackPlan2ID=-1; // Unit types. int attackerUnitTypeID1=cUnitTypeHoplite; int attackerUnitTypeID2=cUnitTypeHippikon; int attackerUnitTypeID3=cUnitTypeToxotes; int attackerUnitTypeID4=cUnitTypeHypaspist; int attackerUnitTypeID5=cUnitTypePeltast; int attackerSiegeTypeID1=cUnitTypePetrobolos; int attackerSiegeTypeID2=cUnitTypeHelepolis; int attackerMythTypeID1=cUnitTypeCyclops; int attackerMythTypeID2=cUnitTypeNemeanLion; int attackerMythTypeID3=cUnitTypeColossus; int attackerHeroTypeID1=cUnitTypeHeroGreekAtalanta; int attackerHeroTypeID2=cUnitTypeHeroGreekPolyphemus; // Maintain Plans int maintainPlan1ID=-1; int maintainPlan2ID=-1; int maintainPlan3ID=-1; int maintainPlan4ID=-1; int maintainPlan5ID=-1; int maintainVillagerID=-1; int maintainMythPlan1ID=-1; int maintainMythPlan2ID=-1; int maintainHeroPlan1ID=-1; int maintainHeroPlan2ID=-1; int maintainSiegePlanID=-1; // Route and path vars int attackRoute1ID=-1; int attackPath1ID=-1; int attackRoute2ID=-1; int attackPath2ID=-1; //========================================================================================= // 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 gatherPointEast=kbGetBlockPosition("2442"); vector gatherPointWest=kbGetBlockPosition("2455"); //Setup attack path 1 - go east attackPath1ID=kbPathCreate("Attack Path 1"); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("2443")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("2444")); kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("2445")); //Create attack route 1. attackRoute1ID=kbCreateAttackRouteWithPath("Attack Route 1", gatherPointEast, kbGetBlockPosition("2449")); if (attackRoute1ID >= 0) kbAttackRouteAddPath(attackRoute1ID, attackPath1ID); //Setup attack path 2 - go west attackPath2ID=kbPathCreate("Attack Path 2"); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("2446")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("2447")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("2450")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("2453")); //Create attack route 2. attackRoute2ID=kbCreateAttackRouteWithPath("Attack Route 2", gatherPointWest, kbGetBlockPosition("2454")); if (attackRoute2ID >= 0) kbAttackRouteAddPath(attackRoute2ID, attackPath2ID); } //============================================================================== // setupHumanAttack (human fun) //============================================================================== bool setupHumanAttack(int playerID=-1) { // Difficulty Level check. int difflevel=-1; difflevel=aiGetWorldDifficulty(); 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 points. vector gatherPointEast=kbGetBlockPosition("2442"); vector gatherPointWest=kbGetBlockPosition("2455"); //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 East."); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID); aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPointEast); } else { aiEcho("Attack Going West."); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute2ID); aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPointWest); } //Set the gather point and gather point distance. aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 50.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); if ( difflevel > 0 ) { aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID3, attackMinimumGroupSize, attackMaximumGroupSize, attackMaximumGroupSize); } // Myth units if available...fewer on easy. if ( difflevel > 0 ) { aiPlanAddUnitType(newAttackPlanID, attackerMythTypeID2, 0, 4, 4); aiPlanAddUnitType(newAttackPlanID, attackerMythTypeID3, 0, 2, 2); } else { aiPlanAddUnitType(newAttackPlanID, attackerMythTypeID2, 0, 1, 1); aiPlanAddUnitType(newAttackPlanID, attackerMythTypeID3, 0, 1, 1); } // Both heroes if available, except on easy. if ( difflevel > 0 ) { aiPlanAddUnitType(newAttackPlanID, attackerHeroTypeID1, 0, 1, 1); aiPlanAddUnitType(newAttackPlanID, attackerHeroTypeID2, 0, 1, 1); } // Siege towers if available if ( difflevel > 0 ) { aiPlanAddUnitType(newAttackPlanID, attackerSiegeTypeID2, 0, 2, 2); } else { aiPlanAddUnitType(newAttackPlanID, attackerSiegeTypeID2, 0, 1, 1); } //Set the initial position. if (randomPath == 0) { aiPlanSetInitialPosition(newAttackPlanID, gatherPointEast); } else { aiPlanSetInitialPosition(newAttackPlanID, gatherPointWest); } //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 - Mixed group of human units //============================================================================== rule attackGeneratorHuman minInterval 115 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. // Hoplites are the primary unit. int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID1); aiEcho("There are "+numberAvailableUnits+" hoplites available for a new attack."); if (numberAvailableUnits >= attackMinimumGroupSize) setupHumanAttack(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(); } */ //============================================================================== // Favor cheat - favor every so often. //============================================================================== rule favorCheat minInterval 40 active group AttackRules { // Cheat for favor. That Gargarensis is a bastard. aiResourceCheat( 2, cResourceFavor, 20.0 ); } //============================================================================== // RULE repairBuildings //============================================================================== rule repairBuildings minInterval 10 inactive { int buildingID = kbFindBestBuildingToRepair(kbBaseGetLocation(cMyID, kbBaseGetMainID(cMyID)), 100.0, 1.0, cUnitTypeBuilding); if(buildingID >= 0) { //-- Don't create another plan for the same building. if(aiPlanGetIDByTypeAndVariableType(cPlanRepair, cRepairPlanTargetID, buildingID, true) >= 0) return; //Create the plan. static int num=0; num = num + 1; string planName="Repair_"+num; int planID=aiPlanCreate(planName, cPlanRepair); if (planID < 0) return; aiPlanSetDesiredPriority(planID, 30); aiPlanSetVariableInt(planID, cRepairPlanTargetID, 0, buildingID); aiPlanAddUnitType(planID, kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionBuilder, 0), 0, 3, 3); aiPlanSetActive(planID); } } //===================================================================================== // Player has Plenties! Once the player has destroyed a fortress, this AI FUNC // fires and the Temple Mount AI kicks into high gear and starts attacking. // // Don't ask why this is called what it is. It's a long story. :) // // Also forward-builds walls and adds a couple of towers to the rear. // DAL: This may end up being a difficulty-dependent thing. //===================================================================================== void playerHasPlenties(int scriptCall = -1) { aiEcho("*** PLAYER 2: HP has destroyed a forward fortress ***"); // Start launching attacks. xsEnableRule("attackGeneratorHuman"); // Start maintaining myth units. vector gatherPointTemple=kbGetBlockPosition("2458"); vector gatherPointSiege=kbGetBlockPosition("2512"); vector Wall1Point1=kbGetBlockPosition("2916"); vector Wall1Point2=kbGetBlockPosition("2917"); vector Wall2Point1=kbGetBlockPosition("2918"); vector Wall2Point2=kbGetBlockPosition("2919"); vector TowerPoint1=kbGetBlockPosition("2918"); vector TowerPoint2=kbGetBlockPosition("2919"); //Maintain Nemean Lions (4) maintainMythPlan1ID=aiPlanCreate("Maintain 4 "+kbGetProtoUnitName(attackerMythTypeID2), cPlanTrain); if (maintainMythPlan1ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainMythPlan1ID, cTrainPlanUnitType, 0, attackerMythTypeID2); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainMythPlan1ID, cTrainPlanNumberToMaintain, 0, 4); //Don't train units too fast aiPlanSetVariableInt(maintainMythPlan1ID, cTrainPlanFrequency, 0, 90); //Set a gather point. aiPlanSetVariableVector(maintainMythPlan1ID, cTrainPlanGatherPoint, 0, gatherPointTemple); //Activate the plan. aiPlanSetActive(maintainMythPlan1ID); } //Maintain Colossi (2) maintainMythPlan2ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerMythTypeID3), cPlanTrain); if (maintainMythPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainMythPlan2ID, cTrainPlanUnitType, 0, attackerMythTypeID3); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainMythPlan2ID, cTrainPlanNumberToMaintain, 0, 2); //Don't train units too fast aiPlanSetVariableInt(maintainMythPlan2ID, cTrainPlanFrequency, 0, 70); //Set a gather point. aiPlanSetVariableVector(maintainMythPlan2ID, cTrainPlanGatherPoint, 0, gatherPointTemple); //Activate the plan. aiPlanSetActive(maintainMythPlan2ID); } //Maintain Siege Things (2) maintainSiegePlanID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerSiegeTypeID2), cPlanTrain); if (maintainMythPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainSiegePlanID, cTrainPlanUnitType, 0, attackerSiegeTypeID2); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainSiegePlanID, cTrainPlanNumberToMaintain, 0, 2); //Don't train units too fast aiPlanSetVariableInt(maintainSiegePlanID, cTrainPlanFrequency, 0, 120); //Set a gather point. aiPlanSetVariableVector(maintainSiegePlanID, cTrainPlanGatherPoint, 0, gatherPointSiege); //Activate the plan. aiPlanSetActive(maintainSiegePlanID); } // Tasty Villager-on-Villager action. Mmm, lovin' that. // Build a wall. Or two. // DAL - removed for now. /* aiWallFromAToB("Build Wall 1", Wall1Point1, Wall1Point2, 1, 1, 1, cRootEscrowID, 1 ); aiWallFromAToB("Build Wall 2", Wall2Point1, Wall2Point2, 1, 1, 1, cRootEscrowID, 1 ); */ //-- Build a tower /* int buildTower1 = aiPlanCreate("Build Tower 1", cPlanBuild); if(buildTower1 >= 0) { //BP Type and Priority. aiPlanSetVariableInt(buildTower1, cBuildPlanBuildingTypeID, 0, cUnitTypeTower); aiPlanSetDesiredPriority(buildTower1, 40); aiPlanSetVariableVector(buildTower1, cBuildPlanCenterPosition, 0, TowerPoint1); aiPlanSetVariableFloat(buildTower1, cBuildPlanCenterPositionDistance, 0, 10); aiPlanAddUnitType(buildTower1, kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionBuilder, 0), 1, 1, 1); aiPlanSetEscrowID(buildTower1, cRootEscrowID); aiPlanSetActive(buildTower1); } //-- Build another tower int buildTower2 = aiPlanCreate("Build Tower 2", cPlanBuild); if(buildTower2 >= 0) { //BP Type and Priority. aiPlanSetVariableInt(buildTower2, cBuildPlanBuildingTypeID, 0, cUnitTypeTower); aiPlanSetDesiredPriority(buildTower2, 40); aiPlanSetVariableVector(buildTower2, cBuildPlanCenterPosition, 0, TowerPoint2); aiPlanSetVariableFloat(buildTower2, cBuildPlanCenterPositionDistance, 0, 10); aiPlanAddUnitType(buildTower2, kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionBuilder, 0), 1, 1, 1); aiPlanSetEscrowID(buildTower2, cRootEscrowID); aiPlanSetActive(buildTower2); } */ // Repair stuff with all the villagers once you're done building stuff (in theory). xsEnableRule("repairBuildings"); } //============================================================================== // Maintain stuff - separated out for sanity's sake. //============================================================================== void maintainStuff(void) { //Share a common gather point. vector gatherPointAcademy=kbGetBlockPosition("2456"); vector gatherPointArcheryRange=kbGetBlockPosition("2457"); vector gatherPointTemple=kbGetBlockPosition("2458"); vector gatherPointHero=kbGetBlockPosition("2512"); vector gatherPointVillager=kbGetBlockPosition("2922"); //Share the number to maintain. int numberToMaintain=attackMinimumGroupSize*2; //Maintain hoplites (base #) maintainPlan1ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID1), cPlanTrain); if (maintainPlan1ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanUnitType, 0, attackerUnitTypeID1); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanNumberToMaintain, 0, numberToMaintain); //Don't train units too fast aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 30); //Set a gather point. aiPlanSetVariableVector(maintainPlan1ID, cTrainPlanGatherPoint, 0, gatherPointAcademy); //Activate the plan. aiPlanSetActive(maintainPlan1ID); } //Maintain toxotes (base #) maintainPlan3ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID3), cPlanTrain); if (maintainPlan3ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanUnitType, 0, attackerUnitTypeID3); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanNumberToMaintain, 0, numberToMaintain); //Don't train units too fast aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanFrequency, 0, 35); //Set a gather point. aiPlanSetVariableVector(maintainPlan3ID, cTrainPlanGatherPoint, 0, gatherPointArcheryRange); //Activate the plan. aiPlanSetActive(maintainPlan3ID); } //Maintain hypaspists(12) maintainPlan4ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID4), cPlanTrain); if (maintainPlan4ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanUnitType, 0, attackerUnitTypeID4); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanNumberToMaintain, 0, 12); //Don't train units too fast aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanFrequency, 0, 45); //Set a gather point. aiPlanSetVariableVector(maintainPlan4ID, cTrainPlanGatherPoint, 0, gatherPointAcademy); //Activate the plan. aiPlanSetActive(maintainPlan4ID); } //Maintain peltasts(8) maintainPlan5ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID4), cPlanTrain); if (maintainPlan5ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanUnitType, 0, attackerUnitTypeID5); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanNumberToMaintain, 0, 8); //Don't train units too fast aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanFrequency, 0, 55); //Set a gather point. aiPlanSetVariableVector(maintainPlan5ID, cTrainPlanGatherPoint, 0, gatherPointArcheryRange); //Activate the plan. aiPlanSetActive(maintainPlan5ID); } // Hero Maintain Plans maintainHeroPlan1ID=aiPlanCreate("Maintain "+kbGetProtoUnitName(attackerHeroTypeID1), cPlanTrain); if (maintainHeroPlan1ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainHeroPlan1ID, cTrainPlanUnitType, 0, attackerHeroTypeID1); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainHeroPlan1ID, cTrainPlanNumberToMaintain, 0, 1); //Don't train units too fast aiPlanSetVariableInt(maintainHeroPlan1ID, cTrainPlanFrequency, 0, 105); //Set a gather point. aiPlanSetVariableVector(maintainHeroPlan1ID, cTrainPlanGatherPoint, 0, gatherPointHero); //Activate the plan. aiPlanSetActive(maintainHeroPlan1ID); } maintainHeroPlan2ID=aiPlanCreate("Maintain "+kbGetProtoUnitName(attackerHeroTypeID2), cPlanTrain); if (maintainHeroPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainHeroPlan2ID, cTrainPlanUnitType, 0, attackerHeroTypeID2); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainHeroPlan2ID, cTrainPlanNumberToMaintain, 0, 1); //Don't train units too fast aiPlanSetVariableInt(maintainHeroPlan2ID, cTrainPlanFrequency, 0, 140); //Set a gather point. aiPlanSetVariableVector(maintainHeroPlan2ID, cTrainPlanGatherPoint, 0, gatherPointHero); //Activate the plan. aiPlanSetActive(maintainHeroPlan2ID); } maintainVillagerID=aiPlanCreate("Maintain "+kbGetProtoUnitName(cUnitTypeVillagerGreek), cPlanTrain); if (maintainHeroPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainVillagerID, cTrainPlanUnitType, 0, cUnitTypeVillagerGreek); //You can limit the number of units that are ever trained by this plan with this call. // After nine total villagers, don't build any more ever. aiPlanSetVariableInt(maintainVillagerID, cTrainPlanNumberToTrain, 0, 3); //Set the number of units to maintain in the world at one time - three should do it. aiPlanSetVariableInt(maintainVillagerID, cTrainPlanNumberToMaintain, 0, 3); //Don't train units too fast aiPlanSetVariableInt(maintainVillagerID, cTrainPlanFrequency, 0, 10); //Set a gather point. aiPlanSetVariableVector(maintainVillagerID, cTrainPlanGatherPoint, 0, gatherPointVillager); //Activate the plan. aiPlanSetActive(maintainVillagerID); } } //============================================================================== // Defend plan excitement. //============================================================================== void defendPlanSetup(void) { // Six hypaspists at each of the defend locations. int defendPlan1ID=aiPlanCreate("East Defense", cPlanDefend); if (defendPlan1ID >= 0) { //Main gate location vector eastChoke=kbGetBlockPosition("2443"); //Add the unit(s). aiPlanAddUnitType(defendPlan1ID, attackerUnitTypeID4, 0, 6, 6); aiPlanAddUnitType(defendPlan1ID, attackerUnitTypeID5, 0, 4, 4); //Setup the vars. aiPlanSetDesiredPriority(defendPlan1ID, 40); aiPlanSetVariableVector(defendPlan1ID, cDefendPlanDefendPoint, 0, eastChoke); aiPlanSetVariableFloat(defendPlan1ID, cDefendPlanEngageRange, 0, 20); aiPlanSetActive(defendPlan1ID); } int defendPlan2ID=aiPlanCreate("West Defense", cPlanDefend); if (defendPlan2ID >= 0) { //Main gate location vector westChoke=kbGetBlockPosition("2446"); //Add the unit(s). aiPlanAddUnitType(defendPlan2ID, attackerUnitTypeID4, 0, 6, 6); aiPlanAddUnitType(defendPlan2ID, attackerUnitTypeID5, 0, 4, 4); //Setup the vars. aiPlanSetDesiredPriority(defendPlan2ID, 40); aiPlanSetVariableVector(defendPlan2ID, cDefendPlanDefendPoint, 0, westChoke); aiPlanSetVariableFloat(defendPlan2ID, cDefendPlanEngageRange, 0, 20); aiPlanSetActive(defendPlan2ID); } // A single evil Titan defending at the gate int defendPlan3ID=aiPlanCreate("Titan Defense", cPlanDefend); if (defendPlan3ID >= 0) { //Main gate location vector theGate=kbGetBlockPosition("2511"); //Add the unit(s). aiPlanAddUnitType(defendPlan3ID, cUnitTypeTitanBad, 1, 1, 1); //Setup the vars. aiPlanSetDesiredPriority(defendPlan3ID, 90); aiPlanSetVariableVector(defendPlan3ID, cDefendPlanDefendPoint, 0, theGate); aiPlanSetVariableFloat(defendPlan3ID, cDefendPlanEngageRange, 0, 25); aiPlanSetUnitStance(defendPlan3ID, cUnitStanceDefensive); aiPlanSetAllowUnderAttackResponse(defendPlan3ID, false); aiPlanSetActive(defendPlan3ID); } } //============================================================================== // MAIN //============================================================================== void main(void) { // Difficulty Level check. int difflevel=-1; difflevel=aiGetWorldDifficulty(); //Startup. miscStartup(); //Set up maintain plans. maintainStuff(); // Set up a couple of defend plans. defendPlanSetup(); // Difflevel adjustments. if ( difflevel < 1 ) { xsSetRuleMinInterval( "favorCheat", 90 ); } if ( difflevel == 3 ) { xsSetRuleMinInterval( "favorCheat", 20 ); xsSetRuleMinInterval("attackGeneratorHuman", 75); aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 20); aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanFrequency, 0, 20); aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanFrequency, 0, 15); aiPlanSetVariableInt(maintainHeroPlan2ID, cTrainPlanFrequency, 0, 40); aiPlanSetVariableInt(maintainMythPlan1ID, cTrainPlanFrequency, 0, 45); } }