Skip to content

Conversation

@erectorOps
Copy link
Contributor

@erectorOps erectorOps commented Sep 2, 2025

feat: Add NP/Star Conditions, Update Target Dialog, and Skill Priority Drag-Sort on Spam Screen

Note

This PR has not been rebased onto the #2076 PR.
It was created from upstream/master and manually includes changes equivalent to #2076.
Therefore, merging both this PR and #2076 simultaneously may cause conflicts.

  • Bug Fix
  • Feature Implementation
  • Documentation
  • Other

This PR is currently combined into a single one, but if needed, it can be split into separate PRs by the following categories:
bugfix api-utility data core ui

Related Issue

Description

  • Added NP conditions to Servant skill settings in Spam mode

    • NP is detected using two methods:
      1. Detect Charged state via the right edge color of the gauge
      2. Calculate NP value from the gauge length (values above 100 treated as 100)
  • Added Star conditions

    • Detect total critical stars using Tesseract OCR
  • Improved skill cooldown detection

    • Detect from the color of the bottom frame of skill icons
    • Ignore skills under Eternal Sleep, which do not change bottom frame color
  • Added Repeat Until Used option for Kishinami Hakuno’s “Sparks Route ∞”

    • Allows skills to be cast multiple times in the same turn
    • Loop stops when conditions no longer match or skill goes on cooldown
  • Replaced skill target selection dialog with AutoSkillAction UI

  • Added DragSort at the bottom to adjust skill priority

    • Removed dependency on specific layout in the previous implementation
  • Bug Fixes

Screenshots

  • Spam screen
    Skill priority drag-sort at the bottom of the screen
    spam_screen

  • Spam mode dialog
    Shows new condition fields
    spam_mode_dialog

  • Target selection UI
    AutoSkillAction (directly reused without modification)
    target_dialog

  • Cooldown detection (zoomed)
    Checks whether the mean HSV of the region is within the HSV range
    skill_ready
    skill_on_cooldown

  • NP Charged detection (zoomed)
    Checks whether the mean HSV of the region is within the HSV range
    np_low
    np_charged

  • NP Visual bar detection (zoomed)
    Checks 1×8 pixels per column for HSV range and measures bar length to determine NP value
    visual_bar_length

  • Critical Star OCR detection & normalized image (zoomed)
    ocr
    tesseract

Testing Notes

…ity, and select targets using AutoSkillAction (core)
…g-sort (ui)

      - Replace simple ListDialog with a condition dialog for Spam mode, NP Condition, Star Condition, and Repeat Until Used
      - Update Target selection UI from simple ListDialog to AutoSkillAction-based UI
      - Add DragSortView and DragSortAdapter to set skill usage priority
@github-actions
Copy link

github-actions bot commented Sep 2, 2025

Build 485

Download the latest APK for testing here

Note

You need a GitHub account to download the APK.

This URL is valid as long as the artifact has not expired yet.

@Vylantze
Copy link

Vylantze commented Sep 3, 2025

Well, I'll be damned. NP detection was just what I wanted for my own pull request. Magical.

Also @erectorOps your screenshots are not working.

@erectorOps
Copy link
Contributor Author

Also @erectorOps your screenshots are not working.

I see, so attachments uploaded in my own repository can’t be displayed.
I’ve re-uploaded it, so it should be viewable now.

@ArthurKun21
Copy link
Collaborator

You could use this instead of using recycle view

https://github.com/Calvin-LL/Reorderable

@ArthurKun21 ArthurKun21 requested a review from Copilot September 3, 2025 16:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds NP conditions, star conditions, and skill priority drag-sort functionality to the Spam screen. It replaces image-based skill detection with color/HSV-based detection and introduces a new target selection UI.

Key changes:

  • Added NP gauge detection using HSV color analysis and visual bar length measurement
  • Added critical star detection using Tesseract OCR
  • Replaced skill image detection with HSV-based cooldown detection
  • Added skill priority drag-sort functionality with visual ordering
  • Introduced new conditional fields (NP, Star) to skill spam configuration

