aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael <[email protected]>2017-08-04 18:35:53 -0400
committerMichael <[email protected]>2017-08-04 18:35:53 -0400
commit6ec4837523395accbb0ed8c9b206daa6882adc1a (patch)
tree93548c562bf1583143092b6e7158c3f027f331c1
parent1f131438c0be7fe7a7c558530d32f24d3696686a (diff)
downloadshiftos_thereturn-6ec4837523395accbb0ed8c9b206daa6882adc1a.tar.gz
shiftos_thereturn-6ec4837523395accbb0ed8c9b206daa6882adc1a.tar.bz2
shiftos_thereturn-6ec4837523395accbb0ed8c9b206daa6882adc1a.zip
chat stuff and eas failure
-rw-r--r--ShiftOS.Frontend/Apps/ChatClient.cs153
-rw-r--r--ShiftOS.Frontend/Commands.cs24
-rw-r--r--ShiftOS.Frontend/ShiftOS.cs237
-rw-r--r--ShiftOS.Frontend/Stories/BeginTutorials.cs52
-rw-r--r--ShiftOS.Objects/IRCNetwork.cs37
-rw-r--r--ShiftOS.Objects/ShiftOS.Objects.csproj1
-rw-r--r--ShiftOS_TheReturn/Story.cs8
7 files changed, 421 insertions, 91 deletions
diff --git a/ShiftOS.Frontend/Apps/ChatClient.cs b/ShiftOS.Frontend/Apps/ChatClient.cs
index 1f685dc..ab4ea76 100644
--- a/ShiftOS.Frontend/Apps/ChatClient.cs
+++ b/ShiftOS.Frontend/Apps/ChatClient.cs
@@ -11,6 +11,7 @@ using ShiftOS.Frontend.GraphicsSubsystem;
using Microsoft.Xna.Framework;
using static ShiftOS.Engine.SkinEngine;
using System.Text.RegularExpressions;
+using System.Threading;
namespace ShiftOS.Frontend.Apps
{
@@ -23,17 +24,12 @@ namespace ShiftOS.Frontend.Apps
private TextInput _input = null;
private Button _send = null;
private List<ChatMessage> _messages = new List<ChatMessage>();
-
-
+ const int usersListWidth = 100;
+ const int topicBarHeight = 24;
+ public IRCNetwork NetInfo = null;
public ChatClient()
{
- _messages.Add(new ChatMessage
- {
- Timestamp = DateTime.Now,
- Author = "michael",
- Message = "Welcome to ShiftOS IRC! Type in the box below to type a message."
- });
_send = new GUI.Button();
_input = new GUI.TextInput();
_sendprompt = new GUI.TextControl();
@@ -81,6 +77,16 @@ namespace ShiftOS.Frontend.Apps
}
}
+ public bool ChannelConnected
+ {
+ get; private set;
+ }
+
+ public bool NetworkConnected
+ {
+ get; private set;
+ }
+
public void SendMessage()
{
_messages.Add(new Apps.ChatMessage
@@ -150,13 +156,16 @@ namespace ShiftOS.Frontend.Apps
protected override void OnPaint(GraphicsContext gfx)
{
+ int messagesTop = NetworkConnected ? topicBarHeight : 0;
+ int messagesFromRight = ChannelConnected ? usersListWidth : 0;
+
int _bottomseparator = _send.Y - 10;
gfx.DrawRectangle(0, _bottomseparator, Width, 1, UIManager.SkinTextures["ControlTextColor"]);
int nnGap = 25;
int messagebottom = _bottomseparator - 5;
foreach (var msg in _messages.OrderByDescending(x=>x.Timestamp))
{
- if (Height - messagebottom <= 0)
+ if (Height - messagebottom <= messagesTop)
break;
var tsProper = $"[{msg.Timestamp.Hour.ToString("##")}:{msg.Timestamp.Minute.ToString("##")}]";
var nnProper = $"<{msg.Author}>";
@@ -166,16 +175,134 @@ namespace ShiftOS.Frontend.Apps
vertSeparatorLeft = (int)Math.Round(Math.Max(vertSeparatorLeft, tsMeasure.X + nnGap + nnMeasure.X+2));
if (old != vertSeparatorLeft)
requiresRepaint = true;
- var msgMeasure = gfx.MeasureString(msg.Message, LoadedSkin.TerminalFont, Width - vertSeparatorLeft - 4);
+ var msgMeasure = gfx.MeasureString(msg.Message, LoadedSkin.TerminalFont, (Width - vertSeparatorLeft - 4) - messagesFromRight);
messagebottom -= (int)msgMeasure.Y;
gfx.DrawString(tsProper, 0, messagebottom, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.TerminalFont);
- var nnColor = (msg.Author == SaveSystem.CurrentSave.Username) ? Color.Red : Color.LightGreen;
+ var nnColor = Color.LightGreen;
+
+ if (msg.Author == SaveSystem.CurrentSave.Username)
+ nnColor = Color.Red;
+ else
+ {
+ if (NetInfo != null)
+ {
+ if (NetInfo.Channel != null)
+ {
+ if (NetInfo.Channel.OnlineUsers != null)
+ {
+ var user = NetInfo.Channel.OnlineUsers.FirstOrDefault(x => x.Nickname == msg.Author);
+ if(user != null)
+ {
+ switch(user.Permission)
+ {
+ case IRCPermission.ChanOp:
+ nnColor = Color.Orange;
+ break;
+ case IRCPermission.NetOp:
+ nnColor = Color.Yellow;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
gfx.DrawString(nnProper, (int)tsMeasure.X + nnGap, messagebottom, nnColor, LoadedSkin.TerminalFont);
- gfx.DrawString(msg.Message, vertSeparatorLeft + 4, messagebottom, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.TerminalFont, Width - vertSeparatorLeft - 4);
+ var mcolor = LoadedSkin.ControlTextColor.ToMonoColor();
+ if (msg.Message.Contains(SaveSystem.CurrentSave.Username))
+ mcolor = Color.Orange;
+ gfx.DrawString(msg.Message, vertSeparatorLeft + 4, messagebottom, mcolor, LoadedSkin.TerminalFont, (Width - vertSeparatorLeft - 4) - messagesFromRight);
+ }
+
+ string topic = "";
+ if (NetworkConnected)
+ {
+ topic = $"{NetInfo.FriendlyName}: {NetInfo.MOTD}";
+ if (ChannelConnected)
+ {
+ topic = $"#{NetInfo.Channel.Tag} | {NetInfo.Channel.Topic}";
+ int usersStartY = messagesTop;
+ foreach(var user in NetInfo.Channel.OnlineUsers.OrderBy(x=>x.Nickname))
+ {
+ var measure = gfx.MeasureString(user.Nickname, LoadedSkin.TerminalFont);
+
+ var nnColor = Color.LightGreen;
+ if (user.Nickname == SaveSystem.CurrentSave.Username)
+ nnColor = Color.Red;
+ else
+ {
+ switch (user.Permission)
+ {
+ case IRCPermission.ChanOp:
+ nnColor = Color.Orange;
+ break;
+ case IRCPermission.NetOp:
+ nnColor = Color.Yellow;
+ break;
+ }
+ }
+
+ gfx.DrawString(user.Nickname, Width - messagesFromRight + 2, usersStartY, nnColor, LoadedSkin.TerminalFont);
+
+ usersStartY += (int)measure.Y;
+ }
+ gfx.DrawRectangle(Width - messagesFromRight, messagesTop, 1, _bottomseparator - messagesTop, LoadedSkin.ControlTextColor.ToMonoColor());
+ }
+ gfx.DrawString(topic, 0, 0, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.TerminalFont);
+ gfx.DrawRectangle(0, messagesTop, Width, 1, LoadedSkin.ControlTextColor.ToMonoColor());
}
- gfx.DrawRectangle(vertSeparatorLeft, 0, 1, _bottomseparator, UIManager.SkinTextures["ControlTextColor"]);
+
+ gfx.DrawRectangle(vertSeparatorLeft, messagesTop, 1, _bottomseparator - messagesTop, UIManager.SkinTextures["ControlTextColor"]);
}
+ public void FakeConnection(IRCNetwork net)
+ {
+ NetInfo = net;
+ var cs = net.Channel.OnlineUsers.FirstOrDefault(x => x.Nickname == "ChanServ");
+ if (cs == null)
+ net.Channel.OnlineUsers.Add(new IRCUser
+ {
+ Nickname = "ChanServ",
+ Permission = IRCPermission.ChanOp
+ });
+ var t = new Thread(() =>
+ {
+ SendClientMessage("shiftos", $"Looking up {net.SystemName}");
+ Thread.Sleep(250);
+ SendClientMessage("*", $"Connecting to {net.SystemName} ({net.SystemName}:6667)");
+ Thread.Sleep(1500);
+ SendClientMessage("*", "Connected. Now logging in.");
+ Thread.Sleep(25);
+ SendClientMessage("*", "*** Looking up your hostname... ");
+ Thread.Sleep(2000);
+ SendClientMessage("*", "***Checking Ident");
+ Thread.Sleep(10);
+ SendClientMessage("*", "*** Couldn't look up your hostname");
+ Thread.Sleep(10);
+ SendClientMessage("*", "***No Ident response");
+ Thread.Sleep(750);
+ SendClientMessage("*", "Capabilities supported: account-notify extended-join identify-msg multi-prefix sasl");
+ Thread.Sleep(250);
+ SendClientMessage("*", "Capabilities requested: account-notify extended-join identify-msg multi-prefix");
+ Thread.Sleep(250);
+ SendClientMessage("*", "Capabilities acknowledged: account-notify extended-join identify-msg multi-prefix");
+ Thread.Sleep(500);
+ SendClientMessage("*", $"Welcome to the {net.FriendlyName} {SaveSystem.CurrentSave.Username}");
+ NetworkConnected = true;
+ Thread.Sleep(250);
+ SendClientMessage("*", $"{SaveSystem.CurrentSave.Username} sets mode +i on {SaveSystem.CurrentSave.Username}");
+ Thread.Sleep(300);
+ SendClientMessage("shiftos", "Joining #" + net.Channel.Tag);
+ Thread.Sleep(100);
+ ChannelConnected = true;
+ SendClientMessage("shiftos", $"{net.Channel.Topic}: {net.Channel.OnlineUsers.Count} users online");
+ Thread.Sleep(10);
+ SendClientMessage("ChanServ", "ChanServ sets mode -v on " + SaveSystem.CurrentSave.Username);
+ });
+ t.Start();
+ }
+
public void OnLoad()
{
if (System.IO.File.Exists("aicache.dat"))
diff --git a/ShiftOS.Frontend/Commands.cs b/ShiftOS.Frontend/Commands.cs
index 67bf94f..e557ea2 100644
--- a/ShiftOS.Frontend/Commands.cs
+++ b/ShiftOS.Frontend/Commands.cs
@@ -44,6 +44,30 @@ using ShiftOS.Engine;
namespace ShiftOS.Frontend
{
+ public static class FrontendDebugCommands
+ {
+ /// <summary>
+ /// Debug command to drop a fatal objective/hack failure screen in the form of an emergency alert system-esque screen.
+ ///
+ /// ...Because WE'RE CANADA.
+ /// </summary>
+ [Command("drop_eas")]
+ [ShellConstraint("shiftos_debug> ")]
+ [RequiresArgument("id")]
+ public static void DropEAS(Dictionary<string, object> args)
+ {
+ Story.DisplayFailure(args["id"].ToString());
+ }
+
+ [Command("loaddefaultskn")]
+ [ShellConstraint("shiftos_debug> ")]
+ public static void LoadDefault()
+ {
+ Utils.Delete(Paths.GetPath("skin.json"));
+ SkinEngine.Init();
+ }
+ }
+
public static class Cowsay
{
[Command("cowsay")]
diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs
index 597c4ff..5c897d3 100644
--- a/ShiftOS.Frontend/ShiftOS.cs
+++ b/ShiftOS.Frontend/ShiftOS.cs
@@ -19,10 +19,28 @@ namespace ShiftOS.Frontend
internal GraphicsDeviceManager graphicsDevice;
SpriteBatch spriteBatch;
+ private bool isFailing = false;
+ private double failFadeInMS = 0;
+ private const double failFadeMaxMS = 500;
+ private string failMessage = "";
+ private string failRealMessage = "";
+ private double failFadeOutMS = 0;
+ private bool failEnded = false;
+ private double failCharAddMS = 0;
+
private bool DisplayDebugInfo = false;
public ShiftOS()
{
+ Story.FailureRequested += (message) =>
+ {
+ failMessage = "";
+ failRealMessage = message;
+ isFailing = true;
+ failFadeInMS = 0;
+ failFadeOutMS = 0;
+ failEnded = false;
+ };
graphicsDevice = new GraphicsDeviceManager(this);
var uconf = Objects.UserConfig.Get();
graphicsDevice.PreferredBackBufferHeight = uconf.ScreenHeight;
@@ -154,115 +172,163 @@ namespace ShiftOS.Frontend
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
- if (UIManager.CrossThreadOperations.Count > 0)
+ if (isFailing)
{
- var action = UIManager.CrossThreadOperations.Dequeue();
- action?.Invoke();
- }
+ if (failFadeInMS < failFadeMaxMS)
+ failFadeInMS += gameTime.ElapsedGameTime.TotalMilliseconds;
+ if(failEnded == false)
+ {
+ shroudOpacity = (float)GUI.ProgressBar.linear(failFadeInMS, 0, failFadeMaxMS, 0, 1);
+ if(shroudOpacity >= 1)
+ {
+ if (failMessage == failRealMessage + "|")
+ {
+ var keydata = Keyboard.GetState();
- //Let's get the mouse state
- var mouseState = Mouse.GetState(this.Window);
- LastMouseState = mouseState;
-
- UIManager.ProcessMouseState(LastMouseState, mouseMS);
- if (mouseState.LeftButton == ButtonState.Pressed)
- {
- mouseMS = 0;
+ if (keydata.GetPressedKeys().FirstOrDefault(x => x != Keys.None) != Keys.None)
+ {
+ failEnded = true;
+ }
+ }
+ else
+ {
+ failCharAddMS += gameTime.ElapsedGameTime.TotalMilliseconds;
+ if (failCharAddMS >= 75)
+ {
+ failMessage = failRealMessage.Substring(0, failMessage.Length) + "|";
+ failCharAddMS = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ if(failFadeOutMS < failFadeMaxMS)
+ {
+ failFadeOutMS += gameTime.ElapsedGameTime.TotalMilliseconds;
+ }
+
+ shroudOpacity = 1 - (float)GUI.ProgressBar.linear(failFadeOutMS, 0, failFadeMaxMS, 0, 1);
+
+ if(shroudOpacity <= 0)
+ {
+ isFailing = false;
+ }
+ }
}
else
{
- mouseMS += gameTime.ElapsedGameTime.TotalMilliseconds;
+ if (UIManager.CrossThreadOperations.Count > 0)
+ {
+ var action = UIManager.CrossThreadOperations.Dequeue();
+ action?.Invoke();
+ }
- }
- //So we have mouse input, and the UI layout system working...
+ //Let's get the mouse state
+ var mouseState = Mouse.GetState(this.Window);
+ LastMouseState = mouseState;
- //But an OS isn't useful without the keyboard!
+ UIManager.ProcessMouseState(LastMouseState, mouseMS);
+ if (mouseState.LeftButton == ButtonState.Pressed)
+ {
+ mouseMS = 0;
+ }
+ else
+ {
+ mouseMS += gameTime.ElapsedGameTime.TotalMilliseconds;
- //Let's see how keyboard input works.
+ }
+ //So we have mouse input, and the UI layout system working...
- //Hmmm... just like the mouse...
- var keystate = Keyboard.GetState();
+ //But an OS isn't useful without the keyboard!
- //Simple... just iterate through this list and generate some key events?
- var keys = keystate.GetPressedKeys();
- if (keys.Length > 0)
- {
- var key = keys.FirstOrDefault(x => x != Keys.LeftControl && x != Keys.RightControl && x != Keys.LeftShift && x != Keys.RightShift && x != Keys.LeftAlt && x != Keys.RightAlt);
- if(lastKey != key)
- {
- kb_elapsedms = 0;
- lastKey = key;
- }
- }
- if (keystate.IsKeyDown(lastKey))
- {
- if (kb_elapsedms == 0 || kb_elapsedms >= 500)
+ //Let's see how keyboard input works.
+
+ //Hmmm... just like the mouse...
+ var keystate = Keyboard.GetState();
+
+ //Simple... just iterate through this list and generate some key events?
+ var keys = keystate.GetPressedKeys();
+ if (keys.Length > 0)
{
- if (lastKey == Keys.F11)
+ var key = keys.FirstOrDefault(x => x != Keys.LeftControl && x != Keys.RightControl && x != Keys.LeftShift && x != Keys.RightShift && x != Keys.LeftAlt && x != Keys.RightAlt);
+ if (lastKey != key)
{
- UIManager.Fullscreen = !UIManager.Fullscreen;
+ kb_elapsedms = 0;
+ lastKey = key;
}
- else
+ }
+ if (keystate.IsKeyDown(lastKey))
+ {
+ if (kb_elapsedms == 0 || kb_elapsedms >= 500)
{
- var shift = keystate.IsKeyDown(Keys.LeftShift) || keystate.IsKeyDown(Keys.RightShift);
- var alt = keystate.IsKeyDown(Keys.LeftAlt) || keystate.IsKeyDown(Keys.RightAlt);
- var control = keystate.IsKeyDown(Keys.LeftControl) || keystate.IsKeyDown(Keys.RightControl);
-
- if (control && lastKey == Keys.D)
+ if (lastKey == Keys.F11)
{
- DisplayDebugInfo = !DisplayDebugInfo;
+ UIManager.Fullscreen = !UIManager.Fullscreen;
}
- else if(control && lastKey == Keys.E)
- {
- UIManager.ExperimentalEffects = !UIManager.ExperimentalEffects;
- }
else
{
- var e = new KeyEvent(control, alt, shift, lastKey);
- UIManager.ProcessKeyEvent(e);
+ var shift = keystate.IsKeyDown(Keys.LeftShift) || keystate.IsKeyDown(Keys.RightShift);
+ var alt = keystate.IsKeyDown(Keys.LeftAlt) || keystate.IsKeyDown(Keys.RightAlt);
+ var control = keystate.IsKeyDown(Keys.LeftControl) || keystate.IsKeyDown(Keys.RightControl);
+
+ if (control && lastKey == Keys.D)
+ {
+ DisplayDebugInfo = !DisplayDebugInfo;
+ }
+ else if (control && lastKey == Keys.E)
+ {
+ UIManager.ExperimentalEffects = !UIManager.ExperimentalEffects;
+ }
+ else
+ {
+ var e = new KeyEvent(control, alt, shift, lastKey);
+ UIManager.ProcessKeyEvent(e);
+ }
}
}
- }
- kb_elapsedms += gameTime.ElapsedGameTime.TotalMilliseconds;
- }
- else
- {
- kb_elapsedms = 0;
- }
+ kb_elapsedms += gameTime.ElapsedGameTime.TotalMilliseconds;
+ }
+ else
+ {
+ kb_elapsedms = 0;
+ }
- //Cause layout update on all elements
- UIManager.LayoutUpdate(gameTime);
+ //Cause layout update on all elements
+ UIManager.LayoutUpdate(gameTime);
- timeSinceLastPurge += gameTime.ElapsedGameTime.TotalSeconds;
+ timeSinceLastPurge += gameTime.ElapsedGameTime.TotalSeconds;
- if(timeSinceLastPurge > 2)
- {
- GraphicsContext.StringCaches.Clear();
- timeSinceLastPurge = 0;
- GC.Collect();
- }
+ if (timeSinceLastPurge > 2)
+ {
+ GraphicsContext.StringCaches.Clear();
+ timeSinceLastPurge = 0;
+ GC.Collect();
+ }
- //Some hackables have a connection timeout applied to them.
- //We must update timeout values here, and disconnect if the timeout
- //hits zero.
+ //Some hackables have a connection timeout applied to them.
+ //We must update timeout values here, and disconnect if the timeout
+ //hits zero.
- if(Hacking.CurrentHackable != null)
- {
- if (Hacking.CurrentHackable.DoConnectionTimeout)
+ if (Hacking.CurrentHackable != null)
{
- Hacking.CurrentHackable.MillisecondsCountdown -= gameTime.ElapsedGameTime.TotalMilliseconds;
- shroudOpacity = (float)GUI.ProgressBar.linear(Hacking.CurrentHackable.MillisecondsCountdown, Hacking.CurrentHackable.TotalConnectionTimeMS, 0, 0, 1);
- if (Hacking.CurrentHackable.MillisecondsCountdown <= 0)
+ if (Hacking.CurrentHackable.DoConnectionTimeout)
{
- Hacking.FailHack();
+ Hacking.CurrentHackable.MillisecondsCountdown -= gameTime.ElapsedGameTime.TotalMilliseconds;
+ shroudOpacity = (float)GUI.ProgressBar.linear(Hacking.CurrentHackable.MillisecondsCountdown, Hacking.CurrentHackable.TotalConnectionTimeMS, 0, 0, 1);
+ if (Hacking.CurrentHackable.MillisecondsCountdown <= 0)
+ {
+ Hacking.FailHack();
+ }
}
}
+ else
+ {
+ shroudOpacity = 0;
+ }
}
- else
- {
- shroudOpacity = 0;
- }
+
base.Update(gameTime);
}
@@ -301,6 +367,21 @@ namespace ShiftOS.Frontend
spriteBatch.Draw(UIManager.SkinTextures["PureWhite"], new Rectangle(0, 0, UIManager.Viewport.Width, UIManager.Viewport.Height), Color.Red * shroudOpacity);
+ if(isFailing && failFadeInMS >= failFadeMaxMS)
+ {
+ var gfx = new GraphicsContext(graphicsDevice.GraphicsDevice, spriteBatch, 0,0, UIManager.Viewport.Width, UIManager.Viewport.Height);
+ string objectiveFailed = "- OBJECTIVE FAILURE -";
+ string prompt = "[press any key to dismiss this message and return to your sentience]";
+ int textMaxWidth = UIManager.Viewport.Width / 3;
+ var topMeasure = gfx.MeasureString(objectiveFailed, SkinEngine.LoadedSkin.HeaderFont, textMaxWidth);
+ var msgMeasure = gfx.MeasureString(failMessage, SkinEngine.LoadedSkin.Header3Font, textMaxWidth);
+ var pMeasure = gfx.MeasureString(prompt, SkinEngine.LoadedSkin.MainFont, textMaxWidth);
+
+ gfx.DrawString(objectiveFailed, (UIManager.Viewport.Width - (int)topMeasure.X) / 2, UIManager.Viewport.Height / 3, Color.White, SkinEngine.LoadedSkin.HeaderFont, textMaxWidth);
+ gfx.DrawString(failMessage, (UIManager.Viewport.Width - (int)msgMeasure.X) / 2, (UIManager.Viewport.Height - (int)msgMeasure.Y) / 2, Color.White, SkinEngine.LoadedSkin.Header3Font, textMaxWidth);
+ gfx.DrawString(prompt, (UIManager.Viewport.Width - (int)pMeasure.X) / 2, UIManager.Viewport.Height - (UIManager.Viewport.Height / 3), Color.White, SkinEngine.LoadedSkin.MainFont, textMaxWidth);
+ }
+
if(Hacking.CurrentHackable != null)
{
if (Hacking.CurrentHackable.DoConnectionTimeout)
diff --git a/ShiftOS.Frontend/Stories/BeginTutorials.cs b/ShiftOS.Frontend/Stories/BeginTutorials.cs
index f5e1905..a023178 100644
--- a/ShiftOS.Frontend/Stories/BeginTutorials.cs
+++ b/ShiftOS.Frontend/Stories/BeginTutorials.cs
@@ -257,5 +257,57 @@ namespace ShiftOS.Frontend.Stories
});
});
}
+
+ [RequiresUpgrade("tutorial_hacking_basics")]
+ [Mission("the_syndicate", "The Syndicate", "You just exploited a server owned by a group known as ShiftSyndicate. They found out, and they see you as a worthy recruit.", 250, "thejackel")]
+ public static void TheSyndicateEntry()
+ {
+ Story.Context.AutoComplete = false;
+ var irc = AppearanceManager.OpenForms.FirstOrDefault(x => x.ParentWindow is Apps.ChatClient) as Apps.ChatClient;
+ if (irc == null)
+ {
+ irc = new Apps.ChatClient();
+ AppearanceManager.SetupWindow(irc);
+ }
+
+ irc.FakeConnection(new Objects.IRCNetwork
+ {
+ SystemName = "shiftsyndicate_irc",
+ FriendlyName = "ShiftSyndicate IRC Network",
+ MOTD = "Welcome to ShiftSyndicate IRC. This network is dedicated to finding out what this Digital Society is and how to break out. Unauthorized users WILL be z-lined.",
+ Channel = new Objects.IRCChannel
+ {
+ Tag = "recruitment",
+ Topic = "Artificial intelligence do everything now. Nobody is really here.",
+ OnlineUsers = new List<Objects.IRCUser>
+ {
+ new Objects.IRCUser
+ {
+ Nickname = "thejackel",
+ Permission = Objects.IRCPermission.NetOp
+ },
+ new Objects.IRCUser
+ {
+ Nickname = SaveSystem.CurrentSave.Username,
+ Permission = Objects.IRCPermission.User
+ }
+ }
+ }
+ });
+ while (!irc.ChannelConnected)
+ Thread.Sleep(10);
+ SendClientMessage(irc, "thejackel", $"Hello there, {SaveSystem.CurrentSave.Username}. Welcome to our network.");
+ SendClientMessage(irc, "thejackel", $"I see you breached our File Transfer Protocol server.");
+ SendClientMessage(irc, "thejackel", $"You may not realize exactly who we are...");
+ SendClientMessage(irc, "thejackel", $"We know about you, and we know what you want.");
+ SendClientMessage(irc, "thejackel", $"");
+
+ }
+
+ public static void SendClientMessage(Apps.ChatClient client, string nick, string message)
+ {
+ Thread.Sleep(message.Length * 25);
+ client.SendClientMessage(nick, message);
+ }
}
}
diff --git a/ShiftOS.Objects/IRCNetwork.cs b/ShiftOS.Objects/IRCNetwork.cs
new file mode 100644
index 0000000..cbf8688
--- /dev/null
+++ b/ShiftOS.Objects/IRCNetwork.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS.Objects
+{
+ public class IRCNetwork
+ {
+ public string SystemName { get; set; }
+ public string FriendlyName { get; set; }
+ public string MOTD { get; set; }
+ public IRCChannel Channel { get; set; }
+ }
+
+ public class IRCChannel
+ {
+ public string Tag { get; set; }
+ public string Topic { get; set; }
+ public List<IRCUser> OnlineUsers { get; set; }
+
+ }
+
+ public class IRCUser
+ {
+ public string Nickname { get; set; }
+ public IRCPermission Permission { get; set; }
+ }
+
+ public enum IRCPermission
+ {
+ User,
+ ChanOp,
+ NetOp,
+ }
+}
diff --git a/ShiftOS.Objects/ShiftOS.Objects.csproj b/ShiftOS.Objects/ShiftOS.Objects.csproj
index 65324fb..8117cd9 100644
--- a/ShiftOS.Objects/ShiftOS.Objects.csproj
+++ b/ShiftOS.Objects/ShiftOS.Objects.csproj
@@ -52,6 +52,7 @@
<Compile Include="Hacking\Payload.cs" />
<Compile Include="Hacking\Exploit.cs" />
<Compile Include="Hacking\Hackable.cs" />
+ <Compile Include="IRCNetwork.cs" />
<Compile Include="MudAttributes.cs" />
<Compile Include="Objects.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/ShiftOS_TheReturn/Story.cs b/ShiftOS_TheReturn/Story.cs
index c62d3bd..674b782 100644
--- a/ShiftOS_TheReturn/Story.cs
+++ b/ShiftOS_TheReturn/Story.cs
@@ -95,6 +95,14 @@ namespace ShiftOS.Engine
public static StoryContext Context { get; private set; }
public static event Action<string> StoryComplete;
public static List<Objective> CurrentObjectives { get; private set; }
+ public static event Action<string> FailureRequested;
+
+ public static void DisplayFailure(string message)
+ {
+ FailureRequested?.Invoke(message);
+ }
+
+
public static void PushObjective(string name, string desc, Func<bool> completeFunc, Action onComplete)
{