Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["web", "docs"]
"privatePackages": false
}
7 changes: 4 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ These rules ensure maintainability, safety, and developer velocity.
### 5 - Changesets (Package Publishing)

- **CS-1 (MUST)** When modifying files in `packages/ui/`, you MUST create a changeset
- **CS-2** Run `pnpm changeset` and follow the interactive prompts:
- **CS-2 (MUST NOT)** Never create changesets for any other package. `@tableslayer/ui` is the only published package; everything else (`stage`, `web`, `docs`, configs) is private/internal and excluded via `privatePackages: false` in `.changeset/config.json`
- **CS-3** Run `pnpm changeset` and follow the interactive prompts:
- Select `@tableslayer/ui` as the changed package
- Choose bump type: `patch` (bug fixes), `minor` (new features), `major` (breaking changes)
- Write a brief description of the change
- **CS-3** Commit the generated `.changeset/*.md` file with your changes
- **CS-4** The CI will fail if UI files change without a changeset
- **CS-4** Commit the generated `.changeset/*.md` file with your changes
- **CS-5** The CI will fail if UI files change without a version bump (run `pnpm release` before merging)

### 6 - Important File References

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
{ text: 'Ice', value: AnnotationEffect.Ice },
{ text: 'Magic', value: AnnotationEffect.Magic },
{ text: 'Grease', value: AnnotationEffect.Grease },
{ text: 'Space Tear', value: AnnotationEffect.SpaceTear }
{ text: 'Space Tear', value: AnnotationEffect.SpaceTear },
{ text: 'Web', value: AnnotationEffect.Web },
{ text: 'Entangle', value: AnnotationEffect.Entangle }
];

function getLayerEffectType(layer: AnnotationLayerData): AnnotationEffect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
RainPreset,
LeavesPreset,
AshPreset,
DustStormPreset,
EmbersPreset,
BlizzardPreset,
FirefliesPreset,
type StageProps
} from '@tableslayer/stage';
import { KernelSize } from 'postprocessing';
Expand All @@ -19,11 +23,16 @@
Snow: WeatherType.Snow,
Leaves: WeatherType.Leaves,
Ash: WeatherType.Ash,
'Dust storm': WeatherType.DustStorm,
Embers: WeatherType.Embers,
Blizzard: WeatherType.Blizzard,
Fireflies: WeatherType.Fireflies,
Custom: WeatherType.Custom
};

const particleTypeOptions: ListOptions<number> = {
Ash: ParticleType.Ash,
Fireflies: ParticleType.Fireflies,
Leaves: ParticleType.Leaves,
Rain: ParticleType.Rain,
Snow: ParticleType.Snow
Expand Down Expand Up @@ -51,6 +60,18 @@
case WeatherType.Ash:
preset = { ...AshPreset };
break;
case WeatherType.DustStorm:
preset = { ...DustStormPreset };
break;
case WeatherType.Embers:
preset = { ...EmbersPreset };
break;
case WeatherType.Blizzard:
preset = { ...BlizzardPreset };
break;
case WeatherType.Fireflies:
preset = { ...FirefliesPreset };
break;
default:
preset = { ...RainPreset };
}
Expand Down
42 changes: 38 additions & 4 deletions apps/web/src/lib/components/GameSession/WeatherControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@
RadioButton,
Label
} from '@tableslayer/ui';
import { type StageProps } from '@tableslayer/stage';
import {
WeatherType,
RainPreset,
SnowPreset,
LeavesPreset,
AshPreset,
DustStormPreset,
EmbersPreset,
BlizzardPreset,
FirefliesPreset,
type StageProps
} from '@tableslayer/stage';
import { to8CharHex, queuePropertyUpdate, trackChecklistItem } from '$lib/utils';
import chroma from 'chroma-js';

Expand All @@ -27,11 +38,30 @@

const selectedWeather = $state(stageProps.weather.type.toString());

// Each weather type looks right at its own field of view and intensity
const weatherPresets: Record<number, { fov: number; intensity: number }> = {
[WeatherType.Rain]: RainPreset,
[WeatherType.Snow]: SnowPreset,
[WeatherType.Leaves]: LeavesPreset,
[WeatherType.Ash]: AshPreset,
[WeatherType.DustStorm]: DustStormPreset,
[WeatherType.Embers]: EmbersPreset,
[WeatherType.Blizzard]: BlizzardPreset,
[WeatherType.Fireflies]: FirefliesPreset
};

