public IPattern TakeScreenshot() { _superUser.SendCommand($"/system/bin/screencap {_imgPath}"); using var f = File.OpenRead(_imgPath); using var reader = new BinaryReader(f, Encoding.ASCII); var w = reader.ReadInt32(); var h = reader.ReadInt32(); var format = reader.ReadInt32(); if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { reader.ReadInt32(); } if (_buffer == null) { // If format is not RGBA, notify if (format != 1) { AutomataApi.Toast($"Unexpected raw image format: {format}"); } _buffer = new byte[w * h * 4]; _rootLoadMat = new Mat(h, w, CvType.Cv8uc4); } reader.Read(_buffer, 0, _buffer.Length); _rootLoadMat.Put(0, 0, _buffer); Imgproc.CvtColor(_rootLoadMat, _rootConvertMat, Imgproc.ColorRgba2gray); return(new DroidCvPattern(_rootConvertMat, false)); }
bool RegisterGestures() { IGestureService gestureService; try { if (Preferences.Instance.UseRootForGestures) { gestureService = new RootGestures(GetSuperUser()); } else { gestureService = new AccessibilityGestureService(this); } } catch (Exception e) { Toast.MakeText(this, e.Message, ToastLength.Short).Show(); return false; } _gestureService = gestureService; AutomataApi.RegisterGestures(_gestureService); return true; }
public void PerformBattle() { AutomataApi.UseSameSnapIn(OnTurnStarted); AutomataApi.Wait(2); var NpsClicked = false; if (Preferences.Instance.EnableAutoSkill) { NpsClicked = AutoSkill.Execute(); AutoSkill.ResetNpTimer(); } if (!HasClickedAttack) { ClickAttack(); } if (Card.CanClickNpCards) { NpsClicked = Card.ClickNpCards(); } Card.ClickCommandCards(5); if (Preferences.Instance.UnstableFastSkipDeadAnimation) { SkipDeathAnimation(); } Card.ResetCommandCards(); AutomataApi.Wait(NpsClicked ? 25 : 5); }
public void PerformBattle() { AutomataApi.UseSameSnapIn(OnTurnStarted); AutomataApi.Wait(2); var wereNpsClicked = false; if (Preferences.Instance.EnableAutoSkill) { wereNpsClicked = AutoSkill.Execute(); AutoSkill.ResetNpTimer(); } if (!HasClickedAttack) { ClickAttack(); } if (Card.CanClickNpCards) { // We shouldn't do the long wait due to NP spam/danger modes // They click on NPs even when not charged // So, don't assign wereNpsClicked here Card.ClickNpCards(); } Card.ClickCommandCards(5); Card.ResetCommandCards(); AutomataApi.Wait(wereNpsClicked ? 25 : 5); }
// Click begin quest in Formation selection, then select boost item, if applicable, then confirm selection. void StartQuest() { Game.MenuStartQuestClick.Click(); AutomataApi.Wait(2); var boostItem = Preferences.Instance.BoostItemSelectionMode; if (boostItem >= 0) { Game.MenuBoostItemClickArray[boostItem].Click(); // in case you run out of items Game.MenuBoostItemSkipClick.Click(); } if (Preferences.Instance.StorySkip) { AutomataApi.Wait(10); if (Game.MenuStorySkipRegion.Exists(ImageLocator.StorySkip)) { Game.MenuStorySkipClick.Click(); AutomataApi.Wait(0.5); Game.MenuStorySkipYesClick.Click(); } } }
protected override void Script() { Scaling.Init(); var isInSupport = AutoBattle.IsInSupport(); var supportBound = new Region(53 * 2, 0, 143 * 2, 110 * 2); var regionAnchor = ImageLocator.SupportRegionTool; var regionArray = AutomataApi.FindAll(new Region(2100, 0, 300, 1440), regionAnchor); var screenBounds = new Region(0, 0, Game.ScriptWidth, Game.ScriptHeight); var timestamp = DateTime.Now.Ticks; var i = 0; foreach (var testRegion in regionArray) { // At max two Servant+CE are completely on screen if (i > 1) { break; } if (isInSupport) { supportBound.Y = testRegion.Y - 70 + 68 * 2; } else // Assume we are on Friend List { supportBound.Y = testRegion.Y + 82; supportBound.X += 10; } if (!screenBounds.Contains(supportBound)) { continue; } using var pattern = supportBound.GetPattern(); var servant = pattern.Crop(new Region(0, 0, 125, 44)); servant.Save(Path.Combine(ImageLocator.SupportServantImgFolder, $"{timestamp}_servant{i}.png")); var ce = pattern.Crop(new Region(0, 80, pattern.Width, 25)); ce.Save(Path.Combine(ImageLocator.SupportCeImgFolder, $"{timestamp}_ce{i}.png")); ++i; } if (i == 0) { throw new ScriptExitException("No support images were found on the current screen. Are you on Support selection or Friend list screen?"); } throw new ScriptExitException($"Support Image(s) were generated."); }
void SkipDeathAnimation() { // https://github.com/29988122/Fate-Grand-Order_Lua/issues/55 Experimental for (var i = 0; i < 3; ++i) { Game.BattleSkipDeathAnimationClick.Click(); AutomataApi.Wait(1); } }
void ChooseTarget(int Index) { Game.BattleTargetClickArray[Index].Click(); AutomataApi.Wait(0.5); Game.BattleExtrainfoWindowCloseClick.Click(); HasChoosenTarget = true; }
void SelectSkillTarget(Location Location) { Location.Click(); AutomataApi.Wait(0.5); // Exit any extra menu Game.BattleExtrainfoWindowCloseClick.Click(); WaitForAnimationToFinish(); }
void SelectEnemyTarget(Location Location) { Location.Click(); AutomataApi.Wait(0.5); // Exit any extra menu Game.BattleExtrainfoWindowCloseClick.Click(); ChangeArray(_defaultFunctionArray); }
public void ClickAttack() { Game.BattleAttackClick.Click(); // Although it seems slow, make it no shorter than 1 sec to protect user with less processing power devices. AutomataApi.Wait(1.5); HasClickedAttack = true; Card.ReadCommandCards(); }
public void Click(Location Location) { const int duration = 50; var swipePath = new Path(); swipePath.MoveTo(Location.X, Location.Y); PerformGesture(new GestureDescription.StrokeDescription(swipePath, 0, duration)); AutomataApi.Wait(clickWaitTime); }
void Reset() { ResetClick.Click(); AutomataApi.Wait(0.5); ResetConfirmationClick.Click(); AutomataApi.Wait(3); ResetCloseClick.Click(); AutomataApi.Wait(2); }
public void Swipe(Location Start, Location End) { var swipePath = new Path(); swipePath.MoveTo(Start.X, Start.Y); swipePath.LineTo(End.X, End.Y); var swipeStroke = new GestureDescription.StrokeDescription(swipePath, 0, GestureTimings.SwipeDurationMs); PerformGesture(swipeStroke); AutomataApi.Wait(GestureTimings.SwipeWaitTimeSec); }
void PreloadNp() { if (!Battle.HasClickedAttack) { Battle.ClickAttack(); // There is a delay after clicking attack before NP Cards come up. DON'T DELETE! AutomataApi.Wait(2); } ChangeArray(_cardsPressed); }
public void ContinueClick(Location Location, int Times) { while (Times-- > 0) { var swipePath = new Path(); swipePath.MoveTo(Location.X, Location.Y); var stroke = new GestureDescription.StrokeDescription(swipePath, GestureTimings.ClickDelayMs, GestureTimings.ClickDurationMs); PerformGesture(stroke); } AutomataApi.Wait(GestureTimings.ClickWaitTimeSec); }
void BeginOrderChange() { OpenMasterSkillMenu(); Game.BattleMasterSkill3Click.Click(); if (Preferences.Instance.SkillConfirmation) { Game.BattleSkillOkClick.Click(); } AutomataApi.Wait(0.3); ChangeArray(_startingMemberFunctionArray); }
public void ContinueClick(Location Location, int Times) { const int clickTime = 50; const int clickDelay = 10; while (Times-- > 0) { var swipePath = new Path(); swipePath.MoveTo(Location.X, Location.Y); var stroke = new GestureDescription.StrokeDescription(swipePath, clickDelay, clickTime); PerformGesture(stroke); } AutomataApi.Wait(clickWaitTime); }
// Selections Support option void Support() { // Friend selection var hasSelectedSupport = _support.SelectSupport(Preferences.Instance.Support.SelectionMode); if (hasSelectedSupport && !_isContinuing) { AutomataApi.Wait(4); StartQuest(); // Wait timer till battle starts. // Uses less battery to wait than to search for images for a few seconds. // Adjust according to device. AutomataApi.Wait(10); } }
public void Scroll(Location Start, Location End) { const int swipeDuration = 300; var swipePath = new Path(); swipePath.MoveTo(Start.X, Start.Y); swipePath.LineTo(End.X, End.Y); var swipeStroke = new GestureDescription.StrokeDescription(swipePath, 0, swipeDuration); PerformGesture(swipeStroke); const double scrollWaitTime = 0.7; AutomataApi.Wait(scrollWaitTime); }
protected override void Script() { Scaling.Init(); new Location(1400, 1120).Click(); new Location(1600, 1120).Click(); while (true) { new Location(1600, 1420).Click(); new Location(1600, 1120).Click(); AutomataApi.Wait(3); AutomataApi.ContinueClick(new Location(1600, 1300), 15); AutomataApi.Wait(0.5); } }
static IPattern CreatePattern(string FilePath) { var assembly = Assembly.GetExecutingAssembly(); var resourceName = $"{nameof(FateGrandAutomata)}.{FilePath}"; var stream = assembly.GetManifestResourceStream(resourceName); if (stream == null) { return(null); } using (stream) { return(AutomataApi.LoadPattern(stream)); } }
void SelectSubMemeber(Location Location) { Location.Click(); AutomataApi.Wait(0.3); Game.BattleOrderChangeOkClick.Click(); // Extra wait to allow order change dialog to close AutomataApi.Wait(1); WaitForAnimationToFinish(15); // Extra wait for the lag introduced by Order change AutomataApi.Wait(1); ChangeArray(_defaultFunctionArray); }
void Withdraw() { if (!Preferences.Instance.WithdrawEnabled) { throw new ScriptExitException("All servants have been defeated and auto-withdrawing is disabled."); } Game.WithdrawRegion.Click(); AutomataApi.Wait(0.5); // Click the "Accept" button after choosing to withdraw Game.WithdrawAcceptClick.Click(); AutomataApi.Wait(1); // Click the "Close" button after accepting the withdrawal Game.StaminaBronzeClick.Click(); }
public static IPattern LoadSupportImagePattern(string FileName) { if (!SupportCachedPatterns.ContainsKey(FileName)) { var stream = FileLoader(FileName); if (stream == null) { throw new ScriptExitException( $"Unable to load image: {FileName}. Put images in {SupportImgFolder} folder"); } using (stream) { SupportCachedPatterns.Add(FileName, AutomataApi.LoadPattern(stream)); } } return(SupportCachedPatterns[FileName]); }
static IPattern GetScaledScreenshot() { var sshot = _platformImpl.Screenshot() .Crop(GameAreaManager.GameArea); var scale = TransformationExtensions.ScreenToImageScale(); if (scale != null) { if (_resizeTarget == null) { _resizeTarget = AutomataApi.GetResizableBlankPattern(); } sshot.Resize(_resizeTarget, new Size(sshot.Width, sshot.Height) * scale.Value); return(_resizeTarget); } return(sshot); }
CardScore GetCardType(Region Region) { if (Region.Exists(ImageLocator.Buster)) { return(CardScore.Buster); } if (Region.Exists(ImageLocator.Art)) { return(CardScore.Arts); } if (Region.Exists(ImageLocator.Quick)) { return(CardScore.Quick); } AutomataApi.Toast($"Failed to determine Card type (X: {Region.X}, Y: {Region.Y}, W: {Region.W}, H: {Region.H})"); return(CardScore.Buster); }
void RefillStamina() { if (Preferences.Instance.Refill.Enabled && _stonesUsed < Preferences.Instance.Refill.Repetitions) { switch (Preferences.Instance.Refill.Resource) { case RefillResource.SQ: Game.StaminaSqClick.Click(); break; case RefillResource.AllApples: Game.StaminaBronzeClick.Click(); Game.StaminaSilverClick.Click(); Game.StaminaGoldClick.Click(); break; case RefillResource.Gold: Game.StaminaGoldClick.Click(); break; case RefillResource.Silver: Game.StaminaSilverClick.Click(); break; case RefillResource.Bronze: Game.StaminaBronzeClick.Click(); break; } AutomataApi.Wait(1); Game.StaminaOkClick.Click(); ++_stonesUsed; AutomataApi.Wait(3); } else { throw new ScriptExitException("AP ran out!"); } }
Dictionary <CardScore, List <int> > GetCommandCards() { var storagePerPriority = new Dictionary <CardScore, List <int> >(); AutomataApi.UseSameSnapIn(() => { for (var cardSlot = 0; cardSlot < 5; ++cardSlot) { var score = GetCardAffinity(Game.BattleCardAffinityRegionArray[cardSlot]) | GetCardType(Game.BattleCardTypeRegionArray[cardSlot]); if (!storagePerPriority.ContainsKey(score)) { storagePerPriority.Add(score, new List <int>()); } storagePerPriority[score].Add(cardSlot); } }); return(storagePerPriority); }
// Reset battle state, then click quest and refill stamina if needed. void Menu() { _battle.ResetState(); if (Preferences.Instance.Refill.Enabled) { var refillRepetitions = Preferences.Instance.Refill.Repetitions; if (refillRepetitions > 0) { AutomataApi.Toast($"{_stonesUsed} refills used out of {refillRepetitions}"); } } // Click uppermost quest Game.MenuSelectQuestClick.Click(); AutomataApi.Wait(1.5); // Auto refill while (Game.StaminaScreenRegion.Exists(ImageLocator.Stamina)) { RefillStamina(); } }