using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ShiftOS { /// /// Hacker battles and stuff like that. /// public class Hacking { public static List Characters = new List(); public static List Tools = new List(); public static List EnemyHackers = new List(); public static List MyNetwork = new List(); public static bool Failure = false; public static DateTime FailDate = DateTime.Now; internal static string HackerBattleAward = null; public static Timer RepairTimer = null; public static Module MyCore { get { var m = new Module(SystemType.Core, 1, "invalid"); foreach(var mod in MyNetwork) { if(mod.Hostname == "localhost") { m = mod; } } return m; } } /// /// Gives a shiftorium upgrade for free. /// /// Upgrade ID. public static void GiveUpgrade(string id) { API.Upgrades[id] = true; } /// /// Increases skill of a character. /// /// The character ID. public static void IncreaseSkill(int cid) { var rnd = new Random(); int newspeed = rnd.Next(0, 5); int newskill = rnd.Next(0, 10); Characters[cid].Speed += newspeed; Characters[cid].Skill += newskill; SaveCharacters(); API.CreateInfoboxSession("Hack complete.", $"{Characters[cid].Name} has successfully completed their hack. {Characters[cid].Name} has gained {newspeed} Speed Points, and {newskill} Skill Points.", infobox.InfoboxMode.Info); } /// /// Applies a hack. /// /// Type of hack to apply. public static void GiveHack(Hack hack) { switch (hack) { case Hack.PayoutIncrease: API.CurrentSave.CodepointMultiplier += 1; break; case Hack.PriceDrop: API.CurrentSave.PriceDivider += 1; break; } } /// /// Add a new character. /// /// The new character. public static void AddCharacter(Character ch) { bool c = true; foreach(var character in Characters) { if(character.Name == ch.Name) { c = false; } } if(c == true) { Characters.Add(ch); SaveCharacters(); } } /// /// Adds a new hacking tool. /// /// The hacking tool. public static void AddTool(HackTool ch) { if (!Tools.Contains(ch)) { Tools.Add(ch); } } /// /// Returns a random hack type. /// /// The hack type. public static Hack GetRandomHack() { var t = new List(Enum.GetValues(typeof(Hack)).Cast()); var rnd = new Random(); return t[rnd.Next(0, t.Count - 1)]; } /// /// Start a hack with a character. /// /// Character to hire. /// Type of hack to pull off. public static void StartHackWithCharacter(int cid, Hack hack) { var h = Characters[cid]; var f = new Form(); f.BackColor = Color.Black; f.ForeColor = Color.White; f.Font = new Font(OSInfo.GetMonospaceFont(), 9); var l = new Label(); int p = 0; int speed = 100000 / h.Speed; //If a hacker has a speed of one, it will take 100,000 milliseconds to move 1% in the hack progress. Divide it by a thousand, you get 10,000 seconds. var t = new Timer(); t.Interval = speed; f.FormBorderStyle = FormBorderStyle.None; f.Show(); switch (API.CurrentSkin.desktoppanelposition) { case "Top": f.Location = new Point(5, API.CurrentSkin.desktoppanelheight + 5); break; case "Bottom": f.Location = new Point(5, 5); break; } f.Controls.Add(l); l.Show(); l.TextAlign = ContentAlignment.MiddleCenter; f.Height = 25; f.TopMost = true; l.Text = $"Progress: {p}%"; l.Dock = DockStyle.Fill; t.Tick += (object s, EventArgs a) => { if (l.Text != "Hack failed.") { if (p <= 100) { l.Text = $"Progress: {p}%"; int fail = new Random().Next(0, h.Skill * h.Speed); if (fail == h.Skill / 2) { l.Text = "Hack failed."; } } else { GiveHack(hack); f.Close(); t.Stop(); IncreaseSkill(cid); } } else { f.Close(); t.Stop(); } p += 1; }; t.Start(); } /// /// Hacker Battles: List of modules the user can buy. /// /// The list that was created by the method. What did you think it would return? A boolean? public static List GetFutureModules() { var lst = new List(); lst.Add(new FutureModule("Antivirus", 15, "This module will heal any other module within it's area of effect to 10 HP. Higher grades can improve it's area of effect.", SystemType.Antivirus)); lst.Add(new FutureModule("Dedicated DDoS module", 10, "This module will attempt to disable the enemy network by sending a DDoS attack allowing you to take a breather.", SystemType.DedicatedDDoS)); lst.Add(new FutureModule("Turret", 5, "It's not super-effective, but the Turret will blast through any Grade 1 defenses pretty quickly. The higher the grade, the higher the strength.", SystemType.Turret)); lst.Add(new FutureModule("Firewall", 20, "Will decrease the amount of damage taken by any module within it's area of effect. The higher the grade, the bigger the area of effect and more protection it offers.", SystemType.Firewall)); lst.Add(new FutureModule("Repair Module", 150, "Slowly repairs all modules within the area of effect to the same HP as the repair module.", SystemType.RepairModule)); lst.Add(new FutureModule("Server Stack", 250, "Capable of sending a worm attack to the entire enemy network, preventing it from attacking until it can recover.", SystemType.ServerStack)); return lst; } /// /// Hire a character to attempt to hack a Shiftorium Upgrade. /// /// The character. /// The upgrade ID. public static void StartHackWithCharacter(int cid, string upgrade) { if (upgrade == "random") { StartHackWithCharacter(cid, GetRandomHack()); } else { var h = Characters[cid]; var f = new Form(); f.BackColor = Color.Black; f.ForeColor = Color.White; f.Font = new Font(OSInfo.GetMonospaceFont(), 9); var l = new Label(); int p = 0; int speed = 100000 / h.Speed; //If a hacker has a speed of one, it will take 100,000 milliseconds to move 1% in the hack progress. Divide it by a thousand, you get 10,000 seconds. var t = new Timer(); t.Interval = speed; f.FormBorderStyle = FormBorderStyle.None; f.Show(); switch (API.CurrentSkin.desktoppanelposition) { case "Top": f.Location = new Point(5, API.CurrentSkin.desktoppanelheight + 5); break; case "Bottom": f.Location = new Point(5, 5); break; } f.Controls.Add(l); l.Show(); l.TextAlign = ContentAlignment.MiddleCenter; f.Height = 25; f.TopMost = true; l.Text = $"Progress: {p}%"; l.Dock = DockStyle.Fill; t.Tick += (object s, EventArgs a) => { if (l.Text != "Hack failed.") { if (p <= 100) { l.Text = $"Progress: {p}%"; int fail = new Random().Next(0, h.Skill + h.Speed); if (fail == h.Skill / 2) { l.Text = "Hack failed."; } } else { GiveUpgrade(upgrade); f.Close(); t.Stop(); IncreaseSkill(cid); } } else { f.Close(); t.Stop(); } p += 1; }; t.Start(); } } /// /// Start a hack with a tool. /// /// Tool ID. /// The hack type. public static void StartHack(int cid, Hack hack) { var h = Tools[cid]; switch (h.Name) { case "Destabilizer Attack": var t = new Timer(); t.Interval = 100; var rnd = new Random(); t.Tick += (object s, EventArgs a) => { int r = rnd.Next(0, 100); if (r == 90) { t.Stop(); API.CreateInfoboxSession("Hack complete.", "The hack has been completed.", infobox.InfoboxMode.Info); GiveHack(hack); } else { try { int p = rnd.Next(0, 10); switch (p) { case 1: API.OpenProgram("shiftorium"); break; case 2: API.OpenProgram("ki"); break; case 3: API.CreateInfoboxSession(API.Encryption.Encrypt("Praise Lord Michael"), API.Encryption.Encrypt("You will bow down to me."), infobox.InfoboxMode.Info); break; case 4: API.PlaySound(Properties.Resources._3beepvirus); break; case 5: API.CurrentSession.BackColor = Color.White; break; case 6: API.CurrentSession.BackColor = Color.Black; break; case 7: API.PlaySound(Properties.Resources.dial_up_modem_02); break; case 8: API.PlaySound(Properties.Resources.writesound); break; case 9: API.PlaySound(Properties.Resources.typesound); break; } } catch(Exception ex) { t.Stop(); var tr = new Terminal(); tr.Show(); tr.WindowState = FormWindowState.Maximized; tr.txtterm.BackColor = Color.Red; tr.Crash(); } } }; t.Start(); break; } } /// /// Start a hack with a tool, to attempt to get an upgrade. /// /// Tool ID. /// Upgrade ID. public static void StartHack(int cid, string upgrade) { if (upgrade == "random") { StartHack(cid, GetRandomHack()); } else { var h = Tools[cid]; switch(h.Name) { case "Destabilizer Attack": var t = new Timer(); t.Interval = 1000 / h.Effectiveness; var rnd = new Random(); t.Tick += (object s, EventArgs a) => { int r = rnd.Next(0, 100); if(r == 90) { t.Stop(); API.CreateInfoboxSession("Hack complete.", "The hack has been completed.", infobox.InfoboxMode.Info); GiveUpgrade(upgrade); } else { int p = rnd.Next(0, 10); switch(p) { case 1: API.OpenProgram("shiftorium"); break; case 2: API.OpenProgram("ki"); break; case 3: API.CreateInfoboxSession(API.Encryption.Encrypt("Praise Lord Michael"), API.Encryption.Encrypt("You will bow down to me."), infobox.InfoboxMode.Info); break; case 4: API.PlaySound(Properties.Resources._3beepvirus); break; case 5: API.CurrentSession.BackColor = Color.White; break; case 6: API.CurrentSession.BackColor = Color.Black; break; case 7: API.PlaySound(Properties.Resources.dial_up_modem_02); break; case 8: API.PlaySound(Properties.Resources.writesound); break; case 9: API.PlaySound(Properties.Resources.typesound); break; } } }; t.Start(); break; } } } /// /// Initiates the Hacker Battle training simulation. /// public static void StartBattleTutorial() { var e = new EnemyHacker("Tutorial", "Tutorial hacker", "Tutorial hacker", 0, 0, "easy"); var y = new HackUI(e); y.IsTutorial = true; API.CreateForm(y, "You", Properties.Resources.iconTerminal); } /// /// Loads characters and other data from the save file. /// public static void GetCharacters() { if (File.Exists(Paths.SystemDir + "_hackers.json")) { Characters = JsonConvert.DeserializeObject>(API.Encryption.Decrypt(File.ReadAllText(Paths.SystemDir + "_hackers.json"))); } else { var c = new Character("BinaryFire", "I may not be good, but it's what I like to do. You don't need to pay me.", 25, 10, 0); AddCharacter(c); File.WriteAllText(Paths.SystemDir + "_hackers.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(Characters))); } if(File.Exists(Paths.SystemDir + "_hacktools.json")) { Tools = JsonConvert.DeserializeObject>(API.Encryption.Decrypt(File.ReadAllText(Paths.SystemDir + "_hacktools.json"))); } else { var c = new HackTool("Destabilizer Attack", 10, "Destabilize ShiftOS by causing it to go beyond what it can do, opening many programs at once, and making it do things it was NEVER intended to do."); AddTool(c); File.WriteAllText(Paths.SystemDir + "_hacktools.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(Tools))); } if (File.Exists(Paths.SystemDir + "_enemies.json")) { EnemyHackers = JsonConvert.DeserializeObject>(API.Encryption.Decrypt(File.ReadAllText(Paths.SystemDir + "_enemies.json"))); } else { var c = new EnemyHacker("Tutorial", "Enter the Tutorial Sequence.", "", 0, 0, "Easy"); EnemyHackers.Add(c); File.WriteAllText(Paths.SystemDir + "enemies.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(EnemyHackers))); } if (File.Exists(Paths.Drivers + "Network.dri")) { MyNetwork = JsonConvert.DeserializeObject>(API.Encryption.Decrypt(File.ReadAllText(Paths.Drivers + "Network.dri"))); } else { var c = new Module(SystemType.Core, 1, "localhost"); c.HP = 100; //bugfix: core not appearing during battle on new save c.X = 0; c.Y = 0; MyNetwork.Add(c); File.WriteAllText(Paths.Drivers + "Network.dri", API.Encryption.Encrypt(JsonConvert.SerializeObject(MyNetwork))); } List coresToRemove = new List(); foreach(var m in MyNetwork) { if(m.Type == SystemType.Core && m != MyCore) { coresToRemove.Add(m); } } foreach(var m in coresToRemove) { MyNetwork.Remove(m); } RepairTimer = new Timer(); RepairTimer.Interval = 2000; var r = new Random(); RepairTimer.Tick += (object s, EventArgs a) => { var repairable = new List(); foreach(var mod in MyNetwork) { if(mod.HP < mod.GetTotalHP()) { repairable.Add(mod); } } int index = r.Next(0, repairable.Count); try { int increase = 1; foreach(var mod in MyNetwork) { if(mod.Type == SystemType.RepairModule) { increase += mod.HP / 4; } } var m = repairable[index]; while(m.HP + increase > m.GetTotalHP()) { increase -= 1; } if(m.HP < m.GetTotalHP()) { m.HP += increase; } } catch { } }; RepairTimer.Start(); } /// /// Saves characters and other data to the save file. /// public static void SaveCharacters() { File.WriteAllText(Paths.SystemDir + "_hackers.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(Characters))); File.WriteAllText(Paths.SystemDir + "_hacktools.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(Tools))); File.WriteAllText(Paths.Drivers + "Network.dri", API.Encryption.Encrypt(JsonConvert.SerializeObject(MyNetwork))); File.WriteAllText(Paths.SystemDir + "_enemies.json", API.Encryption.Encrypt(JsonConvert.SerializeObject(EnemyHackers))); } /// /// Tells user about the 'help hacking' command. /// public static void StartTutorial() { API.CreateInfoboxSession("Upgrade Category Not Available", "This upgrade category requires more capability from the OS, and is locked. You can type 'help hacking' in the Terminal for more info.", infobox.InfoboxMode.Info); } } public class Character { /// /// Creates a new hirable character. /// /// The name of the character. /// The bio of the character. /// Starting skill level. /// Starting speed level. /// Amount of Codepoints required to hire the hacker. public Character(string name, string bio, int skill, int speed, int cost) { Name = name; Skill = skill; Speed = speed; Cost = cost; Bio = bio; } public string Name { get; set; } public int Speed { get; set; } public int Skill { get; set; } public int Cost { get; set; } public string Bio { get; set; } } public class HackTool { /// /// Creates a new hacking tool. /// /// Tool name. /// Effectiveness level. /// Tool description. public HackTool(string name, int effectiveness, string description) { Name = name; Effectiveness = effectiveness; Description = description; } public string Name { get; set; } public int Effectiveness { get; set; } public string Description { get; set; } } /// /// Enum representing a type of hack. /// public enum Hack { PriceDrop, PayoutIncrease, } public class Module { /// /// Creates a new module. /// /// Type of module. /// Starting grade level. /// Hostname. public Module(SystemType t, int grade, string hname) { Hostname = hname; Type = t; Grade = grade; } public string Hostname { get; set; } public ModuleType ModuleType { get; set; } public SystemType Type { get; set; } public int HP { get; set; } public int Grade { get; set; } /// /// X position on the virtual network. /// public int X { get; set; } /// /// Y position on the virtual network. /// public int Y { get; set; } /// /// Deploys the module to a Computer control that can actually do things. /// /// The new computer. public Computer Deploy() { var c = new Computer(); c.TotalHP = GetTotalHP(); //for proper status display c.Hostname = Hostname; c.Type = Type; c.HP = HP; c.Visible = true; c.Grade = Grade; if(X != 0 && Y != 0) { c.Location = new Point(X, Y); } return c; } public int GetTotalHP() { switch (Type) { case SystemType.Core: return 100; default: switch (Grade) { case 1: return 10; case 2: return 20; case 3: return 40; case 4: return 80; default: return 10; } } } } /// /// Unused... /// public enum ModuleType { Offensive, Defensive } public class EnemyHacker { /// /// An enemy network. /// /// Leader or network name. /// Network Description /// If the leader becomes a friend, what will his bio be? /// If the leader becomes a friend, what will his skill be? /// If the leader becomes a friend, what will his speed be? /// Arbitrary value that means absolutely nothing. public EnemyHacker(string name, string description, string fdesc, int fskill, int fspeed, string difficulty) { Name = name; Description = description; FriendDesc = fdesc; FriendSkill = fskill; FriendSpeed = fspeed; Difficulty = difficulty; Network = new List(); var m = new Module(SystemType.Core, 1, name.ToLower().Replace(" ", "_")); m.X = 0; m.Y = 0; Network.Add(m); //Hacker will always have a core system. } public bool IsLeader = false; public string Name { get; set; } public string FriendDesc { get; set; } public string Description { get; set; } public int FriendSpeed { get; set; } public int FriendSkill { get; set; } public string Difficulty { get; set; } public List Network { get; set; } /// /// Add a new module to this hacker's network. /// /// The module to add. public void AddModule(Module m) { Network.Add(m); } /// /// Befriends the leader. /// /// How much will it cost to hire him? public void Befriend(int cost) { var c = new Character(Name, FriendDesc, FriendSpeed, FriendSkill, cost); Hacking.AddCharacter(c); Hacking.SaveCharacters(); } } public class FutureModule { /// /// A purchasable module. /// /// Module name. /// Cost in Codepoints /// Module description /// Module type. public FutureModule(string name, int cost, string description, SystemType type) { Name = name; Description = description; Type = type; Cost = cost; } public string Name { get; set; } public int Cost { get; set; } public string Description { get; set; } public SystemType Type { get; set; } } }