summaryrefslogtreecommitdiff
path: root/DSACore
diff options
context:
space:
mode:
authorTrueDoctor <d-kobert@web.de>2018-09-26 20:51:37 +0200
committerTrueDoctor <d-kobert@web.de>2018-09-26 20:51:37 +0200
commitb411aa2128c2724bec0ecedb8cb4e1ffa59f3b53 (patch)
tree14e0a0cca2cf66b95fda402c8c7d7b6bd5b7b222 /DSACore
parent92e8bb7523c775014ccf68355e3f0178ebf4a61c (diff)
disconnected most vital calles from the Discord Bot
Diffstat (limited to 'DSACore')
-rw-r--r--DSACore/Audio/Sound.cs18
-rw-r--r--DSACore/Auxiliary/Calculator/Argument.cs38
-rw-r--r--DSACore/Auxiliary/Calculator/ISolvable.cs10
-rw-r--r--DSACore/Auxiliary/Calculator/Operator.cs51
-rw-r--r--DSACore/Auxiliary/Calculator/Ops.cs13
-rw-r--r--DSACore/Auxiliary/Calculator/StringSolver.cs207
-rw-r--r--DSACore/Auxiliary/CommandInfo.cs32
-rw-r--r--DSACore/Auxiliary/Dice.cs48
-rw-r--r--DSACore/Auxiliary/Extensions.cs33
-rw-r--r--DSACore/Auxiliary/RandomMisc.cs52
-rw-r--r--DSACore/Auxiliary/SpellCorrect.cs147
-rw-r--r--DSACore/Auxiliary/TalentEnumerableExtension.cs84
-rw-r--r--DSACore/DSACore.csproj5
-rw-r--r--DSACore/DSA_Game/Characters/Character.cs286
-rw-r--r--DSACore/DSA_Game/Characters/NPC.cs114
-rw-r--r--DSACore/DSA_Game/Characters/SaveChar.cs44
-rw-r--r--DSACore/DSA_Game/Dsa.cs61
-rw-r--r--DSACore/DSA_Game/Save/Properties.cs77
-rw-r--r--DSACore/DSA_Game/Save/SaveCommand.cs70
-rw-r--r--DSACore/DSA_Game/Save/Session.cs47
20 files changed, 1437 insertions, 0 deletions
diff --git a/DSACore/Audio/Sound.cs b/DSACore/Audio/Sound.cs
new file mode 100644
index 0000000..d259850
--- /dev/null
+++ b/DSACore/Audio/Sound.cs
@@ -0,0 +1,18 @@
+namespace DSACore.Audio
+{
+ public class Sound
+ {
+ public Sound(string name, string url, int volume)
+ {
+ this.Name = name;
+ this.Url = url;
+ this.Volume = volume;
+ }
+
+ public string Name { get; }
+
+ public string Url { get; }
+
+ public int Volume { get; }
+ }
+}
diff --git a/DSACore/Auxiliary/Calculator/Argument.cs b/DSACore/Auxiliary/Calculator/Argument.cs
new file mode 100644
index 0000000..2379bfe
--- /dev/null
+++ b/DSACore/Auxiliary/Calculator/Argument.cs
@@ -0,0 +1,38 @@
+namespace DiscoBot.Auxiliary.Calculator
+{
+ using System;
+
+ /// <summary>
+ /// Provides an ISolvable class to save numbers. The class handles Argument checking and conversion from string to int.
+ /// </summary>
+ public class Argument : ISolvable
+ {
+ private readonly int value;
+
+ public Argument(string value)
+ {
+ // check whether the value given is an empty string
+ if (string.IsNullOrEmpty(value))
+ {
+ throw new ArgumentException("Argument kann nicht mit einem leeren string instanziert werden. ", nameof(value));
+ }
+
+ if (!int.TryParse(value, out int result))
+ {
+ throw new ArgumentException($"Kann {value} nicht in Integer konvertieren");
+ }
+
+ this.value = result;
+ }
+
+ public int Solve()
+ {
+ return this.value;
+ }
+
+ public override string ToString()
+ {
+ return this.value.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/DSACore/Auxiliary/Calculator/ISolvable.cs b/DSACore/Auxiliary/Calculator/ISolvable.cs
new file mode 100644
index 0000000..a869bdb
--- /dev/null
+++ b/DSACore/Auxiliary/Calculator/ISolvable.cs
@@ -0,0 +1,10 @@
+namespace DiscoBot.Auxiliary.Calculator
+{
+ /// <summary>
+ /// Object has to be able to return an integer as it's value
+ /// </summary>
+ public interface ISolvable
+ {
+ int Solve();
+ }
+}
diff --git a/DSACore/Auxiliary/Calculator/Operator.cs b/DSACore/Auxiliary/Calculator/Operator.cs
new file mode 100644
index 0000000..703f060
--- /dev/null
+++ b/DSACore/Auxiliary/Calculator/Operator.cs
@@ -0,0 +1,51 @@
+using System;
+using DSACore.Auxiliary;
+
+namespace DiscoBot.Auxiliary.Calculator
+{
+ /// <summary>
+ /// The Operator Class represents a binary operator with tow Arguments and an Operation type
+ /// </summary>
+ public class Operator : ISolvable
+ {
+ private readonly ISolvable arg1, arg2;
+
+ public Operator(ISolvable arg1, ISolvable arg2, Ops operatorType)
+ {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.OperatorType = operatorType;
+ }
+
+ public Ops OperatorType { get; set; }
+
+ public int Solve()
+ {
+ int result;
+ switch (this.OperatorType)
+ {
+ case Ops.Dice:
+ result = Dice.Roll(this.arg1.Solve(), this.arg2.Solve());
+ break;
+ case Ops.Multiply:
+ result = this.arg1.Solve() * this.arg2.Solve();
+ break;
+ case Ops.Add:
+ result = this.arg1.Solve() + this.arg2.Solve();
+ break;
+ case Ops.Subtract:
+ result = this.arg1.Solve() - this.arg2.Solve();
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return $"({this.arg1} {this.OperatorType} {this.arg2})";
+ }
+ }
+}
diff --git a/DSACore/Auxiliary/Calculator/Ops.cs b/DSACore/Auxiliary/Calculator/Ops.cs
new file mode 100644
index 0000000..62c1309
--- /dev/null
+++ b/DSACore/Auxiliary/Calculator/Ops.cs
@@ -0,0 +1,13 @@
+namespace DiscoBot.Auxiliary.Calculator
+{
+ /// <summary>
+ /// The Different Operations, witch can be performed in execution-order
+ /// </summary>
+ public enum Ops
+ {
+ Dice,
+ Multiply,
+ Subtract,
+ Add
+ }
+}
diff --git a/DSACore/Auxiliary/Calculator/StringSolver.cs b/DSACore/Auxiliary/Calculator/StringSolver.cs
new file mode 100644
index 0000000..30c2134
--- /dev/null
+++ b/DSACore/Auxiliary/Calculator/StringSolver.cs
@@ -0,0 +1,207 @@
+namespace DiscoBot.Auxiliary.Calculator
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ /// <summary>
+ /// The StringSolver divides the calculation string into operations and SubStringSolvers if the string contains parentheses
+ /// </summary>
+ public class StringSolver : ISolvable
+ {
+ private readonly string input;
+ private readonly List<object> arguments = new List<object>();
+
+ public StringSolver(string input)
+ {
+ this.input = input;
+ }
+
+ public override string ToString()
+ {
+ return "(0+" + this.input.Replace(" ", string.Empty).ToLower() + ")";
+ }
+
+ public int Solve()
+ {
+ string workInput = "0+" + this.input.Replace(" ", string.Empty).ToLower();
+ workInput = ExpandParentheses(workInput);
+
+ // Create a List of the different parts of the calculation, e.g.:{"0", "+", "(5+6)", "d", "3"}.
+ this.AtomizeOperations(workInput);
+
+ // traverse the List in order of Operation to Create the binary operation tree .
+ this.NestOperations();
+
+ // the List now contains only the top operation node, witch can be solved recursively,
+ return ((ISolvable)this.arguments.First()).Solve();
+ }
+
+ private static string GetInner(ref string input) // extract the inner bracket an remove the section from the input string
+ {
+ int depth = 0;
+ for (var index = 1; index < input.Length; index++)
+ {
+ char c = input[index];
+ switch (c)
+ {
+ case '(':
+ depth++;
+ break;
+ case ')':
+ if (depth == 0)
+ {
+ var split = input.Substring(1, index - 1);
+ input = input.Substring(index + 1);
+ return split.Equals(string.Empty) ? "0" : split;
+ }
+ else
+ {
+ depth--;
+ }
+
+ break;
+ }
+ }
+
+ return string.Empty;
+ }
+
+ private static Ops GetOps(char c)
+ {
+ switch (c)
+ {
+ case 'd':
+ case 'w':
+ return Ops.Dice;
+ case '+':
+ return Ops.Add;
+ case '-':
+ return Ops.Subtract;
+ case '*':
+ return Ops.Multiply;
+ default:
+ return Ops.Multiply;
+ }
+ }
+
+ private static string ExpandParentheses(string input) // insert * between Parentheses and digits
+ {
+ for (int i = 0; i < input.Length - 1; i++)
+ {
+ if (input[i + 1] == '(' && char.IsNumber(input[i]))
+ {
+ input = input.Insert(i + 1, "*");
+ }
+ }
+
+ for (int i = 1; i < input.Length; i++)
+ {
+ if (input[i - 1] == ')' && char.IsNumber(input[i]))
+ {
+ input = input.Insert(i, "*");
+ }
+ }
+
+ return input;
+ }
+
+ private void AtomizeOperations(string workInput)
+ {
+ for (var index = 0; index < workInput.Length; index++)
+ {
+ char c = workInput[index];
+
+ if (char.IsNumber(c))
+ {
+ // if char number, check if at end of string, else continue looping
+ if (index == workInput.Length - 1)
+ {
+ // if at end of string; add remaining number to arguments
+ this.arguments.Add(new Argument(workInput.Substring(0, index + 1)));
+ }
+
+ continue;
+ }
+
+ switch (c)
+ {
+ case ')':
+ throw new ArgumentException($"Unmögliche Anordnung von Klammern");
+ case '(':
+ this.arguments.Add(new StringSolver(GetInner(ref workInput)));
+ index = -1;
+ break;
+ default:
+ if (index > 0)
+ {
+ this.arguments.Add(new Argument(workInput.Substring(0, index)));
+ }
+
+ this.arguments.Add(GetOps(c));
+ workInput = workInput.Remove(0, index + 1);
+ index = -1;
+ break;
+ }
+ }
+ }
+
+ private void NestOperations()
+ {
+ foreach (Ops currentOp in Enum.GetValues(typeof(Ops)))
+ {
+ // cycle through operators in operational order
+ for (var index = 0; index < this.arguments.Count; index++)
+ {
+ var arg = this.arguments[index];
+
+ if (arg.GetType() != typeof(Ops))
+ {
+ continue;
+ }
+
+ // arg is of type Ops
+ var op = (Ops)arg;
+
+ if (op != currentOp)
+ {
+ continue;
+ }
+
+ // arg describes the current operation
+ this.HandleSpecialFormatting(ref index, op); // Deal with special needs...
+
+ // replace the previous current and next Element in the List with one Operation object
+ var temp = new Operator((ISolvable)this.arguments[index - 1], (ISolvable)this.arguments[index + 1], op);
+ this.arguments[index - 1] = temp;
+ this.arguments.RemoveRange(index, 2);
+ index--;
+ }
+ }
+ }
+
+ private void HandleSpecialFormatting(ref int index, Ops op)
+ {
+ var arg1 = this.arguments[index - 1];
+ if (arg1.GetType() == typeof(Ops))
+ {
+ if (op == Ops.Dice)
+ {
+ this.arguments.Insert(index++, new Argument("1")); // w6 -> 1w6
+ }
+
+ if (op == Ops.Subtract)
+ {
+ this.arguments.Insert(index++, new Argument("0")); // +-3 -> +0-3
+ }
+ }
+
+ var arg2 = this.arguments[index + 1]; // 3+-5 -> 3+(0-5)
+ if (arg2.GetType() == typeof(Ops))
+ {
+ this.arguments[index + 1] = new Operator(new Argument("0"), (ISolvable)this.arguments[index + 2], (Ops)arg2);
+ this.arguments.RemoveAt(index + 2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/DSACore/Auxiliary/CommandInfo.cs b/DSACore/Auxiliary/CommandInfo.cs
new file mode 100644
index 0000000..a83e30a
--- /dev/null
+++ b/DSACore/Auxiliary/CommandInfo.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DSACore.Auxiliary
+{
+ public struct CommandInfo
+ {
+ public CommandInfo(string name, string brief, string[] description, string scope)
+ {
+ this.Name = name;
+ this.Scope = scope;
+ this.Brief = brief;
+ this.Description = description;
+ }
+
+ public string Name { get; }
+
+ public string Scope { get; }
+
+ public string Brief { get; }
+
+ public string[] Description { get; }
+
+ public string GetDescription()
+ {
+ return this.Description.Aggregate((s, c) => s + c);
+ }
+ }
+}
diff --git a/DSACore/Auxiliary/Dice.cs b/DSACore/Auxiliary/Dice.cs
new file mode 100644
index 0000000..2df8aa7
--- /dev/null
+++ b/DSACore/Auxiliary/Dice.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Linq;
+
+namespace DSACore.Auxiliary
+{
+ public static class Dice // roll it!
+ {
+ private static readonly System.Random Rnd = new System.Random();
+
+ public static int Roll(int d = 20)
+ {
+ return Rnd.Next(d) + 1;
+ }
+
+ public static int Roll(string input)
+ {
+ var strings = input.ToLower().Split(new[] { 'w', 'd' }, 2, StringSplitOptions.RemoveEmptyEntries).ToList();
+ int count = Convert.ToInt32(strings[0]);
+ int d = Convert.ToInt32(strings[0]);
+
+ if (strings.Count != 2)
+ {
+ throw new ArgumentException($"{input}: erfüllt nicht die Formatvogaben( Anzahl d Augenzahl)");
+ }
+
+ return Roll(count, d);
+ }
+
+ public static int Roll(int count, int d)
+ {
+ if (d <= 0)
+ {
+ return 0;
+ }
+
+ int sum = 0;
+ for (int i = 0; i < Math.Abs(count); i++)
+ {
+ var roll = Dice.Roll(d);
+ sum += roll;
+ }
+
+ sum *= Math.Abs(count) / count;
+
+ return sum;
+ }
+ }
+}
diff --git a/DSACore/Auxiliary/Extensions.cs b/DSACore/Auxiliary/Extensions.cs
new file mode 100644
index 0000000..8ef6298
--- /dev/null
+++ b/DSACore/Auxiliary/Extensions.cs
@@ -0,0 +1,33 @@
+namespace DSACore.Auxiliary
+{
+ public static class StringExtension
+ {
+ //This mehod extends string. It adds spaces until a fixed length is reached.
+ //If the original string is already longer, it is returner unmodified.
+ public static string AddSpaces(this string str, int length)
+ {
+ string temp = str;
+ for(int i = str.Length; i < length; i++)
+ {
+ temp += " ";
+ }
+ return temp;
+ }
+
+
+
+ //This mehod extends string.
+ //It adds spaces at the HEAD of a string until a fixed length is reached.
+ //If the original string is already longer, it is returner unmodified.
+ public static string AddSpacesAtHead(this string str, int length)
+ {
+ string temp = "";
+ for (int i = str.Length; i < length; i++)
+ {
+ temp += " ";
+ }
+ return temp + str;
+ }
+ }
+
+}
diff --git a/DSACore/Auxiliary/RandomMisc.cs b/DSACore/Auxiliary/RandomMisc.cs
new file mode 100644
index 0000000..1295f02
--- /dev/null
+++ b/DSACore/Auxiliary/RandomMisc.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Linq;
+using System.Text;
+
+namespace DSACore.Auxiliary
+{
+ public static class RandomMisc
+ {
+ private static readonly Random Rand = new Random();
+
+ // use: 4w6 +4
+ public static string Roll(string input)
+ {
+ var output = new StringBuilder();
+ var strings = input.Split('w', 'd').ToList();
+ int count = Convert.ToInt32(strings[0]);
+ strings = strings[1].Split(' ').ToList();
+ int d = Convert.ToInt32(strings[0]);
+
+ if (strings.Count > 0)
+ {
+ }
+
+ int sum = 0;
+ for (int i = 0; i < count; i++)
+ {
+ var roll = Dice.Roll(d);
+ sum += roll;
+ output.Append("[" + roll + "] ");
+ }
+
+ if (strings.Count > 1)
+ {
+ sum += Convert.ToInt32(strings[1]);
+ output.Append("sum: " + sum);
+ }
+
+ return output.ToString();
+ }
+
+ public static double Random(double stdDev = 1, double mean = 0)
+ {
+ double u1 = Rand.NextDouble(); // uniform(0,1) random doubles
+ double u2 = Rand.NextDouble();
+ double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
+ Math.Sin(2.0 * Math.PI * u2); // random normal(0,1)
+ double randNormal =
+ mean + stdDev * randStdNormal; // random normal(mean,stdDev^2)
+ return randNormal;
+ }
+ }
+}
diff --git a/DSACore/Auxiliary/SpellCorrect.cs b/DSACore/Auxiliary/SpellCorrect.cs
new file mode 100644
index 0000000..c9603f6
--- /dev/null
+++ b/DSACore/Auxiliary/SpellCorrect.cs
@@ -0,0 +1,147 @@
+namespace DSACore.Auxiliary
+{
+ using System;
+ using System.Diagnostics;
+ using System.Linq;
+
+ public class SpellCorrect : StringComparer
+ {
+ public const int ErrorThreshold = 94100;
+
+ public override int Compare(string x, string y)
+ {
+ return CompareEasy(x, y);
+ }
+
+ public static int CompareEasy(string x, string y)
+ {
+ if (string.IsNullOrEmpty(x))
+ {
+ throw new ArgumentException("message", nameof(x));
+ }
+
+ if (string.IsNullOrEmpty(y))
+ {
+ throw new ArgumentException("message", nameof(y));
+ }
+
+ if (x.Equals(y))
+ {
+ return 0;
+ }
+
+ x = x.ToLower();
+ y = y.ToLower();
+ if (x.Equals(y))
+ {
+ return 1;
+ }
+
+ var subs = y.Split(' ', '/');
+ int score = subs.Count();
+ foreach (string s in subs)
+ {
+ if (s.Equals(x))
+ {
+ score--;
+ }
+ }
+
+ if (score < subs.Count())
+ {
+ return score + 1;
+ }
+
+ return 100000 - (int)(CompareExact(x, y) * 1000.0);
+ /*if (y.Contains(x))
+ return 6;*/
+ }
+
+ public override bool Equals(string x, string y)
+ {
+ Debug.Assert(x != null, nameof(x) + " != null");
+ return x.Equals(y);
+ }
+
+ public override int GetHashCode(string obj)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static double CompareExact(string s, string q)
+ {
+
+ s = s.ToLower();
+ q = q.ToLower();
+
+ int i, j;
+ const double Match = 3.0;
+ const double Gap = -2.0;
+ const double Mismatch = -2.0;
+
+ double decay;
+
+ double[,] matrix = new double[s.Length + 1, q.Length + 1];
+ double max = 0.0;
+ matrix[0, 0] = 0.0;
+
+ for (i = 1; i < s.Length; i++)
+ {
+ // matrix[i, 0] = 0.0;
+ matrix[i, 0] = i * Gap;
+ }
+
+ for (i = 1; i < q.Length; i++)
+ {
+ matrix[0, i] = 0.0;
+ }
+
+
+ for (i = 1; i <= s.Length; i++)
+ {
+ for (j = 1; j <= q.Length; j++)
+ {
+ decay = j / (double)(s.Length * 1000);
+ double add = s[i - 1] == q[j - 1] ? (Match - decay) : Mismatch;
+ double score = matrix[i - 1, j - 1] + add;
+
+ if (score < (matrix[i - 1, j] + Gap))
+ {
+ score = matrix[i - 1, j] + Gap;
+ }
+
+ if (score < (matrix[i, j - 1] + Gap))
+ {
+ score = matrix[i, j - 1] + Gap;
+ }
+
+ if (i > 1 && j > 1)
+ {
+ if (s[i - 1] == q[j - 2] && s[i - 2] == q[j - 1])
+ {
+ add = (3 / 2.0) * Match - decay;
+ if (score < matrix[i - 2, j - 2] + add)
+ {
+ score = matrix[i - 2, j - 2] + add;
+ }
+ }
+ }
+
+ // if (score < 0)
+ // {
+ // score = 0;
+ // }
+
+ if (max < score && i == s.Length)
+ {
+ max = score;
+ }
+
+ matrix[i, j] = score;
+ }
+ }
+
+ return max;
+ }
+ }
+}
diff --git a/DSACore/Auxiliary/TalentEnumerableExtension.cs b/DSACore/Auxiliary/TalentEnumerableExtension.cs
new file mode 100644
index 0000000..d8af015
--- /dev/null
+++ b/DSACore/Auxiliary/TalentEnumerableExtension.cs
@@ -0,0 +1,84 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using DiscoBot.DSA_Game.Characters;
+using DSALib;
+
+namespace DSACore.Auxiliary
+{
+ public static class TalentEnumerableExtension
+ {
+ public static string ProbenTest(this IEnumerable<Talent> List, Character c, string talent, int erschwernis = 0)
+ {
+ var output = new StringBuilder();
+ var sc = new SpellCorrect();
+ var tTalent = List.OrderBy(x => sc.Compare(talent, x.Name)).First();
+
+ if (sc.Compare(talent, tTalent.Name) > SpellCorrect.ErrorThreshold)
+ {
+ return $"{c.Name} kann nicht {talent}...";
+ }
+
+ var props = tTalent.GetEigenschaften(); // get the required properties
+ int tap = tTalent.Value; // get taw
+ var werte = props.Select(p => c.Eigenschaften[c.PropTable[p]]).ToList();
+
+ output.AppendFormat(
+ "{0} würfelt: {1} \n{2} - {3} taw:{4} {5} \n",
+ c.Name,
+ tTalent.Name,
+ tTalent.Probe,
+ string.Join("/", werte),
+ tTalent.Value,
+ erschwernis.Equals(0) ? string.Empty : "Erschwernis: " + erschwernis);
+
+ output.Append(" ");
+ tap -= erschwernis;
+ int gesamtErschwernis = tap;
+ if (gesamtErschwernis < 0)
+ {
+ tap = 0;
+ for (int i = 0; i <= 2; i++)
+ {
+ // foreach property, dice and tap
+ int temp = Dice.Roll();
+ int eigenschaft = c.Eigenschaften[c.PropTable[props[i]]];
+
+ if (eigenschaft + gesamtErschwernis < temp)
+ {
+ tap -= temp - (eigenschaft + gesamtErschwernis);
+ }
+
+ output.Append($"[{temp}]"); // add to string
+ }
+
+ if (tap >= 0)
+ {
+ tap = 1;
+ }
+ }
+ else
+ {
+ for (int i = 0; i <= 2; i++)
+ {
+ // foreach property, dice and tap
+ int temp = Dice.Roll();
+ int eigenschaft = c.Eigenschaften[c.PropTable[props[i]]];
+
+ if (eigenschaft < temp)
+ {
+ tap -= temp - eigenschaft;
+ }
+
+ output.Append($"[{temp}]"); // add to string
+ }
+ }
+
+ tap = (tap == 0) ? 1 : tap;
+
+ output.AppendFormat(" tap: {0,2}", tap);
+
+ return output.ToString(); // return output
+ }
+ }
+}
diff --git a/DSACore/DSACore.csproj b/DSACore/DSACore.csproj
index 1661770..44c4f8c 100644
--- a/DSACore/DSACore.csproj
+++ b/DSACore/DSACore.csproj
@@ -6,10 +6,15 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
+ <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\DSALib\DSALib.csproj" />
+ </ItemGroup>
+
</Project>
diff --git a/DSACore/DSA_Game/Characters/Character.cs b/DSACore/DSA_Game/Characters/Character.cs
new file mode 100644
index 0000000..1236b12
--- /dev/null
+++ b/DSACore/DSA_Game/Characters/Character.cs
@@ -0,0 +1,286 @@
+using DSACore.Auxiliary;
+using DSALib;
+using DSALib.Characters;
+
+namespace DiscoBot.DSA_Game.Characters
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Xml;
+
+
+ public class Character : Being, ICharacter
+ {
+ public Character()
+ {
+ this.PropTable.Add("MU", "Mut"); // routing
+ this.PropTable.Add("KL", "Klugheit");
+ this.PropTable.Add("IN", "Intuition");
+ this.PropTable.Add("CH", "Charisma");
+ this.PropTable.Add("FF", "Fingerfertigkeit");
+ this.PropTable.Add("GE", "Gewandtheit");
+ this.PropTable.Add("KO", "Konstitution");
+ this.PropTable.Add("KK", "Körperkraft");
+
+ }
+
+ public Character(string path) : this()
+ {
+ this.Load(path); // load
+ this.Post_process(); // calculate derived values
+ }
+
+ public Character(Character c, string name, int stDv = 2) : this()
+ {
+ this.Name = name;
+ foreach (var i in c.Eigenschaften)
+ {
+ this.Eigenschaften.Add(i.Key, i.Value + (int)Math.Round(RandomMisc.Random(stDv)));
+ }
+
+ foreach (var i in c.Vorteile)
+ {
+ this.Vorteile.Add(new Vorteil(i.Name, i.Value + (int)Math.Round(RandomMisc.Random(stDv))));
+ }
+
+ foreach (var i in c.Talente)
+ {
+ this.Talente.Add(new Talent(i.Name, i.Probe, i.Value + (int)Math.Round(RandomMisc.Random(stDv))));
+ }
+
+ foreach (var i in c.Zauber)
+ {
+ this.Zauber.Add(new Zauber(i.Name, i.Probe, i.Value + (int)Math.Round(RandomMisc.Random(stDv)), i.Complexity, i.Representation));
+ }
+
+ foreach (var i in c.Kampftalente)
+ {
+ this.Kampftalente.Add(new KampfTalent(i.Name, i.At + (int)Math.Round(RandomMisc.Random(stDv)), i.Pa + (int)Math.Round(RandomMisc.Random(stDv))));
+ }
+
+ this.Post_process(); // calculate derived values
+ }
+
+ public Dictionary<string, int> Eigenschaften { get; set; } = new Dictionary<string, int>(); // char properties
+
+ public List<Talent> Talente { get; set; } = new List<Talent>(); // list of talent objects (talents)
+
+ public List<Zauber> Zauber { get; set; } = new List<Zauber>(); // list of spell objects
+
+ public List<KampfTalent> Kampftalente { get; set; } = new List<KampfTalent>(); // list of combat objects
+
+ public List<Vorteil> Vorteile { get; set; } = new List<Vorteil>();
+
+ public Dictionary<string, string> PropTable { get; set; } = new Dictionary<string, string>(); // -> Körperkraft
+
+ public string TestTalent(string talent, int erschwernis = 0) // Talentprobe
+ {
+ return this.Talente.ProbenTest(this, talent, erschwernis);
+ }
+
+ public string TestZauber(string zauber, int erschwernis = 0) // Talentprobe
+ {
+ return this.Zauber.ProbenTest(this, zauber, erschwernis);
+ }
+
+ public string TestEigenschaft(string eigenschaft, int erschwernis = 0)
+ {
+ var output = new StringBuilder();
+ var prop = this.PropTable[eigenschaft.ToUpper()];
+ int tap = this.Eigenschaften[prop];
+ output.AppendFormat(
+ "{0}-Eigenschaftsprobe ew:{1} {2} \n",
+ prop,
+ tap,
+ erschwernis.Equals(0) ? string.Empty : "Erschwernis: " + erschwernis);
+ int roll = Dice.Roll();
+ output.Append($"Gewürfelt: {roll} übrig: {tap - roll - erschwernis}");
+ return output.ToString();
+ }
+
+ public string Angriff(string talent, int erschwernis = 0) // pretty self explanatory
+ {
+ var output = new StringBuilder();
+ var sc = new SpellCorrect();
+ var attack = this.Kampftalente.OrderBy(x => sc.Compare(talent, x.Name)).First();
+ if (sc.Compare(talent, attack.Name) > SpellCorrect.ErrorThreshold)
+ {
+ return $"{this.Name} kann nicht mit der Waffenart {talent} umgehen...";
+ }
+
+ int tap = attack.At;
+ output.AppendFormat(
+ "{0}-Angriff taw:{1} {2} \n",
+ attack.Name,
+ tap,
+ erschwernis.Equals(0) ? string.Empty : "Erschwernis: " + erschwernis);
+
+ int temp = Dice.Roll();
+ output.Append(temp - erschwernis);
+ return output.ToString();
+ }
+
+ public string Parade(string talent, int erschwernis = 0)
+ {
+ var output = new StringBuilder();
+ var sc = new SpellCorrect();
+ var attack = this.Kampftalente.OrderBy(x => sc.Compare(talent, x.Name)).First();
+
+ if (sc.Compare(talent, attack.Name) > SpellCorrect.ErrorThreshold)
+ {
+ return $"{this.Name} kann nicht mit der Waffenart {talent} umgehen...";
+ }
+
+ int tap = attack.Pa;
+ output.AppendFormat(
+ "{0}-Parade taw:{1} {2}\n",
+ attack.Name,
+ tap,
+ erschwernis.Equals(0) ? string.Empty : "Erschwernis: " + erschwernis);
+
+ int temp = Dice.Roll();
+ output.Append(temp - erschwernis);
+ return output.ToString();
+ }
+
+ public string Fernkampf(string talent, int erschwernis = 0)
+ {
+ var output = new StringBuilder();
+ var sc = new SpellCorrect();
+ int fk = this.Eigenschaften["fk"];
+ var attack = this.Talente.OrderBy(x => sc.Compare(talent, x.Name)).First();
+ if (sc.Compare(talent, attack.Name) > SpellCorrect.ErrorThreshold)
+ {
+ return $"{this.Name} kann nicht mit der Waffenart {talent} umgehen...";
+ }
+
+ int tap = attack.Value;
+ output.AppendFormat(
+ "{0} taw:{1} {2} \n",
+ attack.Name,
+ tap,
+ erschwernis.Equals(0) ? string.Empty : "Erschwernis: " + erschwernis);
+ tap -= erschwernis;
+ int temp = Dice.Roll();
+ tap -= temp > fk ? temp - fk : 0;
+ output.Append($"W20: {temp} tap: {tap}");
+ return output.ToString();
+ }
+
+ private void Post_process()
+ {
+ var LE_Wert = this.Eigenschaften["Lebensenergie"];
+ var AE_Wert = this.Eigenschaften.First(s => s.Key.Contains("Astralenergie")).Value;
+
+ //var KL_Wert = this.Eigenschaften.First(s => s.Key.Contains("Klugheit")).Value;
+ var MU_Wert = this.Eigenschaften.First(s => s.Key.Contains("Mut")).Value;
+ var IN_Wert = this.Eigenschaften.First(s => s.Key.Contains("Intuition")).Value;
+ var CH_Wert = this.Eigenschaften.First(s => s.Key.Contains("Charisma")).Value;
+ var KK_Wert = this.Eigenschaften["Körperkraft"];
+ var KO__Wert = this.Eigenschaften["Konstitution"];
+
+ this.Astralpunkte_Basis = 0;
+
+ this.Ausdauer_Basis = 0;
+
+ this.Lebenspunkte_Basis = LE_Wert + (int)(KO__Wert + (KK_Wert / 2.0) + 0.5);
+
+ if (this.Vorteile.Exists(x => x.Name.ToLower().Contains("zauberer")))
+ {
+ this.Astralpunkte_Basis = AE_Wert + (int)((MU_Wert + IN_Wert + CH_Wert) / 2.0 + 0.5);
+ }
+
+ this.Lebenspunkte_Aktuell = this.Lebenspunkte_Basis;
+ this.Astralpunkte_Aktuell = this.Astralpunkte_Basis;
+ this.Ausdauer_Aktuell = this.Ausdauer_Basis;
+
+ }
+
+
+ private void Load(string path)
+ {
+ var reader = new XmlTextReader(path);
+ while (reader.Read())
+ {
+ // read until he hits keywords
+ if (reader.NodeType != XmlNodeType.Element)
+ {
+ continue;
+ }
+
+ switch (reader.Name)
+ {
+ case "Wesen":
+ reader.Skip();
+ break;
+ case "held":
+ this.Name = reader.GetAttribute("name"); // name
+ break;
+ case "eigenschaft":
+ this.Eigenschaften.Add(
+ reader.GetAttribute("name") ?? throw new InvalidOperationException(),
+ Convert.ToInt32(reader.GetAttribute("value")) + Convert.ToInt32(reader.GetAttribute("mod")));
+ break;
+ case "vt":
+ reader.Read();
+ while (reader.Name.Equals("vorteil"))
+ {
+ try
+ {
+ this.Vorteile.Add(new Vorteil(
+ reader.GetAttribute("name"),
+ // Convert.ToInt32(reader.GetAttribute("value"))));
+ reader.GetAttribute("value")));
+ }
+ catch
+ {
+ this.Vorteile.Add(new Vorteil(reader.GetAttribute("name")));
+ }
+
+ reader.Read();
+ }
+
+ break;
+ case "talentliste":
+ reader.Read();
+ while (reader.Name.Equals("talent"))
+ {
+ this.Talente.Add(
+ new Talent(
+ reader.GetAttribute("name"),
+ reader.GetAttribute("probe")?.Remove(0, 2).Trim(')'),
+ Convert.ToInt32(reader.GetAttribute("value"))));
+ reader.Read();
+ }
+
+ break;
+ case "zauberliste":
+ reader.Read();
+ while (reader.Name.Equals("zauber"))
+ {
+ this.Zauber.Add(
+ new Zauber(
+ reader.GetAttribute("name"),
+ reader.GetAttribute("probe")?.Remove(0, 2).Trim(')'),
+ Convert.ToInt32(reader.GetAttribute("value")),
+ reader.GetAttribute("k").ToCharArray()[0],
+ reader.GetAttribute("repraesentation")));
+ reader.Read();
+ }
+
+ break;
+ case "kampfwerte":
+ string atName = reader.GetAttribute("name");
+ reader.Read();
+ int at = Convert.ToInt32(reader.GetAttribute("value"));
+ reader.Read();
+ int pa = Convert.ToInt32(reader.GetAttribute("value"));
+ this.Kampftalente.Add(new KampfTalent(atName, at, pa));
+ break;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/DSACore/DSA_Game/Characters/NPC.cs b/DSACore/DSA_Game/Characters/NPC.cs
new file mode 100644
index 0000000..ec8adfc
--- /dev/null
+++ b/DSACore/DSA_Game/Characters/NPC.cs
@@ -0,0 +1,114 @@
+using DSACore.Auxiliary;
+using DSALib.Characters;
+
+namespace DiscoBot.Characters
+{
+ using System;
+
+ using DiscoBot.Auxiliary;
+ using DiscoBot.DSA_Game.Characters;
+
+ public class Npc : Being, ICharacter
+ {
+ private readonly int mean, stDv;
+
+ public Npc(string name, int mean, int stDv)
+ {
+ this.mean = mean;
+ this.stDv = stDv;
+ this.Name = name;
+ }
+
+ public string TestTalent(string talent, int tap = 3)
+ {
+ for (int i = 0; i <= 2; i++)
+ {
+ // foreach property, dice and tap
+ int temp = Dice.Roll();
+ int eigenschaft = (int)Math.Round(RandomMisc.Random(this.stDv, this.mean));
+
+ if (eigenschaft < temp)
+ {
+ tap -= temp - eigenschaft;
+ }
+ }
+
+ if (tap >= 0)
+ {
+ return $"{this.Name} vollführt {talent} erfolgreich";
+ }
+
+
+ return $"{this.Name} scheitert an {talent}";
+ }
+
+ public string TestEigenschaft(string eigenschaft, int erschwernis = 0)
+ {
+ int temp = Dice.Roll();
+ int prop = (int)Math.Round(RandomMisc.Random(this.stDv, this.stDv));
+
+ if (temp + erschwernis < prop)
+ {
+ return $"{this.Name} vollführt {eigenschaft} erfolgreich";
+ }
+
+ return $"{this.Name} scheitert an {eigenschaft}";
+ }
+
+ public string Angriff(string waffe, int erschwernis = 0)
+ {
+ int temp = Dice.Roll();
+
+ if (temp == 1)
+ {
+ return $"{this.Name} greift kritisch mit {waffe} an";
+ }
+
+ if (temp < erschwernis)
+ {
+ return $"{this.Name} greift mit {waffe} an";
+ }
+
+ return $"{this.Name} haut mit {waffe} daneben";
+ }
+
+ public string Parade(string waffe, int erschwernis = 0)
+ {
+ int temp = Dice.Roll();
+
+ if (temp == 1)
+ {
+ return $"{this.Name} pariert mit {waffe} meisterlich";
+ }
+
+ if (temp < erschwernis)
+ {
+ return $"{this.Name} pariert mit {waffe} an";
+ }
+
+ return $"{this.Name} schafft es nicht mit {waffe} zu parieren";
+ }
+
+ public string Fernkampf(string waffe, int erschwernis = 0)
+ {
+ int temp = Dice.Roll();
+
+ if (temp == 1)
+ {
+ return $"{this.Name} trifft kritisch mit {waffe}";
+ }
+
+ if (temp < erschwernis)
+ {
+ return $"{this.Name} greift mit {waffe} an";
+ }
+
+ return $"{this.Name} schießt mit {waffe} daneben";
+ }
+
+ public string TestZauber(string zauber, int erschwernis)
+ {
+ return TestTalent(zauber, erschwernis);
+ }
+ }
+}
diff --git a/DSACore/DSA_Game/Characters/SaveChar.cs b/DSACore/DSA_Game/Characters/SaveChar.cs
new file mode 100644
index 0000000..50cb91c
--- /dev/null
+++ b/DSACore/DSA_Game/Characters/SaveChar.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DSALib.Characters;
+
+namespace DiscoBot.DSA_Game.Characters
+{
+
+ public class SaveChar
+ {
+ public string Name { get; set; }
+
+ public int Lebenspunkte_Aktuell { get; set; }
+
+ public int Ausdauer_Aktuell { get; set; }
+
+ public int Astralpunkte_Aktuell { get; set; }
+
+ public static SaveChar FromICharacter(ICharacter c)
+ {
+ return new SaveChar
+ {
+ Astralpunkte_Aktuell = c.Astralpunkte_Aktuell,
+ Ausdauer_Aktuell = c.Ausdauer_Aktuell,
+ Lebenspunkte_Aktuell = c.Lebenspunkte_Aktuell,
+ Name = c.Name
+ };
+ }
+ }
+
+
+ public static class ICharExtension
+ {
+ public static void Update(this ICharacter c, SaveChar s)
+ {
+ c.Astralpunkte_Aktuell = s.Astralpunkte_Aktuell;
+ c.Ausdauer_Aktuell = s.Ausdauer_Aktuell;
+ c.Lebenspunkte_Aktuell = s.Lebenspunkte_Aktuell;
+ c.Name = s.Name;
+ }
+ }
+}
diff --git a/DSACore/DSA_Game/Dsa.cs b/DSACore/DSA_Game/Dsa.cs
new file mode 100644
index 0000000..8907f96
--- /dev/null
+++ b/DSACore/DSA_Game/Dsa.cs
@@ -0,0 +1,61 @@
+using DSALib;
+using DSALib.Characters;
+
+namespace DiscoBot.DSA_Game
+{
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using DiscoBot.DSA_Game.Characters;
+ using DiscoBot.DSA_Game.Save;
+
+ public static class Dsa
+ {
+ private static Session s_session;
+
+ public static List<ICharacter> Chars { get; set; } = new List<ICharacter>(); // list of all characters
+
+ public static List<Talent> Talente { get; set; } = new List<Talent>();
+
+ public static Session Session
+ {
+ get
+ {
+ s_session.Chars = Chars.Select(x => SaveChar.FromICharacter(x)).ToList();
+ return s_session;
+ }
+
+ set
+ {
+ s_session = value;
+ foreach (var x in value.Chars)
+ {
+ Chars.Find(c => c.Name.Equals(x.Name)).Update(x);
+ }
+ }
+ }
+
+ public static void Startup()
+ {
+ //new DiscoBot.Auxiliary.Calculator.StringSolver("1d100 - (1d200 + 1) * -50000").Solve();
+ /*Session = new Session();*/
+ // relation.Add("Papo", "Pump aus der Gosse");
+ foreach (var filename in Directory.GetFiles("helden", "*.xml"))
+ {
+ Chars.Add(new Character(filename));
+ (Chars.Last() as Character)?.Talente.Select(x => new Talent(x.Name, x.Probe, 0))
+ .Where(c => !Talente.Exists(v => v.Name.Equals(c.Name))).ToList().ForEach(v => Talente.Add(v));
+ }
+
+ Properties.Deserialize();
+ Properties.Serialize();
+
+ Talente = Talente.OrderBy(x => x.Name).ToList();
+ Session = new Session
+ {
+ Chars = Chars.Select(x => SaveChar.FromICharacter(x)).ToList()
+ };
+ Session.Save();
+ }
+ }
+} \ No newline at end of file
diff --git a/DSACore/DSA_Game/Save/Properties.cs b/DSACore/DSA_Game/Save/Properties.cs
new file mode 100644
index 0000000..a27c9d7
--- /dev/null
+++ b/DSACore/DSA_Game/Save/Properties.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using DSACore.Audio;
+using DSACore.Auxiliary;
+
+namespace DiscoBot.DSA_Game.Save
+{
+ using System.Collections;
+ using System.IO;
+ using Newtonsoft.Json;
+
+ public static class Properties
+ {
+ private static Dictionary<string, object> objects;
+
+ static Properties()
+ {
+ objects = new Dictionary<string, object>();
+ /*this.objects.Add("Sounds", new List<Sound>());
+ this.objects.Add("CommandInfos", new List<CommandInfo>());*/
+ }
+
+ public static List<CommandInfo> CommandInfos { get => objects["CommandInfo"] as List<CommandInfo>; set => objects["CommandInfo"] = value; } // use Properties.Commandinfos to access the abstract Object array
+
+ public static List<Sound> Sounds { get => objects["Sound"] as List<Sound>; set => objects["Sound"] = value; }
+
+ public static void Deserialize(string path = @"..\..\Properties")
+ {
+
+ var files = Directory.GetFiles(path, "*.json");
+
+ foreach (string file in files)
+ {
+ try
+ {
+ string name = file.Split('\\').Last().Split('.')[0].Replace('-', '.');
+ string data = File.ReadAllText(file);
+ Type type = Type.GetType(name);
+ if (data.StartsWith("["))
+ {
+ type = typeof(List<>).MakeGenericType(type);
+ }
+
+ var o = JsonConvert.DeserializeObject(data, type);
+ objects.Add(name.Split('.').Last(), o);
+ }
+ catch (Exception e)
+ {
+ // ignored
+ Console.WriteLine($"Laden von Save-File {file} fehlgeschlagen."+ e);
+ }
+
+ }
+
+ }
+
+ public static void Serialize(string path = @"..\..\Properties\")
+ {
+ try
+ {
+ foreach (var o in objects)
+ {
+ string assembly = o.Value is IList list ? ((IList)list)[0]?.GetType().FullName : o.Value.GetType().FullName;
+
+ var name = path + assembly.Replace('.', '-') + ".json";
+ File.WriteAllText(name, JsonConvert.SerializeObject(o.Value, Formatting.Indented)); // Deserialize Data and create CommandInfo Struct
+ }
+ }
+ catch (Exception e)
+ {
+ // ignored
+ Console.WriteLine($"Speichern von Save-File fehlgeschlagen."+ e);
+ }
+ }
+ }
+}
diff --git a/DSACore/DSA_Game/Save/SaveCommand.cs b/DSACore/DSA_Game/Save/SaveCommand.cs
new file mode 100644
index 0000000..9a2ae8e
--- /dev/null
+++ b/DSACore/DSA_Game/Save/SaveCommand.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace DiscoBot.DSA_Game.Save
+{
+ using System.IO;
+
+ public class SaveCommand
+ {
+ public void LoadSession(string name = "")
+ {
+ if (name.Equals("?") || name.Equals(string.Empty))
+ {
+ Console.WriteLine($"Gespeicherte Sessions:");
+ Console.WriteLine(this.ListSessions());
+ return;
+ }
+
+ var path = DSA_Game.Save.Session.DirectoryPath + @"\" + name;
+
+ var files = Directory.GetFiles(path);
+ var session = files.OrderByDescending(x => Convert.ToInt32(x.Split('-').Last().Split('.').First())).First();
+ Dsa.Session = Session.Load(session);
+
+ Console.WriteLine($"{name} wurde geladen");
+ }
+
+ public void SessionSave(string name = "")
+ {
+ //var sendFile = this.Context.Channel.SendWebFile("https://cdn.discordapp.com/attachments/377123019673567232/465615882048110603/giphy.gif");
+
+ if (name.Equals("?") || name.Equals(string.Empty))
+ {
+ Console.WriteLine($"Gespeicherte Sessions:");
+ Console.WriteLine(this.ListSessions());
+ return;
+ }
+
+ var path = DSA_Game.Save.Session.DirectoryPath + @"\" + name;
+ if (Directory.Exists(path))
+ {
+ var files = Directory.GetFiles(path);
+ int current = files.Max(x => Convert.ToInt32(x.Split('-').Last().Split('.').First()));
+ Dsa.Session.SessionName = name;
+ Dsa.Session.Save(path + "\\" + name + $"-{++current}.json");
+ }
+ else
+ {
+ Directory.CreateDirectory(path);
+ Dsa.Session.SessionName = name;
+ Dsa.Session.Save(path + "\\" + name + $"-0.json");
+ }
+
+ Console.WriteLine($"{name} wurde gespeichert");
+ //await sendFile;
+ }
+
+ private string[] ListSessions()
+ {
+ string[] dirs = Directory.GetDirectories(Session.DirectoryPath).OrderByDescending(x => new DirectoryInfo(x).LastAccessTime.Ticks).ToArray();
+ for (int i = 0; i < dirs.Length; i++)
+ {
+ dirs[i] += "; " + new DirectoryInfo(dirs[i]).LastAccessTime;
+ }
+
+ return dirs;
+ }
+ }
+}
diff --git a/DSACore/DSA_Game/Save/Session.cs b/DSACore/DSA_Game/Save/Session.cs
new file mode 100644
index 0000000..d0cba21
--- /dev/null
+++ b/DSACore/DSA_Game/Save/Session.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace DiscoBot.DSA_Game.Save
+{
+ using System.IO;
+ using DiscoBot.DSA_Game.Characters;
+ using Newtonsoft.Json;
+
+ public class Session
+ {
+ public static string DirectoryPath { get; set; } = @"..\..\sessions";
+
+ public Dictionary<string, string> Relation { get; set; } = new Dictionary<string, string>(); // dictionary to match the char
+
+ public List<SaveChar> Chars { get; set; } = new List<SaveChar>(); // list of all characters
+
+ public string SessionName { get; set; }
+
+ public static Session Load(string path = @"..\..\session.json")
+ {
+ try
+ {
+ return JsonConvert.DeserializeObject<Session>(File.ReadAllText(path)); // Deserialize Data and create Session Object
+ }
+ catch (Exception e)
+ {
+ // ignored
+ Console.WriteLine($"Laden von Save-File {path} fehlgeschlagen."+ e);
+ return null;
+ }
+ }
+
+ public void Save(string path = @"..\..\session.json")
+ {
+ try
+ {
+ File.WriteAllText(path, JsonConvert.SerializeObject(this, Formatting.Indented)); // Deserialize Data and create CommandInfo Struct
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Speichern von Save-File {path} fehlgeschlagen.\n"+ e);
+ // ignored
+ }
+ }
+ }
+}