From 6f08bd9bed87a2830c86c812266ac856998a5b7d Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:14:56 +0800 Subject: [PATCH 1/7] command spell --- .../ui/skill_maker/SkillMakerActivity.kt | 22 +++- .../ui/skill_maker/SkillMakerCommandSpell.kt | 110 ++++++++++++++++++ .../ui/skill_maker/SkillMakerMain.kt | 20 +++- .../ui/skill_maker/SkillMakerNav.kt | 2 + .../ui/skill_maker/SkillMakerTarget.kt | 9 +- .../ui/skill_maker/SkillMakerViewModel.kt | 41 ++++++- .../util/LocalizationExtensions.kt | 7 ++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/localized.xml | 7 ++ .../scripts/entrypoints/AutoBattle.kt | 1 + .../scripts/locations/MasterLocations.kt | 12 ++ .../scripts/models/AutoSkillAction.kt | 5 + .../scripts/models/AutoSkillCommand.kt | 10 ++ .../scripts/models/Skill.kt | 12 ++ .../scripts/modules/AutoSkill.kt | 1 + .../scripts/modules/Caster.kt | 33 ++++++ 16 files changed, 282 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt index 0372dd3dd..618075d55 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt @@ -82,6 +82,8 @@ fun SkillMakerUI( val turn by vm.turn val wave by vm.wave + val commandSpellRemaining by vm.commandSpell.collectAsState() + Crossfade( current, animationSpec = spring() @@ -106,6 +108,13 @@ fun SkillMakerUI( SkillMakerNav.Main -> { SkillMakerMain( vm = vm, + onCommandSpell = { + if (commandSpellRemaining <=0) { + navigate(SkillMakerNav.CommandSpellWarning) + } else { + navigate(SkillMakerNav.CommandSpell) + } + }, onMasterSkills = { navigate(SkillMakerNav.MasterSkills) }, onAtk = { navigate(SkillMakerNav.Atk) }, onSkill = { vm.initSkill(it) }, @@ -123,6 +132,14 @@ fun SkillMakerUI( onOrderChange = { navigate(SkillMakerNav.OrderChange) } ) } + SkillMakerNav.CommandSpell -> { + SkillMakerCommandSpells( + onCommandSpell = { vm.initSkill(it) }, + ) + } + SkillMakerNav.CommandSpellWarning -> { + SkillMakerCommandSpellWarning() + } SkillMakerNav.OrderChange -> { SkillMakerOrderChange( @@ -152,7 +169,7 @@ fun SkillMakerUI( onSpaceIshtar = { navigate(SkillMakerNav.SpaceIshtar(nav.skill)) }, - showKukulkan = nav.skill !is Skill.Master, + showKukulkan = nav.skill is Skill.Servant, onKukulkan = { navigate(SkillMakerNav.Kukulkan(nav.skill)) }, @@ -163,7 +180,8 @@ fun SkillMakerUI( ), onMelusine = { vm.targetSkill(ServantTarget.Melusine) - } + }, + showTargetNone = nav.skill !is Skill.CommandSpell, ) } diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt new file mode 100644 index 000000000..547d76f96 --- /dev/null +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt @@ -0,0 +1,110 @@ +package io.github.fate_grand_automata.ui.skill_maker + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.sizeIn +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.github.fate_grand_automata.R +import io.github.fate_grand_automata.scripts.models.Skill +import io.github.fate_grand_automata.ui.FGATheme +import io.github.fate_grand_automata.ui.FGATitle +import io.github.fate_grand_automata.util.stringRes + +@Composable +fun SkillMakerCommandSpells( + onCommandSpell: (Skill.CommandSpell) -> Unit, +) { + Column( + modifier = Modifier + .fillMaxHeight() + .padding(16.dp) + ) { + FGATitle( + stringResource(R.string.skill_maker_command_spell) + ) + + Row( + modifier = Modifier.weight(1f), + verticalAlignment = Alignment.CenterVertically + ) { + Skill.CommandSpell.list.forEach { + SkillButton( + skill = it, + color = colorResource(R.color.colorCommandSpell) + ) { + onCommandSpell(it) + } + } + } + } +} + +@Composable +fun RowScope.SkillButton( + skill: Skill, + color: Color, + onClick: () -> Unit +) { + Surface( + color = color, + shape = MaterialTheme.shapes.medium, + modifier = Modifier + .padding(5.dp) + .sizeIn(maxWidth = 45.dp) + .aspectRatio(1f) + .fillMaxSize() + .weight(1f, false), + onClick = onClick + ) { + Box { + Text( + stringResource(skill.stringRes).uppercase(), + textAlign = TextAlign.Center, + color = Color.White, + modifier = Modifier.align(Alignment.Center) + ) + } + } +} + +@Composable +fun SkillMakerCommandSpellWarning() { + Column( + modifier = Modifier + .fillMaxHeight() + .padding(16.dp) + ) { + FGATitle( + stringResource(R.string.skill_maker_command_spell_warning) + ) + } +} + +@Preview(name = "Light Mode", widthDp = 600, heightDp = 300) +@Preview(name = "Dark Mode", widthDp = 600, heightDp = 300, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun TestCommandSpell() { + FGATheme { + SkillMakerCommandSpells(onCommandSpell = { }) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt index 683b18a48..3d5c8602d 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt @@ -46,6 +46,7 @@ import io.github.fate_grand_automata.ui.icon @Composable fun SkillMakerMain( vm: SkillMakerViewModel, + onCommandSpell: () -> Unit, onMasterSkills: () -> Unit, onAtk: () -> Unit, onSkill: (Skill.Servant) -> Unit, @@ -124,6 +125,8 @@ fun SkillMakerMain( Skills(onSkill = onSkill) } + val commandSpellRemaining by vm.commandSpell.collectAsState() + Column( verticalArrangement = Arrangement.Bottom, horizontalAlignment = Alignment.End, @@ -132,6 +135,20 @@ fun SkillMakerMain( .width(IntrinsicSize.Max) .fillMaxHeight() ) { + + Button( + colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.colorCommandSpell)), + onClick = onCommandSpell + ) { + Text( + stringResource(R.string.skill_maker_command_spell_title_short, 3 - commandSpellRemaining), + textAlign = TextAlign.Center, + color = Color.White + ) + } + + Spacer(Modifier.height(8.dp)) + Button( colors = ButtonDefaults.buttonColors(containerColor = colorResource(R.color.colorMasterSkill)), onClick = onMasterSkills @@ -143,7 +160,7 @@ fun SkillMakerMain( ) } - Spacer(Modifier.height(16.dp)) + Spacer(Modifier.height(8.dp)) Button( shape = CircleShape, @@ -237,6 +254,7 @@ val SkillMakerEntry?.colorRes: Int 'g', 'h', 'i' -> R.color.colorServant3 else -> defaultColor } + is AutoSkillAction.CommandSpell -> R.color.colorCommandSpell else -> defaultColor } diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerNav.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerNav.kt index 0da915402..adf9f479f 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerNav.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerNav.kt @@ -13,4 +13,6 @@ sealed class SkillMakerNav { data class SpaceIshtar(val skill: Skill) : SkillMakerNav() data class Kukulkan(val skill: Skill) : SkillMakerNav() data class KukulkanTarget(val skill: Skill, val firstTarget: ServantTarget) : SkillMakerNav() + data object CommandSpell : SkillMakerNav() + data object CommandSpellWarning : SkillMakerNav() } \ No newline at end of file diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt index 3211e6395..cf348ca25 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt @@ -31,7 +31,8 @@ fun SkillMakerTarget( showKukulkan: Boolean, onKukulkan: () -> Unit, showMelusine: Boolean, - onMelusine: () -> Unit + onMelusine: () -> Unit, + showTargetNone: Boolean ) { Column( modifier = Modifier @@ -98,8 +99,10 @@ fun SkillMakerTarget( } } - Button(onClick = { onSkillTarget(null) }) { - Text(stringResource(R.string.skill_maker_target_none)) + if (showTargetNone) { + Button(onClick = { onSkillTarget(null) }) { + Text(stringResource(R.string.skill_maker_target_none)) + } } } } diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt index d93e43089..a87db86c1 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt @@ -13,6 +13,11 @@ import io.github.fate_grand_automata.scripts.models.ServantTarget import io.github.fate_grand_automata.scripts.models.Skill import io.github.fate_grand_automata.scripts.prefs.IBattleConfig import io.github.fate_grand_automata.scripts.prefs.IPreferences +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn import javax.inject.Inject @HiltViewModel @@ -48,6 +53,21 @@ class SkillMakerViewModel @Inject constructor( m } + private var _commandSpell: MutableStateFlow = + MutableStateFlow( + skillCommand.value.count { + it is SkillMakerEntry.Action && it.action is AutoSkillAction.CommandSpell + } + ) + + val commandSpell: StateFlow = _commandSpell + .map { it.coerceIn(0..3) } + .stateIn( + scope = viewModelScope, + started = SharingStarted.Eagerly, + initialValue = 0 + ) + private val _wave = mutableIntStateOf( if (state.skillString != null) { state.wave @@ -175,7 +195,7 @@ class SkillMakerViewModel @Inject constructor( } fun targetSkill(targets: List) { - val skill = (Skill.Servant.list + Skill.Master.list) + val skill = (Skill.Servant.list + Skill.Master.list + Skill.CommandSpell.list) .first { it.autoSkillCode == currentSkill } add( @@ -183,6 +203,10 @@ class SkillMakerViewModel @Inject constructor( when (skill) { is Skill.Servant -> AutoSkillAction.ServantSkill(skill, targets) is Skill.Master -> AutoSkillAction.MasterSkill(skill, targets.firstOrNull()) + is Skill.CommandSpell -> { + ++_commandSpell.value + AutoSkillAction.CommandSpell(skill, targets.firstOrNull()) + } } ) ) @@ -307,10 +331,17 @@ class SkillMakerViewModel @Inject constructor( } is SkillMakerEntry.Action -> { - if (last.action is AutoSkillAction.TargetEnemy) { - deleteSelected() - revertToPreviousEnemyTarget() - } else deleteSelected() + when(last.action) { + is AutoSkillAction.TargetEnemy -> { + deleteSelected() + revertToPreviousEnemyTarget() + } + is AutoSkillAction.CommandSpell -> { + --_commandSpell.value + deleteSelected() + } + else -> deleteSelected() + } } // Do nothing is SkillMakerEntry.Start -> { diff --git a/app/src/main/java/io/github/fate_grand_automata/util/LocalizationExtensions.kt b/app/src/main/java/io/github/fate_grand_automata/util/LocalizationExtensions.kt index c4d38ffc6..8a21c5e75 100644 --- a/app/src/main/java/io/github/fate_grand_automata/util/LocalizationExtensions.kt +++ b/app/src/main/java/io/github/fate_grand_automata/util/LocalizationExtensions.kt @@ -10,6 +10,7 @@ import io.github.fate_grand_automata.scripts.enums.ShuffleCardsEnum import io.github.fate_grand_automata.scripts.enums.SpamEnum import io.github.fate_grand_automata.scripts.enums.SupportClass import io.github.fate_grand_automata.scripts.enums.SupportSelectionModeEnum +import io.github.fate_grand_automata.scripts.models.Skill val RefillResourceEnum.stringRes get() = when (this) { @@ -185,4 +186,10 @@ val GameServer.simpleStringRes GameServer.Kr -> R.string.game_server_kr is GameServer.En -> R.string.game_server_na is GameServer.Jp -> R.string.game_server_jp + } + +val Skill.CommandSpell.stringRes + get() = when (this) { + Skill.CommandSpell.CS1 -> R.string.skill_maker_command_spell_full_np + Skill.CommandSpell.CS2 -> R.string.skill_maker_command_spell_full_hp } \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7c509bb40..21a0d7f08 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -5,6 +5,7 @@ #2e7d32 #006064 + #a03243 #616161 #c62828 #0277bd diff --git a/app/src/main/res/values/localized.xml b/app/src/main/res/values/localized.xml index 512d160f1..1cc617f07 100644 --- a/app/src/main/res/values/localized.xml +++ b/app/src/main/res/values/localized.xml @@ -117,6 +117,7 @@ Skills" "Stop on CE GET" "Stop on first-clear rewards" "First-time quest completion rewards and Bond CEs (Experimental)" + Ran out of Command Spell(s). "Screenshot Drops" "Saved to 'drops' folder" "Save unmodified screenshots" @@ -387,6 +388,12 @@ After pressing on the button, switch the app filter from \"Not optimized\" to \" "Download successful. Restarting app in 5 seconds." "Mélusine" + Command Spell + "CS (%d)" + Ran out of Command Spell(s) + Full NP + Full HP + "Reset all" "Reset to default" diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoBattle.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoBattle.kt index b9b88266a..adc88bb4c 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoBattle.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoBattle.kt @@ -74,6 +74,7 @@ class AutoBattle @Inject constructor( class CardPriorityParseError(val msg: String) : ExitReason() data object Paused : ExitReason() data object StopAfterThisRun : ExitReason() + data object OutOfCommandSpells: ExitReason() } internal class BattleExitException(val reason: ExitReason) : Exception(reason.cause) diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/MasterLocations.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/MasterLocations.kt index eaf95317e..40e72514a 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/MasterLocations.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/MasterLocations.kt @@ -47,4 +47,16 @@ class MasterLocations @Inject constructor( val masterSkillOpenClick get() = Location(0, 640) + masterOffsetNewUI + + val commandSpellOpenClick + get() = Region(if (isWide) -360 else -260, 100, 33, 53) + masterOffsetNewUI + + val cancelCommandSpellRegion = Region(-202, 764, 95, 174).xFromCenter() + + fun locate(skill: Skill.CommandSpell) = when (skill) { + Skill.CommandSpell.CS1 -> 700 + Skill.CommandSpell.CS2 -> 1000 + }.let { y -> + Location(0, y).xFromCenter() + } } \ No newline at end of file diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillAction.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillAction.kt index 18bc98659..f86701697 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillAction.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillAction.kt @@ -27,6 +27,11 @@ sealed class AutoSkillAction { class TargetEnemy(val enemy: EnemyTarget) : AutoSkillAction() + class CommandSpell( + val skill: Skill.CommandSpell, + val target: ServantTarget? + ) : AutoSkillAction() + class OrderChange( val starting: OrderChangeMember.Starting, val sub: OrderChangeMember.Sub diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillCommand.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillCommand.kt index 4b5036435..097e47bd8 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillCommand.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/AutoSkillCommand.kt @@ -70,6 +70,16 @@ class AutoSkillCommand private constructor( AutoSkillAction.MasterSkill(skill, target) } + in Skill.CommandSpell.list.map { it.autoSkillCode } -> { + val spell = Skill.CommandSpell.list.first { it.autoSkillCode == c } + val target = getTarget(queue) + + AutoSkillAction.CommandSpell( + skill = spell, + target = target + ) + } + in CommandCard.NP.list.map { it.autoSkillCode } -> { val np = CommandCard.NP.list.first { it.autoSkillCode == c } diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/Skill.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/Skill.kt index 7a6799e7f..4bfe71a3b 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/Skill.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/models/Skill.kt @@ -28,4 +28,16 @@ sealed class Skill(val autoSkillCode: Char) { val list by lazy { listOf(A, B, C) } } } + + sealed class CommandSpell(autoSkillCode: Char) : Skill(autoSkillCode) { + // full NP + data object CS1 : CommandSpell('m') + + // full HP + data object CS2 : CommandSpell('n') + + companion object { + val list by lazy { listOf(CS1, CS2) } + } + } } \ No newline at end of file diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/AutoSkill.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/AutoSkill.kt index 7e577707e..e5d79e016 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/AutoSkill.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/AutoSkill.kt @@ -17,6 +17,7 @@ class AutoSkill @Inject constructor( is AutoSkillAction.Atk -> {} is AutoSkillAction.ServantSkill -> caster.castServantSkill(action.skill, action.targets) is AutoSkillAction.MasterSkill -> caster.castMasterSkill(action.skill, action.target) + is AutoSkillAction.CommandSpell -> caster.castCommandSpell(action.skill, action.target) is AutoSkillAction.TargetEnemy -> caster.selectEnemyTarget(action.enemy) is AutoSkillAction.OrderChange -> caster.orderChange(action) } diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/Caster.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/Caster.kt index 2fcaefbda..d335ebda2 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/Caster.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/modules/Caster.kt @@ -2,6 +2,7 @@ package io.github.fate_grand_automata.scripts.modules import io.github.fate_grand_automata.scripts.IFgoAutomataApi import io.github.fate_grand_automata.scripts.Images +import io.github.fate_grand_automata.scripts.entrypoints.AutoBattle import io.github.fate_grand_automata.scripts.enums.SpamEnum import io.github.fate_grand_automata.scripts.models.AutoSkillAction import io.github.fate_grand_automata.scripts.models.CommandCard @@ -41,6 +42,11 @@ class Caster @Inject constructor( locations.battle.screenCheckRegion.exists(img, timeout) } + private fun confirmCommandSpell(): Boolean = locations.battle.master.cancelCommandSpellRegion.exists( + images[Images.Cancel], + timeout = 2.seconds + ) + private fun confirmSkillUse() { if (skillConfirmation == null) { skillConfirmation = locations.battle.skillUseRegion.exists(images[Images.SkillUse], 0.5.seconds) @@ -57,8 +63,23 @@ class Caster @Inject constructor( when (skill) { is Skill.Master -> locations.battle.master.locate(skill) is Skill.Servant -> locations.battle.locate(skill) + is Skill.CommandSpell -> locations.battle.master.locate(skill) }.click() + if (skill is Skill.CommandSpell) { + // has an extra confirmation window + + 0.5.seconds.wait() + val isCommandSpellExist = confirmCommandSpell() + if (isCommandSpellExist) { + locations.battle.skillOkClick.click() + } else { + throw AutoBattle.BattleExitException(AutoBattle.ExitReason.OutOfCommandSpells) + } + + 0.5.seconds.wait() + } + confirmSkillUse() targets.forEach { target -> @@ -126,6 +147,18 @@ class Caster @Inject constructor( locations.battle.locate(actualTarget)?.click() } + private fun openCommandSpellMenu() { + locations.battle.master.commandSpellOpenClick.click() + + 0.5.seconds.wait() + } + + fun castCommandSpell(skill: Skill.CommandSpell, target: ServantTarget?) { + openCommandSpellMenu() + + castSkill(skill, target) + } + private fun openMasterSkillMenu() { locations.battle.master.masterSkillOpenClick.click() From cb705687097b5269c5ae1020fabe5ca8e1c08e64 Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:18:55 +0800 Subject: [PATCH 2/7] missing assets --- app/src/main/assets/En/cancel.png | Bin 0 -> 2741 bytes .../fate_grand_automata/util/ImageLoader.kt | 1 + .../github/fate_grand_automata/scripts/Images.kt | 3 ++- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 app/src/main/assets/En/cancel.png diff --git a/app/src/main/assets/En/cancel.png b/app/src/main/assets/En/cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..f3a55583804f509287e56d183c9ccfb4294bad17 GIT binary patch literal 2741 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 literal 0 HcmV?d00001 diff --git a/app/src/main/java/io/github/fate_grand_automata/util/ImageLoader.kt b/app/src/main/java/io/github/fate_grand_automata/util/ImageLoader.kt index 01340609c..619a8535b 100644 --- a/app/src/main/java/io/github/fate_grand_automata/util/ImageLoader.kt +++ b/app/src/main/java/io/github/fate_grand_automata/util/ImageLoader.kt @@ -134,6 +134,7 @@ class ImageLoader @Inject constructor( Images.OkKR -> "ok-kr.png" Images.Execute -> "execute.png" Images.SupportBlankCE -> "support_blank_ce.png" + Images.Cancel -> "cancel.png" } override operator fun get(img: Images, gameServer: GameServer?): Pattern = synchronized(regionCachedPatterns) { diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/Images.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/Images.kt index 5fa842b78..d71b03507 100644 --- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/Images.kt +++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/Images.kt @@ -88,5 +88,6 @@ enum class Images { */ OkKR, Execute, - SupportBlankCE + SupportBlankCE, + Cancel } \ No newline at end of file From fd21b1dc91f6230e85cadd87c7b99d8d69866897 Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:26:23 +0800 Subject: [PATCH 3/7] fix missing --- .../java/io/github/fate_grand_automata/ui/exit/BattleExit.kt | 1 + .../fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt | 1 + .../ui/skill_maker/SkillMakerCommandSpell.kt | 4 ++-- .../fate_grand_automata/ui/skill_maker/SkillMakerEntry.kt | 1 + .../fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt | 4 +++- .../fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt | 1 + 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/exit/BattleExit.kt b/app/src/main/java/io/github/fate_grand_automata/ui/exit/BattleExit.kt index fbc59068c..31c391ab6 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/exit/BattleExit.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/exit/BattleExit.kt @@ -77,6 +77,7 @@ private fun AutoBattle.ExitReason.text(): String = when (this) { AutoBattle.ExitReason.FirstClearRewards -> stringResource(R.string.first_clear_rewards) AutoBattle.ExitReason.Paused -> stringResource(R.string.script_paused) AutoBattle.ExitReason.StopAfterThisRun -> stringResource(R.string.stop_after_this_run) + AutoBattle.ExitReason.OutOfCommandSpells -> stringResource(id = R.string.p_stop_on_out_of_command_spell) } @Composable diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt index 618075d55..4d45cc42b 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.core.view.WindowCompat import dagger.hilt.android.AndroidEntryPoint +import androidx.compose.runtime.collectAsState import io.github.fate_grand_automata.R import io.github.fate_grand_automata.scripts.models.ServantTarget import io.github.fate_grand_automata.scripts.models.Skill diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt index 547d76f96..f0870702b 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerCommandSpell.kt @@ -48,7 +48,7 @@ fun SkillMakerCommandSpells( verticalAlignment = Alignment.CenterVertically ) { Skill.CommandSpell.list.forEach { - SkillButton( + CommandSpellButton( skill = it, color = colorResource(R.color.colorCommandSpell) ) { @@ -60,7 +60,7 @@ fun SkillMakerCommandSpells( } @Composable -fun RowScope.SkillButton( +private fun RowScope.CommandSpellButton( skill: Skill, color: Color, onClick: () -> Unit diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerEntry.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerEntry.kt index 505b4c5c7..970be7c8b 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerEntry.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerEntry.kt @@ -33,6 +33,7 @@ sealed class SkillMakerEntry { is AutoSkillAction.ServantSkill -> toString(action.skill, action.targets) is AutoSkillAction.MasterSkill -> toString(action.skill, action.target) + is AutoSkillAction.CommandSpell -> toString(action.skill, action.target) is AutoSkillAction.TargetEnemy -> "t${action.enemy.autoSkillCode}" is AutoSkillAction.OrderChange -> "x${action.starting.autoSkillCode}${action.sub.autoSkillCode}" } diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt index cf348ca25..23fe21b06 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt @@ -129,6 +129,7 @@ private fun TestSkillMaker( showKukulkan: Boolean = false, showSpaceIshtar: Boolean = false, showMelusine: Boolean = showEmiya + showTargetNone: Boolean = false ) { FGATheme { SkillMakerTarget( @@ -140,7 +141,8 @@ private fun TestSkillMaker( showKukulkan = showKukulkan, onKukulkan = {}, showMelusine = showMelusine, - onMelusine = {} + onMelusine = {}, + showTargetNone = showTargetNone ) } } \ No newline at end of file diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt index a87db86c1..a8a96ddb7 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt @@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn +import androidx.lifecycle.viewModelScope import javax.inject.Inject @HiltViewModel From ca6b3f410b2c6c5c7502b142fdd57b0218305f7c Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:30:18 +0800 Subject: [PATCH 4/7] forgot comma --- .../fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt index 23fe21b06..053cf34be 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerTarget.kt @@ -128,7 +128,7 @@ private fun TestSkillMaker( showEmiya: Boolean = false, showKukulkan: Boolean = false, showSpaceIshtar: Boolean = false, - showMelusine: Boolean = showEmiya + showMelusine: Boolean = showEmiya, showTargetNone: Boolean = false ) { FGATheme { From 1b69db8bd6bf4b006f45fbd2d496e697de2ade55 Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:08:26 +0800 Subject: [PATCH 5/7] fix --- .../fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt index a8a96ddb7..46cffc585 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt @@ -56,7 +56,7 @@ class SkillMakerViewModel @Inject constructor( private var _commandSpell: MutableStateFlow = MutableStateFlow( - skillCommand.value.count { + skillCommand.count { it is SkillMakerEntry.Action && it.action is AutoSkillAction.CommandSpell } ) From 5bafd1a1191053ad98885597f52fd9dc39d3c14c Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:16:43 +0800 Subject: [PATCH 6/7] convert stateflow to state --- .../ui/skill_maker/SkillMakerActivity.kt | 2 +- .../ui/skill_maker/SkillMakerViewModel.kt | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt index 4d45cc42b..ff47a8999 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt @@ -83,7 +83,7 @@ fun SkillMakerUI( val turn by vm.turn val wave by vm.wave - val commandSpellRemaining by vm.commandSpell.collectAsState() + val commandSpellRemaining by vm.commandSpell Crossfade( current, diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt index 46cffc585..547fabc36 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerViewModel.kt @@ -54,20 +54,15 @@ class SkillMakerViewModel @Inject constructor( m } - private var _commandSpell: MutableStateFlow = - MutableStateFlow( + private var _commandSpell = + mutableIntStateOf( skillCommand.count { it is SkillMakerEntry.Action && it.action is AutoSkillAction.CommandSpell } ) - val commandSpell: StateFlow = _commandSpell + val commandSpell: State = _commandSpell .map { it.coerceIn(0..3) } - .stateIn( - scope = viewModelScope, - started = SharingStarted.Eagerly, - initialValue = 0 - ) private val _wave = mutableIntStateOf( if (state.skillString != null) { From 653627e48ef46ea1b0a8f986fcc292d6e5aa041d Mon Sep 17 00:00:00 2001 From: ArthurKun <16458204+ArthurKun21@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:19:53 +0800 Subject: [PATCH 7/7] fix --- .../fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt | 1 - .../github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt index ff47a8999..3fe278aba 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerActivity.kt @@ -12,7 +12,6 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.res.stringResource import androidx.core.view.WindowCompat import dagger.hilt.android.AndroidEntryPoint -import androidx.compose.runtime.collectAsState import io.github.fate_grand_automata.R import io.github.fate_grand_automata.scripts.models.ServantTarget import io.github.fate_grand_automata.scripts.models.Skill diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt index 3d5c8602d..3098d1304 100644 --- a/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt +++ b/app/src/main/java/io/github/fate_grand_automata/ui/skill_maker/SkillMakerMain.kt @@ -125,7 +125,7 @@ fun SkillMakerMain( Skills(onSkill = onSkill) } - val commandSpellRemaining by vm.commandSpell.collectAsState() + val commandSpellRemaining by vm.commandSpell Column( verticalArrangement = Arrangement.Bottom,