Created
August 19, 2020 06:14
-
-
Save sathyarajshetigar/07c75ca988ee6a062f3d98011e4a8070 to your computer and use it in GitHub Desktop.
UIPlayer.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma warning disable 0649 | |
| using System; | |
| using System.Collections; | |
| using System.Collections.Generic; | |
| using System.Text; | |
| using TMPro; | |
| using UnityEngine; | |
| using UnityEngine.UI; | |
| using UnityEngine.XR; | |
| using VivoxUnity; | |
| namespace SkipBo | |
| { | |
| [Serializable] | |
| public class UIPlayer : MonoBehaviour | |
| { | |
| [SerializeField] | |
| private GameObject playerRoot; | |
| [SerializeField] | |
| private GameObject timerImage; | |
| [SerializeField] | |
| private TextMeshProUGUI nameLabel; | |
| [SerializeField] | |
| private TextMeshProUGUI debugHandCardsText; | |
| [SerializeField] | |
| private TextMeshProUGUI debugStockCardsText; | |
| [SerializeField] | |
| private TextMeshProUGUI stockPileCountLabel; | |
| [SerializeField] | |
| private Image stockPileCountLabelAnimationParticle; | |
| [SerializeField] | |
| private Image profileImage; | |
| [SerializeField] | |
| private RectTransform handCardsParent; | |
| [SerializeField] | |
| private RectTransform[] handCardsRects; | |
| [SerializeField] | |
| private RectTransform discardPileParent; | |
| [SerializeField] | |
| private RectTransform[] discardPileRects; | |
| [SerializeField] | |
| private IjsUiFramework.UITransparentButton[] discardPileColliders; | |
| [SerializeField] | |
| private RectTransform stockPileTopCardParent; | |
| [Header("Use this only for local player")] | |
| [SerializeField] | |
| private GameObject turnTimer; | |
| [SerializeField] | |
| private TextMeshProUGUI turnTimerLabel; | |
| [Header("Use this only for opponent player")] | |
| [SerializeField] | |
| private Image playerPanelBG; | |
| [SerializeField] | |
| private Color playerPanelBGDefaultColor; | |
| [SerializeField] | |
| private Color playerPanelBGTurnColor; | |
| [SerializeField] | |
| private GameObject chatBubble; | |
| [SerializeField] | |
| private TextMeshProUGUI chatBubbleText; | |
| [SerializeField] | |
| private GameObject _voiceDetectedIcon; | |
| [SerializeField] | |
| private Image _muteIcon; | |
| [SerializeField] | |
| private Sprite _muteIconSprite, _unmuteIconSprite; | |
| private UICard stockPileCard; // top card of stock pile | |
| private Player player; | |
| private List<UICard> handCards = new List<UICard>(); // flipped inwards. Dummy cards showing total hand count | |
| private List<UICard> discardPile = new List<UICard>(); // ui cards of drop pile | |
| private readonly Vector2 vecor2Zero = new Vector2(0, 0); | |
| private readonly Vector2 vecor2One = new Vector2(1, 1); | |
| private readonly Vector2 LOCALPLAYERCARDSCALE = new Vector2(0.4f, 0.4f); | |
| private readonly Vector2 OPPONENTPLAYERCARDSCALE = new Vector2(0.3f, 0.3f); | |
| public static Vector2 LOCALPLAYERSTOCKPILECARDSCALE = new Vector2(0.5f, 0.5f); | |
| private readonly Vector2 OPPONENTPLAYERSTOCKPILECARDSCALE = new Vector2(0.3f, 0.3f); | |
| private readonly Vector2 OPPONENTPLAYERDISCARDPILECARDSCALE = new Vector2(0.25f, 0.25f); | |
| private const float AICARDTWEENSPEED = 0.5f; | |
| private WaitForSeconds reArrageCardWaitDelay = new WaitForSeconds(0.03f);//caching helps avoid GC | |
| private int _seatID; | |
| private bool _micMuted; | |
| private IParticipant _participant; | |
| float duckTime; | |
| //Properties | |
| internal int id => player?.id ?? -1; | |
| internal string playfabID => player?.playerProfile.playFabID ?? string.Empty; | |
| internal int seatID => _seatID; | |
| internal bool isLocalPlayer => player?.isLocalPlayer ?? false; | |
| private void Awake() | |
| { | |
| ToggleTurnTimer(false); | |
| if (turnTimer != null) | |
| turnTimer.SetActive(false); | |
| HideChatBubble(); | |
| duckTime = Time.time; | |
| HideMicIcon(); | |
| } | |
| internal void ToggleTurnTimer(bool show) | |
| { | |
| // Game.Log($"ToggleTurnTimer {show} id {id}"); | |
| if (this != null) | |
| timerImage?.SetActive(show); | |
| } | |
| internal void ToggleTurnTimerWithText(bool show) | |
| { | |
| // Game.Log($"ToggleTurnTimerWithText {show} id {id}"); | |
| if (this != null) | |
| timerImage?.SetActive(show); | |
| if (turnTimer != null) | |
| turnTimer.SetActive(show); | |
| } | |
| internal void ToggleVisibility(bool show) | |
| { | |
| playerRoot?.SetActive(show); | |
| } | |
| /// <summary> | |
| /// Constructor alternative. called when the Player.cs object is created | |
| /// </summary> | |
| /// <param name="player"></param> | |
| internal void PreparePlayer(Player p, int seatID, bool createProfile) | |
| { | |
| if (player != null) | |
| { | |
| player.CancelAsyncTasks(); | |
| RemoveListeners(); | |
| } | |
| player = p; | |
| _seatID = seatID; | |
| Game.Log($"PreparePlayer createProfile {createProfile} _micMuted {_micMuted} _participant == null? {_participant == null}"); | |
| player.onCardsAddedToHandEvent += onCardsAddedToHand; | |
| player.onCardsAddedToStockPileEvent += onCardsAddedToStockPile; | |
| //player.onValidBuildPileDropEvent += onValidBuildPileDrop; | |
| player.onMyTurnEndEvent += onMyTurnEnd; | |
| player.onMyTurnBeginEvent += onMyTurnBegin; | |
| //vivox | |
| if (createProfile) | |
| { | |
| if (PlayFabManager.instance?.useVivoxChat == false || Game.playMode != PlayModes.OnlinePrivate || player.isAI || VivoxVoiceManager.Instance?.hasMicPermission == false) | |
| { | |
| HideMicIcon(); | |
| } | |
| else | |
| { | |
| Game.Log($"processing vivox"); | |
| VivoxVoiceManager.OnSpeechDetectedEvent += OnPlayerVoiceDetected; | |
| VivoxVoiceManager.OnParticipantAddedEvent += OnParticipantAdded; | |
| VivoxVoiceManager.OnParticipantRemovedEvent += OnParticipantRemoved; | |
| _voiceDetectedIcon.SetActive(false); | |
| _micMuted = false; | |
| VivoxPlayerData vivoxPlayerData = VivoxVoiceManager.Instance.GetVivoxPlayerData(playfabID); | |
| Game.Log($"processing vivox vivoxPlayerData? {vivoxPlayerData == null} playfabID {playfabID} playerName {player.playerProfile.playerName}"); | |
| if (vivoxPlayerData != null) | |
| { | |
| _participant = vivoxPlayerData.participant; | |
| _micMuted = vivoxPlayerData.isMuted; | |
| Game.Log($"processing vivox _micMuted? {_micMuted}"); | |
| if (_micMuted) | |
| { | |
| if (isLocalPlayer) | |
| VivoxVoiceManager.Instance.ToggleMuteLocalPlayer(_micMuted); | |
| else | |
| VivoxVoiceManager.Instance.ToggleMutePlayer(_participant, id, _micMuted); | |
| } | |
| _muteIcon.gameObject.SetActive(true); | |
| } | |
| UpdateMuteMicSprite(); | |
| } | |
| } | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| { | |
| if (Game.isOnlineGame) | |
| player.onOnlineGameForceDiscardEvent += OnOnlineGameForceDiscard; | |
| player.onUndoEvent += onUndo; | |
| } | |
| else if (player.playerType == PlayerType.Opponent) | |
| { | |
| player.onValidAIDiscardPileDropEvent += onValidAIDiscardPileDrop; | |
| player.onCardsAddedToNetworkPlayersStockPileEvent += OnCardsAddedToNetworkPlayersStockPile; | |
| //player.onCardsAddedToNetworkPlayersHandEvent += OnCardsAddedToNetworkPlayersHand; | |
| } | |
| //Hide all hand cards for opponent players | |
| if (player.playerType == PlayerType.Opponent) | |
| { | |
| int handCardsRectsLength = handCardsRects.Length; | |
| for (int i = 0; i < handCardsRectsLength; i++) handCardsRects[i].gameObject.SetActive(false); | |
| } | |
| UpdateStockPileCardsCountText(); | |
| stockPileCountLabelAnimationParticle.rectTransform.localScale = vecor2Zero; | |
| debugHandCardsText.gameObject.SetActive(Game.showDebugUI); | |
| debugStockCardsText.gameObject.SetActive(Game.showDebugUI); | |
| if (createProfile) | |
| { | |
| CreatePlayerProfile(); | |
| } | |
| } | |
| internal void HideMicIcon() | |
| { | |
| _voiceDetectedIcon.SetActive(false); | |
| _muteIcon.gameObject.SetActive(false); | |
| } | |
| private void UpdateMuteMicSprite() | |
| { | |
| _muteIcon.sprite = _micMuted ? _unmuteIconSprite : _muteIconSprite; | |
| } | |
| public void CacheVivoxPlayer(IParticipant participant) | |
| { | |
| Game.Log($"CacheVivoxPlayer {participant.Account.DisplayName}", LogType.Log, Color.green); | |
| _participant = participant; | |
| // _micMuted = false; | |
| //if (isLocalPlayer) | |
| // _micMuted = _participant.LocalMute; | |
| //else | |
| _micMuted = false; | |
| VivoxPlayerData vivoxPlayerData = VivoxVoiceManager.Instance.GetVivoxPlayerData(participant.ParticipantId); | |
| if (vivoxPlayerData != null) | |
| { | |
| _micMuted = vivoxPlayerData.isMuted; | |
| if (_micMuted) | |
| { | |
| if (isLocalPlayer) | |
| VivoxVoiceManager.Instance.ToggleMuteLocalPlayer(_micMuted); | |
| else | |
| VivoxVoiceManager.Instance.ToggleMutePlayer(_participant, id, _micMuted); | |
| } | |
| } | |
| Game.Log($"CacheVivoxPlayer _micMuted {_micMuted} DisplayName {_participant.Account.DisplayName} LocalMute {_participant.LocalMute} IsMutedForAll {_participant.IsMutedForAll}", LogType.Log, Color.green); | |
| UpdateMuteMicSprite(); | |
| _voiceDetectedIcon.SetActive(false); | |
| _muteIcon.gameObject.SetActive(true); | |
| } | |
| public void ClearCachedVivoxPlayer() | |
| { | |
| _participant = null; | |
| UpdateMuteMicSprite(); | |
| HideMicIcon(); | |
| } | |
| public void ToggleMuteMic() | |
| { | |
| _micMuted = !_micMuted; | |
| if (isLocalPlayer) | |
| VivoxVoiceManager.Instance.ToggleMuteLocalPlayer(_micMuted); | |
| else | |
| VivoxVoiceManager.Instance.ToggleMutePlayer(_participant, id, _micMuted); | |
| UpdateMuteMicSprite(); | |
| if (_micMuted) | |
| _voiceDetectedIcon.SetActive(false); | |
| } | |
| private void OnPlayerVoiceDetected(string username, ChannelId channel, bool value, double audioEnergy) | |
| { | |
| if (username.Equals(player.playerProfile.playFabID)) | |
| { | |
| if (!_micMuted) | |
| { | |
| _voiceDetectedIcon.SetActive(value); | |
| if (value) | |
| _muteIcon.gameObject.SetActive(true); | |
| //if (player.isLocalPlayer) | |
| //{ | |
| // Game.Log($"Deteched speech {audioEnergy} detected {value}"); | |
| // // if (Time.time >= duckTime + 1f) | |
| // { | |
| // duckTime = Time.time; | |
| // SoundManager.instance.DuckAudio(value);// && audioEnergy > 0.3f); | |
| // } | |
| //} | |
| } | |
| else | |
| { | |
| _voiceDetectedIcon.SetActive(false); | |
| _muteIcon.gameObject.SetActive(true); | |
| } | |
| } | |
| } | |
| private void OnParticipantAdded(string username, ChannelId channel, IParticipant participant) | |
| { | |
| if (username.Equals(player.playerProfile.playFabID)) | |
| CacheVivoxPlayer(participant); | |
| } | |
| private void OnParticipantRemoved(string username, ChannelId channel, IParticipant participant) | |
| { | |
| if (username.Equals(player.playerProfile.playFabID)) | |
| ClearCachedVivoxPlayer(); | |
| } | |
| private void CreatePlayerProfile() | |
| { | |
| nameLabel.SetText(player.playerName.Split()[0]); | |
| if (string.IsNullOrWhiteSpace(player.playerProfile.avatarURL)) | |
| { | |
| if (Game.isOnlineGame && player.isAI) | |
| { | |
| Game.Log($"CreatePlayerProfile avatarID {player.playerProfile.avatarID} lastGamesGhost {player.lastGamesGhost} total avatars {IjsUiFramework.GameSkinData.gameSkin.currentGameData.guestAvatars.Length}"); | |
| //If playerprofile exists in last game then use the same profile | |
| if (!player.lastGamesGhost && string.IsNullOrWhiteSpace(player.playerProfile.playFabID) && profileImage != null) | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.onlineFakePlayerAvatars[player.playerProfile.avatarID]; | |
| else | |
| { | |
| if (profileImage != null) | |
| { | |
| if (player.lastGamesGhost && string.IsNullOrWhiteSpace(player.playerProfile.playFabID)) | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.onlineFakePlayerAvatars[player.playerProfile.avatarID]; | |
| else | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.guestAvatars[player.playerProfile.avatarID]; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (profileImage != null) | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.guestAvatars[player.playerProfile.avatarID]; | |
| } | |
| } | |
| else | |
| { | |
| if (player != null && player.playerProfile != null) | |
| { | |
| PlayerProfile.GetProfileImage(player.playerProfile.playFabID, player.playerProfile.avatarURL, (sprite) => | |
| { | |
| if (player != null && player.playerProfile != null) | |
| { | |
| if (sprite != null && profileImage != null) | |
| profileImage.sprite = sprite; | |
| else//incase if facebook sprite fails to load | |
| { | |
| int index = player?.playerProfile?.avatarID ?? 0; | |
| if (index < 0) index = 0; | |
| if (Game.isOnlineGame && player.isAI && profileImage != null) | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.onlineFakePlayerAvatars[index]; | |
| else | |
| { | |
| if (profileImage != null) | |
| profileImage.sprite = IjsUiFramework.GameSkinData.gameSkin.currentGameData.guestAvatars[index]; | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| } | |
| internal void ShowChatMessage(string message) | |
| { | |
| if (chatBubble) | |
| { | |
| //chatBubble.transform.localScale = Vector3.zero; | |
| chatBubble.SetActive(true); | |
| if (message.Length > 20) | |
| message = $"{message.Truncate(20)}..."; | |
| chatBubbleText.SetText(message); | |
| //LeanTween.value(chatBubble, (Vector3 value) => chatBubble.transform.localScale = value, Vector3.zero, Vector3.one, 0.1f).setOnComplete(() => | |
| //{ | |
| // Canvas.ForceUpdateCanvases(); | |
| // chatBubbleText.Rebuild(CanvasUpdate.PreRender); | |
| //}); | |
| CancelInvoke("HideChatBubble"); | |
| Invoke("HideChatBubble", 2f); | |
| } | |
| } | |
| private void HideChatBubble() | |
| { | |
| if (chatBubble) | |
| { | |
| chatBubble.SetActive(false); | |
| //LeanTween.value(chatBubble, (Vector2 value) => chatBubble.transform.localScale = value, Vector3.one, Vector3.zero, 0.1f).setOnComplete(() => | |
| //{ | |
| // chatBubble.SetActive(false); | |
| //}); | |
| } | |
| } | |
| /// <summary> | |
| /// On undo re-parent cards to UIPlayer | |
| /// </summary> | |
| /// <param name="card"></param> | |
| /// <param name="cardDragSourceType"></param> | |
| /// <param name="buildPileIndex"></param> | |
| private void onUndo(Card card, CardDragSourceType cardDragSourceType, int buildPileIndex) | |
| { | |
| UICard uiCard = SkipBoGameManager.instance.GetTopUICardFromTheBuildPile(buildPileIndex, true); | |
| const float RESETSPEED = 0.2f; | |
| switch (cardDragSourceType) | |
| { | |
| case CardDragSourceType.DiscardPile: | |
| if (uiCard != null) | |
| { | |
| ReturnCardToDiscardPile(uiCard); | |
| Game.Log($"UIPlayer.cs onUndo card.discardPileIndex {card.discardPileIndex}"); | |
| TogglePlayerCardsTouch(false); | |
| uiCard.SetParentAndUpdatePosition(discardPileRects[card.discardPileIndex], vecor2Zero, true, RESETSPEED, false, LeanTweenType.easeOutCirc); | |
| uiCard.TweenScale(LOCALPLAYERCARDSCALE, RESETSPEED, (c) => | |
| { | |
| if (card.isSkipBoCard) card.UpdateSkipBoCardValue(0, true); | |
| uiCard.ToggleInteractive(true); | |
| TogglePlayerCardsTouch(true); | |
| }); | |
| ReArrangeDiscardPiles(uiCard.card.discardPileIndex, 0.5f, true); | |
| } | |
| //else | |
| // throw new Exception($"requested card not found in the build pile {card.ToString()}"); | |
| break; | |
| case CardDragSourceType.Hand: | |
| if (uiCard != null) | |
| { | |
| InsertCardsToHand(uiCard, card.handPileIndex); | |
| TogglePlayerCardsTouch(false); | |
| uiCard.SetParentAndUpdatePosition(handCardsRects[card.handPileIndex], vecor2Zero, true, RESETSPEED, false, LeanTweenType.easeOutCirc); | |
| uiCard.TweenScale(LOCALPLAYERCARDSCALE, RESETSPEED, (c) => | |
| { | |
| if (card.isSkipBoCard) card.UpdateSkipBoCardValue(0, true); | |
| StartCoroutine(ReArrangeHandCards(UIDropCell.CellType.BuildPile, true)); | |
| TogglePlayerCardsTouch(true); | |
| }); | |
| } | |
| //else | |
| // throw new Exception($"requested card not found in the build pile {card.ToString()}"); | |
| break; | |
| case CardDragSourceType.StockPile: | |
| if (uiCard != null) | |
| { | |
| uiCard.SetParentAndUpdatePosition(stockPileTopCardParent, vecor2Zero, true, RESETSPEED, true, LeanTweenType.easeOutCirc); | |
| uiCard.TweenScale(LOCALPLAYERSTOCKPILECARDSCALE, RESETSPEED, (c) => | |
| { | |
| if (card.isSkipBoCard) card.UpdateSkipBoCardValue(0, false); | |
| ShowNextTopStockPileCardForLocalPlayer(false); | |
| UpdateStockPileCardsCountText(); | |
| }); | |
| } | |
| //else | |
| // throw new Exception($"requested card not found in the build pile {card.ToString()}"); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| /// <summary> | |
| /// Loads saved game and updates UI | |
| /// </summary> | |
| internal void LoadSavedGameUI() | |
| { | |
| //Game.Log($"LoadSavedGameUI player hand is null {player == null} player hand {player.Hand?.Count} stock pile count {player.StockPile.Count} isMyTurn {player.isMyTurn} id {player.id}"); | |
| //First build hand cards | |
| if (isLocalPlayer) | |
| { | |
| onCardsAddedToHand(player.Hand); | |
| } | |
| else | |
| UpdateOpponentDummyHandCards(player?.Hand?.Count ?? 0, false); | |
| //Then build stock pile cards | |
| onCardsAddedToStockPile(player.StockPile); | |
| //next build discard Pile Cards for ai and local player | |
| int count = player.DiscardPileStackOne.Count; | |
| for (int i = 0; i < count; i++) | |
| if (player.isAI) | |
| onValidAIDiscardPileDrop(player.DiscardPileStackOne[i], player.DiscardPileStackOne[i].discardPileIndex, CardDragSourceType.Hand); | |
| else | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackOne[i]); | |
| count = player.DiscardPileStackTwo.Count; | |
| for (int i = 0; i < count; i++) | |
| if (player.isAI) | |
| onValidAIDiscardPileDrop(player.DiscardPileStackTwo[i], player.DiscardPileStackTwo[i].discardPileIndex, CardDragSourceType.Hand); | |
| else | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackTwo[i]); | |
| count = player.DiscardPileStackThree.Count; | |
| for (int i = 0; i < count; i++) | |
| if (player.isAI) | |
| onValidAIDiscardPileDrop(player.DiscardPileStackThree[i], player.DiscardPileStackThree[i].discardPileIndex, CardDragSourceType.Hand); | |
| else | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackThree[i]); | |
| count = player.DiscardPileStackFour.Count; | |
| for (int i = 0; i < count; i++) | |
| if (player.isAI) | |
| onValidAIDiscardPileDrop(player.DiscardPileStackFour[i], player.DiscardPileStackFour[i].discardPileIndex, CardDragSourceType.Hand); | |
| else | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackFour[i]); | |
| if (isLocalPlayer) | |
| { | |
| for (int i = 0; i < 4; i++) | |
| ReArrangeDiscardPiles(i, 0f, true); | |
| } | |
| } | |
| /// <summary> | |
| /// When loading the saved game create discarded cards as well | |
| /// </summary> | |
| /// <param name="card"></param> | |
| private void LoadAndCreateDiscardedCardsForRealPlayer(Card card) | |
| { | |
| //spawn at deck and move the card to desired location | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, discardPileRects[card.discardPileIndex]); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| cardObject.SetActive(true); | |
| cardRect.localScale = player.isLocalPlayer ? LOCALPLAYERCARDSCALE : OPPONENTPLAYERDISCARDPILECARDSCALE; | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| uiCard.SetupCard(card, CardDragSourceType.DiscardPile); | |
| uiCard.ToggleInteractive(player.isMyTurn); | |
| if (!Game.saveLoadedGame) | |
| uiCard.QuickFlip().FlipCard(); | |
| discardPile.Add(uiCard); | |
| } | |
| /// <summary> | |
| /// Remove listeners when the game is destroyed | |
| /// </summary> | |
| internal void RemoveListeners() | |
| { | |
| //UIDropCell.onValidDropEvent -= onValidDrop; | |
| if (player != null) | |
| { | |
| //Game.Log($"unsbuscribing player.cs in UIPlayer.cs GetHashCode {player.GetHashCode()}"); | |
| player.onTimerTickEvent -= OnTimerTick; | |
| player.onCardsAddedToStockPileEvent -= onCardsAddedToStockPile; | |
| player.onCardsAddedToHandEvent -= onCardsAddedToHand; | |
| player.onMyTurnBeginEvent -= onMyTurnBegin; | |
| player.onMyTurnEndEvent -= onMyTurnEnd; | |
| // player.onValidBuildPileDropEvent -= onValidBuildPileDrop; | |
| player.onValidAIDiscardPileDropEvent -= onValidAIDiscardPileDrop; | |
| player.onUndoEvent -= onUndo; | |
| player.onCardsAddedToNetworkPlayersStockPileEvent -= OnCardsAddedToNetworkPlayersStockPile; | |
| player.onOnlineGameForceDiscardEvent -= OnOnlineGameForceDiscard; | |
| //player.onCardsAddedToNetworkPlayersHandEvent -= OnCardsAddedToNetworkPlayersHand; | |
| } | |
| player = null; | |
| VivoxVoiceManager.OnSpeechDetectedEvent -= OnPlayerVoiceDetected; | |
| VivoxVoiceManager.OnParticipantAddedEvent -= OnParticipantAdded; | |
| VivoxVoiceManager.OnParticipantRemovedEvent -= OnParticipantRemoved; | |
| } | |
| /// <summary> | |
| /// called for real player when a card is dropped on timeout in multiplayer game | |
| /// </summary> | |
| /// <param name="card"></param> | |
| /// <param name="dropCellID"></param> | |
| /// <param name="cardDragSourceType"></param> | |
| private void OnOnlineGameForceDiscard(Card card, int dropCellID, CardDragSourceType cardDragSourceType) | |
| { | |
| Game.Log($"OnOnlineGameForceDiscard {card} dropCellID {dropCellID} cardDragSourceType {cardDragSourceType}"); | |
| if (player.playerType == PlayerType.LocalPlayer && cardDragSourceType == CardDragSourceType.Hand) | |
| { | |
| GameObject cardObject = handCards.Find(c => c.card.uniqueID == card.uniqueID)?.gameObject; | |
| if (cardObject != null) | |
| { | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| uiCard.SetParentAndUpdatePosition(discardPileRects[dropCellID], vecor2Zero, true, (0.5f), false, LeanTweenType.easeOutCirc); | |
| handCards.Remove(uiCard); | |
| discardPile.Add(uiCard); | |
| StartCoroutine(ReArrangeHandCards(UIDropCell.CellType.DiscardPile)); | |
| ReArrangeDiscardPiles(uiCard.card.discardPileIndex, 0.6f, false); | |
| } | |
| //else | |
| // throw new Exception($"Card {card} not found in the hand"); | |
| UpdateDebugHandCardsText(); | |
| } | |
| } | |
| /// <summary> | |
| /// Called from an event when ai drops a card onto discardPile | |
| /// </summary> | |
| /// <param name="card"></param> | |
| /// <param name="dropCellID"></param> | |
| /// <param name="cardDragSourceType"></param> | |
| private void onValidAIDiscardPileDrop(Card card, int dropCellID, CardDragSourceType cardDragSourceType) | |
| { | |
| // Game.Log($"onValidAIDiscardPileDrop {card.ToString()} dropCellID {dropCellID} cardDragSourceType {cardDragSourceType}"); | |
| if (player.playerType == PlayerType.Opponent && cardDragSourceType == CardDragSourceType.Hand) | |
| { | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, handCardsParent); | |
| cardObject.SetActive(true); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| Vector2 localScale = vecor2One; | |
| if (!Game.saveLoadedGame) | |
| cardRect.localScale = OPPONENTPLAYERDISCARDPILECARDSCALE * 0.5f; | |
| else | |
| cardRect.localScale = OPPONENTPLAYERDISCARDPILECARDSCALE; | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| uiCard.SetupCard(card, CardDragSourceType.DiscardPile).ToggleInteractive(false); | |
| if (!Game.saveLoadedGame) | |
| uiCard.QuickFlip(); | |
| uiCard.SetParentAndUpdatePosition(discardPileRects[dropCellID], vecor2Zero, true, Game.saveLoadedGame ? 0 : (0.5f), false, LeanTweenType.easeOutCirc); | |
| Vector2 scaleTo = vecor2One; | |
| if (!Game.saveLoadedGame) | |
| uiCard.TweenScale(OPPONENTPLAYERDISCARDPILECARDSCALE, Game.saveLoadedGame ? 0 : (0.5f), c => { if (!Game.saveLoadedGame) c.FlipCard(); }); | |
| UpdateOpponentDummyHandCards(player.handCardsCount, false); | |
| discardPile.Add(uiCard); | |
| } | |
| //in tutorial if its the fouth player | |
| if (!Game.isOnlineGame && player.isMyTurn && player.playerType == PlayerType.Opponent && player.id == 3) | |
| { | |
| if (Game.tutorialStep == 8)//If you cannot play a card on the build pile, finish your turn by moving a card from your hand to a disacrd pile. | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepNine"); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Called from an event when Player drops card onto build pile | |
| /// </summary> | |
| /// <param name="card"></param> | |
| /// <param name="buildcellIndex"></param> | |
| public void onValidBuildPileDrop(Card card, int buildcellIndex, CardDragSourceType cardDragSourceType) | |
| { | |
| if (player.playerType == PlayerType.Opponent) | |
| { | |
| Game.Log($"UIPlayer.cs onValidBuildPileDrop_for_opponent id {id} {card} dropCellID {buildcellIndex} cardDragSourceType {cardDragSourceType}"); | |
| RectTransform cardSpawnParent = null;//decide where to spawn the card | |
| switch (cardDragSourceType) | |
| { | |
| case CardDragSourceType.None: | |
| break; | |
| case CardDragSourceType.Hand: | |
| cardSpawnParent = handCardsParent; | |
| break; | |
| case CardDragSourceType.DiscardPile: | |
| cardSpawnParent = discardPileParent; | |
| break; | |
| case CardDragSourceType.StockPile: | |
| cardSpawnParent = stockPileTopCardParent; | |
| UpdateStockPileCardsCountText(); | |
| //Scale the counter | |
| TweenStockPileCardsCountLabel(); | |
| break; | |
| default: | |
| break; | |
| } | |
| GameObject cardObject; | |
| if (cardDragSourceType == CardDragSourceType.DiscardPile) | |
| { | |
| // discardPile.ForEach(c => Game.Log($"UIPlayer.cs onValidBuildPileDrop discardPile {c.card}")); | |
| if (Game.isOnlineGame) | |
| { | |
| cardObject = discardPile?.Find(c => c != null && c.card != null && card != null && c.card.uniqueID == card.uniqueID)?.gameObject; | |
| } | |
| else | |
| cardObject = discardPile?.Find(c => c != null && c.card != null && card != null && c.card.uniqueID == card.uniqueID)?.gameObject; | |
| if (cardObject == null) | |
| { | |
| discardPile.ForEach(c => Game.Log($"UIPlayer.cs onValidBuildPileDrop discardPile {c.card}")); | |
| } | |
| } | |
| else | |
| cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, cardSpawnParent); | |
| cardObject?.SetActive(true); | |
| RectTransform cardRect = null; | |
| if (cardObject.GetComponent<RectTransform>() != null) | |
| cardRect = cardObject.GetComponent<RectTransform>(); | |
| else | |
| cardRect = null; | |
| if (cardDragSourceType == CardDragSourceType.Hand && cardRect != null) | |
| cardRect.localScale = OPPONENTPLAYERSTOCKPILECARDSCALE * 0.5f; | |
| UICard uiCard = null; | |
| if (cardObject.GetComponent<UICard>() != null) | |
| uiCard = cardObject.GetComponent<UICard>(); | |
| if (uiCard != null) | |
| { | |
| uiCard.SetupCard(card, CardDragSourceType.StockPile); | |
| uiCard.ToggleInteractive(false); | |
| //when dropping make sure it does not go through other build pile cards so make the parent as the last sibling index | |
| SkipBoGameManager.instance.buildPiles[buildcellIndex].SetAsLastSibling(); | |
| uiCard.SetParentAndUpdatePosition(SkipBoGameManager.instance.buildPiles[buildcellIndex], vecor2Zero, true, (0.4f), false, LeanTweenType.easeOutCubic); | |
| uiCard.TweenScale(LOCALPLAYERSTOCKPILECARDSCALE, (0.4f)); | |
| SkipBoGameManager.instance.AddUICardToBuildPile(uiCard, buildcellIndex); | |
| } | |
| else | |
| Game.Log($"onValidBuildPileDrop card not handled. Should not happen"); | |
| UpdateOpponentDummyHandCards(player.handCardsCount, false); | |
| //Update stock pile top card if card was dropped from the stok pile | |
| if (cardDragSourceType == CardDragSourceType.StockPile) | |
| ShowNextTopStockPileCardForLocalPlayer(true); | |
| } | |
| } | |
| /// <summary> | |
| /// Draws the top ui card of stock pile | |
| /// </summary> | |
| private void ShowNextTopStockPileCardForLocalPlayer(bool flipCard) | |
| { | |
| Game.Log($" UIPlayer.cs ShowNextTopStockPileCardForLocalPlayer flipCard {flipCard}"); | |
| if (player?.stockPileCardsCount == 0) | |
| { | |
| stockPileTopCardParent?.gameObject?.SetActive(false); | |
| } | |
| else | |
| { | |
| stockPileCard?.SetupCard(player.topStockPileCard, CardDragSourceType.StockPile); | |
| if (flipCard) | |
| stockPileCard?.QuickFlip()?.FlipCard(); | |
| UpdateStockPileCardsText(); | |
| } | |
| } | |
| /// <summary> | |
| /// Called from an event when card is dropped on a valid drop cell. Called only for real local player | |
| /// </summary> | |
| /// <param name="dropCellType"></param> | |
| /// <param name="cellID"></param> | |
| /// <param name="card"></param> | |
| internal void onValidDrop(UIDropCell.CellType dropCellType, int dropCellID, UICard card, CardDragSourceType cardDragSourceType) | |
| { | |
| Game.Log($" UIPlayer.cs onValidDrop dropCellID {dropCellID} id {player.id} card {card.card} cardDragSourceType {cardDragSourceType} cellType {dropCellType} id {player.id}"); | |
| if (Game.showingTutorial) | |
| card.ToggleCardOutline(false); | |
| switch (dropCellType) | |
| { | |
| case UIDropCell.CellType.DiscardPile: | |
| MoveCardFromHandToDiscardPile(card); //Add dropped card to appropriate drop pile stack | |
| DisableHand(); | |
| DisableStockPile(); | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| ReArrangeDiscardPiles(dropCellID, 0.1f); | |
| break; | |
| case UIDropCell.CellType.BuildPile: | |
| MoveCardToBuildPile(card, dropCellID, cardDragSourceType); //Continue the turn | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| ReArrangeDiscardPiles(card.card.discardPileIndex, 0.1f, true); | |
| break; | |
| default: | |
| break; | |
| } | |
| if (cardDragSourceType == CardDragSourceType.StockPile) | |
| TweenStockPileCardsCountLabel(); //Scale the counter | |
| else if (cardDragSourceType == CardDragSourceType.Hand) | |
| StartCoroutine(ReArrangeHandCards(dropCellType)); | |
| Game.Log($" UIPlayer.cs onValidDrop rank {card.card.rank} Game.tutorialStep {Game.tutorialStep}"); | |
| if (!Game.isOnlineGame && player.isMyTurn) | |
| { | |
| if (Game.showingTutorial) | |
| { | |
| if (dropCellType == UIDropCell.CellType.BuildPile) | |
| { | |
| //if(Game.tutorialStep == 0) | |
| //{ | |
| // //hits when the game is over in tut mode | |
| // SkipBoGameManager.instance.HideTutorialScreen(); | |
| //} | |
| if (Game.tutorialStep == 2 && card.card.rank == 1) //Start a build pile by dragging a 1 onto one of the empty center spaces. | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepThree"); | |
| } | |
| else if (Game.tutorialStep == 3 && card.card.rank == 2) //Cards must be placed on the build piles in sequence from 1 - 12 | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepFour"); | |
| } | |
| else if (Game.tutorialStep == 4 && card.card.rank == 3) //Play cards from your stockpile whenever you can. | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepSix"); | |
| } | |
| else if (Game.tutorialStep == 6 && card.card.isSkipBoCard) //A skip-Bo card is wild.Play yours on any of the build piles. | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepSeven"); | |
| } | |
| else if (Game.tutorialStep == 8) //OK, it is yor turn to play again. try and empty your stockpile! | |
| { | |
| stockPileCard?.ToggleCardOutline(true); | |
| } | |
| } | |
| else if (dropCellType == UIDropCell.CellType.DiscardPile) | |
| { | |
| if (Game.tutorialStep == 7 && card.card.rank == 6) //Start a build pile by dragging a 1 onto one of the empty center spaces. | |
| { | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| #region Tutorial | |
| private IEnumerator ContinueTutorialStepZero() | |
| { | |
| SkipBoGameManager.instance.buildPiles[1].GetComponent<Image>().raycastTarget = false; | |
| SkipBoGameManager.instance.buildPiles[2].GetComponent<Image>().raycastTarget = false; | |
| SkipBoGameManager.instance.buildPiles[3].GetComponent<Image>().raycastTarget = false; | |
| for (int i = 0; i < 4; i++) | |
| { | |
| discardPileRects[i].GetComponent<Image>().raycastTarget = false; | |
| discardPileColliders[i].enabled = false; | |
| } | |
| DisableHand()?.DisableStockPile(); | |
| SkipBoGameManager.instance.ShowTutorialStep(0); //The first person to empty their Stock Pile wins the game | |
| yield return new WaitForSeconds(3f); | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| yield return new WaitForSeconds(2f); | |
| StartCoroutine("ContinueTutorialStepOne"); | |
| } | |
| private IEnumerator ContinueTutorialStepOne() | |
| { | |
| SkipBoGameManager.instance.ShowTutorialStep(1); //You can do this by making build piles in the middle of the table. | |
| yield return new WaitForSeconds(3f); | |
| SkipBoGameManager.instance.HideTutorialScreen(); | |
| StartCoroutine("ContinueTutorialStepTwo"); | |
| } | |
| private IEnumerator ContinueTutorialStepTwo() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand()?.DisableStockPile(); | |
| SkipBoGameManager.instance.ShowTutorialStep(2);//Start a build pile by dragging a 1 onto one of the empty center spaces. | |
| yield return new WaitForSeconds(2f); | |
| FindHandCardByRank(1)?.ToggleInteractive(true).ToggleCardOutline(true); | |
| } | |
| private IEnumerator ContinueTutorialStepThree() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand()?.DisableStockPile(); | |
| yield return new WaitForSeconds(1f); | |
| SkipBoGameManager.instance.ShowTutorialStep(3);//Cards must be placed on the build piles in sequence from 1 - 12 | |
| yield return new WaitForSeconds(2f); | |
| DisableHand().DisableStockPile().FindHandCardByRank(2)?.ToggleInteractive(true)?.ToggleCardOutline(true); | |
| } | |
| private IEnumerator ContinueTutorialStepFour() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand()?.DisableStockPile(); | |
| SkipBoGameManager.instance.ShowTutorialStep(4); //Play cards from your stockpile whenever you can. | |
| yield return new WaitForSeconds(2f); | |
| DisableHand().EnableStockPile(); | |
| stockPileCard.ToggleCardOutline(true); | |
| } | |
| //skip step 5 | |
| //private IEnumerator ContinueTutorialStepFive() | |
| //{ | |
| // yield return new WaitForSeconds(2f); | |
| // // DisableHand().DisableStockPile(); | |
| // SkipBoGameManager.instance.ShowTutorialStep(5); //Play cards from your stockpile whenever you can. | |
| // yield return new WaitForSeconds(2f); | |
| // SkipBoGameManager.instance.HideTutorialScreen(); | |
| // yield return new WaitForSeconds(1f); | |
| // StartCoroutine("ContinueTutorialStepSix"); | |
| //} | |
| private IEnumerator ContinueTutorialStepSix() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand().DisableStockPile(); | |
| yield return new WaitForSeconds(1f); | |
| SkipBoGameManager.instance.ShowTutorialStep(6); //A skip-Bo card is wild.Play yours on any of the build piles. | |
| yield return new WaitForSeconds(2f); | |
| DisableHand().DisableStockPile().FindHandCardByRank(0).ToggleInteractive(true).ToggleCardOutline(true); | |
| } | |
| private IEnumerator ContinueTutorialStepSeven() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand().DisableStockPile(); | |
| yield return new WaitForSeconds(2f); | |
| SkipBoGameManager.instance.ShowTutorialStep(7); // If you cannot play a card on the build pile, finish your turn by moving a card from your hand to a disacrd pile. | |
| yield return new WaitForSeconds(3f); | |
| for (int i = 0; i < 4; i++) | |
| { | |
| discardPileRects[i].GetComponent<Image>().raycastTarget = true; | |
| discardPileColliders[i].enabled = true; | |
| } | |
| FindHandCardByRank(6).ToggleInteractive(true).ToggleCardOutline(true); | |
| } | |
| private IEnumerator ContinueTutorialStepEight() | |
| { | |
| yield return new WaitForSeconds(0.6f); | |
| DisableHand().DisableStockPile(); | |
| yield return new WaitForSeconds(1f); | |
| EnableHand().EnableStockPile(); | |
| SkipBoGameManager.instance.ShowTutorialStep(8); //OK, it is yor turn to play again. try and empty your stockpile! | |
| for (int i = 0; i < 4; i++) | |
| { | |
| discardPileRects[i].GetComponent<Image>().raycastTarget = false; | |
| discardPileRects[i].GetComponent<UIDropCell>().ToggleInteractive(false); | |
| discardPileColliders[i].enabled = false; | |
| } | |
| yield return new WaitForSeconds(1f); | |
| stockPileCard.ToggleCardOutline(true); | |
| } | |
| #endregion | |
| /// <summary> | |
| /// If Player takes card from the middle of the hand jsut rearrange it | |
| /// </summary> | |
| private IEnumerator ReArrangeHandCards(UIDropCell.CellType dropCellType, bool forceRefresh = false) | |
| { | |
| //DestroyUnlinkedCards(); | |
| //disable touch | |
| TogglePlayerCardsTouch(false); | |
| int handCardsCount = handCards?.Count ?? 0; | |
| Game.Log($"ReArrangeHandCards {handCardsCount}"); | |
| if (handCardsCount == 5 && !forceRefresh) yield return null; | |
| //FailCheck | |
| if (handCardsCount > 5) | |
| { | |
| Game.Log($"ReArrangeHandCards {handCardsCount} trimming count to handle exception"); | |
| handCardsCount = 5; | |
| } | |
| int index = 0; | |
| if (handCardsCount > 0) | |
| { | |
| foreach (UICard uiCard in handCards) | |
| { | |
| if (uiCard != null) | |
| { | |
| uiCard.card?.UpdateCard(CardDragSourceType.Hand, -1, -1); | |
| uiCard.ToggleInteractive(false); | |
| uiCard.SetParentAndUpdatePosition(handCardsRects[index], vecor2Zero, true, 0.2f, false, LeanTweenType.easeOutBounce, null); | |
| index++; | |
| if (Game.showingTutorial) | |
| yield return new WaitForSeconds(0.01f); | |
| else | |
| yield return reArrageCardWaitDelay; | |
| } | |
| } | |
| } | |
| if (dropCellType == UIDropCell.CellType.BuildPile && !Game.showingTutorial) | |
| TogglePlayerCardsTouch(true); | |
| } | |
| /// <summary> | |
| /// ReArranges discard piles such a way top three cards are visible | |
| /// </summary> | |
| internal void ReArrangeDiscardPiles(int discardPileID, float refreshDelay = 0f, bool enableTopCard = false) | |
| { | |
| StartCoroutine(ReArrangeDiscardPilesNow(discardPileID, refreshDelay, enableTopCard)); | |
| } | |
| IEnumerator ReArrangeDiscardPilesNow(int discardPileID, float refreshDelay = 0f, bool enableTopCard = false) | |
| { | |
| if (discardPileID < 0) yield break; | |
| // Game.Log($"ReArrangeDiscardPilesNow {discardPileID}"); | |
| UICard[] uiCards = discardPileRects[discardPileID].GetComponentsInChildren<UICard>(); | |
| int uiCardsLength = uiCards.Length; | |
| for (int i = 0; i < uiCardsLength; i++) | |
| { | |
| //uiCards[i].GetComponent<RectTransform>().anchoredPosition = vecor2Zero; | |
| uiCards[i]?.ToggleInteractive(false); | |
| } | |
| yield return new WaitForSeconds(refreshDelay); | |
| Vector2 offset = new Vector2(0, uiCardsLength > 2 ? -60 : -30); | |
| int iterateIndex = 0; | |
| for (int i = uiCardsLength - 1; i >= 0; i--) | |
| { | |
| UICard uiCard = uiCards[i]; | |
| RectTransform rt = uiCard.GetComponent<RectTransform>(); | |
| if (i > 0 && iterateIndex < 2) | |
| { | |
| //Game.Log($"ReArrangeDiscardPilesNow offset {offset} i {i} card {uiCard.card}"); | |
| LeanTween.value(uiCard.gameObject, (Vector2 val) => rt.anchoredPosition = val, rt.anchoredPosition, offset, 0.1f); | |
| //Game.Log($"ReArrangeDiscardPilesNow offset after {card.GetComponent<RectTransform>().anchoredPosition} i {i}"); | |
| offset = new Vector2(0, offset.y + 30); | |
| } | |
| else | |
| { | |
| LeanTween.value(uiCard.gameObject, (Vector2 val) => rt.anchoredPosition = val, rt.anchoredPosition, vecor2Zero, 0.1f); | |
| } | |
| iterateIndex++; | |
| } | |
| if (uiCardsLength > 0) | |
| uiCards[uiCardsLength - 1]?.ToggleInteractive(enableTopCard); | |
| } | |
| /// <summary> | |
| /// At some point if there is any extra cards in hand pile clean em up | |
| /// </summary> | |
| void DestroyUnlinkedCards() | |
| { | |
| //Iterate through | |
| for (int i = 0; i < handCardsRects.Length; i++) | |
| { | |
| UICard[] childrenCards = handCardsRects[i].GetComponentsInChildren<UICard>(); | |
| int childrenCardsLength = childrenCards.Length; | |
| // Game.Log($"DestroyUnlinkedCards i {i} childrenCards.Length {childrenCardsLength}"); | |
| if (childrenCardsLength > 0) | |
| { | |
| // for (int j = 0; j < childrenCardsLength; j++) | |
| foreach (UICard uiCard in childrenCards) | |
| { | |
| // UICard card = handCards.Find(c => c.card.uniqueID == uiCard.card.uniqueID); | |
| UICard ui_card = handCards.Find(c => c == uiCard); | |
| // Game.Log($"DestroyUnlinkedCards card found ? {ui_card != null}"); | |
| if (ui_card == null) | |
| { | |
| // Game.Log($"Despawing {uiCard.card.ToString()}"); | |
| Lean.Pool.LeanPool.Despawn(uiCard.gameObject); | |
| //SkipBoGameManager.instance.leanPool.Despawn(uiCard.gameObject); | |
| // Destroy(uiCard.gameObject); | |
| } | |
| else | |
| { | |
| Card card = player.Hand.Find(c => c.uniqueID == ui_card.card.uniqueID); | |
| if (card == null) | |
| { | |
| // Game.Log($"Card {ui_card.card.ToString()} is not found in player.Hand"); | |
| Lean.Pool.LeanPool.Despawn(uiCard.gameObject); | |
| handCards.Remove(ui_card); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| { | |
| Game.Log($"Despawing discardPile.Count {discardPile.Count}"); | |
| foreach (UICard discardedCard in discardPile) | |
| { | |
| //Game.Log($"Despawing ieteration {discardedCard.card.ToString()}"); | |
| UICard uiCard = discardPile.Find(c => c.gameObject == discardedCard.gameObject); | |
| if (uiCard == null) | |
| { | |
| Game.Log($"Card {discardedCard.card} is not found in discard pile"); | |
| Lean.Pool.LeanPool.Despawn(discardedCard.gameObject); | |
| } | |
| else | |
| { | |
| // Game.Log($"Card {discardedCard.card} is found in discard pile. Continuing........."); | |
| for (int i = 0; i < 4; i++) | |
| { | |
| UICard[] discardedCards = discardPileRects[i].GetComponentsInChildren<UICard>(); | |
| // Game.Log($" discardedCards count {i} {discardedCards.Length} "); | |
| foreach (UICard _uiCard in discardedCards) | |
| { | |
| Card card = null; | |
| switch (i) | |
| { | |
| case 0: card = player.DiscardPileStackOne.Find(c => c == _uiCard.card); break; | |
| case 1: card = player.DiscardPileStackTwo.Find(c => c == _uiCard.card); break; | |
| case 2: card = player.DiscardPileStackThree.Find(c => c == _uiCard.card); break; | |
| case 3: card = player.DiscardPileStackFour.Find(c => c == _uiCard.card); break; | |
| default: | |
| break; | |
| } | |
| if (card == null) | |
| { | |
| Game.Log($"Card {_uiCard.card} is not found in discard pile {i} removing it"); | |
| Lean.Pool.LeanPool.Despawn(_uiCard.gameObject); | |
| //continue; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Inserts the card to hand at given index | |
| /// </summary> | |
| /// <param name="cards"></param> | |
| /// <param name="insertIndex"></param> | |
| internal void InsertCardsToHand(UICard card, int insertIndex) | |
| { | |
| handCards.Insert(insertIndex, card); | |
| } | |
| /// <summary> | |
| /// Adds the ui card back to the discard pile | |
| /// </summary> | |
| /// <param name="card"></param> | |
| internal void ReturnCardToDiscardPile(UICard card) | |
| { | |
| discardPile.Add(card); | |
| } | |
| /// <summary> | |
| /// Scales the stock pile cards count label and resets it | |
| /// </summary> | |
| private void TweenStockPileCardsCountLabel() | |
| { | |
| LeanTween.value(stockPileCountLabel.gameObject, val => stockPileCountLabel.rectTransform.localScale = val, stockPileCountLabel.rectTransform.localScale, stockPileCountLabel.rectTransform.localScale * 2.5f, 0.1f).setOnComplete((t) => | |
| { | |
| LeanTween.value(stockPileCountLabel.gameObject, (Vector2 scale) => stockPileCountLabel.rectTransform.localScale = scale, stockPileCountLabel.rectTransform.localScale, vecor2One, 0.2f).setOnComplete(() => | |
| { | |
| LeanTween.value(stockPileCountLabelAnimationParticle.gameObject, (Vector2 scale) => stockPileCountLabelAnimationParticle.rectTransform.localScale = scale, stockPileCountLabel.rectTransform.localScale, new Vector2(2, 2), 0.2f).setOnComplete(() => | |
| { | |
| stockPileCountLabelAnimationParticle.rectTransform.localScale = vecor2Zero; | |
| }); | |
| LeanTween.value(stockPileCountLabelAnimationParticle.gameObject, (float alpha) => stockPileCountLabelAnimationParticle.SetTransparency(alpha), 1, 0, 0.2f); | |
| }); | |
| }); | |
| } | |
| /// <summary> | |
| /// Move UICard to discardPile | |
| /// </summary> | |
| /// <param name="card"></param> | |
| /// <param name="discardPile"></param> | |
| private void MoveCardFromHandToDiscardPile(UICard card) | |
| { | |
| Game.Log($"MoveCardFromHandToDiscardPile {card.card} hand count {handCards?.Count ?? -1}"); | |
| UICard discardedCard = handCards?.Find(c => c.card.uniqueID == card.card.uniqueID); | |
| if (discardedCard != null) | |
| { | |
| Game.Log($"MoveCardFromHandToDiscardPile added to discard pile"); | |
| handCards.Remove(discardedCard); | |
| discardPile.Add(discardedCard); | |
| } | |
| else | |
| { | |
| handCards.ForEach(c => Game.Log($"-> UIPlayer.cs hand {c?.card}", LogType.Error)); | |
| CorrectUIHandCards(); | |
| MoveCardFromHandToDiscardPile(card); | |
| } | |
| UpdateDebugHandCardsText(); | |
| } | |
| /// <summary> | |
| /// Move UICard to build pile | |
| /// </summary> | |
| /// <param name="uiCard"></param> | |
| /// <param name="discardPile"></param> | |
| private void MoveCardToBuildPile(UICard uiCard, int buildCellIndex, CardDragSourceType cardDragSourceType) | |
| { | |
| Game.Log($"UIPlayer.cs MoveCardToBuildPile {uiCard.card} cardDragSourceType {cardDragSourceType} hash {player.GetHashCode()} discardPile count {discardPile?.Count}"); | |
| UICard droppedCard = null; | |
| switch (cardDragSourceType) | |
| { | |
| case CardDragSourceType.None: | |
| break; | |
| case CardDragSourceType.Hand: | |
| droppedCard = handCards.Find(c => c.card?.uniqueID == uiCard.card.uniqueID); | |
| if (droppedCard != null) | |
| handCards.Remove(droppedCard); | |
| else | |
| { | |
| CorrectUIHandCards(); | |
| droppedCard = handCards.Find(c => c.card?.uniqueID == uiCard.card.uniqueID); | |
| if (droppedCard != null) | |
| handCards.Remove(droppedCard); | |
| } | |
| break; | |
| case CardDragSourceType.DiscardPile: | |
| droppedCard = discardPile.Find(c => c.card?.uniqueID == uiCard.card.uniqueID); | |
| if (droppedCard != null) | |
| discardPile.Remove(droppedCard); | |
| else | |
| { | |
| CorrectDiscardPile(); | |
| droppedCard = discardPile.Find(c => c.card?.uniqueID == uiCard.card.uniqueID); | |
| if (droppedCard != null) | |
| discardPile.Remove(droppedCard); | |
| } | |
| break; | |
| case CardDragSourceType.StockPile: | |
| droppedCard = stockPileCard; | |
| AddAnUICardOnStockPile(); | |
| UpdateStockPileCardsCountText(); | |
| break; | |
| default: | |
| break; | |
| } | |
| if (droppedCard == null) | |
| { | |
| if (cardDragSourceType == CardDragSourceType.Hand) | |
| handCards.ForEach(c => Game.Log($"-> UIPlayer.cs MoveCardToBuildPile hand {c.card.ToString()}", LogType.Error)); | |
| else if (cardDragSourceType == CardDragSourceType.DiscardPile) | |
| discardPile.ForEach(c => Game.Log($"-> UIPlayer.cs discardPile hand {c.card.ToString()}", LogType.Error)); | |
| else if (cardDragSourceType == CardDragSourceType.StockPile) | |
| Game.Log($"-> UIPlayer.cs discardPile hand {stockPileCard.card.ToString()}", LogType.Error); | |
| return; | |
| } | |
| droppedCard.TweenScale(LOCALPLAYERSTOCKPILECARDSCALE, 0.1f); | |
| SkipBoGameManager.instance.AddUICardToBuildPile(droppedCard, buildCellIndex); | |
| UpdateDebugHandCardsText(); | |
| } | |
| /// <summary> | |
| /// Stock pile for local player shows only one visual card on top. When that card is moved to the build pile | |
| /// add a new card to show the top stock pile card | |
| /// </summary> | |
| private void AddAnUICardOnStockPile() | |
| { | |
| UICard[] oldCards = stockPileTopCardParent.GetComponentsInChildren<UICard>(); | |
| Game.Log($"#AddAnUICardOnStockPile {player.topStockPileCard?.ToString()} oldCards count {oldCards.Length}"); | |
| if (oldCards.Length > 0) | |
| { | |
| foreach (UICard card in oldCards) | |
| { | |
| Game.Log($"#AddAnUICardOnStockPile Removing {card.card}"); | |
| SkipBoGameManager.instance.leanPool.Despawn(card.gameObject); | |
| } | |
| } | |
| //If card was dragged from the stock pile update the top stock pile card | |
| if (player.playerType == PlayerType.LocalPlayer && player.stockPileCardsCount > 0)//do it only if there are more then 0 cards in stock pile | |
| { | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, stockPileTopCardParent); | |
| cardObject.SetActive(true); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| cardRect.localScale = LOCALPLAYERSTOCKPILECARDSCALE; | |
| stockPileCard = cardObject.GetComponent<UICard>(); | |
| stockPileCard.SetupCard(player.topStockPileCard, CardDragSourceType.StockPile); | |
| stockPileCard.QuickFlip().FlipCard(); | |
| if (player.isMyTurn) | |
| stockPileCard.ToggleInteractive(true); | |
| UpdateStockPileCardsText(); | |
| } | |
| else | |
| { | |
| Game.Log($"Game over. Player {player.id} won the game-----------------------------------------------"); | |
| stockPileTopCardParent.gameObject.SetActive(false); | |
| } | |
| } | |
| /// <summary> | |
| /// Called from an event when Cards are added to the hand from deck | |
| /// </summary> | |
| /// <param name="cards"></param> | |
| private void onCardsAddedToHand(List<Card> cards) | |
| { | |
| if (player == null || cards == null || cards.Count == 0) return; | |
| //Game.Log($"UIPlayer.cs onCardAddedToHand {cards?.Count} handCards count {handCards?.Count} player.playerType {player?.playerType} playerID {player?.id}"); | |
| int cardsCount = cards?.Count ?? 0; | |
| if (player.playerType == PlayerType.LocalPlayer) // instantiate visual cards only for local player. for opponent show only dummy card back | |
| { | |
| //safeCheck | |
| if (cardsCount + handCards?.Count > 5) | |
| { | |
| Game.Log($"Invalid flow. Extra cards added to the hand*********************************************************** added cards count {cardsCount} hand count{handCards?.Count }"); | |
| CorrectUIHandCards(); | |
| return; | |
| } | |
| if (cardsCount > 0) | |
| { | |
| for (int i = 0; i < cardsCount; i++) | |
| { | |
| //spawn at deck and move the card to desired location | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, SkipBoGameManager.instance.deckParent); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| cardObject.SetActive(true); | |
| //set separate scaling for local player and opponent player | |
| switch (player.playerType) | |
| { | |
| case PlayerType.LocalPlayer: | |
| cardRect.localScale = LOCALPLAYERCARDSCALE; | |
| break; | |
| case PlayerType.Opponent: | |
| cardRect.localScale = OPPONENTPLAYERCARDSCALE; | |
| break; | |
| } | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| uiCard.SetupCard(cards[i], CardDragSourceType.Hand); | |
| if (!Game.saveLoadedGame) | |
| uiCard.QuickFlip().FlipCard(); | |
| handCards?.Add(uiCard); | |
| uiCard.ToggleInteractive(false); | |
| } | |
| int handCardsCount = handCards?.Count ?? 0; | |
| // Game.Log($"onCardAddedToHand {handCardsCount} player.playerType {player.playerType} added cardsCount {cardsCount} "); | |
| for (int i = 0; i < handCardsCount; i++) | |
| { | |
| // Game.Log($"onCardAddedToHand localScale {handCards[i].transform.localScale} id {player.id}"); | |
| handCards[i]?.SetParentAndUpdatePosition(handCardsRects[i], vecor2Zero, true, Game.saveLoadedGame ? 0 : ((i + 1) * 0.2f), false, LeanTweenType.easeOutExpo, | |
| (uiCard) => | |
| { | |
| //if (player?.isLocalPlayer ?? false) | |
| // Game.Log($"Game.saveLoadedGame {Game.saveLoadedGame} isMyTurn {player?.isMyTurn ?? false} id {player?.id ?? -1}"); | |
| uiCard?.ToggleInteractive(((player?.isMyTurn ?? false) && !Game.saveLoadedGame)); | |
| });//enable the collider if its my turn and its not saveLoadedGame case | |
| } | |
| } | |
| else | |
| { | |
| if (SkipBoGameManager.instance.remainingCardsInDeck == 0) | |
| { | |
| Game.Log($"onCardsAddedToHand showing no cards toast"); | |
| DialogBox.ShowToastMessage(Game.GetLocTxt(LKeys.DECKISEMPTYMESSAGE), 3f); | |
| } | |
| } | |
| if (player.handCardsCount != handCards.Count) | |
| CorrectUIHandCards(); | |
| } | |
| else | |
| { | |
| //For opponent show number of dummy cards | |
| UpdateOpponentDummyHandCards(cardsCount, true); | |
| } | |
| UpdateDebugHandCardsText(); | |
| } | |
| /// <summary> | |
| /// If there is a issue with the sync then regenerate the hand | |
| /// </summary> | |
| void CorrectUIHandCards() | |
| { | |
| // if (player.handCardsCount != handCards.Count) | |
| { | |
| Game.Log($"Invalid flow. There was a mismatch in hand count fixed now player.handCardsCount {player.handCardsCount} handCards.Count {handCards.Count} ***********************************************************", LogType.Error); | |
| //fix issue where player.cs has more cards than UIPlayer.cs | |
| foreach (UICard uiCard in handCards) | |
| { | |
| if (uiCard.gameObject != null) | |
| SkipBoGameManager.instance.leanPool.Despawn(uiCard.gameObject); | |
| } | |
| handCards.Clear(); | |
| for (int i = 0; i < player.handCardsCount; i++) | |
| { | |
| //spawn at deck and move the card to desired location | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, SkipBoGameManager.instance.deckParent); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| cardObject.SetActive(true); | |
| //set separate scaling for local player and opponent player | |
| switch (player.playerType) | |
| { | |
| case PlayerType.LocalPlayer: | |
| cardRect.localScale = LOCALPLAYERCARDSCALE; | |
| break; | |
| case PlayerType.Opponent: | |
| cardRect.localScale = OPPONENTPLAYERCARDSCALE; | |
| break; | |
| } | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| uiCard.SetupCard(player.Hand[i], CardDragSourceType.Hand); | |
| if (!Game.saveLoadedGame) | |
| uiCard.QuickFlip().FlipCard(); | |
| handCards?.Add(uiCard); | |
| uiCard.ToggleInteractive(false); | |
| } | |
| int index = 0; | |
| Game.Log($"player.handCardsCount {player.handCardsCount} handCards.Count {handCards.Count}", LogType.Log); | |
| foreach (UICard card in handCards) | |
| { | |
| card?.SetParentAndUpdatePosition(handCardsRects[index], vecor2Zero, false, 0.01f, false, LeanTweenType.easeOutExpo, | |
| (uiCard) => | |
| { | |
| if (player?.isLocalPlayer ?? false) | |
| Game.Log($"Game.saveLoadedGame {Game.saveLoadedGame} isMyTurn {player?.isMyTurn ?? false} id {player?.id ?? -1}"); | |
| uiCard?.ToggleInteractive((player?.isMyTurn ?? false) && !Game.saveLoadedGame); | |
| });//enable the collider if its my turn and its not saveLoadedGame case | |
| index++; | |
| } | |
| } | |
| } | |
| void CorrectDiscardPile() | |
| { | |
| Game.Log($"CorrectDiscardPile"); | |
| if (isLocalPlayer) | |
| { | |
| foreach (UICard uiCard in discardPile) | |
| { | |
| if (uiCard.gameObject != null) | |
| SkipBoGameManager.instance.leanPool.Despawn(uiCard.gameObject); | |
| } | |
| discardPile.Clear(); | |
| //next build discard Pile Cards for ai and local player | |
| int count = player.DiscardPileStackOne.Count; | |
| for (int i = 0; i < count; i++) | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackOne[i]); | |
| count = player.DiscardPileStackTwo.Count; | |
| for (int i = 0; i < count; i++) | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackTwo[i]); | |
| count = player.DiscardPileStackThree.Count; | |
| for (int i = 0; i < count; i++) | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackThree[i]); | |
| count = player.DiscardPileStackFour.Count; | |
| for (int i = 0; i < count; i++) | |
| LoadAndCreateDiscardedCardsForRealPlayer(player.DiscardPileStackFour[i]); | |
| for (int i = 0; i < 4; i++) | |
| ReArrangeDiscardPiles(i, 0f, true); | |
| } | |
| } | |
| /// <summary> | |
| /// Show dummy cards when cards are added to network player's Stock pile | |
| /// </summary> | |
| /// <param name="cardsCount"></param> | |
| private void OnCardsAddedToNetworkPlayersStockPile(int cardsCount) | |
| { | |
| UpdateStockPileCardsCountText(); | |
| UpdateStockPileCardsText(); | |
| //TODO: Show Animation | |
| } | |
| /// <summary> | |
| /// For Debug purpose. Shows opponent hand ranks | |
| /// </summary> | |
| internal void UpdateDebugHandCardsText() | |
| { | |
| // Game.Log($"UpdateDebugHandCardsText id {player.id}"); | |
| if (Game.showDebugUI) | |
| { | |
| int cardsCount = player.Hand.Count; | |
| //Game.Log($"UpdateDebugHandCardsText {SkipBoGameManager.instance.showDebugUI} cardsCount {cardsCount}"); | |
| StringBuilder sb = new StringBuilder(); | |
| for (int i = 0; i < cardsCount; i++) sb.Append($" {player.Hand[i].rank},"); | |
| string text = sb.ToString(); | |
| //Game.Log($"UpdateDebugHandCardsText {text} id {player.id}"); | |
| debugHandCardsText.SetText(text); | |
| } | |
| } | |
| /// <summary> | |
| /// For Debug purpose. Shows opponent top stock card rank | |
| /// </summary> | |
| internal void UpdateStockPileCardsText() | |
| { | |
| //Game.Log($"UpdateStockPileCardsText id {player.id}"); | |
| if (Game.showDebugUI) | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| for (int i = 0; i < player.StockPile.Count; i++) | |
| { | |
| sb.Append($"{player.StockPile[i].rank}, "); | |
| } | |
| string text = sb.ToString(); | |
| //Game.Log($"UpdateStockPileCardsText {text} id {player.id}"); | |
| debugStockCardsText.SetText(text); | |
| } | |
| } | |
| /// <summary> | |
| /// Instead of showing real UICard object show only the dummy card. It reduces UI CPU overhead | |
| /// </summary> | |
| internal void UpdateOpponentDummyHandCards(int cardsCount, bool showAnimation) | |
| { | |
| //Game.Log($"UpdateOpponentDummyHandCards count {cardsCount}\t player id {player.id}\t showAnimation {showAnimation}"); | |
| if (showAnimation) | |
| { | |
| for (int i = 5 - cardsCount; i < 5; i++) | |
| { | |
| //Game.Log($"UpdateOpponentDummyHandCards {i}"); | |
| if (i < handCardsRects.Length) | |
| StartCoroutine(ShowDummyHandCardAnimation(handCardsRects[i], (i + 1) * 0.1f)); | |
| } | |
| } | |
| else | |
| { | |
| int handCardsRectsLength = handCardsRects.Length; | |
| for (int i = 0; i < handCardsRectsLength; i++) handCardsRects[i].gameObject.SetActive(false); | |
| for (int i = 0; i < cardsCount; i++) | |
| { | |
| if (i < handCardsRects.Length) | |
| handCardsRects[i].gameObject.SetActive(true); | |
| } | |
| } | |
| UpdateDebugHandCardsText(); | |
| } | |
| /// <summary> | |
| /// Plays opponent dummy card rect animation from deck to the hand | |
| /// </summary> | |
| /// <param name="card"></param> | |
| private IEnumerator ShowDummyHandCardAnimation(RectTransform card, float time) | |
| { | |
| if (card != null) | |
| { | |
| card.gameObject.SetActive(true); | |
| Vector2 toPos = card.anchoredPosition; | |
| Vector3 toRot = card.eulerAngles; | |
| Vector3 toScale = card.localScale; | |
| card.SetParent(SkipBoGameManager.instance.deckParent);//first set the deck as parent so we can start the animation from deck pos | |
| card.anchoredPosition = vecor2Zero;//set the position to zero relative to deck parent | |
| card.SetParent(handCardsParent);//now set the parent to default one and play the tween | |
| LeanTween.value(card.gameObject, (Vector2 value) => card.anchoredPosition = value, card.anchoredPosition, toPos, Game.saveLoadedGame ? 0 : time).setEase(LeanTweenType.easeOutCirc); | |
| LeanTween.value(card.gameObject, (Vector2 value) => card.eulerAngles = value, vecor2Zero, toRot, Game.saveLoadedGame ? 0 : time); | |
| LeanTween.value(card.gameObject, (Vector3 value) => card.localScale = value, new Vector3(5, 5, 1), toScale, Game.saveLoadedGame ? 0 : time); | |
| } | |
| yield return new WaitForSeconds(0.2f); | |
| } | |
| /// <summary> | |
| /// Called from an event when cards are added to stock pile. which happens only once in the begining | |
| /// and one card if player did not play in his turn | |
| /// </summary> | |
| /// <param name="cards"></param> | |
| private void onCardsAddedToStockPile(List<Card> cards) | |
| { | |
| // Game.Log($"UIPlayer.cs onCardsAddedToStockPile stock pile {cards.Count}"); | |
| int cardsCount = cards.Count; | |
| int dummyCardsAnimationCount = cardsCount; | |
| if (dummyCardsAnimationCount > 5) dummyCardsAnimationCount = 5; | |
| if (cardsCount > 0) | |
| { | |
| //Animate dummy cards | |
| // if(false) | |
| { | |
| // for (int i = 0; i < cardsCount; i++) | |
| for (int i = 0; i < dummyCardsAnimationCount; i++) //show only 5 cards no matter the pile size | |
| { | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, SkipBoGameManager.instance.deckParent); | |
| cardObject.SetActive(true); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| UICard uiCard = cardObject.GetComponent<UICard>(); | |
| Vector2 scaleTo = vecor2Zero; | |
| float time = 0.2f; | |
| // if (cardsCount > 10) time = 0.07f; | |
| //set separate scaling for local player and opponent player | |
| switch (player.playerType) | |
| { | |
| case PlayerType.LocalPlayer: scaleTo = LOCALPLAYERSTOCKPILECARDSCALE; break; | |
| case PlayerType.Opponent: scaleTo = OPPONENTPLAYERSTOCKPILECARDSCALE; break; | |
| } | |
| cardRect.localScale = scaleTo * 0.5f; | |
| // uiCard.SetupCard(cards[i], CardDragSourceType.StockPile).QuickFlip().ToggleInteractive(false); | |
| uiCard.QuickFlip().ToggleInteractive(false); | |
| uiCard.TweenScale(scaleTo, (dummyCardsAnimationCount - i + 1) * time); | |
| uiCard.SetParentAndUpdatePosition(stockPileTopCardParent, vecor2Zero, true, Game.saveLoadedGame ? 0 : (dummyCardsAnimationCount - i + 1) * time, true, LeanTweenType.easeOutCirc); | |
| } | |
| } | |
| //Show only Top Card | |
| if (stockPileCard == null) | |
| { | |
| GameObject cardObject = SkipBoGameManager.instance.leanPool.Spawn(vecor2Zero, Quaternion.identity, stockPileTopCardParent); | |
| cardObject.SetActive(true); | |
| RectTransform cardRect = cardObject.GetComponent<RectTransform>(); | |
| stockPileCard = cardObject.GetComponent<UICard>(); | |
| //set separate scaling for local player and opponent player | |
| switch (player.playerType) | |
| { | |
| case PlayerType.LocalPlayer: cardRect.localScale = LOCALPLAYERSTOCKPILECARDSCALE; break; | |
| case PlayerType.Opponent: cardRect.localScale = OPPONENTPLAYERSTOCKPILECARDSCALE; stockPileCard.ToggleInteractive(false); break; | |
| } | |
| stockPileCard.SetupCard(cards[cardsCount - 1], CardDragSourceType.StockPile); | |
| } | |
| else | |
| stockPileCard.SetupCard(cards[cardsCount - 1], CardDragSourceType.StockPile); | |
| stockPileCard.ToggleInteractive(false); | |
| UpdateStockPileCardsCountText(); | |
| UpdateStockPileCardsText(); | |
| } | |
| } | |
| /// <summary> | |
| /// Called from event when the player turn begins | |
| /// </summary> | |
| private void onMyTurnBegin() | |
| { | |
| Game.Log($"^onMyTurnBegin******************************************* ID : {player} Game.tutorialStep {Game.tutorialStep} gameObject.name {gameObject.name}"); | |
| //TODO: Show some turn indicator Animation | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| { | |
| // DestroyUnlinkedCards(); | |
| // UIDropCell.onValidDropEvent += onValidDrop; | |
| player.onTimerTickEvent += OnTimerTick; | |
| if (player.isMyTurn) | |
| { | |
| TogglePlayerCardsTouch(true); | |
| if (Game.isOnlineGame && turnTimer != null && Game.useMultiplayerTimer) | |
| turnTimer.SetActive(true); | |
| } | |
| if (Game.showingTutorial) | |
| { | |
| if (Game.tutorialStep == 0) | |
| StartCoroutine("ContinueTutorialStepZero"); | |
| else if (Game.tutorialStep == 7) | |
| StartCoroutine("ContinueTutorialStepEight"); | |
| } | |
| } | |
| else | |
| { | |
| // LeanTween.value(playerPanelBG.gameObject, (Color col) => playerPanelBG.color = col, playerPanelBGDefaultColor, playerPanelBGTurnColor, 0.5f); | |
| // playerPanelBG.color = playerPanelBGTurnColor; | |
| } | |
| if (!player.isMyTurn) | |
| ToggleTurnTimer(false); | |
| else | |
| { | |
| HideOthersTurnHighlightImage(); | |
| ToggleTurnTimer(true); | |
| } | |
| } | |
| private void HideOthersTurnHighlightImage() | |
| { | |
| SkipBoGameManager.instance.HideOthersTurnHighlightImage(id); | |
| } | |
| private void OnTimerTick(int tick) | |
| { | |
| if (tick < 0) tick = 0; | |
| turnTimerLabel.SetText(tick.ToString()); | |
| } | |
| /// <summary> | |
| /// Called from event when the player turn is over | |
| /// </summary> | |
| private void onMyTurnEnd() | |
| { | |
| Game.Log($"^onMyTurnEnd******************************************* ID : {player.id}"); | |
| //TODO: add turn over animation | |
| // UIDropCell.onValidDropEvent -= onValidDrop; | |
| player.onTimerTickEvent -= OnTimerTick; | |
| TogglePlayerCardsTouch(false); | |
| ToggleTurnTimer(false); | |
| timerImage.SetActive(false); | |
| if (turnTimer != null) | |
| turnTimer.SetActive(false); | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| DestroyUnlinkedCards(); | |
| StartCoroutine(ReArrangeHandCards(UIDropCell.CellType.DiscardPile)); | |
| //if (player.playerType == PlayerType.Opponent) | |
| // LeanTween.value(playerPanelBG.gameObject, (Color col) => playerPanelBG.color = col, playerPanelBGTurnColor, playerPanelBGDefaultColor, 0.5f); | |
| //playerPanelBG.color = playerPanelBGDefaultColor; | |
| } | |
| /// <summary> | |
| /// Toggles interactive for local player's hand discard and stock piles | |
| /// </summary> | |
| /// <param name="enable"></param> | |
| private void TogglePlayerCardsTouch(bool enable) | |
| { | |
| Game.Log($"TogglePlayerCardsTouch {enable}"); | |
| int handCardsCount = handCards?.Count ?? 0; | |
| int dropPileCount = discardPile?.Count ?? 0; | |
| for (int i = 0; i < handCardsCount; i++) handCards[i]?.ToggleInteractive(enable); | |
| for (int i = 0; i < dropPileCount; i++) discardPile[i]?.ToggleInteractive(false); | |
| stockPileCard?.ToggleInteractive(enable); | |
| if (player.playerType == PlayerType.LocalPlayer) | |
| { | |
| for (int i = 0; i < 4; i++) | |
| ReArrangeDiscardPiles(i, 0f, enable); | |
| } | |
| } | |
| internal void SetName(string name) | |
| { | |
| nameLabel.SetText(name); | |
| } | |
| internal void UpdateStockPileCardsCountText() | |
| { | |
| stockPileCountLabel.SetText(player.stockPileCardsCount.ToString()); | |
| } | |
| /// <summary> | |
| /// Disables collision for hand | |
| /// </summary> | |
| internal UIPlayer DisableHand() | |
| { | |
| handCards.ForEach(c => c.ToggleInteractive(false)); | |
| return this; | |
| } | |
| /// <summary> | |
| /// Enables collision for hand | |
| /// </summary> | |
| internal UIPlayer EnableHand() | |
| { | |
| handCards.ForEach(c => c.ToggleInteractive(true)); | |
| return this; | |
| } | |
| /// <summary> | |
| /// Disables collision for stock pile | |
| /// </summary> | |
| internal UIPlayer DisableStockPile() | |
| { | |
| stockPileCard.ToggleInteractive(false); | |
| return this; | |
| } | |
| /// <summary> | |
| /// Enables collision for stock pile | |
| /// </summary> | |
| internal UIPlayer EnableStockPile() | |
| { | |
| stockPileCard.ToggleInteractive(true); | |
| return this; | |
| } | |
| /// <summary> | |
| /// Finds and returns card by rank. Does not remove from the hand | |
| /// </summary> | |
| /// <param name="rank"></param> | |
| /// <returns></returns> | |
| internal UICard FindHandCardByRank(int rank) => handCards.Find(c => c.card.rank == rank); | |
| private void OnDestroy() | |
| { | |
| handCards.Clear(); | |
| discardPile.Clear(); | |
| RemoveListeners(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment