From da46b71cad8eb453277d23392f2c27046b819671 Mon Sep 17 00:00:00 2001
From: Pan
Date: Fri, 30 Dec 2022 14:25:37 +1300
Subject: [PATCH] cap the number of units that can be built by the AI in easy
difficulty
---
enemyAI/unitProductionAI.java | 1085 +++++++++++++++++----------------
1 file changed, 543 insertions(+), 542 deletions(-)
diff --git a/enemyAI/unitProductionAI.java b/enemyAI/unitProductionAI.java
index edf75b2..b465232 100644
--- a/enemyAI/unitProductionAI.java
+++ b/enemyAI/unitProductionAI.java
@@ -1,542 +1,543 @@
-package enemyAI;
-
-import core.baseInfo;
-import core.gameData;
-import core.mainThread;
-import core.vector;
-import entity.*;
-
-//decide which unit to produce to counter player's force
-//keep track of the units that are under control by combatAI.
-
-public class unitProductionAI {
-
- public baseInfo theBaseInfo;
-
- public lightTank[] lightTanksControlledByCombatAI;
- public rocketTank[] rocketTanksControlledByCombatAI;
- public stealthTank[] stealthTanksControlledByCombatAI;
- public heavyTank[] heavyTanksControlledByCombatAI;
- public solidObject[] troopsControlledByCombatAI;
-
- public float combatAICenterX;
- public float combatAICenterZ;
-
- public int currentProductionOrder;
- public final int produceLightTank = 0;
- public final int produceRocketTank = 1;
- public final int produceStealthTank = 2;
- public final int produceHeavyTank = 3;
-
- public vector rallyPoint;
- //public int unitProduced;
- public int numberOfCombatUnit;
- public int numberOfUnitInCombatRadius;
- public int numberOfUnitOutsideCombatRadius;
- public int numberOfCombatUnitsUnderAttack;
-
- public int numberOfLightTanksControlledByCombatAI;
- public int numberOfRocketTanksControlledByCombatAI;
- public int numberOfStealthTanksControlledByCombatAI;
- public int numberOfHeavyTanksControlledByCombatAI;
-
- public solidObject[] unitInCombatRadius;
- public solidObject[] unitOutsideCombatRadius;
-
- public float rushRallyPointX, rushRallyPointZ;
-
- public int frameAI;
-
- public unitProductionAI(){
- this.theBaseInfo = mainThread.ec.theBaseInfo;
- rallyPoint = new vector(0,0,0);
-
-
- rushRallyPointX = 9.5f+2;
- rushRallyPointZ = 5.5f+2;
-
-
-
- lightTanksControlledByCombatAI = new lightTank[192];
- rocketTanksControlledByCombatAI = new rocketTank[72];
- stealthTanksControlledByCombatAI = new stealthTank[96];
- heavyTanksControlledByCombatAI = new heavyTank[60];
-
- troopsControlledByCombatAI = new solidObject[512];
- unitInCombatRadius = new solidObject[384];
- unitOutsideCombatRadius = new solidObject[128];
-
- combatAICenterX = -1;
- combatAICenterZ = -1;
-
- }
-
-
-
- public void processAI(){
- frameAI = mainThread.ec.frameAI;
-
- //set the rally point to near the construction yard which is closest to the AI player's starting position
- float x = 0;
- float z = 999999;
-
-
- int numberOfLightTanks_AI = mainThread.ec.theUnitProductionAI.numberOfLightTanksControlledByCombatAI;
- int numberOfRocketTanks_AI = mainThread.ec.theUnitProductionAI.numberOfRocketTanksControlledByCombatAI;
- int numberOfStealthTanks_AI = mainThread.ec.theUnitProductionAI.numberOfStealthTanksControlledByCombatAI;
- int numberOfHeavyTanks_AI = mainThread.ec.theUnitProductionAI.numberOfHeavyTanksControlledByCombatAI;
- boolean unitCountLow = mainThread.ec.theCombatManagerAI.unitCountLow;
-
- int index = 0;
- for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
- if(mainThread.theAssetManager.constructionYards[i] != null && mainThread.theAssetManager.constructionYards[i].currentHP > 0 && mainThread.theAssetManager.constructionYards[i].teamNo != 0){
- if(unitCountLow && mainThread.ec.theDefenseManagerAI.majorThreatLocation.x != 0) {
- float xPos1 = mainThread.theAssetManager.constructionYards[i].centre.x;
- float zPos1 = mainThread.theAssetManager.constructionYards[i].centre.z;
- float xPos2 = mainThread.ec.theDefenseManagerAI.majorThreatLocation.x;
- float zPos2 = mainThread.ec.theDefenseManagerAI.majorThreatLocation.z;
- float d = (xPos1 - xPos2) * (xPos1 - xPos2) + (zPos1 - zPos2) * (zPos1 - zPos2);
- if(d < 9) {
- continue;
- }
- }
-
- index = i;
- if(mainThread.theAssetManager.constructionYards[i].centre.z < z && mainThread.theAssetManager.constructionYards[i].centre.z > 7 && mainThread.theAssetManager.constructionYards[i].centre.x > 7){
- x = mainThread.theAssetManager.constructionYards[i].centre.x;
- z = mainThread.theAssetManager.constructionYards[i].centre.z;
- }
- }
- }
- if(z != 999999) {
-
- rallyPoint.set(x - 2f, 0, z - 1.5f);
-
- if(frameAI < 240 && mainThread.ec.difficulty == 2) {
- rallyPoint.set(mainThread.theAssetManager.goldMines[5].centre);
- }
- }else {
- if(mainThread.theAssetManager.constructionYards[index] != null && mainThread.theAssetManager.constructionYards[index].teamNo !=0)
- rallyPoint.set(mainThread.theAssetManager.constructionYards[index].centre.x - 2.5f, 0, mainThread.theAssetManager.constructionYards[index].centre.z -2.5f);
- }
-
- //If the difficulty is set to normal or hard, set the rally point just outside of player's natural expansion.
- //So if the player is going for a fast expansion and don't have much units, the AI can perform a rush attack.
- //if(mainThread.ec.theMapAwarenessAI.canRushPlayer && frameAI < 360 && mainThread.ec.theCombatManagerAI.checkIfAIHasBiggerForce(0.75f)) {
- // rallyPoint.set(rushRallyPointX, 0, rushRallyPointZ);
- //}
-
- //make sure not to over produce when the resource is running low
- int maxNumOfUnitCanBeProduced = theBaseInfo.currentCredit / 500 + 1;
-
-
- for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
- factory f = mainThread.theAssetManager.factories[i];
- if(f != null && f.teamNo !=0){
- if(!f.isIdle())
- maxNumOfUnitCanBeProduced--;
- }
- }
-
- for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
- constructionYard c = mainThread.theAssetManager.constructionYards[i];
- if(c != null && c.teamNo !=0){
- if(!c.isIdle())
- maxNumOfUnitCanBeProduced--;
- }
- }
-
-
- if(mainThread.ec.difficulty > 0) {
- //make decision on what unit to produce
- int numberOfPlayerGunTurrets= mainThread.ec.theMapAwarenessAI.numberOfGunTurret_player;
- int numberOfPlayerMissileTurrets= mainThread.ec.theMapAwarenessAI.numberOfMissileTurret_player;
- int numberOfLightTanks_player = mainThread.ec.theMapAwarenessAI.numberOfLightTanks_player;
- int numberOfRocketTanks_player = mainThread.ec.theMapAwarenessAI.numberOfRocketTanks_player;
- int numberOfStealthTanks_player = mainThread.ec.theMapAwarenessAI.numberOfStealthTanks_player;
- int numberOfHeavyTanks_player = mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_player;
- int maxNumberOfStealthTanks_playerInLastFiveMinutes = mainThread.ec.theMapAwarenessAI.maxNumberOfStealthTanks_playerInLastFiveMinutes;
-
- boolean playerHasMostlyLightTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyLightTanks;
- boolean playerHasMostlyHeavyTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyTanks;
- boolean playIsRushingHighTierUnits = mainThread.ec.theMapAwarenessAI.playIsRushingHighTierUnits;
- boolean playerLikelyCanNotProduceHighTierUnits = mainThread.ec.theMapAwarenessAI.playerLikelyCanNotProduceHighTierUnits;
- boolean playerDoesntHaveMassHeavyTanks = mainThread.ec.theMapAwarenessAI.playerDoesntHaveMassHeavyTanks;
- boolean playerHasManyLightTanksButNoHeavyTank = mainThread.ec.theMapAwarenessAI.playerHasManyLightTanksButNoHeavyTank;
- boolean playerHasMostlyHeavyAndStealthTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyAndStealthTanks;
- boolean playerHasMostlyLightAndStealthTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyLightAndStealthTanks;
- boolean playerArmyCanBeCounteredWithLightTanks = mainThread.ec.theMapAwarenessAI.playerArmyCanBeCounteredWithLightTanks;
- boolean playerArmyCanBeCounteredWithStealthTanks = mainThread.ec.theMapAwarenessAI.playerArmyCanBeCounteredWithStealthTanks;
-
- int timeToBuildHeavyTank = 500;
- int timeToBuildStealthTank = 200;
- if(mainThread.ec.theMapAwarenessAI.canRushPlayer) {
- //when AI decides to rush the player, then dont build higher tier units so it can mass produce light tanks
- timeToBuildHeavyTank = 500;
- timeToBuildStealthTank = 300;
- }
-
- boolean b1 = (numberOfRocketTanks_AI < 3 && !playerHasMostlyHeavyTanks && (frameAI > 400 || frameAI > 170 && frameAI < 240 && mainThread.ec.theMapAwarenessAI.numberOfConstructionYard_player > 0) && !playerHasMostlyLightTanks);
- boolean b2 = (numberOfRocketTanks_AI < numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets*1.5);
- if( b1 || b2){
- currentProductionOrder = produceRocketTank;
- }else if(theBaseInfo.canBuildHeavyTank && numberOfHeavyTanksControlledByCombatAI < 20 && !(numberOfStealthTanksControlledByCombatAI < 1) && !playerHasMostlyHeavyTanks && !playerHasMostlyLightTanks && !playerHasMostlyLightAndStealthTanks && !playerArmyCanBeCounteredWithLightTanks && !playerArmyCanBeCounteredWithStealthTanks &&
- (playerHasMostlyHeavyAndStealthTanks || (frameAI > timeToBuildHeavyTank && numberOfHeavyTanks_AI < 3) ||
- !playerHasManyLightTanksButNoHeavyTank
- && !(numberOfHeavyTanks_player == 0 && maxNumberOfStealthTanks_playerInLastFiveMinutes < 3 && frameAI > 600)
- && !(playerHasMostlyHeavyTanks && numberOfStealthTanks_player < numberOfHeavyTanks_AI*2)
- && (playIsRushingHighTierUnits || maxNumberOfStealthTanks_playerInLastFiveMinutes*4 > numberOfHeavyTanks_AI))){
- currentProductionOrder = produceHeavyTank;
- }else if(theBaseInfo.canBuildStealthTank && ((numberOfStealthTanksControlledByCombatAI < 1) || (playerDoesntHaveMassHeavyTanks && !playerHasMostlyHeavyTanks && !playerArmyCanBeCounteredWithLightTanks && !(numberOfStealthTanksControlledByCombatAI >= 9 && frameAI < 600) && !(numberOfStealthTanksControlledByCombatAI >= 18 && frameAI > 600)
- && (playerHasMostlyLightTanks || playerLikelyCanNotProduceHighTierUnits || playerDoesntHaveMassHeavyTanks || playerHasMostlyLightAndStealthTanks) && !playerHasMostlyHeavyTanks && (frameAI > timeToBuildStealthTank || numberOfLightTanks_player > 8)))){
- currentProductionOrder = produceStealthTank;
- }else{
- currentProductionOrder = produceLightTank;
- }
-
- //make decision on what tech to research
- if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfCommunicationCenter > 0 && mainThread.ec.difficulty > 1) {
- if(mainThread.ec.theDefenseManagerAI.needMissileTurret || theBaseInfo.currentCredit > 1500 && frameAI > 450) {
- if(!communicationCenter.rapidfireResearched_enemy) {
- if(communicationCenter.rapidfireResearchProgress_enemy == 255){
- communicationCenter.researchRapidfire(1);
- System.out.println("----------------------------AI starts researching rapid fire ability------------------------------------");
- }
- }
- }
-
- if(mainThread.ec.theEconomyManagerAI.numberOfharvesters >= 6 && theBaseInfo.currentCredit > 1500 && mainThread.ec.difficulty > 1) {
- if(!communicationCenter.harvesterSpeedResearched_enemy) {
- if(communicationCenter.harvesterSpeedResearchProgress_enemy == 255){
- communicationCenter.researchHarvesterSpeed(1);
- System.out.println("----------------------------AI starts researching harvester speed ability------------------------------------");
- }
- }
- }
- }
-
- if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfTechCenter > 0){
-
- //Immediately start stealth tank upgrades when a tech center is built
- if(!techCenter.stealthTankResearched_enemy){
- if(techCenter.stealthTankResearchProgress_enemy == 255){
- techCenter.cancelResearch(1);
- techCenter.researchStealthTank(1);
- System.out.println("----------------------------AI starts researching stealth tank------------------------------------");
- }
- }
-
-
- if(numberOfLightTanks_AI >= 15 && theBaseInfo.currentCredit > 1000){
- if(!techCenter.lightTankResearched_enemy){
- if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
- techCenter.researchLightTank(1);
- System.out.println("----------------------------AI starts researching light tank------------------------------------");
- }
- }
- }
-
- if(numberOfRocketTanks_AI > 2 && theBaseInfo.currentCredit > 1250 && (numberOfPlayerGunTurrets > 0 || numberOfPlayerMissileTurrets > 0 || frameAI > 600)){
- if(!techCenter.rocketTankResearched_enemy){
- if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
-
- techCenter.researchRocketTank(1);
- System.out.println("----------------------------AI starts researching rocket tank------------------------------------");
- }
- }
- }
-
- if(numberOfHeavyTanks_AI > 5 && theBaseInfo.currentCredit > 1000){
- if(!techCenter.heavyTankResearched_enemy){
- if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
- techCenter.researchHeavyTank(1);
- System.out.println("----------------------------AI starts researching heavy tank------------------------------------");
- }
- }
- }
-
-
- }
- }else {
- int roll = gameData.getRandom();
- if(roll < 612) {
- currentProductionOrder = produceLightTank;
- }else if(roll >= 612 && roll < 700) {
- currentProductionOrder = produceRocketTank;
- }else if(roll >= 700 && roll < 900) {
- currentProductionOrder = produceStealthTank;
- }else {
- currentProductionOrder = produceHeavyTank;
- }
-
- }
-
-
- for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
- factory f = mainThread.theAssetManager.factories[i];
- if(f != null && f.teamNo !=0){
- f.moveTo(rallyPoint.x, rallyPoint.z);
- if(f.isIdle()){
- if(theBaseInfo.canBuildLightTank && maxNumOfUnitCanBeProduced > 0){
-
- if(currentProductionOrder == produceLightTank)
- f.buildLightTank();
- else if(currentProductionOrder == produceRocketTank)
- f.buildRocketTank();
- else if(currentProductionOrder == produceStealthTank)
- f.buildStealthTank();
- else if(currentProductionOrder == produceHeavyTank)
- f.buildHeavyTank();
-
- maxNumOfUnitCanBeProduced--;
- }
- continue;
- }
- }
- }
-
-
- countTroopControlledByCombatAI();
- findCenterOfTroopControlledByCombatAI();
-
- }
-
- public void addLightTank(lightTank o){
- //check if other AI agent need light tank
-
- if(mainThread.ec.theScoutingManagerAI.needLightTank()){
- mainThread.ec.theScoutingManagerAI.addLightTank(o);
-
- return;
- }
-
-
- //add the new light tank to combat AI's command
- for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
- if(lightTanksControlledByCombatAI[i] == null || (lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP <=0)){
- lightTanksControlledByCombatAI[i] = o;
- if(mainThread.ec.difficulty > 0)
- mainThread.ec.theDefenseManagerAI.addUnitToDefenders(o);
- break;
- }
- }
-
-
- }
-
- public void addRocketTank(rocketTank o){
- //check if other AI agent need rocket tank
-
- //add the new rocket tank to combat AI's command
- for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
- if(rocketTanksControlledByCombatAI[i] == null || (rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP <=0)){
- rocketTanksControlledByCombatAI[i] = o;
- break;
- }
- }
- }
-
- public void addStealthTank(stealthTank o){
- //check if other AI agent need stealth tank
-
- if(mainThread.ec.theScoutingManagerAI.needStealthTank()){
- mainThread.ec.theScoutingManagerAI.addStealthTank(o);
- return;
- }
-
- if(mainThread.ec.theBaseExpentionAI.needStealthTank()){
- mainThread.ec.theBaseExpentionAI.addStealthTank(o);
- return;
- }
-
-
-
- //add the new stealth tank to combat AI's command
- for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
- if(stealthTanksControlledByCombatAI[i] == null || (stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP <=0)){
- stealthTanksControlledByCombatAI[i] = o;
- if(mainThread.ec.difficulty > 0)
- mainThread.ec.theDefenseManagerAI.addUnitToDefenders(o);
- break;
- }
- }
- }
-
- public void addHeavyTank(heavyTank o){
- //add the new heavy tank to combat AI's command
- for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
- if(heavyTanksControlledByCombatAI[i] == null || (heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP <=0)){
- heavyTanksControlledByCombatAI[i] = o;
- break;
- }
- }
- }
-
-
- public void countTroopControlledByCombatAI(){
- numberOfCombatUnitsUnderAttack = 0;
-
- numberOfLightTanksControlledByCombatAI = 0;
- numberOfRocketTanksControlledByCombatAI = 0;
- numberOfStealthTanksControlledByCombatAI = 0;
- numberOfHeavyTanksControlledByCombatAI = 0;
-
- for(int i = 0; i < troopsControlledByCombatAI.length; i++){
- troopsControlledByCombatAI[i] = null;
- }
-
- numberOfCombatUnit = 0;
- for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
- if(lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP > 0){
- troopsControlledByCombatAI[numberOfCombatUnit] = lightTanksControlledByCombatAI[i];
- if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
- numberOfCombatUnitsUnderAttack++;
- numberOfCombatUnit++;
- numberOfLightTanksControlledByCombatAI++;
- }
- }
- for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
- if(rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP > 0){
- troopsControlledByCombatAI[numberOfCombatUnit] = rocketTanksControlledByCombatAI[i];
- if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
- numberOfCombatUnitsUnderAttack++;
- numberOfCombatUnit++;
- numberOfRocketTanksControlledByCombatAI++;
- }
- }
- for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
- if(stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP > 0){
- troopsControlledByCombatAI[numberOfCombatUnit] = stealthTanksControlledByCombatAI[i];
- if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
- numberOfCombatUnitsUnderAttack++;
- numberOfCombatUnit++;
- numberOfStealthTanksControlledByCombatAI++;
- }
- }
- for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
- if(heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP > 0){
- troopsControlledByCombatAI[numberOfCombatUnit] = heavyTanksControlledByCombatAI[i];
- if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
- numberOfCombatUnitsUnderAttack++;
- numberOfCombatUnit++;
- numberOfHeavyTanksControlledByCombatAI++;
- }
- }
- }
-
- public void findCenterOfTroopControlledByCombatAI(){
- float centerX = 0;
- float centerZ = 0;
-
- vector centre;
- double distance = 0;
-
- numberOfUnitInCombatRadius = 0;
- numberOfUnitOutsideCombatRadius = 0;
-
-
- //when there is no combat unit there is no point to calculate the center of the combat units
- if(numberOfCombatUnit == 0){
- combatAICenterX = -1;
- combatAICenterZ = -1;
- return;
- }
-
- for(int i = 0; i < unitInCombatRadius.length; i++){
- unitInCombatRadius[i] = null;
- }
-
- for(int i = 0; i < unitOutsideCombatRadius.length; i++){
- unitOutsideCombatRadius[i] = null;
- }
-
-
- //calculate the center of the troops using the all the unites that are under the control of the combatAI
- if(combatAICenterX == -1){
- combatAICenterX = 0;
- combatAICenterZ = 0;
- for(int i =0; i < numberOfCombatUnit; i++){
- centre = troopsControlledByCombatAI[i].centre;
- combatAICenterX+=centre.x;
- combatAICenterZ+=centre.z;
- }
- combatAICenterX /= numberOfCombatUnit;
- combatAICenterZ /= numberOfCombatUnit;
- }
-
- //exclude the units are too far away from the center of the troops, (i.e the unites that just come out of the factory), and recalculate the center
- for(int i =0; i < numberOfCombatUnit; i++){
- centre = troopsControlledByCombatAI[i].centre;
- distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
- if(distance < 4.5){
- centerX += centre.x;
- centerZ += centre.z;
- if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
- unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
- numberOfUnitInCombatRadius++;
- }else{
- if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
- unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
- numberOfUnitOutsideCombatRadius++;
- }
- }
-
- float unitInCombactRadiusPercentage = 1;
- if(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius >0)
- unitInCombactRadiusPercentage = (float)numberOfUnitInCombatRadius/(float)(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius);
-
- float unitInCombactRadiusPercentageThreshold = 0.7f;
- if(mainThread.ec.theCombatManagerAI.currentState == mainThread.ec.theCombatManagerAI.aggressing) {
- if(mainThread.ec.theCombatManagerAI.distanceToTarget < 6)
- unitInCombactRadiusPercentageThreshold = 0.475f;
- }
- if(numberOfCombatUnitsUnderAttack > 0)
- unitInCombactRadiusPercentageThreshold = 0.25f;
-
- //need to recalculate the center if there is a significant amount of combat unites that are outside of the combat radius
- if(unitInCombactRadiusPercentage < unitInCombactRadiusPercentageThreshold){
-
- combatAICenterX = 0;
- combatAICenterZ = 0;
- for(int i =0; i < numberOfCombatUnit; i++){
- centre = troopsControlledByCombatAI[i].centre;
- combatAICenterX+=centre.x;
- combatAICenterZ+=centre.z;
- }
- combatAICenterX /= numberOfCombatUnit;
- combatAICenterZ /= numberOfCombatUnit;
-
- for(int i = 0; i < unitInCombatRadius.length; i++){
- unitInCombatRadius[i] = null;
- }
-
- for(int i = 0; i < unitOutsideCombatRadius.length; i++){
- unitOutsideCombatRadius[i] = null;
- }
- numberOfUnitInCombatRadius = 0;
- numberOfUnitOutsideCombatRadius = 0;
- centerX = 0;
- centerZ = 0;
-
- for(int i =0; i < numberOfCombatUnit; i++){
- centre = troopsControlledByCombatAI[i].centre;
- distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
- if(distance < 10){
- centerX += centre.x;
- centerZ += centre.z;
- if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
- unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
- numberOfUnitInCombatRadius++;
- }else{
- if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
- unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
- numberOfUnitOutsideCombatRadius++;
- }
- }
- }
-
- combatAICenterX = centerX/numberOfUnitInCombatRadius;
- combatAICenterZ = centerZ/numberOfUnitInCombatRadius;
-
- }
-}
+package enemyAI;
+
+import core.baseInfo;
+import core.gameData;
+import core.mainThread;
+import core.vector;
+import entity.*;
+
+//decide which unit to produce to counter player's force
+//keep track of the units that are under control by combatAI.
+
+public class unitProductionAI {
+
+ public baseInfo theBaseInfo;
+
+ public lightTank[] lightTanksControlledByCombatAI;
+ public rocketTank[] rocketTanksControlledByCombatAI;
+ public stealthTank[] stealthTanksControlledByCombatAI;
+ public heavyTank[] heavyTanksControlledByCombatAI;
+ public solidObject[] troopsControlledByCombatAI;
+
+ public float combatAICenterX;
+ public float combatAICenterZ;
+
+ public int currentProductionOrder;
+ public final int produceLightTank = 0;
+ public final int produceRocketTank = 1;
+ public final int produceStealthTank = 2;
+ public final int produceHeavyTank = 3;
+
+ public vector rallyPoint;
+ //public int unitProduced;
+ public int numberOfCombatUnit;
+ public int numberOfUnitInCombatRadius;
+ public int numberOfUnitOutsideCombatRadius;
+ public int numberOfCombatUnitsUnderAttack;
+
+ public int numberOfLightTanksControlledByCombatAI;
+ public int numberOfRocketTanksControlledByCombatAI;
+ public int numberOfStealthTanksControlledByCombatAI;
+ public int numberOfHeavyTanksControlledByCombatAI;
+
+ public solidObject[] unitInCombatRadius;
+ public solidObject[] unitOutsideCombatRadius;
+
+ public float rushRallyPointX, rushRallyPointZ;
+
+ public int frameAI;
+
+ public unitProductionAI(){
+ this.theBaseInfo = mainThread.ec.theBaseInfo;
+ rallyPoint = new vector(0,0,0);
+
+
+ rushRallyPointX = 9.5f+2;
+ rushRallyPointZ = 5.5f+2;
+
+
+
+ lightTanksControlledByCombatAI = new lightTank[192];
+ rocketTanksControlledByCombatAI = new rocketTank[72];
+ stealthTanksControlledByCombatAI = new stealthTank[96];
+ heavyTanksControlledByCombatAI = new heavyTank[60];
+
+ troopsControlledByCombatAI = new solidObject[512];
+ unitInCombatRadius = new solidObject[384];
+ unitOutsideCombatRadius = new solidObject[128];
+
+ combatAICenterX = -1;
+ combatAICenterZ = -1;
+
+ }
+
+
+
+ public void processAI(){
+ frameAI = mainThread.ec.frameAI;
+
+ //set the rally point to near the construction yard which is closest to the AI player's starting position
+ float x = 0;
+ float z = 999999;
+
+
+ int numberOfLightTanks_AI = mainThread.ec.theUnitProductionAI.numberOfLightTanksControlledByCombatAI;
+ int numberOfRocketTanks_AI = mainThread.ec.theUnitProductionAI.numberOfRocketTanksControlledByCombatAI;
+ int numberOfStealthTanks_AI = mainThread.ec.theUnitProductionAI.numberOfStealthTanksControlledByCombatAI;
+ int numberOfHeavyTanks_AI = mainThread.ec.theUnitProductionAI.numberOfHeavyTanksControlledByCombatAI;
+ boolean unitCountLow = mainThread.ec.theCombatManagerAI.unitCountLow;
+
+ int index = 0;
+ for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
+ if(mainThread.theAssetManager.constructionYards[i] != null && mainThread.theAssetManager.constructionYards[i].currentHP > 0 && mainThread.theAssetManager.constructionYards[i].teamNo != 0){
+ if(unitCountLow && mainThread.ec.theDefenseManagerAI.majorThreatLocation.x != 0) {
+ float xPos1 = mainThread.theAssetManager.constructionYards[i].centre.x;
+ float zPos1 = mainThread.theAssetManager.constructionYards[i].centre.z;
+ float xPos2 = mainThread.ec.theDefenseManagerAI.majorThreatLocation.x;
+ float zPos2 = mainThread.ec.theDefenseManagerAI.majorThreatLocation.z;
+ float d = (xPos1 - xPos2) * (xPos1 - xPos2) + (zPos1 - zPos2) * (zPos1 - zPos2);
+ if(d < 9) {
+ continue;
+ }
+ }
+
+ index = i;
+ if(mainThread.theAssetManager.constructionYards[i].centre.z < z && mainThread.theAssetManager.constructionYards[i].centre.z > 7 && mainThread.theAssetManager.constructionYards[i].centre.x > 7){
+ x = mainThread.theAssetManager.constructionYards[i].centre.x;
+ z = mainThread.theAssetManager.constructionYards[i].centre.z;
+ }
+ }
+ }
+ if(z != 999999) {
+
+ rallyPoint.set(x - 2f, 0, z - 1.5f);
+
+ if(frameAI < 240 && mainThread.ec.difficulty == 2) {
+ rallyPoint.set(mainThread.theAssetManager.goldMines[5].centre);
+ }
+ }else {
+ if(mainThread.theAssetManager.constructionYards[index] != null && mainThread.theAssetManager.constructionYards[index].teamNo !=0)
+ rallyPoint.set(mainThread.theAssetManager.constructionYards[index].centre.x - 2.5f, 0, mainThread.theAssetManager.constructionYards[index].centre.z -2.5f);
+ }
+
+ //If the difficulty is set to normal or hard, set the rally point just outside of player's natural expansion.
+ //So if the player is going for a fast expansion and don't have much units, the AI can perform a rush attack.
+ //if(mainThread.ec.theMapAwarenessAI.canRushPlayer && frameAI < 360 && mainThread.ec.theCombatManagerAI.checkIfAIHasBiggerForce(0.75f)) {
+ // rallyPoint.set(rushRallyPointX, 0, rushRallyPointZ);
+ //}
+
+ //make sure not to over produce when the resource is running low
+ int maxNumOfUnitCanBeProduced = theBaseInfo.currentCredit / 500 + 1;
+
+
+ for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
+ factory f = mainThread.theAssetManager.factories[i];
+ if(f != null && f.teamNo !=0){
+ if(!f.isIdle())
+ maxNumOfUnitCanBeProduced--;
+ }
+ }
+
+ for(int i = 0; i < mainThread.theAssetManager.constructionYards.length; i++){
+ constructionYard c = mainThread.theAssetManager.constructionYards[i];
+ if(c != null && c.teamNo !=0){
+ if(!c.isIdle())
+ maxNumOfUnitCanBeProduced--;
+ }
+ }
+
+
+ if(mainThread.ec.difficulty > 0) {
+ //make decision on what unit to produce
+ int numberOfPlayerGunTurrets= mainThread.ec.theMapAwarenessAI.numberOfGunTurret_player;
+ int numberOfPlayerMissileTurrets= mainThread.ec.theMapAwarenessAI.numberOfMissileTurret_player;
+ int numberOfLightTanks_player = mainThread.ec.theMapAwarenessAI.numberOfLightTanks_player;
+ int numberOfRocketTanks_player = mainThread.ec.theMapAwarenessAI.numberOfRocketTanks_player;
+ int numberOfStealthTanks_player = mainThread.ec.theMapAwarenessAI.numberOfStealthTanks_player;
+ int numberOfHeavyTanks_player = mainThread.ec.theMapAwarenessAI.numberOfHeavyTanks_player;
+ int maxNumberOfStealthTanks_playerInLastFiveMinutes = mainThread.ec.theMapAwarenessAI.maxNumberOfStealthTanks_playerInLastFiveMinutes;
+
+ boolean playerHasMostlyLightTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyLightTanks;
+ boolean playerHasMostlyHeavyTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyTanks;
+ boolean playIsRushingHighTierUnits = mainThread.ec.theMapAwarenessAI.playIsRushingHighTierUnits;
+ boolean playerLikelyCanNotProduceHighTierUnits = mainThread.ec.theMapAwarenessAI.playerLikelyCanNotProduceHighTierUnits;
+ boolean playerDoesntHaveMassHeavyTanks = mainThread.ec.theMapAwarenessAI.playerDoesntHaveMassHeavyTanks;
+ boolean playerHasManyLightTanksButNoHeavyTank = mainThread.ec.theMapAwarenessAI.playerHasManyLightTanksButNoHeavyTank;
+ boolean playerHasMostlyHeavyAndStealthTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyHeavyAndStealthTanks;
+ boolean playerHasMostlyLightAndStealthTanks = mainThread.ec.theMapAwarenessAI.playerHasMostlyLightAndStealthTanks;
+ boolean playerArmyCanBeCounteredWithLightTanks = mainThread.ec.theMapAwarenessAI.playerArmyCanBeCounteredWithLightTanks;
+ boolean playerArmyCanBeCounteredWithStealthTanks = mainThread.ec.theMapAwarenessAI.playerArmyCanBeCounteredWithStealthTanks;
+
+ int timeToBuildHeavyTank = 500;
+ int timeToBuildStealthTank = 200;
+ if(mainThread.ec.theMapAwarenessAI.canRushPlayer) {
+ //when AI decides to rush the player, then dont build higher tier units so it can mass produce light tanks
+ timeToBuildHeavyTank = 500;
+ timeToBuildStealthTank = 300;
+ }
+
+ boolean b1 = (numberOfRocketTanks_AI < 3 && !playerHasMostlyHeavyTanks && (frameAI > 400 || frameAI > 170 && frameAI < 240 && mainThread.ec.theMapAwarenessAI.numberOfConstructionYard_player > 0) && !playerHasMostlyLightTanks);
+ boolean b2 = (numberOfRocketTanks_AI < numberOfPlayerGunTurrets + numberOfPlayerMissileTurrets*1.5);
+ if( b1 || b2){
+ currentProductionOrder = produceRocketTank;
+ }else if(theBaseInfo.canBuildHeavyTank && numberOfHeavyTanksControlledByCombatAI < 20 && !(numberOfStealthTanksControlledByCombatAI < 1) && !playerHasMostlyHeavyTanks && !playerHasMostlyLightTanks && !playerHasMostlyLightAndStealthTanks && !playerArmyCanBeCounteredWithLightTanks && !playerArmyCanBeCounteredWithStealthTanks &&
+ (playerHasMostlyHeavyAndStealthTanks || (frameAI > timeToBuildHeavyTank && numberOfHeavyTanks_AI < 3) ||
+ !playerHasManyLightTanksButNoHeavyTank
+ && !(numberOfHeavyTanks_player == 0 && maxNumberOfStealthTanks_playerInLastFiveMinutes < 3 && frameAI > 600)
+ && !(playerHasMostlyHeavyTanks && numberOfStealthTanks_player < numberOfHeavyTanks_AI*2)
+ && (playIsRushingHighTierUnits || maxNumberOfStealthTanks_playerInLastFiveMinutes*4 > numberOfHeavyTanks_AI))){
+ currentProductionOrder = produceHeavyTank;
+ }else if(theBaseInfo.canBuildStealthTank && ((numberOfStealthTanksControlledByCombatAI < 1) || (playerDoesntHaveMassHeavyTanks && !playerHasMostlyHeavyTanks && !playerArmyCanBeCounteredWithLightTanks && !(numberOfStealthTanksControlledByCombatAI >= 9 && frameAI < 600) && !(numberOfStealthTanksControlledByCombatAI >= 18 && frameAI > 600)
+ && (playerHasMostlyLightTanks || playerLikelyCanNotProduceHighTierUnits || playerDoesntHaveMassHeavyTanks || playerHasMostlyLightAndStealthTanks) && !playerHasMostlyHeavyTanks && (frameAI > timeToBuildStealthTank || numberOfLightTanks_player > 8)))){
+ currentProductionOrder = produceStealthTank;
+ }else{
+ currentProductionOrder = produceLightTank;
+ }
+
+ //make decision on what tech to research
+ if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfCommunicationCenter > 0 && mainThread.ec.difficulty > 1) {
+ if(mainThread.ec.theDefenseManagerAI.needMissileTurret || theBaseInfo.currentCredit > 1500 && frameAI > 450) {
+ if(!communicationCenter.rapidfireResearched_enemy) {
+ if(communicationCenter.rapidfireResearchProgress_enemy == 255){
+ communicationCenter.researchRapidfire(1);
+ System.out.println("----------------------------AI starts researching rapid fire ability------------------------------------");
+ }
+ }
+ }
+
+ if(mainThread.ec.theEconomyManagerAI.numberOfharvesters >= 6 && theBaseInfo.currentCredit > 1500 && mainThread.ec.difficulty > 1) {
+ if(!communicationCenter.harvesterSpeedResearched_enemy) {
+ if(communicationCenter.harvesterSpeedResearchProgress_enemy == 255){
+ communicationCenter.researchHarvesterSpeed(1);
+ System.out.println("----------------------------AI starts researching harvester speed ability------------------------------------");
+ }
+ }
+ }
+ }
+
+ if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfTechCenter > 0){
+
+ //Immediately start stealth tank upgrades when a tech center is built
+ if(!techCenter.stealthTankResearched_enemy){
+ if(techCenter.stealthTankResearchProgress_enemy == 255){
+ techCenter.cancelResearch(1);
+ techCenter.researchStealthTank(1);
+ System.out.println("----------------------------AI starts researching stealth tank------------------------------------");
+ }
+ }
+
+
+ if(numberOfLightTanks_AI >= 15 && theBaseInfo.currentCredit > 1000){
+ if(!techCenter.lightTankResearched_enemy){
+ if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
+ techCenter.researchLightTank(1);
+ System.out.println("----------------------------AI starts researching light tank------------------------------------");
+ }
+ }
+ }
+
+ if(numberOfRocketTanks_AI > 2 && theBaseInfo.currentCredit > 1250 && (numberOfPlayerGunTurrets > 0 || numberOfPlayerMissileTurrets > 0 || frameAI > 600)){
+ if(!techCenter.rocketTankResearched_enemy){
+ if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
+
+ techCenter.researchRocketTank(1);
+ System.out.println("----------------------------AI starts researching rocket tank------------------------------------");
+ }
+ }
+ }
+
+ if(numberOfHeavyTanks_AI > 5 && theBaseInfo.currentCredit > 1000){
+ if(!techCenter.heavyTankResearched_enemy){
+ if(techCenter.lightTankResearchProgress_enemy >= 240 && techCenter.stealthTankResearchProgress_enemy >= 240 && techCenter.rocketTankResearchProgress_enemy >= 240 && techCenter.heavyTankResearchProgress_enemy >= 240){
+ techCenter.researchHeavyTank(1);
+ System.out.println("----------------------------AI starts researching heavy tank------------------------------------");
+ }
+ }
+ }
+
+
+ }
+ }else {
+ //cap the number of units that can be built by the AI in easy difficulty
+ int roll = gameData.getRandom();
+ currentProductionOrder = -1;
+ if((roll < 612) && (numberOfLightTanksControlledByCombatAI < 7)) {
+ currentProductionOrder = produceLightTank;
+ }else if(roll >= 612 && roll < 700 && numberOfRocketTanksControlledByCombatAI < 2) {
+ currentProductionOrder = produceRocketTank;
+ }else if(roll >= 700 && roll < 900 && numberOfStealthTanksControlledByCombatAI < 2) {
+ currentProductionOrder = produceStealthTank;
+ }else if(numberOfHeavyTanksControlledByCombatAI < 1){
+ currentProductionOrder = produceHeavyTank;
+ }
+ }
+
+
+ for(int i = 0; i < mainThread.theAssetManager.factories.length; i++){
+ factory f = mainThread.theAssetManager.factories[i];
+ if(f != null && f.teamNo !=0){
+ f.moveTo(rallyPoint.x, rallyPoint.z);
+ if(f.isIdle()){
+ if(theBaseInfo.canBuildLightTank && maxNumOfUnitCanBeProduced > 0){
+
+ if(currentProductionOrder == produceLightTank)
+ f.buildLightTank();
+ else if(currentProductionOrder == produceRocketTank)
+ f.buildRocketTank();
+ else if(currentProductionOrder == produceStealthTank)
+ f.buildStealthTank();
+ else if(currentProductionOrder == produceHeavyTank)
+ f.buildHeavyTank();
+
+ maxNumOfUnitCanBeProduced--;
+ }
+ continue;
+ }
+ }
+ }
+
+
+ countTroopControlledByCombatAI();
+ findCenterOfTroopControlledByCombatAI();
+
+ }
+
+ public void addLightTank(lightTank o){
+ //check if other AI agent need light tank
+
+ if(mainThread.ec.theScoutingManagerAI.needLightTank()){
+ mainThread.ec.theScoutingManagerAI.addLightTank(o);
+
+ return;
+ }
+
+
+ //add the new light tank to combat AI's command
+ for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
+ if(lightTanksControlledByCombatAI[i] == null || (lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP <=0)){
+ lightTanksControlledByCombatAI[i] = o;
+ if(mainThread.ec.difficulty > 0)
+ mainThread.ec.theDefenseManagerAI.addUnitToDefenders(o);
+ break;
+ }
+ }
+
+
+ }
+
+ public void addRocketTank(rocketTank o){
+ //check if other AI agent need rocket tank
+
+ //add the new rocket tank to combat AI's command
+ for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
+ if(rocketTanksControlledByCombatAI[i] == null || (rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP <=0)){
+ rocketTanksControlledByCombatAI[i] = o;
+ break;
+ }
+ }
+ }
+
+ public void addStealthTank(stealthTank o){
+ //check if other AI agent need stealth tank
+
+ if(mainThread.ec.theScoutingManagerAI.needStealthTank()){
+ mainThread.ec.theScoutingManagerAI.addStealthTank(o);
+ return;
+ }
+
+ if(mainThread.ec.theBaseExpentionAI.needStealthTank()){
+ mainThread.ec.theBaseExpentionAI.addStealthTank(o);
+ return;
+ }
+
+
+
+ //add the new stealth tank to combat AI's command
+ for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
+ if(stealthTanksControlledByCombatAI[i] == null || (stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP <=0)){
+ stealthTanksControlledByCombatAI[i] = o;
+ if(mainThread.ec.difficulty > 0)
+ mainThread.ec.theDefenseManagerAI.addUnitToDefenders(o);
+ break;
+ }
+ }
+ }
+
+ public void addHeavyTank(heavyTank o){
+ //add the new heavy tank to combat AI's command
+ for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
+ if(heavyTanksControlledByCombatAI[i] == null || (heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP <=0)){
+ heavyTanksControlledByCombatAI[i] = o;
+ break;
+ }
+ }
+ }
+
+
+ public void countTroopControlledByCombatAI(){
+ numberOfCombatUnitsUnderAttack = 0;
+
+ numberOfLightTanksControlledByCombatAI = 0;
+ numberOfRocketTanksControlledByCombatAI = 0;
+ numberOfStealthTanksControlledByCombatAI = 0;
+ numberOfHeavyTanksControlledByCombatAI = 0;
+
+ for(int i = 0; i < troopsControlledByCombatAI.length; i++){
+ troopsControlledByCombatAI[i] = null;
+ }
+
+ numberOfCombatUnit = 0;
+ for(int i = 0; i < lightTanksControlledByCombatAI.length; i++){
+ if(lightTanksControlledByCombatAI[i] != null && lightTanksControlledByCombatAI[i].currentHP > 0){
+ troopsControlledByCombatAI[numberOfCombatUnit] = lightTanksControlledByCombatAI[i];
+ if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
+ numberOfCombatUnitsUnderAttack++;
+ numberOfCombatUnit++;
+ numberOfLightTanksControlledByCombatAI++;
+ }
+ }
+ for(int i = 0; i < rocketTanksControlledByCombatAI.length; i++){
+ if(rocketTanksControlledByCombatAI[i] != null && rocketTanksControlledByCombatAI[i].currentHP > 0){
+ troopsControlledByCombatAI[numberOfCombatUnit] = rocketTanksControlledByCombatAI[i];
+ if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
+ numberOfCombatUnitsUnderAttack++;
+ numberOfCombatUnit++;
+ numberOfRocketTanksControlledByCombatAI++;
+ }
+ }
+ for(int i = 0; i < stealthTanksControlledByCombatAI.length; i++){
+ if(stealthTanksControlledByCombatAI[i] != null && stealthTanksControlledByCombatAI[i].currentHP > 0){
+ troopsControlledByCombatAI[numberOfCombatUnit] = stealthTanksControlledByCombatAI[i];
+ if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
+ numberOfCombatUnitsUnderAttack++;
+ numberOfCombatUnit++;
+ numberOfStealthTanksControlledByCombatAI++;
+ }
+ }
+ for(int i = 0; i < heavyTanksControlledByCombatAI.length; i++){
+ if(heavyTanksControlledByCombatAI[i] != null && heavyTanksControlledByCombatAI[i].currentHP > 0){
+ troopsControlledByCombatAI[numberOfCombatUnit] = heavyTanksControlledByCombatAI[i];
+ if(troopsControlledByCombatAI[numberOfCombatUnit].underAttackCountDown > 0)
+ numberOfCombatUnitsUnderAttack++;
+ numberOfCombatUnit++;
+ numberOfHeavyTanksControlledByCombatAI++;
+ }
+ }
+ }
+
+ public void findCenterOfTroopControlledByCombatAI(){
+ float centerX = 0;
+ float centerZ = 0;
+
+ vector centre;
+ double distance = 0;
+
+ numberOfUnitInCombatRadius = 0;
+ numberOfUnitOutsideCombatRadius = 0;
+
+
+ //when there is no combat unit there is no point to calculate the center of the combat units
+ if(numberOfCombatUnit == 0){
+ combatAICenterX = -1;
+ combatAICenterZ = -1;
+ return;
+ }
+
+ for(int i = 0; i < unitInCombatRadius.length; i++){
+ unitInCombatRadius[i] = null;
+ }
+
+ for(int i = 0; i < unitOutsideCombatRadius.length; i++){
+ unitOutsideCombatRadius[i] = null;
+ }
+
+
+ //calculate the center of the troops using the all the unites that are under the control of the combatAI
+ if(combatAICenterX == -1){
+ combatAICenterX = 0;
+ combatAICenterZ = 0;
+ for(int i =0; i < numberOfCombatUnit; i++){
+ centre = troopsControlledByCombatAI[i].centre;
+ combatAICenterX+=centre.x;
+ combatAICenterZ+=centre.z;
+ }
+ combatAICenterX /= numberOfCombatUnit;
+ combatAICenterZ /= numberOfCombatUnit;
+ }
+
+ //exclude the units are too far away from the center of the troops, (i.e the unites that just come out of the factory), and recalculate the center
+ for(int i =0; i < numberOfCombatUnit; i++){
+ centre = troopsControlledByCombatAI[i].centre;
+ distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
+ if(distance < 4.5){
+ centerX += centre.x;
+ centerZ += centre.z;
+ if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
+ unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
+ numberOfUnitInCombatRadius++;
+ }else{
+ if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
+ unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
+ numberOfUnitOutsideCombatRadius++;
+ }
+ }
+
+ float unitInCombactRadiusPercentage = 1;
+ if(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius >0)
+ unitInCombactRadiusPercentage = (float)numberOfUnitInCombatRadius/(float)(numberOfUnitInCombatRadius + numberOfUnitOutsideCombatRadius);
+
+ float unitInCombactRadiusPercentageThreshold = 0.7f;
+ if(mainThread.ec.theCombatManagerAI.currentState == mainThread.ec.theCombatManagerAI.aggressing) {
+ if(mainThread.ec.theCombatManagerAI.distanceToTarget < 6)
+ unitInCombactRadiusPercentageThreshold = 0.475f;
+ }
+ if(numberOfCombatUnitsUnderAttack > 0)
+ unitInCombactRadiusPercentageThreshold = 0.25f;
+
+ //need to recalculate the center if there is a significant amount of combat unites that are outside of the combat radius
+ if(unitInCombactRadiusPercentage < unitInCombactRadiusPercentageThreshold){
+
+ combatAICenterX = 0;
+ combatAICenterZ = 0;
+ for(int i =0; i < numberOfCombatUnit; i++){
+ centre = troopsControlledByCombatAI[i].centre;
+ combatAICenterX+=centre.x;
+ combatAICenterZ+=centre.z;
+ }
+ combatAICenterX /= numberOfCombatUnit;
+ combatAICenterZ /= numberOfCombatUnit;
+
+ for(int i = 0; i < unitInCombatRadius.length; i++){
+ unitInCombatRadius[i] = null;
+ }
+
+ for(int i = 0; i < unitOutsideCombatRadius.length; i++){
+ unitOutsideCombatRadius[i] = null;
+ }
+ numberOfUnitInCombatRadius = 0;
+ numberOfUnitOutsideCombatRadius = 0;
+ centerX = 0;
+ centerZ = 0;
+
+ for(int i =0; i < numberOfCombatUnit; i++){
+ centre = troopsControlledByCombatAI[i].centre;
+ distance = Math.sqrt((centre.x - combatAICenterX)*(centre.x - combatAICenterX) + (centre.z - combatAICenterZ)*(centre.z - combatAICenterZ));
+ if(distance < 10){
+ centerX += centre.x;
+ centerZ += centre.z;
+ if(numberOfUnitInCombatRadius < unitInCombatRadius.length)
+ unitInCombatRadius[numberOfUnitInCombatRadius] = troopsControlledByCombatAI[i];
+ numberOfUnitInCombatRadius++;
+ }else{
+ if(numberOfUnitOutsideCombatRadius < unitOutsideCombatRadius.length)
+ unitOutsideCombatRadius[numberOfUnitOutsideCombatRadius] = troopsControlledByCombatAI[i];
+ numberOfUnitOutsideCombatRadius++;
+ }
+ }
+ }
+
+ combatAICenterX = centerX/numberOfUnitInCombatRadius;
+ combatAICenterZ = centerZ/numberOfUnitInCombatRadius;
+
+ }
+}