mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-28 14:20:46 -05:00
Improve special/splatted parsing
This commit is contained in:
@@ -257,12 +257,17 @@ sequenceDiagram
|
||||
badge-less frame scores the geometries on how decisively the bodies
|
||||
read and sticks with the established layout unless another wins
|
||||
clearly, or unless the slot comb — which is positional, so it sees a
|
||||
pitch the body reads cannot — puts narrow-right decisively ahead of a
|
||||
latched `even`, as happens when a spectator toggles between the
|
||||
overhead map and a player POV mid-match — the special-ready wash also pulses, so its dim trough is told
|
||||
pitch the body reads cannot — decisively picks a geometry (even needs
|
||||
the widest win) or puts narrow-right decisively ahead of a latched
|
||||
`even`, as happens when a spectator toggles between the overhead map and
|
||||
a player POV mid-match, and in S3 POV itself, which resizes each side's
|
||||
icons as the objective swings and so cycles through all three
|
||||
geometries within one game — the special-ready wash also pulses, so its dim trough is told
|
||||
apart from a splat by its team tint: a splat is a neutral grey plate under
|
||||
a grey X, which a blown-out backdrop turns near-white while a wash stays
|
||||
tinted at every pulse phase, and a ready read
|
||||
tinted at every pulse phase (a big dark weapon render such as the
|
||||
Nautilus drum dilutes that tint, but a diluted wash still reads pale,
|
||||
which a tinted splat never does), and a ready read
|
||||
must also see a washed (ink-poor) body: pale backdrop, a ship's hull or
|
||||
the lead banner leaking past an icon edge fakes the shoulder glow, and a ready the shoulder glow does
|
||||
not corroborate needs the body's ink gone rather than merely paled,
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
* splatted = neutral grey plate under a grey X, ink-poor and untinted whatever
|
||||
* the backdrop brightness. Three geometries, named by which
|
||||
* side sits at the packed pitch: "even", "narrow-right" (usual spectator HUD;
|
||||
* S3 POV draws it too) and "narrow-left" (right column nearly coincides with
|
||||
* even's). Camera badges prove a broadcast, but broadcasts can hide them, so a
|
||||
* badge-less frame picks the geometry reading more decisively, with a slot-comb
|
||||
* win proving narrow-left or unseating a latched even, and a history-less
|
||||
* S3 POV draws all three, resizing each side as the objective swings) and
|
||||
* "narrow-left" (right column nearly coincides with even's). Camera badges
|
||||
* prove a broadcast, but broadcasts can hide them, so a badge-less frame picks
|
||||
* the geometry reading more decisively, with a decisive slot-comb win proving
|
||||
* any geometry outright or unseating a latched even, and a history-less
|
||||
* near-tie staying narrow-right (pickLayout). Only the unsaturated glow counts
|
||||
* toward ready — saturated backdrop leaks and bright team ink alike must not
|
||||
* fake a state — and a ready read the shoulder does not corroborate needs a
|
||||
@@ -32,8 +33,13 @@ import {
|
||||
STATUS_COMB_GAP_HALF_WIDTH,
|
||||
STATUS_COMB_MAX_SHIFT,
|
||||
STATUS_COMB_SIDE_SPANS,
|
||||
STATUS_DARK_MAX_VALUE,
|
||||
STATUS_DEAD_MAX_BODY_INK,
|
||||
STATUS_DEAD_MAX_SHOULDER_GLOW,
|
||||
STATUS_DECISIVE_COMB_LEAD,
|
||||
STATUS_DECISIVE_COMB_MIN,
|
||||
STATUS_DECISIVE_EVEN_COMB_LEAD,
|
||||
STATUS_DECISIVE_EVEN_COMB_MIN,
|
||||
STATUS_DPAD_PROBES_EVEN,
|
||||
STATUS_DPAD_PROBES_NARROW_LEFT,
|
||||
STATUS_DPAD_PROBES_NARROW_RIGHT,
|
||||
@@ -45,12 +51,12 @@ import {
|
||||
STATUS_FRESH_NARROW_RIGHT_MIN_DECISIVENESS,
|
||||
STATUS_GLOW_MAX_SPREAD,
|
||||
STATUS_GLOW_MIN_VALUE,
|
||||
STATUS_GREY_MAX_VALUE,
|
||||
STATUS_GREY_MIN_VALUE,
|
||||
STATUS_INK_MIN_SPREAD,
|
||||
STATUS_INK_MIN_VALUE,
|
||||
STATUS_LAYOUT_SCORE_CAP,
|
||||
STATUS_LAYOUT_STICKY_MARGIN,
|
||||
STATUS_NARROW_LEFT_COMB_LEAD,
|
||||
STATUS_NARROW_LEFT_COMB_MIN,
|
||||
STATUS_PALE_MAX_SPREAD,
|
||||
STATUS_PALE_MIN_VALUE,
|
||||
STATUS_READY_CLEAN_WASH_MAX_BODY_INK,
|
||||
@@ -68,6 +74,9 @@ import {
|
||||
STATUS_STICKY_FLIP_COMB_MIN,
|
||||
STATUS_TINT_MIN_SPREAD,
|
||||
STATUS_TINT_MIN_VALUE,
|
||||
STATUS_UNCROSSED_WASH_MAX_BODY_DARK,
|
||||
STATUS_UNCROSSED_WASH_MAX_BODY_GREY,
|
||||
STATUS_UNCROSSED_WASH_MIN_BODY_TINT,
|
||||
STATUS_WASH_MIN_BODY_TINT,
|
||||
STATUS_WHITE_MAX_SPREAD,
|
||||
STATUS_WHITE_MIN_VALUE,
|
||||
@@ -77,7 +86,7 @@ export const PLAYER_STATUS_EVENT_TYPE = "PlayerStatus";
|
||||
|
||||
/**
|
||||
* classFractions' per-pixel classes by (max, min) channel: bit 0 ink, 1 glow,
|
||||
* 2 pale glow, 3 pale, 4 tint.
|
||||
* 2 pale glow, 3 pale, 4 tint, 5 grey, 6 dark.
|
||||
*/
|
||||
const PIXEL_CLASSES = (() => {
|
||||
const classes = new Uint8Array(1 << 16);
|
||||
@@ -99,6 +108,13 @@ const PIXEL_CLASSES = (() => {
|
||||
spread < STATUS_INK_MIN_SPREAD
|
||||
)
|
||||
flags |= 16;
|
||||
if (
|
||||
value >= STATUS_GREY_MIN_VALUE &&
|
||||
value <= STATUS_GREY_MAX_VALUE &&
|
||||
spread <= STATUS_TINT_MIN_SPREAD
|
||||
)
|
||||
flags |= 32;
|
||||
if (value <= STATUS_DARK_MAX_VALUE) flags |= 64;
|
||||
classes[(value << 8) | low] = flags;
|
||||
}
|
||||
}
|
||||
@@ -151,6 +167,8 @@ interface SlotRead {
|
||||
bodyInk: number;
|
||||
bodyPale: number;
|
||||
bodyTint: number;
|
||||
bodyGrey: number;
|
||||
bodyDark: number;
|
||||
shoulderGlow: number;
|
||||
shoulderPaleGlow: number;
|
||||
}
|
||||
@@ -200,6 +218,8 @@ export function parsePlayerStatus(
|
||||
bodyInk: reads.map((read) => Number(read.bodyInk.toFixed(2))),
|
||||
bodyPale: reads.map((read) => Number(read.bodyPale.toFixed(2))),
|
||||
bodyTint: reads.map((read) => Number(read.bodyTint.toFixed(2))),
|
||||
bodyGrey: reads.map((read) => Number(read.bodyGrey.toFixed(2))),
|
||||
bodyDark: reads.map((read) => Number(read.bodyDark.toFixed(2))),
|
||||
shoulderGlow: reads.map((read) => Number(read.shoulderGlow.toFixed(2))),
|
||||
shoulderPaleGlow: reads.map((read) =>
|
||||
Number(read.shoulderPaleGlow.toFixed(2)),
|
||||
@@ -241,6 +261,8 @@ function readSlots(
|
||||
body.ink,
|
||||
body.pale,
|
||||
body.tint,
|
||||
body.grey,
|
||||
body.dark,
|
||||
shoulder.glow,
|
||||
shoulder.paleGlow,
|
||||
layout,
|
||||
@@ -279,8 +301,10 @@ const SCORED_FLIPS: Record<PlayerStatusLayout, readonly PlayerStatusLayout[]> =
|
||||
* SCORED_FLIPS keeps the even/narrow-left false friends from trading places.
|
||||
* Four decisions decisiveness cannot make alone:
|
||||
* - badge-less narrow-left (sendou-triton VoD) scores below narrow-right even
|
||||
* when true, so a decisive slot-comb win (combContrast) overrides all but
|
||||
* badges — positional, so only the differing left columns can lead;
|
||||
* when true, and S3 POV swaps geometries as the objective swings (Triton cup
|
||||
* VoD) while SCORED_FLIPS and the sticky margin hold the old one,
|
||||
* so a decisive slot-comb win (combContrast, STATUS_DECISIVE_*COMB_*)
|
||||
* overrides all but badges, fresh or sticky;
|
||||
* - a spectator toggling between the overhead map and a player POV swaps even
|
||||
* for narrow-right mid-match, and even's columns sit between the narrow ones,
|
||||
* so the two score within 0.001 of each other and the wrong pick sticks for a
|
||||
@@ -325,14 +349,8 @@ function pickLayout(
|
||||
sideCombs[layout][0] + sideCombs[layout][1],
|
||||
]),
|
||||
) as Record<PlayerStatusLayout, number>;
|
||||
if (
|
||||
combs["narrow-left"] >= STATUS_NARROW_LEFT_COMB_MIN &&
|
||||
combs["narrow-left"] >=
|
||||
combs["narrow-right"] + STATUS_NARROW_LEFT_COMB_LEAD &&
|
||||
combs["narrow-left"] >= combs.even + STATUS_NARROW_LEFT_COMB_LEAD
|
||||
) {
|
||||
return { layout: "narrow-left", scores };
|
||||
}
|
||||
const combWinner = decisiveCombWinner(combs);
|
||||
if (combWinner) return { layout: combWinner, scores };
|
||||
const combFlipsEven =
|
||||
combs["narrow-right"] >= STATUS_EVEN_FLIP_COMB_MIN &&
|
||||
combs["narrow-right"] >= combs.even + STATUS_EVEN_FLIP_COMB_LEAD;
|
||||
@@ -344,8 +362,7 @@ function pickLayout(
|
||||
(layout) =>
|
||||
prevLayout !== "narrow-right" ||
|
||||
(combs[layout] >= STATUS_STICKY_FLIP_COMB_MIN &&
|
||||
combs[layout] >=
|
||||
combs["narrow-right"] + STATUS_NARROW_LEFT_COMB_LEAD),
|
||||
combs[layout] >= combs["narrow-right"] + STATUS_DECISIVE_COMB_LEAD),
|
||||
);
|
||||
const challenger =
|
||||
challengers.length > 0
|
||||
@@ -388,6 +405,26 @@ function pickLayout(
|
||||
};
|
||||
}
|
||||
|
||||
function decisiveCombWinner(
|
||||
combs: Record<PlayerStatusLayout, number>,
|
||||
): PlayerStatusLayout | null {
|
||||
for (const layout of ALL_LAYOUTS) {
|
||||
const [min, lead] =
|
||||
layout === "even"
|
||||
? [STATUS_DECISIVE_EVEN_COMB_MIN, STATUS_DECISIVE_EVEN_COMB_LEAD]
|
||||
: [STATUS_DECISIVE_COMB_MIN, STATUS_DECISIVE_COMB_LEAD];
|
||||
if (
|
||||
combs[layout] >= min &&
|
||||
ALL_LAYOUTS.every(
|
||||
(rival) => rival === layout || combs[layout] >= combs[rival] + lead,
|
||||
)
|
||||
) {
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function sideDecisiveness(reads: SlotRead[]): number {
|
||||
return (
|
||||
reads.reduce(
|
||||
@@ -408,7 +445,9 @@ function sideDecisiveness(reads: SlotRead[]): number {
|
||||
* splat or a wash, and its tint tells them apart: the wash is a pale team tint
|
||||
* at every pulse phase while the splat is neutral grey — even when a blown-out
|
||||
* backdrop turns the plate near-white, or the trough dims the wash under both
|
||||
* ready floors. Only unsaturated glow counts as the wash's
|
||||
* ready floors. Where a big dark weapon render dilutes the wash's tint as low
|
||||
* as a splat over a bright tinted backdrop reads, the splat's grey X strokes
|
||||
* still tell them apart. Only unsaturated glow counts as the wash's
|
||||
* (STATUS_GLOW_MAX_SPREAD): bright team ink lights the shoulder on its own
|
||||
* once the ink is light enough (orange clears the glow floor, lime does not).
|
||||
* The wash also replaces the body's ink, so an ink-heavy body means backdrop
|
||||
@@ -423,6 +462,8 @@ function classifySlot(
|
||||
bodyInk: number,
|
||||
bodyPale: number,
|
||||
bodyTint: number,
|
||||
bodyGrey: number,
|
||||
bodyDark: number,
|
||||
shoulderGlow: number,
|
||||
shoulderPaleGlow: number,
|
||||
layout: PlayerStatusLayout,
|
||||
@@ -430,7 +471,11 @@ function classifySlot(
|
||||
// the wash glows pale on every layout; raw brightness is team ink or backdrop
|
||||
const washGlow = shoulderPaleGlow;
|
||||
const inkPoor = bodyInk <= STATUS_DEAD_MAX_BODY_INK;
|
||||
const tinted = bodyTint >= STATUS_WASH_MIN_BODY_TINT;
|
||||
const tinted =
|
||||
bodyTint >= STATUS_WASH_MIN_BODY_TINT ||
|
||||
(bodyTint >= STATUS_UNCROSSED_WASH_MIN_BODY_TINT &&
|
||||
bodyGrey <= STATUS_UNCROSSED_WASH_MAX_BODY_GREY &&
|
||||
bodyDark <= STATUS_UNCROSSED_WASH_MAX_BODY_DARK);
|
||||
const dead =
|
||||
inkPoor &&
|
||||
!tinted &&
|
||||
@@ -470,16 +515,26 @@ function classifySlot(
|
||||
bodyInk,
|
||||
bodyPale,
|
||||
bodyTint,
|
||||
bodyGrey,
|
||||
bodyDark,
|
||||
shoulderGlow,
|
||||
shoulderPaleGlow,
|
||||
};
|
||||
}
|
||||
|
||||
/** Ink, glow, pale, and tint pixel fractions of a ROI (see rois.ts for the classes). */
|
||||
/** Ink, glow, pale, tint, grey, and dark pixel fractions of a ROI (see rois.ts for the classes). */
|
||||
function classFractions(
|
||||
frame: Mat,
|
||||
roi: Roi,
|
||||
): { ink: number; glow: number; paleGlow: number; pale: number; tint: number } {
|
||||
): {
|
||||
ink: number;
|
||||
glow: number;
|
||||
paleGlow: number;
|
||||
pale: number;
|
||||
tint: number;
|
||||
grey: number;
|
||||
dark: number;
|
||||
} {
|
||||
const cols = frame.cols;
|
||||
const inside =
|
||||
roi.x >= 0 &&
|
||||
@@ -501,6 +556,8 @@ function classFractions(
|
||||
let paleGlow = 0;
|
||||
let pale = 0;
|
||||
let tint = 0;
|
||||
let grey = 0;
|
||||
let dark = 0;
|
||||
for (let y = 0; y < roi.h; y++) {
|
||||
const rowStart = start + y * rowStride;
|
||||
const rowEnd = rowStart + roi.w * channels;
|
||||
@@ -515,7 +572,9 @@ function classFractions(
|
||||
glow += (flags >> 1) & 1;
|
||||
paleGlow += (flags >> 2) & 1;
|
||||
pale += (flags >> 3) & 1;
|
||||
tint += flags >> 4;
|
||||
tint += (flags >> 4) & 1;
|
||||
grey += (flags >> 5) & 1;
|
||||
dark += flags >> 6;
|
||||
}
|
||||
}
|
||||
crop?.delete();
|
||||
@@ -526,6 +585,8 @@ function classFractions(
|
||||
paleGlow: paleGlow / count,
|
||||
pale: pale / count,
|
||||
tint: tint / count,
|
||||
grey: grey / count,
|
||||
dark: dark / count,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -533,7 +594,7 @@ function classFractions(
|
||||
* Slot-comb contrast per layout and side: mean iconness (ink-or-pale column
|
||||
* fraction) at slot centers minus at gap midpoints, maximized over a small
|
||||
* shift. A rigid comb at the wrong pitch cannot score all four slots at once:
|
||||
* positional evidence orthogonal to body decisiveness (STATUS_NARROW_LEFT_COMB_*).
|
||||
* positional evidence orthogonal to body decisiveness (STATUS_DECISIVE_*COMB_*).
|
||||
*/
|
||||
function combScores(frame: Mat): Record<PlayerStatusLayout, [number, number]> {
|
||||
const profiles = STATUS_COMB_SIDE_SPANS.map(([x0, x1]) =>
|
||||
|
||||
@@ -215,12 +215,38 @@ export const STATUS_DEAD_MAX_SHOULDER_GLOW = 0.2;
|
||||
/**
|
||||
* Wash body: tinted past this on an ink-poor body means the special-ready
|
||||
* wash at any pulse phase (bright frames and the dim trough alike), under it
|
||||
* a splat. Splats read <=0.19 (SWS26 splat on a blown-out white sky: 0.07 at
|
||||
* a splat. Splats read <=0.25 (SWS26 splat on a blown-out white sky: 0.07 at
|
||||
* pale 0.80), ink-poor washes >=0.45 (SWS26 even-layout trough: 0.57 at pale
|
||||
* 0.13, shoulder glow 0.20 — under both ready floors).
|
||||
*/
|
||||
export const STATUS_WASH_MIN_BODY_TINT = 0.3;
|
||||
|
||||
/**
|
||||
* Grey pixel: neutral (the tint class's complement) at mid brightness — the
|
||||
* splat's X strokes, which cross the whole body box on every splat whatever
|
||||
* the backdrop does to the translucent plate under them.
|
||||
*/
|
||||
export const STATUS_GREY_MIN_VALUE = 90;
|
||||
export const STATUS_GREY_MAX_VALUE = 200;
|
||||
|
||||
/** Dark pixel: the unlit plate of a splatted or vacant slot. */
|
||||
export const STATUS_DARK_MAX_VALUE = 70;
|
||||
|
||||
/**
|
||||
* ...or tinted past a lower floor on a body no X crosses: a large dark weapon
|
||||
* render (Nautilus drum) fills the body box and dilutes the wash to 0.2-0.3
|
||||
* tint (Triton cup VoD, S3 POV), where splats over a bright tinted backdrop
|
||||
* land too (sky and sunlit walls through the translucent plate). The X strokes
|
||||
* split them: splats in that band read grey >=0.17 (median ~0.35), the
|
||||
* drum-diluted washes <=0.10. Grey renders (Painbrush) put other washes at
|
||||
* 0.15-0.25, left to the main floor. The dark cap keeps out the unlit black
|
||||
* squid a slot shows without any X (InTheZone VoD: dark >=0.57, drum-diluted
|
||||
* washes 0.20-0.35).
|
||||
*/
|
||||
export const STATUS_UNCROSSED_WASH_MIN_BODY_TINT = 0.2;
|
||||
export const STATUS_UNCROSSED_WASH_MAX_BODY_GREY = 0.15;
|
||||
export const STATUS_UNCROSSED_WASH_MAX_BODY_DARK = 0.45;
|
||||
|
||||
/** Special ready: shoulder glow past this (attested >=0.40 vs <=0.06). */
|
||||
export const STATUS_READY_MIN_SHOULDER_GLOW = 0.25;
|
||||
|
||||
@@ -310,8 +336,17 @@ export const STATUS_FRESH_NARROW_LEFT_RIVAL_COMB_VETO = 0.3;
|
||||
/**
|
||||
* Slot-comb contrast (combContrast): a rigid comb exposes the pitch — badge-less
|
||||
* narrow-left scores 0.81 while narrow-right reads it at -0.07 (sendou-triton
|
||||
* MakoMart), so a decisive win proves narrow-left despite the shared right
|
||||
* column. Both gates needed: worst false narrow-left comb is 0.44 with a 0.24 lead.
|
||||
* MakoMart), so a decisive win (past the floor AND leading both rivals) proves
|
||||
* that geometry whatever came before. Both gates needed: worst false narrow-left
|
||||
* comb is 0.44 with a 0.24 lead. S3 POV resizes each side's icons as the
|
||||
* objective swings (there, a side both holding the zone and leading drew
|
||||
* large), so one Splat Zones game cycles through all three geometries and some
|
||||
* in-between pitches (Triton cup VoD, Brinewater Springs: a dozen switches),
|
||||
* which only the comb follows. Even needs the stronger win: its columns sit between the narrow ones, so the
|
||||
* comb's ±10px shift lets it half-fit either, and the AREA CUP overhead view
|
||||
* (left column ~12px off narrow-right) combs even 0.77 with a 0.30 lead. Clean
|
||||
* even frames in that Triton game comb 0.98 with a 0.40 lead at the median,
|
||||
* and three in four clear both floors — enough, as the pick is sticky.
|
||||
*/
|
||||
export const STATUS_COMB_BAND_Y = 35;
|
||||
export const STATUS_COMB_BAND_H = 61;
|
||||
@@ -325,12 +360,14 @@ export const STATUS_COMB_SIDE_SPANS: readonly [
|
||||
export const STATUS_COMB_CENTER_HALF_WIDTH = 16;
|
||||
export const STATUS_COMB_GAP_HALF_WIDTH = 7;
|
||||
export const STATUS_COMB_MAX_SHIFT = 10;
|
||||
export const STATUS_NARROW_LEFT_COMB_MIN = 0.5;
|
||||
export const STATUS_NARROW_LEFT_COMB_LEAD = 0.25;
|
||||
export const STATUS_DECISIVE_COMB_MIN = 0.5;
|
||||
export const STATUS_DECISIVE_COMB_LEAD = 0.25;
|
||||
export const STATUS_DECISIVE_EVEN_COMB_MIN = 0.8;
|
||||
export const STATUS_DECISIVE_EVEN_COMB_LEAD = 0.35;
|
||||
|
||||
/**
|
||||
* Sticky flips away from narrow-right need comb corroboration (past this floor
|
||||
* AND leading by STATUS_NARROW_LEFT_COMB_LEAD): while the S3 POV player is dead
|
||||
* AND leading by STATUS_DECISIVE_COMB_LEAD): while the S3 POV player is dead
|
||||
* the strip shrinks ~0.77 toward the timer, landing near narrow-left pitches
|
||||
* (2026-08-11 Um'ami VoD locked 107 of 136 reads that way). True narrow-left
|
||||
* combs 0.41-0.81 with >=0.31 lead; worst POV false comb 0.20, negative lead.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"event": "PlayerStatus",
|
||||
"data": {
|
||||
"layout": "even",
|
||||
"cast": null,
|
||||
"time": 257,
|
||||
"special": [
|
||||
[false, false, false, true],
|
||||
[true, false, false, false]
|
||||
],
|
||||
"dead": [
|
||||
[false, false, false, false],
|
||||
[false, false, false, false]
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"notes": "Triton cup VoD (v2811381928, 720p S3 POV), Brinewater Springs SZ at 4:17, t=6087.3. S3 POV resizes each side's icons as the objective swings, and this game cycles through even, narrow-left, narrow-right and back a dozen times. Here both sides sit at the even pitch (apexes ~[570,659,748,833 | 1087,1175,1263,1351]) but decisiveness is a near-tie (even 0.257 vs narrow-right 0.246, under the 0.025 lead a fresh even pick needs), so the fresh pick stayed narrow-right, and a live scan kept whatever geometry it had latched: the Nautilus wash on right slot 0 then read as a splat under narrow-right's probes. The comb sees the pitch (even 1.07 vs 0.62/0.62), so a decisive comb win now picks even outright, fresh or sticky (STATUS_DECISIVE_EVEN_COMB_*)."
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"event": "PlayerStatus",
|
||||
"data": {
|
||||
"layout": "narrow-right",
|
||||
"cast": null,
|
||||
"time": 266,
|
||||
"special": [
|
||||
[false, false, false, true],
|
||||
[true, false, false, false]
|
||||
],
|
||||
"dead": [
|
||||
[false, false, true, false],
|
||||
[false, false, false, false]
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"notes": "Triton cup VoD (v2811381928, 720p S3 POV), Brinewater Springs SZ at 4:26, t=6078.3. Same Nautilus wash as pov-brinewater-nautilus-wash-read-as-splat, this time at the narrow-right pitch (left apexes ~[543,641,737,829], right ~[1087,1162,1238,1313]) and diluted further by the drum: tint 0.26 at pale 0.15, read as a splat. Left slot 2 is a real splat on a dark backdrop (tint 0.07, pale 0.03) that must stay one, and left slot 3 holds a wash."
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1016 KiB |
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"event": "PlayerStatus",
|
||||
"data": {
|
||||
"layout": "narrow-left",
|
||||
"cast": null,
|
||||
"time": 247,
|
||||
"special": [
|
||||
[false, true, false, true],
|
||||
[true, false, false, false]
|
||||
],
|
||||
"dead": [
|
||||
[false, false, false, false],
|
||||
[false, false, false, true]
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"notes": "Triton cup VoD (v2811381928, 720p S3 POV), Brinewater Springs SZ at 4:07, t=6097.3. Right slot 0 holds a Nautilus whose special-ready wash is plainly visible (pale lilac icon) but whose big dark drum render fills most of the body box: the body reads ink-poor (0.00) with the wash diluted to tint 0.28, just under the 0.30 wash floor, so the slot read as a splat. Over the game the slot alternated ★/✕ every second while ready (pulse phases landing either side of the floor). It still reads pale 0.16, which a tinted splat never does (tinted splats read pale <=0.01), hence STATUS_PALE_WASH_*. Right slot 3 is a real splat, left slots 1 and 3 hold washes. The strip is at the narrow-left pitch here (left apexes ~[608,683,758,834], right ~[1087,1183,1280,1377])."
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Reference in New Issue
Block a user