#include "Main.h" void ProgramProduceUnitQueue::Init(UnitEntry *Entry) { _CurState = ProgramProduceUnitQueueSelectSupportBuildings; _Entry = Entry; Name = String("Produce<") + _Entry->Name + String(">"); } ProgramResultType ProgramProduceUnitQueue::ExecuteStep() { FrameHUDManager &FrameHUD = g_Context->Managers.FrameHUD; if(_CurState == ProgramProduceUnitQueueSelectSupportBuildings) { if(_Entry->BuiltAt == "Gateway") { bool GatewaysFound = (g_Context->Managers.ControlGroup.FindControlGroup(ControlGroupBuildingSupport).CountUnitsMatchingName("Gateway") > 0); if(FrameHUD.WarpGateReady() && !GatewaysFound) { LogThreadEvent("Selecting Warp Gates", LogStep); g_Context->Managers.KeyboardMouse.SendKey(KEY_W); _CurState = ProgramProduceUnitQueueWarpGateMoveToSpawnPoint; return ProgramResultStillExecuting; } } LogThreadEvent("Selecting Support Buildings", LogStep); g_Context->Managers.KeyboardMouse.SendKey(KEY_0 + g_Context->Managers.ControlGroup.FindControlGroupIndex(ControlGroupBuildingSupport)); _CurState = ProgramProduceUnitQueueSelectSupportBuilding; return ProgramResultStillExecuting; } if(_CurState == ProgramProduceUnitQueueSelectSupportBuilding) { if(FrameHUD.SoloPortrait() == NULL) { Vector<UINT> ValidIndices; for(UINT Index = 0; Index < BubblePortraitCount; Index++) { Texture *CurTexture = FrameHUD.BubblePortraits(Index).Tex; if(CurTexture != NULL && CurTexture->ID() == _Entry->BuiltAt) { ValidIndices.PushEnd(Index); } } if(ValidIndices.Length() == 0) { LogThreadEvent("No valid buildings found", LogError); return ProgramResultFail; } Vec2i ScreenCoord = FrameHUD.ScreenCoordFromBubblePortraitIndex(ValidIndices.RandomElement()); LogThreadEvent(String("Left Click: ") + ScreenCoord.CommaSeparatedString(), LogStep); g_Context->Managers.KeyboardMouse.Click(ScreenCoord, MouseButtonLeft, ModifierNone); } else { Texture *CurTexture = FrameHUD.SoloPortrait(); if(CurTexture->Unit()->SecondaryType != UnitSecondaryBase) { LogThreadEvent("Selected building is not a base", LogError); return ProgramResultFail; } LogThreadEvent("Single base selected", LogStep); } _CurState = ProgramProduceUnitQueueProduce; return ProgramResultStillExecuting; } if(_CurState == ProgramProduceUnitQueueProduce) { ActionButtonStateType State; if(FrameHUD.BuildQueuePresent()) { LogThreadEvent("Build queue already present", LogError); return ProgramResultFail; } if(_Entry->BuiltAt == "Gateway") { if(FrameHUD.ActionButtonPresent("ResearchWarpGate", State)) { if(State == ActionButtonStateNormal) { LogThreadEvent("Pressing WarpGate button", LogDone); g_Context->Managers.KeyboardMouse.SendKey(KEY_G); return ProgramResultSuccess; } } } if(!FrameHUD.ActionButtonPresent(_Entry->Name, State)) { LogThreadEvent(_Entry->Name + String(" button not found"), LogError); return ProgramResultFail; } if(State != ActionButtonStateNormal) { LogThreadEvent(_Entry->Name + String(" button in invalid state"), LogError); return ProgramResultFail; } g_Context->Managers.KeyboardMouse.SendKey(KEY_A + (_Entry->Hotkey - 'a')); LogThreadEvent("Ordering unit", LogStep); _TimeoutTime = GameTime() + 1.0; _CurState = ProgramProduceUnitQueueWaitForUnit; return ProgramResultStillExecuting; } if(_CurState == ProgramProduceUnitQueueWaitForUnit) { if(GameTime() > _TimeoutTime) { LogThreadEvent("Timed out waiting for unit", LogError); return ProgramResultFail; } if(FrameHUD.BuildQueueEntryPresent(_Entry->Name)) { LogThreadEvent(_Entry->Name + String(" found"), LogDone); g_Context->ReportAction(_Entry->Name, RGBColor::Green); g_Context->Managers.Knowledge.RecordUnitInProduction(_Entry, GameTime()); return ProgramResultSuccess; } else { LogThreadEvent("Waiting for unit", LogStep); return ProgramResultStillExecuting; } } if(_CurState == ProgramProduceUnitQueueWarpGateMoveToSpawnPoint) { ActionButtonStateType State; if(!FrameHUD.ActionButtonPresent(_Entry->Name, State)) { LogThreadEvent(_Entry->Name + String(" not present"), LogError); return ProgramResultFail; } if(State != ActionButtonStateNormal) { LogThreadEvent(_Entry->Name + String(" is in an invalid state"), LogError); return ProgramResultFail; } const BaseInfo* TargetSite = g_Context->Managers.Knowledge.FindBuildSite(); if(TargetSite == NULL) { LogThreadEvent("TargetSite not found", LogError); return ProgramResultFail; } Vec2i ScreenCoord = g_Context->Constants.MinimapCoordToScreenCoord(TargetSite->BuildLocation); LogThreadEvent(String("MoveToSpawnPoint: ") + ScreenCoord.CommaSeparatedString(), LogStep); g_Context->Managers.KeyboardMouse.Click(ScreenCoord, MouseButtonLeft, ModifierNone); _CurState = ProgramProduceUnitQueueWarpGateSelectUnit; return ProgramResultStillExecuting; } if(_CurState == ProgramProduceUnitQueueWarpGateSelectUnit) { ActionButtonStateType State; if(!FrameHUD.ActionButtonPresent(_Entry->Name, State)) { LogThreadEvent(_Entry->Name + String(" not present"), LogError); return ProgramResultFail; } if(State != ActionButtonStateNormal) { LogThreadEvent(_Entry->Name + String(" is in an invalid state"), LogError); return ProgramResultFail; } const BaseInfo* TargetSite = g_Context->Managers.Knowledge.FindBuildSite(); if(TargetSite == NULL) { LogThreadEvent("TargetSite not found", LogError); return ProgramResultFail; } LogThreadEvent("Selecting unit hotkey", LogStep); g_Context->Managers.KeyboardMouse.SendKey(KEY_A + (_Entry->Hotkey - 'a')); _CurState = ProgramProduceUnitQueueWarpGateFindSpawnLocation; _TimeoutTime = GameTime() + 1.0; return ProgramResultStillExecuting; } if(_CurState == ProgramProduceUnitQueueWarpGateFindSpawnLocation) { ActionButtonStateType State; if(!FrameHUD.ActionButtonPresent("Cancel", State)) { LogThreadEvent(_Entry->Name + String(" finished"), LogDone); g_Context->ReportAction(_Entry->Name, RGBColor::Green); g_Context->Managers.Knowledge.RecordUnitInProduction(_Entry, GameTime()); return ProgramResultSuccess; } if(GameTime() > _TimeoutTime) { LogThreadEvent("Timed out searching for unit location", LogError); return ProgramResultFail; } Vec2i ScreenCoord = g_Context->Constants.RandomClickablePoint(0.02f); LogThreadEvent(String("RandomSpawnPoint: ") + ScreenCoord.CommaSeparatedString(), LogStep); g_Context->Managers.KeyboardMouse.Click(ScreenCoord, MouseButtonLeft, ModifierNone); return ProgramResultStillExecuting; } HANDLE_CRITICAL_FAILURE; }