public static int GetArmorClass(Character chr, TEML teml, StatAttr stat, ItemBonusMode mode) { int dex = GetAttributeValue(chr, StatAttr.DEX, mode); int baseAC = GetStatValue(chr, teml, stat, mode) - dex; int armorAC = 0; switch (chr.armorType) { case ArmorType.UNARMORED: break; case ArmorType.LIGHT: dex = Mathf.Min(dex, 4); armorAC = Mathf.Max(Mathf.Max(5 - dex, 0), 2); break; case ArmorType.MEDIUM: dex = Mathf.Min(dex, 2); armorAC = Mathf.Max(Mathf.Max(5 - dex, 0), 4); break; case ArmorType.HEAVY: dex = Mathf.Min(dex, 0); armorAC = Mathf.Max(Mathf.Max(6 - dex, 0), 6); break; case ArmorType.MAGIC: armorAC = 1 + (chr.level > 11 ? 1 : 0); break; } return(baseAC + armorAC + dex); }
public static int GetStatValue(Character chr, TEML teml, StatAttr stat, ItemBonusMode mode) { int b = (int)teml; if (teml > TEML.UNTRAINED) { b += chr.level; } b += GetAttributeValue(chr, stat, mode); return(b); }
public static int GetReflexSave(Character chr, TEML teml, StatAttr stat, ItemBonusMode mode) { int baseSave = GetStatValue(chr, teml, stat, mode); int bulwark = 0; switch (chr.armorType) { case ArmorType.HEAVY: bulwark = 3; break; } return(baseSave + bulwark); }
private static void CalcStatsForSkills(Character chr, int minLv, int maxLv, StatisticsResults result, ItemBonusMode mode) { int skil; for (int level = minLv; level <= maxLv; level++) { skil = Character.GetStatValue(chr, chr.perception, StatAttr.WIS, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.PERCEPTION); result.totSkills++; result.perceptiontot++; int diff = 14 + level + (level / 3) + (level >= 22 ? (level >= 23 ? (level >= 25 ? 3 : 2) : 1) : 0); for (int i = 1; i <= 20; i++) { if (skil + i >= diff) { result.perception[i - 1] += (int)RollResult.SUCCESS; } else { if (result.perception[20] < i) { result.perception[20] = i; } result.perception[i - 1] += (int)RollResult.FAIL; } } TEML maxTeml = GetBestTeml(chr, chr.level); StatAttr skillStat = (chr.classStat != StatAttr.CON && level < maxLv ? chr.classStat : GetBestSkillStat(chr, 0)); skil = Character.GetStatValue(chr, maxTeml, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_BEST); //diff = 14 + level + (level / 3); for (int i = 1; i <= 20; i++) { result.skillSpecialist[i - 1] += GetRollResult(i, skil, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillSpecialist[20], ref result.skillSpecialist[21]); } maxTeml = GetBestTeml(chr, chr.level / 2); skillStat = GetBestSkillStat(chr, 1); skil = Character.GetStatValue(chr, maxTeml, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_DECENT); //diff = 14 + level + (level / 3); for (int i = 1; i <= 20; i++) { result.skillDecent[i - 1] += GetRollResult(i, skil, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillDecent[20], ref result.skillDecent[21]); } skillStat = GetBestSkillStat(chr, 3); skil = Character.GetStatValue(chr, TEML.TRAINED, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_LOWEST); //diff = 14 + level + (level / 3); for (int i = 1; i <= 20; i++) { result.skillDabbler[i - 1] += GetRollResult(i, skil, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillDabbler[20], ref result.skillDabbler[21]); } } }
private static void CalcStatsForPair(Character chr, Monster mon, StatisticsResults result, ItemBonusMode mode) { int off; if (chr.attackStat == StatAttr.STR || chr.attackStat == StatAttr.DEX) { off = Character.GetStatValue(chr, chr.attacks, chr.attackStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.WEAPON); } else { off = Character.GetStatValue(chr, chr.classSpellDC, chr.attackStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SPELLDC); } int def = Monster.GetArmor(mon.armorClass, mon.level); result.attacktot += mon.weight; bool attackIsDex = chr.attackStat == StatAttr.DEX || chr.attackStat == StatAttr.INT || chr.attackStat == StatAttr.WIS || chr.attackStat == StatAttr.CHA; if (chr.attackBoost.HasFlag(SaveIncrease.MONSTER_HUNTER)) { int diff = mon.level - chr.level; int monsterHunter = 1; if (chr.attackBoost.HasFlag(SaveIncrease.LEGENDARY_MONSTER_HUNTER)) { monsterHunter = 2; } for (int i = 1; i <= 20; i++) { float total = 0; for (int s = 1; s <= 20; s++) { //basing recall knowledge off an average between a decent skill and a dabbler //to account for there being 4 different skills (odds are high that a ranger isn't going to be best at more than 1) TEML maxTeml = GetBestTeml(chr, chr.level / 2); StatAttr skillStat = GetBestSkillStat(chr, 1); int skil1 = Character.GetStatValue(chr, maxTeml, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_DECENT); skillStat = GetBestSkillStat(chr, 3); int skil2 = Character.GetStatValue(chr, TEML.TRAINED, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_LOWEST); int skil = (skil1 + skil2) / 2; diff = 14 + mon.level + (mon.level / 3) + (mon.level >= 5 ? (mon.level >= 23 ? (mon.level >= 25 ? 3 : 2) : 1) : 0); float a = 0, b = 0; if (GetRollResult(s, skil, diff, SaveIncrease.NONE, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref a, ref b) >= (chr.attackBoost.HasFlag(SaveIncrease.MASTER_MONSTER_HUNTER) ? 2 : 1)) { total += mon.weight * GetRollResult(i, off + monsterHunter, def, chr.attackBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.attack[20], ref result.attack[21]); } else { total += mon.weight * GetRollResult(i, off, def, chr.attackBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.attack[20], ref result.attack[21]); } } result.attack[i - 1] += total / 20f; } } else { for (int i = 1; i <= 20; i++) { float r = mon.weight * GetRollResult(i, off, def, chr.attackBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.attack[20], ref result.attack[21]); result.attack[i - 1] += r; } } int sdc; int sve; if (chr.alchemistUseItemDC) { if (chr.level < 8) { sdc = 17 + chr.level + (chr.level / 3); } else { sdc = Math.Max(Character.GetStatValue(chr, chr.classSpellDC, chr.classStat, mode) + 10 + Character.GetItemBonus(chr, mode, ItemBonusType.SPELLDC), 17 + chr.level + (chr.level / 3)); } } else { sdc = Character.GetStatValue(chr, chr.classSpellDC, chr.classStat, mode) + 10 + Character.GetItemBonus(chr, mode, ItemBonusType.SPELLDC); } if (chr.canAffectsSaves.HasFlag(AffectType.FORT) || chr.canAffectsSaves.HasFlag(AffectType.FORT_LIVING)) { result.spellDCtot += mon.weight; sve = Monster.GetSavingThrow(mon.fort, mon.level); sve += Math.Max(chr.effectsType.HasFlag(EffectType.ARCANE | EffectType.DIVINE | EffectType.OCCULT | EffectType.PRIMAL) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_1_VS_MAGIC | SaveIncrease.PLUS_2_VS_MAGIC) ? (mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_2_VS_MAGIC) ? 2 : 1) : 0, chr.effectsType.HasFlag(EffectType.DIVINE) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_3_VS_DIVINE) ? 3 : 0); for (int i = 1; i <= 20; i++) { result.classSpellDC[i - 1] += mon.weight * GetRollResult(i, sve, sdc, SaveIncrease.NONE, SaveIncrease.NONE, ref result.classSpellDC[20], ref result.classSpellDC[21]); } } if (chr.canAffectsSaves.HasFlag(AffectType.REFX)) { result.spellDCtot += mon.weight; sve = Monster.GetSavingThrow(mon.refx, mon.level); sve += Math.Max(chr.effectsType.HasFlag(EffectType.ARCANE | EffectType.DIVINE | EffectType.OCCULT | EffectType.PRIMAL) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_1_VS_MAGIC | SaveIncrease.PLUS_2_VS_MAGIC) ? (mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_2_VS_MAGIC) ? 2 : 1) : 0, chr.effectsType.HasFlag(EffectType.DIVINE) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_3_VS_DIVINE) ? 3 : 0); for (int i = 1; i <= 20; i++) { result.classSpellDC[i - 1] += mon.weight * GetRollResult(i, sve, sdc, mon.globalDefenseBoost.HasFlag(SaveIncrease.EVASION) ? SaveIncrease.SUCCESS_IS_CRIT_SUCCESS : SaveIncrease.NONE, SaveIncrease.NONE, ref result.classSpellDC[20], ref result.classSpellDC[21]); } } if (chr.canAffectsSaves.HasFlag(AffectType.WILL)) { result.spellDCtot += mon.weight; sve = Monster.GetSavingThrow(mon.will, mon.level); sve += Math.Max(chr.effectsType.HasFlag(EffectType.ARCANE | EffectType.DIVINE | EffectType.OCCULT | EffectType.PRIMAL) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_1_VS_MAGIC | SaveIncrease.PLUS_2_VS_MAGIC) ? (mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_2_VS_MAGIC) ? 2 : 1) : 0, chr.effectsType.HasFlag(EffectType.DIVINE) && mon.globalDefenseBoost.HasFlag(SaveIncrease.PLUS_3_VS_DIVINE) ? 3 : 0); for (int i = 1; i <= 20; i++) { result.classSpellDC[i - 1] += mon.weight * GetRollResult(i, sve, sdc, SaveIncrease.NONE, SaveIncrease.NONE, ref result.classSpellDC[20], ref result.classSpellDC[21]); } } if (mon.canAffectsSaves.HasFlag(AffectType.FORT) || mon.canAffectsSaves.HasFlag(AffectType.FORT_LIVING)) { sve = Character.GetStatValue(chr, chr.fort, StatAttr.CON, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SAVING_THROWS); sdc = Monster.GetAbilityDC(mon.abilitySaveDC, mon.level); result.forttot += mon.weight; for (int i = 1; i <= 20; i++) { result.fort[i - 1] += mon.weight * GetRollResult(i, sve, sdc, chr.fortSaveBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.fort[20], ref result.fort[21]); } } if (mon.canAffectsSaves.HasFlag(AffectType.REFX)) { sve = Character.GetReflexSave(chr, chr.refx, StatAttr.DEX, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SAVING_THROWS); sdc = Monster.GetAbilityDC(mon.abilitySaveDC, mon.level); result.refxtot += mon.weight; for (int i = 1; i <= 20; i++) { result.refx[i - 1] += mon.weight * GetRollResult(i, sve, sdc, chr.refxSaveBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.refx[20], ref result.refx[21]); } } if (mon.canAffectsSaves.HasFlag(AffectType.WILL)) { sve = Character.GetStatValue(chr, chr.will, StatAttr.WIS, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SAVING_THROWS); sdc = Monster.GetAbilityDC(mon.abilitySaveDC, mon.level); result.willtot += mon.weight; for (int i = 1; i <= 20; i++) { result.will[i - 1] += mon.weight * GetRollResult(i, sve, sdc, chr.willSaveBoost, attackIsDex ? SaveIncrease.NONE : mon.globalDefenseBoost, ref result.will[20], ref result.will[21]); } } if (mon.attacks != MTEML.NONE) { off = Monster.GetAttack(mon.attacks, mon.level, mon.attacksAreSpells); def = Character.GetArmorClass(chr, chr.armorClass, StatAttr.DEX, mode) + 10; int b = Character.GetItemBonus(chr, mode, chr.armorType == ArmorType.HEAVY ? ItemBonusType.HEAVY_ARMOR : ItemBonusType.ARMOR); def += b; result.armortot += mon.weight; for (int i = 1; i <= 20; i++) { result.armorClass[i - 1] += mon.weight * GetRollResult(i, off, def, chr.defenseBoost, SaveIncrease.NONE, ref result.armorClass[20], ref result.armorClass[21]) / 2; result.armorClass[i - 1] += mon.weight * GetRollResult(i, off, def + chr.shieldBonus, SaveIncrease.NONE, chr.defenseBoost, ref result.armorClass[20], ref result.armorClass[21]) / 2; } } if (mon.stealth != MTEML.NONE) { int skil = Character.GetStatValue(chr, chr.perception, StatAttr.WIS, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.PERCEPTION); int diff = 10 + Monster.GetStealth(mon.stealth, mon.level); result.perceptiontot += mon.weight; for (int i = 1; i <= 20; i++) { if (skil + i >= diff) { result.perception[i - 1] += mon.weight * (int)RollResult.SUCCESS; } else { if (result.perception[20] < i) { result.perception[20] = i; } result.perception[i - 1] += mon.weight * (int)RollResult.FAIL; } } } //player stealth vs. monster perception is *heavily* biased in favor of the monster if (false && mon.perception != MTEML.NONE) { int skil = Character.GetStatValue(chr, chr.perception, StatAttr.WIS, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.PERCEPTION); int diff = 10 + Monster.GetPerception(mon.perception, mon.level); result.totSkills++; StatAttr skillStat = GetBestSkillStat(chr, 0); off = Character.GetSkillValue(chr, GetBestTeml(chr, chr.level), skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_BEST); for (int i = 1; i <= 20; i++) { result.skillSpecialist[i - 1] += GetRollResult(i, off, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillSpecialist[20], ref result.skillSpecialist[21]); } skillStat = GetBestSkillStat(chr, 1); off = Character.GetSkillValue(chr, GetBestTeml(chr, chr.level - 7), skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_DECENT); for (int i = 1; i <= 20; i++) { result.skillDecent[i - 1] += GetRollResult(i, off, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillDecent[20], ref result.skillDecent[21]); } skillStat = GetBestSkillStat(chr, 3); off = Character.GetSkillValue(chr, TEML.TRAINED, skillStat, mode) + Character.GetItemBonus(chr, mode, ItemBonusType.SKILL_LOWEST); for (int i = 1; i <= 20; i++) { result.skillDabbler[i - 1] += GetRollResult(i, off, diff, SaveIncrease.NONE, SaveIncrease.NONE, ref result.skillDabbler[20], ref result.skillDabbler[21]); } } }