private void PayTokenCost(Action callBack)
        {
            List <Type> tokenRequirements = HostShip.GetWeaponAttackRequirement(this, isSilent: false);

            if (tokenRequirements.Contains(typeof(BlueTargetLockToken)))
            {
                List <GenericToken> waysToPay = new List <GenericToken>();

                List <char>  letters         = ActionsHolder.GetTargetLocksLetterPairs(Combat.Attacker, Combat.Defender);
                GenericToken targetLockToken = Combat.Attacker.Tokens.GetToken(typeof(BlueTargetLockToken), letters.FirstOrDefault());
                if (targetLockToken != null)
                {
                    waysToPay.Add(targetLockToken);
                }

                Combat.Attacker.CallOnGenerateAvailableAttackPaymentList(waysToPay);

                if (waysToPay.Count == 1)
                {
                    if (WeaponInfo.SpendsToken == typeof(BlueTargetLockToken) || waysToPay.First() is ForceToken)
                    {
                        Combat.Attacker.Tokens.SpendToken(
                            waysToPay.First().GetType(),
                            callBack,
                            (waysToPay.First() as BlueTargetLockToken != null) ? (waysToPay.First() as BlueTargetLockToken).Letter : ' '
                            );
                    }
                    else
                    {
                        callBack();
                    }
                }
                else
                {
                    if (WeaponInfo.SpendsToken != null)
                    {
                        PayAttackCostDecisionSubPhase subphase = Phases.StartTemporarySubPhaseNew <PayAttackCostDecisionSubPhase>(
                            "Choose how to pay attack cost",
                            callBack
                            );
                        subphase.Weapon = this;
                        subphase.Start();
                    }
                    else
                    {
                        callBack();
                    }
                }
            }
            else if (tokenRequirements.Contains(typeof(FocusToken)) && WeaponInfo.SpendsToken == typeof(FocusToken))
            {
                Combat.Attacker.Tokens.SpendToken(typeof(FocusToken), callBack);
            }
            else
            {
                callBack();
            }
        }
        private bool AreTokenRequirementsMet(GenericShip targetShip)
        {
            List <Type> tokenRequirements = HostShip.GetWeaponAttackRequirement(this, isSilent: true);

            if (tokenRequirements.Count > 0)
            {
                foreach (Type tokenRequirement in tokenRequirements)
                {
                    if (tokenRequirement == typeof(BlueTargetLockToken))
                    {
                        List <GenericToken> waysToPay = new List <GenericToken>();

                        List <char>  letters         = ActionsHolder.GetTargetLocksLetterPairs(HostShip, targetShip);
                        GenericToken targetLockToken = HostShip.Tokens.GetToken(typeof(BlueTargetLockToken), letters.FirstOrDefault());
                        if (targetLockToken != null)
                        {
                            waysToPay.Add(targetLockToken);
                        }

                        HostShip.CallOnGenerateAvailableAttackPaymentList(waysToPay);

                        if (waysToPay.Count != 0)
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        if (HostShip.Tokens.HasToken(tokenRequirement))
                        {
                            return(true);
                        }
                    }
                }
            }
            else
            {
                return(true);
            }

            return(false);
        }
        public virtual bool IsShotAvailable(GenericShip targetShip)
        {
            bool result = true;

            int MinRangeUpdated = WeaponInfo.MinRange;
            int MaxRangeUpdated = WeaponInfo.MaxRange;

            HostShip.CallUpdateWeaponRange(this, ref MinRangeUpdated, ref MaxRangeUpdated);

            if (!State.IsFaceup)
            {
                return(false);
            }

            if (State.UsesCharges && State.Charges == 0)
            {
                return(false);
            }

            ShotInfo shotInfo = new ShotInfo(HostShip, targetShip, this);
            int      range    = shotInfo.Range;

            if (!shotInfo.IsShotAvailable)
            {
                return(false);
            }

            if (range < MinRangeUpdated)
            {
                return(false);
            }
            if (range > MaxRangeUpdated)
            {
                return(false);
            }

            Type tokenRequirement = HostShip.GetWeaponAttackRequirement(this, isSilent: true);

            if (tokenRequirement == typeof(BlueTargetLockToken))
            {
                List <GenericToken> waysToPay = new List <GenericToken>();

                List <char>  letters         = ActionsHolder.GetTargetLocksLetterPairs(HostShip, targetShip);
                GenericToken targetLockToken = HostShip.Tokens.GetToken(typeof(BlueTargetLockToken), letters.FirstOrDefault());
                if (targetLockToken != null)
                {
                    waysToPay.Add(targetLockToken);
                }

                HostShip.CallOnGenerateAvailableAttackPaymentList(waysToPay);

                if (waysToPay.Count == 0)
                {
                    return(false);
                }
            }
            else if (tokenRequirement != null)
            {
                if (!HostShip.Tokens.HasToken(tokenRequirement))
                {
                    return(false);
                }
            }

            return(result);
        }