// copy constructor, amrite? public Stats(Stats rhs) { Health = rhs.Health; Attack = rhs.Attack; Defense = rhs.Defense; Speed = rhs.Speed; CritRate = rhs.CritRate; CritDamage = rhs.CritDamage; Resistance = rhs.Resistance; Accuracy = rhs.Accuracy; }
// sum the result of dividing the runes value by flat/percent per stat internal double Test(Stats rFlat, Stats rPerc, int fake, bool pred) { double val = 0; for (int i = 0; i < Build.statNames.Length; i++) { string stat = Build.statNames[i]; if (i < 4 && rFlat[stat] != 0) val += this[stat + "flat", fake, pred] / (double)rFlat[stat]; if (i != 3 && rPerc[stat] != 0) val += this[stat + "perc", fake, pred] / (double)rPerc[stat]; } return val; }
// For each non-zero stat in flat and percent, divide the runes value and see if any >= test public bool Or(Stats rFlat, Stats rPerc, Stats rTest, int fake, bool pred) { for (int i = 0; i < Build.statNames.Length; i++) { string stat = Build.statNames[i]; if (i < 4 && rFlat[stat] != 0 && rTest[stat] != 0) if (this[stat + "flat", fake, pred] / (double)rFlat[stat] >= rTest[stat]) return true; if (i != 3 && rPerc[stat] != 0 && rTest[stat] != 0) if (this[stat + "perc", fake, pred] / (double)rPerc[stat] >= rTest[stat]) return true; } return false; }
/// <summary> /// Fills the instance with acceptable runes from save /// </summary> /// <param name="save">The Save data that contais the runes</param> /// <param name="useLocked">If it should include locked runes</param> /// <param name="useEquipped">If it should include equipped runes (other than the current monster)</param> public void GenRunes(Save save, bool useLocked = false, bool useEquipped = false, bool saveStats = false) { if (save == null) return; if (save.Runes == null) return; IEnumerable<Rune> rsGlobal = save.Runes; // Only using 'inventory' or runes on mon // also, include runes which have been unequipped (should only look above) if (!useEquipped) rsGlobal = rsGlobal.Where(r => (r.AssignedName == "Unknown name" || r.AssignedName == mon.Name) || r.Swapped); // only if the rune isn't currently locked for another purpose if (!useLocked) rsGlobal = rsGlobal.Where(r => r.Locked == false); // Only runes which we've included rsGlobal = rsGlobal.Where(r => BuildSets.Contains(r.Set)); if (saveStats) { foreach (Rune r in rsGlobal) { r.manageStats_Set++; } } int[] slotFakes = new int[6]; bool[] slotPred = new bool[6]; // For each runeslot for (int i = 0; i < 6; i++) { // put the right ones in runes[i] = rsGlobal.Where(r => r.Slot == i + 1).ToArray(); // crank the rune prediction Rune[] rs = runes[i]; int raiseTo = 0; bool predictSubs = false; // find the largest number to raise to // if any along the tree say to predict, do it if (runePrediction.ContainsKey("g")) { int glevel = runePrediction["g"].Key; if (glevel > raiseTo) raiseTo = glevel; predictSubs |= runePrediction["g"].Value; } if (runePrediction.ContainsKey(((i % 2 == 0) ? "o" : "e"))) { int mlevel = runePrediction[((i % 2 == 0) ? "o" : "e")].Key; if (mlevel > raiseTo) raiseTo = mlevel; predictSubs |= runePrediction[((i % 2 == 0) ? "o" : "e")].Value; } if (runePrediction.ContainsKey((i + 1).ToString())) { int slevel = runePrediction[(i + 1).ToString()].Key; if (slevel > raiseTo) raiseTo = slevel; predictSubs |= runePrediction[(i + 1).ToString()].Value; } slotFakes[i] = raiseTo; slotPred[i] = predictSubs; // default fail OR Predicate<Rune> slotTest = r => false; int and = 0; // this means that runes won't get in unless they meet at least 1 criteria // which tab we pulled the filter from string gotScore = ""; // the value to test SUM against int testVal = 0; // TODO: check what inheriting SUM (eg. Odd and 3) does // TODO: check what inheriting AND/OR then SUM (or visa versa) // find the most significant operatand of joining checks if (runeScoring.ContainsKey("g") && runeFilters.ContainsKey("g") && runeFilters["g"].Any(r => r.Value.NonZero)) { var kv = runeScoring["g"]; gotScore = "g"; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // is it and odd or even slot? string tmk = (i % 2 == 1 ? "e" : "o"); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // turn the 0-5 to a 1-6 tmk = (i + 1).ToString(); if (runeScoring.ContainsKey(tmk) && runeFilters.ContainsKey(tmk) && runeFilters[tmk].Any(r => r.Value.NonZero)) { var kv = runeScoring[tmk]; gotScore = tmk; and = kv.Key; if (kv.Key == 1) { slotTest = r => true; } else if (kv.Key == 2) { testVal = kv.Value; } } // if an operand was found, ensure the tab contains filter data if (gotScore != "") { if (runeFilters.ContainsKey(gotScore)) { // if all the filters for the tab are zero if (runeFilters[gotScore].All(r => !r.Value.NonZero)) { // set to OR TRUE slotTest = r => true; and = 0; } } } else { // if there wasn't any relevant data for how to pick runes, just take 'em all! slotTest = r => true; } // pull the filters (flat, perc, test) for all the tabs and stats Dictionary<string, RuneFilter> rfG = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey("g")) rfG = runeFilters["g"]; Dictionary<string, RuneFilter> rfM = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey((i % 2 == 1 ? "e" : "o"))) rfM = runeFilters[(i % 2 == 1 ? "e" : "o")]; Dictionary<string, RuneFilter> rfS = new Dictionary<string, RuneFilter>(); if (runeFilters.ContainsKey((i+1).ToString())) rfS = runeFilters[(i + 1).ToString()]; // if there where no filters with data bool blank = true; Stats rFlat = new Stats(); Stats rPerc = new Stats(); Stats rTest = new Stats(); foreach (string stat in statNames) { RuneFilter rf = new RuneFilter(); if (rfS.ContainsKey(stat)) { rf = rfS[stat]; if (rfM.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfM[stat]); if (rfG.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfG[stat]); } else { if (rfM.ContainsKey(stat)) { rf = rfM[stat]; if (rfG.ContainsKey(stat)) rf = RuneFilter.Min(rf, rfG[stat]); } else { if (rfG.ContainsKey(stat)) rf = rfG[stat]; } } if (rf.NonZero) { // put the most relevant divisor in? rFlat[stat] = rf.Flat; rPerc[stat] = rf.Percent; rTest[stat] = rf.Test; blank = false; } } // TODO: seems like it just ignores all the slotTesting before now // no filter data = use all if (blank) slotTest = r => true; else { // Set the test based on the type found if (and == 0) { slotTest = r => r.Or(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 1) { slotTest = r => r.And(rFlat, rPerc, rTest, raiseTo, predictSubs); } else if (and == 2) { slotTest = r => r.Test(rFlat, rPerc, raiseTo, predictSubs) >= testVal; } } runes[i] = runes[i].Where(r => slotTest.Invoke(r)).ToArray(); if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_RuneFilt++; } } if (i % 2 == 1) // actually evens because off by 1 { // makes sure that the primary stat type is in the selection if (slotStats[i].Count > 0) runes[i] = runes[i].Where(r => slotStats[i].Contains(r.MainType.ToForms())).ToArray(); } if (saveStats) { foreach (Rune r in runes[i]) { r.manageStats_TypeFilt++; } } } // Make sure that for each set type, there are enough slots with runes in them // Eg. if only 1,4,5 have Violent, remove all violent runes because you need 4 // for each included set foreach (RuneSet s in BuildSets) { // find how many slots have acceptable runes for it int slots = 0; for (int i = 0; i < 6; i++) { if (runes[i].Any(r => r.Set == s)) slots += 1; } // if there isn't enough slots if (slots < Rune.SetRequired(s)) { // remove that set for (int i = 0; i < 6; i++) { runes[i] = runes[i].Where(r => r.Set != s).ToArray(); } } } }
internal bool GreaterEqual(Stats rhs) { if (this.Accuracy < rhs.Accuracy) return false; if (this.Attack < rhs.Attack) return false; if (this.CritDamage < rhs.CritDamage) return false; if (this.CritRate < rhs.CritRate) return false; if (this.Defense < rhs.Defense) return false; if (this.Health < rhs.Health) return false; if (this.Resistance < rhs.Resistance) return false; if (this.Speed < rhs.Speed) return false; return true; }
private void ShowStats(Stats cur, Stats mon) { foreach (string stat in new string[] { "HP", "ATK", "DEF", "SPD" }) { groupBox1.Controls.Find(stat + "Base", false).FirstOrDefault().Text = mon[stat].ToString(); groupBox1.Controls.Find(stat + "Total", false).FirstOrDefault().Text = cur[stat].ToString(); groupBox1.Controls.Find(stat + "Bonus", false).FirstOrDefault().Text = "+" + (cur[stat] - mon[stat]).ToString(); } foreach (string stat in new string[] { "CR", "CD", "RES", "ACC" }) { groupBox1.Controls.Find(stat + "Base", false).FirstOrDefault().Text = mon[stat].ToString() + "%"; groupBox1.Controls.Find(stat + "Total", false).FirstOrDefault().Text = cur[stat].ToString() + "%"; groupBox1.Controls.Find(stat + "Bonus", false).FirstOrDefault().Text = "+" + (cur[stat] - mon[stat]).ToString(); } }
private void refreshStats(Monster mon, Stats cur) { statName.Text = mon.Name; statID.Text = mon.ID.ToString(); statLevel.Text = mon.level.ToString(); // read a bunch of numbers foreach (var stat in statNames) { var ctrlBase = (Label)groupBox1.Controls.Find(stat + "Base", true).FirstOrDefault(); ctrlBase.Text = mon[stat].ToString(); var ctrlBonus = (Label)groupBox1.Controls.Find(stat + "Bonus", true).FirstOrDefault(); var ctrlTotal = (TextBox)groupBox1.Controls.Find(stat + "Total", true).FirstOrDefault(); ctrlTotal.Tag = new KeyValuePair<Label, Label>(ctrlBase, ctrlBonus); var ctrlCurrent = groupBox1.Controls.Find(stat + "Current", true).FirstOrDefault(); ctrlCurrent.Text = cur[stat].ToString(); var ctrlWorth = groupBox1.Controls.Find(stat + "Worth", true).FirstOrDefault(); var ctrlThresh = groupBox1.Controls.Find(stat + "Thresh", true).FirstOrDefault(); var ctrlMax = groupBox1.Controls.Find(stat + "Max", true).FirstOrDefault(); if (build.Minimum[stat] > 0) ctrlTotal.Text = build.Minimum[stat].ToString(); if (build.Sort[stat] != 0) ctrlWorth.Text = build.Sort[stat].ToString(); if (build.Maximum[stat] != 0) ctrlMax.Text = build.Maximum[stat].ToString(); if (build.Threshold[stat] != 0) ctrlThresh.Text = build.Threshold[stat].ToString(); } foreach (var extra in extraNames) { var ctrlBase = (Label)groupBox1.Controls.Find(extra + "Base", true).FirstOrDefault(); ctrlBase.Text = mon.ExtraValue(extra).ToString(); var ctrlBonus = (Label)groupBox1.Controls.Find(extra + "Bonus", true).FirstOrDefault(); var ctrlTotal = (TextBox)groupBox1.Controls.Find(extra + "Total", true).FirstOrDefault(); ctrlTotal.Tag = new KeyValuePair<Label, Label>(ctrlBase, ctrlBonus); var ctrlCurrent = groupBox1.Controls.Find(extra + "Current", true).FirstOrDefault(); ctrlCurrent.Text = cur.ExtraValue(extra).ToString(); var ctrlWorth = groupBox1.Controls.Find(extra + "Worth", true).FirstOrDefault(); var ctrlThresh = groupBox1.Controls.Find(extra + "Thresh", true).FirstOrDefault(); var ctrlMax = groupBox1.Controls.Find(extra + "Max", true).FirstOrDefault(); if (build.Minimum.ExtraGet(extra) > 0) ctrlTotal.Text = build.Minimum.ExtraGet(extra).ToString(); if (build.Sort.ExtraGet(extra) != 0) ctrlWorth.Text = build.Sort.ExtraGet(extra).ToString(); if (build.Maximum.ExtraGet(extra) != 0) ctrlMax.Text = build.Maximum.ExtraGet(extra).ToString(); if (build.Threshold.ExtraGet(extra) != 0) ctrlThresh.Text = build.Threshold.ExtraGet(extra).ToString(); } }
// Using the given stats as a base, apply the modifiers public Stats GetStats(Stats baseStats) { Stats value = new Stats(baseStats); // Apply percent before flat value.Health += (int)Math.Ceiling(baseStats.Health * HealthPercent / 100.0) + HealthFlat; value.Attack += (int)Math.Ceiling(baseStats.Attack * AttackPercent / 100.0) + AttackFlat; value.Defense += (int)Math.Ceiling(baseStats.Defense * DefensePercent / 100.0) + DefenseFlat; value.Speed += (int)Math.Ceiling(baseStats.Speed * SpeedPercent / 100.0) + Speed; value.CritDamage += CritDamage; value.CritRate += CritRate; value.Accuracy += Accuracy; value.Resistance += Resistance; return value; }
private double GetPoints(Stats Cur, Action<string, int> w = null) { double pts = 0; double p; int i = 1; foreach (var stat in statNames) { string str = Cur[stat].ToString(); if (build.Sort[stat] != 0) { p = Cur[stat] / build.Sort[stat]; if (build.Threshold[stat] != 0) p -= Math.Max(0, Cur[stat] - build.Threshold[stat]) / build.Sort[stat]; str = p.ToString("0.#") + " (" + Cur[stat].ToString() + ")"; pts += p; } w.Invoke(str, i); i++; } foreach (var extra in extraNames) { string str = Cur.ExtraValue(extra).ToString(); if (build.Sort.ExtraGet(extra) != 0) { p = Cur.ExtraValue(extra) / build.Sort.ExtraGet(extra); if (build.Threshold.ExtraGet(extra) != 0) p -= Math.Max(0, Cur.ExtraValue(extra) - build.Threshold.ExtraGet(extra)) / build.Sort.ExtraGet(extra); str = p.ToString("0.#") + " (" + Cur.ExtraValue(extra).ToString() + ")"; pts += p; } w.Invoke(str, i); i++; } return pts; }