Esempio n. 1
0
        internal static float NormalDistibutionRandom(VarianceBounds bounds, int step = -1)
        {
            // compute a random number that fits a gaussian function https://en.wikipedia.org/wiki/Gaussian_function
            // iterative w/ limit adapted from https://natedenlinger.com/php-random-number-generator-with-normal-distribution-bell-curve/
            const int iterationLimit = 10;
            var       iterations     = 0;
            float     randomNumber;

            do
            {
                var rand1          = Random.value;
                var rand2          = Random.value;
                var gaussianNumber = Mathf.Sqrt(-2 * Mathf.Log(rand1)) * Mathf.Cos(2 * Mathf.PI * rand2);
                var mean           = (bounds.max + bounds.min) / 2;
                randomNumber = (gaussianNumber * bounds.standardDeviation) + mean;
                if (step > 0)
                {
                    randomNumber = Mathf.RoundToInt(randomNumber / step) * step;
                }
                iterations++;
            } while ((randomNumber < bounds.min || randomNumber > bounds.max) && iterations < iterationLimit);

            if (iterations == iterationLimit)
            {
                randomNumber = (bounds.min + bounds.max) / 2.0f;
            }
            return(randomNumber);
        }
        // This method is used by the IL generators in IntermediateLanguageFuckery
        public static float VariantDamage(WeaponEffect weaponEffect, DesignMaskDef designMask)
        {
            var weapon = weaponEffect.weapon;
            var key    = ShotMemoKey(weaponEffect);

            if (DamageWasAlreadyCalculated(key, out var variantDamage))
            {
                return(variantDamage);
            }
            if (IsNonVariantWeapon(key, weapon, out var damageVariance, out var normalDamage))
            {
                return(normalDamage);
            }

            // the following damage calcs should match with Weapon.DamagePerShotAdjusted(DesignMaskDef), with
            // the addition of the variance computations
            var damagePerShot = weapon.DamagePerShotAdjusted();

            Logger.Debug(
                $"some damage numbers:\n" +
                $"weapon damage: {weapon.DamagePerShot}\n" +
                $"weapon damage adjusted: {weapon.DamagePerShotAdjusted()}\n" +
                $"stats based: {weapon.StatCollection.GetValue<float>("DamagePerShot")}"
                );

            var bounds = new VarianceBounds(
                min: damagePerShot - damageVariance,
                max: damagePerShot + damageVariance,
                standardDeviation: ModSettings.StandardDeviationVarianceMultiplier * damageVariance
                );
            var damage        = Utility.NormalDistibutionRandom(bounds);
            var combat        = Traverse.Create(weapon).Field("combat").GetValue <CombatGameState>();
            var damageWDesign = damage * weapon.GetMaskDamageMultiplier(weapon.parent.occupiedDesignMask);
            var result        = damageWDesign * weapon.GetMaskDamageMultiplier(combat.MapMetaData.biomeDesignMask);

            Logger.Debug(
                $"effect id: {key.weaponEffectId}\n" +
                $"hit index: {key.hitIndex}\n" +
                $"damage and variance: {damagePerShot}+-{damageVariance}\n" +
                $"damage range: {bounds.min}-{bounds.max} (std. dev. {bounds.standardDeviation}\n" +
                $"computed damage: {damage}\n" +
                $"damage w/ design mask: {damageWDesign}\n" +
                $"damage w/ env: {result}"
                );
            WeaponDamageMemo[key] = result;
            return(WeaponDamageMemo[key]);
        }