示例#1
0
        public static double GetStatValue(this StatsGroup self, Stat stat)
        {
            StatsGroup higher = self.Copy();

            higher[stat] += 1;
            return(Formulas.CalculateDamageFromGCD(higher) - Formulas.CalculateDamageFromGCD(self));
        }
示例#2
0
        public double GetDamageOfGCDAttack(StatsGroup stats)
        {
            bool isCrit;
            bool isDirectHit;

            return(GetDamageOfGCDAttack(stats, out isCrit, out isDirectHit));
        }
示例#3
0
        private static void RunGraph()
        {
            foreach (var statNum in Enum.GetValues(typeof(Stat)))
            {
                var stat = (Stat)statNum;
                Console.WriteLine($"{(int)(stat + 1)} - {stat.ToString()}");
            }

            int      choice  = int.Parse(Console.ReadKey(true).KeyChar.ToString()) - 1;
            FileInfo outFile = new FileInfo("out.csv");

            using (Stream outStream = outFile.OpenWrite())
            {
                StreamWriter writer     = new StreamWriter(outStream);
                double       baseResult = 0;
                for (int stat = StatsGroup.Baseline[(Stat)choice]; stat < 5000; stat += 10)
                {
                    StatsGroup stats = CurrentStats.Copy();
                    stats[(Stat)choice] = stat;
                    double result = RunSimulation(stats, CurrentRotation.Value);

                    if (baseResult == 0)
                    {
                        baseResult = result;
                    }

                    Console.WriteLine($"{stat}\t{result / baseResult}");
                    writer.WriteLine($"{stat}\t{result / baseResult}");
                }
                writer.Flush();
            }
        }
示例#4
0
        public double GetDamageOfGCDAttack(StatsGroup stats, out bool isCrit, out bool isDirectHit)
        {
            double critRate            = RatingConversions.GetCritChance(stats.CritRating);
            double critMult            = RatingConversions.GetCritDamageMultiplier(stats.CritRating);
            double directHitRate       = RatingConversions.GetDirectHitChance(stats.DirectHitRating);
            double determinationFactor = RatingConversions.GetDeterminationFactor(stats.Determination);
            double tenacityFactor      = RatingConversions.GetTenacityFactor(stats.Tenacity);

            isCrit      = (rng.NextDouble() < critRate);
            isDirectHit = (rng.NextDouble() < directHitRate);

            double damage = 1;

            if (isCrit)
            {
                damage *= critMult;
            }
            if (isDirectHit)
            {
                damage *= RatingConversions.GetDirectHitDamageFactor(stats.DirectHitRating);
            }
            damage *= determinationFactor;
            damage *= tenacityFactor;

            TotalCrits      += isCrit ? 1 : 0;
            TotalDirectHits += isDirectHit ? 1 : 0;
            TotalAttacks++;

            return(damage);
        }
示例#5
0
        public double GetDamageOfDoTTick(StatsGroup stats)
        {
            double critRate            = RatingConversions.GetCritChance(stats.CritRating);
            double critMult            = RatingConversions.GetCritDamageMultiplier(stats.CritRating);
            double directHitRate       = RatingConversions.GetDirectHitChance(stats.DirectHitRating);
            double directHitMult       = RatingConversions.GetDirectHitDamageFactor(stats.DirectHitRating);
            double determinationFactor = RatingConversions.GetDeterminationFactor(stats.Determination);
            double tenacityFactor      = RatingConversions.GetTenacityFactor(stats.Tenacity);
            double speedFactor         = RatingConversions.GetSpeedDoTContribution(stats.SpeedRating);

            bool isCrit      = (rng.NextDouble() < critRate);
            bool isDirectHit = (rng.NextDouble() < directHitRate);

            double damage = 1;

            if (isCrit)
            {
                damage *= critMult;
            }
            if (isDirectHit)
            {
                damage *= directHitMult;
            }
            damage *= determinationFactor;
            damage *= tenacityFactor;
            damage *= speedFactor;
            return(damage);
        }
示例#6
0
        public static double GetContribution(this StatsGroup self, Stat stat)
        {
            StatsGroup lower = self.Copy();

            lower[stat] = StatsGroup.Baseline[stat];

            return(Formulas.CalculateDamageFromGCD(self) - Formulas.CalculateDamageFromGCD(lower));
        }
