#include "Main.h" void ProgramMicroAll::Init() { _CurState = ProgramMicroAllSelectGroup; _UnitIndex = -1; Name = String("MicroAll"); } ProgramResultType ProgramMicroAll::ExecuteStep() { FrameHUDManager &FrameHUD = g_Context->Managers.FrameHUD; FrameUnitManager &FrameUnit = g_Context->Managers.FrameUnit; MinimapManager &Minimap = g_Context->Managers.Minimap; KnowledgeManager &Knowledge = g_Context->Managers.Knowledge; KeyboardMouseManager &KeyboardMouse = g_Context->Managers.KeyboardMouse; if(_CurState == ProgramMicroAllSelectGroup) { LogThreadEvent("Selecting Army", LogStep); KeyboardMouse.SendKey(KEY_0 + g_Context->Managers.ControlGroup.FindControlGroupIndex(ControlGroupCombatMicro)); _CurState = ProgramMicroAllSelectUnit; if(_UnitIndex + 1 < BubblePortraitCount) { Vec2i ScreenCoord = FrameHUD.ScreenCoordFromBubblePortraitIndex(_UnitIndex + 1); LogThreadEvent(String("Preemptive MouseMove: ") + String(_UnitIndex + 1), LogStep); KeyboardMouse.PreemptiveMouseMove(ScreenCoord); } return ProgramResultStillExecuting; } if(_CurState == ProgramMicroAllSelectUnit) { _UnitIndex++; bool UnitFound = false; while(_UnitIndex < BubblePortraitCount && !UnitFound) { Texture *Tex = FrameHUD.BubblePortraits(_UnitIndex).Tex; if(Tex != NULL && Tex->Unit() != NULL && Tex->Unit()->SecondaryType != UnitSecondaryBase) { UnitFound = true; } else { _UnitIndex++; } } if(_UnitIndex == BubblePortraitCount) { LogThreadEvent("All units finished", LogDone); return ProgramResultSuccess; } Vec2i ScreenCoord = FrameHUD.ScreenCoordFromBubblePortraitIndex(_UnitIndex); LogThreadEvent(String("Selecting unit ") + String(_UnitIndex), LogStep); KeyboardMouse.Click(ScreenCoord, MouseButtonLeft, ModifierNone); _CurState = ProgramMicroAllCenterUnit; return ProgramResultStillExecuting; } if(_CurState == ProgramMicroAllCenterUnit) { if(FrameHUD.SoloPortrait() == NULL) { LogThreadEvent("Unit selection failed", LogStep); _CurState = ProgramMicroAllSelectGroup; return ProgramResultStillExecuting; } KeyboardMouse.SendCtrlKey(KEY_F); LogThreadEvent(String("Centering on ") + FrameHUD.SoloPortrait()->ID(), LogStep); _CurState = ProgramMicroAllOrderUnit; return ProgramResultStillExecuting; } if(_CurState == ProgramMicroAllOrderUnit) { if(FrameHUD.SoloPortrait() == NULL) { LogThreadEvent("Unit selection failed", LogStep); _CurState = ProgramMicroAllSelectGroup; return ProgramResultStillExecuting; } UnitEntry *MyUnit = FrameHUD.SoloPortrait()->Unit(); if(MyUnit == NULL) { g_Context->Files.Assert << "Selected unit has no entry\n"; _CurState = ProgramMicroAllSelectGroup; return ProgramResultStillExecuting; } LogThreadEvent(String("Ordering ") + FrameHUD.SoloPortrait()->ID(), LogStep); const BaseInfo* NearestBase = Knowledge.FindNearestBase(FrameHUD.MinimapViewportCenter(), PlayerSelf); if(NearestBase == NULL) { g_Context->Files.Assert << "No base found\n"; return ProgramResultFail; } float Health = FrameHUD.CurrentHealthPercentage(); bool RetreatUnitLocal = false; bool RetreatUnitToBase = false; bool FindNewTarget = false; UINT AlliedUnitCount = 0; UINT EnemyUnitCount = 0; double TotalEnemyValue = 0; double EnemyArmyValue = 0, AlliedArmyValue = 0; for(UINT UnitIndex = 0; UnitIndex < FrameUnit.UnitsThisFrame().Length(); UnitIndex++) { const FrameUnitInfo &CurUnit = *FrameUnit.UnitsThisFrame()[UnitIndex]; if(CurUnit.Owner == PlayerEnemy && CurUnit.Entry->Hostile && CurUnit.Entry->SecondaryType != UnitSecondaryWorker) { TotalEnemyValue += CurUnit.Entry->MineralCost + CurUnit.Entry->GasCost; } if(CurUnit.Owner == PlayerEnemy && CurUnit.Clickable() && CurUnit.Entry->Hostile && CurUnit.Entry->SecondaryType != UnitSecondaryWorker) { if( (CurUnit.Entry->AttackAir && MyUnit->Flying) || (CurUnit.Entry->AttackGround && !MyUnit->Flying) ) { EnemyUnitCount++; EnemyArmyValue += CurUnit.Entry->MineralCost + CurUnit.Entry->GasCost; } } if( (CurUnit.Owner == PlayerSelf || CurUnit.Owner == PlayerAlly) && CurUnit.Entry->Hostile && CurUnit.Entry->SecondaryType != UnitSecondaryWorker) { AlliedUnitCount++; AlliedArmyValue += CurUnit.Entry->MineralCost + CurUnit.Entry->GasCost; } } if(AlliedArmyValue < 2.0 * EnemyArmyValue && AlliedUnitCount < 4 && EnemyUnitCount > 6) { if(Vec2f::Dist(NearestBase->BaseLocation, FrameHUD.MinimapViewportCenter()) > 0.1f) { RetreatUnitToBase = true; } } //if(Health > 0.0f && Health < 0.6f && FrameUnit.BattlePosition().ClosestEnemyHostile < 500.0f) RetreatUnit = true; if(MyUnit->Range >= 2 && !MyUnit->Flying && FrameUnit.BattlePosition().ClosestEnemyHostile < 150.0f) { RetreatUnitLocal = true; } if(MyUnit->Range >= 2) { FindNewTarget = true; } if(MyUnit->Range < 2 && FrameUnit.BattlePosition().ClosestEnemyHostile > 200.0f) { FindNewTarget = true; } ActionButtonStateType BlinkState; bool BlinkReady = FrameHUD.ActionButtonPresent("Blink", BlinkState); if(BlinkState != ActionButtonStateNormal) { BlinkReady = false; } if(RetreatUnitLocal || RetreatUnitToBase) { if(RetreatUnitToBase) { RetreatUnitLocal = false; } WORD Key = KEY_M; String Verb; if(BlinkReady) { Key = KEY_B; } Vec2i Target; if(RetreatUnitLocal) { if(BlinkReady) { Verb = "BlinkLocal"; Target = FrameUnit.BattlePosition().SafestBlinkLocation; } else { Verb = "RetreatLocal"; Target = FrameUnit.BattlePosition().SafestRetreatLocation; } } else { Verb = "RetreatBase"; Target = g_Context->Constants.MinimapCoordToScreenCoord(NearestBase->BaseLocation); } g_Context->ReportAction(Verb + String(" ") + FrameHUD.SoloPortrait()->ID(), RGBColor::Magenta); KeyboardMouse.SendKey(Key); KeyboardMouse.Click(Target, MouseButtonLeft, ModifierNone); } else if(FindNewTarget) { const FrameUnitInfo *BestUnit = NULL; float BestUnitValue = -1.0f; Vec2f ScreenCenter = g_Context->Constants.GetVec2fConstant(ScreenConstantVec2fScreenCenter); for(UINT UnitIndex = 0; UnitIndex < FrameUnit.UnitsThisFrame().Length(); UnitIndex++) { const FrameUnitInfo &CurUnit = *FrameUnit.UnitsThisFrame()[UnitIndex]; float CurDist = Vec2f::Dist(CurUnit.ScreenBound.Center(), ScreenCenter); if(CurUnit.Owner == PlayerEnemy && CurDist < 400.0f && CurUnit.Clickable()) { if( (MyUnit->AttackAir && CurUnit.Entry->Flying) || (MyUnit->AttackGround && !CurUnit.Entry->Flying) ) { float CurUnitValue = 0.0f; if(CurUnit.HealthBar != NULL) { CurUnitValue += 1.0f - CurUnit.HealthBar->Health(); } if(CurUnit.Entry->Hostile) { CurUnitValue += 10.0f; } if(CurUnitValue > BestUnitValue) { BestUnitValue = CurUnitValue; BestUnit = &CurUnit; } } } } if(BestUnit == NULL) { g_Context->ReportAction("No enemy units found, attacking nearest enemy location", RGBColor::Magenta); Vec2f NearestEnemyMinimapCoord = Minimap.FindNearestEnemyCoord(FrameHUD.MinimapViewportCenter()); KeyboardMouse.SendKey(KEY_A); KeyboardMouse.Click(g_Context->Constants.MinimapCoordToScreenCoord(NearestEnemyMinimapCoord), MouseButtonLeft, ModifierNone); } else { KeyboardMouse.SendKey(KEY_A); KeyboardMouse.Click(BestUnit->ScreenBound.Center().RoundToVec2i(), MouseButtonLeft, ModifierNone); float HealthValue = 0.0f; if(BestUnit->HealthBar != NULL) { HealthValue = BestUnit->HealthBar->Health(); } g_Context->ReportAction(FrameHUD.SoloPortrait()->ID() + String(">") + BestUnit->Entry->Name + String(", ") + String(HealthValue), RGBColor::Magenta); } } _CurState = ProgramMicroAllSelectGroup; return ProgramResultStillExecuting; } HANDLE_CRITICAL_FAILURE; }