Reviewed Changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
SkillSpam.kt Core spam logic with NP/star detection and priority-based skill execution
CriticalStarTracker.kt New module for OCR-based critical star detection
Caster.kt Enhanced skill casting with cooldown detection and Eternal Sleep handling
SpamConfig.kt Extended configuration model with new conditional fields
BattleScreenLocations.kt Added regions for NP gauge, skill cooldown, and star detection
SpamScreen.kt Updated UI with new condition selection and target picker
DragSortSkillPriorityAdapter.kt New drag-sort adapter for skill priority management
libautomata/*.kt Extended automation API with HSV detection and OCR capabilities

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 207 to 220
// TODO: NpType3 reuses ServantTarget.ABC, so it's affected by deployed state. It should be independent of servant count.
actualSlot = when (deployed.size) {
1 -> FieldSlot.B
2 -> {
if (actualSlot == FieldSlot.B) {
when (null) {
deployed[FieldSlot.A] -> FieldSlot.A
deployed[FieldSlot.C] -> FieldSlot.C
else -> FieldSlot.A // Assume Left when Slot B is empty
}
} else actualSlot
}
else -> actualSlot
}
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The when (null) expression on line 212 will never match any conditions since it's comparing null to non-null values from the map. This should likely be checking for null values in the deployed map entries.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is based on the type analysis assumption that the Map’s values are non-null, so the when(null) would never match. However, in reality, if a key does not exist in the Map, deployed[slot] returns null, so this comment is incorrect. That said, my code currently returns the empty slot as actualSlot, which is not the intended behavior, so I will fix it.

else -> true
}

val starCond = when(star) {
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after when. Should be when (star).

Suggested change
val starCond = when(star) {
val starCond = when (star) {

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +35
* ⚠️ When calling this function inside `useSameSnapIn`, be aware that it may
* reuse a gray cached snapshot and return incorrect results.
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning about useSameSnapIn appears in multiple places but the function name is inconsistent. It should be useSameSnapIn consistently throughout the codebase.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

        // OCR Accuracy Report
        //       0 1 2 3 4 5 6 7 8 9
        // TW:   ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
        // CN:   ✅ ⚠️ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
        // KO:   ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
        // JA:   ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
        // EN:   ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
        // ⚠️: Sometimes a “1” is misrecognized as a “4”.
        //     Safe with current Star Condition options.

It seems that it is checking comments containing ⚠️ and flagging the above comment as inconsistent. However, as you can see, this comment is unrelated to useSameSnapIn, so I believe there is no issue.

}

private fun isSkillConfirmDialogOkButtonDisabled(): Boolean {
val brightness = locations.battle.skillUseOkRegion.getPattern().getAverageBrightness()
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a pattern object just to get average brightness is inefficient. Consider adding a direct brightness check method to the region API to avoid pattern creation overhead.

Copilot uses AI. Check for mistakes.
Comment on lines 104 to 105
* @param invert if true, the binary result is inverted.
*          Set to true for white text
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment uses full-width spaces ( ) instead of regular spaces. This should use regular ASCII spaces for consistency.

Suggested change
* @param invert if true, the binary result is inverted.
*          Set to true for white text
* Set to true for white text

Copilot uses AI. Check for mistakes.
Comment on lines 106 to 112
context, when(item.servantIndex) {
1 -> R.color.servant1_primary_text
2 -> R.color.servant2_primary_text
3 -> R.color.servant3_primary_text
4 -> R.color.servant4_primary_text
5 -> R.color.servant5_primary_text
else -> R.color.servant6_primary_text
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The color selection logic is duplicated three times in this function. Consider extracting this into a helper function to reduce code duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines 390 to 392
val row = gray.row(y)
if (Core.countNonZero(row) > 0) count++
row.release()
Copy link

Copilot AI Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OpenCV Mat objects created by gray.row(y) and gray.col(x) should be released in a try-finally block to ensure proper cleanup even if an exception occurs.

Copilot uses AI. Check for mistakes.
@erectorOps
Copy link
Contributor Author

Thanks for the reviews, @ArthurKun21 and Copilot! I’ve applied the suggested fixes and improvements. I really appreciate your insights and guidance.

@ArthurKun21 ArthurKun21 requested a review from reconman September 8, 2025 11:24
@Vylantze
Copy link

Vylantze commented Sep 9, 2025

I think after this has been merged, I'll probably make a pull request to make use of this new system in the default command line processing. So that you can do the following:

  • Only using Scathach/Skadi skill 3 on its target if the target has < 100% NP bar.
  • Automatically skip an already used skill, and not accidentally proc the popup window detection (causing the rest of your commands to break because FGA thinks that you are using popups when it only popped up because the skill was already used).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants