#include "Main.h"
UINT ControlGroupUnitInfo::ComputeResourceValue(const Vector<ControlGroupUnitInfo> &Units)
{
UINT Result = 0;
for(UINT UnitIndex = 0; UnitIndex < Units.Length(); UnitIndex++)
{
UnitEntry *CurEntry = Units[UnitIndex].Entry;
if(CurEntry->Name == "Zergling")
{
Result += 25;
}
else
{
Result += CurEntry->MineralCost + CurEntry->GasCost;
}
}
return Result;
}
String ControlGroupUnitInfo::Describe(const Vector<ControlGroupUnitInfo> &Units)
{
map<UnitEntry*, UINT> UnitCounts;
for(UINT UnitIndex = 0; UnitIndex < Units.Length(); UnitIndex++)
{
UnitEntry *CurEntry = Units[UnitIndex].Entry;
if(UnitCounts.find(CurEntry) == UnitCounts.end())
{
UnitCounts[CurEntry] = 1;
}
else
{
UnitCounts[CurEntry]++;
}
}
String Result;
for(map<UnitEntry*, UINT>::const_iterator Iterator = UnitCounts.begin(); Iterator != UnitCounts.end(); Iterator++)
{
UnitEntry *CurEntry = Iterator->first;
UINT Count = Iterator->second;
Result += CurEntry->Name + String(Count) + String(' ');
}
return Result;
}
void ControlGroupInfo::Reset()
{
Type = ControlGroupUnused;
WorkersAssigned = 0;
ControlGroupLevel = 0;
LastObservedNonBaseUnits.FreeMemory();
LastObservedBaseUnits.FreeMemory();
LastObservedAllLevelUnits.FreeMemory();
}
void ControlGroupInfo::UpdateFromHUD()
{
LastObservedNonBaseUnits.FreeMemory();
LastObservedBaseUnits.FreeMemory();
const FrameHUDManager &FrameHUD = g_Context->Managers.FrameHUD;
UINT ExtractorCount = 0;
for(UINT Index = 0; Index < BubblePortraitCount; Index++)
{
Texture *Tex = FrameHUD.BubblePortraits(Index).Tex;
if(Tex != NULL)
{
UnitEntry *Entry = Tex->Unit();
if(Entry != NULL)
{
InsertUnit(Entry);
if(Entry->Name == g_Context->Managers.Knowledge.ExtractorUnit()->Name)
{
ExtractorCount++;
}
}
}
}
Texture *Tex = FrameHUD.SoloPortrait();
if(Tex != NULL)
{
UnitEntry *Entry = Tex->Unit();
if(Entry != NULL)
{
InsertUnit(Entry);
}
}
if(Type == ControlGroupBuildingSupport)
{
g_Context->Managers.Knowledge.ReportExtractorCount(ExtractorCount);
}
ControlGroupLevel = FrameHUD.ControlGroupLevel();
if(ControlGroupLevel < 2)
{
LastObservedAllLevelUnits.FreeMemory();
if(Type == ControlGroupCombatAll)
{
g_Context->Managers.Knowledge.Army().ResourceValue = ControlGroupUnitInfo::ComputeResourceValue(LastObservedNonBaseUnits);
}
}
}
void ControlGroupInfo::AppendAllFromHUD()
{
const FrameHUDManager &FrameHUD = g_Context->Managers.FrameHUD;
for(UINT Index = 0; Index < BubblePortraitCount; Index++)
{
Texture *Tex = FrameHUD.BubblePortraits(Index).Tex;
if(Tex != NULL)
{
UnitEntry *Entry = Tex->Unit();
if(Entry != NULL && Entry->SecondaryType != UnitSecondaryBase)
{
LastObservedAllLevelUnits.PushEnd(Entry);
}
}
}
}
void ControlGroupInfo::InsertUnit(UnitEntry *Entry)
{
if(Entry->SecondaryType == UnitSecondaryBase)
{
LastObservedBaseUnits.PushEnd(Entry);
}
else
{
LastObservedNonBaseUnits.PushEnd(Entry);
}
}
UINT ControlGroupInfo::CountPrerequisiteUnitsMatchingName(const String &Name) const
{
if(Name == "Hatchery")
{
return CountUnitsMatchingName("Hatchery") + CountUnitsMatchingName("Lair") + CountUnitsMatchingName("Hive");
}
if(Name == "Lair")
{
return CountUnitsMatchingName("Lair") + CountUnitsMatchingName("Hive");
}
if(Name == "Gateway")
{
return CountUnitsMatchingName("Gateway") + CountUnitsMatchingName("WarpGate");
}
return CountUnitsMatchingName(Name);
}
UINT ControlGroupInfo::CountUnitsMatchingName(const String &Name) const
{
UINT Result = 0;
for(UINT Index = 0; Index < LastObservedNonBaseUnits.Length(); Index++)
{
if(LastObservedNonBaseUnits[Index].Entry == NULL)
{
g_Context->Files.Assert << "NULL Unit\n";
}
else if(LastObservedNonBaseUnits[Index].Entry->Name == Name)
{
Result++;
}
}
for(UINT Index = 0; Index < LastObservedBaseUnits.Length(); Index++)
{
if(LastObservedBaseUnits[Index].Entry == NULL)
{
g_Context->Files.Assert << "NULL Unit\n";
}
else if(LastObservedBaseUnits[Index].Entry->Name == Name)
{
Result++;
}
}
return Result;
}
void ControlGroupManager::Init()
{
ResetNewGame();
}
void ControlGroupManager::ResetNewGame()
{
for(UINT Index = 0; Index < ControlGroupCount; Index++)
{
_ControlGroups[Index].Reset();
}
_ControlGroups[0].Type = ControlGroupSupply;
_ControlGroups[1].Type = ControlGroupCombatMicro;
_ControlGroups[2].Type = ControlGroupBuildingMain;
_ControlGroups[3].Type = ControlGroupBuildingSupport;
_ControlGroups[4].Type = ControlGroupCombatAll;
_ControlGroups[5].Type = ControlGroupWorkerMineral;
_ControlGroups[6].Type = ControlGroupWorkerGas0;
_ControlGroups[7].Type = ControlGroupWorkerGas1;
_ControlGroups[8].Type = ControlGroupWorkerGas2;
_ControlGroups[9].Type = ControlGroupWorkerGas3;
}
void ControlGroupManager::EndFrame()
{
if(!g_Context->Controller.ConsoleEnabled())
{
return;
}
if( DisplayControlGroups || DisplayArmyInfo )
{
for(UINT ControlGroupIndex = 0; ControlGroupIndex < ControlGroupCount; ControlGroupIndex++)
{
const ControlGroupInfo &CurInfo = _ControlGroups[ControlGroupIndex];
if(DisplayControlGroups)
{
String S = String(ControlGroupIndex) + String(':');
for(UINT UnitIndex = 0; UnitIndex < CurInfo.LastObservedBaseUnits.Length(); UnitIndex++)
{
S += CurInfo.LastObservedBaseUnits[UnitIndex].Entry->Name;
if(UnitIndex != CurInfo.LastObservedBaseUnits.Length() - 1)
{
S.PushEnd(',');
}
}
S.PushEnd('|');
for(UINT UnitIndex = 0; UnitIndex < CurInfo.LastObservedNonBaseUnits.Length(); UnitIndex++)
{
S += CurInfo.LastObservedNonBaseUnits[UnitIndex].Entry->Name;
if(UnitIndex != CurInfo.LastObservedNonBaseUnits.Length() - 1)
{
S.PushEnd(',');
}
}
g_Context->WriteConsole(S, RGBColor::Orange, OverlayPanelStatus);
}
if(DisplayArmyInfo)
{
if(CurInfo.LastObservedAllLevelUnits.Length() > 0)
{
String AllDescription = ControlGroupUnitInfo::Describe(CurInfo.LastObservedAllLevelUnits);
g_Context->WriteConsole(String(ControlGroupIndex) + String(':') + AllDescription, RGBColor::Yellow, OverlayPanelStatus);
}
}
}
}
}
UINT ControlGroupManager::BaseCount() const
{
UINT Result = 0;
int BaseIndex = FindControlGroupIndex(ControlGroupBuildingMain);
if(BaseIndex == -1)
{
return 0;
}
else
{
return _ControlGroups[BaseIndex].LastObservedBaseUnits.Length();
}
return Result;
}
UINT ControlGroupManager::WorkerCount() const
{
UINT Result = 0;
for(UINT Index = 0; Index < ControlGroupCount; Index++)
{
Result += _ControlGroups[Index].CountUnitsMatchingName(g_Context->Managers.Knowledge.WorkerUnit()->Name);
}
return Result;
}
ControlGroupInfo& ControlGroupManager::FindControlGroup(const UnitEntry &Unit)
{
int ControlGroupIndex = FindControlGroupIndex(Unit);
if(ControlGroupIndex == -1)
{
g_Context->Files.Assert << "Control group not found\n";
return _ControlGroups[0];
}
return _ControlGroups[ControlGroupIndex];
}
ControlGroupInfo& ControlGroupManager::FindControlGroup(ControlGroupType Type)
{
int ControlGroupIndex = FindControlGroupIndex(Type);
if(ControlGroupIndex == -1)
{
g_Context->Files.Assert << "Control group not found\n";
return _ControlGroups[0];
}
return _ControlGroups[ControlGroupIndex];
}
int ControlGroupManager::FindControlGroupIndex(ControlGroupType Type) const
{
for(UINT Index = 0; Index < ControlGroupCount; Index++)
{
if(Type == _ControlGroups[Index].Type)
{
return Index;
}
}
return -1;
}
int ControlGroupManager::FindControlGroupIndex(const UnitEntry &Unit) const
{
if(Unit.Name.Length() == 0 || Unit.SecondaryType == UnitSecondaryWorker)
{
return -1;
}
if(Unit.SecondaryType == UnitSecondaryBase)
{
return FindControlGroupIndex(ControlGroupBuildingMain);
}
if(Unit.SecondaryType == UnitSecondarySupply)
{
return FindControlGroupIndex(ControlGroupSupply);
}
if(Unit.Name == "CreepTumor") {
return -1;
}
if(Unit.PrimaryType == UnitPrimaryBuilding || Unit.Name == "Queen")
{
return FindControlGroupIndex(ControlGroupBuildingSupport);
}
if(Unit.PrimaryType == UnitPrimaryMobile)
{
if(Unit.SecondaryType == UnitSecondaryCombatMicro)
{
return FindControlGroupIndex(ControlGroupCombatMicro);
}
return FindControlGroupIndex(ControlGroupCombatAll);
}
return -1;
}
UINT ControlGroupManager::GasControlGroupIndexFromGasIndex(UINT GasIndex) const
{
int BaseIndex = FindControlGroupIndex(ControlGroupWorkerGas0);
return BaseIndex + GasIndex;
}
int ControlGroupManager::FindNewWorkerControlGroupIndex() const
{
UINT ActiveGasGroups = ActiveGasGroupCount();
for(UINT GasIndex = 0; GasIndex < ActiveGasGroups; GasIndex++)
{
UINT ControlGroupIndex = GasControlGroupIndexFromGasIndex(GasIndex);
const ControlGroupInfo &CurGroup = _ControlGroups[ControlGroupIndex];
if(CurGroup.WorkersAssigned < 3 || CurGroup.LastObservedNonBaseUnits.Length() <= 1)
{
return ControlGroupIndex;
}
}
return FindControlGroupIndex(ControlGroupWorkerMineral);
}
UINT ControlGroupManager::ActiveGasGroupCount() const
{
int ExtractorGroupIndex = FindControlGroupIndex(ControlGroupBuildingSupport);
if(ExtractorGroupIndex == -1)
{
return 2;
}
const String ExtractorName = ExtractorNameFromRace(g_Context->Managers.Knowledge.MyRace());
UINT ExtractorCount = _ControlGroups[ExtractorGroupIndex].CountUnitsMatchingName(ExtractorName);
UINT DesiredActiveGasGroupCount = Math::Max(UINT(2), ExtractorCount);
return Math::Min(DesiredActiveGasGroupCount, UINT(4));
}
void ControlGroupManager::ReportWorkerAssigned(UINT ControlGroupIndex)
{
_ControlGroups[ControlGroupIndex].WorkersAssigned++;
UnitEntry *WorkerEntry = g_Context->Managers.Knowledge.WorkerUnit();
if(WorkerEntry == NULL)
{
g_Context->Files.Assert << "WorkerEntry == NULL\n";
}
else
{
_ControlGroups[ControlGroupIndex].LastObservedNonBaseUnits.PushEnd(WorkerEntry);
}
}