/// <summary> /// Calculates ability resistance for an ability. /// The attacker and defender's skills, ability modifiers, and balance affinity will be /// used to make this determination. /// </summary> /// <param name="attacker">The creature using the ability.</param> /// <param name="defender">The creature being targeted by the ability.</param> /// <param name="skill">The skill used for this ability.</param> /// <param name="balanceType">The force balance type to use for this ability.</param> /// <param name="sendRollMessage">If true, the roll message will be sent. Otherwise it won't be.</param> /// <returns>Data regarding the ability resistance roll</returns> public static AbilityResistanceResult CalculateAbilityResistance(NWCreature attacker, NWCreature defender, SkillType skill, ForceBalanceType balanceType, bool sendRollMessage = true) { AbilityType abilityScoreType; switch (skill) { case SkillType.ForceAlter: abilityScoreType = AbilityType.Intelligence; break; case SkillType.ForceControl: abilityScoreType = AbilityType.Wisdom; break; case SkillType.ForceSense: abilityScoreType = AbilityType.Charisma; break; default: throw new ArgumentException("Invalid skill type called for " + nameof(CalculateAbilityResistance) + ", value '" + skill + "' not supported."); } AbilityResistanceResult result = new AbilityResistanceResult(); int attackerSkill = SkillService.GetPCSkillRank(attacker.Object, skill); int attackerAbility = _.GetAbilityModifier(abilityScoreType, attacker); int defenderSkill = SkillService.GetPCSkillRank(defender.Object, skill); int defenderAbility = _.GetAbilityModifier(abilityScoreType, defender); // If the defender is equipped with a lightsaber, we check their lightsaber skill if (defender.RightHand.CustomItemType == CustomItemType.Lightsaber || defender.LeftHand.CustomItemType == CustomItemType.Lightsaber) { int lightsaberSkill = SkillService.GetPCSkillRank(defender.Object, SkillType.Lightsaber); if (lightsaberSkill > defenderSkill) { defenderSkill = lightsaberSkill; } } // If the defender's martial arts skill is greater than the current skill they're using, we'll use that instead. int defenderMASkill = SkillService.GetPCSkillRank(defender.Object, SkillType.MartialArts); if (defenderMASkill > defenderSkill) { defenderSkill = defenderMASkill; } int attackerAffinity = 0; int defenderAffinity = 0; // Only check affinity if ability has a force balance type. if (balanceType == ForceBalanceType.Dark || balanceType == ForceBalanceType.Light) { attackerAffinity = GetBalanceAffinity(attacker.Object, balanceType); defenderAffinity = GetBalanceAffinity(defender.Object, balanceType); } float attackerCR = attacker.IsPlayer ? 0f : attacker.ChallengeRating * 5f; float defenderCR = defender.IsPlayer ? 0f : defender.ChallengeRating * 5f; float attackerTotal = attackerSkill + attackerAbility + attackerAffinity + attackerCR; float defenderTotal = defenderSkill + defenderAbility + defenderAffinity + defenderCR; //float divisor = attackerTotal + defenderTotal + 1; // +1 to prevent division by zero. //Console.WriteLine("attackerCR = " + attackerCR); //Console.WriteLine("defenderCR = " + defenderCR); //Console.WriteLine("attackerSkill = " + attackerSkill); //Console.WriteLine("attackerAbility = " + attackerAbility); //Console.WriteLine("attackerAffinity = " + attackerAffinity); //Console.WriteLine("defenderSkill = " + defenderSkill); //Console.WriteLine("defenderAbility = " + defenderAbility); //Console.WriteLine("defenderAffinity = " + defenderAffinity); //Console.WriteLine("attackerTotal = " + attackerTotal); //Console.WriteLine("defenderTotal = " + defenderTotal); //Console.WriteLine("divisor = " + divisor); result.DC = (int)defenderTotal + 10; // divisor * 100); result.Roll = RandomService.D20(1) + (int)attackerTotal; if (sendRollMessage) { string resisted = result.IsResisted ? ColorTokenService.Red(" [RESISTED " + Math.Abs(result.Delta) + "%]") : string.Empty; string message = ColorTokenService.SavingThrow("Roll: " + result.Roll + " VS " + result.DC + " DC") + resisted; attacker.SendMessage(message); defender.SendMessage(message); } return(result); }