Commit Graph
100 Commits
Author SHA1 Message Date
adminandClaude Opus 4.8 ae0e2de7cf Make the x-ray pulse an asymmetric rising curve
Replace the symmetric sine with a raised cosine raised to
_XRayPulseShape: a long near-zero plateau, a slow rise and a short
full peak. Both shader halves use the identical formula to stay in
phase.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:52:47 +02:00
adminandClaude Opus 4.8 ff034870fc Freeze hiders (pose + transform) during the resolution phase
While a match is in the resolution sub-phase, hiders that have not
been found hold their current pose and position: the pose graph is
frozen (mixer speed 0, current frame re-asserted) and owner input is
disabled while gravity/grounding keep them planted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:52:46 +02:00
adminandClaude Opus 4.8 96528524a6 Prefill save dialog with the selected painting name
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:52:46 +02:00
adminandClaude Opus 4.8 5149544afe Pick height/occlusion channel when sampling own player
The pipette now reads the height (occlusion) value from the own
paint mesh and enables the height toggle; picking anything else
disables the toggle while leaving value and alpha untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:52:37 +02:00
admin 68ee58a167 Update scenes 2026-07-01 20:49:09 +02:00
admin b88516355b Add some generated colliders 2026-07-01 20:48:45 +02:00
adminandClaude Opus 4.8 523bfd3b0e Fix brush size varying with UV density; decouple preview opacity
Brush radius now derives from the mesh-wide average UV density instead of
the hit triangle's own density. Per-triangle density varied up to ~7.6x
across the mesh (spiking at UV seams and stretched islands), so the same
brushSize painted a visibly larger patch on seam triangles than on
evenly-mapped ones. A single global scale keeps the brush the same physical
size everywhere; the stamp remains a 3D box, so seams are still bridged.

Also decouple the hover preview opacity from the brush albedo alpha: the
preview now stays fully opaque and is scaled only by the Preview Opacity
property, since the ring is a size/shape indicator, not a paint-strength
preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 20:35:03 +02:00
adminandClaude Opus 4.8 410f9808b5 Split concavity-bridging slabs in the collider baker
A slab that spans a concave silhouette (e.g. a table side = two legs
plus a top rail, all coplanar and thin) produced one convex hull that
filled the open gap between the legs, so a player standing between them
counted as embedded. Add a refinement pass: each slab whose in-plane
coverage grid shows its convex-hull footprint is less than a
configurable fraction (hullFillThreshold, default 0.6) covered by real
surface is recursively halved along its larger PCA axis until every
piece hugs actual geometry. Solid boards (the shelf) are ~fully covered
and pass through untouched. Verified over a 9600-point grid: zero
bridging (no collider interior lies >6cm from the source surface),
shelf output unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 16:06:36 +02:00
adminandClaude Opus 4.8 5c1f31a887 Add surface-cluster collider baker for concealment volumes
Generate multiple convex collider proxies from a mesh by growing
triangles into thin slabs (PCA minor-axis thickness gate) and hulling
each slab, so shelves and open compartments stay hollow while boards
count as embedding surfaces. Baked meshes get readable, deterministic
asset names (scene/prefab path + hierarchy + collision index) instead
of GUIDs. ConcealmentMeter now also excludes a furniture's own concave
mesh collider when a ConcealmentColliderBaker sits in its parent,
symmetric to the existing ConcealmentVolume rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:30:21 +02:00
adminandClaude Opus 4.8 8603b0d884 Divide out player scale from ConcealmentMeter baked mesh
SkinnedMeshRenderer.BakeMesh(mesh) bakes the renderer's world scale
into the vertices. SkinnedColliderBaker already accounts for this and
divides it back out, but ConcealmentMeter did not: it lifted the
already-scaled verts to world via localToWorldMatrix (scale again),
yielding scale-squared voxel positions. This threw off the embedded
broadphase box, the EmbeddedPercent computation (which now drives the
X-ray reveal) and the debug gizmos whenever PlayerScaler != 1.

Rescale the baked mesh to unit scale right after baking (no-op at
scale 1), matching the SkinnedColliderBaker convention documented in
PlayerScaler, so world = localToWorldMatrix holds on unit geometry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:08:22 +02:00
admin 2f38cf0e32 Update packages 2026-07-01 13:07:28 +02:00
admin 8567b9d8ef Add "Dirt" plugin 2026-07-01 13:07:16 +02:00
admin c2d535c661 Author the player X-ray glow color and fade timing
Set _XRayColor (HDR orange, alpha 0 = off by default), pulse speed/strength
on Player.mat and xrayFadeDuration on the Player prefab.
2026-07-01 12:22:21 +02:00
adminandClaude Opus 4.8 c54e0cf502 Add see-through X-ray reveal overlay for players
Add a second, additive HDR emission color (_XRayColor) that reveals a
player through walls as a pulsing energy glow, driven during matches:

- Shader: XRayOverlay pass (ZTest Greater, additive) for occluded parts
  plus a matching additive term in the forward fragment for visible
  parts, so the glow shows everywhere and never double-blends. Exposes
  _XRayColor, _XRayPulseSpeed and _XRayPulseStrength for a breathing pulse.
- Render it after opaques via a RenderObjects feature (custom XRayReveal
  light-mode tag) on both PC and Mobile renderers, so the through-wall
  test is depth-sort independent and no longer drops out at some camera
  angles/distances.
- MeshPainter drives _XRayColor alpha through a framerate-independent
  fade (xrayFadeDuration) rather than a hard toggle.
- Reveal is driven per avatar on every client: all remaining un-found
  hiders glow during the Resolution phase, and a hider whose
  ConcealmentMeter EmbeddedPercent exceeds MatchManager.embeddedRevealPercent
  glows via an owner-authoritative NetworkVariable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 12:22:17 +02:00
