diff --git a/app/src/main/assets/Tw/close.png b/app/src/main/assets/Tw/close.png
index 4af75a0a8..0bdaa681d 100644
Binary files a/app/src/main/assets/Tw/close.png and b/app/src/main/assets/Tw/close.png differ
diff --git a/app/src/main/java/io/github/fate_grand_automata/runner/ScriptLauncherResponseHandler.kt b/app/src/main/java/io/github/fate_grand_automata/runner/ScriptLauncherResponseHandler.kt
index 38fda0461..03262e277 100644
--- a/app/src/main/java/io/github/fate_grand_automata/runner/ScriptLauncherResponseHandler.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/runner/ScriptLauncherResponseHandler.kt
@@ -31,6 +31,8 @@ class ScriptLauncherResponseHandler @Inject constructor(
giftBoxResp?.let { handleGiftBoxResponse(it) }
+ prefs.loopIntoLotteryAfterPresentBox = resp.returnToLottery
+
ScriptModeEnum.Lottery
}
diff --git a/app/src/main/java/io/github/fate_grand_automata/runner/ScriptManager.kt b/app/src/main/java/io/github/fate_grand_automata/runner/ScriptManager.kt
index 0796c2bba..922d1add3 100644
--- a/app/src/main/java/io/github/fate_grand_automata/runner/ScriptManager.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/runner/ScriptManager.kt
@@ -160,9 +160,30 @@ class ScriptManager @Inject constructor(
}
is AutoLottery.ExitException -> {
- val msg = when (e.reason) {
+ // Resetting these preferences ensures that the script does not loop into the lottery
+ // or assume the present box is full after handling an AutoLottery.ExitException.
+ preferences.loopIntoLotteryAfterPresentBox = false
+ preferences.isPresentBoxFull = false
+ val msg = when (val reason = e.reason) {
AutoLottery.ExitReason.PresentBoxFull -> context.getString(R.string.present_box_full)
AutoLottery.ExitReason.RanOutOfCurrency -> context.getString(R.string.lottery_currency_depleted)
+ is AutoLottery.ExitReason.PresentBoxFullAndCannotSelectAnymore -> {
+ if (reason.pickedGoldEmbers == 0) {
+ context.getString(R.string.present_box_full_and_embers_are_overflowing)
+ } else {
+ context.getString(
+ R.string.present_box_full_and_have_pick_at_least_embers,
+ reason.pickedGoldEmbers
+ )
+ }
+ }
+
+ AutoLottery.ExitReason.NoEmbersFound -> context.getString(R.string.no_embers_found)
+ is AutoLottery.ExitReason.CannotSelectAnyMore -> {
+ context.getString(R.string.picked_exp_stacks, reason.pickedStacks, reason.pickedGoldEmbers)
+ }
+
+ AutoLottery.ExitReason.Abort -> context.getString(R.string.aborted)
}
messages.notify(msg)
@@ -170,6 +191,8 @@ class ScriptManager @Inject constructor(
}
is AutoGiftBox.ExitException -> {
+ preferences.loopIntoLotteryAfterPresentBox = false
+ preferences.isPresentBoxFull = false
val msg = when (val reason = e.reason) {
is AutoGiftBox.ExitReason.CannotSelectAnyMore -> context.getString(
R.string.picked_exp_stacks,
@@ -178,6 +201,11 @@ class ScriptManager @Inject constructor(
)
AutoGiftBox.ExitReason.NoEmbersFound -> context.getString(R.string.no_embers_found)
+ is AutoGiftBox.ExitReason.ReturnToLottery -> context.getString(
+ R.string.picked_exp_stacks_return_to_lottery,
+ reason.pickedStacks,
+ reason.pickedGoldEmbers
+ )
}
messages.notify(msg)
diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/fine_tune/FineTuneSettingsViewModel.kt b/app/src/main/java/io/github/fate_grand_automata/ui/fine_tune/FineTuneSettingsViewModel.kt
index c68e2b722..00d833920 100644
--- a/app/src/main/java/io/github/fate_grand_automata/ui/fine_tune/FineTuneSettingsViewModel.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/ui/fine_tune/FineTuneSettingsViewModel.kt
@@ -88,7 +88,14 @@ class FineTuneSettingsViewModel @Inject constructor(
valueRange = 0..50,
valueRepresentation = { "${it}ms" },
hint = "Delay between individual taps/clicks when doing so repeatedly like at the end of battles, friend point summon and lottery script."
- )
+ ),
+ FineTuneItem(
+ pref = prefs.lottoSpin,
+ name = R.string.p_fine_tune_lotto_clicks,
+ icon = icon(R.drawable.ic_click),
+ valueRange = 10..20,
+ hint = "The number of clicks for lotto spin. Decrease this if your device is lagging."
+ ),
)
),
FineTuneGroup(
diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/GiftBoxLauncher.kt b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/GiftBoxLauncher.kt
index 4f9737e4f..8f6309c1b 100644
--- a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/GiftBoxLauncher.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/GiftBoxLauncher.kt
@@ -29,6 +29,12 @@ fun ColumnScope.GiftBoxLauncherContent(
maxGoldEmberTotalCount: Int,
changeMaxGoldEmberTotalCount: (Int) -> Unit
) {
+ Text(
+ text = stringResource(R.string.p_script_mode_gift_box_warning),
+ modifier= Modifier.fillMaxWidth(),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.secondary
+ )
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/LotteryLauncher.kt b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/LotteryLauncher.kt
index 7fa6b2ad9..e43d56af5 100644
--- a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/LotteryLauncher.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/LotteryLauncher.kt
@@ -1,5 +1,10 @@
package io.github.fate_grand_automata.ui.launcher
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.shrinkVertically
+import androidx.compose.animation.slideInVertically
+import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -12,12 +17,14 @@ import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.github.fate_grand_automata.R
import io.github.fate_grand_automata.scripts.prefs.IPreferences
@@ -28,8 +35,9 @@ fun lotteryLauncher(
modifier: Modifier = Modifier
): ScriptLauncherResponseBuilder {
var receiveEmbers by remember { mutableStateOf(prefs.receiveEmbersWhenGiftBoxFull) }
- var maxGoldEmberStackSize by remember { mutableStateOf(prefs.maxGoldEmberStackSize) }
- var maxGoldEmberTotalCount by remember { mutableStateOf(prefs.maxGoldEmberTotalCount) }
+ var returnToLotteryAfterPresentBox by remember { mutableStateOf(prefs.loopIntoLotteryAfterPresentBox) }
+ var maxGoldEmberStackSize by remember { mutableIntStateOf(prefs.maxGoldEmberStackSize) }
+ var maxGoldEmberTotalCount by remember { mutableIntStateOf(prefs.maxGoldEmberTotalCount) }
Column(
modifier = modifier
@@ -67,23 +75,64 @@ fun lotteryLauncher(
)
}
- if (receiveEmbers) {
- GiftBoxLauncherContent(
- maxGoldEmberStackSize = maxGoldEmberStackSize,
- changeMaxGoldEmberStackSize = { maxGoldEmberStackSize = it },
- maxGoldEmberTotalCount = maxGoldEmberTotalCount,
- changeMaxGoldEmberTotalCount = { maxGoldEmberTotalCount = it }
+ AnimatedVisibility(
+ visible = receiveEmbers,
+ label = "Animate the showing of the gift box settings",
+ enter = slideInVertically { it } + expandVertically(expandFrom = Alignment.Top),
+ exit = slideOutHorizontally { -it } + shrinkVertically(shrinkTowards = Alignment.Top)
+ ) {
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ GiftBoxLauncherContent(
+ maxGoldEmberStackSize = maxGoldEmberStackSize,
+ changeMaxGoldEmberStackSize = { maxGoldEmberStackSize = it },
+ maxGoldEmberTotalCount = maxGoldEmberTotalCount,
+ changeMaxGoldEmberTotalCount = { maxGoldEmberTotalCount = it },
+ )
+ }
+ }
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 5.dp)
+ .clickable(
+ enabled = receiveEmbers,
+ onClick = {
+ returnToLotteryAfterPresentBox = !returnToLotteryAfterPresentBox
+ }
+ )
+ ) {
+ Text(
+ stringResource(R.string.p_return_to_lottery),
+ style = MaterialTheme.typography.bodyMedium,
+ color = when(receiveEmbers) {
+ true -> MaterialTheme.colorScheme.secondary
+ false -> MaterialTheme.colorScheme.secondary.copy(alpha = 0.3f)
+ },
+ textAlign = TextAlign.Justify
+ )
+
+ Switch(
+ checked = returnToLotteryAfterPresentBox,
+ onCheckedChange = { returnToLotteryAfterPresentBox = it },
+ enabled = receiveEmbers
)
}
+
+
}
return ScriptLauncherResponseBuilder(
canBuild = { true },
build = {
ScriptLauncherResponse.Lottery(
- if (receiveEmbers) {
+ giftBox = if (receiveEmbers) {
ScriptLauncherResponse.GiftBox(maxGoldEmberStackSize, maxGoldEmberTotalCount)
- } else null
+ } else null,
+ returnToLottery = returnToLotteryAfterPresentBox
)
}
)
diff --git a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/ScriptLauncherResponse.kt b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/ScriptLauncherResponse.kt
index e2c2bfecc..a8435c406 100644
--- a/app/src/main/java/io/github/fate_grand_automata/ui/launcher/ScriptLauncherResponse.kt
+++ b/app/src/main/java/io/github/fate_grand_automata/ui/launcher/ScriptLauncherResponse.kt
@@ -4,7 +4,8 @@ sealed class ScriptLauncherResponse {
data object Cancel : ScriptLauncherResponse()
data class FP(val limit: Int?) : ScriptLauncherResponse()
data class Lottery(
- val giftBox: GiftBox?
+ val giftBox: GiftBox?,
+ val returnToLottery: Boolean,
) : ScriptLauncherResponse()
data class GiftBox(
diff --git a/app/src/main/res/values/localized.xml b/app/src/main/res/values/localized.xml
index f6f59a355..5b0f82bba 100644
--- a/app/src/main/res/values/localized.xml
+++ b/app/src/main/res/values/localized.xml
@@ -89,6 +89,7 @@ Skills"
"Runs"
"Limit number of rolls"
"Receive embers"
+ "Experimental:\nReturn to lottery after successfully getting ember/s from present box.\nThis will loop until you got full present box and embers in storage."
"Name"
"Command"
"Notes"
@@ -158,6 +159,7 @@ Copy or rename it if you want to keep it."
"MLB Similarity"
"Stage Counter Similarity"
"Clicks"
+ "Lotto Clicks"
"Wait after clicking"
"Click duration"
"Multi-Click Interval"
@@ -237,6 +239,8 @@ Please turn on accessibility for this app from System settings. If it is already
"Ran out of lottery currency"
"Inventory Full"
"Present Box Full"
+ "Present Box is full and Embers are overflowing."
+ "Present Box is full and Embers are overflowing. Have pick at least %d Gold embers"
"No support images were found on the current screen. Are you on Support selection or Friend list screen?"
"Support selection set to Manual"
"When using 'preferred' support selection mode, specify at least one Servant or Craft Essence."
@@ -256,7 +260,10 @@ Please turn on accessibility for this app from System settings. If it is already
"Average time per run: %s"
"Turns: %d"
"Turns: %1$d (min), %2$.02f (avg), %3$d (max)"
+
"Picked %1$d EXP stacks, resulting in a total amount of %2$d Gold embers"
+ "Picked %d EXP stacks, resulting in a total amount of %d Gold embers. Returning to lottery."
+
"Couldn't find Embers on screen. Make sure that you've filtered for EXP cards."
"Failed to get root access"
"Materials"
@@ -454,6 +461,10 @@ After pressing on the button, switch the app filter from \"Not optimized\" to \"
Treat Support like own Servants
Will do normal face card checks instead of looking for the "Support" icon on face cards. This solves problems with super-buffed Support Servants, but will break card priority if you have 2 of the same Servant in the party.
+ Aborted
+
+ Please ensure you have set the filters to Embers only.
+
"Screenshot Bond"
"Experimental screenshot of bond level up regardless of level to 'bond' folder\nNote: Auto-click on another results screen might cause occasional missed screenshots, potentially skipping the bond level-up."
Hide SQ in AP Resources
diff --git a/prefs/src/main/java/io/github/fate_grand_automata/prefs/Preferences.kt b/prefs/src/main/java/io/github/fate_grand_automata/prefs/Preferences.kt
index bcee9eecd..624a16ced 100644
--- a/prefs/src/main/java/io/github/fate_grand_automata/prefs/Preferences.kt
+++ b/prefs/src/main/java/io/github/fate_grand_automata/prefs/Preferences.kt
@@ -114,6 +114,12 @@ class PreferencesImpl @Inject constructor(
override var receiveEmbersWhenGiftBoxFull by prefs.receiveEmbersWhenGiftBoxFull
+ override var loopIntoLotteryAfterPresentBox by prefs.loopIntoLotteryAfterPresentBox
+
+ override var isPresentBoxFull by prefs.isPresentBoxFull
+
+ override var lottoSpin by prefs.lottoSpin
+
private val autoSkillMap = mutableMapOf()
override val servant: IServantEnhancementPreferences =
diff --git a/prefs/src/main/java/io/github/fate_grand_automata/prefs/core/PrefsCore.kt b/prefs/src/main/java/io/github/fate_grand_automata/prefs/core/PrefsCore.kt
index 98be008d1..d064d74e2 100644
--- a/prefs/src/main/java/io/github/fate_grand_automata/prefs/core/PrefsCore.kt
+++ b/prefs/src/main/java/io/github/fate_grand_automata/prefs/core/PrefsCore.kt
@@ -54,6 +54,9 @@ class PrefsCore @Inject constructor(
val shouldLimitFP = maker.bool("should_fp_limit")
val limitFP = maker.int("fp_limit", 1)
val receiveEmbersWhenGiftBoxFull = maker.bool("receive_embers_when_gift_box_full")
+ val loopIntoLotteryAfterPresentBox = maker.bool("loop_into_lottery_after_present_box")
+ val isPresentBoxFull = maker.bool("is_present_box_full")
+ val lottoSpin = maker.stringAsInt("lotto_spin", 20)
val supportSwipesPerUpdate = maker.int("support_swipes_per_update_x", 10)
val supportMaxUpdates = maker.int("support_max_updates_x", 5)
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..802780fcd 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
@@ -343,7 +343,7 @@ class AutoBattle @Inject constructor(
// Lock the Ordeal Call for JP server
if (prefs.gameServer !is GameServer.Jp) return false
- return images[Images.Close] in locations.ordealCallOutOfPodsRegion
+ return images[Images.Close] in locations.closeLowerMiddleScreenRegion
}
private fun ordealCallOutOfPods() {
diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoGiftBox.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoGiftBox.kt
index 175775d15..13424e68a 100644
--- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoGiftBox.kt
+++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoGiftBox.kt
@@ -3,6 +3,7 @@ package io.github.fate_grand_automata.scripts.entrypoints
import io.github.fate_grand_automata.scripts.IFgoAutomataApi
import io.github.fate_grand_automata.scripts.Images
import io.github.fate_grand_automata.scripts.enums.GameServer
+import io.github.fate_grand_automata.scripts.enums.ScriptModeEnum
import io.github.fate_grand_automata.scripts.modules.ConnectionRetry
import io.github.lib_automata.EntryPoint
import io.github.lib_automata.ExitManager
@@ -21,7 +22,9 @@ class AutoGiftBox @Inject constructor(
private val connectionRetry: ConnectionRetry
) : EntryPoint(exitManager), IFgoAutomataApi by api {
sealed class ExitReason {
- object NoEmbersFound : ExitReason()
+
+ class ReturnToLottery(val pickedStacks: Int, val pickedGoldEmbers: Int) : ExitReason()
+ data object NoEmbersFound : ExitReason()
class CannotSelectAnyMore(val pickedStacks: Int, val pickedGoldEmbers: Int) : ExitReason()
}
@@ -72,6 +75,35 @@ class AutoGiftBox @Inject constructor(
receiveEnabledPattern in receiveEnabledRegion
)
+
+ if (prefs.loopIntoLotteryAfterPresentBox && prefs.scriptMode == ScriptModeEnum.Lottery) {
+ val isFullDialog = locations.closeLowerMiddleScreenRegion.exists(
+ images[Images.Close],
+ timeout = 10.seconds
+ )
+ if (isFullDialog) {
+ prefs.isPresentBoxFull = true
+ locations.closeLowerMiddleScreenRegion.click()
+ 0.5.seconds.wait()
+ }
+ // close window
+ locations.resultCeRewardCloseClick.click()
+ 1.seconds.wait()
+
+ locations.lottery.checkRegion.exists(
+ images[Images.LotteryBoxFinished],
+ timeout = 15.seconds
+ )
+
+ throw ExitException(
+ ExitReason.ReturnToLottery(
+ totalSelected.pickedStacks,
+ totalSelected.pickedGoldEmbers
+ )
+ )
+ }
+
+
throw ExitException(
ExitReason.CannotSelectAnyMore(
totalSelected.pickedStacks,
diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoLottery.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoLottery.kt
index 013e9b8ea..c7c481f15 100644
--- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoLottery.kt
+++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/entrypoints/AutoLottery.kt
@@ -5,6 +5,7 @@ import io.github.fate_grand_automata.scripts.Images
import io.github.fate_grand_automata.scripts.modules.ConnectionRetry
import io.github.lib_automata.EntryPoint
import io.github.lib_automata.ExitManager
+import io.github.lib_automata.ScriptAbortException
import io.github.lib_automata.dagger.ScriptScope
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@@ -20,8 +21,20 @@ class AutoLottery @Inject constructor(
private val connectionRetry: ConnectionRetry
) : EntryPoint(exitManager), IFgoAutomataApi by api {
sealed class ExitReason {
- object RanOutOfCurrency : ExitReason()
- object PresentBoxFull : ExitReason()
+ data object RanOutOfCurrency : ExitReason()
+ data object PresentBoxFull : ExitReason()
+
+ data object NoEmbersFound : ExitReason()
+
+ class CannotSelectAnyMore(
+ val pickedStacks: Int, val pickedGoldEmbers: Int,
+ ) : ExitReason()
+
+ object Abort : ExitReason()
+
+ class PresentBoxFullAndCannotSelectAnymore(
+ val pickedStacks: Int, val pickedGoldEmbers: Int,
+ ) : ExitReason()
}
class ExitException(val reason: ExitReason) : Exception()
@@ -29,20 +42,66 @@ class AutoLottery @Inject constructor(
private fun spin() {
// Don't increase this too much or you'll regret when you're not able to stop the script
// And your phone won't let you press anything
- locations.lottery.spinClick.click(20)
+ locations.lottery.spinClick.click(
+ prefs.lottoSpin
+ )
}
+ private var pickedStacks = 0
+ private var pickedGoldEmbers = 0
+
+
private fun presentBoxFull() {
if (prefs.receiveEmbersWhenGiftBoxFull) {
+ if (prefs.isPresentBoxFull) {
+ throw ExitException(
+ ExitReason.PresentBoxFullAndCannotSelectAnymore(
+ pickedStacks,
+ pickedGoldEmbers
+ )
+ )
+ }
+
val moveToPresentBox = locations.lottery.fullPresentBoxRegion
.find(images[Images.PresentBoxFull])
moveToPresentBox?.region?.click()
3.seconds.wait()
- giftBox.script()
+ try {
+ giftBox.script()
+ } catch (e: AutoGiftBox.ExitException) {
+ when (e.reason) {
+ is AutoGiftBox.ExitReason.ReturnToLottery -> {
+ if (!prefs.isPresentBoxFull) {
+ pickedStacks += e.reason.pickedStacks
+ pickedGoldEmbers += e.reason.pickedGoldEmbers
+ }
+ }
+
+ AutoGiftBox.ExitReason.NoEmbersFound -> {
+ throw ExitException(ExitReason.NoEmbersFound)
+ }
+
+ is AutoGiftBox.ExitReason.CannotSelectAnyMore -> {
+ // this will only execute if the loop present box is not enabled
+ throw ExitException(
+ ExitReason.CannotSelectAnyMore(
+ e.reason.pickedStacks,
+ e.reason.pickedGoldEmbers
+ )
+ )
+ }
+ }
+ }
}
+
+ // If the loopIntoLotteryAfterPresentBox preference is enabled,
+ // return silently to allow the script to continue looping into the lottery.
+ if (prefs.loopIntoLotteryAfterPresentBox) {
+ return
+ }
throw ExitException(ExitReason.PresentBoxFull)
}
@@ -78,6 +137,17 @@ class AutoLottery @Inject constructor(
}
override fun script(): Nothing {
+ prefs.isPresentBoxFull = false
+ try {
+ loop()
+ } catch (e: ScriptAbortException) {
+ throw ExitException(ExitReason.Abort)
+ } catch (e: ExitException) {
+ throw e
+ }
+ }
+
+ private fun loop(): Nothing {
val screens: Map<() -> Boolean, () -> Unit> = mapOf(
{ connectionRetry.needsToRetry() } to { connectionRetry.retry() },
{ images[Images.PresentBoxFull] in locations.lottery.fullPresentBoxRegion } to { presentBoxFull() },
diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/Locations.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/Locations.kt
index 00fcb91b7..a51d0a4be 100644
--- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/Locations.kt
+++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/locations/Locations.kt
@@ -29,7 +29,11 @@ class Locations @Inject constructor(
val inventoryFullRegion = Region(-280, 860, 560, 190).xFromCenter()
- val ordealCallOutOfPodsRegion = Region(-112, 1088, 219, 72).xFromCenter()
+ val closeLowerMiddleScreenRegion = when(gameServer){
+ is GameServer.En -> Region(-111, 1084, 219, 72).xFromCenter()
+ // JP and TW Option
+ else -> Region(-112, 1088, 219, 72).xFromCenter()
+ }
val ordealCallOutOfPodsClick = Location(-2, 1124).xFromCenter()
diff --git a/scripts/src/main/java/io/github/fate_grand_automata/scripts/prefs/IPreferences.kt b/scripts/src/main/java/io/github/fate_grand_automata/scripts/prefs/IPreferences.kt
index 46df78165..8e7963436 100644
--- a/scripts/src/main/java/io/github/fate_grand_automata/scripts/prefs/IPreferences.kt
+++ b/scripts/src/main/java/io/github/fate_grand_automata/scripts/prefs/IPreferences.kt
@@ -36,6 +36,10 @@ interface IPreferences {
var shouldLimitFP: Boolean
var limitFP: Int
var receiveEmbersWhenGiftBoxFull: Boolean
+ var loopIntoLotteryAfterPresentBox: Boolean
+ var isPresentBoxFull: Boolean
+
+ val lottoSpin: Int
val stageCounterSimilarity: Double
val stageCounterNew: Boolean