using GUPS.AntiCheat.Protected; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; public class Game_Lucky : MonoBehaviour { public LuckyGameCupCounter m_LuckyGameCupCounter; public Game_Lucky_Result m_Game_Lucky_Result; public Image i_girl, i_refillbtn; public GameObject[] gos_boobs; public TextMeshProUGUI[] texts; // 0 시간, 1 null, 2 컵안 오브젝트 갯수, 3 리필 횟수, 4 리필 갯수 public TextMeshProUGUI[] texts_money; // 0 하트 코인, 1 챗 코인, 2 가챠 코인 public GameObject go_dropobj; // 떨어질 공 prefab public Transform tf_cup; // 컵 (움직이고 회전하는 부분) public Transform tf_cupin; // 컵 안 (공들이 들어가는 위치 부모) public Transform tf_fallobjs; // 컵 안에서 밖으로 떨어지는 공들의 부모 public Transform tf_refillobjs; // 리필 공들 public Transform tf_addobjs; // 추가 공들 (+, x 에 의해 추가되는 공들) List list_dropobj = new List(); public List list_randomblock; // 회전 관련 변수 private bool isRotating = false; private float targetZ = -150f; private float originalZ = 0f; private float rotateSpeed = 150f; // 초당 몇 도 회전할지 float Cup_minX, Cup_maxX; [SerializeField] private float cupMargin = 128.5f; // 간격 bool bRotCup = false, updateTime = false, isRefill = false; ProtectedFloat m_Time; Dictionary dic_Amount = new Dictionary { { eMoney.AlbumOpen, 0 }, { eMoney.Chat, 0 }, { eMoney.Gacha, 0 }, }; ProtectedInt32 _bb; public int m_BubbleAmount { get { return _bb; } set { _bb = value; _bb.Obfuscate(); } } ProtectedInt32 TotalBubbleAmount = 50, m_RefillCount = 0; int CupInAmount = 0; // 컵 안에 있는 오브젝트 갯수 AsyncOperationHandle m_Handle; int curGirl; private void Awake() { // 화면 좌표 (0,0) → 월드 좌표 Vector3 leftWorld = Camera.main.ScreenToWorldPoint( new Vector3(0 + cupMargin, Screen.height / 2f, Camera.main.nearClipPlane)); // 화면 좌표 (Screen.width,0) → 월드 좌표 Vector3 rightWorld = Camera.main.ScreenToWorldPoint( new Vector3(Screen.width - cupMargin, Screen.height / 2f, Camera.main.nearClipPlane)); Cup_minX = leftWorld.x; Cup_maxX = rightWorld.x; var refill = table_GlobalValue.Ins.Get_Int("LuckyGame_RefillAmount") << 1; for (int i = 0; i < refill; i++) { var obj = DSUtil.Get_Clone(go_dropobj, tf_refillobjs); obj.gameObject.SetActive(false); } texts[4].text = $"x{table_GlobalValue.Ins.Get_Int("LuckyGame_RefillAmount")}"; // 기본 공 + 리필 공 에 최고 배수만큼 미리 생성 var addobjAmount = (TotalBubbleAmount + refill) * 5; for (int i = 0; i < addobjAmount; i++) { var obj = DSUtil.Get_Clone(go_dropobj, tf_addobjs); obj.gameObject.SetActive(false); } } public void Set() { gameObject.SetActive(true); SoundInfo.Ins.Play_BGM(eBGM.b007_LuckyGame); m_LuckyGameCupCounter.Set(count => { texts[2].text = count.ToString(); }); m_Game_Lucky_Result.gameObject.SetActive(false); ADInfo.Ins.Set_Banner(false); isRefill = bRotCup = false; curGirl = SaveMgr.Ins.Get_SelectGirlID(); i_girl.enabled = false; AddrResourceMgr.Ins.LoadObject($"Girl_LuckyGame/{curGirl}.png", handle => { m_Handle = handle; i_girl.enabled = true; i_girl.sprite = handle.Result; }); m_RefillCount = SaveMgr.Ins.Get_LuckyGameRefill(); m_RefillCount.Obfuscate(); DSUtil.InActivateGameObjects(gos_boobs, curGirl - 1); // tf_cup 초기화 tf_cup.localPosition = Vector3.zero; tf_cup.rotation = Quaternion.Euler(0, 0, 0); originalZ = tf_cup.eulerAngles.z; StartCoroutine(Co_Block()); Set_Ball(); Init_game(); Set_Texts(); } void Set_Ball() { // list_dropobj.Count 가 0 이면 50개 생성해서 tf_cupin 안에 넣기 if (list_dropobj.Count == 0) { TotalBubbleAmount.Obfuscate(); for (int i = 0; i < TotalBubbleAmount; i++) { GameObject obj = Instantiate(go_dropobj, tf_cupin); obj.transform.localPosition = Get_CupInLocalPos(); list_dropobj.Add(obj); } } if (list_dropobj.Count > TotalBubbleAmount) { var moveCount = list_dropobj.Count - TotalBubbleAmount; var maxRefiil = table_GlobalValue.Ins.Get_Int("LuckyGame_RefillAmount") << 1; if (moveCount > maxRefiil) moveCount = maxRefiil; for (int i = 0; i < moveCount; i++) { list_dropobj[0].transform.SetParent(tf_refillobjs); list_dropobj[0].gameObject.SetActive(false); list_dropobj.RemoveAt(0); } } if (list_dropobj.Count > TotalBubbleAmount) { var moveCount = list_dropobj.Count - TotalBubbleAmount; for (int i = 0; i < moveCount; i++) { list_dropobj[0].transform.SetParent(tf_addobjs); list_dropobj[0].gameObject.SetActive(false); list_dropobj.RemoveAt(0); } } CupInAmount = TotalBubbleAmount; texts[2].text = CupInAmount.ToString(); // 글로벌 밸류에 설정된 비율에 따라 볼 설정 var chatcoin = TotalBubbleAmount * table_GlobalValue.Ins.Get_Float("LuckyChatCoinRate"); var heartcoin = TotalBubbleAmount * table_GlobalValue.Ins.Get_Float("LuckyAlbumOpenRate"); var iLoop_chatcoin = 0; var iLoop_heartcoin = 0; for (int i = 0; i < TotalBubbleAmount; i++) { if (iLoop_chatcoin < chatcoin) { ++iLoop_chatcoin; list_dropobj[i].GetComponent().Init(eMoney.Chat, Get_CupInLocalPos(), tf_cupin, tf_fallobjs); } else if (iLoop_heartcoin < heartcoin) { ++iLoop_heartcoin; list_dropobj[i].GetComponent().Init(eMoney.AlbumOpen, Get_CupInLocalPos(), tf_cupin, tf_fallobjs); } else list_dropobj[i].GetComponent().Init(eMoney.Gacha, Get_CupInLocalPos(), tf_cupin, tf_fallobjs); } } void Init_game() { updateTime = true; m_Time = 30f; m_Time.Obfuscate(); dic_Amount[eMoney.AlbumOpen] = 0; dic_Amount[eMoney.AlbumOpen].Obfuscate(); dic_Amount[eMoney.Chat] = 0; dic_Amount[eMoney.Chat].Obfuscate(); dic_Amount[eMoney.Gacha] = 0; dic_Amount[eMoney.Gacha].Obfuscate(); m_BubbleAmount = 0; } void Set_Texts() { texts[0].text = m_Time.Value.ToString("N0"); i_refillbtn.sprite = UIAtlasMgr.Ins.Get_Sprite(m_RefillCount > 0 ? "refill btn_lucky mini game" : "refill btn lock_lucky mini game"); texts[3].text = m_RefillCount.ToString(); texts_money[0].text = dic_Amount[eMoney.AlbumOpen].ToString(); texts_money[1].text = dic_Amount[eMoney.Chat].ToString(); texts_money[2].text = dic_Amount[eMoney.Gacha].ToString(); } public void Add_Amount(eMoney money, int amount) { dic_Amount[money] += amount; dic_Amount[money].Obfuscate(); Set_Texts(); ++m_BubbleAmount; if (m_BubbleAmount >= list_dropobj.Count) GameOver(); } void GameOver() { StartCoroutine(Co_GameOver()); } IEnumerator Co_GameOver() { updateTime = false; list_dropobj.ForEach(f => f.GetComponent().StopObj()); yield return new WaitForSecondsRealtime(0.5f); m_Game_Lucky_Result.Set(dic_Amount); StopAllCoroutines(); } public void ReleaseImage() { AddrResourceMgr.Ins.Relese(m_Handle); i_girl.sprite = null; gameObject.SetActive(false); } Vector3 Get_CupInLocalPos(float addy = 0f) { return new Vector3(Random.Range(-50f, 50f), Random.Range(-50f, 50f) + addy, 0f); } public void OnMyDrag() { if (!bRotCup) { Vector3 mousePos = Input.mousePosition; Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, Camera.main.nearClipPlane)); // 컵의 x 위치를 화면 경계 안으로 Clamp Vector3 cupPos = tf_cup.position; cupPos.x = Mathf.Clamp(worldPos.x, Cup_minX, Cup_maxX); tf_cup.position = cupPos; } } public void OnClick_Screen() { if (bRotCup) { return; } bRotCup = true; // 마우스/터치 입력 위치 → 월드 좌표 변환 Vector3 mousePos = Input.mousePosition; Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos); // tf_cup을 터치한 위치의 x 값만 받아서 거기에 위치시킴 Vector3 cupPos = tf_cup.position; cupPos.x = Mathf.Clamp(worldPos.x, Cup_minX, Cup_maxX); tf_cup.position = cupPos; // 회전 시작 (목표: -150도) targetZ = -150f; isRotating = true; SoundInfo.Ins.Play_OneShot((eSound)Random.Range(14, 16)); } public void OnPointerDown() { isRotating = true; } public void OnPointerUp() { isRotating = false; } private void Update() { if (isRefill) return; float currentZ = tf_cup.eulerAngles.z; if (currentZ > 180f) currentZ -= 360f; // -180~180 범위 보정 if (isRotating) { // 목표 각도로 이동 float newZ = Mathf.MoveTowards(currentZ, targetZ, rotateSpeed * Time.deltaTime); tf_cup.rotation = Quaternion.Euler(0, 0, newZ); } else { // 손을 뗐을 때 원래 각도로 복귀 float newZ = Mathf.MoveTowards(currentZ, originalZ, rotateSpeed * Time.deltaTime); tf_cup.rotation = Quaternion.Euler(0, 0, newZ); } if (updateTime && m_Time > 0f) { m_Time -= Time.deltaTime; Set_Texts(); if (m_Time <= 0f) GameOver(); } } IEnumerator Co_Block() { list_randomblock.ForEach(f => f.Init()); LuckyRandomBlock PreBlock = null; while (true) { for (int i = 0; i < list_randomblock.Count; i++) { if (!list_randomblock[i].IsMoving() && (PreBlock == null || PreBlock.IsCrossTwoThirds())) { PreBlock = list_randomblock[i]; PreBlock.Move(); } } yield return null; } } public void OnClick_Refill() { if (!isRefill && m_RefillCount > 0) { --m_RefillCount; m_RefillCount.Obfuscate(); Set_Texts(); StartCoroutine(Co_Refill()); } } IEnumerator Co_Refill() { isRefill = true; tf_cup.rotation = Quaternion.Euler(0, 0, 0); m_LuckyGameCupCounter.StartRefill(); var TotalRefillAmount = table_GlobalValue.Ins.Get_Int("LuckyGame_RefillAmount"); // 글로벌 밸류에 설정된 비율에 따라 볼 설정 var chatcoin = TotalRefillAmount * table_GlobalValue.Ins.Get_Float("LuckyChatCoinRate"); var heartcoin = TotalRefillAmount * table_GlobalValue.Ins.Get_Float("LuckyAlbumOpenRate"); var iLoop_chatcoin = 0; var iLoop_heartcoin = 0; for (int i = 0; i < TotalRefillAmount; i++) { for (int j = 0; j < tf_refillobjs.childCount; j++) { var child = tf_refillobjs.GetChild(j); if (!child.gameObject.activeInHierarchy) { list_dropobj.Add(child.gameObject); if (iLoop_chatcoin < chatcoin) { ++iLoop_chatcoin; child.GetComponent().Init(eMoney.Chat, Get_CupInLocalPos(100f), tf_cupin, tf_fallobjs); } else if (iLoop_heartcoin < heartcoin) { ++iLoop_heartcoin; child.GetComponent().Init(eMoney.AlbumOpen, Get_CupInLocalPos(100f), tf_cupin, tf_fallobjs); } else child.GetComponent().Init(eMoney.Gacha, Get_CupInLocalPos(100f), tf_cupin, tf_fallobjs); yield return new WaitForSeconds(0.5f); break; } } } while (m_LuckyGameCupCounter.refillobjectCount < TotalRefillAmount) yield return null; m_LuckyGameCupCounter.EndRefill(); isRefill = false; } public void Add_Ball(eMoney money, Vector3 pos) { for (int i = 0; i < tf_addobjs.childCount; i++) { var child = tf_addobjs.GetChild(i); if (!child.gameObject.activeInHierarchy) { list_dropobj.Add(child.gameObject); child.GetComponent().Init_Add(money, pos, tf_fallobjs); break; } } } }