admin d7104f9314 Tune the player brush defaults and reset occlusion to neutral
Set occlusion to 0.5 (the new neutral for painted height) so Reset
HUD/Values lands on neutral, and adjust the default brush colour,
metallic/smoothness, active brush and alignment.
2026-07-01 08:15:22 +02:00
adminandClaude Opus 4.8 addc606bb3 Leave brush opacities untouched when picking with the pipette
The pipette now samples only what is painted (albedo, metallic,
smoothness, emission), not how strongly - the albedo alpha,
metallic/smoothness opacity and emission alpha are preserved instead
of being forced to 1 in every pick path and in FinalizePick.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 08:15:18 +02:00
admin bb74f748bf Author the painted-height sliders in the paint HUD
Add the occlusion-shift, normal-intensity and parallax-intensity slider
instances to the HUD layout prefab under their stable widget names so the
binder wires them to the painter's material knobs.
2026-07-01 07:07:43 +02:00
adminandClaude Opus 4.8 59939b3496 Add painted-height HUD sliders for AO shift and relief intensity
Wire three material-backed look sliders (occlusion AO shift, relief normal
intensity, parallax intensity) through the paint HUD, its layout/state
persistence, the .paint slot format (bumped to v4), owner-authoritative
network sync and the runtime reset, mirroring the existing camo-knob path so
they save, restore, replicate and reset alongside the brush values.

Change the occlusion AO mapping from a division threshold to a linear shift:
AO fades from 1 down to (1 - shift) at the deepest painted hole, so a 0 shift
no longer leaves black spots. Enable _NORMALMAP alongside _PARALLAXMAP so URP
transforms the painted relief normal into world space (otherwise it discards
normalTS and the relief is invisible), and pin the added keyword in the build
keep-alive material.

Stop the pipette from picking the occlusion/height value and turn its toggle
off after a pick. Default the knobs to 0.2 shift / 1.4 normal / 1.0 parallax
across the shader, painter, network and HUD fallbacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 07:07:39 +02:00
adminandClaude Opus 4.8 fdcb4f8d8a Drive parallax height and relief from the painted occlusion channel
Reuse the existing occlusion paint channel (no new map, MAP_COUNT stays 3):
0.5 is neutral, above 0.5 raises a hill, below 0.5 sinks a hole and also
fades ambient occlusion (saturate(2*occ)). Bind the MSO map to _ParallaxMap,
enable _PARALLAXMAP, derive a relief normal from the height gradient, and
reseed unpainted occlusion to 0.5 so untouched surfaces stay visually neutral.
Pin the _PARALLAXMAP runtime variant in the build keep-alive material.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:40:23 +02:00
admin e349446fb7 Strip ProBuilder editor scripts on build 2026-06-30 21:47:28 +02:00
admin f629731539 Author the general and paintings panels in the paint HUD
Add the General and Paintings panels to the HUD layout prefab and register
their stable widget names so the binder can find and manage them.
2026-06-30 21:47:23 +02:00
adminandClaude Opus 4.8 44cea8dd15 Load paintings instantly and allow overwriting saves in the paint HUD
Load now applies the selected slot immediately instead of going through a
confirmation dialog. Save keeps its OK button enabled even when the name
already exists (the warning text stays, purely informational) and writes
through with overwrite, so re-saving under the same name replaces the slot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:47:16 +02:00
admin b6d60d7a98 Tune the hero cutout in Main and drop the duplicate driver
Remove the second HeroCutout from the Main Camera (the GameManager host is the
intended, single driver), set the GameManager cutout radius/feather, and set
hunterCount to 0.
2026-06-30 21:32:36 +02:00
adminandClaude Opus 4.8 f0a0fa4595 Point the paint variant keep-alive at the right shader
The painter clones Player.mat (Custom/PlayerCamoLit) at runtime and enables
_METALLICSPECGLOSSMAP, _EMISSION and _OCCLUSIONMAP, all shader_feature_local.
That keyword combination existed on no PlayerCamoLit material at build time,
so Unity stripped the variant and the build fell back to the base variant -
metallic/smoothness/emission/occlusion ignored, giving the flat look. The
keep-alive material that should pin this variant pointed at URP/Lit instead
of PlayerCamoLit, so it kept the wrong shader alive. Swap its shader GUID to
PlayerCamoLit; the three keep-alive keywords already match what the painter
sets, so the needed variant is now pinned into every build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:32:32 +02:00
adminandClaude Opus 4.8 b22d2ed342 Scale the hero cutout with the player's PlayerScaler
The cutout cone's radius and feather are now multiplied by the hero target's
uniform world scale (lossyScale.x, the same body-scale source the orbit input
uses). The authored values are the scale-1 sizes, so the see-through hole and
its soft edge keep the same on-screen proportion for a small hider or a large
hunter, and a mid-match conversion tracks live since lossyScale is read every
frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:32:25 +02:00
adminandClaude Opus 4.8 c29cd172bf Destroy pre-match objects on seek and block hunter wall-climb while hiding
Destroy every GameObject tagged "PreMatch" locally when the match enters
the Seek sub-phase (hooked in ApplyPhaseLocal, runs on every machine; the
objects are plain scene geometry with no NetworkObject, so each client
cleans up its own copies). Block hunters from starting a wall- or
ceiling-climb during the Hide sub-phase via a WallClimbBlockedNow() gate
in UpdateWallClimbState; an in-progress climb is exited cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 20:05:09 +02:00
adminandClaude Opus 4.8 6fcada4631 Keep the pan limit constant across zoom and hand off cleanly to free cam
Two paint-mode pan refinements:
- The max-distance clamp is back to body-relative only (CurrentScale, no zoom
  factor), so the world-space pan limit is identical at every zoom level;
  only the sensitivity stays zoom-scaled (finer when zoomed in).
