PlayerVisual Customization
This commit is contained in:
@@ -10,7 +10,7 @@ PrefabInstance:
|
||||
m_Modifications:
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
value: -0.8480131
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
@@ -18,23 +18,23 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
value: 0.0050586592
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
value: 0.9627553
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
value: 0.2703743
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
@@ -42,7 +42,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
value: 31.373
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -8679921383154817045, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
@@ -59,7 +59,15 @@ PrefabInstance:
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 6268899434028451206}
|
||||
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 6551637819182465063}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
--- !u!137 &4078132247542626195 stripped
|
||||
SkinnedMeshRenderer:
|
||||
m_CorrespondingSourceObject: {fileID: 6799780747793633427, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
m_PrefabInstance: {fileID: 7405539825535706880}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &7639418806218873425 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 2b8eab5f9e0c5c649a40b323ec6d99db, type: 3}
|
||||
@@ -87,3 +95,59 @@ Animator:
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!114 &6551637819182465063
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7639418806218873425}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 93c4f218e1a930f4f86c5a26eb731a70, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::PlayerVisual
|
||||
_customization:
|
||||
Colors: []
|
||||
_references:
|
||||
Player: {fileID: 0}
|
||||
Anim: {fileID: 6268899434028451206}
|
||||
Renderers:
|
||||
- {fileID: 4078132247542626195}
|
||||
Materials:
|
||||
- {fileID: 2100000, guid: b44589781f5e0e04c8ca5f190db42ada, type: 2}
|
||||
- {fileID: 2100000, guid: 0c8bf99957763684b9f83d1f8b070549, type: 2}
|
||||
- {fileID: 2100000, guid: 27e2a9836de184e4b9ac07a0099ff283, type: 2}
|
||||
_playerAnimationStateMapper:
|
||||
- PlayerState: 0
|
||||
AnimatorState: move
|
||||
BlockingState:
|
||||
Trigger: trigger_move
|
||||
- PlayerState: 1
|
||||
AnimatorState: move
|
||||
BlockingState:
|
||||
Trigger: trigger_move
|
||||
- PlayerState: 2
|
||||
AnimatorState: jump
|
||||
BlockingState: fall
|
||||
Trigger: trigger_jump
|
||||
- PlayerState: 3
|
||||
AnimatorState: fall
|
||||
BlockingState: jump
|
||||
Trigger: trigger_fall
|
||||
- PlayerState: 4
|
||||
AnimatorState: stunned
|
||||
BlockingState:
|
||||
Trigger: trigger_stun
|
||||
- PlayerState: 5
|
||||
AnimatorState: die
|
||||
BlockingState:
|
||||
Trigger: trigger_die
|
||||
- PlayerState: 6
|
||||
AnimatorState: loose
|
||||
BlockingState:
|
||||
Trigger: trigger_loose
|
||||
- PlayerState: 7
|
||||
AnimatorState: win
|
||||
BlockingState:
|
||||
Trigger: trigger_win
|
||||
|
||||
@@ -72,7 +72,6 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Player
|
||||
_settings:
|
||||
Type: 0
|
||||
Speed: 18
|
||||
JumpForce: 8
|
||||
RotationSpeed: 10
|
||||
@@ -80,6 +79,7 @@ MonoBehaviour:
|
||||
GroundLayer:
|
||||
serializedVersion: 2
|
||||
m_Bits: 64
|
||||
ExtraForcesDrag: 8
|
||||
StateLogs: 0
|
||||
_references:
|
||||
Controller: {fileID: 2782052458842062556}
|
||||
@@ -88,12 +88,8 @@ MonoBehaviour:
|
||||
CurrentState: 0
|
||||
IsPaused: 0
|
||||
IsGrounded: 0
|
||||
IsGravitySuspended: 0
|
||||
VerticalVelocity: 0
|
||||
HorizontalVelocity: {x: 0, y: 0}
|
||||
ExtraVelocity: {x: 0, y: 0, z: 0}
|
||||
GroundVelocity: {x: 0, y: 0, z: 0}
|
||||
GroundTransform: {fileID: 0}
|
||||
Velocity: {x: 0, y: 0, z: 0}
|
||||
Ground: {fileID: 0}
|
||||
--- !u!1001 &3220452639741296132
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -102,6 +98,10 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 3550202301939281011}
|
||||
m_Modifications:
|
||||
- target: {fileID: 6551637819182465063, guid: dce89e082ea7b9c48ab0fe0f0d38f147, type: 3}
|
||||
propertyPath: _references.Player
|
||||
value:
|
||||
objectReference: {fileID: 4344386118898155814}
|
||||
- target: {fileID: 7011957565800906987, guid: dce89e082ea7b9c48ab0fe0f0d38f147, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
|
||||
@@ -1466,32 +1466,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: effa7acb4388bcf4381294d9134d23f6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Springboqrd
|
||||
_force: 50
|
||||
_duration: 0.8
|
||||
_curve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 1
|
||||
inSlope: -1.4231426
|
||||
outSlope: -1.4231426
|
||||
tangentMode: 0
|
||||
weightedMode: 3
|
||||
inWeight: 0
|
||||
outWeight: 0.58424336
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0.0060086255
|
||||
outSlope: 0.0060086255
|
||||
tangentMode: 0
|
||||
weightedMode: 3
|
||||
inWeight: 0.39625585
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
_force: 30
|
||||
_onJump:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
@@ -1506,7 +1481,7 @@ MonoBehaviour:
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
m_CallState: 0
|
||||
--- !u!4 &388514092 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 3389128502618183018, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
@@ -2625,64 +2600,6 @@ Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 553282937401526563, guid: b5c21a868c96fd847b25cfd6700dcab9, type: 3}
|
||||
m_PrefabInstance: {fileID: 1002917971}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1058476794 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 5095245121602118741, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
m_PrefabInstance: {fileID: 8321447544296836963}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!95 &1058476796 stripped
|
||||
Animator:
|
||||
m_CorrespondingSourceObject: {fileID: 8813195164535651202, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
m_PrefabInstance: {fileID: 8321447544296836963}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &1058476797
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1058476794}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 93c4f218e1a930f4f86c5a26eb731a70, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::PlayerVisual
|
||||
_references:
|
||||
Player: {fileID: 3488783991102291675}
|
||||
Anim: {fileID: 1058476796}
|
||||
_playerAnimationStateMapper:
|
||||
- PlayerState: 0
|
||||
AnimatorState: move
|
||||
BlockingState:
|
||||
Trigger: trigger_move
|
||||
- PlayerState: 1
|
||||
AnimatorState: move
|
||||
BlockingState:
|
||||
Trigger: trigger_move
|
||||
- PlayerState: 2
|
||||
AnimatorState: jump
|
||||
BlockingState: fall
|
||||
Trigger: trigger_jump
|
||||
- PlayerState: 3
|
||||
AnimatorState: fall
|
||||
BlockingState: jump
|
||||
Trigger: trigger_fall
|
||||
- PlayerState: 4
|
||||
AnimatorState: stunned
|
||||
BlockingState:
|
||||
Trigger: trigger_stun
|
||||
- PlayerState: 5
|
||||
AnimatorState: die
|
||||
BlockingState:
|
||||
Trigger: trigger_die
|
||||
- PlayerState: 6
|
||||
AnimatorState: loose
|
||||
BlockingState:
|
||||
Trigger: trigger_loose
|
||||
- PlayerState: 7
|
||||
AnimatorState: win
|
||||
BlockingState:
|
||||
Trigger: trigger_win
|
||||
--- !u!1 &1080756049
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5985,17 +5902,6 @@ PrefabInstance:
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: dfb5576e46653d9419747f6c7e441ee4, type: 3}
|
||||
--- !u!114 &3488783991102291675 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 4344386118898155814, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
m_PrefabInstance: {fileID: 8321447544296836963}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e2481070b28cbc44e84c75778af5844f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Player
|
||||
--- !u!1001 &5497189567890878294
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6279,10 +6185,7 @@ PrefabInstance:
|
||||
- targetCorrespondingSourceObject: {fileID: 3389128502618183018, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 1080756050}
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 5095245121602118741, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 1058476797}
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 6c5886a0ad4a20042ad31e7317391355, type: 3}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
|
||||
@@ -302,6 +302,9 @@ public class Player : MonoBehaviour
|
||||
_state.Ground = currentGround;
|
||||
_lastPlatformPosition = _state.Ground.position;
|
||||
_lastPlatformRotation = _state.Ground.rotation;
|
||||
|
||||
_impulseForce.y = _platformVelocity.y = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -342,9 +345,32 @@ public class Player : MonoBehaviour
|
||||
private void SetGravity(float deltaTime)
|
||||
{
|
||||
if (_state.IsGrounded && _state.Velocity.y < 0)
|
||||
{
|
||||
_state.Velocity.y = STICK_FORCE;
|
||||
}
|
||||
else if (_persistentForce.y <= 0)
|
||||
_state.Velocity.y = Mathf.Max(_state.Velocity.y + GRAVITY * deltaTime, MAX_GRAVITY);
|
||||
{
|
||||
if (_platformVelocity.y > 0)
|
||||
{
|
||||
_platformVelocity.y += GRAVITY * deltaTime;
|
||||
|
||||
if (_platformVelocity.y < 0)
|
||||
_state.Velocity.y += _platformVelocity.y;
|
||||
}
|
||||
else if (_impulseForce.y > 0)
|
||||
{
|
||||
_impulseForce.y += GRAVITY * deltaTime;
|
||||
|
||||
if (_impulseForce.y < 0)
|
||||
_state.Velocity.y += _impulseForce.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_state.Velocity.y += GRAVITY * deltaTime;
|
||||
}
|
||||
|
||||
_state.Velocity.y = Mathf.Max(_state.Velocity.y, MAX_GRAVITY);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetVelocity(float deltaTime)
|
||||
@@ -398,19 +424,25 @@ public class Player : MonoBehaviour
|
||||
|
||||
private void SetMovement(float deltaTime)
|
||||
{
|
||||
Vector3 totalVelocity = _state.Velocity + _impulseForce + _persistentForce + _platformVelocity;
|
||||
_references.Controller.Move(totalVelocity * deltaTime);
|
||||
Vector3 velocity = _state.Velocity + _impulseForce + _persistentForce + _platformVelocity;
|
||||
_references.Controller.Move(velocity * deltaTime);
|
||||
|
||||
// Decay impulse force
|
||||
_impulseForce = Vector3.MoveTowards(_impulseForce, Vector3.zero,
|
||||
_settings.ExtraForcesDrag * deltaTime);
|
||||
Vector3 impulseForce = Vector3.MoveTowards(_impulseForce, Vector3.zero, _settings.ExtraForcesDrag * deltaTime);
|
||||
impulseForce.y = _impulseForce.y;
|
||||
_impulseForce = impulseForce;
|
||||
|
||||
// Decay inherited platform velocity — reset when back on ground
|
||||
if (_state.IsGrounded)
|
||||
{
|
||||
_platformVelocity = Vector3.zero;
|
||||
}
|
||||
else
|
||||
_platformVelocity = Vector3.MoveTowards(_platformVelocity, Vector3.zero,
|
||||
_settings.ExtraForcesDrag * deltaTime);
|
||||
{
|
||||
Vector3 platformVelocity = Vector3.MoveTowards(_platformVelocity, Vector3.zero, _settings.ExtraForcesDrag * deltaTime);
|
||||
platformVelocity.y = _platformVelocity.y;
|
||||
_platformVelocity = platformVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetState()
|
||||
|
||||
@@ -3,11 +3,19 @@ using UnityEngine;
|
||||
|
||||
public class PlayerVisual : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
private class Customization
|
||||
{
|
||||
[ColorUsage(false, true)] public Color[] Colors;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class References
|
||||
{
|
||||
public Player Player;
|
||||
public Animator Anim;
|
||||
public Renderer[] Renderers;
|
||||
public Material[] Materials;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
@@ -19,15 +27,20 @@ public class PlayerVisual : MonoBehaviour
|
||||
public string Trigger;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Customization _customization;
|
||||
|
||||
[SerializeField]
|
||||
private References _references;
|
||||
|
||||
[SerializeField]
|
||||
private PlayerAnimationStateMapper[] _playerAnimationStateMapper;
|
||||
|
||||
private const string PP_CUSTOM = "CustomPlayer";
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
LoadCustom();
|
||||
}
|
||||
|
||||
void Update()
|
||||
@@ -35,8 +48,54 @@ public class PlayerVisual : MonoBehaviour
|
||||
UpdateAnimation();
|
||||
}
|
||||
|
||||
public void RandomizeCustom()
|
||||
{
|
||||
Debug.Log("randomize");
|
||||
}
|
||||
|
||||
private void SetCustom()
|
||||
{
|
||||
foreach (Renderer rend in _references.Renderers)
|
||||
{
|
||||
foreach (Material mat in rend.materials)
|
||||
{
|
||||
Material sourceMat = _references.Materials.FirstOrDefault(m => mat.name.StartsWith(m.name));
|
||||
|
||||
if (sourceMat)
|
||||
{
|
||||
Color col = _customization.Colors[System.Array.IndexOf(_references.Materials, sourceMat)];
|
||||
|
||||
if (!mat.IsKeywordEnabled("_EMISSION"))
|
||||
mat.color = col;
|
||||
else
|
||||
mat.SetColor("_EmissionColor", col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadCustom()
|
||||
{
|
||||
if (!PlayerPrefs.HasKey(PP_CUSTOM))
|
||||
return;
|
||||
|
||||
string json = PlayerPrefs.GetString(PP_CUSTOM);
|
||||
_customization = JsonUtility.FromJson<Customization>(json);
|
||||
|
||||
SetCustom();
|
||||
}
|
||||
|
||||
private void SaveCustom()
|
||||
{
|
||||
string json = JsonUtility.ToJson(_customization);
|
||||
PlayerPrefs.SetString(PP_CUSTOM, json);
|
||||
}
|
||||
|
||||
private void UpdateAnimation()
|
||||
{
|
||||
if (!_references.Player)
|
||||
return;
|
||||
|
||||
if (_references.Anim.IsInTransition(0))
|
||||
return;
|
||||
|
||||
@@ -61,4 +120,17 @@ public class PlayerVisual : MonoBehaviour
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color ShiftHue(Color color, float hueShift)
|
||||
{
|
||||
Color.RGBToHSV(color, out float h, out float s, out float v);
|
||||
|
||||
h += hueShift / 360f;
|
||||
h = Mathf.Repeat(h, 1f);
|
||||
|
||||
Color result = Color.HSVToRGB(h, s, v);
|
||||
result.a = color.a;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ using UnityEngine.Events;
|
||||
|
||||
public class Springboard : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float _force = 60;
|
||||
[SerializeField] private float _duration = .4f;
|
||||
[SerializeField] private AnimationCurve _curve = AnimationCurve.EaseInOut(0, 1, 1, 0);
|
||||
[SerializeField] private float _force = 20;
|
||||
[SerializeField] private UnityEvent _onJump;
|
||||
|
||||
void OnTriggerEnter(Collider col)
|
||||
@@ -13,7 +11,7 @@ public class Springboard : MonoBehaviour
|
||||
if (Player.Instance && col.gameObject == Player.Instance.gameObject)
|
||||
{
|
||||
Debug.Log("Player triggered springboard");
|
||||
//Player.Instance.AddExtraForce(transform.up * _force, true, _duration, _curve);
|
||||
Player.Instance.AddForce(transform.up * _force);
|
||||
_onJump?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user