[Feat] 돌발 이벤트 컷씬 추가
This commit is contained in:
parent
7d51909f0c
commit
4ae48da950
BIN
Assets/LIN/Housing Copy.unity
(Stored with Git LFS)
BIN
Assets/LIN/Housing Copy.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/LIN/ReHousing Copy.unity
(Stored with Git LFS)
Normal file
BIN
Assets/LIN/ReHousing Copy.unity
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86c6ebc5f9b48c345bd9d6f402bdc848
|
||||
guid: 5324096d5b520144d873395ac6861fe5
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
8
Assets/LIN/Resources.meta
Normal file
8
Assets/LIN/Resources.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e2ae75cada1f20448baf1ac68f1a31d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -3,17 +3,17 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class InteractionController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] LayerMask interactionLayerMask;
|
||||
[FormerlySerializedAs("housingCanvasManager")]
|
||||
[Header("UI 연동")]
|
||||
[SerializeField] HousingCanvasController housingCanvasController;
|
||||
|
||||
[FormerlySerializedAs("housingCanvasManager")] [Header("UI 연동")] [SerializeField]
|
||||
HousingCanvasController housingCanvasController;
|
||||
|
||||
[SerializeField] private InteractionAnimationPanelController interactionAnimationPanelController;
|
||||
|
||||
private SuddenEventController _suddenEventController = new SuddenEventController();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
@ -23,88 +23,98 @@ public class InteractionController : MonoBehaviour
|
||||
// 상호작용 가능한 사물 범위에 들어올 때
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if(other.gameObject.layer == LayerMask.NameToLayer("NPC"))
|
||||
if (other.gameObject.layer == LayerMask.NameToLayer("NPC"))
|
||||
{
|
||||
housingCanvasController.ShowNpcInteractionButton(() =>
|
||||
{
|
||||
GameManager.Instance.StartNPCDialogue(GamePhase.Gameplay);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (interactionLayerMask == (interactionLayerMask | (1 << other.gameObject.layer)))
|
||||
{
|
||||
ActionType interactionType = other.gameObject.GetComponent<InteractionProp>().RoutineEnter();
|
||||
if( interactionType != null )
|
||||
if (interactionType != null)
|
||||
{
|
||||
PopActionOnScreen(interactionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 사물에서 벗어날 때 UI 정리
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if(other.gameObject.layer == LayerMask.NameToLayer("NPC")) housingCanvasController.HideInteractionButton();
|
||||
|
||||
if (other.gameObject.layer == LayerMask.NameToLayer("NPC")) housingCanvasController.HideInteractionButton();
|
||||
|
||||
if (interactionLayerMask == (interactionLayerMask | (1 << other.gameObject.layer)))
|
||||
{
|
||||
housingCanvasController.HideInteractionButton();
|
||||
housingCanvasController.interactionTextsController.InitInteractionTexts();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ActionType 별로 화면에 상호작용 내용 표시, 상호작용 버튼에 이벤트 작성
|
||||
private void PopActionOnScreen(ActionType interactionType)
|
||||
{
|
||||
HousingConstants.interactions.TryGetValue(interactionType, out var interactionTexts);
|
||||
|
||||
housingCanvasController.ShowInteractionButton(interactionTexts.ActionText,interactionTexts.DescriptionText,()=>
|
||||
{
|
||||
if (PlayerStats.Instance.CanPerformByHealth(interactionType))
|
||||
{
|
||||
PlayerStats.Instance.PerformAction(interactionType);
|
||||
|
||||
if (interactionType == ActionType.Dungeon)
|
||||
housingCanvasController.ShowInteractionButton(interactionTexts.ActionText, interactionTexts.DescriptionText,
|
||||
() =>
|
||||
{
|
||||
if (PlayerStats.Instance.CanPerformByHealth(interactionType))
|
||||
{
|
||||
GameManager.Instance.ChangeToGameScene();
|
||||
PlayerStats.Instance.PerformAction(interactionType);
|
||||
|
||||
if (interactionType == ActionType.Dungeon)
|
||||
{
|
||||
GameManager.Instance.ChangeToGameScene();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameManager.Instance.PlayInteractionSound(interactionType);
|
||||
interactionAnimationPanelController.ShowAnimationPanel(interactionType,
|
||||
interactionTexts.AnimationText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GameManager.Instance.PlayInteractionSound(interactionType);
|
||||
interactionAnimationPanelController.ShowAnimationPanel(interactionType,interactionTexts.AnimationText);
|
||||
housingCanvasController.interactionTextsController.ActiveTexts(interactionTexts.LackOfHealth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
housingCanvasController.interactionTextsController.ActiveTexts(interactionTexts.LackOfHealth);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public Action SuddenEventHappen()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SuddenAfterWorkEventHappen()
|
||||
|
||||
//퇴근 후 돌발 이벤트
|
||||
private AfterWorkEventType SuddenEventCalculator()
|
||||
{
|
||||
AfterWorkEvent afterWorkEvent = _suddenEventController.SuddenEventCalculator();
|
||||
if (afterWorkEvent == AfterWorkEvent.None)
|
||||
return;
|
||||
switch (afterWorkEvent)
|
||||
var index = Random.Range(0, HousingConstants.AFTER_WORK_DENOMINATOR);
|
||||
return HousingConstants.AfterWorkEvents.GetValueOrDefault(index, AfterWorkEventType.None);
|
||||
}
|
||||
|
||||
private void SuddenAfterWorkEventHappen()
|
||||
{
|
||||
AfterWorkEventType afterWorkEventType = SuddenEventCalculator();
|
||||
Debug.Log(afterWorkEventType);
|
||||
|
||||
if (afterWorkEventType == AfterWorkEventType.None) return;
|
||||
switch (afterWorkEventType)
|
||||
{
|
||||
case AfterWorkEvent.OvertimeWork:
|
||||
case AfterWorkEventType.OvertimeWork:
|
||||
housingCanvasController.ShowSuddenEventPanel("부장님이 퇴근을 안하셔.. 야근할까?", () =>
|
||||
{
|
||||
//Todo: 컷씬과 스테이터스 변경
|
||||
housingCanvasController.HideSuddenEventPanel();
|
||||
housingCanvasController.ShowSuddenEventImage(0);
|
||||
//Todo: 스테이터스 변경
|
||||
});
|
||||
break;
|
||||
case AfterWorkEvent.TeamGathering:
|
||||
housingCanvasController.ShowSuddenEventPanel("갑자기 팀 회식이 잡혔다. 참석 하러 가자", () =>
|
||||
{
|
||||
housingCanvasController.HideSuddenEventPanel();
|
||||
});
|
||||
case AfterWorkEventType.TeamGathering:
|
||||
housingCanvasController.ShowSuddenEventPanel("갑자기 팀 회식이 잡혔다. 참석 하러 가자",
|
||||
() => { housingCanvasController.ShowSuddenEventImage(1); });
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class SuddenEventController
|
||||
{
|
||||
// 랜덤 값에 일치하는 함수를 리턴하기 위한 딕셔너리
|
||||
// AFTER_WORK_DENOMINATOR 값 확정 후에 키 값 수정
|
||||
private Dictionary<int, AfterWorkEvent> afterWorkEvents = new Dictionary<int, AfterWorkEvent>();
|
||||
public SuddenEventController()
|
||||
{
|
||||
afterWorkEvents.Add(0, AfterWorkEvent.OvertimeWork);
|
||||
afterWorkEvents.Add(1, AfterWorkEvent.TeamGathering);
|
||||
}
|
||||
|
||||
//퇴근 후 돌발 이벤트
|
||||
public AfterWorkEvent SuddenEventCalculator()
|
||||
{
|
||||
var index = Random.Range(0,HousingConstants.AFTER_WORK_DENOMINATOR);
|
||||
return afterWorkEvents.GetValueOrDefault(index, AfterWorkEvent.None);
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26ce8577425c4630903173b182839514
|
||||
timeCreated: 1745306651
|
@ -14,7 +14,10 @@ public class HousingCanvasController : MonoBehaviour
|
||||
[Header("돌발 이벤트")]
|
||||
[SerializeField] private GameObject suddenPanel;
|
||||
[SerializeField] private TMP_Text suddenText;
|
||||
[SerializeField] private GameObject[] suddenEventImages;
|
||||
|
||||
private Coroutine _autoHideCoroutine;
|
||||
|
||||
public Action OnInteractionButtonPressed;
|
||||
public Action OnSuddenButtonPressed;
|
||||
|
||||
@ -72,6 +75,7 @@ public class HousingCanvasController : MonoBehaviour
|
||||
#region 돌발 이벤트
|
||||
public void ShowSuddenEventPanel(string actText, Action onSuddenButtonPressed)
|
||||
{
|
||||
Debug.Log("call evenet panel show");
|
||||
suddenPanel.SetActive(true);
|
||||
suddenText.text = actText;
|
||||
OnSuddenButtonPressed += onSuddenButtonPressed;
|
||||
@ -84,8 +88,46 @@ public class HousingCanvasController : MonoBehaviour
|
||||
}
|
||||
public void OnSuddenConfirmButton()
|
||||
{
|
||||
suddenText.text = "";
|
||||
OnSuddenButtonPressed?.Invoke();
|
||||
}
|
||||
|
||||
public void ShowSuddenEventImage(int index)
|
||||
{
|
||||
if (_autoHideCoroutine != null) StopCoroutine(_autoHideCoroutine);
|
||||
|
||||
suddenEventImages[index].SetActive(true);
|
||||
//사운드 재생
|
||||
|
||||
_autoHideCoroutine = StartCoroutine(AutoHideSuddenImage());
|
||||
|
||||
}
|
||||
|
||||
public void HideSuddenEventImage()
|
||||
{
|
||||
foreach (var image in suddenEventImages)
|
||||
{
|
||||
image.SetActive(false);
|
||||
}
|
||||
}
|
||||
private IEnumerator AutoHideSuddenImage()
|
||||
{
|
||||
float startTime = Time.time;
|
||||
while (Time.time - startTime < 2.0f)
|
||||
{
|
||||
if (Input.touchCount > 0 || Input.GetMouseButtonDown(0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
|
||||
//패널 닫고 애니메이션 null처리
|
||||
HideSuddenEventImage();
|
||||
HideSuddenEventPanel();
|
||||
|
||||
_autoHideCoroutine = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
public enum AfterWorkEvent
|
||||
|
||||
public enum AfterWorkEventType
|
||||
{
|
||||
None,
|
||||
TeamGathering,
|
||||
@ -12,7 +13,9 @@ public enum AfterWorkEvent
|
||||
public static class HousingConstants
|
||||
{
|
||||
//돌발 이벤트 확률 계산
|
||||
public static int AFTER_WORK_DENOMINATOR = 4;
|
||||
public static int AFTER_WORK_DENOMINATOR = 2;
|
||||
//돌발 이벤트 보여줄 시간
|
||||
public static float SUDDENEVENT_IAMGE_SHOW_TIME = 3.0f;
|
||||
|
||||
|
||||
#region 상호작용 멘트
|
||||
@ -47,4 +50,11 @@ public static class HousingConstants
|
||||
AnimationText = animationText;
|
||||
}
|
||||
}
|
||||
|
||||
// 랜덤 값에 일치하는 함수를 리턴하기 위한 딕셔너리
|
||||
// AFTER_WORK_DENOMINATOR 값 확정 후에 키 값 수정
|
||||
public static readonly Dictionary<int, AfterWorkEventType> AfterWorkEvents = new Dictionary<int, AfterWorkEventType> {
|
||||
{0, AfterWorkEventType.OvertimeWork},
|
||||
{1, AfterWorkEventType.TeamGathering}
|
||||
};
|
||||
}
|
||||
|
0
Assets/LIN/Scripts/UI/SuddenEventPanelController.cs
Normal file
0
Assets/LIN/Scripts/UI/SuddenEventPanelController.cs
Normal file
11
Assets/LIN/Scripts/UI/SuddenEventPanelController.cs.meta
Normal file
11
Assets/LIN/Scripts/UI/SuddenEventPanelController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82021c35b93bcfb4885be342e5ddd363
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/LIN/Sprites/LateWork.PNG
(Stored with Git LFS)
Normal file
BIN
Assets/LIN/Sprites/LateWork.PNG
(Stored with Git LFS)
Normal file
Binary file not shown.
114
Assets/LIN/Sprites/LateWork.PNG.meta
Normal file
114
Assets/LIN/Sprites/LateWork.PNG.meta
Normal file
@ -0,0 +1,114 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccfd5bb6682e8484d8088d1a70dc9ccb
|
||||
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: 0
|
||||
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: 1
|
||||
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: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
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: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/LIN/Sprites/TeamGathering.png
(Stored with Git LFS)
Normal file
BIN
Assets/LIN/Sprites/TeamGathering.png
(Stored with Git LFS)
Normal file
Binary file not shown.
114
Assets/LIN/Sprites/TeamGathering.png.meta
Normal file
114
Assets/LIN/Sprites/TeamGathering.png.meta
Normal file
@ -0,0 +1,114 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 516de2d9e0014d74bbec3c4a248d927c
|
||||
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: 0
|
||||
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: 1
|
||||
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: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
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: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
x
Reference in New Issue
Block a user