- Don't zero the pan offset in OnDisable. The only thing that disables this
  component is FreeCamMode taking over, and the freecam snaps to the live
  (still panned) view. Zeroing here jumped the orbit camera the brain blends
  FROM to center while the freecam sat at the panned pose - the visible
  "snap to 0, then translate to the offset" on the paint->free-cam switch.
  Leaving the offset frozen keeps blend-from == blend-to (both panned) for a
  seamless handoff; the pan glides home on its own once the orbit input next
  runs in a non-paint mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:53:35 +02:00
adminandClaude Opus 4.8 5965f7199a Suppress global hotkeys while a text field is focused
The save-dialog name field is a focused TMP_InputField, but global discrete
hotkeys kept reading the keyboard every frame, so typing a name like
"Checkers" cycled the pose (C) and shut the server down (K). Add a shared
TypingGuard.IsTyping check (focused TMP/legacy InputField) and short-circuit
the global handlers on it: pose cycle, network dev keys, mode switch, and
paint undo/redo. Movement was already gated out via ControlEnabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:53:26 +02:00
admin b951556f35 Update The Room materials and refresh brush assets 2026-06-30 19:25:53 +02:00
admin 6bedc7cf3e Serialize the paint-mode pan tunables in Main 2026-06-30 19:25:48 +02:00
adminandClaude Opus 4.8 3fa99f32fe Keep the paint-mode pan on release and scale it by zoom
The middle-mouse pan now persists when the button is released and only glides back to center on leaving paint mode. Pan sensitivity and max distance scale with the orbit zoom distance, so panning stays consistent on screen at any zoom and unchanged at the default zoom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 19:25:45 +02:00
admin 4e8a907a8c Add a square brush and wire up the HUD brush preview
Add the BrushesSquare texture, replace the duplicated brush slots on the
player with it, show a brush preview in the paint HUD, and surface the
spawn-area tags and conversion reveal delay in the inspector.
2026-06-30 18:37:23 +02:00
adminandClaude Opus 4.8 2166d2b67a Note painting undo as done in the design doc
Undo is implemented (checkpoint-based, replicated); a separate full reset
is intentionally unnecessary since undo covers it. Drop the stale open item
and polish note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:37:18 +02:00
admin 9a90b772d7 Add a second pose to the hunter variant 2026-06-30 18:20:29 +02:00
admin f1ab62b061 Author the alpha sliders, reset button, and slider curves in the HUD
Add Slider_AlbedoAlpha / Slider_EmissionAlpha, the Lib_ResetHud button,
and SliderCurve components to the paint HUD panel.
2026-06-30 18:20:26 +02:00
adminandClaude Opus 4.8 6e76510005 Update the game design doc to the current state
Move the implemented systems (netcode, hunter role, phase/timer match
loop, win conditions, both match modes, spawn areas, shooting,
role-based visibility, spectator freecam, networked paint) out of the
"missing" section, document the multiplayer and match-loop subsystems,
and trim the open items to what's actually left.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:20:20 +02:00
adminandClaude Opus 4.8 057c99fa1d Persist material scalars, reset the HUD, and split alpha from the picker
Save and restore the emission intensity and the three camo knobs
(half-Lambert, half-Lambert brightness, specular dampen) with a named
painting. The .paint format moves to v3 with a small scalar block
between the header and the pixel maps; v2 paintings still load with
their painter values left untouched. Loading re-syncs the emission and
camo sliders, and peers pick the values up for free through the
existing owner-authoritative paint NetworkVariables.

Add a HUD reset (Lib_ResetHud button plus context-menu fallback) that
behaves as if the saved hud-layout file were deleted: it removes the
file, restores panels to their authored prefab positions, and resets
the brush values to the painter/material defaults captured before any
carry/restore runs.

Remove the alpha bar from HsvColorPicker so alpha is driven by
standalone Slider_AlbedoAlpha / Slider_EmissionAlpha bindings; the
picker now writes RGB only and the sliders write alpha only, with no
feedback between them. Add a generic SliderCurve component that reshapes
a slider's handle position into a non-linear value (with an inverse for
setting values back), and make the slider wiring curve-aware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:20:13 +02:00
adminandClaude Opus 4.8 fe8f12b8bb Spawn converted hunters in place and smooth their reveal
Fix the in-place Conversion respawn snapping to the origin (0,0,0),
which surfaced when a hider was tagged mid wall-climb. The owner holds
authority over the NetworkTransform, so the server's Instantiate
position is ignored on the owner. Deliver the tagged world position
through a replicated _spawnOverride the server writes in OnNetworkSpawn,
and have the owner re-assert it before PlayerCharacterController's first
Update snapshots the kill-plane rescue target. This replaces the fragile
SpawnedMidSeek phase check.

Also hide a freshly converted hunter on other clients for a short
settle window (conversionRevealDelay) so nobody sees it pop in or
interpolate from the spawn frame; the shot hider is already despawned,
then the hunter cleanly materializes in its place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 16:18:53 +02:00
admin 24de7ef3da Select the conversion match mode in Main 2026-06-30 15:20:58 +02:00
adminandClaude Opus 4.8 f485d1676b Add the conversion match mode
Introduce a second match mode alongside Classic. In Conversion mode
hiders are invisible to each other (and to hunters during Hide), and a
hunter hit converts the hider into a full hunter in place instead of
sending them to the spectator freecam. The mode is replicated to all
clients through the existing phase named-message byte; visibility is
computed locally per client per mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:20:54 +02:00
admin 1f46e6258d Raise reflection intensity across the scenes
Bump reflection intensity to 0.75 in the lobby, test map and The Room, and warm the subtractive shadow colour in The Room.
2026-06-30 14:00:03 +02:00
admin 8fcf2d6de0 Tune the match phase durations and shooting in Main
Set hideDuration 30, seekDuration 60, resolveDuration 10, shootRange 100 and shootCooldown 1.5 on the MatchManager.
2026-06-30 13:59:57 +02:00
adminandClaude Opus 4.8 5b3fe1d3d1 Add the hide/seek/resolution match state machine
Drive the match through three server-authoritative phases (hide, seek,
resolution) with per-phase durations, broadcasting the active phase and
countdown to clients over the existing named-message infrastructure so
MatchManager stays a plain MonoBehaviour and Main keeps zero in-scene
network objects.

