private void MarkCrits() { Value = Expression.Value; ValueType = Expression.ValueType; _values.Clear(); DieFlags mask = 0; if (Critical != null) { mask |= DieFlags.Critical; } if (Fumble != null) { mask |= DieFlags.Fumble; } foreach (var die in Expression.Values) { DieFlags flags = 0; if (die.DieType == DieType.Special || die.DieType == DieType.Group) { // we don't skip over dropped dice here since we DO still want to // mark them as criticals/fumbles as needed. _values.Add(die); continue; } if (Critical?.Compare(die.Value) == true) { flags |= DieFlags.Critical; // if tracking successes; a critical success is worth 2 successes if (ValueType == ResultType.Successes) { // just in case the die wasn't already marked as a success if ((die.Flags & DieFlags.Success) == 0) { flags |= DieFlags.Success; Value++; } Value++; } } if (Fumble?.Compare(die.Value) == true) { flags |= DieFlags.Fumble; // if tracking failures; a critical failure is worth -2 successes if (ValueType == ResultType.Successes) { // just in case the die wasn't already marked as a failure if ((die.Flags & DieFlags.Failure) == 0) { flags |= DieFlags.Failure; Value--; } Value--; } } _values.Add(new DieResult() { DieType = die.DieType, NumSides = die.NumSides, Value = die.Value, // strip any existing crit/fumble flag off and use ours, // assuming a comparison was defined for it. // (we may have an existing flag if the die rolled min or max value) Flags = (die.Flags & ~mask) | flags }); } }