diff --git a/src/@types/sprite-types.ts b/src/@types/sprite-types.ts deleted file mode 100644 index de329268826..00000000000 --- a/src/@types/sprite-types.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Tuple type representing a set of RGB color values. - * Values should be in integer form (inside the interval `[0, 255]`). - */ -export type RGBArray = [r: number, g: number, b: number]; diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 59da590e9b0..289c9a8f051 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -299,11 +299,7 @@ export class BattleScene extends SceneBase { public seed: string; public waveSeed: string; public waveCycleOffset: number; - /** - * Whether to offset Gym Leader waves by 10 (30, 50, 70 instead of 20, 40, 60). - * Determined at the start of the run, and is unused for non-Classic game modes. - */ - public offsetGym = false; + public offsetGym: boolean; public damageNumberHandler: DamageNumberHandler; private spriteSparkleHandler: PokemonSpriteSparkleHandler; diff --git a/src/data/terrain.ts b/src/data/terrain.ts index 7c37c04e5c4..315ed919e03 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -4,7 +4,6 @@ import { PokemonType } from "#enums/pokemon-type"; import type { Pokemon } from "#field/pokemon"; import type { Move } from "#moves/move"; import { isFieldTargeted, isSpreadMove } from "#moves/move-utils"; -import type { RGBArray } from "#types/sprite-types"; import i18next from "i18next"; export enum TerrainType { @@ -94,7 +93,7 @@ export function getTerrainName(terrainType: TerrainType): string { return ""; } -export function getTerrainColor(terrainType: TerrainType): RGBArray { +export function getTerrainColor(terrainType: TerrainType): [number, number, number] { switch (terrainType) { case TerrainType.MISTY: return [232, 136, 200]; diff --git a/src/field/arena.ts b/src/field/arena.ts index f58f3e9ee7a..3e214ff1ea7 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -35,7 +35,6 @@ import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEven import type { Pokemon } from "#field/pokemon"; import { FieldEffectModifier } from "#modifiers/modifier"; import type { Move } from "#moves/move"; -import type { RGBArray } from "#types/sprite-types"; import type { AbstractConstructor } from "#types/type-helpers"; import { type Constructor, NumberHolder, randSeedInt } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; @@ -544,24 +543,22 @@ export class Arena { } } - public getTimeOfDay(): TimeOfDay { + getTimeOfDay(): TimeOfDay { switch (this.biomeType) { case BiomeId.ABYSS: return TimeOfDay.NIGHT; } - if (Overrides.TIME_OF_DAY_OVERRIDE !== null) { - return Overrides.TIME_OF_DAY_OVERRIDE; - } - - const waveCycle = ((globalScene.currentBattle?.waveIndex ?? 0) + globalScene.waveCycleOffset) % 40; + const waveCycle = ((globalScene.currentBattle?.waveIndex || 0) + globalScene.waveCycleOffset) % 40; if (waveCycle < 15) { return TimeOfDay.DAY; } + if (waveCycle < 20) { return TimeOfDay.DUSK; } + if (waveCycle < 35) { return TimeOfDay.NIGHT; } @@ -569,10 +566,6 @@ export class Arena { return TimeOfDay.DAWN; } - /** - * @returns Whether the current biome takes place "outdoors" - * (for the purposes of time of day tints) - */ isOutside(): boolean { switch (this.biomeType) { case BiomeId.SEABED: @@ -591,7 +584,23 @@ export class Arena { } } - getDayTint(): RGBArray { + overrideTint(): [number, number, number] { + switch (Overrides.ARENA_TINT_OVERRIDE) { + case TimeOfDay.DUSK: + return [98, 48, 73].map(c => Math.round((c + 128) / 2)) as [number, number, number]; + case TimeOfDay.NIGHT: + return [64, 64, 64]; + case TimeOfDay.DAWN: + case TimeOfDay.DAY: + default: + return [128, 128, 128]; + } + } + + getDayTint(): [number, number, number] { + if (Overrides.ARENA_TINT_OVERRIDE !== null) { + return this.overrideTint(); + } switch (this.biomeType) { case BiomeId.ABYSS: return [64, 64, 64]; @@ -600,15 +609,24 @@ export class Arena { } } - getDuskTint(): RGBArray { + getDuskTint(): [number, number, number] { + if (Overrides.ARENA_TINT_OVERRIDE) { + return this.overrideTint(); + } if (!this.isOutside()) { return [0, 0, 0]; } - return [113, 88, 101]; + switch (this.biomeType) { + default: + return [98, 48, 73].map(c => Math.round((c + 128) / 2)) as [number, number, number]; + } } - getNightTint(): RGBArray { + getNightTint(): [number, number, number] { + if (Overrides.ARENA_TINT_OVERRIDE) { + return this.overrideTint(); + } switch (this.biomeType) { case BiomeId.ABYSS: case BiomeId.SPACE: @@ -620,7 +638,10 @@ export class Arena { return [64, 64, 64]; } - return [48, 48, 98]; + switch (this.biomeType) { + default: + return [48, 48, 98]; + } } setIgnoreAbilities(ignoreAbilities: boolean, ignoringEffectSource: BattlerIndex | null = null): void { diff --git a/src/overrides.ts b/src/overrides.ts index dd84e6887a8..3f61196f0b4 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -76,13 +76,7 @@ class DefaultOverrides { readonly BATTLE_STYLE_OVERRIDE: BattleStyle | null = null; readonly STARTING_WAVE_OVERRIDE: number = 0; readonly STARTING_BIOME_OVERRIDE: BiomeId | null = null; - /** - * Overrides the Time of Day for the given biome. - * Set to `null` to disable. - * @remarks - * Will also influence field sprite tint coloration. - */ - readonly TIME_OF_DAY_OVERRIDE: Exclude | null = null; + readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null; /** Multiplies XP gained by this value including 0. Set to null to ignore the override. */ readonly XP_MULTIPLIER_OVERRIDE: number | null = null; /** diff --git a/src/pipelines/field-sprite.ts b/src/pipelines/field-sprite.ts index 04b1e4c0f0d..9132fd585ec 100644 --- a/src/pipelines/field-sprite.ts +++ b/src/pipelines/field-sprite.ts @@ -1,8 +1,5 @@ import { globalScene } from "#app/global-scene"; -import Overrides from "#app/overrides"; -import { getTerrainColor } from "#data/terrain"; -import { TimeOfDay } from "#enums/time-of-day"; -import type { RGBArray } from "#types/sprite-types"; +import { getTerrainColor, TerrainType } from "#data/terrain"; import { getCurrentTime } from "#utils/common"; import Phaser from "phaser"; import fieldSpriteFragShader from "./glsl/field-sprite-frag-shader.frag?raw"; @@ -33,17 +30,15 @@ export class FieldSpritePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPi const sprite = gameObject as Phaser.GameObjects.Sprite | Phaser.GameObjects.NineSlice; const data = sprite.pipelineData; - const ignoreTimeTint = !!data["ignoreTimeTint"]; - const terrainColorRatio = (data["terrainColorRatio"] as number) ?? 0; + const ignoreTimeTint = data["ignoreTimeTint"] as boolean; + const terrainColorRatio = (data["terrainColorRatio"] as number) || 0; const time = globalScene.currentBattle?.waveIndex ? ((globalScene.currentBattle.waveIndex + globalScene.waveCycleOffset) % 40) / 40 // ((new Date().getSeconds() * 1000 + new Date().getMilliseconds()) % 10000) / 10000 : getCurrentTime(); - this.set1f("time", time); - this.setBoolean("ignoreTimeTint", ignoreTimeTint); - this.setBoolean("isOutside", globalScene.arena.isOutside()); - this.set3fv("overrideTint", overrideTint()); + this.set1i("ignoreTimeTint", ignoreTimeTint ? 1 : 0); + this.set1i("isOutside", globalScene.arena.isOutside() ? 1 : 0); this.set3fv( "dayTint", globalScene.arena.getDayTint().map(c => c / 255), @@ -58,7 +53,7 @@ export class FieldSpritePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPi ); this.set3fv( "terrainColor", - getTerrainColor(globalScene.arena.getTerrainType()).map(c => c / 255), + getTerrainColor(globalScene.arena.terrain?.terrainType || TerrainType.NONE).map(c => c / 255), ); this.set1f("terrainColorRatio", terrainColorRatio); } @@ -69,21 +64,3 @@ export class FieldSpritePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPi } } } - -/** - * Override the current arena tint based on the Time of day override - * @returns The overriden tint colors as an RGB array. - */ -function overrideTint(): RGBArray { - switch (Overrides.TIME_OF_DAY_OVERRIDE) { - case TimeOfDay.DAY: - case TimeOfDay.DAWN: - return globalScene.arena.getDayTint(); - case TimeOfDay.DUSK: - return globalScene.arena.getDuskTint(); - case TimeOfDay.NIGHT: - return globalScene.arena.getNightTint(); - default: - return [0, 0, 0]; - } -} diff --git a/src/pipelines/glsl/field-sprite-frag-shader.frag b/src/pipelines/glsl/field-sprite-frag-shader.frag index 6bb82f55531..f11f6308808 100644 --- a/src/pipelines/glsl/field-sprite-frag-shader.frag +++ b/src/pipelines/glsl/field-sprite-frag-shader.frag @@ -20,9 +20,8 @@ varying float outTintEffect; varying vec4 outTint; uniform float time; -uniform bool ignoreTimeTint; -uniform bool isOutside; -uniform vec3 overrideTint; +uniform int ignoreTimeTint; +uniform int isOutside; uniform vec3 dayTint; uniform vec3 duskTint; uniform vec3 nightTint; @@ -143,12 +142,10 @@ void main() { } /* Apply day/night tint */ - if (color.a > 0.0 && ignoreTimeTint) { + if (color.a > 0.0 && ignoreTimeTint == 0) { vec3 dayNightTint; - if (any(lessThan(vec3(0.0), overrideTint))) { - dayNightTint = overrideTint; - } else if (time < 0.25) { + if (time < 0.25) { dayNightTint = dayTint; } else if (isOutside == 0 && time < 0.5) { dayNightTint = mix(dayTint, nightTint, (time - 0.25) / 0.25); @@ -169,13 +166,10 @@ void main() { color = vec4(blendHardLight(color.rgb, dayNightTint), color.a); } - if ( - terrainColorRatio > 0.0 - && (1.0 - terrainColorRatio) < outTexCoord.y - && color.a > 0.0 - && (any(lessThan(vec3(0.0), terrainColor))) - ) { - color.rgb = mix(color.rgb, blendHue(color.rgb, terrainColor), 1.0); + if (terrainColorRatio > 0.0 && (1.0 - terrainColorRatio) < outTexCoord.y) { + if (color.a > 0.0 && (terrainColor.r > 0.0 || terrainColor.g > 0.0 || terrainColor.b > 0.0)) { + color.rgb = mix(color.rgb, blendHue(color.rgb, terrainColor), 1.0); + } } gl_FragColor = color; diff --git a/src/pipelines/glsl/sprite-frag-shader.frag b/src/pipelines/glsl/sprite-frag-shader.frag index 880ea5d7bb3..e2c7f0d0e84 100644 --- a/src/pipelines/glsl/sprite-frag-shader.frag +++ b/src/pipelines/glsl/sprite-frag-shader.frag @@ -21,15 +21,14 @@ varying float outTintEffect; varying vec4 outTint; uniform float time; -uniform bool ignoreTimeTint; -uniform bool isOutside; -uniform vec3 overrideTint; +uniform int ignoreTimeTint; +uniform int isOutside; uniform vec3 dayTint; uniform vec3 duskTint; uniform vec3 nightTint; uniform float teraTime; uniform vec3 teraColor; -uniform bool hasShadow; +uniform int hasShadow; uniform int yCenter; uniform float fieldScale; uniform float vCutoff; @@ -188,7 +187,7 @@ void main() { // Multiply texture tint vec4 color = texture * texel; - if (color.a > 0.0 && all(lessThan(vec3(0.0), teraColor))) { + if (color.a > 0.0 && teraColor.r > 0.0 && teraColor.g > 0.0 && teraColor.b > 0.0) { vec2 relUv = (outTexCoord.xy - texFrameUv.xy) / (size.xy / texSize.xy); vec2 teraTexCoord = vec2(relUv.x * (size.x / 200.0), relUv.y * (size.y / 120.0)); vec4 teraCol = texture2D(uMainSampler[1], teraTexCoord); @@ -222,12 +221,10 @@ void main() { color.rgb += tone.rgb * (color.a / 255.0); /* Apply day/night tint */ - if (color.a > 0.0 && !ignoreTimeTint) { + if (color.a > 0.0 && ignoreTimeTint == 0) { vec3 dayNightTint; - if (any(lessThan(overrideTint, vec3(0.0)))) { - dayNightTint = overrideTint; - } else if (time < 0.25) { + if (time < 0.25) { dayNightTint = dayTint; } else if (isOutside == 0 && time < 0.5) { dayNightTint = mix(dayTint, nightTint, (time - 0.25) / 0.25); @@ -248,7 +245,7 @@ void main() { color.rgb = blendHardLight(color.rgb, dayNightTint); } - if (hasShadow) { + if (hasShadow == 1) { float width = size.x - (yOffset / 2.0); float spriteX = ((floor(outPosition.x / fieldScale) - relPosition.x) / width) + 0.5; diff --git a/src/pipelines/sprite.ts b/src/pipelines/sprite.ts index ca7d234c0f9..65f8007e2f8 100644 --- a/src/pipelines/sprite.ts +++ b/src/pipelines/sprite.ts @@ -27,7 +27,7 @@ export class SpritePipeline extends FieldSpritePipeline { this.set1f("teraTime", 0); this.set3fv("teraColor", [0, 0, 0]); - this.setBoolean("hasShadow", false); + this.set1i("hasShadow", 0); this.set1i("yCenter", 0); this.set2f("relPosition", 0, 0); this.set2f("texFrameUv", 0, 0); @@ -73,7 +73,7 @@ export class SpritePipeline extends FieldSpritePipeline { "teraColor", teraColor.map(c => c / 255), ); - this.setBoolean("hasShadow", hasShadow); + this.set1i("hasShadow", hasShadow ? 1 : 0); this.set1i("yCenter", sprite.originY === 0.5 ? 1 : 0); this.set1f("fieldScale", field?.scale || 1); this.set2f("relPosition", position[0], position[1]);