During hide, hider meshes are culled on hunter clients only (each client
computes visibility locally from role, phase and found state). During
seek, hunters shoot a single raycast from the first-person camera centre
(left click, cooldown-gated); a validated hit marks the hider found,
which hides its mesh for everyone and binds the owner to spectator
freecam. Seek ends early once every hider is found, then resolution runs
before returning to the lobby.

Force AlwaysAnimate on remote replicas so the animator keeps writing bone
transforms while the body is hidden or off-screen. The Paintman animator
is authored CullUpdateTransforms, so a culled renderer froze the pose on
the rest pose and the skinned collider baked that frozen pose, landing
replicated paint stamps on the wrong body location and leaving the
painting desynced after hiders were shown again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 13:59:46 +02:00
admin 95effb91da Set the hunter count and re-enable the camera component in Main
Bump hunterCount to 1 and re-enable the disabled camera component on the
main camera.
2026-06-30 12:03:33 +02:00
admin 7198968cc6 Author spawn area colliders and tags in The Room
Add the SpawnArea, HunterSpawnArea, HiderSpawnArea and PreMatch tags and
author the spawn area colliders in The Room scene.
2026-06-30 12:03:29 +02:00
adminandClaude Opus 4.8 c1a13f6338 Pick role-specific spawn areas with a shared fallback
Choose the spawn area by player role: Hunter avatars look for a
HunterSpawnArea-tagged collider, Hiders for HiderSpawnArea. When the
role-specific area is missing, fall back to the shared SpawnArea tag, and
when that is absent too, keep the existing client-id ring placement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 12:03:22 +02:00
admin 1e17b90358 Add the hero cutout to the main camera and tune the deoccluder
Attach the HeroCutout component to the Main Camera with dialed-in cone values (radius 0.42, feather/depthFeather 0.15) and lower the deoccluder MinimumDistanceFromTarget to 0.05.
2026-06-30 08:42:06 +02:00
admin 3709bf76db Swap the living-room and shared materials to the new shader
Point the living-room set and the shared materials at the new shader GUID and clear the stale MOTIONVECTORS pass / custom render queue overrides.
2026-06-30 08:42:02 +02:00
adminandClaude Opus 4.8 04c73623d3 Pick the material of the hit submesh on multi-material renderers
PickFromForeignMaterial read rend.sharedMaterial, which is always slot 0, so any renderer with several materials (one per submesh) always sampled the first material's values. Resolve the submesh from the hit triangle (collider triangleIndex, or the recovered render-mesh triangle) and read sharedMaterials[submesh] (clamped) instead. Single-material renderers stay on slot 0, byte-identical to before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:41:57 +02:00
adminandClaude Opus 4.8 06f5f33e63 Drive the hero cutout from a single camera-to-target ray
Replace the multi-sample silhouette probe with one camera->target raycast: any world geometry in the line of sight arms the cut, a clear line keeps occluders solid. The shader carves a world-space cone (apex at the camera, radius growing toward the target) so the screen-space hole stays a constant size regardless of occluder depth, with a soft radial fade plus a symmetric axial fade around the target so geometry just behind the player feathers out instead of hard-cutting along a plane. Anything well past the target stays solid. Also suppresses the deoccluder pull-in so the camera holds its orbit distance and the cut takes over.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:41:52 +02:00
admin 1aa1f6d869 Tune the corner guard and persist the eyedropper toggle on the player
Dial corner guard to 70 degrees / 0.7 fraction and serialize the
pipetteAlbedoFromScreen toggle on the player prefab.
2026-06-29 20:58:12 +02:00
adminandClaude Opus 4.8 fd2cc9eb98 Block paint dabs that wrap too far around corners
Add a geometry-based gate in PaintAtScreen that estimates how much of the
brush footprint lands on faces whose normals deviate sharply from the hit
surface. When that fraction exceeds the threshold the whole dab is
suppressed (no draw, emit, or undo mark) instead of smearing around the
edge. Backend-independent (no GPU readback) and winding-robust. Tunable via
cornerGuard / cornerGuardAngle / cornerGuardMaxFraction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:58:07 +02:00
admin 7e5e33e228 Move the network prefabs list to Assets root and tidy editor tooling
Move DefaultNetworkPrefabs.asset out of Assets/Settings back to the Assets root (where NGO expects it), and fix the PlaySceneWindow domain-reload toggle to read and write EnterPlayModeOptions correctly.
2026-06-29 20:12:58 +02:00
admin fbbc46cc6e Update scenes, lighting and materials
Authoring pass on The Room plus lighting tweaks across Lobby and Main, add a new Gold material, and bump the PC renderer SSAO intensity and radius.
2026-06-29 20:12:49 +02:00
admin b091f1175b Add camo sliders to the paint HUD and tune the player
Add the HalfLambert, HalfLambert brightness and specular-damp sliders to the paint HUD panel, dial the camo values on Player.mat, and disable shadow casting on the Paintman renderer so the player's cast shadow no longer gives away its position.
2026-06-29 20:12:44 +02:00
adminandClaude Opus 4.8 7c84f6ba92 Expose the camo knobs in the HUD, persist and replicate them
Surface the PlayerCamoLit material knobs (HalfLambert, HalfLambert brightness, specular dampen) as material-backed properties on MeshPainter, guarded by an IsReady gate since the HUD binds before the material instance exists. Wire the three HUD sliders to them and seed the sliders from the live material once the painter is ready. Persist the values into the same HUD JSON as the brush settings (with a hasCamoValues flag so pre-camo save files never clobber the authored material) and carry them across a scene-switch respawn. Replicate them owner-authoritatively via a NetworkVariable in PlayerPaintSync, exactly like emission intensity, so remotes and late joiners show the same camo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:12:39 +02:00
adminandClaude Opus 4.8 b5bd1fdb8b Rework the camo shader to flatten toward darkness, drop FormSoftness
Rebuild the camo controls around hiding a painted player in a dark scene. _HalfLambert is now a two-segment curve (0 = no effect / URP Lit, 0.5 = classic half-lambert soft terminator, 1 = fully flat) and a companion _HalfLambertBrightness (-1..1) additively shifts the flattened diffuse so the body tone matches the scene. _SpecularDampen still scales down the direct highlight. The view-coupled _FormSoftness normal-bend is removed entirely (it flipped light/dark with the camera); all knobs are now term-based and view-independent, and stay byte-identical to URP/Lit at their no-op values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:12:31 +02:00
adminandClaude Opus 4.8 67e3696339 Add a toggle for picking foreign albedo from screen or material
The hybrid foreign-object pipette previously always overwrote albedo with the lit on-screen pixel. Gate that behind a new serialized pipetteAlbedoFromScreen flag (default off): off reads albedo texel-exact from the material like the other channels, on takes it from the rendered, fully-lit pixel. The data channels still always come from the material.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:12:19 +02:00
admin 4da2e3a70c Update scenes, lighting and glass materials
Heavy authoring pass on The Room scene plus lighting/render tuning across
scenes: Lobby gets lower ambient/reflection intensity, softer shadow
strength and a baked lighting data asset; Main and Test Map drop their
lighting data/settings links. Replace the living-room Glass materials with
reworked versions under Assets/Materials, update BrightDaySettings, and set
hunterCount to 0 in Main.
2026-06-29 16:24:12 +02:00
admin e351336b39 Reorganize project folders and clean up editor tooling
Move editor scripts to Assets/Scripts/Editor (PlaySceneWindow, SceneCollection),
move DefaultNetworkPrefabs and the Main Camera custom blends asset into
Assets/Settings, and shelve the unused HeroCutout shader/include under
Assets/Unused. Rename the Chameleon background texture, delete the obsolete
DefaultParentForEditor script and New Lighting Settings asset, add a The Room
SceneCollection asset, and drop the redundant Assets menu entry from the
StraightenKnees tool.
2026-06-29 16:23:50 +02:00
admin 42c5fcc323 Apply camouflage material to the player
New Player.mat using Custom/PlayerCamoLit, assigned to the Paintman renderer
on the Player prefab so the camo shader is active on hunters and hiders.
2026-06-29 16:23:14 +02:00
admin 3f48823513 Remove second-pipette toggle and preview from paint HUD
Drop the now-unused Toggle_PipetteScreen and the Preview element from the
paint HUD panel after consolidating back to a single (hybrid) pipette.
2026-06-29 16:23:03 +02:00
adminandClaude Opus 4.8 05cd52aa5e Add player camouflage shader
Custom/PlayerCamoLit is a URP 17 Lit clone whose ForwardLit pass routes
through PlayerCamo.hlsl - a faithful copy of UniversalFragmentPBR that
delegates all GI/APV/shadow/cluster-light helpers unchanged and only swaps
the three light calls for a camo variant. Three sliders flatten the form
cues that give a painted player away: _FormSoftness bends the per-pixel
normal toward the camera (softens diffuse + specular + reflections),
_HalfLambert lifts the diffuse shadow side, _SpecularDampen scales down the
direct highlight. All sliders at 0 are byte-identical to URP/Lit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:22:57 +02:00
adminandClaude Opus 4.8 188f16a4e8 Make the eyedropper a hybrid material/screen pick
On a foreign object the pipette now reads the data channels
(metallic/smoothness/occlusion/emission) texel-exact from the material
while taking albedo from the rendered, fully-lit on-screen pixel - so the
picked colour honours baked lightmaps/ambient/SSAO while keeping the
material's PBR fidelity. Falls back to a pure screen pick when no readable
UV is available. Pull the render+readback out of PickFromScreen into a
shared TrySampleScreenColor.

