feat(peipei): 支持 Eye/UF 演出倍速与音效 pitch
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -388,7 +388,7 @@ namespace AibisDream.Kit
|
||||
}
|
||||
}
|
||||
|
||||
public void PlaySfx(string eventName, string audioKey = null)
|
||||
public void PlaySfx(string eventName, string audioKey = null, float pitch = 1f)
|
||||
{
|
||||
var eventPath = FormatEventPath(eventName);
|
||||
var key = string.IsNullOrEmpty(audioKey) ? eventName : audioKey;
|
||||
@@ -405,6 +405,11 @@ namespace AibisDream.Kit
|
||||
AddSfx(key, newSfx);
|
||||
}
|
||||
|
||||
if (!Mathf.Approximately(pitch, 1f))
|
||||
{
|
||||
newSfx.setPitch(Mathf.Max(0.01f, pitch));
|
||||
}
|
||||
|
||||
newSfx.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,17 @@ namespace AibisDream
|
||||
|
||||
public EyeColorState GetCurrentColorState() => _currentState;
|
||||
|
||||
public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState);
|
||||
/// <summary>Eye/UF 演出倍速(默认见 Visual Tuning → Presentation Speed)。</summary>
|
||||
public float PresentationSpeed => Mathf.Max(0.01f, visualSettings != null ? visualSettings.presentationSpeed : 1f);
|
||||
|
||||
public float ScaleDuration(float duration) => duration / PresentationSpeed;
|
||||
|
||||
public float GetEffectTransitionDuration() => ScaleDuration(visualSettings.GetDurationForState(_currentState));
|
||||
|
||||
private void PlayPresentationSfx(string eventName)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx(eventName, pitch: PresentationSpeed);
|
||||
}
|
||||
|
||||
/// <summary>仅「可想象色彩」上色时眨眼;无 autoBlink / 失焦眨眼。</summary>
|
||||
private bool ShouldBlinkForImagine()
|
||||
@@ -85,7 +95,8 @@ namespace AibisDream
|
||||
visualSettings,
|
||||
() => eyeStateEffect?.ApplyFocusedEffect(target, this),
|
||||
visualSettings.imagineEffectAtBlinkOpen,
|
||||
visualSettings.imagineBlinkGap);
|
||||
visualSettings.imagineBlinkGap,
|
||||
PresentationSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -97,6 +108,7 @@ namespace AibisDream
|
||||
|
||||
private IEnumerator RunBlurOut(EyeTarget target, float duration)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
if (target != null)
|
||||
{
|
||||
target.BlurOut(duration);
|
||||
@@ -279,12 +291,12 @@ namespace AibisDream
|
||||
|
||||
if (duration > 0.01f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/visualturn");
|
||||
PlayPresentationSfx("event:/ActionFB/visualturn");
|
||||
}
|
||||
|
||||
mouseFollowAndZoom.MoveFocusTo(
|
||||
focusTransform,
|
||||
duration,
|
||||
ScaleDuration(duration),
|
||||
focusMinBounds,
|
||||
focusMaxBounds,
|
||||
GetFocusViewportSize());
|
||||
@@ -404,7 +416,10 @@ namespace AibisDream
|
||||
[YarnCommand("EyeBlink")]
|
||||
public void EyeBlink(float duration = 0f)
|
||||
{
|
||||
EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null, restartAutoBlinkAfter: true);
|
||||
EnsureViewportOverlay()?.PlayBlink(
|
||||
duration > 0f ? duration : null,
|
||||
restartAutoBlinkAfter: true,
|
||||
presentationSpeed: PresentationSpeed);
|
||||
}
|
||||
|
||||
[YarnCommand("set_Eyetarget")]
|
||||
@@ -444,9 +459,10 @@ namespace AibisDream
|
||||
}
|
||||
|
||||
const float focusMoveDuration = 1f;
|
||||
float scaledFocusMove = ScaleDuration(focusMoveDuration);
|
||||
FocusOnTarget(target, focusMoveDuration);
|
||||
|
||||
yield return WaitForFocusMovement(focusMoveDuration);
|
||||
yield return WaitForFocusMovement(scaledFocusMove);
|
||||
|
||||
currentTarget = target;
|
||||
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
|
||||
@@ -483,7 +499,7 @@ namespace AibisDream
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return RunFocusedEffectWithPreBlink(currentTarget);
|
||||
}
|
||||
|
||||
@@ -501,7 +517,7 @@ namespace AibisDream
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return RunUnfocusedEffect(currentTarget);
|
||||
}
|
||||
|
||||
@@ -550,6 +566,7 @@ namespace AibisDream
|
||||
public IEnumerator Set_Saturation(float targetSaturation, float duration)
|
||||
{
|
||||
targetSaturation = Mathf.Clamp01(targetSaturation);
|
||||
duration = ScaleDuration(duration);
|
||||
|
||||
Sequence saturationSequence = DOTween.Sequence();
|
||||
if (!TryJoinTargetSaturation(saturationSequence, targetSaturation, duration))
|
||||
@@ -577,13 +594,14 @@ namespace AibisDream
|
||||
Debug.LogWarning("[EyeSystem] 无可用 EyeTarget Glitch tween。", this);
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(visualSettings.glitchInDuration);
|
||||
yield return new WaitForSeconds(ScaleDuration(visualSettings.glitchInDuration));
|
||||
}
|
||||
|
||||
[YarnCommand("EyeGlitch_out")]
|
||||
public void EyeGlitch_out(float duration)
|
||||
{
|
||||
TryStopUnifiedGlitch(duration > 0f ? duration : visualSettings.glitchOutDuration);
|
||||
float resolved = duration > 0f ? duration : visualSettings.glitchOutDuration;
|
||||
TryStopUnifiedGlitch(ScaleDuration(resolved));
|
||||
}
|
||||
|
||||
[YarnCommand("set_EyeColor")]
|
||||
@@ -614,11 +632,17 @@ namespace AibisDream
|
||||
memoryRender.sprite = memoryHandle.Result;
|
||||
memoryRender.gameObject.SetActive(true);
|
||||
|
||||
float fadeIn = ScaleDuration(1.5f);
|
||||
float hold = ScaleDuration(1.5f);
|
||||
float squeeze = ScaleDuration(2f);
|
||||
float fadeOut = ScaleDuration(0.5f);
|
||||
float fadeOutAt = fadeIn + hold + squeeze;
|
||||
|
||||
Sequence memorySequence = DOTween.Sequence();
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", 1.5f));
|
||||
memorySequence.AppendInterval(1.5f);
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", 2f));
|
||||
memorySequence.Insert(4.5f, memoryMaterial.DOFloat(0f, "_FullDistortionFade", 0.5f).OnComplete(() =>
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", fadeIn));
|
||||
memorySequence.AppendInterval(hold);
|
||||
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", squeeze));
|
||||
memorySequence.Insert(fadeOutAt, memoryMaterial.DOFloat(0f, "_FullDistortionFade", fadeOut).OnComplete(() =>
|
||||
{
|
||||
memoryRender.gameObject.SetActive(false);
|
||||
}));
|
||||
@@ -628,7 +652,7 @@ namespace AibisDream
|
||||
|
||||
Sequence sequence = DOTween.Sequence();
|
||||
|
||||
Sequence waveIn = CreateTargetRoundWaveSequence(1f, visualSettings.roundWaveInDuration);
|
||||
Sequence waveIn = CreateTargetRoundWaveSequence(1f, ScaleDuration(visualSettings.roundWaveInDuration));
|
||||
if (waveIn != null)
|
||||
{
|
||||
sequence.Append(waveIn);
|
||||
@@ -636,7 +660,7 @@ namespace AibisDream
|
||||
|
||||
sequence.AppendCallback(() => { EyeGlitch_out(visualSettings.glitchOutDuration); });
|
||||
|
||||
Sequence waveOut = CreateTargetRoundWaveSequence(0f, visualSettings.roundWaveOutDuration);
|
||||
Sequence waveOut = CreateTargetRoundWaveSequence(0f, ScaleDuration(visualSettings.roundWaveOutDuration));
|
||||
if (waveOut != null)
|
||||
{
|
||||
sequence.Append(waveOut);
|
||||
@@ -666,6 +690,7 @@ namespace AibisDream
|
||||
|
||||
public Tween TweenUnifiedUfWeights(float ascii, float dream, float memory, float duration)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
Sequence sequence = DOTween.Sequence();
|
||||
bool hasTween = false;
|
||||
|
||||
@@ -710,7 +735,7 @@ namespace AibisDream
|
||||
|
||||
foreach (EyeTarget target in targets)
|
||||
{
|
||||
Sequence targetGlitch = target.StartUnifiedGlitch(visualSettings.glitchInDuration);
|
||||
Sequence targetGlitch = target.StartUnifiedGlitch(ScaleDuration(visualSettings.glitchInDuration));
|
||||
if (targetGlitch == null)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -180,7 +180,10 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
|
||||
public Tween PlayBlink(float? totalDuration = null, bool restartAutoBlinkAfter = false)
|
||||
public Tween PlayBlink(
|
||||
float? totalDuration = null,
|
||||
bool restartAutoBlinkAfter = false,
|
||||
float presentationSpeed = 1f)
|
||||
{
|
||||
if (instanceMaterial == null || activeSettings == null)
|
||||
{
|
||||
@@ -189,11 +192,12 @@ namespace AibisDream
|
||||
|
||||
blinkTween?.Kill();
|
||||
|
||||
float closeDuration = activeSettings.blinkCloseDuration;
|
||||
float openDuration = activeSettings.blinkOpenDuration;
|
||||
float durationScale = 1f / Mathf.Max(0.01f, presentationSpeed);
|
||||
float closeDuration = activeSettings.blinkCloseDuration * durationScale;
|
||||
float openDuration = activeSettings.blinkOpenDuration * durationScale;
|
||||
if (totalDuration.HasValue)
|
||||
{
|
||||
float total = Mathf.Max(0.05f, totalDuration.Value);
|
||||
float total = Mathf.Max(0.05f, totalDuration.Value) * durationScale;
|
||||
closeDuration = total * 0.42f;
|
||||
openDuration = total * 0.58f;
|
||||
}
|
||||
@@ -221,7 +225,8 @@ namespace AibisDream
|
||||
EyeVisualSettings settings,
|
||||
System.Action onEffectStart,
|
||||
float effectAtOpenRatio,
|
||||
float betweenBlinkGap = 0f)
|
||||
float betweenBlinkGap = 0f,
|
||||
float presentationSpeed = 1f)
|
||||
{
|
||||
if (!ShouldPlayTransitionBlink(settings))
|
||||
{
|
||||
@@ -234,11 +239,12 @@ namespace AibisDream
|
||||
bool effectStarted = false;
|
||||
blinkCount = Mathf.Max(1, blinkCount);
|
||||
effectAtOpenRatio = Mathf.Clamp01(effectAtOpenRatio);
|
||||
float durationScale = 1f / Mathf.Max(0.01f, presentationSpeed);
|
||||
|
||||
for (int i = 0; i < blinkCount; i++)
|
||||
{
|
||||
bool isLastBlink = i == blinkCount - 1;
|
||||
Tween blink = PlayBlink();
|
||||
Tween blink = PlayBlink(presentationSpeed: presentationSpeed);
|
||||
if (blink == null)
|
||||
{
|
||||
if (isLastBlink && !effectStarted)
|
||||
@@ -252,7 +258,8 @@ namespace AibisDream
|
||||
|
||||
if (isLastBlink)
|
||||
{
|
||||
float effectDelay = settings.blinkCloseDuration + settings.blinkOpenDuration * effectAtOpenRatio;
|
||||
float effectDelay = (settings.blinkCloseDuration + settings.blinkOpenDuration * effectAtOpenRatio)
|
||||
* durationScale;
|
||||
yield return new WaitForSeconds(effectDelay);
|
||||
if (!effectStarted)
|
||||
{
|
||||
@@ -267,7 +274,7 @@ namespace AibisDream
|
||||
yield return blink.WaitForCompletion();
|
||||
if (betweenBlinkGap > 0f)
|
||||
{
|
||||
yield return new WaitForSeconds(betweenBlinkGap);
|
||||
yield return new WaitForSeconds(betweenBlinkGap * durationScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace AibisDream
|
||||
[Tooltip("Focused / imagined color state.")]
|
||||
[Range(0f, 1f)] public float colorRevealMax = 1f;
|
||||
|
||||
[Header("Presentation Speed")]
|
||||
[Tooltip("Eye/UF 演出整体倍速(等待、Tween、眨眼、关联 SFX pitch)。2.5 = 快 2.5 倍。")]
|
||||
[Min(0.01f)] public float presentationSpeed = 2.5f;
|
||||
|
||||
[Header("Transition Duration (seconds)")]
|
||||
public float imagineColorDuration = 1f;
|
||||
public float cannotImagineDuration = 1f;
|
||||
|
||||
@@ -40,6 +40,16 @@ public class UFSystem : MonoBehaviour
|
||||
memory
|
||||
}
|
||||
|
||||
private float PresentationSpeed => eyeSystem != null ? eyeSystem.PresentationSpeed : 1f;
|
||||
|
||||
private float ScaleDuration(float duration) =>
|
||||
eyeSystem != null ? eyeSystem.ScaleDuration(duration) : duration;
|
||||
|
||||
private void PlayPresentationSfx(string eventName)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx(eventName, pitch: PresentationSpeed);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
FixSystemCenter.SystemDic.Register(this);
|
||||
@@ -87,10 +97,11 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_spriteIn")]
|
||||
public IEnumerator UF_spriteIn(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
var target = ResolveSpriteTarget();
|
||||
if (target != null)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
target.ImageIn(duration);
|
||||
}
|
||||
|
||||
@@ -100,10 +111,11 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_spriteOut")]
|
||||
public IEnumerator UF_spriteOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
var target = ResolveSpriteTarget();
|
||||
if (target != null)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
target.ImageOut(duration);
|
||||
}
|
||||
|
||||
@@ -113,6 +125,7 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_AllspriteIn")]
|
||||
public IEnumerator UF_AllspriteIn(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
foreach (EyeTarget target in eyeSystem.Targets)
|
||||
{
|
||||
target.ImageIn(duration);
|
||||
@@ -124,6 +137,7 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_AllspriteOut")]
|
||||
public IEnumerator UF_AllspriteOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
foreach (EyeTarget target in eyeSystem.Targets)
|
||||
{
|
||||
target.ImageOut(duration);
|
||||
@@ -146,6 +160,7 @@ public class UFSystem : MonoBehaviour
|
||||
Debug.LogWarning("[UFSystem] UF_faceIn: face.sprite 为空(可能是 aseprite 重导入后子资源 ID 失效)。", this);
|
||||
}
|
||||
|
||||
duration = ScaleDuration(duration);
|
||||
face.gameObject.SetActive(true);
|
||||
face.DOFade(1f, duration);
|
||||
yield return new WaitForSeconds(duration);
|
||||
@@ -159,6 +174,7 @@ public class UFSystem : MonoBehaviour
|
||||
yield break;
|
||||
}
|
||||
|
||||
duration = ScaleDuration(duration);
|
||||
face.DOFade(0f, duration);
|
||||
yield return new WaitForSeconds(duration);
|
||||
face.gameObject.SetActive(false);
|
||||
@@ -167,7 +183,8 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_ImaginationEffectIn")]
|
||||
public IEnumerator UF_ImaginationEffectIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(imageVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -176,15 +193,17 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_ImaginationEffectOut")]
|
||||
public IEnumerator UF_ImaginationEffectOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(imageVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
[YarnCommand("UF_MemoryEffectIn")]
|
||||
public IEnumerator UF_MemoryEffectIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(finalVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -193,15 +212,17 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_MemoryEffectOut")]
|
||||
public IEnumerator UF_MemoryEffectOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(finalVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
[YarnCommand("UF_EyeTargetAscillIn")]
|
||||
public IEnumerator UF_EyeTargetAscillIn(float duration = 1.5f)
|
||||
{
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
TweenWeight(imageAscillVolume, 1f, duration);
|
||||
yield return new WaitForSeconds(0f);
|
||||
@@ -210,8 +231,9 @@ public class UFSystem : MonoBehaviour
|
||||
[YarnCommand("UF_EyeTargetAscillOut")]
|
||||
public IEnumerator UF_EyeTargetAscillOut(float duration = 1.5f)
|
||||
{
|
||||
duration = ScaleDuration(duration);
|
||||
TweenWeight(imageAscillVolume, 0f, duration);
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
yield return new WaitForSeconds(0f);
|
||||
}
|
||||
|
||||
@@ -251,6 +273,7 @@ public class UFSystem : MonoBehaviour
|
||||
public void UF_fightEffect()
|
||||
{
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
float loopDuration = ScaleDuration(1f);
|
||||
scaleTween = DOTween.To(() => 0f, t =>
|
||||
{
|
||||
if (imageVolume != null)
|
||||
@@ -267,7 +290,7 @@ public class UFSystem : MonoBehaviour
|
||||
{
|
||||
finalVolume.weight = Mathf.Lerp(1f, 0f, t);
|
||||
}
|
||||
}, 1f, 1f)
|
||||
}, 1f, loopDuration)
|
||||
.SetEase(Ease.InOutSine)
|
||||
.SetLoops(-1, LoopType.Yoyo);
|
||||
}
|
||||
@@ -285,15 +308,15 @@ public class UFSystem : MonoBehaviour
|
||||
while (isLoopImage)
|
||||
{
|
||||
eyeSystem.StartCoroutine(eyeSystem.SetTargetCoroutine(eyeSystem.Targets[index].name, false));
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
yield return new WaitForSeconds(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_spriteIn(0.5f));
|
||||
StartCoroutine(UF_ImaginationEffectIn(0.5f));
|
||||
eyeSystem.Targets[index].ImageIn(0.5f);
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
eyeSystem.Targets[index].ImageIn(ScaleDuration(0.5f));
|
||||
yield return new WaitForSeconds(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_ImaginationEffectOut(0.5f));
|
||||
StartCoroutine(UF_MemoryEffectIn(0.5f));
|
||||
yield return new WaitForSeconds(1f);
|
||||
eyeSystem.Targets[index].ImageOut(0.5f);
|
||||
yield return new WaitForSeconds(ScaleDuration(1f));
|
||||
eyeSystem.Targets[index].ImageOut(ScaleDuration(0.5f));
|
||||
StartCoroutine(UF_MemoryEffectOut(0.5f));
|
||||
index++;
|
||||
if (index >= eyeSystem.Targets.Count - 2)
|
||||
@@ -385,7 +408,8 @@ public class UFSystem : MonoBehaviour
|
||||
yield break;
|
||||
}
|
||||
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
|
||||
duration = ScaleDuration(duration);
|
||||
PlayPresentationSfx("event:/ActionFB/color_imagine");
|
||||
ClearUnifiedUfSpriteWeights();
|
||||
|
||||
switch (state)
|
||||
|
||||
Reference in New Issue
Block a user