private List <MinMaxDouble> CalculateImprintingBonus(Species species, double imprintingBonusRounded, double imprintingBonusMultiplier, double torpor, double food) { List <MinMaxDouble> imprintingBonusList = new List <MinMaxDouble>(); if (species.stats[(int)StatNames.Torpidity].BaseValue == 0 || species.stats[(int)StatNames.Torpidity].IncPerWildLevel == 0) { return(imprintingBonusList); // invalid species-data } // classic way to calculate the ImprintingBonus, this is the most exact value, but will not work if the imprinting-gain was different (e.g. events, mods (S+Nanny)) double imprintingBonusFromGainPerCuddle = 0; if (species.breeding != null) { double imprintingGainPerCuddle = Utils.ImprintingGainPerCuddle(species.breeding.maturationTimeAdjusted); imprintingBonusFromGainPerCuddle = Math.Round(imprintingBonusRounded / imprintingGainPerCuddle) * imprintingGainPerCuddle; } double[] statImprintMultipliers = species.StatImprintMultipliers; MinMaxInt wildLevelsFromImprintedTorpor = new MinMaxInt( (int)Math.Round(((((torpor / (1 + species.stats[(int)StatNames.Torpidity].MultAffinity)) - species.stats[(int)StatNames.Torpidity].AddWhenTamed) / ((1 + (imprintingBonusRounded + 0.005) * statImprintMultipliers[(int)StatNames.Torpidity] * imprintingBonusMultiplier) * species.stats[(int)StatNames.Torpidity].BaseValue)) - 1) / species.stats[(int)StatNames.Torpidity].IncPerWildLevel), (int)Math.Round(((((torpor / (1 + species.stats[(int)StatNames.Torpidity].MultAffinity)) - species.stats[(int)StatNames.Torpidity].AddWhenTamed) / ((1 + (imprintingBonusRounded - 0.005) * statImprintMultipliers[(int)StatNames.Torpidity] * imprintingBonusMultiplier) * species.stats[(int)StatNames.Torpidity].BaseValue)) - 1) / species.stats[(int)StatNames.Torpidity].IncPerWildLevel)); // assuming food has no dom-levels, extract the exact imprinting from this stat. If the range is in the range of the torpor-dependent IB, take this more precise value for the imprinting. (food has higher values and yields more precise results) MinMaxInt wildLevelsFromImprintedFood = new MinMaxInt( (int)Math.Round(((((food / (1 + species.stats[(int)StatNames.Food].MultAffinity)) - species.stats[(int)StatNames.Food].AddWhenTamed) / ((1 + (imprintingBonusRounded + 0.005) * statImprintMultipliers[(int)StatNames.Food] * imprintingBonusMultiplier) * species.stats[(int)StatNames.Food].BaseValue)) - 1) / species.stats[(int)StatNames.Food].IncPerWildLevel), (int)Math.Round(((((food / (1 + species.stats[(int)StatNames.Food].MultAffinity)) - species.stats[(int)StatNames.Food].AddWhenTamed) / ((1 + (imprintingBonusRounded - 0.005) * statImprintMultipliers[(int)StatNames.Food] * imprintingBonusMultiplier) * species.stats[(int)StatNames.Food].BaseValue)) - 1) / species.stats[(int)StatNames.Food].IncPerWildLevel)); List <int> otherStatsSupportIB = new List <int>(); // the number of other stats that support this IB-range // for high-level creatures the bonus from imprinting is so high, that a displayed and rounded value of the imprinting bonus can be possible with multiple torpor-levels, i.e. 1 %point IB results in a larger change than a level in torpor. for (int torporLevel = wildLevelsFromImprintedTorpor.Min; torporLevel <= wildLevelsFromImprintedTorpor.Max; torporLevel++) { int support = 0; double imprintingProductTorpor = statImprintMultipliers[(int)StatNames.Torpidity] * imprintingBonusMultiplier; double imprintingProductFood = statImprintMultipliers[(int)StatNames.Food] * imprintingBonusMultiplier; if (imprintingProductTorpor == 0 || imprintingProductFood == 0) { break; } MinMaxDouble imprintingBonusRange = new MinMaxDouble( (((torpor - 0.05) / (1 + species.stats[(int)StatNames.Torpidity].MultAffinity) - species.stats[(int)StatNames.Torpidity].AddWhenTamed) / StatValueCalculation.CalculateValue(species, (int)StatNames.Torpidity, torporLevel, 0, false, 0, 0) - 1) / imprintingProductTorpor, (((torpor + 0.05) / (1 + species.stats[(int)StatNames.Torpidity].MultAffinity) - species.stats[(int)StatNames.Torpidity].AddWhenTamed) / StatValueCalculation.CalculateValue(species, (int)StatNames.Torpidity, torporLevel, 0, false, 0, 0) - 1) / imprintingProductTorpor); // check for each possible food-level the IB-range and if it can narrow down the range derived from the torpor (deriving from food is more precise, due to the higher values) for (int foodLevel = wildLevelsFromImprintedFood.Min; foodLevel <= wildLevelsFromImprintedFood.Max; foodLevel++) { MinMaxDouble imprintingBonusFromFood = new MinMaxDouble( (((food - 0.05) / (1 + species.stats[(int)StatNames.Food].MultAffinity) - species.stats[(int)StatNames.Food].AddWhenTamed) / StatValueCalculation.CalculateValue(species, (int)StatNames.Food, foodLevel, 0, false, 0, 0) - 1) / imprintingProductFood, (((food + 0.05) / (1 + species.stats[(int)StatNames.Food].MultAffinity) - species.stats[(int)StatNames.Food].AddWhenTamed) / StatValueCalculation.CalculateValue(species, (int)StatNames.Food, foodLevel, 0, false, 0, 0) - 1) / imprintingProductFood); // NOTE: it's assumed if the IB-food is in the range of IB-torpor, the values are correct. This doesn't have to be true, but is very probable. If extraction-issues appear, this assumption could be the reason. //if (imprintingBonusFromTorpor.Includes(imprintingBonusFromFood) if (imprintingBonusRange.Overlaps(imprintingBonusFromFood)) { MinMaxDouble intersectionIB = new MinMaxDouble(imprintingBonusRange); intersectionIB.SetToIntersectionWith(imprintingBonusFromFood); if (StatValueCalculation.CalculateValue(species, (int)StatNames.Torpidity, torporLevel, 0, true, 1, intersectionIB.Min) <= torpor && StatValueCalculation.CalculateValue(species, (int)StatNames.Torpidity, torporLevel, 0, true, 1, intersectionIB.Max) >= torpor) { //imprintingBonusFromTorpor = imprintingBonusFromFood; imprintingBonusRange.SetToIntersectionWith(imprintingBonusFromFood); support++; } } } // if classic method results in value in the possible range, take this, probably most exact value if (imprintingBonusRange.Includes(imprintingBonusFromGainPerCuddle) && StatValueCalculation.CalculateValue(species, (int)StatNames.Torpidity, torporLevel, 0, true, 1, imprintingBonusFromGainPerCuddle) == torpor) { imprintingBonusRange.MinMax = imprintingBonusFromGainPerCuddle; support++; } // TODO check if this range has already been added to avoid double loops in the extraction. if existent, update support imprintingBonusList.Add(imprintingBonusRange); otherStatsSupportIB.Add(support); } // sort IB according to the support they got by other stats, then return the distinct means of the possible ranges. return(imprintingBonusList.OrderByDescending(i => otherStatsSupportIB[imprintingBonusList.IndexOf(i)]).ToList()); }