diff --git a/core/AssetManager.java b/core/AssetManager.java index f6e5b4b..a90cc24 100644 --- a/core/AssetManager.java +++ b/core/AssetManager.java @@ -261,7 +261,8 @@ public class AssetManager { //lightTank.tileCheckList_player = lightTank.generateTileCheckList(6); //addLightTank(l); - //addGunTurret(new gunTurret(i*0.25f -0.125f + 13, -0.65f, 0.25f + 20.125f + j*0.25f, 0)); + //if(j == 0 && i == 0) + //addGunTurret(new gunTurret(i*0.25f -0.125f + 28, -0.65f, 0.25f + 28.125f + j*0.25f, 1)); } } diff --git a/core/baseInfo.java b/core/baseInfo.java index f905c84..d3d4bfa 100644 --- a/core/baseInfo.java +++ b/core/baseInfo.java @@ -70,8 +70,7 @@ public class baseInfo { } - currentPowerLevel = numberOfPowerPlant*500 + numberOfConstructionYard*100; - currentPowerConsumption = numberOfRefinery*150 + numberOfFactory*200 + numberOfCommunicationCenter*250 + numberOfGunTurret*100 + numberOfMissileTurret*200 + numberOfOverChargedMissileTurret*150 + numberOfTechCenter*400; + reCalculatePower(); //calculate power level and power consumption if(currentPowerLevel == 0){ @@ -90,4 +89,9 @@ public class baseInfo { } + public void reCalculatePower() { + currentPowerLevel = numberOfPowerPlant*500 + numberOfConstructionYard*100; + currentPowerConsumption = numberOfRefinery*150 + numberOfFactory*200 + numberOfCommunicationCenter*250 + numberOfGunTurret*100 + numberOfMissileTurret*200 + numberOfOverChargedMissileTurret*150 + numberOfTechCenter*400; + } + } diff --git a/core/mainThread.java b/core/mainThread.java index 8048ff8..fb013d0 100644 --- a/core/mainThread.java +++ b/core/mainThread.java @@ -492,13 +492,11 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M framePerSecond = (int)(1000/((thisTime - lastTime)/30)); lastTime = thisTime; } -<<<<<<< HEAD - sleepTime = 0; - while(System.currentTimeMillis()-lastDraw>>>>>> branch 'master' of https://github.com/phu004/JavaRTS.git + try { Thread.sleep(1); sleepTime++; @@ -506,7 +504,7 @@ public class mainThread extends JFrame implements KeyListener, ActionListener, M // TODO Auto-generated catch block e1.printStackTrace(); } - } + }*/ lastDraw=System.currentTimeMillis(); } diff --git a/enemyAI/buildingManagerAI.java b/enemyAI/buildingManagerAI.java index 0ca737b..5345255 100644 --- a/enemyAI/buildingManagerAI.java +++ b/enemyAI/buildingManagerAI.java @@ -100,6 +100,7 @@ public class buildingManagerAI { public void processAI(){ frameIndex++; + powerPlantUnderConstruction = buildingUnderProduction(101); @@ -108,13 +109,22 @@ public class buildingManagerAI { addBuildingToQueue(101); } + //build a gun turret if there is a need for it + if(theBaseInfo.canBuildGunTurret && mainThread.ec.theDefenseManagerAI.needGunTurret) { + addBuildingToQueue(200); + } + + //build missile turret if there is a need for it + if(theBaseInfo.canBuildMissileTurret && mainThread.ec.theDefenseManagerAI.needMissileTurret) { + addBuildingToQueue(199); + } + //build a refinery center if there isn't any if(theBaseInfo.numberOfRefinery == 0 && theBaseInfo.canBuildRefinery){ addBuildingToQueue(102); } - //build an additional refinery if there are more production building //don't build more than 2 refinery around a goldmine if(getNumberOfFunctionalRefinery() < theBaseInfo.numberOfConstructionYard*2 && theBaseInfo.numberOfFactory > 0 && theBaseInfo.canBuildRefinery && getNumberOfRefineriesNearPreferedGoldMine() < 2){ @@ -221,12 +231,89 @@ public class buildingManagerAI { } } + //deploy gun turret + if(constructionYards[i].gunTurretProgress == 240) { + float xPos = mainThread.ec.theDefenseManagerAI.gunTurretDeployLocation.x; + float zPos = mainThread.ec.theDefenseManagerAI.gunTurretDeployLocation.z; + int centerTile = (int)(xPos*64)/16 + (127 - (int)(zPos*64)/16)*128; + if(xPos != 0) { + if(hasRoomForPlacement(200, centerTile)) { + int y = 127 - placementTile/128; + int x = placementTile%128; + gunTurret o = new gunTurret(x*0.25f + 0.125f, -0.65f, y*0.25f + 0.125f, 1); + mainThread.theAssetManager.addGunTurret(o); + + constructionYards[i].finishDeployment(); + } + } + } + + //deploy missile turret + if(constructionYards[i].missileTurretProgress == 240) { + float xPos = mainThread.ec.theDefenseManagerAI.missileTurretDeployLocation.x; + float zPos = mainThread.ec.theDefenseManagerAI.missileTurretDeployLocation.z; + int centerTile = (int)(xPos*64)/16 + (127 - (int)(zPos*64)/16)*128; + if(xPos != 0) { + if(hasRoomForPlacement(200, centerTile)) { + int y = 127 - placementTile/128; + int x = placementTile%128; + missileTurret o = new missileTurret(x*0.25f + 0.125f, -0.65f, y*0.25f + 0.125f, 1); + mainThread.theAssetManager.addMissileTurret(o); + constructionYards[i].finishDeployment(); + } + } + + } } } } public boolean hasRoomForPlacement(int buildingType, int centerTile){ + //check placement for turrets + if(buildingType == 199 || buildingType == 200) { + if(checkIfBlockIsFree(centerTile)) { + placementTile = centerTile; + return true; + }else if(checkIfBlockIsFree(centerTile + 1)) { + placementTile = centerTile + 1; + return true; + }else if(checkIfBlockIsFree(centerTile - 1)) { + placementTile = centerTile - 1; + return true; + }else if(checkIfBlockIsFree(centerTile + 128)) { + placementTile = centerTile + 128; + return true; + }else if(checkIfBlockIsFree(centerTile - 128)) { + placementTile = centerTile - 128; + return true; + }else if(checkIfBlockIsFree(centerTile - 129)) { + placementTile = centerTile - 129; + return true; + }else if(checkIfBlockIsFree(centerTile - 127)) { + placementTile = centerTile - 127; + return true; + }else if(checkIfBlockIsFree(centerTile + 127)) { + placementTile = centerTile + 127; + return true; + }else if(checkIfBlockIsFree(centerTile + 129)) { + placementTile = centerTile + 129; + return true; + }else if(checkIfBlockIsFree(centerTile + 2)) { + placementTile = centerTile + 2; + return true; + }else if(checkIfBlockIsFree(centerTile - 2)) { + placementTile = centerTile - 2; + return true; + }else if(checkIfBlockIsFree(centerTile + 256)) { + placementTile = centerTile + 256; + return true; + }else if(checkIfBlockIsFree(centerTile - 256)) { + placementTile = centerTile - 256; + return true; + } + } + //check placement for power plant if(buildingType == 101){ diff --git a/enemyAI/defenseManagerAI.java b/enemyAI/defenseManagerAI.java index 31f5809..c6f1f3b 100644 --- a/enemyAI/defenseManagerAI.java +++ b/enemyAI/defenseManagerAI.java @@ -6,7 +6,10 @@ import core.vector; import entity.lightTank; import entity.solidObject; import entity.stealthTank; +import entity.communicationCenter; import entity.constructionYard; +import entity.gunTurret; +import entity.missileTurret; public class defenseManagerAI { public baseInfo theBaseInfo; @@ -33,6 +36,9 @@ public class defenseManagerAI { public vector majorThreatLocation; public int majorThreatCooldown; + public boolean needGunTurret; + public boolean needMissileTurret; + public vector gunTurretDeployLocation; public vector missileTurretDeployLocation; @@ -176,7 +182,7 @@ public class defenseManagerAI { if(majorThreatCooldown == 0) majorThreatLocation.reset(); - // if the size of the player unit cluster is less than 5, and no heavy tanks in the cluster, then borrow some unites from combatAI to deal with the threat + // if the size of the player unit cluster is less than 7, and no heavy tanks in the cluster, then borrow some unites from combatAI to deal with the threat if(mainPlayerForceSize < 7 && mainPlayerForceSize>0) { //check if base is attacked by long ranged units boolean attackedByRocketTank = false; @@ -262,18 +268,64 @@ public class defenseManagerAI { } } + + constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards; + int numOfConstructionYard = 0; + + for(int i = 0; i < constructionYards.length; i++){ + if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].currentHP >0) { + numOfConstructionYard++; + } + } + + boolean gunTurretAlreadyInQueue = false; + boolean missileTurretAlreadyInQueue = false; + //check if AI needs to build static defenses /* build a gun turret when any of the following conditions are met: - 1. there is no threat detected and there are more than 1 construction yard, and there is no other gun turret being constructed at the same time - 2. there are threat detected and there is no other gun turret being constructed at the same time + 1. there are more than 1 construction yard + 2. there is no other gun turret being constructed at the same time + 3. not major threat detected build a missile turret when any of the following conditions are met: - 1. there is no threat detected and there are more than 1 construction yard, and there is no other missile turret being constructed at the same time - 2. there are threat detected and there is no other missile turret being constructed at the same time + 1. there are more than 1 construction yard + 2. there is no other missile turret being constructed at the same time + 3. major threat detected */ - + needGunTurret = false; + needMissileTurret = false; + + if(numOfConstructionYard > 1) { + for(int i = 0; i < constructionYards.length; i ++){ + if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].currentHP > 0){ + if(constructionYards[i].currentBuildingType == 200){ + gunTurretAlreadyInQueue = true; + break; + } + } + } + for(int i = 0; i < constructionYards.length; i ++){ + if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].currentHP > 0){ + if(constructionYards[i].currentBuildingType == 199){ + missileTurretAlreadyInQueue = true; + break; + } + } + } + + + if(!gunTurretAlreadyInQueue && majorThreatLocation.x ==0) { + needGunTurret = true; + } + + if(!missileTurretAlreadyInQueue && majorThreatLocation.x != 0) { + needMissileTurret = true; + } + + + } //check if AI needs to deploy static defense @@ -285,7 +337,43 @@ public class defenseManagerAI { gunTurretDeployLocation.reset(); missileTurretDeployLocation.reset(); - constructionYard[] constructionYards = mainThread.theAssetManager.constructionYards; + int numOfGunTurretNearThreat = 0; + int numOfMissileTurretNearThreat = 0; + + + if(minorThreatLocation.x !=0){ + for(int i = 0; i < AIStructures.length; i++) { + if(AIStructures[i] != null && AIStructures[i].teamNo !=0 && AIStructures[i].currentHP > 0 && (AIStructures[i].type == 200 || AIStructures[i].type == 199)) { + float d = (float)Math.sqrt((minorThreatLocation.x-AIStructures[i].centre.x)*(minorThreatLocation.x-AIStructures[i].centre.x) + + (minorThreatLocation.z-AIStructures[i].centre.z)*(minorThreatLocation.z-AIStructures[i].centre.z)); + + if(AIStructures[i].type == 200 && d <= 2) + numOfGunTurretNearThreat++; + if(AIStructures[i].type == 199 && d <= 2.4) + numOfMissileTurretNearThreat++; + } + } + } + + if(majorThreatLocation.x !=0){ + numOfGunTurretNearThreat = 0; + numOfMissileTurretNearThreat = 0; + + for(int i = 0; i < AIStructures.length; i++) { + if(AIStructures[i] != null && AIStructures[i].teamNo !=0 && AIStructures[i].currentHP > 0 && (AIStructures[i].type == 200 || AIStructures[i].type == 199)) { + float d = (float)Math.sqrt((majorThreatLocation.x-AIStructures[i].centre.x)*(majorThreatLocation.x-AIStructures[i].centre.x) + + (majorThreatLocation.z-AIStructures[i].centre.z)*(majorThreatLocation.z-AIStructures[i].centre.z)); + + if(AIStructures[i].type == 200 && d <= 2) + numOfGunTurretNearThreat++; + if(AIStructures[i].type == 199 && d <= 2.4) + numOfMissileTurretNearThreat++; + } + } + } + + + for(int i = 0; i < constructionYards.length; i++){ if(constructionYards[i] != null && constructionYards[i].teamNo != 0 && constructionYards[i].currentHP >0) { @@ -310,11 +398,53 @@ public class defenseManagerAI { } //find deploy location of gun turret - if(threatX != 0 && distanceToThreat < 4.25) { + if(threatX != 0 && distanceToThreat < 4.75 && numOfGunTurretNearThreat < (float)mainPlayerForceSize/3) { + + float d = 1.75f; //minimum deploy distance from conyard + if(distanceToThreat > d + gunTurret.attackRange) + d = distanceToThreat - gunTurret.attackRange; + + gunTurretDeployLocation.x = constructionYards[i].centre.x + (threatX - constructionYards[i].centre.x)/distanceToThreat*d; + gunTurretDeployLocation.z = constructionYards[i].centre.z + (threatZ - constructionYards[i].centre.z)/distanceToThreat*d; + - //check the number of gun turrets that are already deployed near the threat location } + //find deploy location of missile turret + if(threatX != 0 && distanceToThreat < 5.15 && (numOfMissileTurretNearThreat < mainPlayerForceSize/6 || !gunTurretAlreadyInQueue)) { + + float d = 1.35f; //minimum deploy distance from conyard + if(distanceToThreat > d + missileTurret.attackRange) + d = distanceToThreat - missileTurret.attackRange; + + missileTurretDeployLocation.x = constructionYards[i].centre.x + (threatX - constructionYards[i].centre.x)/distanceToThreat*d; + missileTurretDeployLocation.z = constructionYards[i].centre.z + (threatZ - constructionYards[i].centre.z)/distanceToThreat*d; + } + + + } + } + + //enable rapid fire ability for missiles turrets + if(communicationCenter.rapidfireResearched_enemy) { + for(int i = 0; i < AIStructures.length; i++) { + if(AIStructures[i] != null && AIStructures[i].currentHP > 0 && AIStructures[i].teamNo == 1 && AIStructures[i].type == 199) { + missileTurret t = (missileTurret)AIStructures[i]; + if(t.targetObject != null && t.overCharge == false) { + mainThread.ec.theBaseInfo.numberOfOverChargedMissileTurret++; + t.overCharge = true; + mainThread.ec.theBaseInfo.reCalculatePower(); + if(mainThread.ec.theBaseInfo.currentPowerConsumption > mainThread.ec.theBaseInfo.currentPowerLevel) { + mainThread.ec.theBaseInfo.numberOfOverChargedMissileTurret--; + t.overCharge = false; + mainThread.ec.theBaseInfo.reCalculatePower(); + } + }else if((t.targetObject == null || mainThread.ec.theBaseInfo.currentPowerConsumption > mainThread.ec.theBaseInfo.currentPowerLevel) && t.overCharge == true) { + mainThread.ec.theBaseInfo.numberOfOverChargedMissileTurret--; + t.overCharge = false; + mainThread.ec.theBaseInfo.reCalculatePower(); + } + } } } diff --git a/enemyAI/unitProductionAI.java b/enemyAI/unitProductionAI.java index d6800bc..489ef4e 100644 --- a/enemyAI/unitProductionAI.java +++ b/enemyAI/unitProductionAI.java @@ -171,6 +171,18 @@ public class unitProductionAI { //make decision on what tech to research + + if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfCommunicationCenter > 0) { + if(mainThread.ec.theDefenseManagerAI.needMissileTurret && theBaseInfo.currentCredit > 500) { + if(!communicationCenter.rapidfireResearched_enemy) { + if(communicationCenter.rapidfireResearchProgress_enemy == 255){ + communicationCenter.researchRapidfire(1); + System.out.println("----------------------------AI starts researching rapid fire ability------------------------------------"); + } + } + } + } + if(mainThread.ec.theBuildingManagerAI.theBaseInfo.numberOfTechCenter > 0){ //Immediately start stealth tank upgrades when a tech center is built @@ -220,6 +232,8 @@ public class unitProductionAI { } } } + + } diff --git a/entity/gunTurret.java b/entity/gunTurret.java index 60fc568..bd60acf 100644 --- a/entity/gunTurret.java +++ b/entity/gunTurret.java @@ -49,7 +49,7 @@ public class gunTurret extends solidObject{ public int turretAngle; //attack range - public float attackRange = 2f; + public final static float attackRange = 2f; //the angle that the turret have rotated between current frame and previous frame public int turretAngleDelta, accumulatedDelta; diff --git a/entity/missileTurret.java b/entity/missileTurret.java index f83a1ee..f12cd02 100644 --- a/entity/missileTurret.java +++ b/entity/missileTurret.java @@ -49,7 +49,7 @@ public class missileTurret extends solidObject{ public int turretAngle; //attack range - public float attackRange = 2.4f; + public final static float attackRange = 2.4f; //the angle that the turret have rotated between current frame and previous frame public int turretAngleDelta, accumulatedDelta;