Idle Mafia Macro/Source/src/Profile.cs
public int Level = -1, Xp = -1, XpNext = -1, SkillPoints = -1, EnergyMax = -1, StaminaMax = -1, HealthMax = -1;public int SafeLevel = -1, SafeMax = -1, SafeBonus = -1, Respect = -1, AttackPower = -1, DefensePower = -1;public static readonly string[] Ranks = { "Boss", "Underboss", "Advisor", "Capo", "Soldier", "Associate" };string safe = Regex.Replace(Regex.Replace((name ?? "").Trim(), @"\s+", ""), @"[^A-Za-z0-9_\-]", "_");public static string Key(string name) { string f = Path.GetFileNameWithoutExtension(FileFor("", name)); return f.Substring("profile-".Length); }sb.AppendLine("# What Idle Mafia Bot's \"Check my game\" read from this account: it only opened tabs and rolled lists.");string s = v is DateTime ? ((DateTime)v).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)else if (f.FieldType == typeof(int)) { if (int.TryParse(v, NumberStyles.Integer, CultureInfo.InvariantCulture, out n)) f.SetValue(p, n); }else if (f.FieldType == typeof(double)) { if (double.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) f.SetValue(p, d); }else if (f.FieldType == typeof(DateTime)) { if (DateTime.TryParseExact(v, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out t)) f.SetValue(p, t); }public bool Own(Settings s) { return !Equals(Current(s), typeof(Settings).GetField(Field).GetValue(new Settings())); }{ "Fights", "Attack other players" }, { "Bosses", "Fight bosses" }, { "FightStaminaReserve", "Keep stamina for bosses and fights" },{ "Playtime", "Claim playtime rewards" }, { "Contracts", "Claim contract tasks" }, { "Crates", "Open crates" }, { "EquipBest", "Equip the best gear" },{ "FamilyWatch", "Watch my family" }, { "Takedown", "Use free Takedown attacks" }, { "GiveStamina", "Give stamina to a perk" },case Focus.Family: return "Your family first. Its heists, Takedown and perks, with less stamina kept back.";public static List<Proposal> Propose(Profile p, Focus focus, Settings current, List<JobInfo> catalog)Action<string, object, string> add = (field, value, reason) => list.Add(new Proposal { Field = field, Name = Names[field], Value = value, Reason = reason });string bestText = best != null ? string.Format(IC, " (now {0}, {1:N0} XP for {2} energy)", best.Name, best.Xp, best.Cost) : "";Func<Tab, string, string> notYet = (t, what) => "The " + Title(View.TabLabels[t]) + " tab isn't in your menu yet. Once it shows up, " + what + ".";add("Jobs", true, focus == Focus.Money ? (p.JobCash == 1 ? "Every job pays cash as well as XP, and unused energy is wasted." : "Unused energy is wasted."): focus == Focus.Family ? "Energy has no family use, and your own levels open more of the game." : "Jobs never fail, and unused energy is wasted.");add("JobMode", JobMode.Mastery, "Every job to Gold, top down. 100 times gives a skill point and +15% on that job.");add("JobMode", JobMode.BestXp, p.JobCash == 1 ? "Higher jobs pay more cash per energy too, so the best job is also best for money" + bestText + "."add("JobMode", JobMode.BestXp, "The job with the most XP per energy" + bestText + ". Mastery would spend energy on weaker jobs.");add("JobMode", JobMode.BestXp, "Early levels go fastest with the best job" + bestText + ". Mastery pays off from level 30.");heists += string.Format(IC, " It helps when a help gives more than about {0:N0} XP, what its {1} energy give in your best job", best.XpPerEnergy * helpEnergy, helpEnergy)add("Fights", true, p.Lacks(Tab.Fight) ? notYet(Tab.Fight, "the bot attacks real players with the stamina bosses don't use"): "Bosses go first while they're up. While they're away, fights use stamina that would otherwise go to waste. They attack real players, and a loss costs health.");: p.BossHighest > 0 ? "You've reached stage " + p.BossHighest + ". The bot climbs on as far as your level lets it, and beats the stages again every day for XP and Boss Tokens.": "The bot climbs the boss stages one at a time, and beats them again every day for XP and Boss Tokens.");add("FightStaminaReserve", half, string.Format(IC, "Your stamina bar holds {0}. Keeping {1} for bosses leaves the rest for fights.", p.StaminaMax, half));add("Bank", true, "No fee with your No Bank Fees pass. It banks every few minutes, so a player who beats you gets little.");add("Bank", false, string.Format("Without the No Bank Fees pass each deposit costs {0}%. Cash on hand is only at risk when a player beats you in a fight{1}.",add("Bank", false, "The bank's fee didn't read. Without the No Bank Fees pass each deposit costs 10%. If you have the pass, keep it on.");string slots = p.OpsOpen > 0 ? string.Format("You have {0} slot{1}{2}", p.OpsOpen, p.OpsOpen == 1 ? "" : "s", p.OpsPass > 0 ? " (" + p.OpsPass + " more with the Extra Operations Slot pass)" : "") : null;add("Operations", true, money + (p.OpsOpen == 0 ? "No slot is open yet. The bot starts one as soon as one opens.": (slots != null ? slots + ". The bot collects each one and starts the next" : "The bot collects finished ones and keeps every free slot running")add("Contracts", true, p.Lacks(Tab.Contracts) ? notYet(Tab.Contracts, "the bot claims them") : "Free seals and cash for tasks you do anyway.");add("Crates", true, p.Lacks(Tab.Inventory) ? notYet(Tab.Inventory, "the bot opens them") : "Crates hold gear for your crew.");: p.Henchmen >= 0 ? string.Format("New gear goes straight onto your crew ({0} of {1} henchmen).", p.Henchmen, p.HenchSlots) : "New gear goes straight onto your crew.");add("Takedown", true, "Your free attacks come back by themselves and are wasted when full. It never uses tickets.");add("GiveStamina", true, "Your stamina above the part kept for bosses and fights goes to " + family + "'s perks.");add("FightStaminaReserve", keep, "Family first. Only " + keep + " stamina stays back for bosses and fights, the rest goes to the perks.");if (focus == Focus.XP) add("StaminaPerk", "Hustlers", "Hustlers gives every member +1% job XP per level.");else if (focus == Focus.Family) add("StaminaPerk", "", "The perk closest to its next level, so your family gains the most perk levels.");add("FamilyWatch", true, leader ? "You're " + (p.Rank == "Boss" ? "the Boss" : Article(p.Rank) + " " + p.Rank) + ". The Stamina page shows its level, vault and Takedown."add("FamilyWatch", false, "It only reads the family's pages. " + (rank >= 0 ? "As " + Article(p.Rank) + " " + p.Rank : "As a member")add("PointsStat", 0, string.Format("Your best job, {0}, needs {1} energy and your bar holds {2}.", top.Name, top.Cost, p.EnergyMax));if (v is JobMode) return (JobMode)v == JobMode.BestXp ? "best XP per energy" : (JobMode)v == JobMode.Mastery ? "finish mastery (Gold)" : "one job";case "StaminaPerk": return ((string)v).Trim().Length == 0 ? "closest to its next level" : (string)v;case "PointsStat": { int i = (int)v; return i >= 0 && i < Game.StatNames.Length ? Game.StatNames[i] : v.ToString(); }return "You picked one job yourself (" + s.OneJob.Trim() + "). It stays unless you switch this line on.";if (cur is bool) return (bool)cur ? "You switched this on yourself. It stays on unless you switch this line on."return "You set this yourself (" + Show(p.Field, cur) + "). It stays unless you switch this line on.";if (p.Level > 0) parts.Add("level " + p.Level + (p.Xp >= 0 && p.XpNext > 0 ? string.Format(IC, " ({0:N0} of {1:N0} XP)", p.Xp, p.XpNext) : ""));if (p.EnergyMax > 0) parts.Add(string.Format("energy {0}, stamina {1}, health {2}", p.EnergyMax, N(p.StaminaMax), N(p.HealthMax)));row("You", (p.Name.Length > 0 ? p.Name : "Your name didn't read") + (parts.Count > 0 ? ", " + string.Join(", ", parts) : ""));if (p.Rank.Length > 0) f[0] += ", you're " + (p.Rank == "Boss" ? "the Boss" : Article(p.Rank) + " " + p.Rank);else row("Family", p.InFamily == 0 ? "Not in a family. The family parts wait until you join one." : "Not read.");row("Game menu", p.MenuWhole == 1 && lacking.Count == 0 ? "All " + View.TabLabels.Count + " parts of the game are open.": p.MenuWhole == 1 ? "Not open yet: " + string.Join(", ", lacking.Select(t => Title(View.TabLabels[t]))) + ".": tabs.Count > 0 ? tabs.Count + " parts read. Some entries didn't read, so what's missing isn't known." : "Not read.");row("Bank", p.BankFee == 0 ? "No fee. You have the No Bank Fees pass" + (p.BankFeeFrom == "a deposit" ? " (a deposit's message said so)." : ".")var o = new List<string> { p.OpsOpen + (p.OpsOpen == 1 ? " slot" : " slots") + (p.OpsPass > 0 ? " (" + p.OpsPass + " more with the Extra Operations Slot pass)" : "") };if (p.OpsSlots - p.OpsOpen - Math.Max(0, p.OpsPass) > 0) o.Add((p.OpsSlots - p.OpsOpen - Math.Max(0, p.OpsPass)) + " locked");int open = GameData.CityLevels.Count(l => l <= p.Level), next = Array.FindIndex(GameData.CityLevels, l => l > p.Level);string cities = open + (open == 1 ? " city open, " : " cities open, ") + Title(GameData.Cities[0]) + (open > 1 ? " to " + Title(GameData.Cities[open - 1]) : "") + ".";if (next >= 0) cities += " Next is " + Title(GameData.Cities[next]) + " at level " + GameData.CityLevels[next] + ".";if (folded.Count > 0) cities += " Still folded: " + string.Join(", ", folded.Select(i => Title(GameData.Cities[i]))) + ".";row("Crew", (p.Henchmen >= 0 ? p.Henchmen + " of " + p.HenchSlots + " henchmen" : "") + (p.CrewAttack >= 0 ? (p.Henchmen >= 0 ? ", " : "") + string.Format(IC, "+{0:N0} attack, +{1:N0} defense", p.CrewAttack, p.CrewDefense) : ""));if (p.SafeLevel > 0) s.Add("level " + p.SafeLevel + (p.SafeMax > 0 ? " of " + p.SafeMax : "") + (p.SafeBonus >= 0 ? " (+" + p.SafeBonus + "%)" : ""));row("Bosses", (p.BossHighest >= 0 ? "Highest stage " + p.BossHighest : "Stage " + p.BossStage + " in sight")+ (p.BossStage > 0 && p.BossReady == 1 ? ", stage " + p.BossStage + " ready now" : p.BossStage > 0 && p.BossReady == 0 ? ", stage " + p.BossStage + " beaten today" : "")+ "." + (p.BossNeedLevel > 0 ? " The next stage opens at level " + p.BossNeedLevel + "." : "") + " Beaten stages come back every day at 00:00 UTC.");else if (p.Favors >= 0) row("Heists", p.Favors + " favors left today" + (p.FamilyHeists > 0 ? ", " + p.FamilyHeists + " of your family's heists up" : "") + ".");if (GameData.CityLevels[i] > from && GameData.CityLevels[i] <= level) what = Title(GameData.Cities[i]) + " has opened";if (what == null && p.BossNeedLevel > from && p.BossNeedLevel <= level) what = "a new boss stage has opened (level " + p.BossNeedLevel + ")";if (what == null && p.MenuWhole == 1 && p.TabList.Count < View.TabLabels.Count && p.Level + 5 > from && level >= p.Level + 5)if (what == null && p.Level + 25 > from && level >= p.Level + 25) what = "you've gone up " + (level - p.Level) + " levels";return string.Format(IC, "You're level {0} now, and {1} since the last check (level {2}, {3:dd-MM}). Check again?", level, what, p.Level, p.Checked);return (list ?? "").Split(',').Select(s => GameData.CityIndex(s.Trim())).Where(i => i >= 0).Distinct().ToList();static string Article(string word) { return word.Length > 0 && "AEIOU".IndexOf(char.ToUpperInvariant(word[0])) >= 0 ? "an" : "a"; }