Skip to content

Wife3 Scoring System.hx

AutisticLulu edited this page Oct 18, 2025 · 8 revisions

Wife3 Scoring Script for Psych Engine

HScript-based scoring system that implements Etterna's Wife3 accuracy calculation into Psych Engine.

Features:

  • Complete Wife3 Algorithm: Full Etterna-based accuracy calculation
  • Timing Feedback: Color-coded timing display shows hit accuracy
  • Judge Presets: 9 difficulty presets (J1-J9) plus custom scaling
  • 20+ API Functions: Comprehensive API for custom UI development

Wife3 Scoring System - API Reference

Wife3 (Wife version 3) is Etterna's timing-based accuracy algorithm. This script provides 20 global callback functions accessible from any Lua or HScript.


📖 Table of Contents


Configuration Functions

wife3_setEnabled(enabled: Bool)

Enable or disable Wife3 calculations. Does not replace Psych Engine's calculations. See wife3_setReplaceScoreText for replacing score text.

wife3_setEnabled(true)   -- Enable (default)
wife3_setEnabled(false)  -- Disable

wife3_setJudgePreset(judgeNum: Int)

Set difficulty preset (1-9). See Judge Presets for details.

wife3_setJudgePreset(4)  -- J4 = Standard difficulty
wife3_setJudgePreset(9)  -- J9 = JUSTICE (hardest)

wife3_setJudgeScale(scale: Float)

Manually set judge scale value (advanced users).

wife3_setJudgeScale(1.0)   -- Same as J4
wife3_setJudgeScale(0.4)   -- Same as J9

Note: Scale range is 0.009 to 0.090. Values outside this range are clamped.

wife3_resetAccuracy()

Reset all Wife3 counters to zero. Useful for practice mode or custom restart mechanics.

wife3_resetAccuracy()

wife3_setReplaceScoreText(replace: Bool)