The pipette now also arms on Ctrl (in addition to Shift), and Ctrl+wheel
resizes the brush; the orbit camera ignores the wheel while either modifier
is held so it does not zoom and resize at once.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:22:45 +02:00
admin db10eef525 Add Play Scene Tool 2026-06-29 12:17:25 +02:00
admin fd869c9cf8 set living room prefabs as static for lightmap baking 2026-06-29 12:16:39 +02:00
admin 70e926bd82 Build out The Room scene with ProBuilder geometry
Author The Room environment and update ProBuilder editor settings used to
build it (cube shape size, select mode, shape builder defaults).
2026-06-28 23:02:36 +02:00
adminandClaude Opus 4.8 a7a4fbdcb7 Carry first-person facing into orbit camera on mode switch
When leaving first person for an orbit mode (Paint / Player Control), snap
the orbit axes to Camera.main's current view direction instead of restoring
the orbit's last-used angle. With WorldSpace binding + Sphere orbit + a
centered composer the camera look rotation is exactly
Euler(VerticalAxis, HorizontalAxis, 0), so the inverse mapping is exact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 23:02:31 +02:00
admin 054cadbd80 Tune player role scales, poses and render settings
Hunter scale 2.4 -> 1.5 and Hider 0.7 -> 0.5; Player prefab character
controller step offset and skin width tweaks (plus Unity field reserialization).
Pose assets get fall-clip fields and slightly lower controller height/center.
Lower SSAO intensity and radius in PC_Renderer; QualitySettings reserialized
by Unity (mesh LOD threshold, Switch 2 target).
2026-06-28 21:40:27 +02:00
admin 604adcdfd4 Add The Room scene with living room environment, use it as the match scene
New The Room scene built from the Barking_Dog living room asset: prefab
variants under Assets/Prefabs/3D Living Room, an Environment Light prefab and
baked lighting settings. Point MatchManager at The Room (was Test Map) and
swap it into the build settings scene list. Floor_Wood material and the
living room meta files are reserialized by the URP/Unity importer. Main.unity
also carries the inspector-pinned defaults of the orbit-zoom and hunter-count
fields (matching the C# defaults, no behavior change).
2026-06-28 21:40:18 +02:00
admin 7a1adcf6bb Add ProBuilder package
Add com.unity.probuilder 6.0.9 to the manifest and lockfile, with its
default per-project settings.
2026-06-28 21:39:48 +02:00
adminandClaude Opus 4.8 62cf0eae04 Scale third-person orbit zoom range and default by player size
The orbit radius (min/max/default and per-notch step) was in absolute world
units and ignored the player's localScale, so a small Hider started too far
out and a large Hunter too close and could not zoom out far enough. Multiply
range, step and default radius by the follow target's lossyScale (PlayerScaler
keeps the body uniformly scaled), making the inspector fields size-1 design
values that frame every role body-relative. Re-clamp every frame so a runtime
grow/shrink stays in range. GameModeManager.BindLocalPlayer calls ResetZoom
after rebinding so each new avatar starts at its scaled default zoom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:39:41 +02:00
adminandClaude Opus 4.8 0834419a56 Make the number of hunters configurable in MatchManager
StartMatch rolled exactly one random Hunter. Add a serialized hunterCount
field (default 1, [Min(0)], inspector-tunable) and roll N distinct random
Hunters via a partial Fisher-Yates on the client-id list, clamped to the
player count: 0 = all Hiders, >= player count = all Hunters. The match
sequence now carries a HashSet of hunter ids instead of a single id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:39:30 +02:00
adminandClaude Opus 4.8 346a0c6e8c Fix eyedropper sampling base map at wrong UV on convex/primitive colliders
hit.textureCoord is only filled for non-convex MeshColliders; on a convex
MeshCollider (or Box/Sphere/Capsule) it returns Vector2.zero, so the pick
sampled the foreign material's base map at texel (0,0) - a constant, wrong
color ("base map ignored"). Now the UV is recovered from the renderer mesh
itself (camera ray vs triangles, Moeller-Trumbore, barycentric UV) for
convex/primitive colliders, with the screen-pixel pick as fallback when the
mesh is not readable. The fast non-convex path is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:39:25 +02:00
adminandClaude Opus 4.8 09556e45fa Force Direct3D11 for Windows builds to avoid paint-reseed crash
The build crashed natively (UnityPlayer, no managed frames) during the
match-end paint carry, where LoadPaintFromSnapshot/ReseedCanonical tears
down and rebuilds all RenderTextures with DrawMeshNow/Blit and ReadPixels
from LateUpdate, on multiple painters at once. D3D12 is far stricter than
D3D11 about this immediate-mode + RT-lifetime churn outside the render
loop. Pin the Windows standalone graphics API to D3D11 (D3D12 fallback)
as a mitigation without touching the paint architecture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 17:43:55 +02:00
admin f9312d8a69 Lower camera near clip plane to 0.01
Drop the third-person/main camera near clip from 0.1 to 0.01 so the view
does not clip into the player up close.
2026-06-28 17:19:23 +02:00
adminandClaude Opus 4.8 ac25f59232 Add radial hero-cutout shader for third-person camera
Reveal the player when geometry sits between the orbit camera and the
character: a screen-space circular mask in a URP/Lit clone (HeroCutoutLit)
clips occluders in front of the player, depth-gated so only geometry nearer
than the hero is cut. The cutout lives outside UnityPerMaterial (SRP batcher
intact) and is a no-op when disarmed, so occluders look identical to URP/Lit.