示例#7
0
        public double GetDamageOfDoT(StatsGroup stats, int ticks)
        {
            double totalDamage = 0;

            for (int i = 0; i < ticks; ++i)
            {
                totalDamage += GetDamageOfDoTTick(stats);
            }
            return(totalDamage / ticks);
        }
示例#8
0
        public static double CalculateDamageFromAbility(StatsGroup stats)
        {
            double critRate            = RatingConversions.GetCritChance(stats.CritRating);
            double critMult            = RatingConversions.GetCritDamageMultiplier(stats.CritRating);
            double directHitRate       = RatingConversions.GetDirectHitChance(stats.DirectHitRating);
            double determinationFactor = RatingConversions.GetDeterminationFactor(stats.Determination);
            double tenacityFactor      = RatingConversions.GetTenacityFactor(stats.Tenacity);

            return(CalculateDamageFromGCD(critRate, critMult, 1.0, directHitRate, determinationFactor, tenacityFactor));
        }
示例#9
0
        public static StatsGroup operator -(StatsGroup lhs, StatsGroup rhs)
        {
            StatsGroup ret = new StatsGroup();

            ret.CritRating      = lhs.CritRating - rhs.CritRating;
            ret.SpeedRating     = lhs.SpeedRating - rhs.SpeedRating;
            ret.Determination   = lhs.Determination - rhs.Determination;
            ret.Tenacity        = lhs.Tenacity - rhs.Tenacity;
            ret.DirectHitRating = lhs.DirectHitRating - rhs.DirectHitRating;

            return(ret);
        }
        public double GetDamageOfGCDAttack(StatsGroup stats)
        {
            double critRate            = RatingConversions.GetCritChance(stats.CritRating);
            double critMult            = RatingConversions.GetCritDamageMultiplier(stats.CritRating);
            double directHitRate       = RatingConversions.GetDirectHitChance(stats.DirectHitRating);
            double determinationFactor = RatingConversions.GetDeterminationFactor(stats.Determination);
            double tenacityFactor      = RatingConversions.GetTenacityFactor(stats.Tenacity);

            double critFactor      = (1 - critRate) + (critRate * critMult);
            double directHitFactor = (1 - directHitRate) + (directHitRate * 1.25);

            return(critFactor * directHitFactor * determinationFactor * tenacityFactor);
        }
