SelectHandEffect.cs 36 KB

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