From 313bbe98535263689a85c1a1859472d2ff3407e4 Mon Sep 17 00:00:00 2001 From: MusicOnline <39178127+MusicOnline@users.noreply.github.com> Date: Sun, 10 Mar 2024 10:40:54 +0800 Subject: [PATCH] feat: add clash power range and win rate note --- components/EnemySkillForm.vue | 19 ++++++++++++ components/SinnerClashSummary.vue | 43 ++++++++++++++++----------- components/SinnerSkillForm.vue | 25 ++++++++++++++-- composables/state.ts | 37 ++++++++++++++++++++++++ pages/index.vue | 48 ++++++++++++++++--------------- utils/entities.ts | 9 ++++++ 6 files changed, 139 insertions(+), 42 deletions(-) diff --git a/components/EnemySkillForm.vue b/components/EnemySkillForm.vue index 64552cc..0a7a49d 100644 --- a/components/EnemySkillForm.vue +++ b/components/EnemySkillForm.vue @@ -1,5 +1,11 @@ diff --git a/components/SinnerClashSummary.vue b/components/SinnerClashSummary.vue index 1353c0a..df2fcec 100644 --- a/components/SinnerClashSummary.vue +++ b/components/SinnerClashSummary.vue @@ -12,7 +12,8 @@ const sinner = computed( if (!sinner.value) throw new Error(`Comparison sinner ${identityOrEgoId} does not exist`) -const enemySkill = useCustomEnemySkill() +const enemyClashSkill = useCustomEnemyClashSkill() + const getSinnerIdentityName = useGetSinnerIdentityName() const getSinnerSkillName = useGetSinnerSkillName() const removeComparisonSinner = useRemoveComparisonSinner() @@ -21,8 +22,8 @@ const sinnerName = computed( () => SINNER_TO_NAME[sinner.value.sinnerKey] ) -function getWinRate(skill: SkillStats): number { - const sinnerClashSkill = new ClashSkill( +function getSinnerClashSkill(skill: SkillStats): ClashSkill { + return new ClashSkill( skill.basePower, skill.numCoins, skill.coinPower, @@ -31,16 +32,15 @@ function getWinRate(skill: SkillStats): number { skill.finalClashPowerModifier, sinner.value.paralyzeCount ) - const enemyClashSkill = new ClashSkill( - enemySkill.value.basePower, - enemySkill.value.numCoins, - enemySkill.value.coinPower, - enemySkill.value.sanity, - enemySkill.value.offenseLevel, - enemySkill.value.finalClashPowerModifier, - enemySkill.value.paralyzeCount - ) - return computeClash(sinnerClashSkill, enemyClashSkill).winRate +} + +function getWinRate(skill: SkillStats): number { + const sinnerClashSkill = getSinnerClashSkill(skill) + return computeClash(sinnerClashSkill, enemyClashSkill.value).winRate +} +function getSinnerClashPowerRange(skill: SkillStats): [number, number] { + const sinnerClashSkill = getSinnerClashSkill(skill) + return sinnerClashSkill.clashPowerRange(enemyClashSkill.value) } @@ -81,7 +81,7 @@ function getWinRate(skill: SkillStats): number {
{{ getSinnerSkillName(sinner.sinnerKey, skill.id) }}
-
+
{{ skill.basePower }}
+
×{{ skill.numCoins }}
-
({{ skill.offenseLevel }} Off. Lv.)
-
Clash win rate: diff --git a/components/SinnerSkillForm.vue b/components/SinnerSkillForm.vue index 0de4ee7..3aed29c 100644 --- a/components/SinnerSkillForm.vue +++ b/components/SinnerSkillForm.vue @@ -11,13 +11,15 @@ import { } from "~/entities/SinnerSkill" import { SinnerSkillLocaleJsonSchema } from "~/entities/locales/SinnerSkill" -const customSkill = useCustomSinnerSkill() -const customSinnerStats = useCustomSinnerStats() - const sinnerToIdentityData = useSinnerToIdentityData() const sinnerToSkillData = useSinnerToSkillData() const sinnerToSkillLocale = useSinnerToSkillLocaleEn() +const customSkill = useCustomSinnerSkill() +const customSinnerStats = useCustomSinnerStats() +const sinnerClashSkill = useCustomSinnerClashSkill() +const enemyClashSkill = useCustomEnemyClashSkill() + const isLoadingSinner = ref(false) const selectedSinnerKey = ref(null) const selectedSinnerIdentityId = ref(null) @@ -75,6 +77,10 @@ const skillsForSelect = computed<{ value: number; label: string }[]>(() => { })) }) +const sinnerClashPowerRange = computed<[number, number]>(() => + sinnerClashSkill.value.clashPowerRange(enemyClashSkill.value) +) + async function changeSinnerAndFetchData() { selectedSinnerIdentityId.value = null selectedSinnerSkillId.value = null @@ -182,6 +188,7 @@ function updateCustomSinnerSkill() { v-model="selectedSinnerKey" @change="changeSinnerAndFetchData()" class="ml-1 font-bold flex-grow" + :ui-menu="{ height: 'max-h-fit' }" :options="Object.entries(SINNER_TO_NAME)" option-attribute="1" value-attribute="0" @@ -199,6 +206,7 @@ function updateCustomSinnerSkill() { " @change="selectedSinnerSkillId = null" class="ml-1 font-bold flex-grow" + :ui-menu="{ height: 'max-h-fit' }" :options="identitiesForSelect" value-attribute="value" /> @@ -310,5 +318,16 @@ function updateCustomSinnerSkill() { class="w-16 ml-1 font-bold inline-block" />
+ +
+ Clash Power Range: + + {{ sinnerClashPowerRange[0] }} + + ~ + + {{ sinnerClashPowerRange[1] }} + +
diff --git a/composables/state.ts b/composables/state.ts index d85b0f7..e92cad9 100644 --- a/composables/state.ts +++ b/composables/state.ts @@ -1,3 +1,5 @@ +import { ClashSkill } from "~/utils/entities" + export const useCustomEnemySkill = () => useState("customEnemySkill", () => ({ basePower: 6, @@ -25,3 +27,38 @@ export const useCustomSinnerStats = () => sanity: 45, paralyzeCount: 0, })) + +export const useCustomSinnerClashSkill = () => { + const customSinnerStats = useCustomSinnerStats() + const customSinnerSkill = useCustomSinnerSkill() + + return computed( + () => + new ClashSkill( + customSinnerSkill.value.basePower, + customSinnerSkill.value.numCoins, + customSinnerSkill.value.coinPower, + customSinnerStats.value.sanity, + customSinnerSkill.value.offenseLevel, + customSinnerSkill.value.finalClashPowerModifier, + customSinnerStats.value.paralyzeCount + ) + ) +} + +export const useCustomEnemyClashSkill = () => { + const customEnemySkill = useCustomEnemySkill() + + return computed( + () => + new ClashSkill( + customEnemySkill.value.basePower, + customEnemySkill.value.numCoins, + customEnemySkill.value.coinPower, + customEnemySkill.value.sanity, + customEnemySkill.value.offenseLevel, + customEnemySkill.value.finalClashPowerModifier, + customEnemySkill.value.paralyzeCount + ) + ) +} diff --git a/pages/index.vue b/pages/index.vue index f3f2a2d..77eb978 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -7,33 +7,13 @@ const stateTransitionDiagram = ref(null) const isMathRendered = ref(false) const isMathematicalProofEnabled = ref(false) -const customSinnerStats = useCustomSinnerStats() -const customSinnerSkill = useCustomSinnerSkill() -const customEnemySkill = useCustomEnemySkill() const comparisonSinners = useComparisonSinners() +const sinnerClashSkill = useCustomSinnerClashSkill() +const enemyClashSkill = useCustomEnemyClashSkill() const clashResult = computed(() => { - const p1 = new ClashSkill( - customSinnerSkill.value.basePower, - customSinnerSkill.value.numCoins, - customSinnerSkill.value.coinPower, - customSinnerStats.value.sanity, - customSinnerSkill.value.offenseLevel, - customSinnerSkill.value.finalClashPowerModifier, - customSinnerStats.value.paralyzeCount - ) - const p2 = new ClashSkill( - customEnemySkill.value.basePower, - customEnemySkill.value.numCoins, - customEnemySkill.value.coinPower, - customEnemySkill.value.sanity, - customEnemySkill.value.offenseLevel, - customEnemySkill.value.finalClashPowerModifier, - customEnemySkill.value.paralyzeCount - ) - console.time("Computed clash") - const result = computeClash(p1, p2) + const result = computeClash(sinnerClashSkill.value, enemyClashSkill.value) console.timeEnd("Computed clash") return result }) @@ -131,6 +111,28 @@ useHead({ :win-rate="clashResult.winRate" /> + +
+ Note: +
    +
  • + The in-game win rate is deceiving as it is a naive calculation that is + entirely inaccurate when negative Coin Power skills are involved. +
  • +
  • + Some skills, passives and support passives may conditionally grant extra Coin Power + and Clash Power that is not accounted for by default in this + calculator. You may edit the values manually. +
  • +
  • + Some skills, passives and support passives may grant extra Coin Power + and Clash Power based on the in-game win rate and NOT the accurate win + rate calculation given here. See the passive of Ishmael's base Zayin + E.G.O "Snagharpoon". You may edit the values manually. +
  • +
  • A better win rate does not guarantee a clash win.
  • +
+

diff --git a/utils/entities.ts b/utils/entities.ts index 435208f..2406f49 100644 --- a/utils/entities.ts +++ b/utils/entities.ts @@ -86,6 +86,15 @@ export class ClashSkill implements ComputeClashSkillStats { this.finalClashPowerModifier ) } + + clashPowerRange(enemy?: ClashSkill): [number, number] { + const powerAtNoHeads = this.clashPower(0, enemy) + const powerAtMaxHeads = this.clashPower(this.numCoins, enemy) + return [ + Math.min(powerAtNoHeads, powerAtMaxHeads), + Math.max(powerAtNoHeads, powerAtMaxHeads), + ] + } } export class CoinNumberState {