示例#11
0
        static void SelectStats()
        {
            OpenFileDialog openFile = new OpenFileDialog();

            openFile.Filter = "Character stat files (*.char)|*.char|All files (*.*)|*.*";
            openFile.ShowDialog();
            string file = openFile.FileName;

            try
            {
                CurrentStats = StatsGroup.Load(new FileInfo(file));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
示例#12
0
        public static double MonteCarlo(AttackPattern toSimulate, StatsGroup stats, double duration, int count)
        {
            double total = 0;

            double[] results = new double[count];
            Parallel.For(0, count, i =>
            {
                SimpleSimulator sim = new SimpleSimulator();
                results[i]          = sim.Simulate(toSimulate, stats, duration);
            });
            for (int i = 0; i < count; ++i)
            {
                //results[i] = Simulate(toSimulate, stats, duration);
                total += results[i];
            }
            return(total / count);
        }
示例#13
0
        private static void ModifyStats()
        {
            var stats = (CurrentStats ?? StatsGroup.Baseline).Copy();

            foreach (var statNum in Enum.GetValues(typeof(Stat)))
            {
                var stat = (Stat)statNum;
                Console.Write($"{stat.ToString()} = {stats[stat]}+");
                try
                {
                    int amount = int.Parse(Console.ReadLine());
                    stats[stat] += amount;
                }
                catch
                {
                }
            }
            CurrentStats = stats;
        }
示例#14
0
 public static StatsGroup Load(FileInfo fromFile)
 {
     using (var stream = fromFile.OpenRead())
     {
         var reader = new StreamReader(stream);
         var ret    = new StatsGroup();
         while (stream.CanRead)
         {
             string line = reader.ReadLine();
             if (line == null)
             {
                 break;
             }
             string[] toks = line.Split(new char[] { ' ', '=' }, StringSplitOptions.RemoveEmptyEntries);
             if (toks.Length >= 2)
             {
                 Stat stat = (Stat)Enum.Parse(typeof(Stat), toks[0]);
                 ret[stat] = int.Parse(toks[1]);
             }
         }
         return(ret);
     }
 }
示例#15
0
        static void MainMenu()
        {
            bool terminate = false;

            while (!terminate)
            {
                char selected;
                Console.Clear();
                Console.WriteLine($"Stats Loaded: {CurrentStats != null}");
                Console.WriteLine($"Rotation Selected: {CurrentRotation.Key}");
                Console.WriteLine($"Rulesset Selected: {CurrentSimulationRules.GetType().Name}");
                Console.WriteLine("Choose an Action");
                Console.WriteLine("1 - Load Stats");
                Console.WriteLine("2 - Select Rotation");
                Console.WriteLine("3 - Change Rules");
                Console.WriteLine("4 - Enter Stats Manually");
                if (CurrentStats != null && CurrentRotation.Value != null)
                {
                    Console.WriteLine("G - Go!");
                }
                Console.WriteLine("Q - Quit");
                selected = Console.ReadKey(true).KeyChar;
                switch (selected)
                {
                case '1':
                    SelectStats();
                    break;

                case '2':
                    SelectRotation();
                    break;

                case '3':
                    SelectRules();
                    break;

                case '4':
                    ModifyStats();
                    break;

                case '0':
                    CurrentStats = StatsGroup.Baseline;
                    break;

                case 'G':
                case 'g':
                    RunBasicSimulation();
                    break;

                case 'R':
                case 'r':
                    RunAllRotations();
                    break;

                case 'S':
                case 's':
                    RunStatSimulation();
                    break;

                case 'V':
                case 'v':
                    RunGraph();
                    break;

                case 'P':
                case 'p':
                    SaveStats();
                    break;

                case 'I':
                case 'i':
                    PrintInfo();
                    break;

                case 'Q':
                case 'q':
                    terminate = true;
                    break;

                default:
                    selected = '\0';
                    break;
                }
            }
        }
示例#16
0
 private static void EnterStats()
 {
     CurrentStats = StatsGroup.Baseline;
     ModifyStats();
 }
示例#17
0
 public SimulatedAttackPattern(AttackPattern toSimulate, StatsGroup stats, SimpleSimulator sim)
 {
     this.ToSimulate = toSimulate;
     this.Stats      = stats;
     this.Sim        = sim;
 }
示例#18
0
        public double Simulate(AttackPattern toSimulate, StatsGroup stats, double duration)
        {
            SimulatedAttackPattern simulated = new SimulatedAttackPattern(toSimulate, stats, this);

            return(simulated.SimulateTotalPotencyOver(duration));
        }
示例#19
0
        static void RunStatSimulation()
        {
            bool done = false;

            while (!done)
            {
                try
                {
                    Console.WriteLine("Simulating stat variance");
                    Console.Write("Potential Loss: ");
                    int potentialLoss = int.Parse(Console.ReadLine());
                    Console.Write("Potential Gain: ");
                    int potentialGain = int.Parse(Console.ReadLine());
                    Dictionary <string, StatsGroup> possibleStats = new Dictionary <string, StatsGroup>();
                    if (potentialLoss > 0 && potentialGain > 0)
                    {
                        foreach (var lostStat in StatsGroup.GetEachDPSStat())
                        {
                            foreach (var gainedStat in StatsGroup.GetEachDPSStat())
                            {
                                if (lostStat == gainedStat)
                                {
                                    continue;
                                }
                                string     name     = $"{lostStat}->{gainedStat}";
                                StatsGroup newStats = CurrentStats.Copy();
                                newStats[lostStat]   -= potentialLoss;
                                newStats[gainedStat] += potentialGain;
                                possibleStats[name]   = newStats;
                            }
                        }
                    }
                    else if (potentialLoss > 0)
                    {
                        foreach (var lostStatNum in Enum.GetValues(typeof(Stat)))
                        {
                            Stat       lostStat = (Stat)lostStatNum;
                            string     name     = $"-{potentialLoss} {lostStat}";
                            StatsGroup newStats = CurrentStats.Copy();
                            newStats[lostStat] -= potentialLoss;
                            possibleStats[name] = newStats;
                        }
                    }
                    else if (potentialGain > 0)
                    {
                        foreach (var gainedStatNum in Enum.GetValues(typeof(Stat)))
                        {
                            Stat       gainedStat = (Stat)gainedStatNum;
                            string     name       = $"+{potentialGain} {gainedStat}";
                            StatsGroup newStats   = CurrentStats.Copy();
                            newStats[gainedStat] += potentialGain;
                            possibleStats[name]   = newStats;
                        }
                    }

                    done = true;

                    double baseline = RunSimulation(CurrentStats, CurrentRotation.Value, true);
                    Console.WriteLine($"Baseline is {baseline}");
                    foreach (var stats in possibleStats)
                    {
                        double result     = RunSimulation(stats.Value, CurrentRotation.Value);
                        double delta      = result - baseline;
                        double percentage = delta / baseline * 100;
                        string sign       = result > baseline ? "+" : "";
                        Console.WriteLine($"{stats.Key}: {sign}{percentage:0.00}% ({sign}{delta:#.0})");
                    }
                    Console.WriteLine();
                    Console.ReadKey(true);
                }
                catch { }
            }
        }
示例#20
0
        static double RunSimulation(StatsGroup stats, RotationFactory rotation, bool enableLogging = false)
        {
            double totalPotency = 0;

            if (CurrentSimulationRules is DeterministicSimulator)
            {
                Battle battle = new Battle(new DeterministicSimulator(), sampleDuration);
                if (enableLogging)
                {
                    battle.Logger += Console.WriteLine;
                }
                WarriorOfLight hero = rotation(battle, stats);
                battle.Simulate(hero);
                totalPotency = battle.TotalPotency;

                if (enableLogging)
                {
                    Console.WriteLine();
                    Console.WriteLine("Breakdown by Ability");
                    foreach (var breakdown in battle.PotencyBySource)
                    {
                        double percent = breakdown.Value / battle.TotalPotency * 100;
                        Console.WriteLine($"  {breakdown.Key}: {breakdown.Value:#.0} ({percent:0.00}%)");
                    }
                }
            }
            else if (CurrentSimulationRules is RandomSimulator)
            {
                double[]  potencies = new double[monteCarloCount];
                Stopwatch timer     = new Stopwatch();
                timer.Start();
                int count = 0;

                Battle firstBattle = new Battle(new RandomSimulator(), sampleDuration);
                {
                    WarriorOfLight hero = rotation(firstBattle, stats);
                    firstBattle.Simulate(hero);
                    potencies[0] = firstBattle.TotalPotency;
                }

                Parallel.For(1, monteCarloCount, (i) =>
                {
                    if (timer.Elapsed > monteCarloDuration)
                    {
                        return;
                    }
                    Battle battle       = new Battle(new RandomSimulator(), sampleDuration);
                    WarriorOfLight hero = rotation(battle, stats);
                    battle.Simulate(hero);
                    potencies[i] = battle.TotalPotency;
                });
                timer.Stop();

                double minPotency = double.MaxValue, maxPotency = double.MinValue;
                for (int i = 0; i < monteCarloCount; ++i)
                {
                    totalPotency += potencies[i];
                    if (potencies[i] != 0)
                    {
                        minPotency = Math.Min(minPotency, potencies[i]);
                        maxPotency = Math.Max(maxPotency, potencies[i]);
                        count++;
                    }
                }
                totalPotency /= count;

                if (enableLogging)
                {
                    foreach (var breakdown in firstBattle.PotencyBySource)
                    {
                        double percent = breakdown.Value / firstBattle.TotalPotency * 100;
                        Console.WriteLine($"  {breakdown.Key}: {breakdown.Value:#.0} ({percent:0.00}%)");
                    }
                    Console.WriteLine();
                    Console.WriteLine($"Over {count} trials, PPS ranged from {minPotency / sampleDuration:#.0} to {maxPotency / sampleDuration:#.0}");
                }
            }

            return(totalPotency);
        }