Add taunt button, Tab as Escape alternative, free cam Q/E removal
- OverviewMenu: taunt button (manual ping + close, hider/seek-only), Tab triggers the Escape chain (TypingGuard-gated) - GameModeManager: LocalPlayerIsHider helper, allow E-ping in free cam (Q/E no longer used for movement) - FreeCamController: vertical movement only via Space/Ctrl - Icons: Icon_taunt (wired), Icon_firstperson_paint (unwired, for later) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1054bcd3d6
commit
c6a22c1643
7 files changed
+269
-12
No files matched your search
@@ -6,7 +6,7 @@ using UnityEngine.InputSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Free-flying spectator camera on its own dedicated <see cref="CinemachineCamera"/>: WASD flight relative
|
||||
/// to the view, Q/E (or Space/Left Ctrl) for down/up, mouse look. A <see cref="CharacterController"/>
|
||||
/// to the view, Space/Left Ctrl for up/down, mouse look. A <see cref="CharacterController"/>
|
||||
/// capsule makes it slide along world geometry instead of clipping. Driven by <see cref="FreeCamMode"/>
|
||||
/// via <see cref="SetActive"/>; while inactive this component does nothing.
|
||||
/// </summary>
|
||||
@@ -170,14 +170,15 @@ public class FreeCamController : MonoBehaviour
|
||||
if (kb.sKey.isPressed) dir -= transform.forward;
|
||||
if (kb.dKey.isPressed) dir += transform.right;
|
||||
if (kb.aKey.isPressed) dir -= transform.right;
|
||||
if (kb.eKey.isPressed || kb.spaceKey.isPressed) dir += Vector3.up;
|
||||
if (kb.qKey.isPressed || kb.leftCtrlKey.isPressed) dir -= Vector3.up;
|
||||
// Q/E intentionally unbound: E is the taunt key and must work in free cam.
|
||||
if (kb.spaceKey.isPressed) dir += Vector3.up;
|
||||
if (kb.leftCtrlKey.isPressed) dir -= Vector3.up;
|
||||
}
|
||||
#else
|
||||
dir += transform.forward * Input.GetAxisRaw("Vertical");
|
||||
dir += transform.right * Input.GetAxisRaw("Horizontal");
|
||||
if (Input.GetKey(KeyCode.E) || Input.GetKey(KeyCode.Space)) dir += Vector3.up;
|
||||
if (Input.GetKey(KeyCode.Q) || Input.GetKey(KeyCode.LeftControl)) dir -= Vector3.up;
|
||||
if (Input.GetKey(KeyCode.Space)) dir += Vector3.up;
|
||||
if (Input.GetKey(KeyCode.LeftControl)) dir -= Vector3.up;
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The Esc overview menu (the "Overview UI" canvas in Main). Owns ALL Escape handling: Esc toggles
|
||||
/// The Esc overview menu (the "Overview UI" canvas in Main). Owns ALL Escape handling (Tab acts as an
|
||||
/// alternative to Esc): Esc toggles
|
||||
/// this panel as a modal pause overlay (gameplay suspended via <see cref="GameModeManager.SetPaused"/>);
|
||||
/// while the session browser or match results overlay is open instead, Esc closes that, and while paint
|
||||
/// mode is active Esc exits to the camera mode (Player Control, or First Person for the hunter). Buttons
|
||||
@@ -41,6 +42,9 @@ public class OverviewMenu : MonoBehaviour
|
||||
[SerializeField] private Button paintButton;
|
||||
[SerializeField] private Button firstPersonButton;
|
||||
[SerializeField] private Button freeCamButton;
|
||||
[Tooltip("Triggers the hider's manual radar ping (same as the E key) and closes the menu. Only shown " +
|
||||
"for a hider during Seek.")]
|
||||
[SerializeField] private Button tauntButton;
|
||||
|
||||
private bool _open;
|
||||
|
||||
@@ -60,6 +64,7 @@ public class OverviewMenu : MonoBehaviour
|
||||
if (paintButton) paintButton.onClick.AddListener(OnPaint);
|
||||
if (firstPersonButton) firstPersonButton.onClick.AddListener(OnFirstPerson);
|
||||
if (freeCamButton) freeCamButton.onClick.AddListener(OnFreeCam);
|
||||
if (tauntButton) tauntButton.onClick.AddListener(OnTaunt);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
@@ -70,6 +75,7 @@ public class OverviewMenu : MonoBehaviour
|
||||
if (paintButton) paintButton.onClick.RemoveListener(OnPaint);
|
||||
if (firstPersonButton) firstPersonButton.onClick.RemoveListener(OnFirstPerson);
|
||||
if (freeCamButton) freeCamButton.onClick.RemoveListener(OnFreeCam);
|
||||
if (tauntButton) tauntButton.onClick.RemoveListener(OnTaunt);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -147,6 +153,12 @@ public class OverviewMenu : MonoBehaviour
|
||||
gameMode.SetPaused(false);
|
||||
}
|
||||
|
||||
private void OnTaunt()
|
||||
{
|
||||
Close(resume: true);
|
||||
if (MatchManager.Instance) MatchManager.Instance.RequestManualPing();
|
||||
}
|
||||
|
||||
private void OnPlayerControl() => SwitchMode<PlayerControlMode>();
|
||||
private void OnPaint() => SwitchMode<PaintMode>();
|
||||
private void OnFirstPerson() => SwitchMode<FirstPersonMode>();
|
||||
@@ -174,6 +186,12 @@ public class OverviewMenu : MonoBehaviour
|
||||
if (matchResultButton)
|
||||
matchResultButton.gameObject.SetActive(matchResultScreen && matchResultScreen.HasResults);
|
||||
|
||||
// Taunt/ping only does something for a hider during Seek (the server re-gates found hiders) -
|
||||
// hide it otherwise, same pattern as the role-scoped mode buttons.
|
||||
if (tauntButton)
|
||||
tauntButton.gameObject.SetActive(gameMode.LocalPlayerIsHider && MatchManager.Instance &&
|
||||
MatchManager.Instance.LocalSubPhase == MatchManager.MatchSubPhase.Seek);
|
||||
|
||||
SetModeButton<PlayerControlMode>(playerControlButton, modes, active);
|
||||
SetModeButton<PaintMode>(paintButton, modes, active);
|
||||
SetModeButton<FirstPersonMode>(firstPersonButton, modes, active);
|
||||
@@ -191,13 +209,14 @@ public class OverviewMenu : MonoBehaviour
|
||||
button.interactable = !(active is T);
|
||||
}
|
||||
|
||||
// NOT TypingGuard-gated (GameplayKeyPressed): Esc must work even while a text field has focus.
|
||||
// Esc is NOT TypingGuard-gated: it must work even while a text field has focus.
|
||||
// Tab (alternative binding) IS gated so it stays usable for typing/field navigation.
|
||||
private static bool EscapePressed()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
return InputUtil.KeyPressedThisFrame(Key.Escape);
|
||||
return InputUtil.KeyPressedThisFrame(Key.Escape) || InputUtil.GameplayKeyPressed(Key.Tab);
|
||||
#else
|
||||
return InputUtil.KeyPressedThisFrame(KeyCode.Escape);
|
||||
return InputUtil.KeyPressedThisFrame(KeyCode.Escape) || InputUtil.GameplayKeyPressed(KeyCode.Tab);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,9 @@ public class GameModeManager : MonoBehaviour
|
||||
/// <summary>True while gameplay is suspended for a modal overlay (see <see cref="SetPaused"/>).</summary>
|
||||
public bool IsPaused => _paused;
|
||||
|
||||
/// <summary>True while the bound local avatar is a hider (drives the overview menu's taunt button).</summary>
|
||||
public bool LocalPlayerIsHider => _localRole == PlayerRole.Hider;
|
||||
|
||||
/// <summary>The active mode, or - while paused - the mode that will resume. Null in the no-player state.</summary>
|
||||
public GameMode EffectiveMode =>
|
||||
ActiveMode ?? ((_resumeIndex >= 0 && _resumeIndex < _modes.Count) ? _modes[_resumeIndex] : null);
|
||||
@@ -413,9 +416,9 @@ public class GameModeManager : MonoBehaviour
|
||||
}
|
||||
|
||||
// A hider manually pings itself onto every hunter's radar (same blip as the periodic sweep), on demand.
|
||||
// Excluded in Free Cam whose fly controls already use this key; the phase/role gate lives in MatchManager
|
||||
// (RequestManualPing no-ops outside Seek / for a found hider), so a stray press is harmless.
|
||||
if (_localRole == PlayerRole.Hider && !(ActiveMode is FreeCamMode) &&
|
||||
// Works in every mode incl. Free Cam (its fly controls no longer use Q/E); the phase/role gate lives in
|
||||
// MatchManager (RequestManualPing no-ops outside Seek / for a found hider), so a stray press is harmless.
|
||||
if (_localRole == PlayerRole.Hider &&
|
||||
InputUtil.GameplayKeyPressed(pingKey) && MatchManager.Instance)
|
||||
MatchManager.Instance.RequestManualPing();
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 443 KiB |
@@ -0,0 +1,117 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1ee44a22edb1ce47930b5ad143075a4
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 393 KiB |
@@ -0,0 +1,117 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7a95cb24662ee042ae5bba5593ca55a
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 256
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user