using System; using System.Collections.Generic; using System.Linq; using Continentis.MainGame.Character; using Continentis.MainGame.Combat; using Continentis.MainGame.Commands; using SLSFramework.General; using SLSFramework.UModAssistance; using UniRx; using UnityEngine; using Random = UnityEngine.Random; namespace Continentis.MainGame.Card { public partial class CardLogicBase { /// /// 选中目标时触发的效果,效果在所有逻辑组件的Targeting之前执行(在SetUp函数生成EventSubmodule的时候)。 /// 如果必须需要在逻辑组件之后执行,请重写Initialize函数。 /// public virtual void TargetingEffect(CharacterBase target) { } /// /// 取消选中目标时触发的效果,效果在所有逻辑组件的Untargeting之前执行(在SetUp函数生成EventSubmodule的时候)。 /// 如果必须需要在逻辑组件之后执行,请重写Initialize函数。 /// public virtual void UntargetingEffect() { } } public partial class CardLogicBase { /// /// 刷新卡牌属性 /// public void RefreshCardAttributes() { if(user == null) return; attributeSubmodule.RefreshAllAttributes(); if ((handCardView == null && intentionCardView == null) || !handCardView.isSelecting) { eventSubmodule.onUntargeting(); } contentSubmodule.dirtyMark = true; } /// /// 根据卡牌内容应用属性变化 /// public virtual void ApplyAttributeChangesByCard() { } } public partial class CardLogicBase { public virtual void DetectTargetsValidity(out List valid, out List notMet, out List invalid) { List characters = CombatMainManager.Instance.characterController.characters; invalid = new List(characters); notMet = new List(); valid = new List(); int targetCount = attributeSubmodule.targetCount; if (targetCount <= -2) { Debug.LogError("Invalid target count setting on card: " + contentSubmodule.cardName); return; } if (HasKeyword("TargetAll")) { valid.AddRange(characters); } else { if (HasKeyword("TargetAllies") || HasKeyword("Blessing")) { valid.AddRange(user.fraction is Fraction.Ally or Fraction.Player ? characters.Where(character => character.fraction is Fraction.Ally or Fraction.Player) : characters.Where(character => character.fraction == user.fraction)); valid.Remove(user); } if (HasKeyword("TargetSelf")) { valid.Add(user); } if (HasKeyword("TargetEnemies")) { valid.AddRange(user.fraction is Fraction.Ally or Fraction.Player ? characters.Where(character => character.fraction is Fraction.Enemy or Fraction.Neutral) : characters.Where(character => character.fraction != user.fraction)); //处理保护,嘲讽等 if (targetCount != -1) { List protectedTargets = valid.Where(target => target.statusSubmodule.HasStatus(StatusType.Protected)).ToList(); notMet.AddRange(protectedTargets); valid.RemoveRange(protectedTargets); } } } foreach (CharacterBase validTarget in valid) { invalid.Remove(validTarget); } } public virtual List SetRandomTargets(List valid) { List targets = new List(); int maximumTargets = attributeSubmodule.targetCount; if (maximumTargets == -1 || maximumTargets >= valid.Count) { targets.AddRange(valid); } else { while (targets.Count < maximumTargets && valid.Count > 0) { CharacterBase target = valid[Random.Range(0, valid.Count)]; valid.Remove(target); targets.Add(target); } } return targets; } public virtual bool CheckBeforePlay() { if (!user.CheckEnoughStamina(GetAttribute("StaminaCost"))) { MainGameManager.Instance.basePrefabs.GenerateInfoText("Not Enough Stamina", user.characterView); return false; } if (!user.CheckEnoughMana(GetAttribute("ManaCost"))) { MainGameManager.Instance.basePrefabs.GenerateInfoText("Not Enough Mana", user.characterView); return false; } return true; } /// /// 打出卡牌 /// 注意,这个函数内部包含了命令队列的调用 /// /// 目标列表 /// 使用者 /// 打出之前是否进行可用性检测 public bool Play(List targetList, CharacterBase user = null, bool willCheckBeforePlay = true) { if (handCardView != null) { if (handCardView.isDuringPlaying) { return false; } handCardView.isDuringPlaying = true; } cardInstance.user = user ?? CombatMainManager.Instance.currentCharacter; if (!willCheckBeforePlay || CheckBeforePlay()) { cardInstance.user.ModifyStamina(-GetAttribute("StaminaCost")); cardInstance.user.ModifyMana(-GetAttribute("ManaCost")); if (cardInstance.user is PlayerHero) { CombatUIManager.Instance.combatMainPage.combatResourcesDisplayer.UpdateIcons(); } Debug.Log($"Starting to play card: {contentSubmodule.cardName}"); CommandQueueManager.Instance.AddCommand(new Cmd_Function(() => { playSubmodule.isDuringPlayEffect = true; eventSubmodule.onBeforePlay.Invoke(targetList); cardInstance.user.eventSubmodule?.onBeforePlayCard.Invoke(cardInstance, targetList); cardInstance.user.combatBuffSubmodule.buffList.For(buff => { buff.eventSubmodule?.onBeforePlayCard.Invoke(cardInstance, targetList); }); })); CommandQueueManager.Instance.AddCommands(PlayEffect(targetList)); CommandQueueManager.Instance.AddCommand(new Cmd_Function(() => { eventSubmodule.onAfterPlay.Invoke(targetList); combatBuffSubmodule.buffList.For(buff => buff.usageSubmodule?.UpdateModule()); cardInstance.user.eventSubmodule.onAfterPlayCard.Invoke(cardInstance, targetList); cardInstance.user.combatBuffSubmodule.buffList.For(buff => { buff.eventSubmodule?.onAfterPlayCard.Invoke(cardInstance, targetList); }); AfterPlayEffect(targetList); playSubmodule.isDuringPlayEffect = false; handCardView.isDuringPlaying = false; })); return true; } else { if (handCardView != null) { handCardView.isDuringPlaying = false; } return false; } } protected virtual List PlayEffect(List targetList) { return null; } protected virtual void AfterPlayEffect(List targetList) { if (contentSubmodule.cardType == CardType.Power) { CommandQueueManager.Instance.AddCommand(user.deckSubmodule.UsePowerCard(cardInstance)); return; } if (HasKeyword("Exhaust")) { CommandQueueManager.Instance.AddCommand(user.deckSubmodule.ExhaustCard(cardInstance)); return; } if(HasKeyword("Exhaustible")) { if (!cardInstance.cardLogic.HasAttribute("ExhaustibleCount")) { Debug.LogError("Exhaustible card missing ExhaustibleCount attribute: " + contentSubmodule.cardName); CommandQueueManager.Instance.AddCommand(user.deckSubmodule.ExhaustCard(cardInstance)); return; } cardInstance.cardLogic.ModifyAttribute("ExhaustibleCount", -1); if(cardInstance.cardLogic.GetAttribute("ExhaustibleCount") <= 0) { CommandQueueManager.Instance.AddCommand(user.deckSubmodule.ExhaustCard(cardInstance)); return; } } if (user is PlayerHero playerHero) { if(!HasKeyword("Reuseable")) { CommandQueueManager.Instance.AddCommand(playerHero.deckSubmodule.DiscardCard(cardInstance, false)); CommandQueueManager.Instance.AddCommand(new Cmd_Function(() => { if (handCardView != null) { handCardView.isDuringPlaying = false; } })); } } else if (user is CombatNPC npc) { } } } public partial class CardLogicBase { } }