extern int gTowerQuery = -1; extern int gMilitaryQuery = -1; extern vector gAttackLocation = cInvalidVector; extern int gAttackPlayer = -1; extern int gMaxPlanSize = -1; void setSiegeTowerAutoGarrisonFrequency(int time = -1) { xsSetRuleMinInterval("loadAllUnitsIntoAllSiegeTowers", time); } //============================================================================== // loadArmyIntoSiegeTower // // This function can be called an RM script to load an army into an available // siege tower. It will only load the army into a siege tower that is already // empty. //============================================================================== void loadArmyIntoSiegeTower(int armyID = -1) { kbUnitQueryResetResults(gTowerQuery); kbUnitQueryExecute(gTowerQuery); int towerCount = kbUnitQueryNumberResults(gTowerQuery); if(towerCount > 0) { int towerID = -1; for(i = 0; < towerCount) { int id = kbUnitQueryGetResult(gTowerQuery, i); if(kbUnitGetNumberUnitsContained(id) == 0) { towerID = id; break; } } aiEcho("loading army " + armyID + " into siege tower " + towerID); int armyCount = kbGetUnitCountInArmy(armyID); aiEcho("army count " + armyCount); for(i = 0; < armyCount) { aiEcho("unit id " + kbGetUnitInArmy(armyID, i)); aiTaskUnitEnter(kbGetUnitInArmy(armyID, i), towerID); } /*int plan = aiPlanCreate("Siege Tower Transport", cPlanTransport); int towerProtoID = kbFindUnit(cUnitTypeUnitTypeSiegeRam1); aiEcho("proto " + towerProtoID); vector gatherLoc = kbUnitGetPosition(towerID); vector testLoc = vector(40,0,40); aiPlanAddUnitType(plan, towerProtoID, 1, 1, 1); aiPlanSetVariableInt(plan, cTransportPlanTransportID, 0, towerID); aiPlanSetVariableInt(plan, cTransportPlanTransportTypeID, 0, towerProtoID); aiPlanSetVariableVector(plan, cTransportPlanGatherPoint, 0, gatherLoc); aiPlanSetVariableVector(plan, cTransportPlanTargetPoint, 0, testLoc); aiPlanSetVariableVector(plan, cTransportPlanDropOffPoint, 0, testLoc); aiPlanSetVariableInt(plan, cTransportPlanGatherAreaGroup, 0, kbAreaGroupGetIDByPosition(gatherLoc)); aiPlanSetVariableInt(plan, cTransportPlanTargetAreaGroup, 0, kbAreaGroupGetIDByPosition(testLoc)); aiPlanSetVariableInt(plan, cTransportPlanGatherArea, 0, kbAreaGetIDByPosition(gatherLoc)); aiPlanSetVariableInt(plan, cTransportPlanTargetArea, 0, kbAreaGetIDByPosition(testLoc)); int armyCount = kbGetUnitCountInArmy(armyID); aiEcho("army count " + armyCount); for(i = 0; < armyCount) { aiEcho("unit id " + kbGetUnitInArmy(armyID, i)); aiPlanAddUnit(plan, kbGetUnitInArmy(armyID, i)); } aiPlanSetActive(plan, true);*/ } } //============================================================================== // siegeTowerSetAttackLocationXCoord // // Set the X Coord of where the Siege Towers will try to attack when we activate // the manual attack plan. //============================================================================== void siegeTowerSetAttackLocationXCoord(int x = -1) { gAttackLocation = xsVectorSetX(gAttackLocation, x); } //============================================================================== // siegeTowerSetAttackLocationZCoord // // Set the Z Coord of where the Siege Towers will try to attack when we activate // the manual attack plan. //============================================================================== void siegeTowerSetAttackLocationZCoord(int z = -1) { gAttackLocation = xsVectorSetZ(gAttackLocation, z); } //============================================================================== // siegeTowerSetPlayerToAttack // // ID of the player the Siege Towers should attack. //============================================================================== void siegeTowerSetPlayerToAttack(int id = -1) { gAttackPlayer = id; } //============================================================================== // siegeTowerSetMaxPlanSize // // ID of the player the Siege Towers should attack. //============================================================================== void siegeTowerSetMaxPlanSize(int size = -1) { gMaxPlanSize = size; } //============================================================================== // siegeTowerForceAttack // // Creates an attack plan that will grab all Siege Towers the AI has at the moment // and send them to the attack point. //============================================================================== void siegeTowerForceAttack(int unused = -1) { int plan = aiPlanCreate("Siege Tower Attack Plan", cPlanAttack); aiEcho("ATTACK PLAN " + plan); //Priority. aiPlanSetDesiredPriority(plan, 100); //Attack player ID. aiPlanSetVariableInt(plan, cAttackPlanPlayerID, 0, gAttackPlayer); aiPlanSetVariableInt(plan, cAttackPlanTargetTypeID, 0, cUnitTypeBuilding); aiPlanSetVariableInt(plan, cAttackPlanGatherWaitTime, 0, 60000); //Attack. aiPlanSetAttack(plan, true); aiPlanSetInitialPosition(plan, gAttackLocation); aiPlanSetVariableVector(plan, cAttackPlanAttackPoint, 0, gAttackLocation); //Military. aiPlanSetMilitary(plan, true); aiPlanSetEscrowID(plan, cMilitaryEscrowID); aiPlanAddUnitType(plan, cUnitTypeUnitTypeSiegeRam1 , gMaxPlanSize, gMaxPlanSize, gMaxPlanSize); aiPlanSetActive(plan); } //============================================================================== // setUpSiegeTowerQueries // // This function must be called in the main script in order to initialize // some unit queries. //============================================================================== void setUpSiegeTowerQueries() { if(gTowerQuery == -1) { gTowerQuery = kbUnitQueryCreate("Tower Query"); kbUnitQuerySetPlayerRelation(gTowerQuery, cPlayerRelationSelf); kbUnitQuerySetUnitType(gTowerQuery, cUnitTypeUnitTypeSiegeRam1); kbUnitQuerySetState(gTowerQuery, cUnitStateAlive); } if(gMilitaryQuery == -1) { gMilitaryQuery = kbUnitQueryCreate("Military Query"); kbUnitQuerySetPlayerRelation(gMilitaryQuery, cPlayerRelationSelf); kbUnitQuerySetUnitType(gMilitaryQuery, cUnitTypeLogicalTypeLandPickerChoice); kbUnitQuerySetState(gMilitaryQuery, cUnitStateAlive); } } rule loadAllUnitsIntoAllSiegeTowers minInterval 15 active { setUpSiegeTowerQueries(); kbUnitQueryResetResults(gTowerQuery); kbUnitQueryExecute(gTowerQuery); int towerCount = kbUnitQueryNumberResults(gTowerQuery); kbUnitQueryResetResults(gMilitaryQuery); kbUnitQueryExecute(gMilitaryQuery); int unitCount = kbUnitQueryNumberResults(gMilitaryQuery); int unitIndex = 0; aiEcho("tower count " + towerCount); for(i = 0; < towerCount) { int towerID = kbUnitQueryGetResult(gTowerQuery, i); // not sure how to get the max contained number for a unit, so hardcoding it to 16 int remainingUnits = kbUnitGetMaxContained(towerID) - kbUnitGetNumberUnitsContained(towerID); aiEcho("room for " + remainingUnits + " units"); for(j = 0; < remainingUnits) { while((kbUnitCanBeTransportedByTarget(kbUnitQueryGetResult(gMilitaryQuery, unitIndex), towerID) == false || kbUnitIsContained(kbUnitQueryGetResult(gMilitaryQuery, unitIndex)) == true || aiPlanGetType(kbUnitGetPlanID(kbUnitQueryGetResult(gMilitaryQuery, unitIndex))) == cPlanAttack) && unitIndex < unitCount) { aiEcho("unit index " + unitIndex + " is no good"); unitIndex = unitIndex + 1; } // we ran out of units if(unitIndex >= unitCount) break; aiTaskUnitEnter(kbUnitQueryGetResult(gMilitaryQuery, unitIndex), towerID); unitIndex = unitIndex + 1; } } }