// Weather toggle
const handleWeatherTypeChange = (weatherType: string) => {
queuePropertyUpdate(stageProps, ['weather', 'type'], Number(weatherType), 'control');
const type = Number(weatherType);
queuePropertyUpdate(stageProps, ['weather', 'type'], type, 'control');
// Reset to the preset's tuned FOV and intensity; the sliders then adjust per type from there
const preset = weatherPresets[type];
if (preset) {
queuePropertyUpdate(stageProps, ['weather', 'fov'], preset.fov, 'control');
queuePropertyUpdate(stageProps, ['weather', 'intensity'], preset.intensity, 'control');
}
// Track checklist completion for changing weather (only if setting to non-none weather)
if (Number(weatherType) > 0) {
if (type > 0) {
trackChecklistItem('weather');
}
};
Expand All @@ -41,7 +71,11 @@
{ label: 'Rain', value: '1' },
{ label: 'Snow', value: '2' },
{ label: 'Leaves', value: '3' },
{ label: 'Embers', value: '4' }
{ label: 'Ash', value: '4' },
{ label: 'Dust storm', value: '5' },
{ label: 'Embers', value: '6' },
{ label: 'Blizzard', value: '7' },
{ label: 'Fireflies', value: '8' }
];

const handleFogColorUpdate = (cd: ColorUpdatePayload) => {
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/routes/(app)/[party]/play/usePlayTools.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ const DRAW_COLORS: Record<string, string> = {
'draw-yellow': '#ffd93d',
'draw-green': '#6bcf7f',
'draw-blue': '#2e86ab',
'draw-purple': '#b197fc',
'draw-pink': '#f06595',
'draw-turquoise': '#20c997'
'draw-purple': '#b197fc'
};

const DRAW_EFFECTS: Record<string, AnnotationEffect> = {
Expand All @@ -46,7 +44,9 @@ const DRAW_EFFECTS: Record<string, AnnotationEffect> = {
'effect-ice': AnnotationEffect.Ice,
'effect-magic': AnnotationEffect.Magic,
'effect-grease': AnnotationEffect.Grease,
'effect-spacetear': AnnotationEffect.SpaceTear
'effect-spacetear': AnnotationEffect.SpaceTear,
'effect-web': AnnotationEffect.Web,
'effect-entangle': AnnotationEffect.Entangle
};

const PLAYFIELD_FOG_BRUSH_SIZE = 7.0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@
import { AnnotationEffect } from '../Stage/components/AnnotationLayer/types';
import EffectPreview from '../RadialMenu/EffectPreview.svelte';

// Color palette - 10 colors
// Color palette - 8 colors (pink and turquoise gave up their slots to effects)
const COLORS = [
'#d73e2e', // red
'#ffa500', // orange
'#ffd93d', // yellow
'#6bcf7f', // green
'#2e86ab', // blue
'#b197fc', // purple
'#f06595', // pink
'#20c997', // turquoise
'#ffffff', // white
'#2a2a2a' // dark
];
Expand All @@ -37,7 +35,9 @@
AnnotationEffect.Ice,
AnnotationEffect.Magic,
AnnotationEffect.Grease,
AnnotationEffect.SpaceTear
AnnotationEffect.SpaceTear,
AnnotationEffect.Web,
AnnotationEffect.Entangle
];

// Effect colors for the opacity slider gradient
Expand All @@ -48,7 +48,9 @@
[AnnotationEffect.Ice]: '#b3d9ff',
[AnnotationEffect.Magic]: '#9333ea',
[AnnotationEffect.Grease]: '#4d3319',
[AnnotationEffect.SpaceTear]: '#330066'
[AnnotationEffect.SpaceTear]: '#330066',
[AnnotationEffect.Web]: '#e6e8eb',
[AnnotationEffect.Entangle]: '#3a7d2c'
};

