SelectHandEffect.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System.Linq;
  5. using Photon;
  6. using Photon.Pun;
  7. using System;
  8. public class SelectHandEffect : MonoBehaviourPunCallbacks
  9. {
  10. public void SetUp(
  11. Player selectPlayer,
  12. Func<CardSource, bool> canTargetCondition,
  13. Func<List<CardSource>, CardSource, bool> canTargetCondition_ByPreSelecetedList,
  14. Func<List<CardSource>, bool> canEndSelectCondition,
  15. int maxCount,
  16. bool canNoSelect,
  17. bool canEndNotMax,
  18. bool isShowOpponent,
  19. Func<CardSource, IEnumerator> selectCardCoroutine,
  20. Func<List<CardSource>, IEnumerator> afterSelectCardCoroutine,
  21. Mode mode,
  22. ICardEffect cardEffect)
  23. {
  24. _selectPlayer = selectPlayer;
  25. _canTargetCondition = canTargetCondition;
  26. _canTargetCondition_ByPreSelecetedList = canTargetCondition_ByPreSelecetedList;
  27. _canEndSelectCondition = canEndSelectCondition;
  28. _maxCount = maxCount;
  29. _canNoSelect = canNoSelect;
  30. _canEndNotMax = canEndNotMax;
  31. _isShowOpponent = isShowOpponent;
  32. _selectCardCoroutine = selectCardCoroutine;
  33. _afterSelectCardCoroutine = afterSelectCardCoroutine;
  34. _mode = mode;
  35. _cardEffect = cardEffect;
  36. _showCard = true;
  37. _digiXros = false;
  38. _customMessage_ShowCard = null;
  39. _customMessage = "";
  40. _customMessage_Enemy = "";
  41. _showOpponentMessage = true;
  42. _isLocal = false;
  43. _isFaceUp = false;
  44. }
  45. public void SetIsLocal()
  46. {
  47. _isLocal = true;
  48. }
  49. public void SetNotShowCard()
  50. {
  51. _showCard = false;
  52. }
  53. public void SetDigiXros()
  54. {
  55. _digiXros = true;
  56. }
  57. public void SetIsFaceup()
  58. {
  59. _isFaceUp = true;
  60. }
  61. public void SetReducedCostTuple((int reduceCost, Func<CardSource, bool> reduceCostCardCondition)? reduceCostTuple)
  62. {
  63. _reduceCostTuple = reduceCostTuple;
  64. }
  65. public void SetFixedCostTuple((int fixedCost, Func<CardSource, bool> fixedCostCardCondition)? fixedCostTuple)
  66. {
  67. _fixedCostTuple = fixedCostTuple;
  68. }
  69. public void SetUpCustomMessage_ShowCard(string CustomMessage_ShowCard)
  70. {
  71. _customMessage_ShowCard = CustomMessage_ShowCard;
  72. }
  73. public void SetUpCustomMessage(string CustomMessage, string CustomMessage_Enemy)
  74. {
  75. _customMessage = CustomMessage;
  76. _customMessage_Enemy = CustomMessage_Enemy;
  77. }
  78. public void SetNotShowOpponentMessage()
  79. {
  80. _showOpponentMessage = false;
  81. }
  82. //The player who selects the hand
  83. Player _selectPlayer;
  84. //Conditions of the cards that can be selected
  85. Func<CardSource, bool> _canTargetCondition = null;
  86. //Whether the card can be selected with the current selection list status
  87. Func<List<CardSource>, CardSource, bool> _canTargetCondition_ByPreSelecetedList = null;
  88. //Conditions under which a selection can be terminated (see list of selection termination points)
  89. Func<List<CardSource>, bool> _canEndSelectCondition = null;
  90. //Maximum number of sheets to be selected
  91. int _maxCount = 0;
  92. //Whether you can choose not to choose
  93. bool _canNoSelect = false;
  94. //Whether you can finish your selection with less than the maximum number
  95. bool _canEndNotMax = false;
  96. //Whether or not to show it to the other player
  97. bool _isShowOpponent = false;
  98. //(Limited to Mode.Custom) Processing to be performed by selecting
  99. Func<CardSource, IEnumerator> _selectCardCoroutine = null;
  100. //Processing to be done after selection
  101. Func<List<CardSource>, IEnumerator> _afterSelectCardCoroutine = null;
  102. //Classification of processing to be done by selection
  103. Mode _mode = Mode.Custom;
  104. //Skill in making card selections
  105. ICardEffect _cardEffect;
  106. bool _showCard = true;
  107. bool _digiXros = false;
  108. bool _isLocal = false;
  109. bool _isFaceUp = false;
  110. (int reduceCost, Func<CardSource, bool> reduceCostCardCondition)? _reduceCostTuple = null;
  111. (int fixedCost, Func<CardSource, bool> fixedCostCardCondition)? _fixedCostTuple = null;
  112. public enum Mode
  113. {
  114. Discard,
  115. PutLibraryTop,
  116. PutLibraryBottom,
  117. PutSecurityBottom,
  118. PlayForFree,
  119. PlayForCost,
  120. Custom
  121. }
  122. //Selected Hand Card List
  123. List<CardSource> _targetCards = new List<CardSource>();
  124. //No Selection Flag
  125. bool _noSelect = false;
  126. string _customMessage_ShowCard = null;
  127. string _customMessage = null;
  128. string _customMessage_Enemy = null;
  129. bool _showOpponentMessage = true;
  130. #region Whether choice is possible
  131. public bool active()
  132. {
  133. if (_maxCount <= 0) return false;
  134. if (_selectPlayer != null)
  135. {
  136. if (_selectPlayer.HandCards.Count((cardSource) => _canTargetCondition(cardSource)) > 0)
  137. {
  138. return true;
  139. }
  140. }
  141. return false;
  142. }
  143. #endregion
  144. public virtual IEnumerator Activate()
  145. {
  146. bool oldIsSelecting = GManager.instance.turnStateMachine.IsSelecting;
  147. List<PlayPermanentClass> playCharas = new List<PlayPermanentClass>();
  148. List<IDiscardHand> discardHands = new List<IDiscardHand>();
  149. List<CardSource> putClockCards = new List<CardSource>();
  150. _noSelect = false;
  151. if (active())
  152. {
  153. if (_maxCount == 0)
  154. {
  155. _canNoSelect = true;
  156. }
  157. _targetCards = new List<CardSource>();
  158. foreach (Player player in GManager.instance.turnStateMachine.gameContext.Players)
  159. {
  160. GManager.instance.turnStateMachine.OffFieldCardTarget(player);
  161. GManager.instance.turnStateMachine.OffHandCardTarget(player);
  162. }
  163. if (_selectPlayer.isYou)
  164. {
  165. GManager.instance.sideBar.SetUpSideBar();
  166. GManager.instance.turnStateMachine.IsSelecting = true;
  167. #region Message Display
  168. if (!string.IsNullOrEmpty(_customMessage))
  169. {
  170. GManager.instance.commandText.OpenCommandText(_customMessage, _digiXros);
  171. }
  172. else
  173. {
  174. string message = "";
  175. switch (_mode)
  176. {
  177. case Mode.Discard:
  178. message = "Select cards to discard.";
  179. break;
  180. case Mode.PutLibraryTop:
  181. message = "Select cards to put on top of the deck.";
  182. break;
  183. case Mode.PutLibraryBottom:
  184. if (_maxCount >= 2)
  185. {
  186. message = "Select cards to put on bottom of the deck\n(cards will be placed back to the bottom of the deck so that cards with lower numbers are on top).";
  187. }
  188. else
  189. {
  190. message = "Select cards to put on bottom of the deck.";
  191. }
  192. break;
  193. case Mode.PutSecurityBottom:
  194. string str = _isFaceUp ? "faceup" : "facedown";
  195. message = $"Select card(s) to put on bottom of the security {str}.";
  196. break;
  197. case Mode.PlayForFree:
  198. message = "Select cards to play for without paying the cost.";
  199. break;
  200. case Mode.PlayForCost:
  201. message = "Select cards to play.";
  202. break;
  203. case Mode.Custom:
  204. message = "Select cards in your hand.";
  205. break;
  206. }
  207. if (!string.IsNullOrEmpty(message))
  208. {
  209. GManager.instance.commandText.OpenCommandText(message, _digiXros);
  210. }
  211. }
  212. #endregion
  213. List<CardSource> PreSelectedHandCards = new List<CardSource>();
  214. foreach (HandCard handCard in _selectPlayer.HandCardObjects)
  215. {
  216. if (handCard != null)
  217. {
  218. if (_canTargetCondition(handCard.cardSource))
  219. {
  220. handCard.AddClickTarget(OnClickHandCard);
  221. }
  222. }
  223. }
  224. CheckEndSelect();
  225. #region Processing when a card in the hand is clicked
  226. void OnClickHandCard(HandCard handCard)
  227. {
  228. if (PreSelectedHandCards.Contains(handCard.cardSource))
  229. {
  230. PreSelectedHandCards.Remove(handCard.cardSource);
  231. }
  232. else
  233. {
  234. if (_canTargetCondition_ByPreSelecetedList != null)
  235. {
  236. List<CardSource> _PreSelectedList = new List<CardSource>();
  237. for (int i = 0; i < PreSelectedHandCards.Count; i++)
  238. {
  239. if (PreSelectedHandCards.Count >= _maxCount && i == PreSelectedHandCards.Count - 1)
  240. {
  241. continue;
  242. }
  243. _PreSelectedList.Add(PreSelectedHandCards[i]);
  244. }
  245. if (!_canTargetCondition_ByPreSelecetedList(_PreSelectedList, handCard.cardSource))
  246. {
  247. return;
  248. }
  249. }
  250. if (PreSelectedHandCards.Count < _maxCount)
  251. {
  252. PreSelectedHandCards.Add(handCard.cardSource);
  253. }
  254. else
  255. {
  256. if (PreSelectedHandCards.Count > 0)
  257. {
  258. PreSelectedHandCards.RemoveAt(PreSelectedHandCards.Count - 1);
  259. PreSelectedHandCards.Add(handCard.cardSource);
  260. }
  261. }
  262. if (!ContinuousController.instance.checkBeforeEndingSelection
  263. && !_canNoSelect
  264. && !_canEndNotMax
  265. && _maxCount == PreSelectedHandCards.Count)
  266. {
  267. EndSelect_RPC();
  268. return;
  269. }
  270. }
  271. CheckEndSelect();
  272. }
  273. #endregion
  274. void EndSelect_RPC()
  275. {
  276. foreach (Player player in GManager.instance.turnStateMachine.gameContext.Players)
  277. {
  278. foreach (Permanent permanent in player.GetFieldPermanents())
  279. {
  280. permanent.ShowingPermanentCard.RemoveSelectEffect();
  281. permanent.ShowingPermanentCard.RemoveClickTarget();
  282. }
  283. foreach (HandCard handCard in player.HandCardObjects)
  284. {
  285. if (handCard != null)
  286. {
  287. handCard.RemoveClickTarget();
  288. handCard.RemoveSelectEffect();
  289. }
  290. }
  291. }
  292. List<int> CardIDs = new List<int>();
  293. foreach (CardSource cardSource in PreSelectedHandCards)
  294. {
  295. CardIDs.Add(cardSource.CardIndex);
  296. }
  297. if (!_isLocal)
  298. {
  299. photonView.RPC("SetTargetHandCards", RpcTarget.All, _selectPlayer.PlayerID, CardIDs.ToArray());
  300. }
  301. else
  302. {
  303. SetTargetHandCards(_selectPlayer.PlayerID, CardIDs.ToArray());
  304. }
  305. GManager.instance.BackButton.CloseSelectCommandButton();
  306. }
  307. #region Determines if selection can be terminated and displays UI
  308. void CheckEndSelect()
  309. {
  310. #region UI display depending on whether it can be terminated
  311. if (CanEndSelect(PreSelectedHandCards))
  312. {
  313. GManager.instance.selectCommandPanel.SetUpCommandButton(
  314. new List<Command_SelectCommand>()
  315. {
  316. new Command_SelectCommand("End Selection", EndSelect_RPC, 0)
  317. });
  318. }
  319. else
  320. {
  321. GManager.instance.selectCommandPanel.Off(false);
  322. GManager.instance.sideBar.SetUpSideBar();
  323. }
  324. #endregion
  325. #region Card UI display by selection list
  326. foreach (CardSource cardSource in _selectPlayer.HandCards)
  327. {
  328. if (cardSource.ShowingHandCard != null)
  329. {
  330. cardSource.ShowingHandCard.RemoveSelectEffect();
  331. cardSource.ShowingHandCard.OffSelectedIndexText();
  332. if (_canTargetCondition(cardSource))
  333. {
  334. if (PreSelectedHandCards.Contains(cardSource))
  335. {
  336. cardSource.ShowingHandCard.OnSelect();
  337. cardSource.ShowingHandCard.SetOrangeOutline();
  338. cardSource.ShowingHandCard.SetSelectedIndexText(PreSelectedHandCards.IndexOf(cardSource) + 1);
  339. }
  340. else
  341. {
  342. cardSource.ShowingHandCard.OnSelect();
  343. cardSource.ShowingHandCard.SetBlueOutline();
  344. if (_canTargetCondition_ByPreSelecetedList != null)
  345. {
  346. List<CardSource> _PreSelectedList = new List<CardSource>();
  347. for (int i = 0; i < PreSelectedHandCards.Count; i++)
  348. {
  349. if (PreSelectedHandCards.Count >= _maxCount && i == PreSelectedHandCards.Count - 1)
  350. {
  351. continue;
  352. }
  353. _PreSelectedList.Add(PreSelectedHandCards[i]);
  354. }
  355. if (!_canTargetCondition_ByPreSelecetedList(_PreSelectedList, cardSource))
  356. {
  357. cardSource.ShowingHandCard.RemoveSelectEffect();
  358. }
  359. }
  360. }
  361. }
  362. }
  363. }
  364. #endregion
  365. if (PreSelectedHandCards.Count >= 1)
  366. {
  367. GManager.instance.BackButton.CloseSelectCommandButton();
  368. }
  369. else
  370. {
  371. if (_canNoSelect)
  372. {
  373. GManager.instance.BackButton.OpenSelectCommandButton("No Selection", () => NoSelect_RPC(), 0);
  374. void NoSelect_RPC()
  375. {
  376. if (!_isLocal)
  377. {
  378. photonView.RPC("SetTargetHandCards", RpcTarget.All, _selectPlayer.PlayerID, null);
  379. }
  380. else
  381. {
  382. SetTargetHandCards(_selectPlayer.PlayerID, null);
  383. }
  384. }
  385. }
  386. }
  387. }
  388. #endregion
  389. }
  390. else
  391. {
  392. #region Message Display
  393. if (_showOpponentMessage)
  394. {
  395. if (!string.IsNullOrEmpty(_customMessage_Enemy))
  396. {
  397. GManager.instance.commandText.OpenCommandText(_customMessage_Enemy, _digiXros);
  398. }
  399. else
  400. {
  401. GManager.instance.commandText.OpenCommandText("The opponent is selecting cards.", _digiXros);
  402. }
  403. }
  404. #endregion
  405. #region AI
  406. if (GManager.instance.IsAI)
  407. {
  408. List<CardSource> ValidCards = new List<CardSource>();
  409. foreach (CardSource cardSource in _selectPlayer.HandCards)
  410. {
  411. if (_canTargetCondition(cardSource))
  412. {
  413. ValidCards.Add(cardSource);
  414. }
  415. }
  416. if (_canEndNotMax)
  417. {
  418. _noSelect = true;
  419. for (int maxCount = 0; maxCount < _maxCount; maxCount++)
  420. {
  421. IList<int> indexList = Enumerable.Range(0, ValidCards.Count).ToList();
  422. List<int> CardIDs = null;
  423. if (ValidCards.Count >= maxCount)
  424. {
  425. for (int i = 0; i < 1000; i++)
  426. {
  427. List<int> GetIndexes = indexList.GetRandom(maxCount).ToList();
  428. List<CardSource> GetCards = new List<CardSource>();
  429. foreach (int index in GetIndexes)
  430. {
  431. GetCards.Add(ValidCards[index]);
  432. }
  433. if (CanEndSelect(GetCards))
  434. {
  435. CardIDs = new List<int>();
  436. foreach (CardSource cardSource in GetCards)
  437. {
  438. CardIDs.Add(cardSource.CardIndex);
  439. }
  440. break;
  441. }
  442. }
  443. }
  444. SetTargetHandCards(_selectPlayer.PlayerID, CardIDs != null ? CardIDs.ToArray() : null);
  445. }
  446. }
  447. else
  448. {
  449. IList<int> indexList = Enumerable.Range(0, ValidCards.Count).ToList();
  450. List<int> CardIDs = null;
  451. if (ValidCards.Count >= _maxCount)
  452. {
  453. for (int i = 0; i < 1000; i++)
  454. {
  455. List<int> GetIndexes = indexList.GetRandom(_maxCount).ToList();
  456. List<CardSource> GetCards = new List<CardSource>();
  457. foreach (int index in GetIndexes)
  458. {
  459. GetCards.Add(ValidCards[index]);
  460. }
  461. if (CanEndSelect(GetCards))
  462. {
  463. CardIDs = new List<int>();
  464. foreach (CardSource cardSource in GetCards)
  465. {
  466. CardIDs.Add(cardSource.CardIndex);
  467. }
  468. break;
  469. }
  470. }
  471. }
  472. SetTargetHandCards(_selectPlayer.PlayerID, CardIDs != null ? CardIDs.ToArray() : null);
  473. }
  474. }
  475. #endregion
  476. }
  477. #region Determine if you can exit
  478. bool CanEndSelect(List<CardSource> PreSelectedHandCards)
  479. {
  480. //If the number of cards does not meet the requirements
  481. if (!(PreSelectedHandCards.Count == _maxCount || (PreSelectedHandCards.Count <= _maxCount && _canEndNotMax)))
  482. {
  483. return false;
  484. }
  485. //Failure to meet specified conditions
  486. if (_canEndSelectCondition != null)
  487. {
  488. if (!_canEndSelectCondition(PreSelectedHandCards))
  489. {
  490. return false;
  491. }
  492. }
  493. return true;
  494. }
  495. #endregion
  496. //Wait for selection to be completed
  497. yield return new WaitUntil(() => _selectPlayer.HasPlayerSelection());
  498. CardSelection cardSeletion = _selectPlayer.DequeuePlayerSelection<CardSelection>();
  499. _targetCards = new List<CardSource>();
  500. if (cardSeletion != null)
  501. {
  502. _noSelect = cardSeletion.CardIDList == null;
  503. if (!_noSelect)
  504. {
  505. foreach (int CardID in cardSeletion.CardIDList)
  506. {
  507. _targetCards.Add(GManager.instance.turnStateMachine.gameContext.ActiveCardList[CardID]);
  508. }
  509. }
  510. else
  511. {
  512. GManager.instance.selectCommandPanel.CloseSelectCommandPanel();
  513. }
  514. }
  515. #region Reset
  516. foreach (Player player in GManager.instance.turnStateMachine.gameContext.Players)
  517. {
  518. GManager.instance.turnStateMachine.OffFieldCardTarget(player);
  519. GManager.instance.turnStateMachine.OffHandCardTarget(player);
  520. foreach (Permanent chara in player.GetFieldPermanents())
  521. {
  522. chara.ShowingPermanentCard.RemoveSelectEffect();
  523. }
  524. foreach (HandCard handCard in player.HandCardObjects)
  525. {
  526. if (handCard != null)
  527. {
  528. handCard.RemoveClickTarget();
  529. handCard.RemoveSelectEffect();
  530. handCard.OffSelectedIndexText();
  531. }
  532. }
  533. }
  534. GManager.instance.commandText.CloseCommandText();
  535. yield return new WaitWhile(() => GManager.instance.commandText.gameObject.activeSelf);
  536. GManager.instance.sideBar.OffSideBar();
  537. #endregion
  538. if (!_noSelect)
  539. {
  540. #region Show selected cards
  541. if (_targetCards.Count > 0 && _showCard)
  542. {
  543. if (_isShowOpponent || _selectPlayer.isYou)
  544. {
  545. if (!string.IsNullOrEmpty(_customMessage_ShowCard))
  546. {
  547. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, _customMessage_ShowCard, true, true));
  548. }
  549. else
  550. {
  551. switch (_mode)
  552. {
  553. case Mode.Discard:
  554. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Discarded cards", true, true));
  555. break;
  556. case Mode.PutLibraryTop:
  557. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Cards put on top of deck", true, true));
  558. break;
  559. case Mode.PutLibraryBottom:
  560. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Cards put on bottom of deck", true, true));
  561. break;
  562. case Mode.PutSecurityBottom:
  563. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Cards put on bottom of security", _isFaceUp, true));
  564. break;
  565. case Mode.PlayForFree:
  566. case Mode.PlayForCost:
  567. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Played cards", true, true));
  568. break;
  569. case Mode.Custom:
  570. yield return ContinuousController.instance.StartCoroutine(GManager.instance.GetComponent<Effects>().ShowCardEffect(_targetCards, "Selected cards", true, true));
  571. break;
  572. }
  573. }
  574. }
  575. }
  576. #endregion
  577. Hashtable hashtable = new Hashtable();
  578. if (_cardEffect != null)
  579. {
  580. hashtable.Add("CardEffect", _cardEffect);
  581. }
  582. string log = "";
  583. log += $"\nSelected Hand Card:";
  584. #region Processes the selected card
  585. foreach (CardSource cardSource in _targetCards)
  586. {
  587. log += $"\n{cardSource.BaseENGCardNameFromEntity}({cardSource.CardID})";
  588. if(_selectCardCoroutine != null)
  589. yield return StartCoroutine(_selectCardCoroutine(cardSource));
  590. }
  591. switch (_mode)
  592. {
  593. case Mode.Discard:
  594. discardHands = _targetCards.Map(cardSource => new IDiscardHand(cardSource, hashtable));
  595. break;
  596. case Mode.PutLibraryTop:
  597. yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddLibraryTopCards(_targetCards));
  598. break;
  599. case Mode.PutLibraryBottom:
  600. yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddLibraryBottomCards(_targetCards));
  601. break;
  602. case Mode.PutSecurityBottom:
  603. foreach (CardSource cardSource in _targetCards)
  604. yield return ContinuousController.instance.StartCoroutine(CardObjectController.AddSecurityCard(cardSource,false, _isFaceUp));
  605. break;
  606. case Mode.PlayForFree:
  607. yield return ContinuousController.instance.StartCoroutine(
  608. CardEffectCommons.PlayPermanentCards(
  609. cardSources: _targetCards,
  610. activateClass: _cardEffect,
  611. payCost: false,
  612. isTapped: false,
  613. root: SelectCardEffect.Root.Hand,
  614. activateETB: true));
  615. break;
  616. case Mode.PlayForCost:
  617. {
  618. bool PermanentsCondition(List<Permanent> targetPermanents)
  619. {
  620. if (targetPermanents == null)
  621. {
  622. return true;
  623. }
  624. else
  625. {
  626. if (targetPermanents.Count((targetPermanent) => targetPermanent != null) == 0)
  627. {
  628. return true;
  629. }
  630. }
  631. return false;
  632. }
  633. bool SharedCardCondition(CardSource cardSource) => _targetCards.Contains(cardSource);
  634. bool RootCondition(SelectCardEffect.Root root) => true;
  635. bool CanUseCondition(Hashtable hashtable) => true;
  636. #region reduce cost
  637. Func<EffectTiming, ICardEffect> getChangeCostEffect = null;
  638. if (_reduceCostTuple != null)
  639. {
  640. bool CardCondition(CardSource cardSource)
  641. {
  642. return SharedCardCondition(cardSource)
  643. && (_reduceCostTuple.Value.reduceCostCardCondition == null || _reduceCostTuple.Value.reduceCostCardCondition(cardSource));
  644. }
  645. int ChangeCost(CardSource cardSource, int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents)
  646. {
  647. if (PermanentsCondition(targetPermanents))
  648. {
  649. Cost -= _reduceCostTuple.Value.reduceCost;
  650. }
  651. return Cost;
  652. }
  653. bool isUpDown() => true;
  654. ChangeCostClass changeCostClass = new ChangeCostClass();
  655. changeCostClass.SetUpICardEffect($"Play Cost -{_reduceCostTuple.Value.reduceCost}", CanUseCondition, _cardEffect.EffectSourceCard);
  656. changeCostClass.SetUpChangeCostClass(changeCostFunc: ChangeCost, cardSourceCondition: CardCondition, rootCondition: RootCondition, isUpDown: isUpDown, isCheckAvailability: () => false, isChangePayingCost: () => true);
  657. getChangeCostEffect = GetCardEffect;
  658. ICardEffect GetCardEffect(EffectTiming _timing)
  659. {
  660. if (_timing == EffectTiming.None)
  661. {
  662. return changeCostClass;
  663. }
  664. return null;
  665. }
  666. if (getChangeCostEffect != null)
  667. {
  668. _selectPlayer.UntilCalculateFixedCostEffect.Add(getChangeCostEffect);
  669. }
  670. }
  671. #endregion
  672. #region set fixed cost
  673. Func<EffectTiming, ICardEffect> getFixedCostEffect = null;
  674. if (_fixedCostTuple != null)
  675. {
  676. bool CardCondition(CardSource cardSource)
  677. {
  678. return SharedCardCondition(cardSource)
  679. && (_fixedCostTuple.Value.fixedCostCardCondition == null || _fixedCostTuple.Value.fixedCostCardCondition(cardSource));
  680. }
  681. int ChangeCost(CardSource cardSource, int Cost, SelectCardEffect.Root root, List<Permanent> targetPermanents)
  682. {
  683. if (PermanentsCondition(targetPermanents))
  684. {
  685. Cost = _fixedCostTuple.Value.fixedCost;
  686. }
  687. return Cost;
  688. }
  689. bool isUpDown() => false;
  690. ChangeCostClass changeCostClass = new ChangeCostClass();
  691. changeCostClass.SetUpICardEffect($"Play Cost {_fixedCostTuple.Value.fixedCost}", CanUseCondition, _cardEffect.EffectSourceCard);
  692. changeCostClass.SetUpChangeCostClass(changeCostFunc: ChangeCost, cardSourceCondition: CardCondition, rootCondition: RootCondition, isUpDown: isUpDown, isCheckAvailability: () => false, isChangePayingCost: () => true);
  693. getFixedCostEffect = GetCardEffect;
  694. ICardEffect GetCardEffect(EffectTiming _timing)
  695. {
  696. if (_timing == EffectTiming.None)
  697. {
  698. return changeCostClass;
  699. }
  700. return null;
  701. }
  702. if (getFixedCostEffect != null)
  703. {
  704. _selectPlayer.UntilCalculateFixedCostEffect.Add(getFixedCostEffect);
  705. }
  706. }
  707. #endregion
  708. yield return ContinuousController.instance.StartCoroutine(
  709. CardEffectCommons.PlayPermanentCards(
  710. cardSources: _targetCards,
  711. activateClass: _cardEffect,
  712. payCost: true,
  713. isTapped: false,
  714. root: SelectCardEffect.Root.Hand,
  715. activateETB: true));
  716. #region release effect
  717. if (getChangeCostEffect != null) _selectPlayer.UntilCalculateFixedCostEffect.Remove(getChangeCostEffect);
  718. #endregion
  719. #region release effect
  720. if (getFixedCostEffect != null) _selectPlayer.UntilCalculateFixedCostEffect.Remove(getFixedCostEffect);
  721. #endregion
  722. break;
  723. }
  724. }
  725. #endregion
  726. if (discardHands.Count > 0)
  727. {
  728. yield return ContinuousController.instance.StartCoroutine(new IDiscardHands(discardHands, _cardEffect).DiscardHands());
  729. }
  730. #region ���O�lj�
  731. if (_isShowOpponent || _selectPlayer.isYou)
  732. {
  733. if (_targetCards.Count >= 1)
  734. {
  735. log += "\n";
  736. PlayLog.OnAddLog?.Invoke(log);
  737. }
  738. }
  739. #endregion
  740. }
  741. if (_afterSelectCardCoroutine != null)
  742. {
  743. yield return StartCoroutine(_afterSelectCardCoroutine(_targetCards));
  744. }
  745. }
  746. GManager.instance.turnStateMachine.IsSelecting = oldIsSelecting;
  747. }
  748. #region ƒJ[ƒh‘I‘ð‚ðŒˆ’è
  749. [PunRPC]
  750. public void SetTargetHandCards(int playerID, int[] CardIDs)
  751. {
  752. Player selectionPlayer = GManager.instance.GetPlayerFromID(playerID);
  753. if (selectionPlayer == null)
  754. {
  755. return;
  756. }
  757. selectionPlayer.QueuePlayerSelection(new CardSelection(CardIDs));
  758. }
  759. #endregion
  760. }