//============================================================================== // File: aiRMArmyControlCore.xs // Author: Matt Craver // // This file adds functionality to RM scripting that allows armies created via // triggers to be used by the AI. //============================================================================== extern const int cPatrolPlanLocationID = 0; extern const int cPatrolPlanIsReactionary = 1; extern const int cPatrolPlanRepeat = 2; extern int gPatrolLocationsArray = -1; extern int gPatrolPlanArray = -1; extern int gPatrolRepeatArray = -1; extern int gPatrolIndex = -1; extern int gPatrolLocationIndex = -1; extern int gPatrolPlanIndex = -1; extern vector gPatrolTempVector = cInvalidVector; extern int gPatrolMaxSize = -1; extern int gPatrolUnitQuery = -1; extern bool gPatrolTempIsReactionary = false; extern bool gPatrolTempRepeat = true; extern int gReactionQuery = -1; extern int gReactionPointsArray = -1; extern vector gReactionTempVector = cInvalidVector; extern int gReactionCurrentIndex = 0; extern int gReactionRadius = 20; extern int gReactionUnitType = -1; void initializeReactionPoints(int count = -1) { gReactionPointsArray = xsArrayCreateVector(count, cInvalidVector, "Reaction Points"); } void setReactionUnitType(int index = -1) { switch(index) { case 0: { gReactionUnitType = cUnitTypeUnitTypeBldgTower; break; } } } void setReactionRadius(int rad = -1) { gReactionRadius = rad; } void addReactionXCoord(int x = -1) { gReactionTempVector = xsVectorSetX(gReactionTempVector, x); } void addReactionZCoord(int z = -1) { gReactionTempVector = xsVectorSetZ(gReactionTempVector, z); xsArraySetVector(gReactionPointsArray, gReactionCurrentIndex, gReactionTempVector); gReactionCurrentIndex = gReactionCurrentIndex + 1; gReactionTempVector = cInvalidVector; } vector reactionLocation() { //322 284 if(gReactionQuery == -1) { gReactionQuery = kbUnitQueryCreate("Reactionary Query"); kbUnitQuerySetPlayerRelation(gReactionQuery, cPlayerRelationEnemyNotGaia); kbUnitQuerySetUnitType(gReactionQuery, gReactionUnitType); kbUnitQuerySetState(gReactionQuery, cUnitStateAlive); } kbLookAtAllUnitsOnMap(); int count = xsArrayGetSize(gReactionPointsArray); for(i = 0; < count) { kbUnitQuerySetPosition(gReactionQuery, xsArrayGetVector(gReactionPointsArray, i)); kbUnitQuerySetMaximumDistance(gReactionQuery, gReactionRadius); kbUnitQueryResetResults(gReactionQuery); kbUnitQueryExecute(gReactionQuery); if(kbUnitQueryNumberResults(gReactionQuery) > 0) { return(kbUnitGetPosition(kbUnitQueryGetResult(gReactionQuery, 0))); } } return(cInvalidVector); } void setPatrolCount(int count = -1) { gPatrolLocationsArray = xsArrayCreateInt(count, -1, "Patrol Paths"); gPatrolPlanArray = xsArrayCreateInt(count, -1, "Patrol Plans"); gPatrolRepeatArray = xsArrayCreateBool(count, true, "Patrol Repeat Check"); if(gPatrolUnitQuery == -1) { gPatrolUnitQuery = kbUnitQueryCreate("Patrol Unit Query"); kbUnitQuerySetPlayerRelation(gPatrolUnitQuery, cPlayerRelationEnemyNotGaia); kbUnitQuerySetUnitType(gPatrolUnitQuery, cUnitTypeLogicalTypeLandPickerTarget); kbUnitQuerySetState(gPatrolUnitQuery, cUnitStateABQ); } } void addNewPatrol(int patrolPoints = -1) { gPatrolIndex = gPatrolIndex + 1; int arrayID = xsArrayCreateVector(patrolPoints, cInvalidVector, "Patrol Path " + gPatrolIndex); xsArraySetInt(gPatrolLocationsArray, gPatrolIndex, arrayID); gPatrolLocationIndex = 0; gPatrolTempIsReactionary = false; gPatrolTempRepeat = true; } void setPatrolRepeat(int repeat = -1) { if(repeat <= 0) { gPatrolTempRepeat = false; } } void setPatrolIsReactionary(int val = -1) { if(val > 0) { gPatrolTempIsReactionary = true; } } void addPatrolXCoord(int x = -1) { gPatrolTempVector = xsVectorSetX(gPatrolTempVector, x); } void addPatrolZCoord(int z = -1) { gPatrolTempVector = xsVectorSetZ(gPatrolTempVector, z); int arrayID = xsArrayGetInt(gPatrolLocationsArray, gPatrolIndex); xsArraySetVector(arrayID, gPatrolLocationIndex, gPatrolTempVector); gPatrolLocationIndex = gPatrolLocationIndex + 1; gPatrolTempVector = cInvalidVector; } void setMaxPatrolSize(int max = -1) { gPatrolMaxSize = max; } vector getPatrolLocation(int patrolID = -1, int locID = -1) { int arrayID = xsArrayGetInt(gPatrolLocationsArray, patrolID); return(xsArrayGetVector(arrayID, locID)); } void createPatrolWithArmy(int id = -1) { //gPatrolPlanIndex = gPatrolPlanIndex + 1; int armyID = id; int unitCount = kbGetUnitCountInArmy(armyID); int plan = aiPlanCreate("RM Patrol " + gPatrolIndex, cPlanDefend); vector position = kbUnitGetPosition(kbGetUnitInArmy(armyID, 0)); for(i = 0; < unitCount) { aiPlanAddUnit(plan, kbGetUnitInArmy(armyID, i)); } // get the first point in the patrol vector temp = getPatrolLocation(gPatrolIndex, 0); aiEcho("POINT " + temp); aiPlanSetVariableVector(plan, cDefendPlanDefendPoint, 0, getPatrolLocation(gPatrolIndex, 0)); int planCount = unitCount; if(unitCount > gPatrolMaxSize) { planCount = gPatrolMaxSize; } aiPlanSetVariableFloat(plan, cDefendPlanEngageRange, 0, 30); aiPlanSetVariableFloat(plan, cDefendPlanGatherDistance, 0, 20.0); aiPlanSetInitialPosition(plan, getPatrolLocation(gPatrolIndex, 0)); aiPlanSetUnitStance(plan, cUnitStanceAggressive); aiPlanSetVariableInt(plan, cDefendPlanRefreshFrequency, 0, 5); aiPlanSetVariableInt(plan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit); aiPlanSetDesiredPriority(plan, 100); aiPlanAddUnitType(plan, cUnitTypeMilitary, planCount, planCount, planCount); aiPlanAddUserVariableInt(plan, cPatrolPlanLocationID, "Location Index", 1); aiPlanSetUserVariableInt(plan, cPatrolPlanLocationID, 0, 0); aiPlanAddUserVariableBool(plan, cPatrolPlanIsReactionary, "Is Reactionary", 1); aiPlanSetUserVariableBool(plan, cPatrolPlanIsReactionary, 0, gPatrolTempIsReactionary); aiPlanAddUserVariableBool(plan, cPatrolPlanRepeat, "Repeat", 1); aiPlanSetUserVariableBool(plan, cPatrolPlanRepeat, 0, gPatrolTempRepeat); if(gPatrolTempRepeat == false) { aiPlanSetNoMoreUnits(plan, false); } aiPlanSetActive(plan); xsArraySetInt(gPatrolPlanArray, gPatrolIndex, plan); } rule updatePatrolLocations active minInterval 15 { int patrolCount = xsArrayGetSize(gPatrolPlanArray); for(i = 0; < patrolCount) { int planID = xsArrayGetInt(gPatrolPlanArray, i); vector reactionLoc = reactionLocation(); if(aiPlanGetUserVariableBool(planID, cPatrolPlanIsReactionary, 0) && reactionLoc != cInvalidVector) { aiEcho("Reaction triggered for plan " + planID); aiPlanSetVariableVector(planID, cDefendPlanDefendPoint, 0, reactionLoc); } else { int locID = aiPlanGetUserVariableInt(planID, cPatrolPlanLocationID, 0); // get the location of the first unit in the plan vector location = aiPlanGetLocation(planID);//kbUnitGetPosition(aiPlanGetUnitByIndex(planID, 0)); kbUnitQuerySetPosition(gPatrolUnitQuery, location); kbUnitQuerySetMaximumDistance(gPatrolUnitQuery, 20); kbUnitQueryResetResults(gPatrolUnitQuery); kbUnitQueryExecute(gPatrolUnitQuery); int count = kbUnitQueryNumberResults(gPatrolUnitQuery); if(count == 0) { int locCount = xsArrayGetSize(xsArrayGetInt(gPatrolLocationsArray, i)); locID = locID + 1; if(locID >= locCount) { if(aiPlanGetUserVariableBool(planID, cPatrolPlanRepeat, 0) == false) { aiPlanDestroy(planID); continue; } else { locID = 0; } } aiPlanSetVariableVector(planID, cDefendPlanDefendPoint, 0, getPatrolLocation(i, locID)); // only change the MAX unit count if we have less units than we should if(aiPlanGetNumberUnits(planID, cUnitTypeMilitary) < gPatrolMaxSize) { aiPlanAddUnitType(planID, cUnitTypeMilitary, gPatrolMaxSize, gPatrolMaxSize, gPatrolMaxSize); } aiPlanSetUserVariableInt(planID, cPatrolPlanLocationID, 0, locID); } } } }