interface Props {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@
return new THREE.Vector3(0.3, 0.2, 0.1);
case AnnotationEffect.SpaceTear:
return new THREE.Vector3(0.2, 0.0, 0.4);
case AnnotationEffect.Web:
return new THREE.Vector3(0.9, 0.91, 0.93);
case AnnotationEffect.Entangle:
return new THREE.Vector3(0.18, 0.42, 0.12);
default:
return new THREE.Vector3(1.0, 1.0, 1.0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,16 +427,17 @@ events to be detected outside of the fog of war layer.
</T.Mesh>

<!--
All annotations render on Overlay layer (over fog, no post-processing).
Effect annotations have a different render order to appear below plain color annotations.
Color annotations render on the Overlay layer (over fog, no post-processing).
Effect annotations render in the Main pass so they sit under fog of war, lights,
and markers - the trade-off is they receive post-processing (bloom etc.) there.
-->
<T.Mesh name="annotationLayer" scale={[display.resolution.x, display.resolution.y, 1]}>
{#each props.layers as layer, index (layer.id)}
<T.Mesh
name={layer.id}
visible={isVisible(layer)}
position.z={(props.layers.length - index) * 0.001}
layers={[SceneLayer.Overlay]}
layers={hasEffect(layer) ? [SceneLayer.Main] : [SceneLayer.Overlay]}
renderOrder={hasEffect(layer) ? SceneLayerOrder.EffectAnnotation : SceneLayerOrder.Annotation}
>
<AnnotationMaterial
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export enum AnnotationEffect {
Water = 3,
Magic = 4,
Grease = 5,
Ice = 6
Ice = 6,
Web = 7,
Entangle = 8
}

/**
Expand Down Expand Up @@ -186,6 +188,20 @@ export const AnnotationEffectDefaults: Record<AnnotationEffect, Omit<AnnotationE
softness: 0.32,
border: 0.44,
roughness: 0.55
},
[AnnotationEffect.Web]: {
speed: 0.3,
intensity: 1.0,
softness: 0.3,
border: 0.5,
roughness: 0.45
},
[AnnotationEffect.Entangle]: {
speed: 0.6,
intensity: 1.0,
softness: 0.3,
border: 0.5,
roughness: 0.5
}
};

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ash from './particles/atlases/ash.png';
import fireflies from './particles/atlases/fireflies.png';
import leaves from './particles/atlases/leaves.png';
import rain from './particles/atlases/rain.png';
import snow from './particles/atlases/snow.png';
Expand All @@ -7,7 +8,8 @@ export enum ParticleType {
Snow = 1,
Rain = 2,
Leaves = 3,
Ash = 4
Ash = 4,
Fireflies = 5
}

export const ParticleData = {
Expand All @@ -34,6 +36,12 @@ export const ParticleData = {
size: 768,
columns: 3,
rows: 3
},
[ParticleType.Fireflies]: {
url: fireflies,
size: 768,
columns: 3,
rows: 3
}
} as const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
import RainPreset from './presets/RainPreset';
import LeavesPreset from './presets/LeavesPreset';
import AshPreset from './presets/AshPreset';
import DustStormPreset from './presets/DustStormPreset';
import EmbersPreset from './presets/EmbersPreset';
import BlizzardPreset from './presets/BlizzardPreset';
import FirefliesPreset from './presets/FirefliesPreset';

interface Props extends ThrelteProps<typeof THREE.Mesh> {
props: StageProps;
Expand Down Expand Up @@ -83,6 +87,18 @@
case WeatherType.Ash:
weatherPreset = { ...AshPreset };
break;
case WeatherType.DustStorm:
weatherPreset = { ...DustStormPreset };
break;
case WeatherType.Embers:
weatherPreset = { ...EmbersPreset };
break;
case WeatherType.Blizzard:
weatherPreset = { ...BlizzardPreset };
break;
case WeatherType.Fireflies:
weatherPreset = { ...FirefliesPreset };
break;
default:
// Fallback to rain preset
weatherPreset = { ...RainPreset };
Expand Down Expand Up @@ -134,6 +150,13 @@
<T.Scene is={particleScene} visible={false}>
<T.PerspectiveCamera is={particleCamera} manual />
<ParticleSystem props={weatherPreset.particles} opacity={weatherPreset.opacity} intensity={weatherPreset.intensity} />
{#if weatherPreset.secondaryParticles}
<ParticleSystem
props={weatherPreset.secondaryParticles}
opacity={weatherPreset.secondaryParticles.opacity}
intensity={weatherPreset.intensity}
/>
{/if}
</T.Scene>

<T.Mesh bind:ref={mesh} {...meshProps} visible={props.weather.type !== WeatherType.None}>
Expand Down
Loading
Loading