public void ResolveAction(DungeonMaster DM, Character user, Position posTarget,
                                  Character charTarget, string optionalFeatures, Outcome outcome)
        {
            if (!IsValidToDo(DM, user, posTarget, charTarget, optionalFeatures))
            {
                outcome.Message.AppendLine("Can't do that");
                return;
            }

            timesUsedThisTurn++;

            outcome.ActionTaken = this.Name;
            outcome.UserID      = user.ID;
            outcome.PosTarget   = posTarget;
            if (charTarget != null)
            {
                outcome.TargetID = charTarget.ID;
            }
            Deck.ClearTracking();

            if (Tags.Any(t => t == AbilityType.Uncontested))
            {
                foreach (var effect in Effects[Card.CardType.Hit])
                {
                    var effectOutcome = effect.Apply(DM, user, posTarget, charTarget, null, null, "");
                    outcome.Message.Append(effectOutcome.Message); //TODO: better way to combine
                }
                return;
            }

            //generate outcome deck or mark as uncontested
            Deck deck = GetDeckFor(DM, user, posTarget, charTarget);

            outcome.Message.AppendLine(deck.ToString());

            var originalDeck = deck.Clone() as Deck;
            //draw card
            //special drawing rules?
            //deck.OnCardDrawn += DM.CardDrawn;
            Card card = deck.Draw();

            outcome.Message.AppendLine("Drawn:" + card.ToString());

            //inform user and target what card was drawn, possibly for temporary dodge or breaking shields
            user.CardDrawn(deck, card);
            if (charTarget != null)
            {
                charTarget.CardDrawn(deck, card); //TODO: outcome effects
            }

            //apply relevant effects
            foreach (var effect in Effects[card.TypeOfCard])
            {
                var effectOutcome = effect.Apply(DM, user, posTarget, charTarget, deck, card, "");
                outcome.Message.Append(effectOutcome.Message); //TODO: better way to combine
            }

            if (TypeOfAction == ActionType.Major)
            {
                user.HasActed = true;
            }

            outcome.CardsDrawn.AddRange(Deck.DrawnCards);
            DM.CardDrawn(this, new BasicStructures.Events.CardDrawnEventArgs(originalDeck, Deck.DrawnCards));

            return;
        }