A runtime driver (HeroCutout.cs on Main/GameManager) feeds the player's
screen position, radius, feather and depth into global shader properties and
only arms while the third-person orbit vcam is live; it disarms in
first-person, free-cam and the pause menu. Applied to the lobby walls via a
dedicated occluder material (floor left solid). Shipped but shelved for now.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 17:18:32 +02:00
adminandClaude Opus 4.8 b6aaf69235 Add Shift brush controls to paint mode
Hold Shift to momentarily enable the pipette (restores prior state on
release) and Shift+Scroll to resize the brush. The orbit zoom ignores the
wheel while Shift is held so it does not zoom and resize at once. The HUD
brush-size slider follows live via a BrushSizeChanged event, and the brush
preview now stays visible while Shift is held (drawn before the pipette
early-return) so the new size is visible while scrubbing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:20:25 +02:00
admin 4e27b1e729 Disable editor network bootstrap in builds; tune scenes and paint HUD panel
NetworkBootstrap now destroys itself outside the editor. Camera FOV/background
tweaks in Main, lobby light intensity, and paint HUD panel font/color polish.
2026-06-28 15:51:49 +02:00
adminandClaude Opus 4.8 f11fbc8c1c Keep the camera fixed when opening the pause menu
SetPaused no longer Exits the active mode, so the First-Person/Free-Cam rig
keeps its CinemachineCamera priority and the view stays frozen in place instead
of blending back to the orbit camera. Pausing now only disables each rig's
per-frame look input (dropping the controller's enabled flag) and parks the
orbit rig in Disabled to free the cursor; resuming re-enters the same mode whose
snap-to-current-view is a no-op, so there is no jump on close either.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:51:39 +02:00
admin 3f58e75623 Add lobby/main scene background, sky and glow materials
Main scene gets a full-rect Background image (Chameleon Background 1) in
the menu UI and re-enables a UI component. Lobby scene receives extensive
authoring (sky, lighting, props). New Lobby Sky and White Glow materials;
Yellow Glow emission toned down from ~89 to 64.
2026-06-28 15:15:59 +02:00
adminandClaude Opus 4.8 198db9a3ee Add NoClimb climb filter and kill-plane rescue to player controller
Two player-controller additions:

NoClimb: colliders tagged "NoClimb" are now invisible to wall-climb and
ceiling-grab. The grab detector (OnControllerColliderHit) and all three
climb probes (ProbeWall, ProbeCeiling, WallInFront) skip them, so such a
surface still blocks the capsule physically but can never be grabbed,
re-probed onto, or treated as a ceiling. WalkableGroundBelow is left
untouched (it only accepts walkable ground). The tag is read from a
serialized field (default "NoClimb"); an empty tag disables the check.

Rescue: a kill-plane fail-safe. The owner captures its spawn point on the
first Update frame (after OnNetworkSpawn's ring offset has landed) and,
if it falls below rescueMinY (-100), teleports back there with all
momentum cleared, toggling the CharacterController around the write like
PlaceOnSpawnRing. Owner-only; the authoritative NetworkTransform
replicates the reset. Runs ahead of the control gate so it rescues in any
mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:15:45 +02:00
adminandClaude Opus 4.8 dadf9d88d4 Fix paint HUD settings not persisting until a panel is dragged
The debounced auto-save compared painter values against the on-disk
baseline, so after any slider/toggle change the values stayed different
every frame and the 0.5s timer was pushed forward endlessly, never
firing. Saving only happened via the direct drag-end path. Compare
against the previous-frame snapshot instead so the timer fires once the
values settle. Also pin hudSaveId to a stable key so the layout is
shared across scenes instead of split per-scene.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:21:03 +02:00
adminandClaude Opus 4.8 96bcf84b1e Make session panel Disconnect button an Exit in Main scene
In Main (no active session) the context-sensitive button now reads "Exit"
and quits the application (stops play mode in the editor), so the player
can leave the build without Alt+F4. Connected behaviour is unchanged:
"Disconnect" leaves the session, "Back to Lobby" ends the match for the
map authority. The button is now interactable whenever idle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:00:03 +02:00
admin da3938d089 edit paint hud dialogs 2026-06-28 13:57:12 +02:00
admin da47bd3df3 Update font 2026-06-28 13:56:58 +02:00
adminandClaude Opus 4.8 f22ca4765f Persist HUD layout on drag-end instead of only on teardown
HUD panel positions and brush values were written only from
OnApplicationQuit/OnDestroy, which is not guaranteed in a build (Alt-F4,
process kill, crash), so layout work was lost. DraggablePanel now exposes
an IEndDragHandler callback that saves the layout the moment a panel is
dropped. Brush-value changes are detected against a disk baseline in
LateUpdate and flushed after a 0.5s debounce so per-frame slider drags
do not write every frame. The teardown save path is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 13:56:02 +02:00
adminandClaude Opus 4.8 2a6fc163b1 Add persistent global mouse sensitivity setting with slider
MouseSensitivity is a static, PlayerPrefs-backed multiplier (default 1,
clamped 0.1-4.0) that scales the mouse-look delta in the FreeCam,
FirstPerson and ThirdPerson controllers. Writes flush immediately so the
value survives a hard build exit. MouseSensitivitySlider binds the
Settings-panel slider to it (range read from the inspector) and mirrors
the value into its label, syncing on panel open via OnEnable.

Main.unity now contains the session-manager canvas directly (the
Online Session Manager prefab was unpacked) and wires the slider binder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 13:55:53 +02:00
admin 0df37b8e4a First working windows build 2026-06-28 13:16:21 +02:00
admin b27fdb99b4 Update font 2026-06-28 13:15:58 +02:00
adminandClaude Opus 4.8 abfb183c77 Keep _EMISSION/_METALLICSPECGLOSSMAP/_OCCLUSIONMAP shader variants alive in builds
Add a Resources material that sets all three PBR shader_feature keywords so
core build stripping retains the URP/Lit variants the runtime mesh painter
enables on the fly. Fixes metallic/smoothness/occlusion rendering as constant
in player builds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 13:15:34 +02:00
adminandClaude Opus 4.8 cdfec364b2 Toggle session panel with Escape as in-game pause overlay
- Panel shows in Main while disconnected, auto-hides once a connection is
  established, and toggles open/closed with Escape in the Lobby or on a Map.
- Escape now pauses gameplay (active mode exits, cursor freed, paint and
  movement disabled) instead of ending the match directly; closing restores
  the prior mode via SwitchTo.
- Disconnect button is context-aware: leaves the session in the Lobby, acts
  as "Back to Lobby" (EndMatch) for the match authority on a Map, and stays a
  plain disconnect for non-authority clients on a Map.
- Removed the Escape->EndMatch handler from MatchManager; match end now routes
  through RequestEndMatch with the same authority routing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 11:34:13 +02:00
adminandClaude Opus 4.8 d27ee16004 Bind online session browser to canvas, drop IMGUI
- OnlineSessionManager: remove OnGUI/IMGUI state; now a logic-only layer
  exposing Host/Refresh/Join/Disconnect plus Status/IsBusy/IsConnected/
  InSession/Sessions and Changed/SessionsChanged events
- OnlineSessionBrowserUI (new): drives the Servers canvas — 4 buttons,
  session list from Entry Template clones (name + players), row selection,
  state-driven interactability, status footer
- Main scene: attach binder, add status footer line, wire 8 refs; dev
  bootstrap panel disabled
- Online Session Manager.prefab (new)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 11:03:26 +02:00
adminandClaude Opus 4.8 286473930a Close the paint HUD when shutting down to player-less Main
ReleaseToNoPlayer tore down the mode cycle but never raised ModeChanged,
so the paint HUD - which only hides via that event - stayed open after a
shutdown that happened while PaintMode was active. Invoke ModeChanged(null)
after the teardown so any mode-following UI hides.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 10:39:07 +02:00
adminandClaude Opus 4.8 f8b11be290 Add UGS Sessions online hosting with no port-forwarding
Players can now host and join over the internet without port-forwarding
via Unity Gaming Services Relay + Lobby, exposed through the unified
Multiplayer Services SDK (Sessions API).

- OnlineSessionManager: anonymous auth, CreateSessionAsync (public,
  relay-backed), QuerySessionsAsync server browser, JoinSessionByIdAsync,
  and session leave wired into the existing net-stop teardown.
- Per-install auth profile derived from the project path
  (mirror_<sha1(dataPath)>) so junction-mirror clones get distinct UGS
  player ids, avoiding the same-machine 409 LobbyConflict on join.
- Install com.unity.services.multiplayer 2.2.4 (pulls Relay/Lobby/
  Authentication/Core) and attach OnlineSessionManager to the
  NetworkManager in Main.

Loopback dev flow (NetworkBootstrap H/C/J/K) is left untouched; the
online path is additive. MatchManager and gameplay are unchanged since
Sessions starts the host/client through NGO as before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 10:17:28 +02:00
adminandClaude Opus 4.8 f706cdb5a7 Grant match-start/end authority to first client on dedicated server
Host keeps authority as before; a dedicated server (no host player) hands
start/end authority to the first connecting client and reassigns it if that
client leaves. The Start Match trigger now polls a server-side physics overlap
instead of relying on OnTriggerEnter, so it fires for the authority client's
remote avatar (moved by NetworkTransform, no CharacterController.Move on the
server) as well as the host's owned avatar. Esc-to-end routes a named message
from the authority client to the server when that client is not the host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 09:34:18 +02:00
adminandClaude Opus 4.8 9d6570f7fe Carry painting across lobby/map respawns with isolated snapshot transfers
Persist each owner's paint snapshot on the MatchManager across the
despawn/respawn that happens on a lobby<->map scene switch, then reload
and rebroadcast it onto the freshly spawned avatar so painted meshes
survive the transition. Cleared on disconnect/shutdown to avoid stale
carry across sessions.

Isolate concurrent snapshot transfers by id so a respawning replica's
late-join request and the carry broadcast no longer share one reassembly
buffer (which decoded a mixed deflate blob -> "Corrupted data"), and drop
transfers with an older cutoff so a blank late-join cannot overwrite the
carried image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 01:21:39 +02:00
adminandClaude Opus 4.8 b00c415c8c Fix HUD persistence breaking across additive scene switches
The HUD save key was derived from the active scene name, which now changes
across the additive lobby/map loads (Main -> Lobby -> Test Map). Save and
restore landed in different files, so settings appeared lost. Derive the key
from the HUD's own (stable, persistent) scene instead.

Brush settings also live on the avatar's painter, which is despawned and
respawned on every scene switch, resetting them to prefab defaults. Mirror
the brush values into an in-memory snapshot on the persistent HUD and seed the
freshly bound painter from it, so in-session edits carry across the respawn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 00:51:59 +02:00
adminandClaude Opus 4.8 91ce8ff329 Replace stripped-player spectator with a minimal dedicated prefab
Mid-match joiners now spawn a dedicated empty Spectator prefab (NetworkObject
+ SpectatorSetup only) instead of a fully stripped Player prefab. The FreeCam
rig is a standalone scene object in Main, so the spectator needs no avatar body,
renderer, collider, or CharacterController -- eliminating the leftover-body
artifact and the fragile per-peer strip path entirely.

- SpectatorSetup.cs (new): owner binds GameModeManager.BindSpectator (FreeCam-only)
- Spectator.prefab (new): empty avatar (Transform + NetworkObject + SpectatorSetup),
  registered in DefaultNetworkPrefabs, wired on MatchManager in Main
- GameModeManager: add BindSpectator/BuildSpectatorModes; drop the spectator
  branch from BindLocalPlayer; ReleaseToNoPlayer frees the cursor on teardown
- MatchManager: independent entropy-seeded RNG for fair hunter pick (was sharing
  the global engine RNG and always landing on the same client); spawn the
  spectator prefab for mid-match joiners; cursor-safe return-to-Main teardown
- FreeCamController: guard IgnorePlayerCollision against a disabled capsule

Also bundled (unrelated user asset/UI edits): PaintHudPanel layout tuning,
font atlas (arialroundedmtprocyr_bold SDF), forestpack_foliage material.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 00:31:49 +02:00
adminandClaude Opus 4.8 be6db5b0a9 Add match-end, spectator-hold join, and shutdown scene teardown
- Host presses Esc to end a running match: swap Test Map back to Lobby and
  respawn everyone as the neutral Player (server-gated, host-only).
- A client joining mid-match is spectator-held (no avatar) and spawns into
  the lobby when the match ends.
- On shutdown/disconnect, unload every gameplay scene so only Main is left
  loaded & active (NGO's Dispose does not unload additively-synced scenes).
- Generalize RespawnAll to a prefab selector + position so match-start
  (role variants) and match-end (neutral Player) share one path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 23:29:28 +02:00