Enable or disable Wife3 score text replacement (replaces Psych Engine's default score display text).

wife3_setReplaceScoreText(true)   -- Replace Psych Engine's default score text
wife3_setReplaceScoreText(false)  -- Use Psych Engine's default score text

wife3_setShowTimingDisplay(show: Bool)

Enable or disable the built-in timing feedback display.

wife3_setShowTimingDisplay(true)   -- Show timing feedback (default)
wife3_setShowTimingDisplay(false)  -- Hide timing feedback

Data Getter Functions

wife3_getAccuracy(): Float

Returns current accuracy percentage (0-100) based on notes hit so far.

local accuracy = wife3_getAccuracy()
-- Example: 98.45

wife3_getScore(): Int

Returns current song score (Wife3 calculated).

local score = wife3_getScore()
-- Example: 987654

wife3_getGrade(percent: Float): String

Returns letter grade for a given percentage value.

local currentGrade = wife3_getGrade(wife3_getAccuracy())
-- Returns: 'AAAAA', 'AAAA', 'AAA', 'AA', 'A', 'B', 'C', 'D', or 'F'

local hypotheticalGrade = wife3_getGrade(97.5)
-- Calculate grade for any percentage

wife3_getJudgeScale(): Float

Returns the current judge scale value.

local scale = wife3_getJudgeScale()
-- Example: 1.0 (J4)

wife3_getJudgePreset(): Float

Returns the current judge preset as a number (can be fractional for custom scales).

local preset = wife3_getJudgePreset()
-- Returns: 4.0 for J4, 7.25 for custom scale between J7 and J8, etc.

wife3_getReplaceScoreText(): Bool

Returns whether Wife3 score text replacement is currently enabled.

local isReplacing = wife3_getReplaceScoreText()
-- Returns: true if Wife3 is replacing score text, false otherwise

wife3_getShowTimingDisplay(): Bool

Returns whether the timing feedback display is currently enabled.

local showTiming = wife3_getShowTimingDisplay()
-- Returns: true if timing display is enabled, false otherwise

Judgement Counters

Get the number of hits in each timing window:

wife3_getMarvelousHits(): Int

Returns number of Marvelous hits (≤ 22ms × judge scale).

wife3_getPerfectHits(): Int

Returns number of Perfect hits (≤ 45ms × judge scale).

wife3_getGreatHits(): Int

Returns number of Great hits (≤ 90ms × judge scale).

wife3_getGoodHits(): Int

Returns number of Good hits (≤ 135ms × judge scale).

wife3_getBadHits(): Int

Returns number of Bad hits (≤ 180ms × judge scale).


Utility Functions

wife3_getTimingWindow(windowType: String): Float

Get a timing window (in ms) based on current judge scale.

local marvelousWindow = wife3_getTimingWindow('marvelous')  -- ~22ms * scale
local perfectWindow = wife3_getTimingWindow('perfect')      -- ~45ms * scale
local greatWindow = wife3_getTimingWindow('great')          -- ~90ms * scale
local goodWindow = wife3_getTimingWindow('good')            -- ~135ms * scale
local badWindow = wife3_getTimingWindow('bad')              -- ~180ms * scale

Valid window types: 'marvelous', 'perfect', 'great', 'good', 'bad'

wife3_formatPercent(value: Float): String

Format a number to 2 decimal places.

local formatted = wife3_formatPercent(98.456789)
-- Returns: '98.45'

wife3_updateScoreText()

Manually update the score text display. Called automatically when Wife3 score text replacement is enabled.

wife3_updateScoreText()
-- Updates score text with current Wife3 data

Built-in Features

The Wife3 Scoring System includes several built-in features that work out of the box:

Score Text Replacement

By default, Wife3 replaces Psych Engine's score text while keeping Psych Engines style.

  • Default Format: Score: 987654 | Misses: 3 | Rating: 98.45% (AAA)
  • Enabled by default: Score text replacement is automatically active
  • Score Bop Animation: Maintains Psych Engine's score bounce animation
  • Respects Settings: Honors client preferences for score zoom
-- Control score text replacement
wife3_setReplaceScoreText(true)   -- Enable Wife3 score text (default)
wife3_setReplaceScoreText(false)  -- Use Psych Engine's default score text

-- Check current state
local isReplacing = wife3_getReplaceScoreText()

Timing Feedback Display

Built-in visual timing feedback shows hit accuracy in real-time:

  • Location: Center of the playfield between notes
  • Color-Coded: Different colors for different timing windows
  • Animation: Smooth fade-in/fade-out with upward movement
  • Format: +12.34ms or -5.67ms

Timing Display Colors:

  • White: Marvelous (≤22ms × judge scale)
  • Yellow: Perfect (≤45ms × judge scale)
  • Green: Great (≤90ms × judge scale)
  • Cyan: Good (≤135ms × judge scale)
  • Magenta: Bad (≤180ms × judge scale)
  • Red: Way off (>180ms × judge scale)
-- Control timing display
wife3_setShowTimingDisplay(true)   -- Show timing feedback (default)
wife3_setShowTimingDisplay(false)  -- Hide timing feedback

-- Check current state  
local showTiming = wife3_getShowTimingDisplay()

Judge Presets

Judge presets control the timing window difficulty. Lower numbers are easier (wider timing windows), higher numbers are harder (tighter timing windows).

Preset Judge Scale Value Description Typical Use Case
1 J1 4.0 Easiest Casual play, story mode
2 J2 3.0 Very Easy Beginner friendly
3 J3 2.0 Easy Learning new charts
4 J4 1.0 Standard Default/Competitive baseline
5 J5 0.9 Slightly Hard Intermediate challenge
6 J6 0.75 Hard Advanced players
7 J7 0.6 Very Hard Expert challenge
8 J8 0.5 Extremely Hard Mastery testing
9 J9 0.4 JUSTICE Hardest possible

Setting Judge Preset

wife3_setJudgePreset(4)  -- Standard (default)
wife3_setJudgePreset(9)  -- JUSTICE (hardest)

Manual Scale Setting

For fine-tuned control, use wife3_setJudgeScale():

wife3_setJudgeScale(1.0)   -- J4 equivalent
wife3_setJudgeScale(0.6)   -- J7 equivalent
wife3_setJudgeScale(0.85)  -- Custom (between J5 and J6)

Grading System

Wife3 uses Etterna's letter grade system based on accuracy percentage:

Grade Min % Description Tier
AAAAA 99.70% Quadstar Nearly perfect
AAAA 99.50% Quad Exceptional
AAA 99.00% Triple Excellent
AA 98.00% Double Very Good
A 96.50% Single Good
B 93.00% B Tier Above Average
C 90.00% C Tier Average
D 80.00% D Tier Below Average
F < 80.00% Failed Needs Improvement

Grade Calculation

Grades are calculated using the wife3_getGrade(percent) function:

local currentGrade = wife3_getGrade(wife3_getAccuracy())
-- Returns current grade based on accuracy

local hypotheticalGrade = wife3_getGrade(97.5)
-- Calculate grade for any percentage

UI Examples

The Wife3 Scoring System is designed to be UI-agnostic, providing only the calculation backend. Here are complete UI implementation examples for both Lua and HScript.

Minimal Lua Example

For a simpler implementation, here's a minimal Lua example:

-- Simple Wife3 Display (Lua)
function onCreatePost()
    makeLuaText('wife3Display', '', 0, 0, getProperty('scoreTxt.y') + 25)
    setTextSize('wife3Display', 18)
    setTextFont('wife3Display', 'vcr.ttf')
    setTextBorder('wife3Display', 1, '000000')
    setTextAlignment('wife3Display', 'center')
    setObjectCamera('wife3Display', 'hud')
    addLuaText('wife3Display')
end

function updateWife3()
    local acc = wife3_formatPercent(wife3_getAccuracy())
    local grade = wife3_getGrade(wife3_getAccuracy())
    local score = wife3_getScore()
    
    setTextString('wife3Display', 'Wife3: ' .. score .. ' | ' .. acc .. '% (' .. grade .. ')')
end

function goodNoteHit(id, data, type, sustain)
    if not sustain then updateWife3() end
end

function noteMiss()
    updateWife3()
end

Available Functions Summary

This script provides the following 20 global callback functions:

Configuration:

  • wife3_setEnabled(enabled: Bool)
  • wife3_setJudgePreset(judgeNum: Int)
  • wife3_setJudgeScale(scale: Float)
  • wife3_resetAccuracy()
  • wife3_setReplaceScoreText(replace: Bool)
  • wife3_setShowTimingDisplay(show: Bool)

Data Getters:

  • wife3_getAccuracy(): Float
  • wife3_getScore(): Int
  • wife3_getGrade(percent: Float): String
  • wife3_getJudgeScale(): Float
  • wife3_getJudgePreset(): Float
  • wife3_getReplaceScoreText(): Bool
  • wife3_getShowTimingDisplay(): Bool

Judgement Counters:

  • wife3_getMarvelousHits(): Int
  • wife3_getPerfectHits(): Int
  • wife3_getGreatHits(): Int
  • wife3_getGoodHits(): Int
  • wife3_getBadHits(): Int

Utilities:

  • wife3_getTimingWindow(windowType: String): Float
  • wife3_formatPercent(value: Float): String
  • wife3_updateScoreText()

Clone this wiki locally