BWAPI
|
00001 #include "PsiStormAction.h" 00002 00003 #include "UnitTracker.h" 00004 #include "UnitInformation.h" 00005 #include "LatencyTracker.h" 00006 #include "Logger.h" 00007 00008 bool PsiStormAction::update(const Goal &squadGoal, const UnitGroup &squadUnitGroup) 00009 { 00010 if(mUnit->getOrder() == BWAPI::Orders::CastPsionicStorm) 00011 return true; 00012 00013 //TODO : Morph arcon temp in here with some non ideal code till group micro actions is complete, checks if it can actually morph the archon, 00014 // ie not using 3.6 00015 static bool allowsArchonMorph = true; 00016 if(allowsArchonMorph) 00017 { 00018 if(mUnit->getOrder() == BWAPI::Orders::ArchonWarp) 00019 return true; 00020 00021 bool warpPriorityLow = squadGoal.getActionType() != ActionType::Attack || squadGoal.getGoalType() != GoalType::Base || mUnit->getPosition().getApproxDistance(squadGoal.getBase()->getCenterLocation()) > 32*20; 00022 const int energyToTransformAt = warpPriorityLow ? 48 : 65; 00023 if(mUnit->getEnergy() <= energyToTransformAt) 00024 { 00025 Unit otherTemp; 00026 int closestDistance = std::numeric_limits<int>::max(); 00027 for each(Unit ht in UnitTracker::Instance().selectAllUnits(BWAPI::UnitTypes::Protoss_High_Templar)) 00028 { 00029 if(ht == mUnit) 00030 continue; 00031 00032 if(ht->getOrder() == BWAPI::Orders::ArchonWarp) 00033 continue; 00034 00035 if(ht->getEnergy() > energyToTransformAt) 00036 continue; 00037 00038 int distance = mUnit->getDistance(ht); 00039 if(distance < closestDistance) 00040 { 00041 closestDistance = distance; 00042 otherTemp = ht; 00043 } 00044 } 00045 00046 if(otherTemp) 00047 { 00048 Unit otherClosestTemp; 00049 int otherClosestDistance = std::numeric_limits<int>::max(); 00050 for each(Unit ht in UnitTracker::Instance().selectAllUnits(BWAPI::UnitTypes::Protoss_High_Templar)) 00051 { 00052 if(ht == otherTemp) 00053 continue; 00054 00055 if(ht->getOrder() == BWAPI::Orders::ArchonWarp) 00056 continue; 00057 00058 if(ht->getEnergy() > energyToTransformAt) 00059 continue; 00060 00061 int distance = otherTemp->getDistance(ht); 00062 if(distance < otherClosestDistance) 00063 { 00064 otherClosestDistance = distance; 00065 otherClosestTemp = ht; 00066 } 00067 } 00068 00069 if(otherClosestTemp == mUnit) 00070 { 00071 mUnit->useTech(BWAPI::TechTypes::Archon_Warp, otherTemp); 00072 otherTemp->useTech(BWAPI::TechTypes::Archon_Warp, mUnit); 00073 00074 if(BWAPI::Broodwar->getLastError() == BWAPI::Errors::Incompatible_TechType) 00075 { 00076 LOGMESSAGEERROR("Archon Warp Failed, Old BWAPI Version?"); 00077 allowsArchonMorph = false; 00078 } 00079 00080 return true; 00081 } 00082 } 00083 } 00084 } 00085 00086 if(mUnit->getSpellCooldown() > BWAPI::Broodwar->getRemainingLatencyFrames()) 00087 return false; 00088 00089 if(BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Psionic_Storm) && mUnit->getEnergy() >= BWAPI::TechTypes::Psionic_Storm.energyUsed()) 00090 { 00091 int numTargetting = UnitInformation::Instance().getUnitsTargetting(mUnit).size(); 00092 00093 UnitGroup targetsToChooseFrom; 00094 00095 for each(Unit unit in UnitTracker::Instance().selectAllEnemy()) 00096 { 00097 if(!unit->exists() || unit->isStasised() || unit->isUnderStorm()) 00098 continue; 00099 00100 const BWAPI::UnitType &type = unit->getType(); 00101 if(type.isBuilding() || type == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine || type == BWAPI::UnitTypes::Zerg_Egg || type == BWAPI::UnitTypes::Protoss_Interceptor || type == BWAPI::UnitTypes::Zerg_Larva || type == BWAPI::UnitTypes::Protoss_Scarab) 00102 continue; 00103 00104 if(mUnit->getDistance(unit) > BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange()) 00105 continue; 00106 00107 targetsToChooseFrom.insert(unit); 00108 } 00109 00110 UnitGroup targets(targetsToChooseFrom); 00111 00112 bool castUrgenty = (numTargetting > 2 || (numTargetting > 0 && mUnit->totalHitPointFraction() < 0.6)); 00113 00114 int tries = 0; 00115 bool tryAgain = true; 00116 while(tryAgain) 00117 { 00118 tryAgain = false; 00119 00120 /* There are 3 targets or there are targets and we need to cast urgently */ 00121 if(targets.size() >= 3 || (castUrgenty && !targets.empty())) 00122 { 00123 targets = targets.getBestFittingToCircle(64, BWAPI::Broodwar->getRemainingLatencyFrames()+BWAPI::Broodwar->getLatencyFrames()); 00124 if(targets.size() >= 3 || (castUrgenty && !targets.empty())) 00125 { 00126 BWAPI::Position castLocation = targets.getCenter(); 00127 00128 int inStormCount = 0; 00129 for each(Unit unit in UnitTracker::Instance().selectAllUnits()) 00130 { 00131 if(!unit->isUnderStorm() && unit->getDistance(castLocation) < 64) 00132 ++inStormCount; 00133 00134 if(inStormCount > 1) 00135 break; 00136 } 00137 00138 if(inStormCount <= 1) 00139 { 00140 int distanceToStorm = mUnit->getDistance(castLocation); 00141 if(distanceToStorm <= BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange()) 00142 { 00143 mUnit->useTech(BWAPI::TechTypes::Psionic_Storm, castLocation); 00144 LatencyTracker::Instance().placingStorm(mUnit, castLocation); 00145 } 00146 else 00147 { 00148 Vector newCastLocation = mUnit->getPosition() - castLocation; 00149 00150 newCastLocation.normalise(); 00151 00152 newCastLocation *= float(distanceToStorm - BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange()); 00153 00154 newCastLocation += Vector(castLocation); 00155 00156 mUnit->useTech(BWAPI::TechTypes::Psionic_Storm, newCastLocation); 00157 LatencyTracker::Instance().placingStorm(mUnit, newCastLocation); 00158 } 00159 00160 return true; 00161 } 00162 else 00163 { 00164 ++tries; 00165 if(tries < 3) 00166 { 00167 targets = targetsToChooseFrom; 00168 for each(Unit unit in targetsToChooseFrom) 00169 { 00170 if(unit->getDistance(castLocation) < 64) 00171 targets.erase(unit); 00172 } 00173 00174 if(targets.size() >= 3 || (castUrgenty && !targets.empty())) 00175 tryAgain = true; 00176 } 00177 } 00178 } 00179 } 00180 } 00181 } 00182 00183 return false; 00184 }