diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..92514c6
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,133 @@
+[*.cs]
+
+# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+dotnet_diagnostic.CS8618.severity = suggestion
+csharp_indent_labels = one_less_than_current
+csharp_space_around_binary_operators = before_and_after
+csharp_using_directive_placement = outside_namespace:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_style_throw_expression = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_style_prefer_index_operator = true:suggestion
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+csharp_style_prefer_range_operator = true:suggestion
+csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
+csharp_style_prefer_tuple_swap = true:suggestion
+csharp_style_prefer_utf8_string_literals = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
+csharp_style_unused_value_expression_statement_preference = discard_variable:silent
+csharp_prefer_static_local_function = true:suggestion
+csharp_style_prefer_readonly_struct = true:suggestion
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
+csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
+csharp_style_conditional_delegate_call = true:suggestion
+csharp_style_prefer_switch_expression = true:suggestion
+csharp_style_prefer_pattern_matching = true:silent
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_prefer_not_pattern = true:suggestion
+csharp_style_prefer_extended_property_pattern = true:suggestion
+csharp_style_var_for_built_in_types = false:silent
+csharp_style_var_when_type_is_apparent = false:silent
+csharp_style_var_elsewhere = false:silent
+
+[*.{cs,vb}]
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+dotnet_style_readonly_field = true:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
+dotnet_style_allow_multiple_blank_lines_experimental = true:silent
+dotnet_code_quality_unused_parameters = all:suggestion
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
diff --git a/AutoPatcherAdmin/AMain.Designer.cs b/AutoPatcherAdmin/AMain.Designer.cs
new file mode 100644
index 0000000..2c01a28
--- /dev/null
+++ b/AutoPatcherAdmin/AMain.Designer.cs
@@ -0,0 +1,322 @@
+namespace AutoPatcherAdmin
+{
+ partial class AMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.ClientTextBox = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.HostTextBox = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.LoginTextBox = new System.Windows.Forms.TextBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.PasswordTextBox = new System.Windows.Forms.TextBox();
+ this.ProcessButton = new System.Windows.Forms.Button();
+ this.progressBar1 = new System.Windows.Forms.ProgressBar();
+ this.ActionLabel = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this.progressBar2 = new System.Windows.Forms.ProgressBar();
+ this.SpeedLabel = new System.Windows.Forms.Label();
+ this.label7 = new System.Windows.Forms.Label();
+ this.FileLabel = new System.Windows.Forms.Label();
+ this.label8 = new System.Windows.Forms.Label();
+ this.ListButton = new System.Windows.Forms.Button();
+ this.AllowCleanCheckBox = new System.Windows.Forms.CheckBox();
+ this.DownloadExistingButton = new System.Windows.Forms.Button();
+ this.btnFixGZ = new System.Windows.Forms.Button();
+ this.ProtocolDropDown = new System.Windows.Forms.ComboBox();
+ this.label6 = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // ClientTextBox
+ //
+ this.ClientTextBox.Location = new System.Drawing.Point(99, 12);
+ this.ClientTextBox.Name = "ClientTextBox";
+ this.ClientTextBox.Size = new System.Drawing.Size(254, 20);
+ this.ClientTextBox.TabIndex = 0;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 15);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(81, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Client Directory:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(20, 41);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(73, 13);
+ this.label2.TabIndex = 4;
+ this.label2.Text = "Host Address:";
+ //
+ // HostTextBox
+ //
+ this.HostTextBox.Location = new System.Drawing.Point(99, 38);
+ this.HostTextBox.Name = "HostTextBox";
+ this.HostTextBox.Size = new System.Drawing.Size(254, 20);
+ this.HostTextBox.TabIndex = 3;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(57, 67);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(36, 13);
+ this.label3.TabIndex = 6;
+ this.label3.Text = "Login:";
+ //
+ // LoginTextBox
+ //
+ this.LoginTextBox.Location = new System.Drawing.Point(99, 64);
+ this.LoginTextBox.Name = "LoginTextBox";
+ this.LoginTextBox.Size = new System.Drawing.Size(254, 20);
+ this.LoginTextBox.TabIndex = 5;
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(37, 93);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(56, 13);
+ this.label4.TabIndex = 8;
+ this.label4.Text = "Password:";
+ //
+ // PasswordTextBox
+ //
+ this.PasswordTextBox.Location = new System.Drawing.Point(99, 90);
+ this.PasswordTextBox.Name = "PasswordTextBox";
+ this.PasswordTextBox.Size = new System.Drawing.Size(254, 20);
+ this.PasswordTextBox.TabIndex = 7;
+ //
+ // ProcessButton
+ //
+ this.ProcessButton.Location = new System.Drawing.Point(12, 139);
+ this.ProcessButton.Name = "ProcessButton";
+ this.ProcessButton.Size = new System.Drawing.Size(75, 23);
+ this.ProcessButton.TabIndex = 9;
+ this.ProcessButton.Text = "Process";
+ this.ProcessButton.UseVisualStyleBackColor = true;
+ this.ProcessButton.Click += new System.EventHandler(this.ProcessButton_Click);
+ //
+ // progressBar1
+ //
+ this.progressBar1.Location = new System.Drawing.Point(12, 182);
+ this.progressBar1.Name = "progressBar1";
+ this.progressBar1.Size = new System.Drawing.Size(372, 16);
+ this.progressBar1.TabIndex = 12;
+ //
+ // ActionLabel
+ //
+ this.ActionLabel.AutoSize = true;
+ this.ActionLabel.Location = new System.Drawing.Point(59, 166);
+ this.ActionLabel.Name = "ActionLabel";
+ this.ActionLabel.Size = new System.Drawing.Size(24, 13);
+ this.ActionLabel.TabIndex = 11;
+ this.ActionLabel.Text = "Idle";
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(13, 166);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(40, 13);
+ this.label5.TabIndex = 10;
+ this.label5.Text = "Action:";
+ //
+ // progressBar2
+ //
+ this.progressBar2.Location = new System.Drawing.Point(12, 238);
+ this.progressBar2.Name = "progressBar2";
+ this.progressBar2.Size = new System.Drawing.Size(372, 10);
+ this.progressBar2.TabIndex = 13;
+ //
+ // SpeedLabel
+ //
+ this.SpeedLabel.AutoSize = true;
+ this.SpeedLabel.Location = new System.Drawing.Point(59, 222);
+ this.SpeedLabel.Name = "SpeedLabel";
+ this.SpeedLabel.Size = new System.Drawing.Size(24, 13);
+ this.SpeedLabel.TabIndex = 15;
+ this.SpeedLabel.Text = "Idle";
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point(12, 222);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(41, 13);
+ this.label7.TabIndex = 14;
+ this.label7.Text = "Speed:";
+ //
+ // FileLabel
+ //
+ this.FileLabel.AutoSize = true;
+ this.FileLabel.Location = new System.Drawing.Point(59, 209);
+ this.FileLabel.Name = "FileLabel";
+ this.FileLabel.Size = new System.Drawing.Size(24, 13);
+ this.FileLabel.TabIndex = 17;
+ this.FileLabel.Text = "Idle";
+ //
+ // label8
+ //
+ this.label8.AutoSize = true;
+ this.label8.Location = new System.Drawing.Point(27, 209);
+ this.label8.Name = "label8";
+ this.label8.Size = new System.Drawing.Size(26, 13);
+ this.label8.TabIndex = 16;
+ this.label8.Text = "File:";
+ //
+ // ListButton
+ //
+ this.ListButton.Location = new System.Drawing.Point(309, 139);
+ this.ListButton.Name = "ListButton";
+ this.ListButton.Size = new System.Drawing.Size(75, 23);
+ this.ListButton.TabIndex = 20;
+ this.ListButton.Text = "Create List";
+ this.ListButton.UseVisualStyleBackColor = true;
+ this.ListButton.Click += new System.EventHandler(this.ListButton_Click);
+ //
+ // AllowCleanCheckBox
+ //
+ this.AllowCleanCheckBox.AutoSize = true;
+ this.AllowCleanCheckBox.Location = new System.Drawing.Point(99, 116);
+ this.AllowCleanCheckBox.Name = "AllowCleanCheckBox";
+ this.AllowCleanCheckBox.Size = new System.Drawing.Size(98, 17);
+ this.AllowCleanCheckBox.TabIndex = 22;
+ this.AllowCleanCheckBox.Text = "Allow Clean Up";
+ this.AllowCleanCheckBox.UseVisualStyleBackColor = true;
+ //
+ // DownloadExistingButton
+ //
+ this.DownloadExistingButton.Location = new System.Drawing.Point(169, 139);
+ this.DownloadExistingButton.Name = "DownloadExistingButton";
+ this.DownloadExistingButton.Size = new System.Drawing.Size(134, 23);
+ this.DownloadExistingButton.TabIndex = 23;
+ this.DownloadExistingButton.Text = "Download Existing Data";
+ this.DownloadExistingButton.UseVisualStyleBackColor = true;
+ this.DownloadExistingButton.Click += new System.EventHandler(this.DownloadExistingButton_Click);
+ //
+ // btnFixGZ
+ //
+ this.btnFixGZ.Location = new System.Drawing.Point(93, 139);
+ this.btnFixGZ.Name = "btnFixGZ";
+ this.btnFixGZ.Size = new System.Drawing.Size(75, 23);
+ this.btnFixGZ.TabIndex = 24;
+ this.btnFixGZ.Text = "Fix *.gz";
+ this.btnFixGZ.UseVisualStyleBackColor = true;
+ this.btnFixGZ.Click += new System.EventHandler(this.btnFixGZ_Click);
+ //
+ // ProtocolDropDown
+ //
+ this.ProtocolDropDown.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.ProtocolDropDown.FormattingEnabled = true;
+ this.ProtocolDropDown.Items.AddRange(new object[] {
+ "Ftp",
+ "SFtp"});
+ this.ProtocolDropDown.Location = new System.Drawing.Point(262, 114);
+ this.ProtocolDropDown.Name = "ProtocolDropDown";
+ this.ProtocolDropDown.Size = new System.Drawing.Size(91, 21);
+ this.ProtocolDropDown.TabIndex = 25;
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(207, 117);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(49, 13);
+ this.label6.TabIndex = 26;
+ this.label6.Text = "Protocol:";
+ //
+ // AMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(392, 257);
+ this.Controls.Add(this.label6);
+ this.Controls.Add(this.ProtocolDropDown);
+ this.Controls.Add(this.btnFixGZ);
+ this.Controls.Add(this.DownloadExistingButton);
+ this.Controls.Add(this.AllowCleanCheckBox);
+ this.Controls.Add(this.ListButton);
+ this.Controls.Add(this.FileLabel);
+ this.Controls.Add(this.label8);
+ this.Controls.Add(this.SpeedLabel);
+ this.Controls.Add(this.label7);
+ this.Controls.Add(this.progressBar2);
+ this.Controls.Add(this.progressBar1);
+ this.Controls.Add(this.ActionLabel);
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.ProcessButton);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.PasswordTextBox);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.LoginTextBox);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.HostTextBox);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.ClientTextBox);
+ this.Name = "AMain";
+ this.Text = "Auto Patcher Admin";
+ this.Load += new System.EventHandler(this.AMain_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox ClientTextBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox HostTextBox;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.TextBox LoginTextBox;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.TextBox PasswordTextBox;
+ private System.Windows.Forms.Button ProcessButton;
+ private System.Windows.Forms.ProgressBar progressBar1;
+ private System.Windows.Forms.Label ActionLabel;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.ProgressBar progressBar2;
+ private System.Windows.Forms.Label SpeedLabel;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.Label FileLabel;
+ private System.Windows.Forms.Label label8;
+ private System.Windows.Forms.Button ListButton;
+ private System.Windows.Forms.CheckBox AllowCleanCheckBox;
+ private System.Windows.Forms.Button DownloadExistingButton;
+ private System.Windows.Forms.Button btnFixGZ;
+ private System.Windows.Forms.ComboBox ProtocolDropDown;
+ private System.Windows.Forms.Label label6;
+ }
+}
+
diff --git a/AutoPatcherAdmin/AMain.cs b/AutoPatcherAdmin/AMain.cs
new file mode 100644
index 0000000..eb29431
--- /dev/null
+++ b/AutoPatcherAdmin/AMain.cs
@@ -0,0 +1,747 @@
+using System.IO.Compression;
+using WinSCP;
+
+namespace AutoPatcherAdmin
+{
+ public partial class AMain : Form
+ {
+ public const string PatchFileName = @"PList.gz";
+ public const string TempUploadDirectory = "Out";
+ public const string TempDownloadDirectory = "In";
+
+ public string[] ExcludeList = new string[] { "Thumbs.db" };
+
+ public List OldList, NewList;
+ public Queue UploadList;
+
+ public bool Completed;
+
+ public AMain()
+ {
+ InitializeComponent();
+
+ ClientTextBox.Text = Settings.Client;
+ HostTextBox.Text = Settings.Host;
+ LoginTextBox.Text = Settings.Login;
+ PasswordTextBox.Text = Settings.Password;
+ AllowCleanCheckBox.Checked = Settings.AllowCleanUp;
+ ProtocolDropDown.SelectedIndex = ProtocolDropDown.FindString(Settings.Protocol);
+
+ DeleteDirectory(TempDownloadDirectory);
+ DeleteDirectory(TempUploadDirectory);
+ }
+
+ private void CompleteDownload()
+ {
+ FileLabel.Text = "Complete...";
+ SpeedLabel.Text = "Complete...";
+ ActionLabel.Text = "Complete...";
+
+ progressBar1.Value = 100;
+ progressBar2.Value = 100;
+
+ DownloadExistingButton.Enabled = true;
+
+ Completed = true;
+ }
+
+ private void CompleteUpload()
+ {
+ FileLabel.Text = "Complete...";
+ SpeedLabel.Text = "Complete...";
+ ActionLabel.Text = "Complete...";
+
+ progressBar1.Value = 100;
+ progressBar2.Value = 100;
+
+ ProcessButton.Enabled = true;
+ ListButton.Enabled = true;
+ btnFixGZ.Enabled = true;
+
+ Completed = true;
+ }
+
+ private void CleanUp()
+ {
+ if (!Settings.AllowCleanUp) return;
+
+ var rootPath = (new Uri(Settings.Host)).AbsolutePath;
+
+ using Session session = new();
+ OpenSession(session);
+
+ for (int i = 0; i < OldList.Count; i++)
+ {
+ if (NeedFile(OldList[i].FileName)) continue;
+
+ var compressed = OldList[i].Length != OldList[i].Compressed;
+
+ try
+ {
+ var filename = OldList[i].FileName + (compressed ? ".gz" : "");
+
+ var filePath = Path.Combine(rootPath, filename).Replace(@"\", "/");
+
+ if (session.FileExists(filePath))
+ {
+ session.RemoveFile(filePath);
+ }
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ private bool NeedFile(string fileName)
+ {
+ for (int i = 0; i < NewList.Count; i++)
+ {
+ if (fileName.EndsWith(NewList[i].FileName) && !InExcludeList(NewList[i].FileName))
+ return true;
+ }
+
+ return false;
+ }
+
+ private void GetOldFileList()
+ {
+ OldList = new List();
+
+ byte[] data = DownloadFile(PatchFileName);
+
+ if (data != null)
+ {
+ using MemoryStream stream = new MemoryStream(data);
+ using BinaryReader reader = new BinaryReader(stream);
+
+ int count = reader.ReadInt32();
+
+ for (int i = 0; i < count; i++)
+ {
+ OldList.Add(new FileInformation(reader));
+ }
+ }
+ }
+
+ private byte[] CreateNewList()
+ {
+ using MemoryStream stream = new MemoryStream();
+ using BinaryWriter writer = new BinaryWriter(stream);
+
+ writer.Write(NewList.Count);
+ for (int i = 0; i < NewList.Count; i++)
+ {
+ NewList[i].Save(writer);
+ }
+
+ return stream.ToArray();
+ }
+
+ private void GetNewFileList()
+ {
+ NewList = new List();
+
+ string[] files = Directory.GetFiles(Settings.Client, "*.*" ,SearchOption.AllDirectories);
+
+ for (int i = 0; i < files.Length; i++)
+ {
+ NewList.Add(GetFileInformation(files[i]));
+ }
+ }
+
+ private bool InExcludeList(string fileName)
+ {
+ foreach (var item in ExcludeList)
+ {
+ if (fileName.EndsWith(item)) return true;
+ }
+
+ return false;
+ }
+
+ private void FixFilenameExtensions()
+ {
+ var rootPath = (new Uri(Settings.Host)).AbsolutePath;
+
+ using Session session = new Session();
+ OpenSession(session);
+
+ for (int i = 0; i < OldList.Count; i++)
+ {
+ FileInformation old = OldList[i];
+
+ try
+ {
+ ActionLabel.Text = old.FileName;
+ Refresh();
+
+ if (old.Compressed == old.Length)
+ {
+ //exists, but not compressed, lets rename it
+
+ var compressedFilename = OldList[i].FileName + ".gz";
+ var compressedFilePath = Path.Combine(rootPath, compressedFilename).Replace(@"\", "/");
+
+ var uncompressedFilename = OldList[i].FileName;
+ var uncompressedFilePath = Path.Combine(rootPath, compressedFilename).Replace(@"\", "/");
+
+ if (session.FileExists(compressedFilePath))
+ {
+ session.MoveFile(compressedFilePath, uncompressedFilename);
+ }
+ }
+ else
+ {
+ //exists, but its compressed and ends with .gz, so its correct
+ }
+ }
+ catch
+ {
+
+ }
+ }
+ }
+
+ private bool NeedUpdate(FileInformation info)
+ {
+ for (int i = 0; i < OldList.Count; i++)
+ {
+ FileInformation old = OldList[i];
+ if (old.FileName != info.FileName) continue;
+
+ if (old.Length != info.Length) return true;
+ if (old.Creation != info.Creation) return true;
+
+ return false;
+ }
+ return true;
+ }
+
+ private FileInformation? GetFileInformation(string fileName)
+ {
+ if (!File.Exists(fileName))
+ {
+ return null;
+ }
+
+ FileInfo info = new(fileName);
+
+ FileInformation file = new()
+ {
+ FileName = fileName.Remove(0, Settings.Client.Length).TrimStart('\\'),
+ Length = (int)info.Length,
+ Creation = info.LastWriteTime
+ };
+
+ return file;
+ }
+
+ private void OpenSession(Session session)
+ {
+ if (session.Opened) return;
+
+ Uri uri = null;
+
+ if (!string.IsNullOrEmpty(Settings.Host))
+ {
+ uri = new Uri(Settings.Host);
+ }
+
+ if (!Protocol.TryParse(Settings.Protocol, true, out Protocol protocol))
+ {
+ protocol = Protocol.Ftp;
+ }
+
+ SessionOptions sessionOptions = new SessionOptions
+ {
+ Protocol = protocol,
+ HostName = uri.Host,
+ UserName = Settings.Login,
+ Password = Settings.Password
+ };
+
+ if (sessionOptions.Protocol == Protocol.Sftp)
+ {
+ var fingerprint = session.ScanFingerprint(sessionOptions, "SHA-256");
+
+ sessionOptions.SshHostKeyFingerprint = fingerprint;
+ }
+
+ session.Open(sessionOptions);
+ }
+
+
+ private void BeginUpload()
+ {
+ if (UploadList == null) return;
+
+ progressBar1.Value = 0;
+ progressBar2.Value = 0;
+
+ int uploadCount = UploadList.Count;
+
+ while (UploadList.Count > 0)
+ {
+ FileInformation info = UploadList.Dequeue();
+
+ CreateTempUploadFiles(info, File.ReadAllBytes(Settings.Client + (info.FileName)));
+ }
+
+ CleanUp();
+
+ CreateTempUploadFiles(new FileInformation { FileName = PatchFileName }, CreateNewList());
+ UploadFiles(++uploadCount);
+
+ UploadList = null;
+ }
+ private void CreateTempUploadFiles(FileInformation info, byte[] raw)
+ {
+ string fileName = info.FileName.Replace(@"\", "/");
+
+ byte[] data = (!Settings.CompressFiles || fileName == "PList.gz") ? raw : Compress(raw);
+ info.Compressed = data.Length;
+
+ if (fileName != "PList.gz" && Settings.CompressFiles)
+ {
+ fileName += ".gz";
+ }
+
+ var sourceDir = Path.GetDirectoryName(fileName);
+ var tempSourceDir = Path.Combine(TempUploadDirectory, sourceDir);
+
+ var tempFilePath = Path.Combine(TempUploadDirectory, fileName).Replace(@"\", "/");
+
+ if (!Directory.Exists(tempSourceDir))
+ {
+ Directory.CreateDirectory(tempSourceDir);
+ }
+
+ File.WriteAllBytes(tempFilePath, data);
+ File.SetLastWriteTime(tempFilePath, info.Creation);
+ }
+
+ private void UploadFiles(int uploadCount = 0)
+ {
+ var rootPath = (new Uri(Settings.Host)).AbsolutePath;
+
+ using Session session = new Session();
+
+ session.FileTransferProgress += (o, e) =>
+ {
+ int value = (int)(e.OverallProgress * 100);
+ progressBar1.Value = value > progressBar1.Maximum ? progressBar1.Maximum : value;
+
+ int value2 = (int)(e.FileProgress * 100);
+ progressBar2.Value = value2 > progressBar2.Maximum ? progressBar2.Maximum : value2;
+
+ FileLabel.Text = e.FileName.TrimStart(TempUploadDirectory.ToCharArray()).TrimStart('\\');
+ SpeedLabel.Text = ((double)e.CPS / 1024).ToString("0.##") + " KB/s";
+
+ ActionLabel.Text = string.Format("Uploading... Files: {0}", uploadCount);
+ };
+
+ session.FileTransferred += (o, e) =>
+ {
+ uploadCount--;
+
+ if (uploadCount <= 0)
+ {
+ uploadCount = 0;
+ CompleteUpload();
+ }
+ };
+
+ OpenSession(session);
+
+ TransferOptions transferOptions = new TransferOptions
+ {
+ TransferMode = TransferMode.Binary,
+ OverwriteMode = OverwriteMode.Overwrite
+ };
+
+ if (!session.FileExists(rootPath))
+ {
+ session.CreateDirectory(rootPath);
+ }
+
+ var result = session.PutFilesToDirectory(TempUploadDirectory, rootPath, options: transferOptions);
+ result.Check();
+
+ DeleteDirectory(TempUploadDirectory);
+ }
+
+
+
+
+ private byte[] DownloadFile(string fileName)
+ {
+ using Session session = new Session();
+ OpenSession(session);
+
+ try
+ {
+ if (!Directory.Exists(TempDownloadDirectory))
+ {
+ Directory.CreateDirectory(TempDownloadDirectory);
+ }
+
+ TransferOptions transferOptions = new TransferOptions
+ {
+ TransferMode = TransferMode.Binary,
+ OverwriteMode = OverwriteMode.Overwrite
+ };
+
+ var rootPath = (new Uri(Settings.Host)).AbsolutePath;
+
+ var result = session.GetFiles(Path.Combine(rootPath, fileName), Path.Combine(TempDownloadDirectory, fileName), options: transferOptions);
+ result.Check();
+
+ MemoryStream ms = new MemoryStream();
+ using (FileStream fs = new FileStream(Path.Combine(TempDownloadDirectory, fileName), FileMode.Open, FileAccess.Read))
+ fs.CopyTo(ms);
+
+ DeleteDirectory(TempDownloadDirectory);
+
+ return ms.ToArray();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private void DownloadFiles()
+ {
+ var rootPath = (new Uri(Settings.Host)).AbsolutePath;
+
+ using Session session = new Session();
+
+ session.FileTransferProgress += (o, e) =>
+ {
+ int value = (int)(e.OverallProgress * 100);
+ progressBar1.Value = value > progressBar1.Maximum ? progressBar1.Maximum : value;
+
+ int value2 = (int)(e.FileProgress * 100);
+ progressBar2.Value = value2 > progressBar2.Maximum ? progressBar2.Maximum : value2;
+
+ FileLabel.Text = e.FileName.Replace(rootPath, "");
+ SpeedLabel.Text = ((double)e.CPS / 1024).ToString("0.##") + " KB/s";
+
+ ActionLabel.Text = "Downloading... Files";
+ };
+
+ session.FileTransferred += (o, e) =>
+ {
+
+ };
+
+ OpenSession(session);
+
+ TransferOptions transferOptions = new TransferOptions
+ {
+ TransferMode = TransferMode.Binary,
+ OverwriteMode = OverwriteMode.Overwrite
+ };
+
+ if (!Directory.Exists(TempDownloadDirectory))
+ {
+ Directory.CreateDirectory(TempDownloadDirectory);
+ }
+
+ var result = session.GetFilesToDirectory(rootPath, TempDownloadDirectory, options: transferOptions);
+ result.Check();
+
+ CompleteDownload();
+ }
+
+ private void MoveTempDownloadedFiles()
+ {
+ for (int i = 0; i < OldList.Count; i++)
+ {
+ var info = OldList[i];
+ var compressed = OldList[i].Length != OldList[i].Compressed;
+ var filename = OldList[i].FileName + (compressed ? ".gz" : "");
+
+ var currentPath = Path.Combine(TempDownloadDirectory, filename);
+
+ var relativeDestDir = Path.GetDirectoryName(info.FileName);
+ var destDir = Path.Combine(Settings.Client, relativeDestDir);
+ var destFilename = Path.Combine(Settings.Client, info.FileName);
+
+ if (!Directory.Exists(destDir))
+ {
+ Directory.CreateDirectory(destDir);
+ }
+
+ if (File.Exists(destFilename))
+ {
+ File.Delete(destFilename);
+ }
+
+ if (compressed)
+ {
+ byte[] raw = File.ReadAllBytes(currentPath);
+
+ File.WriteAllBytes(destFilename, Decompress(raw));
+ }
+ else
+ {
+ File.Move(currentPath, destFilename);
+ }
+
+ File.SetLastWriteTime(destFilename, info.Creation);
+ }
+
+ DeleteDirectory(TempDownloadDirectory);
+ }
+
+
+
+
+ private void ListButton_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ ListButton.Enabled = false;
+ Settings.Client = ClientTextBox.Text;
+ Settings.Host = HostTextBox.Text;
+ Settings.Login = LoginTextBox.Text;
+ Settings.Password = PasswordTextBox.Text;
+ Settings.Protocol = (string)ProtocolDropDown.SelectedItem;
+
+ GetOldFileList();
+ GetNewFileList();
+
+ for (int i = 0; i < NewList.Count; i++)
+ {
+ FileInformation info = NewList[i];
+ for (int o = 0; o < OldList.Count; o++)
+ {
+ if (OldList[o].FileName != info.FileName) continue;
+
+ NewList[i].Compressed = OldList[o].Compressed;
+ break;
+ }
+
+ if (info.Compressed == 0)
+ {
+ //We've uploaded a new file which is unknown to the existing PList (or no PList available). Assume this file was uploaded uncompressed and set to file length.
+ info.Compressed = info.Length;
+ }
+ }
+
+ CreateTempUploadFiles(new FileInformation { FileName = PatchFileName }, CreateNewList());
+ UploadFiles(1);
+ }
+ catch (Exception ex)
+ {
+ ListButton.Enabled = true;
+ MessageBox.Show(ex.ToString());
+ ActionLabel.Text = "Error...";
+ }
+ }
+
+ private void ProcessButton_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ ProcessButton.Enabled = false;
+ Settings.Client = ClientTextBox.Text;
+ Settings.Host = HostTextBox.Text;
+ Settings.Login = LoginTextBox.Text;
+ Settings.Password = PasswordTextBox.Text;
+ Settings.AllowCleanUp = AllowCleanCheckBox.Checked;
+ Settings.Protocol = (string)ProtocolDropDown.SelectedItem;
+
+ UploadList = new Queue();
+
+ GetOldFileList();
+
+ ActionLabel.Text = "Checking Files...";
+ Refresh();
+
+ GetNewFileList();
+
+ for (int i = 0; i < NewList.Count; i++)
+ {
+ FileInformation info = NewList[i];
+
+ if (InExcludeList(info.FileName)) continue;
+
+ if (NeedUpdate(info))
+ {
+ UploadList.Enqueue(info);
+ }
+ else
+ {
+ for (int o = 0; o < OldList.Count; o++)
+ {
+ if (OldList[o].FileName != info.FileName) continue;
+ NewList[i] = OldList[o];
+ break;
+ }
+ }
+ }
+
+ BeginUpload();
+
+ }
+ catch (Exception ex)
+ {
+ ProcessButton.Enabled = true;
+ MessageBox.Show(ex.ToString());
+ ActionLabel.Text = "Error...";
+ }
+ }
+
+ private void btnFixGZ_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ btnFixGZ.Enabled = false;
+
+ Settings.Client = ClientTextBox.Text;
+ Settings.Host = HostTextBox.Text;
+ Settings.Login = LoginTextBox.Text;
+ Settings.Password = PasswordTextBox.Text;
+ Settings.Protocol = (string)ProtocolDropDown.SelectedItem;
+
+ GetOldFileList();
+ GetNewFileList();
+
+ for (int i = 0; i < NewList.Count; i++)
+ {
+ FileInformation info = NewList[i];
+ for (int o = 0; o < OldList.Count; o++)
+ {
+ if (OldList[o].FileName != info.FileName) continue;
+ NewList[i].Compressed = OldList[o].Length;
+ break;
+ }
+ }
+
+ CreateTempUploadFiles(new FileInformation { FileName = PatchFileName }, CreateNewList());
+ UploadFiles(1);
+
+ FixFilenameExtensions();
+ }
+ catch(Exception ex)
+ {
+ btnFixGZ.Enabled = true;
+ MessageBox.Show(ex.ToString(), "Error");
+ ActionLabel.Text = "Error...";
+ }
+ }
+
+ private void DownloadExistingButton_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ DownloadExistingButton.Enabled = false;
+ Settings.Client = ClientTextBox.Text;
+ Settings.Host = HostTextBox.Text;
+ Settings.Login = LoginTextBox.Text;
+ Settings.Password = PasswordTextBox.Text;
+ Settings.AllowCleanUp = AllowCleanCheckBox.Checked;
+ Settings.Protocol = (string)ProtocolDropDown.SelectedItem;
+
+ GetOldFileList();
+ DownloadFiles();
+ MoveTempDownloadedFiles();
+ }
+ catch (Exception ex)
+ {
+ DownloadExistingButton.Enabled = true;
+ MessageBox.Show(ex.ToString(), "Error");
+ ActionLabel.Text = "Error...";
+ }
+ }
+
+ private void AMain_Load(object sender, EventArgs e)
+ {
+
+ }
+
+
+ private void DeleteDirectory(string target_dir)
+ {
+ if (!Directory.Exists(target_dir)) return;
+
+ string[] files = Directory.GetFiles(target_dir);
+ string[] dirs = Directory.GetDirectories(target_dir);
+
+ foreach (string file in files)
+ {
+ File.SetAttributes(file, FileAttributes.Normal);
+ File.Delete(file);
+ }
+
+ foreach (string dir in dirs)
+ {
+ DeleteDirectory(dir);
+ }
+
+ Directory.Delete(target_dir, false);
+ }
+
+ private byte[] Decompress(byte[] raw)
+ {
+ using (GZipStream gStream = new GZipStream(new MemoryStream(raw), CompressionMode.Decompress))
+ {
+ const int size = 4096; //4kb
+ byte[] buffer = new byte[size];
+ using (MemoryStream mStream = new MemoryStream())
+ {
+ int count;
+ do
+ {
+ count = gStream.Read(buffer, 0, size);
+ if (count > 0)
+ {
+ mStream.Write(buffer, 0, count);
+ }
+ } while (count > 0);
+ return mStream.ToArray();
+ }
+ }
+ }
+
+ private byte[] Compress(byte[] raw)
+ {
+ using (MemoryStream mStream = new MemoryStream())
+ {
+ using (GZipStream gStream = new GZipStream(mStream, CompressionMode.Compress, true))
+ gStream.Write(raw, 0, raw.Length);
+ return mStream.ToArray();
+ }
+ }
+ }
+
+ public class FileInformation
+ {
+ public string FileName; //Relative.
+ public int Length, Compressed;
+ public DateTime Creation;
+
+ public FileInformation()
+ {
+ Creation = DateTime.Now;
+ }
+ public FileInformation(BinaryReader reader)
+ {
+ FileName = reader.ReadString();
+ Length = reader.ReadInt32();
+ Compressed = reader.ReadInt32();
+ Creation = DateTime.FromBinary(reader.ReadInt64());
+ }
+ public void Save(BinaryWriter writer)
+ {
+ writer.Write(FileName);
+ writer.Write(Length);
+ writer.Write(Compressed);
+ writer.Write(Creation.ToBinary());
+ }
+ }
+}
diff --git a/AutoPatcherAdmin/AMain.resx b/AutoPatcherAdmin/AMain.resx
new file mode 100644
index 0000000..3ae1f55
--- /dev/null
+++ b/AutoPatcherAdmin/AMain.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ True
+
+
\ No newline at end of file
diff --git a/AutoPatcherAdmin/AutoPatcherAdmin.csproj b/AutoPatcherAdmin/AutoPatcherAdmin.csproj
new file mode 100644
index 0000000..0a60670
--- /dev/null
+++ b/AutoPatcherAdmin/AutoPatcherAdmin.csproj
@@ -0,0 +1,20 @@
+
+
+
+ WinExe
+ net8.0-windows7.0
+ enable
+ true
+ enable
+
+
+
+ false
+ false
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AutoPatcherAdmin/InIReader.cs b/AutoPatcherAdmin/InIReader.cs
new file mode 100644
index 0000000..50cd9ae
--- /dev/null
+++ b/AutoPatcherAdmin/InIReader.cs
@@ -0,0 +1,420 @@
+namespace AutoPatcherAdmin
+{
+ public class InIReader
+ {
+ #region Fields
+ private readonly List _contents;
+ private readonly string _fileName;
+ #endregion
+
+ #region Constructor
+ public InIReader(string fileName)
+ {
+ _fileName = fileName;
+
+ _contents = new List();
+ try
+ {
+ if (File.Exists(_fileName))
+ _contents.AddRange(File.ReadAllLines(_fileName));
+ }
+ catch
+ {
+ }
+ }
+ #endregion
+
+ #region Functions
+ private string FindValue(string section, string key)
+ {
+ for (int a = 0; a < _contents.Count; a++)
+ if (String.CompareOrdinal(_contents[a], "[" + section + "]") == 0)
+ for (int b = a + 1; b < _contents.Count; b++)
+ if (String.CompareOrdinal(_contents[b].Split('=')[0], key) == 0)
+ return _contents[b].Split('=')[1];
+ else if (_contents[b].StartsWith("[") && _contents[b].EndsWith("]"))
+ return null;
+ return null;
+ }
+
+ private int FindIndex(string section, string key)
+ {
+ for (int a = 0; a < _contents.Count; a++)
+ if (String.CompareOrdinal(_contents[a], "[" + section + "]") == 0)
+ for (int b = a + 1; b < _contents.Count; b++)
+ if (String.CompareOrdinal(_contents[b].Split('=')[0], key) == 0)
+ return b;
+ else if (_contents[b].StartsWith("[") && _contents[b].EndsWith("]"))
+ {
+ _contents.Insert(b - 1, key + "=");
+ return b - 1;
+ }
+ else if (_contents.Count - 1 == b)
+ {
+ _contents.Add(key + "=");
+ return _contents.Count - 1;
+ }
+ if (_contents.Count > 0)
+ _contents.Add("");
+
+ _contents.Add("[" + section + "]");
+ _contents.Add(key + "=");
+ return _contents.Count - 1;
+ }
+
+ public void Save()
+ {
+ try
+ {
+ File.WriteAllLines(_fileName, _contents.ToArray());
+ }
+ catch
+ {
+ }
+ }
+ #endregion
+
+ #region Read
+ public bool ReadBoolean(string section, string key, bool Default)
+ {
+ bool result;
+
+ if (!bool.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public byte ReadByte(string section, string key, byte Default)
+ {
+ byte result;
+
+ if (!byte.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+
+ public sbyte ReadSByte(string section, string key, sbyte Default)
+ {
+ sbyte result;
+
+ if (!sbyte.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+
+ public ushort ReadUInt16(string section, string key, ushort Default)
+ {
+ ushort result;
+
+ if (!ushort.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+
+ public short ReadInt16(string section, string key, short Default)
+ {
+ short result;
+
+ if (!short.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+
+ public uint ReadUInt32(string section, string key, uint Default)
+ {
+ uint result;
+
+ if (!uint.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public int ReadInt32(string section, string key, int Default)
+ {
+ int result;
+
+ if (!int.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public ulong ReadUInt64(string section, string key, ulong Default)
+ {
+ ulong result;
+
+ if (!ulong.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public long ReadInt64(string section, string key, long Default)
+ {
+ long result;
+
+ if (!long.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+
+ public float ReadSingle(string section, string key, float Default)
+ {
+ float result;
+
+ if (!float.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public double ReadDouble(string section, string key, double Default)
+ {
+ double result;
+
+ if (!double.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public decimal ReadDecimal(string section, string key, decimal Default)
+ {
+ decimal result;
+
+ if (!decimal.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public string ReadString(string section, string key, string Default)
+ {
+ string result = FindValue(section, key);
+
+ if (string.IsNullOrEmpty(result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public char ReadChar(string section, string key, char Default)
+ {
+ char result;
+
+ if (!char.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+ return result;
+ }
+
+ public Point ReadPoint(string section, string key, Point Default)
+ {
+ string temp = FindValue(section, key);
+ int tempX, tempY;
+ if (temp == null || !int.TryParse(temp.Split(',')[0], out tempX))
+ {
+ Write(section, key, Default);
+ return Default;
+ }
+ if (!int.TryParse(temp.Split(',')[1], out tempY))
+ {
+ Write(section, key, Default);
+ return Default;
+ }
+
+ return new Point(tempX, tempY);
+ }
+
+ public Size ReadSize(string section, string key, Size Default)
+ {
+ string temp = FindValue(section, key);
+ int tempX, tempY;
+ if (!int.TryParse(temp.Split(',')[0], out tempX))
+ {
+ Write(section, key, Default);
+ return Default;
+ }
+ if (!int.TryParse(temp.Split(',')[1], out tempY))
+ {
+ Write(section, key, Default);
+ return Default;
+ }
+
+ return new Size(tempX, tempY);
+ }
+
+ public TimeSpan ReadTimeSpan(string section, string key, TimeSpan Default)
+ {
+ TimeSpan result;
+
+ if (!TimeSpan.TryParse(FindValue(section, key), out result))
+ {
+ result = Default;
+ Write(section, key, Default);
+ }
+
+
+ return result;
+ }
+ #endregion
+
+ #region Write
+ public void Write(string section, string key, bool value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, byte value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, sbyte value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, ushort value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, short value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, uint value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, int value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, ulong value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, long value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, float value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, double value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, decimal value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, string value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, char value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+
+ public void Write(string section, string key, Point value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value.X + "," + value.Y;
+ Save();
+ }
+
+ public void Write(string section, string key, Size value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value.Width + "," + value.Height;
+ Save();
+ }
+
+ public void Write(string section, string key, TimeSpan value)
+ {
+ _contents[FindIndex(section, key)] = key + "=" + value;
+ Save();
+ }
+ #endregion
+ }
+}
diff --git a/AutoPatcherAdmin/Program.cs b/AutoPatcherAdmin/Program.cs
new file mode 100644
index 0000000..76f651e
--- /dev/null
+++ b/AutoPatcherAdmin/Program.cs
@@ -0,0 +1,20 @@
+namespace AutoPatcherAdmin
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Settings.Load();
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new AMain());
+
+ Settings.Save();
+ }
+ }
+}
diff --git a/AutoPatcherAdmin/Settings.cs b/AutoPatcherAdmin/Settings.cs
new file mode 100644
index 0000000..b17c37a
--- /dev/null
+++ b/AutoPatcherAdmin/Settings.cs
@@ -0,0 +1,40 @@
+namespace AutoPatcherAdmin
+{
+ public static class Settings
+ {
+ private static readonly InIReader Reader = new InIReader(@".\PatchAdmin.ini");
+
+ public static string Client = @"S:\Patch\";
+ public static string Host = @"ftp://127.0.0.1/";
+ public static string Login = string.Empty;
+ public static string Password = string.Empty;
+ public static string Protocol = "Ftp";
+
+ public static bool AllowCleanUp = true;
+ public static bool CompressFiles = false;
+
+ public static void Load()
+ {
+ Client = Reader.ReadString("AutoPatcher", "Client", Client);
+ Host = Reader.ReadString("AutoPatcher", "Host", Host);
+ Login = Reader.ReadString("AutoPatcher", "Login", Login);
+ Password = Reader.ReadString("AutoPatcher", "Password", Password);
+ Protocol = Reader.ReadString("AutoPatcher", "Protocol", Protocol);
+
+ AllowCleanUp = Reader.ReadBoolean("AutoPatcher", "AllowCleanUp", AllowCleanUp);
+ CompressFiles = Reader.ReadBoolean("AutoPatcher", "CompressFiles", CompressFiles);
+ }
+
+ public static void Save()
+ {
+ Reader.Write("AutoPatcher", "Client", Client);
+ Reader.Write("AutoPatcher", "Host", Host);
+ Reader.Write("AutoPatcher", "Login", Login);
+ Reader.Write("AutoPatcher", "Password", Password);
+ Reader.Write("AutoPatcher", "Protocol", Protocol);
+
+ Reader.Write("AutoPatcher", "AllowCleanUp", AllowCleanUp);
+ Reader.Write("AutoPatcher", "CompressFiles", CompressFiles);
+ }
+ }
+}
diff --git a/Client/Client.csproj b/Client/Client.csproj
new file mode 100644
index 0000000..933f7f2
--- /dev/null
+++ b/Client/Client.csproj
@@ -0,0 +1,92 @@
+
+
+
+ WinExe
+ net8.0-windows7.0
+ disable
+ true
+ enable
+ MIR1.ICO
+
+ True
+ x64
+ ..\Build\Client\
+
+
+
+ false
+ false
+ MIR1.ICO
+ git
+ LOMCN
+
+
+
+ True
+ 1701;1702
+
+
+
+ True
+ 1701;1702
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\Components\SlimDX.dll
+
+
+
+
+
+ True
+ True
+ Images.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Images.Designer.cs
+
+
+
+
+
+
+ Always
+ True
+ \
+
+
+
+
\ No newline at end of file
diff --git a/Client/Forms/AMain.Designer.cs b/Client/Forms/AMain.Designer.cs
new file mode 100644
index 0000000..142b84e
--- /dev/null
+++ b/Client/Forms/AMain.Designer.cs
@@ -0,0 +1,424 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.IO.Compression;
+using System.Net;
+using System.Windows.Forms;
+using System.Drawing;
+
+namespace Launcher
+{
+ partial class AMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AMain));
+ ActionLabel = new Label();
+ SpeedLabel = new Label();
+ InterfaceTimer = new System.Windows.Forms.Timer(components);
+ Movement_panel = new Panel();
+ pictureBox1 = new PictureBox();
+ Close_pb = new PictureBox();
+ Config_pb = new PictureBox();
+ Name_label = new Label();
+ Version_label = new Label();
+ CurrentFile_label = new Label();
+ CurrentPercent_label = new Label();
+ TotalPercent_label = new Label();
+ Credit_label = new Label();
+ ProgTotalEnd_pb = new PictureBox();
+ ProgEnd_pb = new PictureBox();
+ ProgressCurrent_pb = new PictureBox();
+ TotalProg_pb = new PictureBox();
+ Launch_pb = new PictureBox();
+ Main_browser = new Microsoft.Web.WebView2.WinForms.WebView2();
+ Movement_panel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Close_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Config_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)ProgTotalEnd_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)ProgEnd_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)ProgressCurrent_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)TotalProg_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Launch_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Main_browser).BeginInit();
+ SuspendLayout();
+ //
+ // ActionLabel
+ //
+ ActionLabel.Anchor = AnchorStyles.Bottom;
+ ActionLabel.BackColor = Color.Transparent;
+ ActionLabel.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ ActionLabel.ForeColor = Color.Gray;
+ ActionLabel.Location = new Point(463, 450);
+ ActionLabel.Margin = new Padding(4, 0, 4, 0);
+ ActionLabel.Name = "ActionLabel";
+ ActionLabel.Size = new Size(126, 21);
+ ActionLabel.TabIndex = 4;
+ ActionLabel.Text = "1423MB/2000MB";
+ ActionLabel.TextAlign = ContentAlignment.MiddleRight;
+ ActionLabel.Visible = false;
+ ActionLabel.Click += ActionLabel_Click;
+ //
+ // SpeedLabel
+ //
+ SpeedLabel.Anchor = AnchorStyles.Bottom;
+ SpeedLabel.BackColor = Color.Transparent;
+ SpeedLabel.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ SpeedLabel.ForeColor = Color.Gray;
+ SpeedLabel.Location = new Point(326, 454);
+ SpeedLabel.Margin = new Padding(4, 0, 4, 0);
+ SpeedLabel.Name = "SpeedLabel";
+ SpeedLabel.RightToLeft = RightToLeft.No;
+ SpeedLabel.Size = new Size(83, 18);
+ SpeedLabel.TabIndex = 13;
+ SpeedLabel.Text = "Speed";
+ SpeedLabel.TextAlign = ContentAlignment.TopRight;
+ SpeedLabel.Visible = false;
+ //
+ // InterfaceTimer
+ //
+ InterfaceTimer.Enabled = true;
+ InterfaceTimer.Interval = 50;
+ InterfaceTimer.Tick += InterfaceTimer_Tick;
+ //
+ // Movement_panel
+ //
+ Movement_panel.BackColor = Color.Transparent;
+ Movement_panel.BackgroundImageLayout = ImageLayout.Center;
+ Movement_panel.Controls.Add(pictureBox1);
+ Movement_panel.Controls.Add(Close_pb);
+ Movement_panel.Controls.Add(Config_pb);
+ Movement_panel.Location = new Point(14, 6);
+ Movement_panel.Margin = new Padding(4, 3, 4, 3);
+ Movement_panel.Name = "Movement_panel";
+ Movement_panel.Size = new Size(922, 55);
+ Movement_panel.TabIndex = 21;
+ Movement_panel.MouseClick += Movement_panel_MouseClick;
+ Movement_panel.MouseDown += Movement_panel_MouseClick;
+ Movement_panel.MouseMove += Movement_panel_MouseMove;
+ Movement_panel.MouseUp += Movement_panel_MouseUp;
+ //
+ // pictureBox1
+ //
+ pictureBox1.Image = Client.Resources.Images.server_base;
+ pictureBox1.Location = new Point(358, -46);
+ pictureBox1.Margin = new Padding(4, 3, 4, 3);
+ pictureBox1.Name = "pictureBox1";
+ pictureBox1.Size = new Size(217, 23);
+ pictureBox1.TabIndex = 33;
+ pictureBox1.TabStop = false;
+ //
+ // Close_pb
+ //
+ Close_pb.BackColor = Color.Transparent;
+ Close_pb.BackgroundImageLayout = ImageLayout.Center;
+ Close_pb.Image = Client.Resources.Images.Cross_Base;
+ Close_pb.Location = new Point(720, 22);
+ Close_pb.Margin = new Padding(4, 3, 4, 3);
+ Close_pb.Name = "Close_pb";
+ Close_pb.Size = new Size(22, 23);
+ Close_pb.TabIndex = 20;
+ Close_pb.TabStop = false;
+ Close_pb.Click += Close_pb_Click;
+ Close_pb.MouseDown += Close_pb_MouseDown;
+ Close_pb.MouseEnter += Close_pb_MouseEnter;
+ Close_pb.MouseLeave += Close_pb_MouseLeave;
+ Close_pb.MouseUp += Close_pb_MouseUp;
+ //
+ // Config_pb
+ //
+ Config_pb.BackColor = Color.Transparent;
+ Config_pb.BackgroundImageLayout = ImageLayout.Center;
+ Config_pb.Image = Client.Resources.Images.Config_Base;
+ Config_pb.Location = new Point(690, 22);
+ Config_pb.Margin = new Padding(4, 3, 4, 3);
+ Config_pb.Name = "Config_pb";
+ Config_pb.Size = new Size(22, 23);
+ Config_pb.TabIndex = 32;
+ Config_pb.TabStop = false;
+ Config_pb.Click += Config_pb_Click;
+ Config_pb.MouseDown += Config_pb_MouseDown;
+ Config_pb.MouseEnter += Config_pb_MouseEnter;
+ Config_pb.MouseLeave += Config_pb_MouseLeave;
+ Config_pb.MouseUp += Config_pb_MouseUp;
+ //
+ // Name_label
+ //
+ Name_label.BackColor = Color.Transparent;
+ Name_label.Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ Name_label.ForeColor = Color.SaddleBrown;
+ Name_label.Image = Client.Resources.Images.server_base;
+ Name_label.Location = new Point(258, 26);
+ Name_label.Margin = new Padding(4, 0, 4, 0);
+ Name_label.Name = "Name_label";
+ Name_label.Size = new Size(320, 25);
+ Name_label.TabIndex = 0;
+ Name_label.Text = "The Legend of Mir 1 - Battle of the King";
+ Name_label.TextAlign = ContentAlignment.MiddleCenter;
+ Name_label.Visible = false;
+ //
+ // Version_label
+ //
+ Version_label.Anchor = AnchorStyles.Bottom;
+ Version_label.BackColor = Color.Transparent;
+ Version_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ Version_label.ForeColor = Color.Gray;
+ Version_label.Location = new Point(633, 514);
+ Version_label.Margin = new Padding(4, 0, 4, 0);
+ Version_label.Name = "Version_label";
+ Version_label.Size = new Size(143, 15);
+ Version_label.TabIndex = 31;
+ Version_label.Text = "Version 1.0.0.0";
+ Version_label.TextAlign = ContentAlignment.TopRight;
+ //
+ // CurrentFile_label
+ //
+ CurrentFile_label.Anchor = AnchorStyles.Bottom;
+ CurrentFile_label.BackColor = Color.Transparent;
+ CurrentFile_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ CurrentFile_label.ForeColor = Color.Gray;
+ CurrentFile_label.Location = new Point(47, 450);
+ CurrentFile_label.Margin = new Padding(4, 0, 4, 0);
+ CurrentFile_label.Name = "CurrentFile_label";
+ CurrentFile_label.Size = new Size(422, 20);
+ CurrentFile_label.TabIndex = 27;
+ CurrentFile_label.Text = "Checking Files.";
+ CurrentFile_label.TextAlign = ContentAlignment.MiddleLeft;
+ CurrentFile_label.Visible = false;
+ //
+ // CurrentPercent_label
+ //
+ CurrentPercent_label.Anchor = AnchorStyles.Bottom;
+ CurrentPercent_label.BackColor = Color.Transparent;
+ CurrentPercent_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ CurrentPercent_label.ForeColor = Color.Gray;
+ CurrentPercent_label.Location = new Point(604, 468);
+ CurrentPercent_label.Margin = new Padding(4, 0, 4, 0);
+ CurrentPercent_label.Name = "CurrentPercent_label";
+ CurrentPercent_label.Size = new Size(41, 23);
+ CurrentPercent_label.TabIndex = 28;
+ CurrentPercent_label.Text = "100%";
+ CurrentPercent_label.TextAlign = ContentAlignment.MiddleCenter;
+ CurrentPercent_label.Visible = false;
+ //
+ // TotalPercent_label
+ //
+ TotalPercent_label.Anchor = AnchorStyles.Bottom;
+ TotalPercent_label.BackColor = Color.Transparent;
+ TotalPercent_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ TotalPercent_label.ForeColor = Color.Gray;
+ TotalPercent_label.Location = new Point(604, 489);
+ TotalPercent_label.Margin = new Padding(4, 0, 4, 0);
+ TotalPercent_label.Name = "TotalPercent_label";
+ TotalPercent_label.Size = new Size(41, 23);
+ TotalPercent_label.TabIndex = 29;
+ TotalPercent_label.Text = "100%";
+ TotalPercent_label.TextAlign = ContentAlignment.MiddleCenter;
+ TotalPercent_label.Visible = false;
+ //
+ // Credit_label
+ //
+ Credit_label.Anchor = AnchorStyles.Bottom;
+ Credit_label.AutoSize = true;
+ Credit_label.BackColor = Color.Transparent;
+ Credit_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ Credit_label.ForeColor = Color.Gray;
+ Credit_label.Location = new Point(45, 514);
+ Credit_label.Margin = new Padding(4, 0, 4, 0);
+ Credit_label.Name = "Credit_label";
+ Credit_label.Size = new Size(98, 13);
+ Credit_label.TabIndex = 30;
+ Credit_label.Text = "Powered by Carbon";
+ Credit_label.Click += Credit_label_Click;
+ //
+ // ProgTotalEnd_pb
+ //
+ ProgTotalEnd_pb.Anchor = AnchorStyles.None;
+ ProgTotalEnd_pb.BackColor = Color.Transparent;
+ ProgTotalEnd_pb.BackgroundImageLayout = ImageLayout.Center;
+ ProgTotalEnd_pb.Image = Client.Resources.Images.NEW_Progress_End__Blue_;
+ ProgTotalEnd_pb.Location = new Point(585, 491);
+ ProgTotalEnd_pb.Margin = new Padding(4, 3, 4, 3);
+ ProgTotalEnd_pb.Name = "ProgTotalEnd_pb";
+ ProgTotalEnd_pb.Size = new Size(5, 17);
+ ProgTotalEnd_pb.TabIndex = 26;
+ ProgTotalEnd_pb.TabStop = false;
+ //
+ // ProgEnd_pb
+ //
+ ProgEnd_pb.Anchor = AnchorStyles.None;
+ ProgEnd_pb.BackColor = Color.Transparent;
+ ProgEnd_pb.BackgroundImageLayout = ImageLayout.Center;
+ ProgEnd_pb.Image = Client.Resources.Images.NEW_Progress_End__Green_;
+ ProgEnd_pb.Location = new Point(585, 474);
+ ProgEnd_pb.Margin = new Padding(4, 3, 4, 3);
+ ProgEnd_pb.Name = "ProgEnd_pb";
+ ProgEnd_pb.Size = new Size(5, 17);
+ ProgEnd_pb.TabIndex = 25;
+ ProgEnd_pb.TabStop = false;
+ //
+ // ProgressCurrent_pb
+ //
+ ProgressCurrent_pb.Anchor = AnchorStyles.None;
+ ProgressCurrent_pb.BackColor = Color.Transparent;
+ ProgressCurrent_pb.BackgroundImageLayout = ImageLayout.Center;
+ ProgressCurrent_pb.Image = Client.Resources.Images.Green_Progress;
+ ProgressCurrent_pb.Location = new Point(45, 474);
+ ProgressCurrent_pb.Margin = new Padding(4, 3, 4, 3);
+ ProgressCurrent_pb.Name = "ProgressCurrent_pb";
+ ProgressCurrent_pb.Size = new Size(557, 17);
+ ProgressCurrent_pb.TabIndex = 23;
+ ProgressCurrent_pb.TabStop = false;
+ ProgressCurrent_pb.SizeChanged += ProgressCurrent_pb_SizeChanged;
+ //
+ // TotalProg_pb
+ //
+ TotalProg_pb.Anchor = AnchorStyles.None;
+ TotalProg_pb.BackColor = Color.Transparent;
+ TotalProg_pb.BackgroundImageLayout = ImageLayout.Center;
+ TotalProg_pb.Image = Client.Resources.Images.Blue_Progress;
+ TotalProg_pb.Location = new Point(45, 491);
+ TotalProg_pb.Margin = new Padding(4, 3, 4, 3);
+ TotalProg_pb.Name = "TotalProg_pb";
+ TotalProg_pb.Size = new Size(558, 16);
+ TotalProg_pb.TabIndex = 22;
+ TotalProg_pb.TabStop = false;
+ TotalProg_pb.SizeChanged += TotalProg_pb_SizeChanged;
+ //
+ // Launch_pb
+ //
+ Launch_pb.Anchor = AnchorStyles.Bottom;
+ Launch_pb.BackColor = Color.Transparent;
+ Launch_pb.BackgroundImageLayout = ImageLayout.Stretch;
+ Launch_pb.Cursor = Cursors.Hand;
+ Launch_pb.Image = Client.Resources.Images.Launch_Base1;
+ Launch_pb.Location = new Point(660, 476);
+ Launch_pb.Margin = new Padding(4, 3, 4, 3);
+ Launch_pb.Name = "Launch_pb";
+ Launch_pb.Size = new Size(131, 56);
+ Launch_pb.TabIndex = 19;
+ Launch_pb.TabStop = false;
+ Launch_pb.Click += Launch_pb_Click;
+ Launch_pb.MouseDown += Launch_pb_MouseDown;
+ Launch_pb.MouseEnter += Launch_pb_MouseEnter;
+ Launch_pb.MouseLeave += Launch_pb_MouseLeave;
+ Launch_pb.MouseUp += Launch_pb_MouseUp;
+ //
+ // Main_browser
+ //
+ Main_browser.AllowExternalDrop = true;
+ Main_browser.CausesValidation = false;
+ Main_browser.CreationProperties = null;
+ Main_browser.DefaultBackgroundColor = Color.Transparent;
+ Main_browser.Enabled = false;
+ Main_browser.Location = new Point(410, 162);
+ Main_browser.Margin = new Padding(4, 3, 4, 3);
+ Main_browser.MaximumSize = new Size(782, 403);
+ Main_browser.Name = "Main_browser";
+ Main_browser.Size = new Size(338, 285);
+ Main_browser.TabIndex = 32;
+ Main_browser.Visible = false;
+ Main_browser.ZoomFactor = 1D;
+ //
+ // AMain
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ BackColor = SystemColors.ActiveCaption;
+ BackgroundImage = Client.Resources.Images.pfffft;
+ BackgroundImageLayout = ImageLayout.Center;
+ ClientSize = new Size(804, 558);
+ Controls.Add(Name_label);
+ Controls.Add(Main_browser);
+ Controls.Add(SpeedLabel);
+ Controls.Add(Credit_label);
+ Controls.Add(Version_label);
+ Controls.Add(TotalPercent_label);
+ Controls.Add(CurrentPercent_label);
+ Controls.Add(CurrentFile_label);
+ Controls.Add(ProgTotalEnd_pb);
+ Controls.Add(ProgEnd_pb);
+ Controls.Add(ProgressCurrent_pb);
+ Controls.Add(TotalProg_pb);
+ Controls.Add(Launch_pb);
+ Controls.Add(ActionLabel);
+ Controls.Add(Movement_panel);
+ DoubleBuffered = true;
+ ForeColor = SystemColors.ControlText;
+ FormBorderStyle = FormBorderStyle.None;
+ Icon = (Icon)resources.GetObject("$this.Icon");
+ Margin = new Padding(4, 3, 4, 3);
+ MaximizeBox = false;
+ MinimizeBox = false;
+ Name = "AMain";
+ StartPosition = FormStartPosition.CenterScreen;
+ Text = "Launcher";
+ TransparencyKey = Color.Black;
+ FormClosed += AMain_FormClosed;
+ Load += AMain_Load;
+ Click += AMain_Click;
+ Movement_panel.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Close_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Config_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)ProgTotalEnd_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)ProgEnd_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)ProgressCurrent_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)TotalProg_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Launch_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Main_browser).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+ private Label ActionLabel;
+ private Label SpeedLabel;
+ public System.Windows.Forms.Timer InterfaceTimer;
+ public PictureBox Launch_pb;
+ private PictureBox Close_pb;
+ private Panel Movement_panel;
+ private PictureBox TotalProg_pb;
+ private PictureBox ProgressCurrent_pb;
+ private Label Name_label;
+ private PictureBox ProgEnd_pb;
+ private PictureBox ProgTotalEnd_pb;
+ private Label CurrentFile_label;
+ private Label CurrentPercent_label;
+ private Label TotalPercent_label;
+ private Label Credit_label;
+ private Label Version_label;
+ private PictureBox Config_pb;
+ private PictureBox pictureBox1;
+ private Microsoft.Web.WebView2.WinForms.WebView2 Main_browser;
+ }
+}
+
diff --git a/Client/Forms/AMain.cs b/Client/Forms/AMain.cs
new file mode 100644
index 0000000..7a97bf0
--- /dev/null
+++ b/Client/Forms/AMain.cs
@@ -0,0 +1,712 @@
+using System.Diagnostics;
+using System.IO.Compression;
+using System.Net;
+using Client;
+using Microsoft.Web.WebView2.Core;
+using System.Net.Http.Headers;
+using System.Net.Http.Handlers;
+using Client.Utils;
+
+namespace Launcher
+{
+ public partial class AMain : Form
+ {
+ long _totalBytes, _completedBytes;
+ private int _fileCount, _currentCount;
+
+ public bool Completed, Checked, CleanFiles, LabelSwitch, ErrorFound;
+
+ public List OldList;
+ public Queue DownloadList = new Queue();
+ public List ActiveDownloads = new List();
+
+ private Stopwatch _stopwatch = Stopwatch.StartNew();
+
+ public Thread _workThread;
+
+ private bool dragging = false;
+ private Point dragCursorPoint;
+ private Point dragFormPoint;
+
+ private Config ConfigForm = new Config();
+
+ private bool Restart = false;
+
+ public AMain()
+ {
+ InitializeComponent();
+
+ BackColor = Color.FromArgb(1, 0, 0);
+ TransparencyKey = Color.FromArgb(1, 0, 0);
+ }
+
+ public static void SaveError(string ex)
+ {
+ try
+ {
+ if (Settings.RemainingErrorLogs-- > 0)
+ {
+ File.AppendAllText(@".\Error.txt",
+ string.Format("[{0}] {1}{2}", DateTime.Now, ex, Environment.NewLine));
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ public void Start()
+ {
+ try
+ {
+ GetOldFileList();
+
+ if (OldList.Count == 0)
+ {
+ MessageBox.Show(GameLanguage.PatchErr);
+ Completed = true;
+ return;
+ }
+
+ _fileCount = OldList.Count;
+ for (int i = 0; i < OldList.Count; i++)
+ CheckFile(OldList[i]);
+
+ Checked = true;
+ _fileCount = 0;
+ _currentCount = 0;
+
+ _fileCount = DownloadList.Count;
+
+ ServicePointManager.DefaultConnectionLimit = Settings.P_Concurrency;
+
+ _stopwatch = Stopwatch.StartNew();
+ for (var i = 0; i < Settings.P_Concurrency; i++)
+ BeginDownload();
+
+
+ }
+ catch (EndOfStreamException ex)
+ {
+ MessageBox.Show("End of stream found. Host is likely using a pre version 1.1.0.0 patch system");
+ Completed = true;
+ SaveError(ex.ToString());
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.ToString(), "Error");
+ Completed = true;
+ SaveError(ex.ToString());
+ }
+
+ _stopwatch.Stop();
+ }
+
+ private void BeginDownload()
+ {
+ if (DownloadList.Count == 0)
+ {
+ Completed = true;
+
+ CleanUp();
+ return;
+ }
+
+ var download = new Download();
+ download.Info = DownloadList.Dequeue();
+
+ DownloadFile(download);
+ }
+
+ private void CleanUp()
+ {
+ if (!CleanFiles) return;
+
+ string[] fileNames = Directory.GetFiles(@".\", "*.*", SearchOption.AllDirectories);
+ string fileName;
+ for (int i = 0; i < fileNames.Length; i++)
+ {
+ if (fileNames[i].StartsWith(".\\Screenshots\\")) continue;
+
+ fileName = Path.GetFileName(fileNames[i]);
+
+ if (fileName == "Mir1Config.ini" || fileName == System.AppDomain.CurrentDomain.FriendlyName) continue;
+
+ try
+ {
+ if (!NeedFile(fileNames[i]))
+ File.Delete(fileNames[i]);
+ }
+ catch { }
+ }
+ }
+ public bool NeedFile(string fileName)
+ {
+ for (int i = 0; i < OldList.Count; i++)
+ {
+ if (fileName.EndsWith(OldList[i].FileName))
+ return true;
+ }
+
+ return false;
+ }
+
+ private void GetOldFileList()
+ {
+ OldList = new List();
+
+ byte[] data = Download(Settings.P_PatchFileName);
+ if (data != null)
+ {
+ using MemoryStream stream = new MemoryStream(data);
+ using BinaryReader reader = new BinaryReader(stream);
+
+ int count = reader.ReadInt32();
+
+ for (int i = 0; i < count; i++)
+ {
+ OldList.Add(new FileInformation(reader));
+ }
+ }
+ }
+
+
+ public void ParseOld(BinaryReader reader)
+ {
+ int count = reader.ReadInt32();
+
+ for (int i = 0; i < count; i++)
+ OldList.Add(new FileInformation(reader));
+ }
+
+ public void CheckFile(FileInformation old)
+ {
+ FileInformation info = GetFileInformation(Settings.P_Client + old.FileName);
+ _currentCount++;
+
+ if (info == null || old.Length != info.Length || old.Creation != info.Creation)
+ {
+ if (info != null && (Path.GetExtension(old.FileName).ToLower() == ".dll" || Path.GetExtension(old.FileName).ToLower() == ".exe"))
+ {
+ string oldFilename = Path.Combine(Path.GetDirectoryName(old.FileName), ("Old__" + Path.GetFileName(old.FileName)));
+
+ try
+ {
+ File.Move(Settings.P_Client + old.FileName, oldFilename);
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ SaveError(ex.ToString());
+ }
+ finally
+ {
+ //Might cause an infinite loop if it can never gain access
+ Restart = true;
+ }
+ }
+
+ DownloadList.Enqueue(old);
+ _totalBytes += old.Length;
+ }
+ }
+
+ public void DownloadFile(Download dl)
+ {
+ var info = dl.Info;
+ string fileName = info.FileName.Replace(@"\", "/");
+
+ if (fileName != "PList.gz" && (info.Compressed != info.Length || info.Compressed == 0))
+ {
+ fileName += ".gz";
+ }
+
+ try
+ {
+ HttpClientHandler httpClientHandler = new() { AllowAutoRedirect = true };
+ ProgressMessageHandler progressMessageHandler = new(httpClientHandler);
+
+ progressMessageHandler.HttpReceiveProgress += (_, args) =>
+ {
+
+ dl.CurrentBytes = args.BytesTransferred;
+
+ };
+
+ using (HttpClient client = new(progressMessageHandler))
+ {
+ client.DefaultRequestHeaders.Accept.Clear();
+ client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ client.DefaultRequestHeaders.AcceptCharset.Clear();
+ client.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
+
+ if (Settings.P_NeedLogin)
+ {
+ string authInfo = Settings.P_Login + ":" + Settings.P_Password;
+ authInfo = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(authInfo));
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
+ }
+
+ ActiveDownloads.Add(dl);
+
+ var task = Task.Run(() => client
+ .GetAsync(new Uri($"{Settings.P_Host}{fileName}"), HttpCompletionOption.ResponseHeadersRead));
+
+ var response = task.Result;
+
+ using Stream sm = response.Content.ReadAsStream();
+ using MemoryStream ms = new();
+ sm.CopyTo(ms);
+ byte[] data = ms.ToArray();
+
+ _currentCount++;
+ _completedBytes += dl.CurrentBytes;
+ dl.CurrentBytes = 0;
+ dl.Completed = true;
+
+ if (info.Compressed > 0 && info.Compressed != info.Length)
+ {
+ data = Decompress(data);
+ }
+
+ var fileNameOut = Settings.P_Client + info.FileName;
+ var dirName = Path.GetDirectoryName(fileNameOut);
+ if (!Directory.Exists(dirName))
+ Directory.CreateDirectory(dirName);
+
+ File.WriteAllBytes(fileNameOut, data);
+ File.SetLastWriteTime(fileNameOut, info.Creation);
+ }
+ }
+ catch (HttpRequestException e)
+ {
+ File.AppendAllText(@".\Error.txt",
+ $"[{DateTime.Now}] {info.FileName} could not be downloaded. ({e.Message}) {Environment.NewLine}");
+ ErrorFound = true;
+ }
+ finally
+ {
+ if (ErrorFound)
+ {
+ MessageBox.Show(string.Format("Failed to download file: {0}", fileName));
+ }
+ }
+
+ BeginDownload();
+ }
+
+ public byte[] Download(string fileName)
+ {
+ using (HttpClient client = new())
+ {
+ client.DefaultRequestHeaders.Accept.Clear();
+ client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ client.DefaultRequestHeaders.AcceptCharset.Clear();
+ client.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
+
+ if (Settings.P_NeedLogin)
+ {
+ string authInfo = Settings.P_Login + ":" + Settings.P_Password;
+ authInfo = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(authInfo));
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
+ }
+
+ var task = Task.Run(() => client
+ .GetAsync(new Uri(Settings.P_Host + Path.ChangeExtension(fileName, ".gz")), HttpCompletionOption.ResponseHeadersRead));
+
+ var response = task.Result;
+
+ using Stream sm = response.Content.ReadAsStream();
+ using MemoryStream ms = new();
+ sm.CopyTo(ms);
+ byte[] data = ms.ToArray();
+ return data;
+ }
+ }
+
+ public static byte[] Decompress(byte[] raw)
+ {
+ using (GZipStream gStream = new GZipStream(new MemoryStream(raw), CompressionMode.Decompress))
+ {
+ const int size = 4096; //4kb
+ byte[] buffer = new byte[size];
+ using (MemoryStream mStream = new MemoryStream())
+ {
+ int count;
+ do
+ {
+ count = gStream.Read(buffer, 0, size);
+ if (count > 0)
+ {
+ mStream.Write(buffer, 0, count);
+ }
+ } while (count > 0);
+ return mStream.ToArray();
+ }
+ }
+ }
+
+ public static byte[] Compress(byte[] raw)
+ {
+ using (MemoryStream mStream = new MemoryStream())
+ {
+ using (GZipStream gStream = new GZipStream(mStream, CompressionMode.Compress, true))
+ gStream.Write(raw, 0, raw.Length);
+ return mStream.ToArray();
+ }
+ }
+
+ public FileInformation GetFileInformation(string fileName)
+ {
+ if (!File.Exists(fileName)) return null;
+
+ FileInfo info = new FileInfo(fileName);
+ return new FileInformation
+ {
+ FileName = fileName.Remove(0, Settings.P_Client.Length),
+ Length = (int)info.Length,
+ Creation = info.LastWriteTime
+ };
+ }
+
+ private void AMain_Load(object sender, EventArgs e)
+ {
+ var envir = CoreWebView2Environment.CreateAsync(null, Settings.ResourcePath).Result;
+ Main_browser.EnsureCoreWebView2Async(envir);
+
+ if (Settings.P_BrowserAddress != "")
+ {
+ Main_browser.NavigationCompleted += Main_browser_NavigationCompleted;
+ Main_browser.Source = new Uri(Settings.P_BrowserAddress);
+ }
+
+ RepairOldFiles();
+
+ Launch_pb.Enabled = false;
+ ProgressCurrent_pb.Width = 5;
+ TotalProg_pb.Width = 5;
+ Version_label.Text = string.Format("Build: {0}.{1}.{2}", Globals.ProductCodename, Settings.UseTestConfig ? "Debug" : "Release", Application.ProductVersion);
+
+ if (Settings.P_ServerName != String.Empty)
+ {
+ Name_label.Visible = true;
+ Name_label.Text = Settings.P_ServerName;
+ }
+
+ _workThread = new Thread(Start) { IsBackground = true };
+ _workThread.Start();
+ }
+
+ private void Main_browser_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
+ {
+ if (Main_browser.Source.AbsolutePath != "blank") Main_browser.Visible = true;
+ }
+
+ private void Launch_pb_Click(object sender, EventArgs e)
+ {
+ Launch();
+ }
+
+ private void Launch()
+ {
+ if (ConfigForm.Visible) ConfigForm.Visible = false;
+ Program.Form = new CMain();
+ Program.Form.Closed += (s, args) => this.Close();
+ Program.Form.Show();
+ Program.PForm.Hide();
+ }
+
+ private void Close_pb_Click(object sender, EventArgs e)
+ {
+ if (ConfigForm.Visible) ConfigForm.Visible = false;
+ Close();
+ }
+
+ private void Movement_panel_MouseClick(object sender, MouseEventArgs e)
+ {
+ if (ConfigForm.Visible) ConfigForm.Visible = false;
+ dragging = true;
+ dragCursorPoint = Cursor.Position;
+ dragFormPoint = this.Location;
+ }
+
+ private void Movement_panel_MouseUp(object sender, MouseEventArgs e)
+ {
+ dragging = false;
+ }
+
+ private void Movement_panel_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (dragging)
+ {
+ Point dif = Point.Subtract(Cursor.Position, new Size(dragCursorPoint));
+ this.Location = Point.Add(dragFormPoint, new Size(dif));
+ }
+ }
+
+ private void Launch_pb_MouseEnter(object sender, EventArgs e)
+ {
+ Launch_pb.Image = Client.Resources.Images.Launch_Hover;
+ }
+
+ private void Launch_pb_MouseLeave(object sender, EventArgs e)
+ {
+ Launch_pb.Image = Client.Resources.Images.Launch_Base1;
+ }
+
+ private void Close_pb_MouseEnter(object sender, EventArgs e)
+ {
+ Close_pb.Image = Client.Resources.Images.Cross_Hover;
+ }
+
+ private void Close_pb_MouseLeave(object sender, EventArgs e)
+ {
+ Close_pb.Image = Client.Resources.Images.Cross_Base;
+ }
+
+ private void Launch_pb_MouseDown(object sender, MouseEventArgs e)
+ {
+ Launch_pb.Image = Client.Resources.Images.Launch_Pressed;
+ }
+
+ private void Launch_pb_MouseUp(object sender, MouseEventArgs e)
+ {
+ Launch_pb.Image = Client.Resources.Images.Launch_Base1;
+ }
+
+ private void Close_pb_MouseDown(object sender, MouseEventArgs e)
+ {
+ Close_pb.Image = Client.Resources.Images.Cross_Pressed;
+ }
+
+ private void Close_pb_MouseUp(object sender, MouseEventArgs e)
+ {
+ Close_pb.Image = Client.Resources.Images.Cross_Base;
+ }
+
+ private void ProgressCurrent_pb_SizeChanged(object sender, EventArgs e)
+ {
+ ProgEnd_pb.Location = new Point((ProgressCurrent_pb.Location.X + ProgressCurrent_pb.Width), ProgressCurrent_pb.Location.Y);
+ if (ProgressCurrent_pb.Width == 0) ProgEnd_pb.Visible = false;
+ else ProgEnd_pb.Visible = true;
+ }
+
+ private void Config_pb_MouseDown(object sender, MouseEventArgs e)
+ {
+ Config_pb.Image = Client.Resources.Images.Config_Pressed;
+ }
+
+ private void Config_pb_MouseEnter(object sender, EventArgs e)
+ {
+ Config_pb.Image = Client.Resources.Images.Config_Hover;
+ }
+
+ private void Config_pb_MouseLeave(object sender, EventArgs e)
+ {
+ Config_pb.Image = Client.Resources.Images.Config_Base;
+ }
+
+ private void Config_pb_MouseUp(object sender, MouseEventArgs e)
+ {
+ Config_pb.Image = Client.Resources.Images.Config_Base;
+ }
+
+ private void Config_pb_Click(object sender, EventArgs e)
+ {
+ if (ConfigForm.Visible) ConfigForm.Hide();
+ else ConfigForm.Show(Program.PForm);
+ ConfigForm.Location = new Point(Location.X + Config_pb.Location.X - 183, Location.Y + 36);
+ }
+
+ private void TotalProg_pb_SizeChanged(object sender, EventArgs e)
+ {
+ ProgTotalEnd_pb.Location = new Point((TotalProg_pb.Location.X + TotalProg_pb.Width), TotalProg_pb.Location.Y);
+ if (TotalProg_pb.Width == 0) ProgTotalEnd_pb.Visible = false;
+ else ProgTotalEnd_pb.Visible = true;
+ }
+
+ private void InterfaceTimer_Tick(object sender, EventArgs e)
+ {
+ try
+ {
+ if (Completed)
+ {
+
+ ActionLabel.Text = "";
+ CurrentFile_label.Text = "Up to date.";
+ SpeedLabel.Text = "";
+ ProgressCurrent_pb.Width = 550;
+ TotalProg_pb.Width = 550;
+ CurrentFile_label.Visible = true;
+ CurrentPercent_label.Visible = true;
+ TotalPercent_label.Visible = true;
+ CurrentPercent_label.Text = "100%";
+ TotalPercent_label.Text = "100%";
+ InterfaceTimer.Enabled = false;
+ Launch_pb.Enabled = true;
+ if (ErrorFound) MessageBox.Show("One or more files failed to download, check Error.txt for details.", "Failed to Download.");
+ ErrorFound = false;
+
+ if (CleanFiles)
+ {
+ CleanFiles = false;
+ MessageBox.Show("Your files have been cleaned up.", "Clean Files");
+ }
+
+ if (Restart)
+ {
+ Program.Restart = true;
+
+ MoveOldFilesToCurrent();
+
+ Close();
+ }
+
+ if (Settings.P_AutoStart)
+ {
+ Launch();
+ }
+ return;
+ }
+
+ var currentBytes = 0L;
+ FileInformation currentFile = null;
+
+ // Remove completed downloads..
+ for (var i = ActiveDownloads.Count - 1; i >= 0; i--)
+ {
+ var dl = ActiveDownloads[i];
+
+ if (dl.Completed)
+ {
+ ActiveDownloads.RemoveAt(i);
+ continue;
+ }
+ }
+
+ for (var i = ActiveDownloads.Count - 1; i >= 0; i--)
+ {
+ var dl = ActiveDownloads[i];
+ if (!dl.Completed)
+ currentBytes += dl.CurrentBytes;
+ }
+
+ if (Settings.P_Concurrency == 1)
+ {
+ // Note: Just mimic old behaviour for now until a better UI is done.
+ if (ActiveDownloads.Count > 0)
+ currentFile = ActiveDownloads[0].Info;
+ }
+
+ ActionLabel.Visible = true;
+ SpeedLabel.Visible = true;
+ CurrentFile_label.Visible = true;
+ CurrentPercent_label.Visible = true;
+ TotalPercent_label.Visible = true;
+
+ if (LabelSwitch) ActionLabel.Text = string.Format("{0} Files Remaining", _fileCount - _currentCount);
+ else ActionLabel.Text = string.Format("{0:#,##0}MB Remaining", ((_totalBytes) - (_completedBytes + currentBytes)) / 1024 / 1024);
+
+ if (Settings.P_Concurrency > 1)
+ {
+ CurrentFile_label.Text = string.Format(" {0}", ActiveDownloads.Count);
+ SpeedLabel.Text = ToSize(currentBytes / _stopwatch.Elapsed.TotalSeconds);
+ }
+ else
+ {
+ if (currentFile != null)
+ {
+ CurrentFile_label.Text = string.Format("{0}", currentFile.FileName);
+ SpeedLabel.Text = ToSize(currentBytes / _stopwatch.Elapsed.TotalSeconds);
+ CurrentPercent_label.Text = ((int)(100 * currentBytes / currentFile.Length)).ToString() + "%";
+ ProgressCurrent_pb.Width = (int)(5.5 * (100 * currentBytes / currentFile.Length));
+ }
+ }
+
+ if (!(_completedBytes is 0 && currentBytes is 0 && _totalBytes is 0))
+ {
+ TotalProg_pb.Width = (int)(5.5 * (100 * (_completedBytes + currentBytes) / _totalBytes));
+ TotalPercent_label.Text = ((int)(100 * (_completedBytes + currentBytes) / _totalBytes)).ToString() + "%";
+ }
+
+ }
+ catch
+ {
+ //to-do
+ }
+
+ }
+
+ private void AMain_Click(object sender, EventArgs e)
+ {
+ if (ConfigForm.Visible) ConfigForm.Visible = false;
+ }
+
+ private void ActionLabel_Click(object sender, EventArgs e)
+ {
+ LabelSwitch = !LabelSwitch;
+ }
+
+ private void Credit_label_Click(object sender, EventArgs e)
+ {
+ if (Credit_label.Text == "Powered by Carbon") Credit_label.Text = "Designed by Jev";
+ else Credit_label.Text = "Powered by Carbon";
+ }
+
+ private void AMain_FormClosed(object sender, FormClosedEventArgs e)
+ {
+ MoveOldFilesToCurrent();
+
+ Launch_pb?.Dispose();
+ Close_pb?.Dispose();
+ Environment.Exit(0);
+ }
+
+ private static string[] suffixes = new[] { " B", " KB", " MB", " GB", " TB", " PB" };
+
+ private string ToSize(double number, int precision = 2)
+ {
+ // unit's number of bytes
+ const double unit = 1024;
+ // suffix counter
+ int i = 0;
+ // as long as we're bigger than a unit, keep going
+ while (number > unit)
+ {
+ number /= unit;
+ i++;
+ }
+ // apply precision and current suffix
+ return Math.Round(number, precision) + suffixes[i];
+ }
+
+ private void RepairOldFiles()
+ {
+ var files = Directory.GetFiles(Settings.P_Client, "*", SearchOption.AllDirectories).Where(x => Path.GetFileName(x).StartsWith("Old__"));
+
+ foreach (var oldFilename in files)
+ {
+ if (!File.Exists(oldFilename.Replace("Old__", "")))
+ {
+ File.Move(oldFilename, oldFilename.Replace("Old__", ""));
+ }
+ else
+ {
+ File.Delete(oldFilename);
+ }
+ }
+ }
+
+ private void MoveOldFilesToCurrent()
+ {
+ var files = Directory.GetFiles(Settings.P_Client, "*", SearchOption.AllDirectories).Where(x => Path.GetFileName(x).StartsWith("Old__"));
+
+ foreach (var oldFilename in files)
+ {
+ string originalFilename = Path.Combine(Path.GetDirectoryName(oldFilename), (Path.GetFileName(oldFilename).Replace("Old__", "")));
+
+ if (!File.Exists(originalFilename) && File.Exists(oldFilename))
+ File.Move(oldFilename, originalFilename);
+ }
+ }
+ }
+}
diff --git a/Client/Forms/AMain.resx b/Client/Forms/AMain.resx
new file mode 100644
index 0000000..d5b6dd4
--- /dev/null
+++ b/Client/Forms/AMain.resx
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ 17, 17
+
+
+
+ 25
+
+
+
+ ..\Resources\$this.Icon11.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/Client/Forms/CMain.Designer.cs b/Client/Forms/CMain.Designer.cs
new file mode 100644
index 0000000..6861753
--- /dev/null
+++ b/Client/Forms/CMain.Designer.cs
@@ -0,0 +1,55 @@
+namespace Client
+{
+ partial class CMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CMain));
+ this.SuspendLayout();
+ //
+ // CMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Black;
+ this.ClientSize = new System.Drawing.Size(275, 260);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MinimumSize = new System.Drawing.Size(200, 213);
+ this.Name = "CMain";
+ this.Text = "Legend of Mir 1 - Battle of the King";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CMain_FormClosing);
+ this.Load += new System.EventHandler(this.CMain_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ }
+}
+
diff --git a/Client/Forms/CMain.cs b/Client/Forms/CMain.cs
new file mode 100644
index 0000000..653c8f4
--- /dev/null
+++ b/Client/Forms/CMain.cs
@@ -0,0 +1,789 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Drawing.Text;
+using System.Runtime.InteropServices;
+using System.Security;
+using Client.MirControls;
+using Client.MirGraphics;
+using Client.MirNetwork;
+using Client.MirScenes;
+using Client.MirSounds;
+using SlimDX.Direct3D9;
+using SlimDX.Windows;
+using Font = System.Drawing.Font;
+
+namespace Client
+{
+ public partial class CMain : RenderForm
+ {
+ public static MirControl DebugBaseLabel, HintBaseLabel;
+ public static MirLabel DebugTextLabel, HintTextLabel, ScreenshotTextLabel;
+ public static Graphics Graphics;
+ public static Point MPoint;
+
+ public readonly static Stopwatch Timer = Stopwatch.StartNew();
+ public readonly static DateTime StartTime = DateTime.UtcNow;
+ public static long Time;
+ public static DateTime Now { get { return StartTime.AddMilliseconds(Time); } }
+ public static readonly Random Random = new Random();
+
+ public static string DebugText = "";
+
+ private static long _fpsTime;
+ private static int _fps;
+ private static long _cleanTime;
+ private static long _drawTime;
+ public static int FPS;
+ public static int DPS;
+ public static int DPSCounter;
+
+ public static long PingTime;
+ public static long NextPing = 10000;
+
+ public static bool Shift, Alt, Ctrl, Tilde, SpellTargetLock;
+ public static double BytesSent, BytesReceived;
+
+ public static KeyBindSettings InputKeys = new KeyBindSettings();
+
+ public CMain()
+ {
+ InitializeComponent();
+
+ Application.Idle += Application_Idle;
+
+ MouseClick += CMain_MouseClick;
+ MouseDown += CMain_MouseDown;
+ MouseUp += CMain_MouseUp;
+ MouseMove += CMain_MouseMove;
+ MouseDoubleClick += CMain_MouseDoubleClick;
+ KeyPress += CMain_KeyPress;
+ KeyDown += CMain_KeyDown;
+ KeyUp += CMain_KeyUp;
+ Deactivate += CMain_Deactivate;
+ MouseWheel += CMain_MouseWheel;
+
+
+ SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.Selectable, true);
+ FormBorderStyle = Settings.FullScreen || Settings.Borderless ? FormBorderStyle.None : FormBorderStyle.FixedDialog;
+
+ Graphics = CreateGraphics();
+ Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+ Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
+ Graphics.CompositingQuality = CompositingQuality.HighQuality;
+ Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ Graphics.TextContrast = 0;
+ }
+
+ private void CMain_Load(object sender, EventArgs e)
+ {
+ this.Text = GameLanguage.GameName;
+ try
+ {
+ ClientSize = new Size(800, 600);
+
+ LoadMouseCursors();
+ SetMouseCursor(MouseCursor.Default);
+
+ SlimDX.Configuration.EnableObjectTracking = true;
+
+ DXManager.Create();
+ SoundManager.Create();
+ CenterToScreen();
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+
+ private static void Application_Idle(object sender, EventArgs e)
+ {
+ try
+ {
+ while (AppStillIdle)
+ {
+ UpdateTime();
+ UpdateFrameTime();
+ UpdateEnviroment();
+
+ if (IsDrawTime())
+ RenderEnvironment();
+ }
+
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+
+ private static void CMain_Deactivate(object sender, EventArgs e)
+ {
+ MapControl.MapButtons = MouseButtons.None;
+ Shift = false;
+ Alt = false;
+ Ctrl = false;
+ Tilde = false;
+ SpellTargetLock = false;
+ }
+
+ public static void CMain_KeyDown(object sender, KeyEventArgs e)
+ {
+ Shift = e.Shift;
+ Alt = e.Alt;
+ Ctrl = e.Control;
+
+ if (!String.IsNullOrEmpty(InputKeys.GetKey(KeybindOptions.TargetSpellLockOn)))
+ {
+ SpellTargetLock = e.KeyCode == (Keys)Enum.Parse(typeof(Keys), InputKeys.GetKey(KeybindOptions.TargetSpellLockOn), true);
+ }
+ else
+ {
+ SpellTargetLock = false;
+ }
+
+
+ if (e.KeyCode == Keys.Oem8)
+ CMain.Tilde = true;
+
+ try
+ {
+ if (e.Alt && e.KeyCode == Keys.Enter)
+ {
+ ToggleFullScreen();
+ return;
+ }
+
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnKeyDown(e);
+
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (Settings.FullScreen || Settings.MouseClip)
+ Cursor.Clip = Program.Form.RectangleToScreen(Program.Form.ClientRectangle);
+
+ MPoint = Program.Form.PointToClient(Cursor.Position);
+
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseMove(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_KeyUp(object sender, KeyEventArgs e)
+ {
+ Shift = e.Shift;
+ Alt = e.Alt;
+ Ctrl = e.Control;
+
+ if (!String.IsNullOrEmpty(InputKeys.GetKey(KeybindOptions.TargetSpellLockOn)))
+ {
+ SpellTargetLock = e.KeyCode == (Keys)Enum.Parse(typeof(Keys), InputKeys.GetKey(KeybindOptions.TargetSpellLockOn), true);
+ }
+ else
+ {
+ SpellTargetLock = false;
+ }
+
+ if (e.KeyCode == Keys.Oem8)
+ CMain.Tilde = false;
+
+ foreach (KeyBind KeyCheck in CMain.InputKeys.Keylist)
+ {
+ if (KeyCheck.function != KeybindOptions.Screenshot) continue;
+ if (KeyCheck.Key != e.KeyCode)
+ continue;
+ if ((KeyCheck.RequireAlt != 2) && (KeyCheck.RequireAlt != (Alt ? 1 : 0)))
+ continue;
+ if ((KeyCheck.RequireShift != 2) && (KeyCheck.RequireShift != (Shift ? 1 : 0)))
+ continue;
+ if ((KeyCheck.RequireCtrl != 2) && (KeyCheck.RequireCtrl != (Ctrl ? 1 : 0)))
+ continue;
+ if ((KeyCheck.RequireTilde != 2) && (KeyCheck.RequireTilde != (Tilde ? 1 : 0)))
+ continue;
+ Program.Form.CreateScreenShot();
+ break;
+
+ }
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnKeyUp(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnKeyPress(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseDoubleClick(object sender, MouseEventArgs e)
+ {
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseClick(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseUp(object sender, MouseEventArgs e)
+ {
+ MapControl.MapButtons &= ~e.Button;
+
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseUp(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseDown(object sender, MouseEventArgs e)
+ {
+ if (Program.Form.ActiveControl is TextBox)
+ {
+ MirTextBox textBox = Program.Form.ActiveControl.Tag as MirTextBox;
+
+ if (textBox != null && textBox.CanLoseFocus)
+ Program.Form.ActiveControl = null;
+ }
+
+ if (e.Button == MouseButtons.Right && (GameScene.SelectedCell != null || GameScene.PickedUpGold))
+ {
+ GameScene.SelectedCell = null;
+ GameScene.PickedUpGold = false;
+ return;
+ }
+
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseDown(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseClick(object sender, MouseEventArgs e)
+ {
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseClick(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+ public static void CMain_MouseWheel(object sender, MouseEventArgs e)
+ {
+ try
+ {
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.OnMouseWheel(e);
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+ }
+ }
+
+ private static void UpdateTime()
+ {
+ Time = Timer.ElapsedMilliseconds;
+ }
+
+ private static void UpdateFrameTime()
+ {
+ if (Time >= _fpsTime)
+ {
+ _fpsTime = Time + 1000;
+ FPS = _fps;
+ _fps = 0;
+
+ DPS = DPSCounter;
+ DPSCounter = 0;
+ }
+ else
+ _fps++;
+ }
+
+ private static bool IsDrawTime()
+ {
+ const int TargetUpdates = 1000 / 60; // 60 frames per second
+
+ if (Time >= _drawTime)
+ {
+ _drawTime = Time + TargetUpdates;
+ return true;
+ }
+ return false;
+ }
+
+ private static void UpdateEnviroment()
+ {
+ if (Time >= _cleanTime)
+ {
+ _cleanTime = Time + 1000;
+
+ DXManager.Clean(); // Clean once a second.
+ }
+
+ Network.Process();
+
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.Process();
+
+ for (int i = 0; i < MirAnimatedControl.Animations.Count; i++)
+ MirAnimatedControl.Animations[i].UpdateOffSet();
+
+ for (int i = 0; i < MirAnimatedButton.Animations.Count; i++)
+ MirAnimatedButton.Animations[i].UpdateOffSet();
+
+ CreateHintLabel();
+
+ if (Settings.DebugMode)
+ {
+ CreateDebugLabel();
+ }
+ }
+
+ private static void RenderEnvironment()
+ {
+ try
+ {
+ if (DXManager.DeviceLost)
+ {
+ DXManager.AttemptReset();
+ Thread.Sleep(1);
+ return;
+ }
+
+ DXManager.Device.Clear(ClearFlags.Target, Color.CornflowerBlue, 0, 0);
+ DXManager.Device.BeginScene();
+ DXManager.Sprite.Begin(SpriteFlags.AlphaBlend);
+ DXManager.SetSurface(DXManager.MainSurface);
+
+ if (MirScene.ActiveScene != null)
+ MirScene.ActiveScene.Draw();
+
+ DXManager.Sprite.End();
+ DXManager.Device.EndScene();
+ DXManager.Device.Present();
+ }
+ catch (Direct3D9Exception ex)
+ {
+ DXManager.DeviceLost = true;
+ SaveError(ex.ToString());
+ }
+ catch (Exception ex)
+ {
+ SaveError(ex.ToString());
+
+ DXManager.AttemptRecovery();
+ }
+ }
+
+ private static void CreateDebugLabel()
+ {
+ string text;
+
+ if (MirControl.MouseControl != null)
+ {
+ text = string.Format("FPS: {0}", FPS);
+
+ text += string.Format(", DPS: {0}", DPS);
+
+ text += string.Format(", Time: {0:HH:mm:ss UTC}", Now);
+
+ if (MirControl.MouseControl is MapControl)
+ text += string.Format(", Co Ords: {0}", MapControl.MapLocation);
+
+ if (MirControl.MouseControl is MirImageControl)
+ text += string.Format(", Control: {0}", MirControl.MouseControl.GetType().Name);
+
+ if (MirScene.ActiveScene is GameScene)
+ text += string.Format(", Objects: {0}", MapControl.Objects.Count);
+
+ if (MirScene.ActiveScene is GameScene && !string.IsNullOrEmpty(DebugText))
+ text += string.Format(", Debug: {0}", DebugText);
+
+ if (MirObjects.MapObject.MouseObject != null)
+ {
+ text += string.Format(", Target: {0}", MirObjects.MapObject.MouseObject.Name);
+ }
+ else
+ {
+ text += string.Format(", Target: none");
+ }
+ }
+ else
+ {
+ text = string.Format("FPS: {0}", FPS);
+ }
+
+ text += string.Format(", Ping: {0}", PingTime);
+
+ text += string.Format(", Sent: {0}, Received: {1}", Functions.ConvertByteSize(BytesSent), Functions.ConvertByteSize(BytesReceived));
+
+ text += string.Format(", TLC: {0}", DXManager.TextureList.Count(x => x.TextureValid));
+ text += string.Format(", CLC: {0}", DXManager.ControlList.Count(x => x.IsDisposed == false));
+
+ if (Settings.FullScreen)
+ {
+ if (DebugBaseLabel == null || DebugBaseLabel.IsDisposed)
+ {
+ DebugBaseLabel = new MirControl
+ {
+ BackColour = Color.FromArgb(50, 50, 50),
+ Border = true,
+ BorderColour = Color.Black,
+ DrawControlTexture = true,
+ Location = new Point(5, 5),
+ NotControl = true,
+ Opacity = 0.5F
+ };
+ }
+
+ if (DebugTextLabel == null || DebugTextLabel.IsDisposed)
+ {
+ DebugTextLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = Color.White,
+ Parent = DebugBaseLabel,
+ };
+
+ DebugTextLabel.SizeChanged += (o, e) => DebugBaseLabel.Size = DebugTextLabel.Size;
+ }
+
+ DebugTextLabel.Text = text;
+ }
+ else
+ {
+ if (DebugBaseLabel != null && DebugBaseLabel.IsDisposed == false)
+ {
+ DebugBaseLabel.Dispose();
+ DebugBaseLabel = null;
+ }
+ if (DebugTextLabel != null && DebugTextLabel.IsDisposed == false)
+ {
+ DebugTextLabel.Dispose();
+ DebugTextLabel = null;
+ }
+
+ Program.Form.Text = $"{GameLanguage.GameName} - {text}";
+ }
+ }
+
+ private static void CreateHintLabel()
+ {
+ if (HintBaseLabel == null || HintBaseLabel.IsDisposed)
+ {
+ HintBaseLabel = new MirControl
+ {
+ BackColour = Color.FromArgb(255, 0, 0, 0),
+ Border = true,
+ DrawControlTexture = true,
+ BorderColour = Color.FromArgb(255, 144, 144, 0),
+ ForeColour = Color.Yellow,
+ Parent = MirScene.ActiveScene,
+ NotControl = true,
+ Opacity = 0.5F
+ };
+ }
+
+
+ if (HintTextLabel == null || HintTextLabel.IsDisposed)
+ {
+ HintTextLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = Color.Yellow,
+ Parent = HintBaseLabel,
+ };
+
+ HintTextLabel.SizeChanged += (o, e) => HintBaseLabel.Size = HintTextLabel.Size;
+ }
+
+ if (MirControl.MouseControl == null || string.IsNullOrEmpty(MirControl.MouseControl.Hint))
+ {
+ HintBaseLabel.Visible = false;
+ return;
+ }
+
+ HintBaseLabel.Visible = true;
+
+ HintTextLabel.Text = MirControl.MouseControl.Hint;
+
+ Point point = MPoint.Add(-HintTextLabel.Size.Width, 20);
+
+ if (point.X + HintBaseLabel.Size.Width >= Settings.ScreenWidth)
+ point.X = Settings.ScreenWidth - HintBaseLabel.Size.Width - 1;
+ if (point.Y + HintBaseLabel.Size.Height >= Settings.ScreenHeight)
+ point.Y = Settings.ScreenHeight - HintBaseLabel.Size.Height - 1;
+
+ if (point.X < 0)
+ point.X = 0;
+ if (point.Y < 0)
+ point.Y = 0;
+
+ HintBaseLabel.Location = point;
+ }
+
+ private static void ToggleFullScreen()
+ {
+ Settings.FullScreen = !Settings.FullScreen;
+
+ Program.Form.FormBorderStyle = Settings.FullScreen || Settings.Borderless ? FormBorderStyle.None : FormBorderStyle.FixedDialog;
+
+ DXManager.Parameters.Windowed = !Settings.FullScreen;
+
+ Program.Form.ClientSize = new Size(Settings.ScreenWidth, Settings.ScreenHeight);
+
+ DXManager.ResetDevice();
+
+ if (MirScene.ActiveScene == GameScene.Scene)
+ {
+ GameScene.Scene.MapControl.FloorValid = false;
+ GameScene.Scene.TextureValid = false;
+ }
+
+ Program.Form.CenterToScreen();
+ }
+
+ public void CreateScreenShot()
+ {
+ string text = string.Format("[{0} Server {1}] {2} {3:hh\\:mm\\:ss}",
+ Settings.P_ServerName.Length > 0 ? Settings.P_ServerName : "Carbon",
+ MapControl.User != null ? MapControl.User.Name : "",
+ Now.ToShortDateString(),
+ Now.TimeOfDay);
+
+ Surface backbuffer = DXManager.Device.GetBackBuffer(0, 0);
+
+ using (var stream = Surface.ToStream(backbuffer, ImageFileFormat.Png))
+ {
+ Bitmap image = new Bitmap(stream);
+
+ using (Graphics graphics = Graphics.FromImage(image))
+ {
+ StringFormat sf = new StringFormat
+ {
+ LineAlignment = StringAlignment.Center,
+ Alignment = StringAlignment.Center
+ };
+
+ graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 3, 10), sf);
+ graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 4, 9), sf);
+ graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 5, 10), sf);
+ graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.Black, new Point((Settings.ScreenWidth / 2) + 4, 11), sf);
+ graphics.DrawString(text, new Font(Settings.FontName, 9F), Brushes.White, new Point((Settings.ScreenWidth / 2) + 4, 10), sf);//SandyBrown
+
+ string path = Path.Combine(Application.StartupPath, @"Screenshots\");
+ if (!Directory.Exists(path))
+ Directory.CreateDirectory(path);
+
+ int count = Directory.GetFiles(path, "*.png").Length;
+
+ image.Save(Path.Combine(path, string.Format("Image {0}.png", count)), ImageFormat.Png);
+ }
+ }
+ }
+
+ public static void SaveError(string ex)
+ {
+ try
+ {
+ if (Settings.RemainingErrorLogs-- > 0)
+ {
+ File.AppendAllText(@".\Error.txt",
+ string.Format("[{0}] {1}{2}", Now, ex, Environment.NewLine));
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ public static void SetResolution(int width, int height)
+ {
+ Settings.ScreenWidth = width;
+ Settings.ScreenHeight = height;
+ Program.Form.ClientSize = new Size(width, height);
+
+ DXManager.Device.Clear(ClearFlags.Target, Color.Black, 0, 0);
+ DXManager.Device.Present();
+ DXManager.ResetDevice();
+
+ Program.Form.CenterToScreen();
+ }
+
+
+ #region ScreenCapture
+
+ //private Bitmap CaptureScreen()
+ //{
+
+ //}
+
+ #endregion
+
+ #region Idle Check
+ private static bool AppStillIdle
+ {
+ get
+ {
+ PeekMsg msg;
+ return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
+ }
+ }
+
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ private static extern bool PeekMessage(out PeekMsg msg, IntPtr hWnd, uint messageFilterMin,
+ uint messageFilterMax, uint flags);
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct PeekMsg
+ {
+ private readonly IntPtr hWnd;
+ private readonly Message msg;
+ private readonly IntPtr wParam;
+ private readonly IntPtr lParam;
+ private readonly uint time;
+ private readonly Point p;
+ }
+ #endregion
+
+ private void CMain_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (CMain.Time < GameScene.LogTime && !Settings.UseTestConfig && !GameScene.Observing)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(string.Format(GameLanguage.CannotLeaveGame, (GameScene.LogTime - CMain.Time) / 1000), ChatType.System);
+ e.Cancel = true;
+ }
+ else
+ {
+ Settings.Save();
+
+ DXManager.Dispose();
+ SoundManager.Dispose();
+ }
+ }
+
+ protected override void WndProc(ref Message m)
+ {
+ if (m.Msg == 0x0112) // WM_SYSCOMMAND
+ {
+ if (m.WParam.ToInt32() == 0xF100) // SC_KEYMENU
+ {
+ m.Result = IntPtr.Zero;
+ return;
+ }
+ else if (m.WParam.ToInt32() == 0xF030) // SC_MAXIMISE
+ {
+ ToggleFullScreen();
+ return;
+ }
+ }
+
+ base.WndProc(ref m);
+ }
+
+
+ public static Cursor[] Cursors;
+ public static MouseCursor CurrentCursor = MouseCursor.None;
+ public static void SetMouseCursor(MouseCursor cursor)
+ {
+ if (!Settings.UseMouseCursors) return;
+
+ if (CurrentCursor != cursor)
+ {
+ CurrentCursor = cursor;
+ Program.Form.Cursor = Cursors[(byte)cursor];
+ }
+ }
+
+ private static void LoadMouseCursors()
+ {
+ Cursors = new Cursor[8];
+
+ Cursors[(int)MouseCursor.None] = Program.Form.Cursor;
+
+ string path = $"{Settings.MouseCursorPath}Cursor_Default.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.Default] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_Normal_Atk.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.Attack] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_Compulsion_Atk.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.AttackRed] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_Npc.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.NPCTalk] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_TextPrompt.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.TextPrompt] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_Trash.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.Trash] = LoadCustomCursor(path);
+
+ path = $"{Settings.MouseCursorPath}Cursor_Upgrade.CUR";
+ if (File.Exists(path))
+ Cursors[(int)MouseCursor.Upgrade] = LoadCustomCursor(path);
+ }
+
+ public static Cursor LoadCustomCursor(string path)
+ {
+ IntPtr hCurs = LoadCursorFromFile(path);
+ if (hCurs == IntPtr.Zero) throw new Win32Exception();
+ var curs = new Cursor(hCurs);
+ // Note: force the cursor to own the handle so it gets released properly
+ //var fi = typeof(Cursor).GetField("ownHandle", BindingFlags.NonPublic | BindingFlags.Instance);
+ //fi.SetValue(curs, true);
+ return curs;
+ }
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ private static extern IntPtr LoadCursorFromFile(string path);
+ }
+}
diff --git a/Client/Forms/CMain.resx b/Client/Forms/CMain.resx
new file mode 100644
index 0000000..6639c33
--- /dev/null
+++ b/Client/Forms/CMain.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\$this.Icon1.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/Client/Forms/Config.cs b/Client/Forms/Config.cs
new file mode 100644
index 0000000..8dd7891
--- /dev/null
+++ b/Client/Forms/Config.cs
@@ -0,0 +1,244 @@
+using Client;
+using System.Resources;
+using System.Reflection;
+using Client.Resolution;
+
+namespace Launcher
+{
+
+ public partial class Config : Form
+ {
+ public Config()
+ {
+ InitializeComponent();
+ }
+
+ private void Config_Load(object sender, EventArgs e)
+ {
+ this.label10.Text = GameLanguage.Resolution;
+ this.AutoStart_label.Text = GameLanguage.Autostart;
+ this.ID_l.Text = GameLanguage.Usrname;
+ this.Password_l.Text = GameLanguage.Password;
+
+ DrawSupportedResolutions();
+ }
+
+ private void Res1_pb_Click(object sender, EventArgs e)
+ {
+ resolutionChoice(eSupportedResolution.w800h600);
+
+ }
+
+ public void resolutionChoice(eSupportedResolution res)
+ {
+ Res2_pb.Image = Client.Resources.Images.Radio_Unactive;
+ Res3_pb.Image = Client.Resources.Images.Radio_Unactive;
+ Res4_pb.Image = Client.Resources.Images.Radio_Unactive;
+ Res5_pb.Image = Client.Resources.Images.Radio_Unactive;
+
+ switch (res)
+ {
+ case eSupportedResolution.w800h600:
+ Res2_pb.Image = Client.Resources.Images.Config_Radio_On;
+ break;
+ case eSupportedResolution.w1366h768:
+ Res3_pb.Image = Client.Resources.Images.Config_Radio_On;
+ break;
+ case eSupportedResolution.w1280h720:
+ Res4_pb.Image = Client.Resources.Images.Config_Radio_On;
+ break;
+ case eSupportedResolution.w1920h1080:
+ Res5_pb.Image = Client.Resources.Images.Config_Radio_On;
+ break;
+
+ }
+
+ Settings.Resolution = (int)res;
+ }
+
+ private void Res2_pb_Click(object sender, EventArgs e)
+ {
+ resolutionChoice(eSupportedResolution.w800h600);
+ }
+
+ private void Res3_pb_Click(object sender, EventArgs e)
+ {
+ resolutionChoice(eSupportedResolution.w1366h768);
+ }
+
+ private void Config_VisibleChanged(object sender, EventArgs e)
+ {
+ if (Visible)
+ {
+ AccountLogin_txt.Text = Settings.AccountID;
+ AccountPass_txt.Text = Settings.Password;
+ resolutionChoice((eSupportedResolution)Settings.Resolution);
+
+ Fullscreen_pb.Image = Settings.FullScreen
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+
+ FPScap_pb.Image = Settings.FPSCap
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+
+ OnTop_pb.Image = Settings.TopMost
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+
+ AutoStart_pb.Image = Settings.P_AutoStart
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+
+ this.ActiveControl = label4;
+ }
+ else
+ {
+ Settings.AccountID = AccountLogin_txt.Text;
+ Settings.Password = AccountPass_txt.Text;
+ Settings.Save();
+ }
+ }
+
+ private void AccountLogin_txt_TextChanged(object sender, EventArgs e)
+ {
+ if (AccountLogin_txt.Text == string.Empty) ID_l.Visible = true;
+ else ID_l.Visible = false;
+ }
+
+ private void AccountPass_txt_TextChanged(object sender, EventArgs e)
+ {
+ if (AccountPass_txt.Text == string.Empty) Password_l.Visible = true;
+ else Password_l.Visible = false;
+ }
+
+ private void AccountLogin_txt_Click(object sender, EventArgs e)
+ {
+ ID_l.Visible = false;
+ AccountLogin_txt.Focus();
+ }
+
+ private void AccountPass_txt_Click(object sender, EventArgs e)
+ {
+ Password_l.Visible = false;
+ AccountPass_txt.Focus();
+ }
+
+ private void Config_Click(object sender, EventArgs e)
+ {
+ this.ActiveControl = label4;
+ }
+
+ private void Fullscreen_pb_Click(object sender, EventArgs e)
+ {
+ Settings.FullScreen = !Settings.FullScreen;
+
+ Fullscreen_pb.Image = Settings.FullScreen
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+ }
+
+ private void FPScap_pb_Click(object sender, EventArgs e)
+ {
+ Settings.FPSCap = !Settings.FPSCap;
+
+ FPScap_pb.Image = Settings.FPSCap
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+ }
+
+ private void OnTop_pb_Click(object sender, EventArgs e)
+ {
+ Settings.TopMost = !Settings.TopMost;
+
+ OnTop_pb.Image = Settings.TopMost
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+ }
+
+ private void AutoStart_pb_Click(object sender, EventArgs e)
+ {
+ Settings.P_AutoStart = !Settings.P_AutoStart;
+
+ AutoStart_pb.Image = Settings.P_AutoStart
+ ? Client.Resources.Images.Config_Check_On
+ : Client.Resources.Images.Config_Check_Off1;
+ }
+
+ private void CleanFiles_pb_MouseDown(object sender, MouseEventArgs e)
+ {
+ CleanFiles_pb.Image = Client.Resources.Images.CheckF_Pressed;
+ }
+
+ private void CleanFiles_pb_MouseUp(object sender, MouseEventArgs e)
+ {
+ CleanFiles_pb.Image = Client.Resources.Images.CheckF_Base2;
+ }
+
+ private void CleanFiles_pb_MouseEnter(object sender, EventArgs e)
+ {
+ CleanFiles_pb.Image = Client.Resources.Images.CheckF_Hover;
+ }
+
+ private void CleanFiles_pb_MouseLeave(object sender, EventArgs e)
+ {
+ CleanFiles_pb.Image = Client.Resources.Images.CheckF_Base2;
+ }
+
+ private void CleanFiles_pb_Click(object sender, EventArgs e)
+ {
+ if (!Program.PForm.Launch_pb.Enabled) return;
+
+ Program.PForm.Completed = false;
+ Program.PForm.InterfaceTimer.Enabled = true;
+ Program.PForm.CleanFiles = true;
+ Program.PForm._workThread = new Thread(Program.PForm.Start) { IsBackground = true };
+ Program.PForm._workThread.Start();
+ }
+
+ private void Res4_pb_Click(object sender, EventArgs e)
+ {
+ resolutionChoice(eSupportedResolution.w1280h720);
+ }
+
+ private void Res5_pb_Click(object sender, EventArgs e)
+ {
+ resolutionChoice(eSupportedResolution.w1920h1080);
+ }
+
+ private void DrawSupportedResolutions()
+ {
+ Res2_pb.Enabled = false;
+ label2.ForeColor = Color.Red;
+ Res4_pb.Enabled = false;
+ label5.ForeColor = Color.Red;
+ Res3_pb.Enabled = false;
+ label3.ForeColor = Color.Red;
+ Res5_pb.Enabled = false;
+ label1.ForeColor = Color.Red;
+
+ foreach (eSupportedResolution supportedResolution in DisplayResolutions.DisplaySupportedResolutions)
+ {
+ switch (supportedResolution)
+ {
+ case (eSupportedResolution.w800h600):
+ Res2_pb.Enabled = true;
+ label2.ForeColor = Color.Gray;
+ break;
+ case (eSupportedResolution.w1280h720):
+ Res4_pb.Enabled = true;
+ label5.ForeColor = Color.Gray;
+ break;
+ case (eSupportedResolution.w1366h768):
+ Res3_pb.Enabled = true;
+ label3.ForeColor = Color.Gray;
+ break;
+ case (eSupportedResolution.w1920h1080):
+ Res5_pb.Enabled = true;
+ label1.ForeColor = Color.Gray;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/Client/Forms/Config.designer.cs b/Client/Forms/Config.designer.cs
new file mode 100644
index 0000000..4ea0d87
--- /dev/null
+++ b/Client/Forms/Config.designer.cs
@@ -0,0 +1,513 @@
+namespace Launcher
+{
+ partial class Config
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ AccountLogin_txt = new TextBox();
+ AccountPass_txt = new TextBox();
+ label2 = new Label();
+ label3 = new Label();
+ Res3_pb = new PictureBox();
+ Res2_pb = new PictureBox();
+ ID_l = new Label();
+ Password_l = new Label();
+ label4 = new Label();
+ AutoStart_pb = new PictureBox();
+ AutoStart_label = new Label();
+ Fullscreen_label = new Label();
+ Fullscreen_pb = new PictureBox();
+ OnTop_label = new Label();
+ OnTop_pb = new PictureBox();
+ FPScap_label = new Label();
+ FPScap_pb = new PictureBox();
+ CleanFiles_pb = new PictureBox();
+ pictureBox6 = new PictureBox();
+ label9 = new Label();
+ label10 = new Label();
+ label11 = new Label();
+ label12 = new Label();
+ label5 = new Label();
+ Res4_pb = new PictureBox();
+ label1 = new Label();
+ Res5_pb = new PictureBox();
+ ((System.ComponentModel.ISupportInitialize)Res3_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Res2_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)AutoStart_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Fullscreen_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)OnTop_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)FPScap_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)CleanFiles_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)pictureBox6).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Res4_pb).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)Res5_pb).BeginInit();
+ SuspendLayout();
+ //
+ // AccountLogin_txt
+ //
+ AccountLogin_txt.BackColor = Color.FromArgb(64, 64, 64);
+ AccountLogin_txt.BorderStyle = BorderStyle.None;
+ AccountLogin_txt.Cursor = Cursors.IBeam;
+ AccountLogin_txt.Font = new Font("Calibri", 9F, FontStyle.Regular, GraphicsUnit.Point);
+ AccountLogin_txt.ForeColor = Color.White;
+ AccountLogin_txt.Location = new Point(29, 205);
+ AccountLogin_txt.Margin = new Padding(4, 3, 4, 3);
+ AccountLogin_txt.Name = "AccountLogin_txt";
+ AccountLogin_txt.Size = new Size(124, 15);
+ AccountLogin_txt.TabIndex = 0;
+ AccountLogin_txt.Tag = "Testing";
+ AccountLogin_txt.Click += AccountLogin_txt_Click;
+ AccountLogin_txt.TextChanged += AccountLogin_txt_TextChanged;
+ AccountLogin_txt.Leave += AccountLogin_txt_TextChanged;
+ //
+ // AccountPass_txt
+ //
+ AccountPass_txt.BackColor = Color.FromArgb(64, 64, 64);
+ AccountPass_txt.BorderStyle = BorderStyle.None;
+ AccountPass_txt.Font = new Font("Calibri", 9F, FontStyle.Regular, GraphicsUnit.Point);
+ AccountPass_txt.ForeColor = Color.White;
+ AccountPass_txt.Location = new Point(29, 232);
+ AccountPass_txt.Margin = new Padding(4, 3, 4, 3);
+ AccountPass_txt.Name = "AccountPass_txt";
+ AccountPass_txt.PasswordChar = '*';
+ AccountPass_txt.Size = new Size(124, 15);
+ AccountPass_txt.TabIndex = 1;
+ AccountPass_txt.Click += AccountPass_txt_Click;
+ AccountPass_txt.TextChanged += AccountPass_txt_TextChanged;
+ AccountPass_txt.Leave += AccountPass_txt_TextChanged;
+ //
+ // label2
+ //
+ label2.AutoSize = true;
+ label2.BackColor = Color.Transparent;
+ label2.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ label2.ForeColor = Color.Gray;
+ label2.Location = new Point(178, 59);
+ label2.Margin = new Padding(4, 0, 4, 0);
+ label2.Name = "label2";
+ label2.Size = new Size(48, 13);
+ label2.TabIndex = 5;
+ label2.Text = "800x600";
+ label2.Click += Res2_pb_Click;
+ //
+ // label3
+ //
+ label3.AutoSize = true;
+ label3.BackColor = Color.Transparent;
+ label3.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ label3.ForeColor = Color.Gray;
+ label3.Location = new Point(178, 100);
+ label3.Margin = new Padding(4, 0, 4, 0);
+ label3.Name = "label3";
+ label3.Size = new Size(54, 13);
+ label3.TabIndex = 7;
+ label3.Text = "1366x768";
+ label3.Click += Res3_pb_Click;
+ //
+ // Res3_pb
+ //
+ Res3_pb.Location = new Point(157, 100);
+ Res3_pb.Margin = new Padding(4, 3, 4, 3);
+ Res3_pb.Name = "Res3_pb";
+ Res3_pb.Size = new Size(12, 12);
+ Res3_pb.TabIndex = 6;
+ Res3_pb.TabStop = false;
+ Res3_pb.Click += Res3_pb_Click;
+ //
+ // Res2_pb
+ //
+ Res2_pb.Location = new Point(157, 59);
+ Res2_pb.Margin = new Padding(4, 3, 4, 3);
+ Res2_pb.Name = "Res2_pb";
+ Res2_pb.Size = new Size(12, 12);
+ Res2_pb.TabIndex = 4;
+ Res2_pb.TabStop = false;
+ Res2_pb.Click += Res2_pb_Click;
+ //
+ // ID_l
+ //
+ ID_l.BackColor = Color.Transparent;
+ ID_l.Cursor = Cursors.IBeam;
+ ID_l.Enabled = false;
+ ID_l.Font = new Font("Calibri", 9.75F, FontStyle.Italic, GraphicsUnit.Point);
+ ID_l.ForeColor = Color.Transparent;
+ ID_l.Location = new Point(29, 204);
+ ID_l.Margin = new Padding(4, 0, 4, 0);
+ ID_l.Name = "ID_l";
+ ID_l.Size = new Size(124, 17);
+ ID_l.TabIndex = 8;
+ ID_l.Text = "Username";
+ ID_l.Click += AccountLogin_txt_Click;
+ //
+ // Password_l
+ //
+ Password_l.BackColor = Color.Transparent;
+ Password_l.Cursor = Cursors.IBeam;
+ Password_l.Enabled = false;
+ Password_l.Font = new Font("Calibri Light", 9.75F, FontStyle.Italic, GraphicsUnit.Point);
+ Password_l.ForeColor = Color.Transparent;
+ Password_l.Location = new Point(29, 232);
+ Password_l.Margin = new Padding(4, 0, 4, 0);
+ Password_l.Name = "Password_l";
+ Password_l.Size = new Size(124, 17);
+ Password_l.TabIndex = 9;
+ Password_l.Text = "Password";
+ Password_l.Click += AccountPass_txt_Click;
+ //
+ // label4
+ //
+ label4.AutoSize = true;
+ label4.BackColor = Color.Transparent;
+ label4.Location = new Point(261, 31);
+ label4.Margin = new Padding(4, 0, 4, 0);
+ label4.Name = "label4";
+ label4.Size = new Size(0, 15);
+ label4.TabIndex = 10;
+ //
+ // AutoStart_pb
+ //
+ AutoStart_pb.BackgroundImageLayout = ImageLayout.Center;
+ AutoStart_pb.Location = new Point(23, 160);
+ AutoStart_pb.Margin = new Padding(4, 3, 4, 3);
+ AutoStart_pb.Name = "AutoStart_pb";
+ AutoStart_pb.Size = new Size(12, 12);
+ AutoStart_pb.TabIndex = 11;
+ AutoStart_pb.TabStop = false;
+ AutoStart_pb.Click += AutoStart_pb_Click;
+ //
+ // AutoStart_label
+ //
+ AutoStart_label.AutoSize = true;
+ AutoStart_label.BackColor = Color.Transparent;
+ AutoStart_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ AutoStart_label.ForeColor = Color.Gray;
+ AutoStart_label.Location = new Point(40, 159);
+ AutoStart_label.Margin = new Padding(4, 0, 4, 0);
+ AutoStart_label.Name = "AutoStart_label";
+ AutoStart_label.Size = new Size(54, 13);
+ AutoStart_label.TabIndex = 12;
+ AutoStart_label.Text = "Auto start";
+ AutoStart_label.Click += AutoStart_pb_Click;
+ //
+ // Fullscreen_label
+ //
+ Fullscreen_label.AutoSize = true;
+ Fullscreen_label.BackColor = Color.Transparent;
+ Fullscreen_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ Fullscreen_label.ForeColor = Color.Gray;
+ Fullscreen_label.Location = new Point(40, 59);
+ Fullscreen_label.Margin = new Padding(4, 0, 4, 0);
+ Fullscreen_label.Name = "Fullscreen_label";
+ Fullscreen_label.Size = new Size(56, 13);
+ Fullscreen_label.TabIndex = 14;
+ Fullscreen_label.Text = "Fullscreen";
+ Fullscreen_label.Click += Fullscreen_pb_Click;
+ //
+ // Fullscreen_pb
+ //
+ Fullscreen_pb.BackgroundImageLayout = ImageLayout.Center;
+ Fullscreen_pb.Location = new Point(23, 59);
+ Fullscreen_pb.Margin = new Padding(4, 3, 4, 3);
+ Fullscreen_pb.Name = "Fullscreen_pb";
+ Fullscreen_pb.Size = new Size(12, 12);
+ Fullscreen_pb.TabIndex = 13;
+ Fullscreen_pb.TabStop = false;
+ Fullscreen_pb.Click += Fullscreen_pb_Click;
+ //
+ // OnTop_label
+ //
+ OnTop_label.AutoSize = true;
+ OnTop_label.BackColor = Color.Transparent;
+ OnTop_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ OnTop_label.ForeColor = Color.Gray;
+ OnTop_label.Location = new Point(40, 113);
+ OnTop_label.Margin = new Padding(4, 0, 4, 0);
+ OnTop_label.Name = "OnTop_label";
+ OnTop_label.Size = new Size(72, 13);
+ OnTop_label.TabIndex = 16;
+ OnTop_label.Text = "Always on top";
+ OnTop_label.Click += OnTop_pb_Click;
+ //
+ // OnTop_pb
+ //
+ OnTop_pb.BackgroundImageLayout = ImageLayout.Center;
+ OnTop_pb.Image = Client.Resources.Images.Config_Check_Off1;
+ OnTop_pb.Location = new Point(23, 113);
+ OnTop_pb.Margin = new Padding(4, 3, 4, 3);
+ OnTop_pb.Name = "OnTop_pb";
+ OnTop_pb.Size = new Size(12, 12);
+ OnTop_pb.TabIndex = 15;
+ OnTop_pb.TabStop = false;
+ OnTop_pb.Click += OnTop_pb_Click;
+ //
+ // FPScap_label
+ //
+ FPScap_label.AutoSize = true;
+ FPScap_label.BackColor = Color.Transparent;
+ FPScap_label.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ FPScap_label.ForeColor = Color.Gray;
+ FPScap_label.Location = new Point(40, 84);
+ FPScap_label.Margin = new Padding(4, 0, 4, 0);
+ FPScap_label.Name = "FPScap_label";
+ FPScap_label.Size = new Size(42, 13);
+ FPScap_label.TabIndex = 18;
+ FPScap_label.Text = "FPS cap";
+ FPScap_label.Click += FPScap_pb_Click;
+ //
+ // FPScap_pb
+ //
+ FPScap_pb.BackgroundImageLayout = ImageLayout.Center;
+ FPScap_pb.Image = Client.Resources.Images.Config_Check_Off1;
+ FPScap_pb.Location = new Point(23, 85);
+ FPScap_pb.Margin = new Padding(4, 3, 4, 3);
+ FPScap_pb.Name = "FPScap_pb";
+ FPScap_pb.Size = new Size(12, 12);
+ FPScap_pb.TabIndex = 17;
+ FPScap_pb.TabStop = false;
+ FPScap_pb.Click += FPScap_pb_Click;
+ //
+ // CleanFiles_pb
+ //
+ CleanFiles_pb.BackgroundImageLayout = ImageLayout.Center;
+ CleanFiles_pb.Image = Client.Resources.Images.CheckF_Base2;
+ CleanFiles_pb.Location = new Point(23, 275);
+ CleanFiles_pb.Margin = new Padding(4, 3, 4, 3);
+ CleanFiles_pb.Name = "CleanFiles_pb";
+ CleanFiles_pb.Size = new Size(67, 23);
+ CleanFiles_pb.TabIndex = 19;
+ CleanFiles_pb.TabStop = false;
+ CleanFiles_pb.Click += CleanFiles_pb_Click;
+ CleanFiles_pb.MouseDown += CleanFiles_pb_MouseDown;
+ CleanFiles_pb.MouseEnter += CleanFiles_pb_MouseEnter;
+ CleanFiles_pb.MouseLeave += CleanFiles_pb_MouseLeave;
+ CleanFiles_pb.MouseUp += CleanFiles_pb_MouseUp;
+ //
+ // pictureBox6
+ //
+ pictureBox6.BackColor = Color.Transparent;
+ pictureBox6.Image = Client.Resources.Images.textboxes;
+ pictureBox6.Location = new Point(23, 198);
+ pictureBox6.Margin = new Padding(4, 3, 4, 3);
+ pictureBox6.Name = "pictureBox6";
+ pictureBox6.Size = new Size(137, 57);
+ pictureBox6.TabIndex = 20;
+ pictureBox6.TabStop = false;
+ //
+ // label9
+ //
+ label9.AutoSize = true;
+ label9.BackColor = Color.Transparent;
+ label9.Font = new Font("Calibri", 9F, FontStyle.Regular, GraphicsUnit.Point);
+ label9.ForeColor = Color.White;
+ label9.Location = new Point(23, 42);
+ label9.Margin = new Padding(4, 0, 4, 0);
+ label9.Name = "label9";
+ label9.Size = new Size(55, 14);
+ label9.TabIndex = 21;
+ label9.Text = "Graphics";
+ //
+ // label10
+ //
+ label10.AutoSize = true;
+ label10.BackColor = Color.Transparent;
+ label10.Font = new Font("Calibri", 9F, FontStyle.Regular, GraphicsUnit.Point);
+ label10.ForeColor = Color.White;
+ label10.Location = new Point(157, 42);
+ label10.Margin = new Padding(4, 0, 4, 0);
+ label10.Name = "label10";
+ label10.Size = new Size(66, 14);
+ label10.TabIndex = 22;
+ label10.Text = "Resolution";
+ //
+ // label11
+ //
+ label11.AutoSize = true;
+ label11.BackColor = Color.Transparent;
+ label11.Font = new Font("Calibri", 9F, FontStyle.Regular, GraphicsUnit.Point);
+ label11.ForeColor = Color.White;
+ label11.Location = new Point(20, 145);
+ label11.Margin = new Padding(4, 0, 4, 0);
+ label11.Name = "label11";
+ label11.Size = new Size(39, 14);
+ label11.TabIndex = 23;
+ label11.Text = "Game";
+ //
+ // label12
+ //
+ label12.AutoSize = true;
+ label12.BackColor = Color.Transparent;
+ label12.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ label12.ForeColor = Color.Gray;
+ label12.Location = new Point(20, 182);
+ label12.Margin = new Padding(4, 0, 4, 0);
+ label12.Name = "label12";
+ label12.Size = new Size(80, 13);
+ label12.TabIndex = 24;
+ label12.Text = "Account details";
+ //
+ // label5
+ //
+ label5.AutoSize = true;
+ label5.BackColor = Color.Transparent;
+ label5.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ label5.ForeColor = Color.Gray;
+ label5.Location = new Point(178, 80);
+ label5.Margin = new Padding(4, 0, 4, 0);
+ label5.Name = "label5";
+ label5.Size = new Size(54, 13);
+ label5.TabIndex = 26;
+ label5.Text = "1280x800";
+ //
+ // Res4_pb
+ //
+ Res4_pb.Image = Client.Resources.Images.Radio_Unactive;
+ Res4_pb.Location = new Point(157, 80);
+ Res4_pb.Margin = new Padding(4, 3, 4, 3);
+ Res4_pb.Name = "Res4_pb";
+ Res4_pb.Size = new Size(12, 12);
+ Res4_pb.TabIndex = 25;
+ Res4_pb.TabStop = false;
+ Res4_pb.Click += Res4_pb_Click;
+ //
+ // label1
+ //
+ label1.AutoSize = true;
+ label1.BackColor = Color.Transparent;
+ label1.Font = new Font("Calibri", 8.25F, FontStyle.Regular, GraphicsUnit.Point);
+ label1.ForeColor = Color.Gray;
+ label1.Location = new Point(178, 121);
+ label1.Margin = new Padding(4, 0, 4, 0);
+ label1.Name = "label1";
+ label1.Size = new Size(60, 13);
+ label1.TabIndex = 27;
+ label1.Text = "1920x1080";
+ //
+ // Res5_pb
+ //
+ Res5_pb.Image = Client.Resources.Images.Radio_Unactive;
+ Res5_pb.Location = new Point(157, 121);
+ Res5_pb.Margin = new Padding(4, 3, 4, 3);
+ Res5_pb.Name = "Res5_pb";
+ Res5_pb.Size = new Size(12, 12);
+ Res5_pb.TabIndex = 28;
+ Res5_pb.TabStop = false;
+ Res5_pb.Click += Res5_pb_Click;
+ //
+ // Config
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ BackColor = Color.Black;
+ BackgroundImage = Client.Resources.Images.Config_Base1;
+ BackgroundImageLayout = ImageLayout.Center;
+ ClientSize = new Size(257, 315);
+ Controls.Add(Res5_pb);
+ Controls.Add(label1);
+ Controls.Add(label5);
+ Controls.Add(Res4_pb);
+ Controls.Add(label12);
+ Controls.Add(label11);
+ Controls.Add(label10);
+ Controls.Add(label9);
+ Controls.Add(CleanFiles_pb);
+ Controls.Add(FPScap_label);
+ Controls.Add(FPScap_pb);
+ Controls.Add(OnTop_label);
+ Controls.Add(OnTop_pb);
+ Controls.Add(Fullscreen_label);
+ Controls.Add(Fullscreen_pb);
+ Controls.Add(AutoStart_label);
+ Controls.Add(AutoStart_pb);
+ Controls.Add(label4);
+ Controls.Add(Password_l);
+ Controls.Add(ID_l);
+ Controls.Add(label3);
+ Controls.Add(Res3_pb);
+ Controls.Add(label2);
+ Controls.Add(Res2_pb);
+ Controls.Add(AccountPass_txt);
+ Controls.Add(AccountLogin_txt);
+ Controls.Add(pictureBox6);
+ DoubleBuffered = true;
+ FormBorderStyle = FormBorderStyle.None;
+ Margin = new Padding(4, 3, 4, 3);
+ Name = "Config";
+ Opacity = 0.94D;
+ ShowIcon = false;
+ ShowInTaskbar = false;
+ SizeGripStyle = SizeGripStyle.Hide;
+ StartPosition = FormStartPosition.CenterScreen;
+ Text = "Config";
+ TransparencyKey = Color.Black;
+ Load += Config_Load;
+ VisibleChanged += Config_VisibleChanged;
+ Click += Config_Click;
+ ((System.ComponentModel.ISupportInitialize)Res3_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Res2_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)AutoStart_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Fullscreen_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)OnTop_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)FPScap_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)CleanFiles_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)pictureBox6).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Res4_pb).EndInit();
+ ((System.ComponentModel.ISupportInitialize)Res5_pb).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private TextBox AccountLogin_txt;
+ private TextBox AccountPass_txt;
+ private Label label2;
+ private PictureBox Res2_pb;
+ private Label label3;
+ private PictureBox Res3_pb;
+ private Label ID_l;
+ private Label Password_l;
+ private Label label4;
+ private PictureBox AutoStart_pb;
+ private Label AutoStart_label;
+ private Label Fullscreen_label;
+ private PictureBox Fullscreen_pb;
+ private Label OnTop_label;
+ private PictureBox OnTop_pb;
+ private Label FPScap_label;
+ private PictureBox FPScap_pb;
+ private PictureBox CleanFiles_pb;
+ private PictureBox pictureBox6;
+ private Label label9;
+ private Label label10;
+ private Label label11;
+ private Label label12;
+ private Label label5;
+ private PictureBox Res4_pb;
+ private Label label1;
+ private PictureBox Res5_pb;
+ }
+}
\ No newline at end of file
diff --git a/Client/Forms/Config.resx b/Client/Forms/Config.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/Client/Forms/Config.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Client/KeyBindSettings.cs b/Client/KeyBindSettings.cs
new file mode 100644
index 0000000..fe0e6c7
--- /dev/null
+++ b/Client/KeyBindSettings.cs
@@ -0,0 +1,346 @@
+namespace Client
+{
+
+ public enum KeybindOptions : int
+ {
+ Bar1Skill1 = 0,
+ Bar1Skill2,
+ Bar1Skill3,
+ Bar1Skill4,
+ Bar1Skill5,
+ Bar1Skill6,
+ Bar1Skill7,
+ Bar1Skill8,
+ Bar2Skill1,
+ Bar2Skill2,
+ Bar2Skill3,
+ Bar2Skill4,
+ Bar2Skill5,
+ Bar2Skill6,
+ Bar2Skill7,
+ Bar2Skill8,
+ Inventory,
+ Inventory2,
+ Equipment,
+ Equipment2,
+ Skills,
+ Skills2,
+ Skillbar,
+ Relationship,
+ Friends,
+ Guilds,
+ GameShop,
+ Quests,
+ Closeall,
+ Options,
+ Options2,
+ Group,
+ Belt,
+ BeltFlip,
+ Pickup,
+ Belt1,
+ Belt1Alt,
+ Belt2,
+ Belt2Alt,
+ Belt3,
+ Belt3Alt,
+ Belt4,
+ Belt4Alt,
+ Belt5,
+ Belt5Alt,
+ Belt6,
+ Belt6Alt,
+ Exit,
+ Logout,
+ Minimap,
+ Bigmap,
+ Trade,
+ ChangeAttackmode,
+ AttackmodePeace,
+ AttackmodeGroup,
+ AttackmodeGuild,
+ AttackmodeEnemyguild,
+ AttackmodeRedbrown,
+ AttackmodeAll,
+ ChangePetmode,
+ PetmodeBoth,
+ PetmodeMoveonly,
+ PetmodeAttackonly,
+ PetmodeNone,
+ Help,
+ Keybind,
+ Autorun,
+ Cameramode,
+ Screenshot,
+ DropView,
+ TargetDead,
+ Ranking,
+ AddGroupMember,
+ TargetSpellLockOn,
+ PetmodeFocusMasterTarget
+ }
+
+ public class KeyBind
+ {
+ public KeybindOptions function = KeybindOptions.Bar1Skill1;
+ public string Group = "", Description = "";
+ public Keys Key = 0;
+
+ ///
+ /// Require Options : 0 = Require unpressed key, 1 = Require pressed key, 2 = Don't care
+ ///
+ public byte RequireCtrl = 0;
+ public byte RequireShift = 0;
+ public byte RequireAlt = 0;
+ public byte RequireTilde = 0;
+ }
+
+
+ public class KeyBindSettings
+ {
+ private static InIReader Reader = new InIReader(@".\KeyBinds.ini");
+ public List Keylist = new List();
+ public List DefaultKeylist = new List();
+
+ public KeyBindSettings()
+ {
+ New(Keylist);
+ New(DefaultKeylist);
+
+ if (!File.Exists(@".\KeyBinds.ini"))
+ {
+ Save(DefaultKeylist);
+ return;
+ }
+
+ Load();
+ }
+
+ public void Load()
+ {
+ foreach (KeyBind Inputkey in Keylist)
+ {
+ Inputkey.RequireAlt = Reader.ReadByte(Inputkey.function.ToString(), "RequireAlt", Inputkey.RequireAlt);
+ Inputkey.RequireShift = Reader.ReadByte(Inputkey.function.ToString(), "RequireShift", Inputkey.RequireShift);
+ Inputkey.RequireTilde = Reader.ReadByte(Inputkey.function.ToString(), "RequireTilde", Inputkey.RequireTilde);
+ Inputkey.RequireCtrl = Reader.ReadByte(Inputkey.function.ToString(), "RequireCtrl", Inputkey.RequireCtrl);
+ string Input = Reader.ReadString(Inputkey.function.ToString(), "RequireKey", Inputkey.Key.ToString());
+ Enum.TryParse(Input, out Inputkey.Key);
+
+ }
+ }
+
+ public void Save(List keyList)
+ {
+ Reader.Write("Guide", "01", "RequireAlt,RequireShift,RequireTilde,RequireCtrl");
+ Reader.Write("Guide", "02", "have 3 options: 0/1/2");
+ Reader.Write("Guide", "03", "0 < you cannot have this key pressed to use the function");
+ Reader.Write("Guide", "04", "1 < you have to have this key pressed to use this function");
+ Reader.Write("Guide", "05", "2 < it doesnt matter if you press this key to use this function");
+ Reader.Write("Guide", "06", "by default just use 2, unless you have 2 functions on the same key");
+ Reader.Write("Guide", "07", "example: change attack mode (ctrl+h) and help (h)");
+ Reader.Write("Guide", "08", "if you set either of those to requireshift 2, then they wil both work at the same time or not work");
+ Reader.Write("Guide", "09", "");
+ Reader.Write("Guide", "10", "To get the value for RequireKey look at:");
+ Reader.Write("Guide", "11", "https://msdn.microsoft.com/en-us/library/system.windows.forms.keys(v=vs.110).aspx");
+
+ foreach (KeyBind Inputkey in keyList)
+ {
+ Reader.Write(Inputkey.function.ToString(), "RequireAlt", Inputkey.RequireAlt);
+ Reader.Write(Inputkey.function.ToString(), "RequireShift", Inputkey.RequireShift);
+ Reader.Write(Inputkey.function.ToString(), "RequireTilde", Inputkey.RequireTilde);
+ Reader.Write(Inputkey.function.ToString(), "RequireCtrl", Inputkey.RequireCtrl);
+ Reader.Write(Inputkey.function.ToString(), "RequireKey", Inputkey.Key.ToString());
+ }
+ }
+
+ public void New(List list)
+ {
+ KeyBind InputKey;
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Inventory Open/Close", function = KeybindOptions.Inventory, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.F9 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Inventory Open/Close Alt", function = KeybindOptions.Inventory2, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 0, Key = Keys.I };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Equipment Open/Close", function = KeybindOptions.Equipment, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.F10 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Equipment Open/Close Alt", function = KeybindOptions.Equipment2, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 0, Key = Keys.C };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Skills Open/Close", function = KeybindOptions.Skills, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.F11 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Skills Open/Close Alt", function = KeybindOptions.Skills2, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 0, Key = Keys.S };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Skillbar Open/Close", function = KeybindOptions.Skillbar, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.R };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Relationship Open/Close", function = KeybindOptions.Relationship, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.L };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Friends Open/Close", function = KeybindOptions.Friends, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.F };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Guild Open/Close", function = KeybindOptions.Guilds, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 0, Key = Keys.G };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Gameshop Open/Close", function = KeybindOptions.GameShop, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Y };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Quest Diary Open/Close", function = KeybindOptions.Quests, RequireAlt = 0, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Q };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Options Open/Close", function = KeybindOptions.Options, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.F12 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Options Open/Close Alt", function = KeybindOptions.Options2, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.O };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Group Open/Close", function = KeybindOptions.Group, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.P };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Belt Open/Close", function = KeybindOptions.Belt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 0, Key = Keys.Z };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Minimap Open/Close", function = KeybindOptions.Minimap, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.V };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Bigmap Open/Close", function = KeybindOptions.Bigmap, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.B };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Ranking Open/Close", function = KeybindOptions.Ranking, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.K };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Help Open/Close", function = KeybindOptions.Help, RequireAlt = 2, RequireShift = 0, RequireTilde = 2, RequireCtrl = 0, Key = Keys.H };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Keybinds Open/Close", function = KeybindOptions.Keybind, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.U };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Dialogs", Description = "Close All Windows", function = KeybindOptions.Closeall, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Escape };
+ list.Add(InputKey);
+
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 1", function = KeybindOptions.Bar1Skill1, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F1 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 2", function = KeybindOptions.Bar1Skill2, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F2 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 3", function = KeybindOptions.Bar1Skill3, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F3 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 4", function = KeybindOptions.Bar1Skill4, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F4 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 5", function = KeybindOptions.Bar1Skill5, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F5 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 6", function = KeybindOptions.Bar1Skill6, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F6 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 7", function = KeybindOptions.Bar1Skill7, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F7 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Slot 8", function = KeybindOptions.Bar1Skill8, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 0, Key = Keys.F8 };
+ list.Add(InputKey);
+
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 1", function = KeybindOptions.Bar2Skill1, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F1 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 2", function = KeybindOptions.Bar2Skill2, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F2 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 3", function = KeybindOptions.Bar2Skill3, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F3 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 4", function = KeybindOptions.Bar2Skill4, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F4 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 5", function = KeybindOptions.Bar2Skill5, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F5 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 6", function = KeybindOptions.Bar2Skill6, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F6 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 7", function = KeybindOptions.Bar2Skill7, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F7 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Skillbar", Description = "Skillbar Alt Slot 8", function = KeybindOptions.Bar2Skill8, RequireAlt = 2, RequireShift = 0, RequireTilde = 0, RequireCtrl = 1, Key = Keys.F8 };
+ list.Add(InputKey);
+
+ InputKey = new KeyBind { Group = "Belt", Description = "Rotate Belt", function = KeybindOptions.BeltFlip, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 1, Key = Keys.Z };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 1", function = KeybindOptions.Belt1, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D1 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 1 Alt", function = KeybindOptions.Belt1Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad1 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 2", function = KeybindOptions.Belt2, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D2 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 2 Alt", function = KeybindOptions.Belt2Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad2 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 3", function = KeybindOptions.Belt3, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D3 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 3 Alt", function = KeybindOptions.Belt3Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad3 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 4", function = KeybindOptions.Belt4, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D4 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 4 Alt", function = KeybindOptions.Belt4Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad4 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 5", function = KeybindOptions.Belt5, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D5 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 5 Alt", function = KeybindOptions.Belt5Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad5 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 6", function = KeybindOptions.Belt6, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D6 };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Belt", Description = "Belt Slot 6 Alt", function = KeybindOptions.Belt6Alt, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.NumPad6 };
+ list.Add(InputKey);
+
+ InputKey = new KeyBind { Group = "General", Description = "Logout", function = KeybindOptions.Logout, RequireAlt = 1, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.X };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "General", Description = "Exit", function = KeybindOptions.Exit, RequireAlt = 1, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Q };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "General", Description = "Pickup Floor Item", function = KeybindOptions.Pickup, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Tab };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "General", Description = "Request Trade", function = KeybindOptions.Trade, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.T };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "General", Description = "Recruit Group Member", function = KeybindOptions.AddGroupMember, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 1, Key = Keys.G };
+ list.Add(InputKey);
+
+ InputKey = new KeyBind { Group = "Toggle", Description = "Toggle Attack Mode", function = KeybindOptions.ChangeAttackmode, RequireAlt = 2, RequireShift = 0, RequireTilde = 2, RequireCtrl = 1, Key = Keys.H };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : Peace", function = KeybindOptions.AttackmodePeace, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : Group", function = KeybindOptions.AttackmodeGroup, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : Guild", function = KeybindOptions.AttackmodeGuild, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : Enemy Guild", function = KeybindOptions.AttackmodeEnemyguild, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : Red/Brown", function = KeybindOptions.AttackmodeRedbrown, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Attack Mode : All", function = KeybindOptions.AttackmodeAll, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Toggle Pet Mode", function = KeybindOptions.ChangePetmode, RequireAlt = 0, RequireShift = 2, RequireTilde = 2, RequireCtrl = 1, Key = Keys.A };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Pet Mode : Both", function = KeybindOptions.PetmodeBoth, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Pet Mode : Move Only", function = KeybindOptions.PetmodeMoveonly, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Pet Mode : Attack Only", function = KeybindOptions.PetmodeAttackonly, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Pet Mode : None", function = KeybindOptions.PetmodeNone, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Set Pet Mode : Focus Master Target", function = KeybindOptions.PetmodeFocusMasterTarget, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Toggle Autorun", function = KeybindOptions.Autorun, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.D };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Toggle Camera Mode", function = KeybindOptions.Cameramode, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Insert };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Take Screenshot", function = KeybindOptions.Screenshot, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.PrintScreen };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Toggle", Description = "Toggle Dropview", function = KeybindOptions.DropView, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.Tab };
+ list.Add(InputKey);
+ InputKey = new KeyBind { Group = "Combat", Description = "Hold to enable target spell lock-on", function = KeybindOptions.TargetSpellLockOn, RequireAlt = 2, RequireShift = 2, RequireTilde = 2, RequireCtrl = 2, Key = Keys.None };
+ list.Add(InputKey);
+ }
+
+ public string GetKey(KeybindOptions Option, bool defaultKey = false)
+ {
+ List lst;
+
+ if (defaultKey) lst = CMain.InputKeys.DefaultKeylist;
+ else lst = CMain.InputKeys.Keylist;
+
+ string output = "";
+ for (int i = 0; i < lst.Count; i++)
+ {
+ if (lst[i].function == Option)
+ {
+ if (lst[i].Key == Keys.None) return output;
+ if (lst[i].RequireAlt == 1)
+ output = "Alt";
+ if (lst[i].RequireCtrl == 1)
+ output = output != "" ? output + " + Ctrl" : "Ctrl";
+ if (lst[i].RequireShift == 1)
+ output = output != "" ? output + " + Shift" : "Shift";
+ if (lst[i].RequireTilde == 1)
+ output = output != "" ? output + " + ~" : "~";
+
+ output = output != "" ? output + " + " + lst[i].Key.ToString() : lst[i].Key.ToString();
+ return output;
+ }
+ }
+ return "";
+ }
+ }
+
+
+}
diff --git a/Client/MIR1.ICO b/Client/MIR1.ICO
new file mode 100644
index 0000000..f32c413
Binary files /dev/null and b/Client/MIR1.ICO differ
diff --git a/Client/MirControls/MirAmountBox.cs b/Client/MirControls/MirAmountBox.cs
new file mode 100644
index 0000000..0ad7bab
--- /dev/null
+++ b/Client/MirControls/MirAmountBox.cs
@@ -0,0 +1,220 @@
+using Client.MirGraphics;
+using Client.MirSounds;
+
+namespace Client.MirControls
+{
+ public sealed class MirAmountBox : MirImageControl
+ {
+ public MirLabel TitleLabel, TextLabel;
+ public MirButton OKButton, CancelButton;
+ public MirTextBox InputTextBox;
+ public MirControl ItemImage;
+ private MirGeneratedBox GeneratedBox;
+ private MLibrary ImageLibrary;
+ public int ImageIndex;
+ public uint Amount, MinAmount, MaxAmount;
+
+ public MirAmountBox(string title, int image, MLibrary library, uint max, uint min = 0, uint defaultAmount = 0)
+ {
+ ImageIndex = image;
+ ImageLibrary = library;
+ MaxAmount = max;
+ MinAmount = min;
+ Amount = max;
+ Modal = true;
+ Movable = false;
+ DrawImage = false;
+
+ AutoSize = false;
+ Size = new Size(240, 120);
+ GeneratedBox = new MirGeneratedBox(79, Size)
+ {
+ Parent = this,
+ Visible = true
+ };
+
+ Location = new Point((Settings.ScreenWidth - Size.Width) / 2, (Settings.ScreenHeight - Size.Height) / 2);
+
+ TitleLabel = new MirLabel
+ {
+ AutoSize = true,
+ Location = new Point(19, 8),
+ Parent = this,
+ NotControl = true,
+ Text = title
+ };
+
+ ItemImage = new MirControl
+ {
+ Location = new Point(15, 34),
+ Size = new Size(38, 34),
+ Parent = this,
+ };
+ ItemImage.AfterDraw += (o, e) => DrawItem();
+
+ OKButton = new MirButton
+ {
+ Index = 115,
+ Library = Libraries.Prguse,
+ Location = new Point(23, 76),
+ Parent = this,
+ PressedIndex = 116,
+ };
+ OKButton.Click += (o, e) => Dispose();
+
+ CancelButton = new MirButton
+ {
+ Index = 117,
+ Library = Libraries.Prguse,
+ Location = new Point(110, 76),
+ Parent = this,
+ PressedIndex = 118,
+ };
+ CancelButton.Click += (o, e) => Dispose();
+
+ InputTextBox = new MirTextBox
+ {
+ Parent = this,
+ Border = true,
+ BorderColour = Color.Lime,
+ Location = new Point(58, 43),
+ Size = new Size(132, 19),
+ };
+ InputTextBox.SetFocus();
+ InputTextBox.TextBox.KeyPress += MirInputBox_KeyPress;
+ InputTextBox.TextBox.TextChanged += TextBox_TextChanged;
+ InputTextBox.Text = (defaultAmount > 0 && defaultAmount <= MaxAmount) ? defaultAmount.ToString() : MaxAmount.ToString();
+ InputTextBox.TextBox.SelectionStart = 0;
+ InputTextBox.TextBox.SelectionLength = InputTextBox.Text.Length;
+
+ }
+
+ void TextBox_TextChanged(object sender, EventArgs e)
+ {
+ if (uint.TryParse(InputTextBox.Text, out Amount) && Amount >= MinAmount)
+ {
+ InputTextBox.BorderColour = Color.Lime;
+
+ OKButton.Visible = true;
+ if (Amount > MaxAmount)
+ {
+ Amount = MaxAmount;
+ InputTextBox.Text = MaxAmount.ToString();
+ InputTextBox.TextBox.SelectionStart = InputTextBox.Text.Length;
+ }
+
+ if (Amount == MaxAmount)
+ InputTextBox.BorderColour = Color.Orange;
+ }
+ else
+ {
+ InputTextBox.BorderColour = Color.Red;
+ OKButton.Visible = false;
+ }
+ }
+
+ void MirInputBox_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ if (!char.IsControl(e.KeyChar)
+ && !char.IsDigit(e.KeyChar))
+ {
+ e.Handled = true;
+ }
+
+ if (e.KeyChar == (char)Keys.Enter)
+ {
+ if (OKButton != null && !OKButton.IsDisposed)
+ OKButton.InvokeMouseClick(EventArgs.Empty);
+ e.Handled = true;
+ }
+ else if (e.KeyChar == (char)Keys.Escape)
+ {
+ if (CancelButton != null && !CancelButton.IsDisposed)
+ CancelButton.InvokeMouseClick(EventArgs.Empty);
+ e.Handled = true;
+ }
+ }
+
+ void DrawItem()
+ {
+ int x = ItemImage.DisplayLocation.X, y = ItemImage.DisplayLocation.Y;
+
+ Size s = Libraries.Items.GetTrueSize(ImageIndex);
+
+ x += (ItemImage.Size.Width - s.Width) / 2;
+ y += (ItemImage.Size.Height - s.Height) / 2;
+
+ ImageLibrary.Draw(ImageIndex, x, y);
+ }
+
+ public override void Show()
+ {
+ if (Parent != null) return;
+
+ Parent = MirScene.ActiveScene;
+
+ Highlight();
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = Program.Form.Controls[i] as TextBox;
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }
+
+ /*
+ CMain.Shift = false;
+ CMain.Ctrl = false;
+ CMain.Alt = false;
+
+ Parent = MirScene.ActiveScene;
+ Activate();
+ Highlight();
+
+ for (int i = 0; i < Main.This.Controls.Count; i++)
+ {
+ TextBox T = (TextBox)Main.This.Controls[i];
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }*/
+ }
+ public override void OnKeyDown(KeyEventArgs e)
+ {
+ base.OnKeyDown(e);
+ e.Handled = true;
+ }
+ public override void OnKeyUp(KeyEventArgs e)
+ {
+ base.OnKeyUp(e);
+ e.Handled = true;
+ }
+ public override void OnKeyPress(KeyPressEventArgs e)
+ {
+ base.OnKeyPress(e);
+
+ if (e.KeyChar == (char)Keys.Escape)
+ CancelButton.InvokeMouseClick(EventArgs.Empty);
+ else if (e.KeyChar == (char)Keys.Enter)
+ OKButton.InvokeMouseClick(EventArgs.Empty);
+ e.Handled = true;
+ }
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = (TextBox)Program.Form.Controls[i];
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Client/MirControls/MirAnimatedButton.cs b/Client/MirControls/MirAnimatedButton.cs
new file mode 100644
index 0000000..93f76d0
--- /dev/null
+++ b/Client/MirControls/MirAnimatedButton.cs
@@ -0,0 +1,289 @@
+namespace Client.MirControls
+{
+ public class MirAnimatedButton : MirButton
+ {
+ public static List Animations = new List();
+
+ #region Animated
+
+ private bool _animated;
+ public event EventHandler AnimatedChanged;
+ public bool Animated
+ {
+ get { return _animated; }
+ set
+ {
+ if (_animated == value) return;
+ _animated = value;
+ _nextOffSet = CMain.Time + _fadeInDelay;
+ OnAnimatedChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnAnimatedChanged(EventArgs e)
+ {
+ Redraw();
+ if (AnimatedChanged != null)
+ AnimatedChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region Animation Count
+
+ private int _animationCount;
+ public event EventHandler AnimationCountChanged;
+ public virtual int AnimationCount
+ {
+ get { return _animationCount; }
+ set
+ {
+ if (_animationCount == value) return;
+ _animationCount = value;
+ OnAnimationCountChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnAnimationCountChanged(EventArgs e)
+ {
+ if (AnimationCountChanged != null)
+ AnimationCountChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region Animation Delay
+
+ private long _animationDelay;
+ public event EventHandler AnimationDelayChanged;
+ public long AnimationDelay
+ {
+ get { return _animationDelay; }
+ set
+ {
+ if (_animationDelay == value) return;
+ _animationDelay = value;
+ OnAnimationDelayChanged();
+ }
+ }
+ protected virtual void OnAnimationDelayChanged()
+ {
+ if (AnimationDelayChanged != null)
+ AnimationDelayChanged.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+
+ #region FadeIn
+
+ private long _nextFadeTime;
+ private bool _fadeIn;
+ public event EventHandler FadeInChanged;
+ public bool FadeIn
+ {
+ get { return _fadeIn; }
+ set
+ {
+ if (_fadeIn == value) return;
+ _nextFadeTime = CMain.Time + _fadeInDelay;
+ _fadeIn = value;
+ OnFadeInChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnFadeInChanged(EventArgs e)
+ {
+ if (FadeInChanged != null)
+ FadeInChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region FadeIn Rate
+
+ private float _fadeInRate;
+ public event EventHandler FadeInRateChanged;
+ public virtual float FadeInRate
+ {
+ get { return _fadeInRate; }
+ set
+ {
+ if (_fadeInRate == value) return;
+ _fadeInRate = value;
+ OnFadeInRateChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnFadeInRateChanged(EventArgs e)
+ {
+ if (FadeInRateChanged != null)
+ FadeInRateChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region FadeIn Delay
+
+ private long _fadeInDelay;
+ public event EventHandler FadeInDelayChanged;
+ public long FadeInDelay
+ {
+ get { return _fadeInDelay; }
+ set
+ {
+ if (_fadeInDelay == value) return;
+ _fadeInDelay = value;
+ OnFadeInDelayChanged();
+ }
+ }
+ protected virtual void OnFadeInDelayChanged()
+ {
+ if (FadeInDelayChanged != null)
+ FadeInDelayChanged.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler AfterAnimation;
+
+ #endregion
+
+ public override int Index
+ {
+ get
+ {
+ if (!Enabled)
+ return base.Index;
+
+ if (PressedIndex >= 0 && ActiveControl == this && MouseControl == this)
+ return PressedIndex;
+
+ if (HoverIndex >= 0 && MouseControl == this)
+ return HoverIndex;
+
+ return base.Index + OffSet;
+ }
+ set { base.Index = value; }
+ }
+
+ #region Loop
+
+ private bool _loop;
+ public event EventHandler LoopChanged;
+ public bool Loop
+ {
+ get { return _loop; }
+ set
+ {
+ if (_loop == value) return;
+ _loop = value;
+ OnLoopChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnLoopChanged(EventArgs e)
+ {
+ if (LoopChanged != null)
+ LoopChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region OffSet
+
+ private int _offSet;
+ public event EventHandler OffSetChanged;
+ public virtual int OffSet
+ {
+ protected get { return _offSet; }
+ set
+ {
+ if (_offSet == value) return;
+ _offSet = value;
+ OnOffSetChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnOffSetChanged(EventArgs e)
+ {
+ OnIndexChanged();
+ if (OffSetChanged != null)
+ OffSetChanged.Invoke(this, e);
+ }
+ private long _nextOffSet;
+
+ #endregion
+
+ public MirAnimatedButton()
+ {
+ _loop = true;
+ _nextFadeTime = CMain.Time;
+ _nextOffSet = CMain.Time;
+ Animations.Add(this);
+ }
+
+ public void UpdateOffSet()
+ {
+ if (_fadeIn && CMain.Time > _nextFadeTime)
+ {
+ if ((Opacity += _fadeInRate) > 1F)
+ {
+ Opacity = 1F;
+ _fadeIn = false;
+ }
+
+ _nextFadeTime = CMain.Time + _fadeInDelay;
+ }
+
+ if (!Visible || !_animated || _animationDelay == 0 || _animationCount == 0) return;
+
+ if (CMain.Time < _nextOffSet) return;
+
+ Redraw();
+
+ _nextOffSet = CMain.Time + _animationDelay;
+
+
+ if (++OffSet < _animationCount) return;
+
+ EventHandler temp = AfterAnimation;
+ AfterAnimation = null;
+
+ if (!Loop)
+ Animated = false;
+ else
+ OffSet = 0;
+
+ if (temp != null)
+ temp.Invoke(this, EventArgs.Empty);
+ }
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ AnimatedChanged = null;
+ _animated = false;
+
+ AnimationCountChanged = null;
+ _animationCount = 0;
+
+ AnimationDelayChanged = null;
+ _animationDelay = 0;
+
+ AfterAnimation = null;
+
+ LoopChanged = null;
+ _loop = false;
+
+ OffSetChanged = null;
+ _offSet = 0;
+
+ _nextOffSet = 0;
+
+ Animations.Remove(this);
+ }
+
+ #endregion
+ }
+}
diff --git a/Client/MirControls/MirAnimatedControl.cs b/Client/MirControls/MirAnimatedControl.cs
new file mode 100644
index 0000000..645a210
--- /dev/null
+++ b/Client/MirControls/MirAnimatedControl.cs
@@ -0,0 +1,277 @@
+namespace Client.MirControls
+{
+ public class MirAnimatedControl : MirImageControl
+ {
+ public static List Animations = new List();
+
+ #region Animated
+
+ private bool _animated;
+ public event EventHandler AnimatedChanged;
+ public bool Animated
+ {
+ get { return _animated; }
+ set
+ {
+ if (_animated == value) return;
+ _animated = value;
+ _nextOffSet = CMain.Time + _fadeInDelay;
+ OnAnimatedChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnAnimatedChanged(EventArgs e)
+ {
+ Redraw();
+ if (AnimatedChanged != null)
+ AnimatedChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region Animation Count
+
+ private int _animationCount;
+ public event EventHandler AnimationCountChanged;
+ public virtual int AnimationCount
+ {
+ get { return _animationCount; }
+ set
+ {
+ if (_animationCount == value) return;
+ _animationCount = value;
+ OnAnimationCountChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnAnimationCountChanged(EventArgs e)
+ {
+ if (AnimationCountChanged != null)
+ AnimationCountChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region Animation Delay
+
+ private long _animationDelay;
+ public event EventHandler AnimationDelayChanged;
+ public long AnimationDelay
+ {
+ get { return _animationDelay; }
+ set
+ {
+ if (_animationDelay == value) return;
+ _animationDelay = value;
+ OnAnimationDelayChanged();
+ }
+ }
+ protected virtual void OnAnimationDelayChanged()
+ {
+ if (AnimationDelayChanged != null)
+ AnimationDelayChanged.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+
+ #region FadeIn
+
+ private long _nextFadeTime;
+ private bool _fadeIn;
+ public event EventHandler FadeInChanged;
+ public bool FadeIn
+ {
+ get { return _fadeIn; }
+ set
+ {
+ if (_fadeIn == value) return;
+ _nextFadeTime = CMain.Time + _fadeInDelay;
+ _fadeIn = value;
+ OnFadeInChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnFadeInChanged(EventArgs e)
+ {
+ if (FadeInChanged != null)
+ FadeInChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region FadeIn Rate
+
+ private float _fadeInRate;
+ public event EventHandler FadeInRateChanged;
+ public virtual float FadeInRate
+ {
+ get { return _fadeInRate; }
+ set
+ {
+ if (_fadeInRate == value) return;
+ _fadeInRate = value;
+ OnFadeInRateChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnFadeInRateChanged(EventArgs e)
+ {
+ if (FadeInRateChanged != null)
+ FadeInRateChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region FadeIn Delay
+
+ private long _fadeInDelay;
+ public event EventHandler FadeInDelayChanged;
+ public long FadeInDelay
+ {
+ get { return _fadeInDelay; }
+ set
+ {
+ if (_fadeInDelay == value) return;
+ _fadeInDelay = value;
+ OnFadeInDelayChanged();
+ }
+ }
+ protected virtual void OnFadeInDelayChanged()
+ {
+ if (FadeInDelayChanged != null)
+ FadeInDelayChanged.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler AfterAnimation;
+
+ #endregion
+
+ public override int Index
+ {
+ get { return base.Index + OffSet; }
+ set { base.Index = value; }
+ }
+
+ #region Loop
+
+ private bool _loop;
+ public event EventHandler LoopChanged;
+ public bool Loop
+ {
+ get { return _loop; }
+ set
+ {
+ if (_loop == value) return;
+ _loop = value;
+ OnLoopChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnLoopChanged(EventArgs e)
+ {
+ if (LoopChanged != null)
+ LoopChanged.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region OffSet
+
+ private int _offSet;
+ public event EventHandler OffSetChanged;
+ public virtual int OffSet
+ {
+ protected get { return _offSet; }
+ set
+ {
+ if (_offSet == value) return;
+ _offSet = value;
+ OnOffSetChanged(EventArgs.Empty);
+ }
+ }
+ protected virtual void OnOffSetChanged(EventArgs e)
+ {
+ OnIndexChanged();
+ if (OffSetChanged != null)
+ OffSetChanged.Invoke(this, e);
+ }
+ private long _nextOffSet;
+
+ #endregion
+
+ public MirAnimatedControl()
+ {
+ _loop = true;
+ _nextFadeTime = CMain.Time;
+ _nextOffSet = CMain.Time;
+ Animations.Add(this);
+ }
+
+ public void UpdateOffSet()
+ {
+ if (_fadeIn && CMain.Time > _nextFadeTime)
+ {
+ if ((Opacity += _fadeInRate) > 1F)
+ {
+ Opacity = 1F;
+ _fadeIn = false;
+ }
+
+ _nextFadeTime = CMain.Time + _fadeInDelay;
+ }
+
+ if (!Visible || !_animated || _animationDelay == 0 || _animationCount == 0) return;
+
+ if (CMain.Time < _nextOffSet) return;
+
+ Redraw();
+
+ _nextOffSet = CMain.Time + _animationDelay;
+
+
+ if (++OffSet < _animationCount) return;
+
+ EventHandler temp = AfterAnimation;
+ //AfterAnimation = null;
+
+ if (!Loop)
+ Animated = false;
+ else
+ OffSet = 0;
+
+ if (temp != null)
+ temp.Invoke(this, EventArgs.Empty);
+ }
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ AnimatedChanged = null;
+ _animated = false;
+
+ AnimationCountChanged = null;
+ _animationCount = 0;
+
+ AnimationDelayChanged = null;
+ _animationDelay = 0;
+
+ AfterAnimation = null;
+
+ LoopChanged = null;
+ _loop = false;
+
+ OffSetChanged = null;
+ _offSet = 0;
+
+ _nextOffSet = 0;
+
+ Animations.Remove(this);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Client/MirControls/MirButton.cs b/Client/MirControls/MirButton.cs
new file mode 100644
index 0000000..0aa53d6
--- /dev/null
+++ b/Client/MirControls/MirButton.cs
@@ -0,0 +1,229 @@
+using Client.MirSounds;
+
+namespace Client.MirControls
+{
+ public class MirButton : MirImageControl
+ {
+ #region Font Colour
+ public virtual Color FontColour
+ {
+ get
+ {
+ if (_label != null && !_label.IsDisposed)
+ return _label.ForeColour;
+ return Color.Empty;
+ }
+ set
+ {
+ if (_label != null && !_label.IsDisposed)
+ _label.ForeColour = value;
+ }
+ }
+ #endregion
+
+ #region Hover Index
+ private int _hoverIndex;
+ public int HoverIndex
+ {
+ get { return _hoverIndex; }
+ set
+ {
+ if (_hoverIndex == value)
+ return;
+ _hoverIndex = value;
+ OnHoverIndexChanged();
+ }
+ }
+ public event EventHandler HoverIndexChanged;
+ private void OnHoverIndexChanged()
+ {
+ if (HoverIndexChanged != null)
+ HoverIndexChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Index
+ public override int Index
+ {
+ get
+ {
+ if (!Enabled)
+ return _disabledIndex >= 0 ? _disabledIndex : base.Index;
+
+ if (_pressedIndex >= 0 && ActiveControl == this && MouseControl == this)
+ return _pressedIndex;
+
+ if (_hoverIndex >= 0 && MouseControl == this)
+ return _hoverIndex;
+
+ return base.Index;
+ }
+ set { base.Index = value; }
+ }
+ #endregion
+
+ #region Label
+ protected MirLabel _label;
+ #endregion
+
+ #region CenterText
+ protected bool _center;
+ public virtual bool CenterText
+ {
+ get
+ {
+ return _center;
+ }
+ set
+ {
+ _center = value;
+ if (_center)
+ {
+ _label.Size = Size;
+ _label.DrawFormat = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
+ }
+ else
+ _label.AutoSize = true;
+ }
+ }
+ #endregion
+
+ #region Pressed Index
+ private int _pressedIndex;
+ public int PressedIndex
+ {
+ set
+ {
+ if (_pressedIndex == value)
+ return;
+ _pressedIndex = value;
+ OnPressedIndexChanged();
+ }
+ get { return _pressedIndex; }
+ }
+
+ public event EventHandler PressedIndexChanged;
+ private void OnPressedIndexChanged()
+ {
+ if (PressedIndexChanged != null)
+ PressedIndexChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Disabled Index
+ private int _disabledIndex;
+ public int DisabledIndex
+ {
+ set
+ {
+ if (_disabledIndex == value)
+ return;
+ _disabledIndex = value;
+ OnDisabledIndexChanged();
+ }
+ get { return _disabledIndex; }
+ }
+
+ public event EventHandler DisabledIndexChanged;
+ private void OnDisabledIndexChanged()
+ {
+ if (DisabledIndexChanged != null)
+ DisabledIndexChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Size
+ protected override void OnSizeChanged()
+ {
+ base.OnSizeChanged();
+
+ if (_label != null && !_label.IsDisposed)
+ _label.Size = Size;
+ }
+ #endregion
+
+ #region Text
+ public virtual string Text
+ {
+ set
+ {
+ if (_label == null || _label.IsDisposed)
+ return;
+ _label.Text = value;
+ _label.Visible = !string.IsNullOrEmpty(value);
+ }
+ }
+ #endregion
+
+ public bool OnlyDrawWhenActive;
+
+ public MirButton()
+ {
+ HoverIndex = -1;
+ PressedIndex = -1;
+ DisabledIndex = -1;
+ Sound = SoundList.ButtonB;
+
+ _label = new MirLabel
+ {
+ NotControl = true,
+ Parent = this,
+ //Font = new Font("Constantia", 8, FontStyle.Italic),
+ //OutLine = true,
+ //OutLineColour = Color.FromArgb(255, 70, 50, 30),
+ };
+ }
+
+ protected internal override void DrawControl()
+ {
+ if (OnlyDrawWhenActive && ActiveControl != this && MouseControl != this)
+ return;
+
+ base.DrawControl();
+ }
+
+ protected override void Highlight()
+ {
+ Redraw();
+ base.Highlight();
+ }
+ protected override void Activate()
+ {
+ Redraw();
+ base.Activate();
+ }
+ protected override void Dehighlight()
+ {
+ Redraw();
+ base.Dehighlight();
+ }
+ protected override void Deactivate()
+ {
+ Redraw();
+ base.Deactivate();
+ }
+
+
+ #region Disposable
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ HoverIndexChanged = null;
+ _hoverIndex = 0;
+
+ if (_label != null && !_label.IsDisposed)
+ _label.Dispose();
+ _label = null;
+
+ PressedIndexChanged = null;
+ _pressedIndex = 0;
+
+ DisabledIndexChanged = null;
+ _disabledIndex = 0;
+ }
+ #endregion
+ }
+}
diff --git a/Client/MirControls/MirCheckBox.cs b/Client/MirControls/MirCheckBox.cs
new file mode 100644
index 0000000..56b8d7b
--- /dev/null
+++ b/Client/MirControls/MirCheckBox.cs
@@ -0,0 +1,102 @@
+using Client.MirSounds;
+
+namespace Client.MirControls
+{
+ public class MirCheckBox : MirButton
+ {
+
+ #region TickedIndex
+ private int _tickedIndex;
+ public int TickedIndex
+ {
+ get { return _tickedIndex; }
+ set { _tickedIndex = value; }
+ }
+ #endregion
+
+ #region UnTickedIndex
+ private int _untickedIndex;
+ public int UnTickedIndex
+ {
+ get { return _untickedIndex; }
+ set { _untickedIndex = value; }
+ }
+ #endregion
+
+ #region Checked
+ private bool _checked;
+ public bool Checked
+ {
+ get { return _checked; }
+ set { _checked = value; Index = value ? TickedIndex : UnTickedIndex; Redraw(); }
+ }
+ #endregion
+
+ #region Label
+ private new MirLabel _label;
+ #endregion
+
+ #region CenterText
+ private new bool _center;
+ public bool CenterLabelText
+ {
+ get
+ {
+ return _center;
+ }
+ set
+ {
+ _center = value;
+ if (_center)
+ {
+ _label.Size = Size;
+ _label.DrawFormat = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
+ }
+ else
+ _label.AutoSize = true;
+ }
+ }
+ #endregion
+
+ #region LabelText
+ public string LabelText
+ {
+ set
+ {
+ if (_label == null || _label.IsDisposed)
+ return;
+ _label.Text = value;
+ _label.Visible = !string.IsNullOrEmpty(value);
+ }
+ }
+ #endregion
+
+ public MirCheckBox()
+ {
+ TickedIndex = -1;
+ UnTickedIndex = -1;
+ Index = -1;
+ HoverIndex = -1;
+ PressedIndex = -1;
+ DisabledIndex = -1;
+ Sound = SoundList.ButtonB;
+ Click += MirCheckBox_Click;
+
+ _label = new MirLabel
+ {
+ AutoSize = true,
+ NotControl = true,
+ Location = new Point(15, -2),
+ Parent = this
+ };
+ }
+
+ private void MirCheckBox_Click(object sender, EventArgs e)
+ {
+ Checked = !Checked;
+ if (Checked) Index = TickedIndex;
+ else Index = UnTickedIndex;
+ Redraw();
+ }
+ }
+}
diff --git a/Client/MirControls/MirControl.cs b/Client/MirControls/MirControl.cs
new file mode 100644
index 0000000..0a4ea66
--- /dev/null
+++ b/Client/MirControls/MirControl.cs
@@ -0,0 +1,1124 @@
+using Client.MirGraphics;
+using Client.MirSounds;
+using SlimDX;
+using SlimDX.Direct3D9;
+
+namespace Client.MirControls
+{
+ public class MirControl : IDisposable
+ {
+ public static MirControl ActiveControl, MouseControl;
+
+ public virtual Point DisplayLocation { get { return Parent == null ? Location : Parent.DisplayLocation.Add(Location); } }
+ public Rectangle DisplayRectangle { get { return new Rectangle(DisplayLocation, Size); } }
+
+ public bool GrayScale { get; set; }
+ public bool Blending { get; set; }
+ public float BlendingRate { get; set; }
+ public BlendMode BlendMode { get; set; }
+
+ #region Back Colour
+ private Color _backColour;
+ public Color BackColour
+ {
+ get { return _backColour; }
+ set
+ {
+ if (_backColour == value)
+ return;
+ _backColour = value;
+ OnBackColourChanged();
+ }
+ }
+ public event EventHandler BackColourChanged;
+ protected virtual void OnBackColourChanged()
+ {
+ TextureValid = false;
+ Redraw();
+ if (BackColourChanged != null)
+ BackColourChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Border
+ protected Rectangle BorderRectangle;
+ private bool _border;
+ protected Vector2[] _borderInfo;
+ protected virtual Vector2[] BorderInfo
+ {
+ get
+ {
+ if (Size == Size.Empty)
+ return null;
+
+ if (BorderRectangle != DisplayRectangle)
+ {
+ _borderInfo = new[]
+ {
+ new Vector2(DisplayRectangle.Left - 1, DisplayRectangle.Top - 1),
+ new Vector2(DisplayRectangle.Right, DisplayRectangle.Top - 1),
+ new Vector2(DisplayRectangle.Left - 1, DisplayRectangle.Top - 1),
+ new Vector2(DisplayRectangle.Left - 1, DisplayRectangle.Bottom),
+ new Vector2(DisplayRectangle.Left - 1, DisplayRectangle.Bottom),
+ new Vector2(DisplayRectangle.Right, DisplayRectangle.Bottom),
+ new Vector2(DisplayRectangle.Right, DisplayRectangle.Top - 1),
+ new Vector2(DisplayRectangle.Right, DisplayRectangle.Bottom)
+ };
+
+ BorderRectangle = DisplayRectangle;
+ }
+ return _borderInfo;
+ }
+ }
+ public virtual bool Border
+ {
+ get { return _border; }
+ set
+ {
+ if (_border == value)
+ return;
+ _border = value;
+ OnBorderChanged();
+ }
+ }
+ public event EventHandler BorderChanged;
+ private void OnBorderChanged()
+ {
+ Redraw();
+ if (BorderChanged != null)
+ BorderChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Border Colour
+ private Color _borderColour;
+ public Color BorderColour
+ {
+ get { return _borderColour; }
+ set
+ {
+ if (_borderColour == value)
+ return;
+ _borderColour = value;
+ OnBorderColourChanged();
+ }
+ }
+ public event EventHandler BorderColourChanged;
+ private void OnBorderColourChanged()
+ {
+ Redraw();
+ if (BorderColourChanged != null)
+ BorderColourChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Control Texture
+ public long CleanTime;
+ protected Texture ControlTexture;
+ protected internal bool TextureValid;
+ private bool _drawControlTexture;
+ protected Size TextureSize;
+ public bool DrawControlTexture
+ {
+ get { return _drawControlTexture; }
+ set
+ {
+ if (_drawControlTexture == value)
+ return;
+ _drawControlTexture = value;
+ Redraw();
+ }
+ }
+ protected virtual void CreateTexture()
+ {
+ if (ControlTexture == null || ControlTexture.Disposed)
+ {
+ DXManager.ControlList.Add(this);
+ ControlTexture = new Texture(DXManager.Device, Size.Width, Size.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
+ TextureSize = Size;
+ }
+
+ Surface oldSurface = DXManager.CurrentSurface;
+ Surface surface = ControlTexture.GetSurfaceLevel(0);
+ DXManager.SetSurface(surface);
+ DXManager.Device.Clear(ClearFlags.Target, BackColour, 0, 0);
+ DXManager.SetSurface(oldSurface);
+
+ TextureValid = true;
+ surface.Dispose();
+ }
+
+ internal void DisposeTexture()
+ {
+ if (ControlTexture == null || ControlTexture.Disposed) return;
+
+ ControlTexture.Dispose();
+ ControlTexture = null;
+ TextureValid = false;
+ TextureSize = Size.Empty;
+
+ DXManager.ControlList.Remove(this);
+ }
+ #endregion
+
+ #region Controls
+ public List Controls { get; private set; }
+ public event EventHandler ControlAdded , ControlRemoved;
+ private void AddControl(MirControl control)
+ {
+ Controls.Add(control);
+ OnControlAdded();
+ }
+ public void InsertControl(int index, MirControl control)
+ {
+ if (control.Parent != this)
+ {
+ control.Parent = null;
+ control._parent = this;
+ }
+
+ if (index >= Controls.Count)
+ Controls.Add(control);
+ else
+ {
+ Controls.Insert(index, control);
+ OnControlAdded();
+ }
+ }
+ private void RemoveControl(MirControl control)
+ {
+ Controls.Remove(control);
+ OnControlRemoved();
+ }
+ private void OnControlAdded()
+ {
+ Redraw();
+ if (ControlAdded != null)
+ ControlAdded.Invoke(this, EventArgs.Empty);
+ }
+ private void OnControlRemoved()
+ {
+ Redraw();
+ if (ControlRemoved != null)
+ ControlRemoved.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Enabled
+ private bool _enabled;
+ public bool Enabled
+ {
+ internal get { return Parent == null ? _enabled : Parent.Enabled && _enabled; }
+ set
+ {
+ if (_enabled == value)
+ return;
+ _enabled = value;
+ OnEnabledChanged();
+ }
+ }
+ public event EventHandler EnabledChanged;
+ protected virtual void OnEnabledChanged()
+ {
+ Redraw();
+
+ if (EnabledChanged != null)
+ EnabledChanged.Invoke(this, EventArgs.Empty);
+
+ if (!Enabled && ActiveControl == this)
+ ActiveControl.Deactivate();
+
+ if (Controls != null)
+ foreach (MirControl control in Controls)
+ control.OnEnabledChanged();
+ }
+ public bool AllowDisabledMouseOver;
+ #endregion
+
+ #region Events
+ protected bool HasShown;
+ public event EventHandler Click , DoubleClick, BeforeDraw , AfterDraw , MouseEnter , MouseLeave , Shown , BeforeShown, Disposing;
+ public event MouseEventHandler MouseWheel,MouseMove, MouseDown, MouseUp;
+ public event KeyEventHandler KeyDown , KeyUp;
+ public event KeyPressEventHandler KeyPress;
+ #endregion
+
+ #region Fore Colour
+ private Color _foreColour;
+ public Color ForeColour
+ {
+ get { return _foreColour; }
+ set
+ {
+ if (_foreColour == value)
+ return;
+ _foreColour = value;
+ OnForeColourChanged();
+ }
+ }
+ public event EventHandler ForeColourChanged;
+ protected virtual void OnForeColourChanged()
+ {
+ TextureValid = false;
+ if (ForeColourChanged != null)
+ ForeColourChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Location
+ private Point _location;
+ public Point Location
+ {
+ get { return _location; }
+ set
+ {
+ if (_location == value)
+ return;
+ _location = value;
+ OnLocationChanged();
+ }
+ }
+ public event EventHandler LocationChanged;
+ protected virtual void OnLocationChanged()
+ {
+ Redraw();
+ if (Controls != null)
+ for (int i = 0; i < Controls.Count; i++)
+ Controls[i].OnLocationChanged();
+
+ if (LocationChanged != null)
+ LocationChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Hint
+ private string _hint;
+ public string Hint
+ {
+ get { return _hint; }
+ set
+ {
+ if (_hint == value)
+ return;
+
+ _hint = value;
+ OnHintChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler HintChanged;
+ private void OnHintChanged(EventArgs e)
+ {
+ Redraw();
+ if (HintChanged != null)
+ HintChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region Modal
+ private bool _modal;
+ public bool Modal
+ {
+ get { return _modal; }
+ set
+ {
+ if (_modal == value)
+ return;
+ _modal = value;
+ OnModalChanged();
+ }
+ }
+ public event EventHandler ModalChanged;
+ private void OnModalChanged()
+ {
+ Redraw();
+ if (ModalChanged != null)
+ ModalChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Movable
+ protected internal bool Moving;
+ private bool _movable;
+ private Point _movePoint;
+
+ public bool Movable
+ {
+ get { return _movable; }
+ set
+ {
+ if (_movable == value)
+ return;
+ _movable = value;
+ OnMovableChanged();
+ }
+ }
+
+ public event EventHandler MovableChanged;
+ public event MouseEventHandler OnMoving;
+
+ private void OnMovableChanged()
+ {
+ Redraw();
+ if (MovableChanged != null)
+ MovableChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Not Control
+ private bool _notControl;
+ public bool NotControl
+ {
+ private get { return _notControl; }
+ set
+ {
+ if (_notControl == value)
+ return;
+ _notControl = value;
+ OnNotControlChanged();
+ }
+ }
+ public event EventHandler NotControlChanged;
+ private void OnNotControlChanged()
+ {
+ Redraw();
+ if (NotControlChanged != null)
+ NotControlChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Opacity
+ private float _opacity;
+ public float Opacity
+ {
+ get { return _opacity; }
+ set
+ {
+ if (value > 1F)
+ value = 1F;
+ if (value < 0F)
+ value = 0;
+
+ if (_opacity == value)
+ return;
+
+ _opacity = value;
+ OnOpacityChanged();
+ }
+ }
+ public event EventHandler OpacityChanged;
+ private void OnOpacityChanged()
+ {
+ Redraw();
+ if (OpacityChanged != null)
+ OpacityChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Parent
+ private MirControl _parent;
+ public MirControl Parent
+ {
+ get { return _parent; }
+ set
+ {
+ if (_parent == value) return;
+
+ if (_parent != null)
+ _parent.RemoveControl(this);
+ _parent = value;
+ if (_parent != null)
+ _parent.AddControl(this);
+ OnParentChanged();
+ }
+ }
+ public event EventHandler ParentChanged;
+ protected virtual void OnParentChanged()
+ {
+ OnLocationChanged();
+ if (ParentChanged != null)
+ ParentChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Size
+
+// ReSharper disable InconsistentNaming
+ protected Size _size;
+// ReSharper restore InconsistentNaming
+
+ public virtual Size Size
+ {
+ get { return _size; }
+ set
+ {
+ if (_size == value)
+ return;
+ _size = value;
+ OnSizeChanged();
+ }
+ }
+
+ public virtual Size TrueSize
+ {
+ get { return _size; }
+ }
+
+ public event EventHandler SizeChanged;
+ protected virtual void OnSizeChanged()
+ {
+ TextureValid = false;
+ Redraw();
+
+ if (SizeChanged != null)
+ SizeChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Sound
+ private int _sound;
+ public int Sound
+ {
+ get { return _sound; }
+ set
+ {
+ if (_sound == value)
+ return;
+ _sound = value;
+ OnSoundChanged();
+ }
+ }
+ public event EventHandler SoundChanged;
+ private void OnSoundChanged()
+ {
+ if (SoundChanged != null)
+ SoundChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Sort
+ private bool _sort;
+ public bool Sort
+ {
+ get { return _sort; }
+ set
+ {
+ if (_sort == value)
+ return;
+ _sort = value;
+ OnSortChanged();
+ }
+ }
+ public event EventHandler SortChanged;
+ private void OnSortChanged()
+ {
+ Redraw();
+ if (SortChanged != null)
+ SortChanged.Invoke(this, EventArgs.Empty);
+ }
+ public void TrySort()
+ {
+ if (Parent == null)
+ return;
+
+ Parent.TrySort();
+
+ if (Parent.Controls[Parent.Controls.Count - 1] == this)
+ return;
+
+ if (!Sort) return;
+
+ Parent.Controls.Remove(this);
+ Parent.Controls.Add(this);
+
+ Redraw();
+ }
+ #endregion
+
+ #region Visible
+ private bool _visible;
+ public virtual bool Visible
+ {
+ get { return Parent == null ? _visible : Parent.Visible && _visible; }
+ set
+ {
+ if (_visible == value)
+ return;
+ _visible = value;
+ OnVisibleChanged();
+ }
+ }
+ public event EventHandler VisibleChanged;
+ protected virtual void OnVisibleChanged()
+ {
+ Redraw();
+ if (VisibleChanged != null)
+ VisibleChanged.Invoke(this, EventArgs.Empty);
+
+ Moving = false;
+ _movePoint = Point.Empty;
+
+ if (Sort && Parent != null)
+ {
+ Parent.Controls.Remove(this);
+ Parent.Controls.Add(this);
+ }
+
+ if (MouseControl == this && !Visible)
+ {
+ Dehighlight();
+ Deactivate();
+ }
+ else if (IsMouseOver(CMain.MPoint))
+ Highlight();
+
+
+ if (Controls != null)
+ foreach (MirControl control in Controls)
+ control.OnVisibleChanged();
+ }
+ protected void OnBeforeShown()
+ {
+ if (HasShown)
+ return;
+
+ if (Visible && IsMouseOver(CMain.MPoint))
+ Highlight();
+
+ if (BeforeShown != null)
+ BeforeShown.Invoke(this, EventArgs.Empty);
+ }
+ protected void OnShown()
+ {
+ if (HasShown)
+ return;
+
+ if (Shown != null)
+ Shown.Invoke(this, EventArgs.Empty);
+
+ HasShown = true;
+ }
+ #endregion
+
+ #region MultiLine
+
+ public virtual void MultiLine()
+ {
+ }
+
+ #endregion
+
+ #region Positions
+
+ protected Point Center
+ {
+ get { return new Point((Settings.ScreenWidth - Size.Width) / 2, (Settings.ScreenHeight - Size.Height) / 2); }
+ }
+
+ protected Point Left
+ {
+ get { return new Point(0, (Settings.ScreenHeight - Size.Height) / 2); }
+ }
+
+ protected Point Top
+ {
+ get { return new Point((Settings.ScreenWidth - Size.Width) / 2, 0); }
+ }
+
+ protected Point Right
+ {
+ get { return new Point(Settings.ScreenWidth - Size.Width, (Settings.ScreenHeight - Size.Height) / 2); }
+ }
+
+ protected Point Bottom
+ {
+ get { return new Point((Settings.ScreenWidth - Size.Width) / 2, Settings.ScreenHeight - Size.Height); }
+ }
+
+ protected Point TopLeft
+ {
+ get { return new Point(0, 0); }
+ }
+
+ protected Point TopRight
+ {
+ get { return new Point(Settings.ScreenWidth - Size.Width, 0); }
+ }
+
+ protected Point BottomRight
+ {
+ get { return new Point(Settings.ScreenWidth - Size.Width, Settings.ScreenHeight - Size.Height); }
+ }
+
+ protected Point BottomLeft
+ {
+ get { return new Point(0, Settings.ScreenHeight - Size.Height); }
+ }
+
+ #endregion
+
+
+ public void BringToFront()
+ {
+ if (Parent == null) return;
+ int index = _parent.Controls.IndexOf(this);
+ if (index == _parent.Controls.Count - 1) return;
+
+ _parent.Controls.RemoveAt(index);
+ _parent.Controls.Add(this);
+ Redraw();
+ }
+
+ public MirControl()
+ {
+ Controls = new List();
+ _opacity = 1F;
+ _enabled = true;
+ _foreColour = Color.White;
+ _visible = true;
+ _sound = SoundList.None;
+ }
+
+ public virtual void Show()
+ {
+ if (Visible) return;
+ Visible = true;
+ }
+
+ public virtual void Hide()
+ {
+ if (!Visible) return;
+ Visible = false;
+ }
+
+ public virtual void Draw()
+ {
+ if (IsDisposed || !Visible /*|| Size.Width == 0 || Size.Height == 0*/ || Size.Width > Settings.ScreenWidth || Size.Height > Settings.ScreenHeight)
+ return;
+
+ OnBeforeShown();
+
+ BeforeDrawControl();
+ DrawControl();
+ DrawChildControls();
+ DrawBorder();
+ AfterDrawControl();
+
+ CleanTime = CMain.Time + Settings.CleanDelay;
+
+ OnShown();
+ }
+
+ protected virtual void BeforeDrawControl()
+ {
+ if (BeforeDraw != null)
+ BeforeDraw.Invoke(this, EventArgs.Empty);
+ }
+ protected internal virtual void DrawControl()
+ {
+ if (!DrawControlTexture)
+ return;
+
+ if (!TextureValid)
+ CreateTexture();
+
+ if (ControlTexture == null || ControlTexture.Disposed)
+ return;
+
+ DXManager.DrawOpaque(ControlTexture, new Rectangle(0, 0, Size.Width, Size.Height), new Vector3?(new Vector3((float)(DisplayLocation.X), (float)(DisplayLocation.Y), 0.0f)), Color.White, Opacity);
+
+ CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ protected void DrawChildControls()
+ {
+ if (Controls != null)
+ for (int i = 0; i < Controls.Count; i++)
+ if (Controls[i] != null)
+ Controls[i].Draw();
+ }
+ protected virtual void DrawBorder()
+ {
+ if (!Border || BorderInfo == null)
+ return;
+ DXManager.Sprite.Flush();
+ DXManager.Line.Draw(BorderInfo, _borderColour);
+ }
+ protected void AfterDrawControl()
+ {
+ if (AfterDraw != null)
+ AfterDraw.Invoke(this, EventArgs.Empty);
+ }
+
+ protected virtual void Deactivate()
+ {
+ if (ActiveControl != this)
+ return;
+
+ ActiveControl = null;
+ Moving = false;
+ _movePoint = Point.Empty;
+ }
+ protected virtual void Dehighlight()
+ {
+ if (MouseControl != this)
+ return;
+ MouseControl.OnMouseLeave();
+ MouseControl = null;
+ }
+ protected virtual void Activate()
+ {
+ if (ActiveControl == this)
+ return;
+
+ if (ActiveControl != null)
+ ActiveControl.Deactivate();
+
+ ActiveControl = this;
+ }
+ protected virtual void Highlight()
+ {
+ if (MouseControl == this)
+ return;
+ if (NotControl)
+ {
+
+ }
+ if (MouseControl != null)
+ MouseControl.Dehighlight();
+
+ if (ActiveControl != null && ActiveControl != this) return;
+
+ OnMouseEnter();
+ MouseControl = this;
+ }
+
+ public virtual bool IsMouseOver(Point p)
+ {
+ return Visible && (DisplayRectangle.Contains(p) || Moving || Modal) && !NotControl;
+ }
+ protected virtual void OnMouseEnter()
+ {
+ if (!_enabled && !AllowDisabledMouseOver)
+ return;
+
+ Redraw();
+
+ if (MouseEnter != null)
+ MouseEnter.Invoke(this, EventArgs.Empty);
+ }
+ protected virtual void OnMouseLeave()
+ {
+ if (!_enabled && !AllowDisabledMouseOver)
+ return;
+
+ Redraw();
+
+ if (MouseLeave != null)
+ MouseLeave.Invoke(this, EventArgs.Empty);
+ }
+ public virtual void OnMouseClick(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ if (Sound != SoundList.None)
+ SoundManager.PlaySound(Sound);
+
+ if (Click != null)
+ InvokeMouseClick(e);
+ }
+ public virtual void OnMouseDoubleClick(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ if (DoubleClick != null)
+ {
+ if (Sound != SoundList.None)
+ SoundManager.PlaySound(Sound);
+ InvokeMouseDoubleClick(e);
+ }
+ else
+ OnMouseClick(e);
+ }
+ public void InvokeMouseClick(EventArgs e)
+ {
+ if (Click != null)
+ Click.Invoke(this, e);
+ }
+ public void InvokeMouseDoubleClick(EventArgs e)
+ {
+ DoubleClick.Invoke(this, e);
+ }
+ public virtual void OnMouseMove(MouseEventArgs e)
+ {
+ if (!_enabled && !AllowDisabledMouseOver)
+ return;
+
+
+ if (Moving)
+ {
+ Point tempPoint = CMain.MPoint.Subtract(_movePoint);
+
+ if (Parent == null)
+ {
+ if (tempPoint.Y + TrueSize.Height > Settings.ScreenHeight)
+ tempPoint.Y = Settings.ScreenHeight - TrueSize.Height - 1;
+
+ if (tempPoint.X + TrueSize.Width > Settings.ScreenWidth)
+ tempPoint.X = Settings.ScreenWidth - TrueSize.Width - 1;
+ }
+ else
+ {
+ if (tempPoint.Y + TrueSize.Height > Parent.TrueSize.Height)
+ tempPoint.Y = Parent.TrueSize.Height - TrueSize.Height;
+
+ if (tempPoint.X + TrueSize.Width > Parent.TrueSize.Width)
+ tempPoint.X = Parent.TrueSize.Width - TrueSize.Width;
+ }
+
+ if (tempPoint.X < 0)
+ tempPoint.X = 0;
+ if (tempPoint.Y < 0)
+ tempPoint.Y = 0;
+
+ Location = tempPoint;
+ if (OnMoving != null)
+ OnMoving.Invoke(this, e);
+ return;
+ }
+
+ if (Controls != null)
+ for (int i = Controls.Count - 1; i >= 0; i--)
+ if (Controls[i].IsMouseOver(CMain.MPoint))
+ {
+ Controls[i].OnMouseMove(e);
+ return;
+ }
+
+ Highlight();
+
+ if (MouseMove != null)
+ MouseMove.Invoke(this, e);
+ }
+ public virtual void OnMouseDown(MouseEventArgs e)
+ {
+ if (!_enabled)
+ return;
+
+ Activate();
+
+ TrySort();
+
+ if (_movable)
+ {
+ Moving = true;
+ _movePoint = CMain.MPoint.Subtract(Location);
+ }
+
+ if (MouseDown != null)
+ MouseDown.Invoke(this, e);
+ }
+ public virtual void OnMouseUp(MouseEventArgs e)
+ {
+ if (!_enabled)
+ return;
+
+ if (Moving)
+ {
+ Moving = false;
+ _movePoint = Point.Empty;
+ }
+
+ if (ActiveControl != null) ActiveControl.Deactivate();
+
+ if (MouseUp != null)
+ MouseUp.Invoke(this, e);
+ }
+ public virtual void OnMouseWheel(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ MouseWheel?.Invoke(this, e);
+ }
+ public virtual void OnKeyPress(KeyPressEventArgs e)
+ {
+ if (!_enabled)
+ return;
+
+ if (Controls != null)
+ for (int i = Controls.Count - 1; i >= 0; i--)
+ if (e.Handled)
+ return;
+ else
+ Controls[i].OnKeyPress(e);
+
+ if (KeyPress == null)
+ return;
+ KeyPress.Invoke(this, e);
+ }
+ public virtual void OnKeyDown(KeyEventArgs e)
+ {
+ if (!_enabled)
+ return;
+
+ if (Controls != null)
+ for (int i = Controls.Count - 1; i >= 0; i--)
+ if (e.Handled)
+ return;
+ else
+ Controls[i].OnKeyDown(e);
+
+ if (KeyDown == null)
+ return;
+ KeyDown.Invoke(this, e);
+ }
+ public virtual void OnKeyUp(KeyEventArgs e)
+ {
+ if (!_enabled)
+ return;
+
+ if (Controls != null)
+ for (int i = Controls.Count - 1; i >= 0; i--)
+ if (e.Handled)
+ return;
+ else
+ Controls[i].OnKeyUp(e);
+
+ if (KeyUp == null)
+ return;
+ KeyUp.Invoke(this, e);
+ }
+
+ public virtual void Redraw()
+ {
+ if (Parent != null) Parent.Redraw();
+
+ }
+
+ #region Font
+ public virtual System.Drawing.Font ScaleFont(System.Drawing.Font font)
+ {
+ var theFont = new System.Drawing.Font(font.Name, font.Size * 96f / CMain.Graphics.DpiX, font.Style);
+ font.Dispose();
+
+ return theFont;
+ }
+ #endregion
+
+ #region Disposable
+ public bool IsDisposed { get; private set; }
+
+ public void Dispose()
+ {
+ if (IsDisposed)
+ return;
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (Disposing != null)
+ Disposing.Invoke(this, EventArgs.Empty);
+
+ Disposing = null;
+
+ BackColourChanged = null;
+ _backColour = Color.Empty;
+
+ BorderChanged = null;
+ _border = false;
+ BorderRectangle = Rectangle.Empty;
+ _borderInfo = null;
+
+ BorderColourChanged = null;
+ _borderColour = Color.Empty;
+
+ DrawControlTexture = false;
+ DisposeTexture();
+
+ ControlAdded = null;
+ ControlRemoved = null;
+
+ if (Controls != null)
+ {
+ for (int i = Controls.Count - 1; i >= 0; i--)
+ {
+ if (Controls[i] != null && !Controls[i].IsDisposed)
+ Controls[i].Dispose();
+ }
+
+ Controls = null;
+ }
+ _enabled = false;
+ EnabledChanged = null;
+
+ HasShown = false;
+
+ BeforeDraw = null;
+ AfterDraw = null;
+ Shown = null;
+ BeforeShown = null;
+
+ Click = null;
+ DoubleClick = null;
+ MouseEnter = null;
+ MouseLeave = null;
+ MouseMove = null;
+ MouseDown = null;
+ MouseUp = null;
+ MouseWheel = null;
+
+ KeyPress = null;
+ KeyUp = null;
+ KeyDown = null;
+
+ ForeColourChanged = null;
+ _foreColour = Color.Empty;
+
+ LocationChanged = null;
+ _location = Point.Empty;
+
+ ModalChanged = null;
+ _modal = false;
+
+ MovableChanged = null;
+ _movePoint = Point.Empty;
+ Moving = false;
+ OnMoving = null;
+ _movable = false;
+
+ NotControlChanged = null;
+ _notControl = false;
+
+ OpacityChanged = null;
+ _opacity = 0F;
+
+ if (Parent != null && Parent.Controls != null)
+ Parent.Controls.Remove(this);
+ ParentChanged = null;
+ _parent = null;
+
+ SizeChanged = null;
+ _size = Size.Empty;
+
+ SoundChanged = null;
+ _sound = 0;
+
+ VisibleChanged = null;
+ _visible = false;
+
+ if (ActiveControl == this) ActiveControl = null;
+ if (MouseControl == this) MouseControl = null;
+ }
+
+ IsDisposed = true;
+ }
+ #endregion
+
+
+
+ }
+}
diff --git a/Client/MirControls/MirDropDownBox.cs b/Client/MirControls/MirDropDownBox.cs
new file mode 100644
index 0000000..51bf96b
--- /dev/null
+++ b/Client/MirControls/MirDropDownBox.cs
@@ -0,0 +1,350 @@
+using Client.MirGraphics;
+
+namespace Client.MirControls
+{
+ public class MirDropDownBox : MirControl
+ {
+ private MirLabel _label;
+ private MirButton _DropDownButton;
+ private MirLabel[] _Option = new MirLabel[5];
+ private MirButton _ScrollUp, _ScrollDown, _ScrollPosition;
+
+ public int _SelectedIndex = -1;
+ public int _WantedIndex = -1;
+ public int MinimumOption = 0;
+ public int ScrollIndex = 0;
+ public int OrigHeight = 0;
+ public long LastMouseLeave = 0;
+ private List _Items = new List();
+ public event EventHandler ValueChanged;
+
+ public int SelectedIndex
+ {
+ get
+ {
+ return _SelectedIndex;
+ }
+ set
+ {
+ _SelectedIndex = value;
+ if (_SelectedIndex >= Items.Count)
+ _SelectedIndex = -1;
+ }
+ }
+
+ public List Items
+ {
+ get
+ {
+ return _Items;
+ }
+ set
+ {
+ _Items = value;
+ ItemsChanged();
+ }
+ }
+
+ #region Back Color
+
+ protected override void OnBackColourChanged()
+ {
+ base.OnBackColourChanged();
+ if (_label != null && !_label.IsDisposed)
+ _label.BackColour = BackColour;
+ }
+
+ #endregion
+
+ #region Size
+ protected override void OnSizeChanged()
+ {
+ base.OnSizeChanged();
+ OrigHeight = OrigHeight == 0 ? Size.Height : OrigHeight;
+ for (int i = 0; i < _Option.Length; i++)
+ {
+ _Option[i].Size = new Size(Size.Width - 16, 16); //Size.Width - 13, 13
+ }
+
+ if (_label != null && !_label.IsDisposed)
+ _label.Size = new Size(Size.Width - 16, 15); //Size.Width - 16, 12
+ if (_DropDownButton != null && !_DropDownButton.IsDisposed)
+ _DropDownButton.Location = new Point(Size.Width - 18, 2);
+ if (_ScrollUp != null && !_ScrollUp.IsDisposed)
+ _ScrollUp.Location = new Point(Size.Width - 12, 14);
+ if (_ScrollDown != null && !_ScrollDown.IsDisposed)
+ _ScrollDown.Location = new Point(Size.Width - 12, 52);
+ if (_ScrollPosition != null && !_ScrollPosition.IsDisposed)
+ _ScrollPosition.Location = new Point(Size.Width - 11, 22);
+
+ }
+ #endregion
+
+ #region Enabled
+
+ protected override void OnEnabledChanged()
+ {
+ base.OnEnabledChanged();
+ if (_DropDownButton != null && !_DropDownButton.IsDisposed)
+ {
+ _DropDownButton.Enabled = Enabled;
+ if (Enabled)
+ _DropDownButton.Visible = true;
+ else
+ _DropDownButton.Visible = false;
+ }
+ }
+
+ #endregion
+
+ public MirDropDownBox()
+ {
+ BackColour = Color.FromArgb(255,6,6,6);
+ ForeColour = Color.White;
+ Enabled = false;
+ _label = new MirLabel
+ {
+ Parent = this,
+ Location = new Point(0, 0),
+ ForeColour = ForeColour,
+ BackColour = BackColour,
+ Font = new Font(Settings.FontName, 8F),
+ Visible = true,
+ };
+ _label.Click += (o, e) =>
+ {
+ if (_DropDownButton.Enabled)
+ DropDownClick();
+ };
+ _label.BeforeDraw += (o, e) =>
+ {
+ if ((Items.Count > 0) && (Items.Count >= SelectedIndex))
+ if (SelectedIndex == -1)
+ {
+ _label.Text = " ";
+ }
+ else
+
+ _label.Text = Items[SelectedIndex];
+ else
+ _label.Text = "None";
+ };
+ for (int i = 0; i < _Option.Length; i++)
+ {
+ _Option[i] = new MirLabel
+ {
+ Parent = this,
+ Visible = false,
+ Location = new Point(0, 15 + (i * 13)),
+ ForeColour = ForeColour,
+ BackColour = Color.FromArgb(255,20,20,20),
+ Font = new Font(Settings.FontName, 8F)
+ };
+ int index = i;
+ _Option[index].MouseEnter += (o, e) => _Option[index].BackColour = Color.FromArgb(255,140,70,0);
+ _Option[index].MouseLeave += (o, e) => _Option[index].BackColour = Color.FromArgb(255, 20, 20, 20);
+ _Option[index].MouseDown += (o, e) => _Option[index].BackColour = Color.FromArgb(255, 20, 20, 20);
+ _Option[index].MouseUp += (o, e) => _Option[index].BackColour = Color.FromArgb(255,20,20,20);
+ _Option[index].Click += (o, e) => SelectOption(index);
+
+ _Option[index].BeforeDraw += (o, e) =>
+ {
+ if (Items.Count > (ScrollIndex + index + MinimumOption))
+ _Option[index].Text = _Items[ScrollIndex + index + MinimumOption];
+ };
+ }
+ _DropDownButton = new MirButton
+ {
+ Index = 207,
+ Library = Libraries.Prguse2,
+ Location = new Point(Size.Width - 18, 1),
+ Parent = this,
+ HoverIndex = 208,
+ PressedIndex = 209,
+ Visible = false,
+ };
+ _DropDownButton.Click += (o, e) => DropDownClick();
+ _ScrollUp = new MirButton
+ {
+ HoverIndex = 2022,
+ Index = 2021,
+ Library = Libraries.Prguse,
+ Location = new Point(Size.Width - 12, 14),
+ Parent = this,
+ PressedIndex = 2023,
+ Visible = false
+ };
+ _ScrollUp.Click += (o, e) => ScrollUp();
+ _ScrollDown = new MirButton
+ {
+ HoverIndex = 2025,
+ Index = 2024,
+ Library = Libraries.Prguse,
+ Location = new Point(Size.Width - 12, 52),
+ Parent = this,
+ PressedIndex = 2026,
+ Visible = false
+ };
+ _ScrollDown.Click += (o, e) => ScrollDown();
+
+ _ScrollPosition = new MirButton
+ {
+ HoverIndex = 2016,
+ Index = 2015,
+ Library = Libraries.Prguse,
+ Location = new Point(Size.Width - 11, 22),
+ Movable = true,
+ Parent = this,
+ PressedIndex = 2017,
+ Visible = false
+ };
+ _ScrollPosition.OnMoving += ScrollPosition;
+ BeforeDraw += MirDropDownBox_BeforeDraw;
+ }
+
+ void MirDropDownBox_BeforeDraw(object sender, EventArgs e)
+ {
+ if (!_Option[0].Visible) return;
+ if (IsMouseOver(CMain.MPoint)) return;
+ foreach (MirControl control in Controls)
+ if (control.IsMouseOver(CMain.MPoint))
+ return;
+
+ CloseDropDown();
+ }
+
+ protected override void OnMouseLeave()
+ {
+ if (!IsMouseOver(CMain.MPoint))
+ CloseDropDown();
+ base.OnMouseLeave();
+ }
+
+ public void SelectOption(int index)
+ {
+ if (ScrollIndex + index + MinimumOption < Items.Count)
+ {
+ _WantedIndex = ScrollIndex + index + MinimumOption;
+ if (ValueChanged != null)
+ ValueChanged.Invoke(this, EventArgs.Empty);
+ }
+ else
+ Update();
+ CloseDropDown();
+ }
+
+ public void ItemsChanged()
+ {
+ CloseDropDown();
+ SelectedIndex = -1;
+ }
+ public void Update()
+ {
+ // Member is not implemented.
+ }
+ public void DropDownClick()
+ {
+ if (_Option[0].Visible)
+ CloseDropDown();
+ else
+ OpenDropDown();
+ }
+ public void OpenDropDown()
+ {
+ Size = new Size(Size.Width, OrigHeight + (Math.Max(5, Items.Count) * 15));
+ ScrollIndex = 0;
+ if (Items.Count > 5)
+ ScrollIndex = SelectedIndex > 3 ? SelectedIndex - 2 : 0;
+ for (int i = 0; i < _Option.Length; i++)
+ if (Items.Count > i)
+ _Option[i].Visible = true;
+ else
+ _Option[i].Visible = false;
+ if (Items.Count > 5)
+ {
+ _ScrollDown.Visible = true;
+ _ScrollPosition.Visible = true;
+ _ScrollUp.Visible = true;
+ }
+ else
+ {
+ _ScrollDown.Visible = false;
+ _ScrollPosition.Visible = false;
+ _ScrollUp.Visible = false;
+ }
+ _ScrollDown.Location = new Point(Size.Width - 12, 9 + Math.Min(5, Items.Count) * 13);
+ }
+ public void CloseDropDown()
+ {
+ Size = new Size(Size.Width, OrigHeight);
+ for (int i = 0; i < _Option.Length; i++)
+ _Option[i].Visible = false;
+ _ScrollDown.Visible = false;
+ _ScrollPosition.Visible = false;
+ _ScrollUp.Visible = false;
+ }
+ public void ScrollUp()
+ {
+ if (ScrollIndex > 0) ScrollIndex--;
+ Update();
+ }
+ public void ScrollDown()
+ {
+ if (ScrollIndex < (Items.Count - 5)) ScrollIndex++;
+ Update();
+ }
+ void ScrollPosition(object sender, MouseEventArgs e)
+ {
+ int x = Size.Width - 11;
+ int y = _ScrollPosition.Location.Y;
+ if (y >= _ScrollDown.Location.Y - 14) y = _ScrollDown.Location.Y - 14;
+ if (y < 20) y = 20;
+
+ int h = _ScrollDown.Location.Y - _ScrollUp.Location.Y + 6;
+ h = (int)((y - 15) / (h / (float)(Items.Count - 1)));
+ if (h > Items.Count - 5) h = Math.Max(0, Items.Count - 5);
+ if (h != ScrollIndex)
+ {
+ ScrollIndex = h;
+ Update();
+ }
+
+ _ScrollPosition.Location = new Point(x, y);
+ }
+
+ #region Disposable
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ if (_label != null && !_label.IsDisposed)
+ _label.Dispose();
+ _label = null;
+
+ if (_DropDownButton != null && !_DropDownButton.IsDisposed)
+ _DropDownButton.Dispose();
+ _DropDownButton = null;
+
+ if (_ScrollDown != null && !_ScrollDown.IsDisposed)
+ _ScrollDown.Dispose();
+ _ScrollDown = null;
+
+ if (_ScrollPosition != null && !_ScrollPosition.IsDisposed)
+ _ScrollPosition.Dispose();
+ _ScrollPosition = null;
+
+ if (_ScrollUp != null && !_ScrollUp.IsDisposed)
+ _ScrollUp.Dispose();
+ _ScrollUp = null;
+ for (int i = 0; i < _Option.Length; i++)
+ {
+ if (_Option[i] != null && !_Option[i].IsDisposed)
+ _Option[i].Dispose();
+ _Option[i] = null;
+ }
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Client/MirControls/MirGameShopCell.cs b/Client/MirControls/MirGameShopCell.cs
new file mode 100644
index 0000000..20056ea
--- /dev/null
+++ b/Client/MirControls/MirGameShopCell.cs
@@ -0,0 +1,479 @@
+using Client.MirGraphics;
+using Client.MirNetwork;
+using Client.MirScenes;
+using Client.MirSounds;
+using C = ClientPackets;
+
+namespace Client.MirControls
+{
+ public sealed class GameShopCell : MirImageControl
+ {
+ public MirLabel nameLabel, typeLabel, goldLabel, gpLabel, stockLabel, StockLabel, countLabel;
+ public GameShopItem Item;
+ public UserItem ShowItem;
+ Rectangle ItemDisplayArea;
+ public MirButton BuyItem, PreviewItem;
+ public MirImageControl ViewerBackground;
+ public byte Quantity = 1;
+ public MirButton quantityUp, quantityDown;
+ public MirLabel quantity;
+ public GameShopViewer Viewer;
+
+ public GameShopCell()
+ {
+ Size = new Size(125, 146);
+ Index = 750;
+ Library = Libraries.Prguse;
+ MouseLeave += (o, e) =>
+ {
+ GameScene.Scene.DisposeItemLabel();
+ GameScene.HoverItem = null;
+ ShowItem = null;
+ };
+
+ nameLabel = new MirLabel
+ {
+ Size = new Size(125, 15),
+ DrawFormat = TextFormatFlags.HorizontalCenter,
+ Location = new Point(0, 13),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 8F),
+ };
+
+ goldLabel = new MirLabel
+ {
+ Size = new Size(95, 20),
+ DrawFormat = TextFormatFlags.RightToLeft | TextFormatFlags.Right,
+ Location = new Point(2, 102),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 8F)
+ };
+
+ gpLabel = new MirLabel
+ {
+ Size = new Size(95, 20),
+ DrawFormat = TextFormatFlags.RightToLeft | TextFormatFlags.Right,
+ Location = new Point(2, 81),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 8F)
+ };
+
+ StockLabel = new MirLabel
+ {
+ Size = new Size(40, 20),
+ Location = new Point(53, 37),
+ Parent = this,
+ NotControl = true,
+ ForeColour = Color.Gray,
+ Font = new Font(Settings.FontName, 7F),
+ Text = "STOCK:"
+ };
+
+ stockLabel = new MirLabel
+ {
+ Size = new Size(20, 20),
+ DrawFormat = TextFormatFlags.HorizontalCenter,
+ Location = new Point(93, 37),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 7F),
+ };
+
+ countLabel = new MirLabel
+ {
+ Size = new Size(30, 20),
+ DrawFormat = TextFormatFlags.Right,
+ Location = new Point(16, 60),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 7F),
+ };
+
+
+ BuyItem = new MirButton
+ {
+ Index = 778,
+ HoverIndex = 779,
+ PressedIndex = 780,
+ Location = new Point(42, 122),
+ Library = Libraries.Prguse,
+ Parent = this,
+ Sound = SoundList.ButtonA,
+ };
+ BuyItem.Click += (o, e) =>
+ {
+ BuyProduct();
+ };
+
+ PreviewItem = new MirButton
+ {
+ Index = 781,
+ HoverIndex = 782,
+ PressedIndex = 783,
+ Location = new Point(8, 122),
+ Library = Libraries.Prguse,
+ Parent = this,
+ Sound = SoundList.ButtonA,
+ Visible = false,
+ };
+ PreviewItem.Click += (o, e) =>
+ {
+ GameScene.Scene.GameShopDialog.Viewer.Dispose();
+ GameScene.Scene.GameShopDialog.Viewer = new GameShopViewer
+ {
+ Parent = GameScene.Scene.GameShopDialog,
+ Visible = true,
+ Location = this.Location.X < 350 ? new Point(416, 115) : new Point(151, 115),
+ };
+ GameScene.Scene.GameShopDialog.Viewer.ViewerItem = Item;
+ GameScene.Scene.GameShopDialog.Viewer.UpdateViewer();
+ };
+
+
+ quantityUp = new MirButton
+ {
+ Index = 243,
+ HoverIndex = 244,
+ PressedIndex = 245,
+ Library = Libraries.Prguse2,
+ Parent = this,
+ Location = new Point(97, 56),
+ Sound = SoundList.ButtonA,
+ };
+ quantityUp.Click += (o, e) =>
+ {
+ if (CMain.Shift) Quantity += 10;
+ else Quantity++;
+
+ if (((decimal)(Quantity * Item.Count) / Item.Info.StackSize) > 5) Quantity = ((5 * Item.Info.StackSize) / Item.Count) > 99 ? Quantity = 99 : Quantity = (byte)((5 * Item.Info.StackSize) / Item.Count);
+ if (Quantity >= 99) Quantity = 99;
+ if (Item.Stock != 0 && Quantity > Item.Stock) Quantity = (byte)Item.Stock;
+ };
+
+ quantityDown = new MirButton
+ {
+ Index = 240,
+ HoverIndex = 241,
+ PressedIndex = 242,
+ Library = Libraries.Prguse2,
+ Parent = this,
+ Location = new Point(55, 56),
+ Sound = SoundList.ButtonA,
+ };
+ quantityDown.Click += (o, e) =>
+ {
+
+ if (CMain.Shift) Quantity -= 10;
+ else Quantity--;
+
+ if (Quantity <= 1 || Quantity > 99) Quantity = 1;
+ };
+
+ quantity = new MirLabel
+ {
+ Size = new Size(20, 13),
+ DrawFormat = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter,
+ Location = new Point(74, 56),
+ Parent = this,
+ NotControl = true,
+ Font = new Font(Settings.FontName, 8F),
+ };
+
+
+
+ }
+
+ public void BuyProduct()
+ {
+ uint CreditCost;
+ uint GoldCost;
+ MirMessageBox messageBox;
+ int pType = -1;
+ if (GameScene.Scene.GameShopDialog.PaymentTypeCredit.Checked && Item.CanBuyCredit)
+ {
+ pType = 0;
+ }
+ else if (GameScene.Scene.GameShopDialog.PaymentTypeGold.Checked && Item.CanBuyGold)
+ {
+ pType = 1;
+ }
+ if (pType == -1)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You MUST select a payment type!", ChatType.System);
+ return;
+ }
+ switch (pType)
+ {
+ case 0: // Credit
+ if (Item.CreditPrice * Quantity <= GameScene.Credit)
+ {
+ CreditCost = Item.CreditPrice * Quantity;
+ messageBox = new MirMessageBox(string.Format("Are you sure would you like to buy {1} x \n{0}({3}) for {2} Credits?", Item.Info.FriendlyName, Quantity, CreditCost, Item.Count), MirMessageBoxButtons.YesNo);
+ messageBox.YesButton.Click += (o, e) => Network.Enqueue(new C.GameshopBuy { GIndex = Item.GIndex, Quantity = Quantity, PType = pType });
+ messageBox.NoButton.Click += (o, e) => { };
+ messageBox.Show();
+ }
+ else
+ GameScene.Scene.ChatDialog.ReceiveChat("You can't afford the selected item.", ChatType.System);
+ break;
+ case 1: // Gold
+ if (Item.GoldPrice * Quantity <= GameScene.Gold)
+ {
+ GoldCost = Item.GoldPrice * Quantity;
+ messageBox = new MirMessageBox(string.Format("Are you sure would you like to buy{1} x \n{0}({3}) for {2} Gold?", Item.Info.FriendlyName, Quantity, GoldCost, Item.Count), MirMessageBoxButtons.YesNo);
+ messageBox.YesButton.Click += (o, e) => Network.Enqueue(new C.GameshopBuy { GIndex = Item.GIndex, Quantity = Quantity, PType = pType });
+ messageBox.NoButton.Click += (o, e) => { };
+ messageBox.Show();
+ }
+ else
+ GameScene.Scene.ChatDialog.ReceiveChat("You can't afford the selected item.", ChatType.System);
+ break;
+ default:
+
+ return;
+ }
+ }
+
+ public override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+
+ if (GameScene.HoverItem != null && (Item.Info.Index != GameScene.HoverItem.Info.Index))
+ {
+ GameScene.Scene.DisposeItemLabel();
+ GameScene.HoverItem = null;
+ ShowItem = null;
+ }
+
+ if (ShowItem == null && ItemDisplayArea.Contains(CMain.MPoint))
+ {
+ ShowItem = new UserItem(Item.Info) { MaxDura = Item.Info.Durability, CurrentDura = Item.Info.Durability, Count = Item.Count };
+ GameScene.Scene.CreateItemLabel(ShowItem);
+ }
+ else if (ShowItem != null && !ItemDisplayArea.Contains(CMain.MPoint))
+ {
+ GameScene.Scene.DisposeItemLabel();
+ GameScene.HoverItem = null;
+ ShowItem = null;
+ }
+ }
+
+ public void UpdateText()
+ {
+ nameLabel.Text = Item.Info.FriendlyName;
+ nameLabel.Text = nameLabel.Text.Length > 17 ? nameLabel.Text.Substring(0, 17) : nameLabel.Text;
+ nameLabel.ForeColour = GameScene.Scene.GradeNameColor(Item.Info.Grade);
+ if (Item.CanBuyGold)
+ goldLabel.Text = (Item.GoldPrice * Quantity).ToString("###,###,##0");
+ if (Item.CanBuyCredit)
+ gpLabel.Text = (Item.CreditPrice * Quantity).ToString("###,###,##0");
+ if (Item.Stock >= 99) stockLabel.Text = "99+";
+ if (Item.Stock == 0) stockLabel.Text = "∞";
+ else stockLabel.Text = Item.Stock.ToString();
+ countLabel.Text = Item.Count.ToString();
+
+ if (Item.Info.Type == ItemType.Weapon || Item.Info.Type == ItemType.Armour)
+ {
+ PreviewItem.Visible = true;
+ BuyItem.Location = new Point(75, 122);
+ }
+ }
+
+ protected internal override void DrawControl()
+ {
+
+ base.DrawControl();
+
+ if (Item == null) return;
+
+ UpdateText();
+
+ Size size = Libraries.Items.GetTrueSize(Item.Info.Image);
+ Point offSet = new Point((32 - size.Width) / 2, (32 - size.Height) / 2);
+
+ Libraries.Items.Draw(Item.Info.Image, offSet.X + DisplayLocation.X + 12, offSet.Y + DisplayLocation.Y + 40);
+ ItemDisplayArea = new Rectangle(new Point(offSet.X + DisplayLocation.X + 12, offSet.Y + DisplayLocation.Y + 40), size);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ Item = null;
+ GameScene.HoverItem = null;
+ ShowItem = null;
+ }
+
+ }
+
+ public sealed class GameShopViewer : MirImageControl
+ {
+
+ public MirAnimatedControl PreviewImage, WeaponImage, WeaponImage2, MountImage;
+
+ public int StartIndex = 0;
+ public int Direction = 6;
+ public GameShopItem ViewerItem;
+
+ public MirButton RightDirection, LeftDirection, CloseButton;
+
+
+ public GameShopViewer()
+ {
+ Index = 785;// 314;
+ Library = Libraries.Prguse;// Libraries.Prguse2;
+ Location = new Point(405, 108);
+ BeforeDraw += GameShopViewer_BeforeDraw;
+ //Click += (o, e) =>
+ //{
+ //Visible = false;
+ //};
+
+ CloseButton = new MirButton
+ {
+ HoverIndex = 362,
+ Index = 361,
+ Location = new Point(230, 8),
+ Library = Libraries.Prguse,
+ Parent = this,
+ PressedIndex = 363,
+ Sound = SoundList.ButtonA,
+ };
+ CloseButton.Click += (o, e) =>
+ {
+ Visible = false;
+ };
+
+ WeaponImage = new MirAnimatedControl
+ {
+ Animated = false,
+ Location = new Point(105, 160),
+ AnimationCount = 6,
+ AnimationDelay = 150,
+ Index = 0,
+ Library = Libraries.Prguse,
+ Loop = true,
+ Parent = this,
+ UseOffSet = true,
+ NotControl = true,
+ };
+ WeaponImage2 = new MirAnimatedControl
+ {
+ Animated = false,
+ Location = new Point(105, 160),
+ AnimationCount = 6,
+ AnimationDelay = 150,
+ Index = 0,
+ Library = Libraries.Prguse,
+ Loop = true,
+ Parent = this,
+ UseOffSet = true,
+ NotControl = true,
+ };
+ MountImage = new MirAnimatedControl
+ {
+ Animated = false,
+ Location = new Point(105, 160),
+ AnimationCount = 8,
+ AnimationDelay = 150,
+ Index = 0,
+ Library = Libraries.Prguse,
+ Loop = true,
+ Parent = this,
+ UseOffSet = true,
+ NotControl = true,
+ };
+
+ PreviewImage = new MirAnimatedControl
+ {
+ Animated = false,
+ Location = new Point(105, 160),
+ AnimationCount = 6,
+ AnimationDelay = 150,
+ Index = 0,
+ Library = Libraries.Prguse,
+ Loop = true,
+ Parent = this,
+ UseOffSet = true,
+ NotControl = true,
+ };
+
+ RightDirection = new MirButton
+ {
+ Index = 243,
+ HoverIndex = 244,
+ PressedIndex = 245,
+ Library = Libraries.Prguse2,
+ Parent = this,
+ Location = new Point(160, 282),
+ Sound = SoundList.ButtonA,
+ };
+ RightDirection.Click += (o, e) =>
+ {
+ Direction++;
+ if (Direction > 8) Direction = 1;
+
+ UpdateViewer();
+ };
+
+ LeftDirection = new MirButton
+ {
+ Index = 240,
+ HoverIndex = 241,
+ PressedIndex = 242,
+ Library = Libraries.Prguse2,
+ Parent = this,
+ Location = new Point(81, 282),
+ Sound = SoundList.ButtonA,
+ };
+ LeftDirection.Click += (o, e) =>
+ {
+ Direction--;
+ if (Direction == 0) Direction = 8;
+
+ UpdateViewer();
+ };
+
+ }
+
+ public void UpdateViewer()
+ {
+ this.Visible = true;
+ if (ViewerItem.Info.Type == ItemType.Weapon) DrawWeapon();
+ if (ViewerItem.Info.Type == ItemType.Armour) DrawArmour();
+ }
+
+ private void GameShopViewer_BeforeDraw(object sender, EventArgs e)
+ {
+ BringToFront();
+ }
+
+ private void DrawMount()
+ {
+ }
+
+ private void DrawWeapon()
+ {
+ }
+
+ private void DrawArmour()
+ {
+
+ }
+
+ private void DrawTransform()
+ {
+
+ }
+
+ private void DrawMask()
+ {
+
+
+ }
+
+ }
+}
diff --git a/Client/MirControls/MirGeneratedBox.cs b/Client/MirControls/MirGeneratedBox.cs
new file mode 100644
index 0000000..64687ed
--- /dev/null
+++ b/Client/MirControls/MirGeneratedBox.cs
@@ -0,0 +1,84 @@
+using Client.MirGraphics;
+
+namespace Client.MirControls
+{
+ public enum GeneratedBoxSections
+ {
+ TopLeft,
+ Top,
+ TopRight,
+ Left,
+ Middle,
+ Right,
+ BottomLeft,
+ Bottom,
+ BottomRight
+ }
+
+ public sealed class MirGeneratedBox : MirImageControl
+ {
+ private GeneratedBoxSections[,] boxArray;
+ private int SectionOffset;
+ public Size FixedSize;
+ public MirGeneratedBox(int offset, Size size)
+ {
+ SectionOffset = offset;
+ DrawImage = false;
+ FixedSize = new Size(size.Width / 40 * 40, size.Height / 40 * 40);
+ boxArray = new GeneratedBoxSections[FixedSize.Width / 40, FixedSize.Height / 40];
+
+ for (int y = 0; y < boxArray.GetLength(1); y++)
+ for (int x = 0; x < boxArray.GetLength(0); x++)
+ {
+ GeneratedBoxSections section = GetSectionForRowAndCol(y, x);
+ boxArray[x, y] = section;
+ }
+
+ BeforeDraw += (o,e) => DrawSections();
+ }
+
+ private GeneratedBoxSections GetSectionForRowAndCol(int row, int col)
+ {
+ int width = boxArray.GetLength(0);
+ int height = boxArray.GetLength(1);
+
+ if (row == 0)
+ {
+ if (col == 0)
+ return GeneratedBoxSections.TopLeft;
+ else if (col == width - 1)
+ return GeneratedBoxSections.TopRight;
+ else
+ return GeneratedBoxSections.Top;
+ }
+ else if (row == height - 1)
+ {
+ if (col == 0)
+ return GeneratedBoxSections.BottomLeft;
+ else if (col == width - 1)
+ return GeneratedBoxSections.BottomRight;
+ else
+ return GeneratedBoxSections.Bottom;
+ }
+ else
+ {
+ if (col == 0)
+ return GeneratedBoxSections.Left;
+ else if (col == width - 1)
+ return GeneratedBoxSections.Right;
+ else
+ return GeneratedBoxSections.Middle;
+ }
+ }
+
+ private void DrawSections()
+ {
+ for (int y = 0; y < boxArray.GetLength(1); y++)
+ for (int x = 0; x < boxArray.GetLength(0); x++)
+ {
+ GeneratedBoxSections section = boxArray[x, y];
+ Libraries.Prguse.Draw(SectionOffset + (int)section, Parent.DisplayLocation.X + Location.X + x * 40, Parent.DisplayLocation.Y + Location.Y + y * 40);
+ }
+ }
+ }
+}
diff --git a/Client/MirControls/MirGoodsCell.cs b/Client/MirControls/MirGoodsCell.cs
new file mode 100644
index 0000000..c026947
--- /dev/null
+++ b/Client/MirControls/MirGoodsCell.cs
@@ -0,0 +1,97 @@
+using Client.MirGraphics;
+using Client.MirScenes;
+using SlimDX;
+
+namespace Client.MirControls
+{
+ public sealed class MirGoodsCell : MirControl
+ {
+ public UserItem Item;
+
+ public MirLabel NameLabel, PriceLabel, CountLabel;
+
+ public bool MultipleAvailable = false;
+ public MirImageControl NewIcon;
+
+ public MirGoodsCell()
+ {
+ Size = new Size(130, 32);
+
+ NameLabel = new MirLabel
+ {
+ AutoSize = true,
+ Parent = this,
+ NotControl = true,
+ Location = new Point(49, 0),
+ };
+
+ CountLabel = new MirLabel
+ {
+ AutoSize = true,
+ Parent = this,
+ NotControl = true,
+ DrawControlTexture = true,
+ Location = new Point(23, 17),
+ ForeColour = Color.Yellow,
+ };
+
+ PriceLabel = new MirLabel
+ {
+ AutoSize = true,
+ Parent = this,
+ NotControl = true,
+ Location = new Point(49, 14),
+ };
+
+ NewIcon = new MirImageControl
+ {
+ Index = 550,
+ Library = Libraries.Prguse,
+ Parent = this,
+ Location = new Point(190, 5),
+ NotControl = true,
+ Visible = false
+ };
+
+ BeforeDraw += (o, e) => Update();
+ AfterDraw += (o, e) => DrawItem();
+ }
+
+ private void Update()
+ {
+ NewIcon.Visible = false;
+
+ if (Item == null || Item.Info == null) return;
+ NameLabel.Text = Item.Info.FriendlyName;
+ CountLabel.Text = (Item.Count <= 1) ? "" : Item.Count.ToString();
+
+ NewIcon.Visible = !Item.IsShopItem || MultipleAvailable;
+
+ PriceLabel.Text = string.Format("Price: {0} gold", (uint)(Item.Price() * GameScene.NPCRate));
+ }
+
+ protected override void OnMouseEnter()
+ {
+ base.OnMouseEnter();
+ GameScene.Scene.CreateItemLabel(Item, hideAdded: GameScene.HideAddedStoreStats);
+ }
+
+ protected override void OnMouseLeave()
+ {
+ base.OnMouseLeave();
+ GameScene.Scene.DisposeItemLabel();
+ GameScene.HoverItem = null;
+ }
+
+ private void DrawItem()
+ {
+ if (Item == null || Item.Info == null) return;
+
+ Size size = Libraries.Items.GetTrueSize(Item.Image);
+ Point offSet = new Point((40 - size.Width)/2, (32 - size.Height)/2);
+ Libraries.Items.Draw(Item.Image, offSet.X + DisplayLocation.X, offSet.Y + DisplayLocation.Y);
+
+ CountLabel.Draw();
+ }
+ }
+}
diff --git a/Client/MirControls/MirImageControl.cs b/Client/MirControls/MirImageControl.cs
new file mode 100644
index 0000000..3935b61
--- /dev/null
+++ b/Client/MirControls/MirImageControl.cs
@@ -0,0 +1,224 @@
+using Client.MirGraphics;
+
+namespace Client.MirControls
+{
+ public class MirImageControl : MirControl
+ {
+ public override Point DisplayLocation { get { return UseOffSet ? base.DisplayLocation.Add(Library.GetOffSet(Index)) : base.DisplayLocation; } }
+ public Point DisplayLocationWithoutOffSet { get { return base.DisplayLocation; } }
+
+ #region Auto Size
+ private bool _autoSize;
+ public bool AutoSize
+ {
+ get { return _autoSize; }
+ set
+ {
+ if (_autoSize == value)
+ return;
+ _autoSize = value;
+ OnAutoSizeChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler AutoSizeChanged;
+ private void OnAutoSizeChanged(EventArgs e)
+ {
+ TextureValid = false;
+ if (AutoSizeChanged != null)
+ AutoSizeChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region DrawImage
+ private bool _drawImage;
+ public bool DrawImage
+ {
+ get { return _drawImage; }
+ set
+ {
+ if (_drawImage == value)
+ return;
+ _drawImage = value;
+ OnDrawImageChanged();
+ }
+ }
+ public event EventHandler DrawImageChanged;
+ private void OnDrawImageChanged()
+ {
+ Redraw();
+ if (DrawImageChanged != null)
+ DrawImageChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Index
+ private int _index;
+ public virtual int Index
+ {
+ get { return _index; }
+ set
+ {
+ if (_index == value)
+ return;
+ _index = value;
+ OnIndexChanged();
+ }
+ }
+ public event EventHandler IndexChanged;
+ protected void OnIndexChanged()
+ {
+ OnSizeChanged();
+ if (IndexChanged != null)
+ IndexChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Library
+ private MLibrary _library;
+ public MLibrary Library
+ {
+ get { return _library; }
+ set
+ {
+ if (_library == value)
+ return;
+ _library = value;
+ OnLibraryChanged();
+ }
+ }
+ public event EventHandler LibraryChanged;
+ private void OnLibraryChanged()
+ {
+ OnSizeChanged();
+ if (LibraryChanged != null)
+ LibraryChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region PixelDetect
+ private bool _pixelDetect;
+ protected bool PixelDetect
+ {
+ set
+ {
+ if (_pixelDetect == value)
+ return;
+ _pixelDetect = value;
+ OnPixelDetectChanged();
+ }
+ }
+ public event EventHandler PixelDetectChanged;
+ private void OnPixelDetectChanged()
+ {
+ Redraw();
+ if (PixelDetectChanged != null)
+ PixelDetectChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region UseOffset
+ private bool _useOffSet;
+ public bool UseOffSet
+ {
+ protected get { return _useOffSet; }
+ set
+ {
+ if (_useOffSet == value)
+ return;
+ _useOffSet = value;
+ OnUseOffSetChanged();
+ }
+ }
+ public event EventHandler UseOffSetChanged;
+ private void OnUseOffSetChanged()
+ {
+ OnLocationChanged();
+ if (UseOffSetChanged != null)
+ UseOffSetChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Size
+ public override Size Size
+ {
+ set { base.Size = value; }
+ get
+ {
+ if (AutoSize && Library != null && Index >= 0)
+ return Library.GetTrueSize(Index);
+ return base.Size;
+ }
+ }
+
+ public override Size TrueSize
+ {
+ get
+ {
+ if (Library != null && Index >= 0)
+ return Library.GetTrueSize(Index);
+ return base.TrueSize;
+ }
+ }
+
+ #endregion
+
+ public MirImageControl()
+ {
+ _drawImage = true;
+ _index = -1;
+ ForeColour = Color.White;
+ _autoSize = true;
+ }
+
+ protected internal override void DrawControl()
+ {
+ base.DrawControl();
+
+ if (DrawImage && Library != null)
+ {
+ bool oldGray = DXManager.GrayScale;
+
+ if (GrayScale)
+ {
+ DXManager.SetGrayscale(true);
+ }
+
+ if (Blending)
+ Library.DrawBlend(Index, DisplayLocation, ForeColour, false, BlendingRate);
+ else
+ Library.Draw(Index, DisplayLocation, ForeColour, false, Opacity);
+
+ if (GrayScale) DXManager.SetGrayscale(oldGray);
+ }
+ }
+
+ public override bool IsMouseOver(Point p)
+ {
+ return base.IsMouseOver(p) && (!_pixelDetect || Library.VisiblePixel(Index, p.Subtract(DisplayLocation),true) || Moving);
+ }
+
+ #region Disposable
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ DrawImageChanged = null;
+ _drawImage = false;
+
+ IndexChanged = null;
+ _index = 0;
+
+ LibraryChanged = null;
+ Library = null;
+
+ PixelDetectChanged = null;
+ _pixelDetect = false;
+
+ UseOffSetChanged = null;
+ _useOffSet = false;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Client/MirControls/MirInputBox.cs b/Client/MirControls/MirInputBox.cs
new file mode 100644
index 0000000..6c9c97c
--- /dev/null
+++ b/Client/MirControls/MirInputBox.cs
@@ -0,0 +1,149 @@
+using Client.MirGraphics;
+
+namespace Client.MirControls
+{
+ public sealed class MirInputBox : MirImageControl
+ {
+ public readonly MirLabel CaptionLabel;
+ public readonly MirButton OKButton, CancelButton;
+ public readonly MirTextBox InputTextBox;
+
+
+ public MirInputBox(string message)
+ {
+ Modal = true;
+ Movable = false;
+
+ Index = 660;
+ Library = Libraries.Prguse;
+
+ Location = new Point((Settings.ScreenWidth - Size.Width) / 2, (Settings.ScreenHeight - Size.Height) / 2);
+
+ CaptionLabel = new MirLabel
+ {
+ DrawFormat = TextFormatFlags.WordBreak,
+ Location = new Point(25, 25),
+ Size = new Size(235, 40),
+ Parent = this,
+ Text = message,
+ };
+
+ InputTextBox = new MirTextBox
+ {
+ Parent = this,
+ Border = true,
+ BorderColour = Color.Lime,
+ Location = new Point(23, 86),
+ Size = new Size(240, 19),
+ MaxLength = 50,
+ };
+ InputTextBox.SetFocus();
+ InputTextBox.TextBox.KeyPress += MirInputBox_KeyPress;
+
+ OKButton = new MirButton
+ {
+ HoverIndex = 201,
+ Index = 200,
+ Library = Libraries.Prguse,
+ Location = new Point(60, 123),
+ Parent = this,
+ PressedIndex = 202,
+ };
+
+ CancelButton = new MirButton
+ {
+ HoverIndex = 204,
+ Index = 203,
+ Library = Libraries.Prguse,
+ Location = new Point(160, 123),
+ Parent = this,
+ PressedIndex = 205,
+ };
+ CancelButton.Click += DisposeDialog;
+ }
+
+ void MirInputBox_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ if (e.KeyChar == (char)Keys.Enter)
+ {
+ if (OKButton != null && !OKButton.IsDisposed)
+ OKButton.InvokeMouseClick(EventArgs.Empty);
+ e.Handled = true;
+ }
+ else if (e.KeyChar == (char)Keys.Escape)
+ {
+ if (CancelButton != null && !CancelButton.IsDisposed)
+ CancelButton.InvokeMouseClick(EventArgs.Empty);
+ e.Handled = true;
+ }
+ }
+ void DisposeDialog(object sender, EventArgs e)
+ {
+ Dispose();
+ }
+
+ public override void OnKeyDown(KeyEventArgs e)
+ {
+ base.OnKeyDown(e);
+ e.Handled = true;
+ }
+ public override void OnKeyUp(KeyEventArgs e)
+ {
+ base.OnKeyUp(e);
+ e.Handled = true;
+ }
+ public override void OnKeyPress(KeyPressEventArgs e)
+ {
+ base.OnKeyPress(e);
+
+ if (e.KeyChar == (char)Keys.Escape)
+ {
+ if (CancelButton != null && !CancelButton.IsDisposed)
+ CancelButton.InvokeMouseClick(EventArgs.Empty);
+ }
+ else if (e.KeyChar == (char)Keys.Enter)
+ {
+ if (OKButton != null && !OKButton.IsDisposed)
+ OKButton.InvokeMouseClick(EventArgs.Empty);
+
+ }
+ e.Handled = true;
+ }
+
+ public override void Show()
+ {
+ if (Parent != null) return;
+
+ Parent = MirScene.ActiveScene;
+
+ Highlight();
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = Program.Form.Controls[i] as TextBox;
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }
+ }
+
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = (TextBox)Program.Form.Controls[i];
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Client/MirControls/MirItemCell.cs b/Client/MirControls/MirItemCell.cs
new file mode 100644
index 0000000..68c9431
--- /dev/null
+++ b/Client/MirControls/MirItemCell.cs
@@ -0,0 +1,1597 @@
+using Client.MirGraphics;
+using Client.MirNetwork;
+using Client.MirObjects;
+using Client.MirScenes;
+using Client.MirSounds;
+using Client.MirScenes.Dialogs;
+using C = ClientPackets;
+
+namespace Client.MirControls
+{
+ public sealed class MirItemCell : MirImageControl
+ {
+ public UserItem Item
+ {
+ get
+ {
+ if (GridType == MirGridType.DropPanel)
+ return NPCDropDialog.TargetItem;
+
+ if (GridType == MirGridType.TrustMerchant)
+ return TrustMerchantDialog.SellItemSlot;
+
+ if (ItemArray != null && _itemSlot >= 0 && _itemSlot < ItemArray.Length)
+ return ItemArray[_itemSlot];
+ return null;
+ }
+ set
+ {
+ if (GridType == MirGridType.DropPanel)
+ NPCDropDialog.TargetItem = value;
+ else if (GridType == MirGridType.TrustMerchant)
+ TrustMerchantDialog.SellItemSlot = value;
+ else if (ItemArray != null && _itemSlot >= 0 && _itemSlot < ItemArray.Length)
+ ItemArray[_itemSlot] = value;
+
+ SetEffect();
+ Redraw();
+ }
+ }
+
+ public UserItem ShadowItem
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public UserItem[] ItemArray
+ {
+ get
+ {
+ switch (GridType)
+ {
+ case MirGridType.Inventory:
+ return MapObject.User.Inventory;
+ case MirGridType.Equipment:
+ return MapObject.User.Equipment;
+ case MirGridType.Storage:
+ return GameScene.Storage;
+ case MirGridType.GuildStorage:
+ return GameScene.GuildStorage;
+ case MirGridType.Trade:
+ return GameScene.User.Trade;
+ case MirGridType.GuestTrade:
+ return GuestTradeDialog.GuestItems;
+ case MirGridType.QuestInventory:
+ return MapObject.User.QuestInventory;
+ case MirGridType.Mail:
+ return MailComposeParcelDialog.Items;
+ case MirGridType.Refine:
+ return GameScene.Refine;
+
+ default:
+ throw new NotImplementedException();
+ }
+
+ }
+ }
+
+ public override bool Border
+ {
+ get { return (GameScene.SelectedCell == this || MouseControl == this || Locked) && !(GridType == MirGridType.DropPanel); }
+ }
+
+ private bool _locked;
+
+ public bool Locked
+ {
+ get { return _locked; }
+ set
+ {
+ if (_locked == value) return;
+ _locked = value;
+ Redraw();
+ }
+ }
+
+
+
+ #region GridType
+
+ private MirGridType _gridType;
+ public event EventHandler GridTypeChanged;
+ public MirGridType GridType
+ {
+ get { return _gridType; }
+ set
+ {
+ if (_gridType == value) return;
+ _gridType = value;
+ OnGridTypeChanged();
+ }
+ }
+
+ private void OnGridTypeChanged()
+ {
+ if (GridTypeChanged != null)
+ GridTypeChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region ItemSlot
+
+ private int _itemSlot;
+ public event EventHandler ItemSlotChanged;
+ public int ItemSlot
+ {
+ get { return _itemSlot; }
+ set
+ {
+ if (_itemSlot == value) return;
+ _itemSlot = value;
+ OnItemSlotChanged();
+ }
+ }
+
+ private void OnItemSlotChanged()
+ {
+ if (ItemSlotChanged != null)
+ ItemSlotChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Count Label
+
+ private MirLabel CountLabel { get; set; }
+
+ #endregion
+
+ public MirItemCell()
+ {
+ Size = new Size(54, 40);
+ GridType = MirGridType.None;
+ DrawImage = false;
+
+ BorderColour = Color.MediumAquamarine;
+
+ BackColour = Color.FromArgb(255, 255, 125, 125);
+ Opacity = 0.5F;
+ DrawControlTexture = true;
+ Library = Libraries.Items;
+ }
+
+ public void SetEffect()
+ {
+ //put effect stuff here??
+ }
+
+
+ public override void OnMouseClick(MouseEventArgs e)
+ {
+ if (Locked || GameScene.Observing) return;
+
+ if (GameScene.PickedUpGold || GridType == MirGridType.QuestInventory) return;
+
+ if (GameScene.SelectedCell == null && (GridType == MirGridType.Mail)) return;
+
+ base.OnMouseClick(e);
+
+ Redraw();
+
+ switch (e.Button)
+ {
+ case MouseButtons.Right:
+ if (CMain.Shift)
+ {
+ if (Item != null)
+ {
+ string text = string.Format("<{0}> ", Item.FriendlyName);
+
+ if (GameScene.Scene.ChatDialog.ChatTextBox.Text.Length + text.Length > Globals.MaxChatLength)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Unable to link item, message exceeds allowed length", ChatType.System);
+ return;
+ }
+
+ GameScene.Scene.ChatDialog.LinkedItems.Add(new ChatItem { UniqueID = Item.UniqueID, Title = Item.FriendlyName, Grid = GridType });
+ GameScene.Scene.ChatDialog.SetChatText(text);
+ }
+
+ break;
+ }
+
+ if (GridType == MirGridType.Inventory && GameScene.Scene.NPCGoodsDialog.Visible)
+ {
+ SellItem();
+ return;
+ }
+
+ UseItem();
+ break;
+ case MouseButtons.Left:
+ if (Item != null && GameScene.SelectedCell == null)
+ PlayItemSound();
+
+ if (CMain.Shift)
+ {
+ if (GridType == MirGridType.Inventory || GridType == MirGridType.Storage)
+ {
+ if (GameScene.SelectedCell == null && Item != null)
+ {
+ if (FreeSpace() == 0)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("No room to split stack.", ChatType.System);
+ return;
+ }
+
+ if (Item.Count > 1)
+ {
+ MirAmountBox amountBox = new MirAmountBox("Split Amount:", Item.Image, Libraries.Items, (uint)(Item.Count - 1));
+
+ amountBox.OKButton.Click += (o, a) =>
+ {
+ if (amountBox.Amount == 0 || amountBox.Amount >= Item.Count) return;
+ Network.Enqueue(new C.SplitItem { Grid = GridType, UniqueID = Item.UniqueID, Count = (ushort)amountBox.Amount });
+ Locked = true;
+ };
+
+ amountBox.Show();
+ }
+ }
+ }
+ }
+
+ //Add support for ALT + click to sell quickly
+ else if (CMain.Alt && GameScene.Scene.NPCDropDialog.Visible && GridType == MirGridType.Inventory) // alt sell/repair
+ {
+ MoveItem(); // pickup item
+ GameScene.Scene.NPCDropDialog.ItemCell.OnMouseClick(e); // emulate click to drop control
+ GameScene.Scene.NPCDropDialog.ConfirmButton.OnMouseClick(e); //emulate OK to confirm trade
+ }
+ //Add support for ALT + click to sell quickly
+
+ else MoveItem();
+ break;
+ }
+ }
+ public override void OnMouseDoubleClick(MouseEventArgs e)
+ {
+ if (Locked) return;
+
+ if (GameScene.PickedUpGold || GridType == MirGridType.TrustMerchant) return;
+
+ base.OnMouseClick(e);
+
+ Redraw();
+
+ GameScene.SelectedCell = null;
+ UseItem();
+ }
+
+
+ private void BuyItem()
+ {
+ if (Item == null || Item.Price() * GameScene.NPCRate > GameScene.Gold) return;
+
+ MirAmountBox amountBox;
+ if (Item.Count > 1)
+ {
+ amountBox = new MirAmountBox("Purchase Amount:", Item.Image, Libraries.Items, Item.Count);
+
+ amountBox.OKButton.Click += (o, e) =>
+ {
+ Network.Enqueue(new C.BuyItemBack { UniqueID = Item.UniqueID, Count = (ushort)amountBox.Amount });
+ Locked = true;
+ };
+ }
+ else
+ {
+ amountBox = new MirAmountBox("Purchase", Item.Image, Libraries.Items, int.MaxValue);
+
+ amountBox.OKButton.Click += (o, e) =>
+ {
+ Network.Enqueue(new C.BuyItemBack { UniqueID = Item.UniqueID, Count = 1 });
+ Locked = true;
+ };
+ }
+
+ amountBox.Show();
+ }
+
+ public void UseItem()
+ {
+ if (Locked || GridType == MirGridType.TrustMerchant || GridType == MirGridType.GuildStorage) return;
+
+ if (GridType == MirGridType.BuyBack)
+ {
+ BuyItem();
+ return;
+ }
+
+ if (GridType == MirGridType.Equipment)
+ {
+ RemoveItem();
+ return;
+ }
+
+ if ((GridType != MirGridType.Inventory && GridType != MirGridType.Storage) || Item == null || !CanUseItem() || GameScene.SelectedCell == this) return;
+
+ CharacterDialog dialog = GameScene.Scene.CharacterDialog;
+ UserObject actor = GameScene.User;
+ if (Item.SoulBoundId != -1 && MapObject.User.Id != Item.SoulBoundId)
+ return;
+
+ switch (Item.Info.Type)
+ {
+ case ItemType.Weapon:
+ if (dialog.Grid[(int)EquipmentSlot.Weapon].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.Weapon });
+ dialog.Grid[(int)EquipmentSlot.Weapon].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Armour:
+ if (dialog.Grid[(int)EquipmentSlot.Armour].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.Armour });
+ dialog.Grid[(int)EquipmentSlot.Armour].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Helmet:
+ if (dialog.Grid[(int)EquipmentSlot.Helmet].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.Helmet });
+ dialog.Grid[(int)EquipmentSlot.Helmet].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Necklace:
+ if (dialog.Grid[(int)EquipmentSlot.Necklace].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.Necklace });
+ dialog.Grid[(int)EquipmentSlot.Necklace].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Bracelet:
+ if ((dialog.Grid[(int)EquipmentSlot.BraceletR].Item == null) && dialog.Grid[(int)EquipmentSlot.BraceletR].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.BraceletR });
+ dialog.Grid[(int)EquipmentSlot.BraceletR].Locked = true;
+ Locked = true;
+ }
+ else if (dialog.Grid[(int)EquipmentSlot.BraceletL].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.BraceletL });
+ dialog.Grid[(int)EquipmentSlot.BraceletL].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Ring:
+ if (dialog.Grid[(int)EquipmentSlot.RingR].Item == null && dialog.Grid[(int)EquipmentSlot.RingR].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.RingR });
+ dialog.Grid[(int)EquipmentSlot.RingR].Locked = true;
+ Locked = true;
+ }
+ else if (dialog.Grid[(int)EquipmentSlot.RingL].CanWearItem(actor, Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GridType, UniqueID = Item.UniqueID, To = (int)EquipmentSlot.RingL });
+ dialog.Grid[(int)EquipmentSlot.RingL].Locked = true;
+ Locked = true;
+ }
+ break;
+ case ItemType.Potion:
+ case ItemType.Scroll:
+ case ItemType.Book:
+ case ItemType.Script:
+ if (CanUseItem() && (GridType == MirGridType.Inventory))
+ {
+ if (CMain.Time < GameScene.UseItemTime) return;
+ if (Item.Info.Type == ItemType.Potion && Item.Info.Shape == 4)
+ {
+ MirMessageBox messageBox = new MirMessageBox("Are you use you want to use this Potion?", MirMessageBoxButtons.YesNo);
+ messageBox.YesButton.Click += (o, e) =>
+ {
+ Network.Enqueue(new C.UseItem { UniqueID = Item.UniqueID, Grid = GridType });
+
+ if (Item.Count == 1 && ItemSlot < GameScene.User.BeltIdx)
+ {
+ for (int i = GameScene.User.BeltIdx; i < GameScene.User.Inventory.Length; i++)
+ if (ItemArray[i] != null && ItemArray[i].Info == Item.Info)
+ {
+ Network.Enqueue(new C.MoveItem { Grid = MirGridType.Inventory, From = i, To = ItemSlot });
+ GameScene.Scene.InventoryDialog.Grid[i - GameScene.User.BeltIdx].Locked = true;
+ break;
+ }
+ }
+
+ GameScene.UseItemTime = CMain.Time + 100;
+ PlayItemSound();
+ };
+
+ messageBox.Show();
+ return;
+ }
+
+ Network.Enqueue(new C.UseItem { UniqueID = Item.UniqueID, Grid = GridType });
+
+ if (Item.Count == 1 && ItemSlot < GameScene.User.BeltIdx)
+ {
+ for (int i = GameScene.User.BeltIdx; i < GameScene.User.Inventory.Length; i++)
+ if (ItemArray[i] != null && ItemArray[i].Info == Item.Info)
+ {
+ Network.Enqueue(new C.MoveItem { Grid = MirGridType.Inventory, From = i, To = ItemSlot });
+ GameScene.Scene.InventoryDialog.Grid[i - GameScene.User.BeltIdx].Locked = true;
+ break;
+ }
+ }
+
+ Locked = true;
+ }
+ break;
+ }
+
+ GameScene.UseItemTime = CMain.Time + 300;
+ PlayItemSound();
+ }
+
+ public void RemoveItem()
+ {
+ int count = 0;
+
+ for (int i = 0; i < GameScene.User.Inventory.Length; i++)
+ {
+ MirItemCell itemCell = i < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[i] : GameScene.Scene.InventoryDialog.Grid[i - GameScene.User.BeltIdx];
+
+ if (itemCell.Item == null) count++;
+ }
+
+ if (Item == null || count < 1) return;
+
+ if (Item.Info.StackSize > 1)
+ {
+ UserItem item = null;
+
+ for (int i = 0; i < GameScene.User.Inventory.Length; i++)
+ {
+ MirItemCell itemCell = i < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[i] : GameScene.Scene.InventoryDialog.Grid[i - GameScene.User.BeltIdx];
+
+ if (itemCell.Item == null || itemCell.Item.Info != Item.Info) continue;
+
+ item = itemCell.Item;
+ }
+
+ if (item != null && ((item.Count + Item.Count) <= item.Info.StackSize))
+ {
+ //Merge.
+ Network.Enqueue(new C.MergeItem { GridFrom = GridType, GridTo = MirGridType.Inventory, IDFrom = Item.UniqueID, IDTo = item.UniqueID });
+
+ Locked = true;
+
+ PlayItemSound();
+ return;
+ }
+ }
+
+ for (int i = 0; i < GameScene.User.Inventory.Length; i++)
+ {
+ MirItemCell itemCell;
+
+ itemCell = i < (GameScene.User.Inventory.Length - GameScene.User.BeltIdx) ? GameScene.Scene.InventoryDialog.Grid[i] : GameScene.Scene.BeltDialog.Grid[i - GameScene.User.Inventory.Length];
+
+ if (itemCell.Item != null) continue;
+
+ Network.Enqueue(new C.RemoveItem { Grid = MirGridType.Inventory, UniqueID = Item.UniqueID, To = itemCell.ItemSlot });
+
+ Locked = true;
+
+ PlayItemSound();
+ break;
+ }
+ }
+
+ private void MoveItem()
+ {
+ if (GridType == MirGridType.BuyBack || GridType == MirGridType.DropPanel || GridType == MirGridType.TrustMerchant) return;
+
+ if (GameScene.SelectedCell != null)
+ {
+ if (GameScene.SelectedCell.Item == null || GameScene.SelectedCell == this)
+ {
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ switch (GridType)
+ {
+ #region To Inventory
+ case MirGridType.Inventory: // To Inventory
+ switch (GameScene.SelectedCell.GridType)
+ {
+ #region From Inventory
+ case MirGridType.Inventory: //From Invenotry
+ if (Item != null)
+ {
+ if (CMain.Ctrl)
+ {
+ MirMessageBox messageBox = new MirMessageBox("Do you want to try and combine these items?", MirMessageBoxButtons.YesNo);
+ messageBox.YesButton.Click += (o, e) =>
+ {
+ //Combine
+ Network.Enqueue(new C.CombineItem { Grid = GameScene.SelectedCell.GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ };
+
+ messageBox.Show();
+ return;
+ }
+
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ //Merge
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ Network.Enqueue(new C.MoveItem { Grid = GridType, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ #endregion
+ #region From Equipment
+ case MirGridType.Equipment: //From Equipment
+ if (!CanRemoveItem(GameScene.SelectedCell.Item))
+ {
+ GameScene.SelectedCell = null;
+ return;
+ }
+ if (Item == null)
+ {
+ Network.Enqueue(new C.RemoveItem { Grid = GridType, UniqueID = GameScene.SelectedCell.Item.UniqueID, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 6; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.RemoveItem { Grid = GridType, UniqueID = GameScene.SelectedCell.Item.UniqueID, To = x });
+
+ MirItemCell temp = x < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[x] : GameScene.Scene.InventoryDialog.Grid[x - GameScene.User.BeltIdx];
+
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ #region From Storage
+ case MirGridType.Storage: //From Storage
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+
+ if (Item == null)
+ {
+ Network.Enqueue(new C.TakeBackItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 6; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.TakeBackItem { From = GameScene.SelectedCell.ItemSlot, To = x });
+
+ MirItemCell temp = x < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[x] : GameScene.Scene.InventoryDialog.Grid[x - GameScene.User.BeltIdx];
+
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ #region From Guild Storage
+ case MirGridType.GuildStorage:
+ if (Item != null)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You cannot swap items.", ChatType.System);
+ return;
+ }
+ if (!GuildDialog.MyOptions.HasFlag(GuildRankOptions.CanRetrieveItem))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Insufficient rights to retrieve items.", ChatType.System);
+ return;
+ }
+ Network.Enqueue(new C.GuildStorageItemChange { Type = 1, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ break;
+ #endregion
+ #region From Trade
+ case MirGridType.Trade: //From Trade
+
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+
+ if (Item == null)
+ {
+ Network.Enqueue(new C.RetrieveTradeItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 6; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.RetrieveTradeItem { From = GameScene.SelectedCell.ItemSlot, To = x });
+
+ MirItemCell temp = x < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[x] : GameScene.Scene.InventoryDialog.Grid[x - GameScene.User.BeltIdx];
+
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ #region From Refine
+ case MirGridType.Refine: //From AwakenItem
+
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+
+ if (Item == null)
+ {
+ Network.Enqueue(new C.RetrieveRefineItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 6; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.RetrieveRefineItem { From = GameScene.SelectedCell.ItemSlot, To = x });
+
+ MirItemCell temp = x < GameScene.User.BeltIdx ? GameScene.Scene.BeltDialog.Grid[x] : GameScene.Scene.InventoryDialog.Grid[x - GameScene.User.BeltIdx];
+
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ }
+ break;
+ #endregion
+ #region To Equipment
+ case MirGridType.Equipment: //To Equipment
+
+ if (GameScene.SelectedCell.GridType != MirGridType.Inventory && GameScene.SelectedCell.GridType != MirGridType.Storage) return;
+
+ if (CorrectSlot(GameScene.SelectedCell.Item, GameScene.SelectedCell.GridType))
+ {
+ if (CanWearItem(GameScene.User, GameScene.SelectedCell.Item))
+ {
+ Network.Enqueue(new C.EquipItem { Grid = GameScene.SelectedCell.GridType, UniqueID = GameScene.SelectedCell.Item.UniqueID, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ }
+ GameScene.SelectedCell = null;
+ }
+ return;
+ #endregion
+ #region To Storage
+ case MirGridType.Storage: //To Storage
+ switch (GameScene.SelectedCell.GridType)
+ {
+ #region From Inventory
+ case MirGridType.Inventory: //From Invenotry
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+
+ if (ItemArray[ItemSlot] == null)
+ {
+ Network.Enqueue(new C.StoreItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 0; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.StoreItem { From = GameScene.SelectedCell.ItemSlot, To = x });
+
+ MirItemCell temp = GameScene.Scene.StorageDialog.Grid[x];
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ #region From Equipment
+ case MirGridType.Equipment: //From Equipment
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ //Merge.
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ if (!CanRemoveItem(GameScene.SelectedCell.Item))
+ {
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ if (Item == null)
+ {
+ Network.Enqueue(new C.RemoveItem { Grid = GridType, UniqueID = GameScene.SelectedCell.Item.UniqueID, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 0; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.RemoveItem { Grid = GridType, UniqueID = GameScene.SelectedCell.Item.UniqueID, To = x });
+
+ MirItemCell temp = GameScene.Scene.StorageDialog.Grid[x];
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ #region From Storage
+ case MirGridType.Storage:
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ //Merge.
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ Network.Enqueue(new C.MoveItem { Grid = GridType, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ #endregion
+
+ }
+ break;
+
+ #endregion
+ #region To guild storage
+ case MirGridType.GuildStorage: //To Guild Storage
+ switch (GameScene.SelectedCell.GridType)
+ {
+ case MirGridType.GuildStorage: //From Guild Storage
+ if (GameScene.SelectedCell.GridType == MirGridType.GuildStorage)
+ {
+ if (!GuildDialog.MyOptions.HasFlag(GuildRankOptions.CanStoreItem))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Insufficient rights to store items.", ChatType.System);
+ return;
+ }
+
+ //if (ItemArray[ItemSlot] == null)
+ //{
+ Network.Enqueue(new C.GuildStorageItemChange { Type = 2, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ //}
+ }
+ return;
+
+ case MirGridType.Inventory:
+
+ if (GameScene.SelectedCell.GridType == MirGridType.Inventory)
+ {
+ if (Item != null)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You cannot swap items.", ChatType.System);
+ return;
+ }
+ if (!GuildDialog.MyOptions.HasFlag(GuildRankOptions.CanStoreItem))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Insufficient rights to store items.", ChatType.System);
+ return;
+ }
+ if (ItemArray[ItemSlot] == null)
+ {
+ Network.Enqueue(new C.GuildStorageItemChange { Type = 0, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+ return;
+ }
+ break;
+ #endregion
+ #region To Trade
+
+ case MirGridType.Trade:
+ if (Item != null && Item.Info.Bind.HasFlag(BindMode.DontTrade)) return;
+
+ switch (GameScene.SelectedCell.GridType)
+ {
+ #region From Trade
+ case MirGridType.Trade: //From Trade
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ //Merge.
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ Network.Enqueue(new C.MoveItem { Grid = GridType, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ #endregion
+
+ #region From Inventory
+ case MirGridType.Inventory: //From Inventory
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+
+ if (ItemArray[ItemSlot] == null)
+ {
+ Network.Enqueue(new C.DepositTradeItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+
+ for (int x = 0; x < ItemArray.Length; x++)
+ if (ItemArray[x] == null)
+ {
+ Network.Enqueue(new C.DepositTradeItem { From = GameScene.SelectedCell.ItemSlot, To = x });
+
+ MirItemCell temp = GameScene.Scene.TradeDialog.Grid[x];
+ if (temp != null) temp.Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ break;
+ #endregion
+ }
+ break;
+
+ #endregion
+ #region To Refine
+
+ case MirGridType.Refine:
+
+ switch (GameScene.SelectedCell.GridType)
+ {
+ #region From Refine
+ case MirGridType.Refine: //From Refine
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ //Merge.
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ Network.Enqueue(new C.MoveItem { Grid = GridType, From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ #endregion
+
+ #region From Inventory
+ case MirGridType.Inventory: //From Inventory
+ if (Item != null)
+ {
+ if (GameScene.SelectedCell.Item.Info == Item.Info && Item.Count < Item.Info.StackSize)
+ {
+ Network.Enqueue(new C.MergeItem { GridFrom = GameScene.SelectedCell.GridType, GridTo = GridType, IDFrom = GameScene.SelectedCell.Item.UniqueID, IDTo = Item.UniqueID });
+
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ }
+ }
+
+ Network.Enqueue(new C.DepositRefineItem { From = GameScene.SelectedCell.ItemSlot, To = ItemSlot });
+ Locked = true;
+ GameScene.SelectedCell.Locked = true;
+ GameScene.SelectedCell = null;
+ return;
+ #endregion
+ }
+ break;
+
+ #endregion
+ #region To Mail
+ case MirGridType.Mail: //To Mail
+ if (GameScene.SelectedCell.GridType == MirGridType.Inventory)
+ {
+ if (Item != null)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You cannot swap items.", ChatType.System);
+ return;
+ }
+
+ if (GameScene.SelectedCell.Item.Info.Bind.HasFlag(BindMode.DontTrade))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You cannot mail this item.", ChatType.System);
+ return;
+ }
+
+ if (ItemArray[ItemSlot] == null)
+ {
+ Item = GameScene.SelectedCell.Item;
+ GameScene.SelectedCell.Locked = true;
+ MailComposeParcelDialog.ItemsIdx[_itemSlot] = GameScene.SelectedCell.Item.UniqueID;
+ GameScene.SelectedCell = null;
+ GameScene.Scene.MailComposeParcelDialog.CalculatePostage();
+
+ return;
+ }
+ }
+ break;
+ #endregion
+ }
+
+ return;
+ }
+
+ if (Item != null)
+ {
+ GameScene.SelectedCell = this;
+ }
+ }
+ private void PlayItemSound()
+ {
+ if (Item == null) return;
+
+ switch (Item.Info.Type)
+ {
+ case ItemType.Weapon:
+ SoundManager.PlaySound(SoundList.ClickWeapon);
+ break;
+ case ItemType.Armour:
+ SoundManager.PlaySound(SoundList.ClickArmour);
+ break;
+ case ItemType.Helmet:
+ SoundManager.PlaySound(SoundList.ClickHelmet);
+ break;
+ case ItemType.Necklace:
+ SoundManager.PlaySound(SoundList.ClickNecklace);
+ break;
+ case ItemType.Bracelet:
+ SoundManager.PlaySound(SoundList.ClickBracelet);
+ break;
+ case ItemType.Ring:
+ SoundManager.PlaySound(SoundList.ClickRing);
+ break;
+ case ItemType.Potion:
+ SoundManager.PlaySound(SoundList.ClickDrug);
+ break;
+ default:
+ SoundManager.PlaySound(SoundList.ClickItem);
+ break;
+ }
+ }
+
+ private int FreeSpace()
+ {
+ int count = 0;
+
+ for (int i = 0; i < ItemArray.Length; i++)
+ if (ItemArray[i] == null) count++;
+
+ return count;
+ }
+
+
+ private bool CanRemoveItem(UserItem i)
+ {
+ return FreeSpace() > 0;
+ }
+
+ private bool CorrectSlot(UserItem i, MirGridType grid)
+ {
+ ItemType type = i.Info.Type;
+
+ switch (GridType)
+ {
+ case MirGridType.Equipment:
+ if (grid != MirGridType.Inventory && grid != MirGridType.Storage)
+ return false;
+ break;
+ }
+
+ switch ((EquipmentSlot)ItemSlot)
+ {
+ case EquipmentSlot.Weapon:
+ return type == ItemType.Weapon;
+ case EquipmentSlot.Armour:
+ return type == ItemType.Armour;
+ case EquipmentSlot.Helmet:
+ return type == ItemType.Helmet;
+ case EquipmentSlot.Necklace:
+ return type == ItemType.Necklace;
+ case EquipmentSlot.BraceletL:
+ return i.Info.Type == ItemType.Bracelet;
+ case EquipmentSlot.BraceletR:
+ return i.Info.Type == ItemType.Bracelet;
+ case EquipmentSlot.RingL:
+ case EquipmentSlot.RingR:
+ return type == ItemType.Ring;
+ default:
+ return false;
+ }
+
+ }
+ private bool CanUseItem()
+ {
+ if (Item == null) return false;
+
+ UserObject actor = GameScene.User;
+
+ switch (actor.Gender)
+ {
+ case MirGender.Male:
+ if (!Item.Info.RequiredGender.HasFlag(RequiredGender.Male))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.NotFemale, ChatType.System);
+ return false;
+ }
+ break;
+ case MirGender.Female:
+ if (!Item.Info.RequiredGender.HasFlag(RequiredGender.Female))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.NotMale, ChatType.System);
+ return false;
+ }
+ break;
+ }
+
+ switch (actor.Class)
+ {
+ case MirClass.Warrior:
+ if (!Item.Info.RequiredClass.HasFlag(RequiredClass.Warrior))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Warriors cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ case MirClass.Wizard:
+ if (!Item.Info.RequiredClass.HasFlag(RequiredClass.Wizard))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Wizards cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ case MirClass.Taoist:
+ if (!Item.Info.RequiredClass.HasFlag(RequiredClass.Taoist))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Taoists cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ }
+
+ switch (Item.Info.RequiredType)
+ {
+ case RequiredType.Level:
+ if (actor.Level < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowLevel, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxAC:
+ if (actor.Stats[Stat.MaxAC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough AC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxMAC:
+ if (actor.Stats[Stat.MaxMAC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough MAC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxDC:
+ if (actor.Stats[Stat.MaxDC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowDC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxMC:
+ if (actor.Stats[Stat.MaxMC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowMC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxSC:
+ if (actor.Stats[Stat.MaxSC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowSC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxLevel:
+ if (actor.Level > Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You have exceeded the maximum level.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinAC:
+ if (actor.Stats[Stat.MinAC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base AC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinMAC:
+ if (actor.Stats[Stat.MinMAC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base MAC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinDC:
+ if (actor.Stats[Stat.MinDC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base DC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinMC:
+ if (actor.Stats[Stat.MinMC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base MC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinSC:
+ if (actor.Stats[Stat.MinSC] < Item.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base SC.", ChatType.System);
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+
+ private bool CanWearItem(UserObject actor, UserItem i)
+ {
+ if (i == null) return false;
+
+ //If Can remove;
+
+ switch (actor.Gender)
+ {
+ case MirGender.Male:
+ if (!i.Info.RequiredGender.HasFlag(RequiredGender.Male))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.NotFemale, ChatType.System);
+ return false;
+ }
+ break;
+ case MirGender.Female:
+ if (!i.Info.RequiredGender.HasFlag(RequiredGender.Female))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.NotMale, ChatType.System);
+ return false;
+ }
+ break;
+ }
+
+ switch (actor.Class)
+ {
+ case MirClass.Warrior:
+ if (!i.Info.RequiredClass.HasFlag(RequiredClass.Warrior))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Warriors cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ case MirClass.Wizard:
+ if (!i.Info.RequiredClass.HasFlag(RequiredClass.Wizard))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Wizards cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ case MirClass.Taoist:
+ if (!i.Info.RequiredClass.HasFlag(RequiredClass.Taoist))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Taoists cannot use this item.", ChatType.System);
+ return false;
+ }
+ break;
+ }
+
+ switch (i.Info.RequiredType)
+ {
+ case RequiredType.Level:
+ if (actor.Level < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowLevel, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxAC:
+ if (actor.Stats[Stat.MaxAC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough AC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxMAC:
+ if (actor.Stats[Stat.MaxMAC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough MAC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxDC:
+ if (actor.Stats[Stat.MaxDC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowDC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxMC:
+ if (actor.Stats[Stat.MaxMC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowMC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxSC:
+ if (actor.Stats[Stat.MaxSC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.LowSC, ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MaxLevel:
+ if (actor.Level > i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You have exceeded the maximum level.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinAC:
+ if (actor.Stats[Stat.MinAC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base AC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinMAC:
+ if (actor.Stats[Stat.MinMAC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base MAC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinDC:
+ if (actor.Stats[Stat.MinDC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base DC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinMC:
+ if (actor.Stats[Stat.MinMC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base MC.", ChatType.System);
+ return false;
+ }
+ break;
+ case RequiredType.MinSC:
+ if (actor.Stats[Stat.MinSC] < i.Info.RequiredAmount)
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("You do not have enough Base SC.", ChatType.System);
+ return false;
+ }
+ break;
+ }
+
+ if (i.Info.Type == ItemType.Weapon)
+ {
+ if (i.Weight - (Item != null ? Item.Weight : 0) + actor.CurrentHandWeight > actor.Stats[Stat.HandWeight])
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat(GameLanguage.TooHeavyToHold, ChatType.System);
+ return false;
+ }
+ }
+ else
+ {
+ if (i.Weight - (Item != null ? Item.Weight : 0) + actor.CurrentWearWeight > actor.Stats[Stat.WearWeight])
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("It is too heavy to wear.", ChatType.System);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected internal override void DrawControl()
+ {
+
+ if (GridType == MirGridType.Inventory && ItemSlot < 6)
+ Libraries.Prguse.Draw(158 + ItemSlot, DisplayLocation.Add(new Point(-2, -1)), Color.White);
+
+ Libraries.Prguse.Draw(1121, DisplayLocation.Add(new Point(-2, -1)), Color.White, UseOffSet, 0.8F);
+
+ if (Item != null && GameScene.SelectedCell != this && Locked != true)
+ {
+ CreateDisposeLabel();
+
+ if (Library != null)
+ {
+ ushort image = Item.Image;
+
+ Size imgSize = Library.GetTrueSize(image);
+
+ Point offSet = new Point((Size.Width - imgSize.Width) / 2, (Size.Height - imgSize.Height) / 2);
+
+ Library.Draw(image, DisplayLocation.Add(offSet), ForeColour, UseOffSet, 1F);
+
+ if (Item.SealedInfo != null && Item.SealedInfo.ExpiryDate > CMain.Now)
+ {
+ Libraries.StateItems.Draw(3590, DisplayLocation.Add(new Point(2, 2)), Color.White, UseOffSet, 1F);
+ }
+ }
+ }
+ else if (Item != null && (GameScene.SelectedCell == this || Locked))
+ {
+ CreateDisposeLabel();
+
+ if (Library != null)
+ {
+ ushort image = Item.Image;
+
+ Size imgSize = Library.GetTrueSize(image);
+
+ Point offSet = new Point((Size.Width - imgSize.Width) / 2, (Size.Height - imgSize.Height) / 2);
+
+ Library.Draw(image, DisplayLocation.Add(offSet), Color.DimGray, UseOffSet, 0.8F);
+ }
+ }
+ else if (ShadowItem != null)
+ {
+ CreateDisposeLabel();
+
+ if (Library != null)
+ {
+ ushort image = ShadowItem.Info.Image;
+
+ Size imgSize = Library.GetTrueSize(image);
+
+ Point offSet = new Point((Size.Width - imgSize.Width) / 2, (Size.Height - imgSize.Height) / 2);
+
+ Library.Draw(image, DisplayLocation.Add(offSet), Color.DimGray, UseOffSet, 0.8F);
+ }
+ }
+ else
+ DisposeCountLabel();
+ }
+
+ protected override void OnMouseEnter()
+ {
+ base.OnMouseEnter();
+ if (Item != null)
+ GameScene.Scene.CreateItemLabel(Item);
+ else if (ShadowItem != null)
+ GameScene.Scene.CreateItemLabel(ShadowItem, false, ShadowItem.CurrentDura == ShadowItem.MaxDura);
+ }
+ protected override void OnMouseLeave()
+ {
+ base.OnMouseLeave();
+ GameScene.Scene.DisposeItemLabel();
+ GameScene.HoverItem = null;
+ }
+
+ private void CreateDisposeLabel()
+ {
+ if (Item == null && ShadowItem == null)
+ return;
+
+ if (Item != null && ShadowItem == null && Item.Info.StackSize <= 1)
+ {
+ DisposeCountLabel();
+ return;
+ }
+
+ if (CountLabel == null || CountLabel.IsDisposed)
+ {
+ CountLabel = new MirLabel
+ {
+ AutoSize = true,
+ ForeColour = Color.Yellow,
+ NotControl = true,
+ OutLine = false,
+ Parent = this,
+ };
+ }
+
+ if (ShadowItem != null)
+ {
+ CountLabel.ForeColour = (Item == null || ShadowItem.Count > Item.Count) ? Color.Red : Color.LimeGreen;
+ CountLabel.Text = string.Format("{0}/{1}", Item == null ? 0 : Item.Count, ShadowItem.Count);
+ }
+ else
+ {
+ CountLabel.Text = Item.Count.ToString("###0");
+ }
+
+ CountLabel.Location = new Point(Size.Width - CountLabel.Size.Width, Size.Height - CountLabel.Size.Height);
+ }
+ private void DisposeCountLabel()
+ {
+ if (CountLabel != null && !CountLabel.IsDisposed)
+ CountLabel.Dispose();
+ CountLabel = null;
+ }
+ private void SellItem()
+ {
+ if (Item.Info.Bind.HasFlag(BindMode.DontSell))
+ {
+ GameScene.Scene.ChatDialog.ReceiveChat("Cannot sell this item.", ChatType.System);
+ return;
+ }
+ if (GameScene.Gold + Item.Price() / 2 <= uint.MaxValue)
+ {
+ MirMessageBox messageBox = new MirMessageBox($"Sell {Item.FriendlyName} for {Item.Price() / 2} gold?", MirMessageBoxButtons.YesNo);
+
+ messageBox.YesButton.Click += (o1, a) =>
+ {
+ Network.Enqueue(new C.SellItem { UniqueID = Item.UniqueID, Count = Item.Count });
+ Locked = true;
+ };
+
+ messageBox.Show();
+ return;
+ }
+ GameScene.Scene.ChatDialog.ReceiveChat("Cannot carry anymore gold.", ChatType.System);
+ }
+ }
+}
diff --git a/Client/MirControls/MirLabel.cs b/Client/MirControls/MirLabel.cs
new file mode 100644
index 0000000..2674934
--- /dev/null
+++ b/Client/MirControls/MirLabel.cs
@@ -0,0 +1,274 @@
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Drawing.Text;
+using Client.MirGraphics;
+using SlimDX;
+using SlimDX.Direct3D9;
+using Font = System.Drawing.Font;
+
+namespace Client.MirControls
+{
+ public class MirLabel : MirControl
+ {
+ #region Auto Size
+ private bool _autoSize;
+ public bool AutoSize
+ {
+ get { return _autoSize; }
+ set
+ {
+ if (_autoSize == value)
+ return;
+ _autoSize = value;
+ OnAutoSizeChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler AutoSizeChanged;
+ private void OnAutoSizeChanged(EventArgs e)
+ {
+ TextureValid = false;
+ GetSize();
+ if (AutoSizeChanged != null)
+ AutoSizeChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region DrawFormat
+ private TextFormatFlags _drawFormat;
+ public TextFormatFlags DrawFormat
+ {
+ get { return _drawFormat; }
+ set
+ {
+ _drawFormat = value;
+ OnDrawFormatChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler DrawFormatChanged;
+ private void OnDrawFormatChanged(EventArgs e)
+ {
+ TextureValid = false;
+
+ if (DrawFormatChanged != null)
+ DrawFormatChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region Font
+ private Font _font;
+ public Font Font
+ {
+ get { return _font; }
+ set
+ {
+ _font = ScaleFont(value);
+ OnFontChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler FontChanged;
+ private void OnFontChanged(EventArgs e)
+ {
+ TextureValid = false;
+
+ GetSize();
+
+ if (FontChanged != null)
+ FontChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region Out Line
+ private bool _outLine;
+ public bool OutLine
+ {
+ get { return _outLine; }
+ set
+ {
+ if (_outLine == value)
+ return;
+ _outLine = value;
+ OnOutLineChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler OutLineChanged;
+ private void OnOutLineChanged(EventArgs e)
+ {
+ TextureValid = false;
+ GetSize();
+
+ if (OutLineChanged != null)
+ OutLineChanged.Invoke(this, e);
+ }
+ #endregion
+
+ #region Out Line Colour
+ private Color _outLineColour;
+ public Color OutLineColour
+ {
+ get { return _outLineColour; }
+ set
+ {
+ if (_outLineColour == value)
+ return;
+ _outLineColour = value;
+ OnOutLineColourChanged();
+ }
+ }
+ public event EventHandler OutLineColourChanged;
+ private void OnOutLineColourChanged()
+ {
+ TextureValid = false;
+
+ if (OutLineColourChanged != null)
+ OutLineColourChanged.Invoke(this, EventArgs.Empty);
+ }
+ #endregion
+
+ #region Size
+
+ private void GetSize()
+ {
+ if (!AutoSize)
+ return;
+
+ if (string.IsNullOrEmpty(_text))
+ Size = Size.Empty;
+ else
+ {
+ Size = TextRenderer.MeasureText(CMain.Graphics, Text, Font);
+ //Size = new Size(Size.Width, Size.Height + 5);
+
+ if (OutLine && Size != Size.Empty)
+ Size = new Size(Size.Width + 2, Size.Height + 2);
+ }
+ }
+ #endregion
+
+ #region Label
+ private string _text;
+ public string Text
+ {
+ get { return _text; }
+ set
+ {
+ if (_text == value)
+ return;
+
+ _text = value;
+ OnTextChanged(EventArgs.Empty);
+ }
+ }
+ public event EventHandler TextChanged;
+ private void OnTextChanged(EventArgs e)
+ {
+ DrawControlTexture = !string.IsNullOrEmpty(Text);
+ TextureValid = false;
+ Redraw();
+
+ GetSize();
+
+ if (TextChanged != null)
+ TextChanged.Invoke(this, e);
+ }
+ #endregion
+
+ public MirLabel()
+ {
+ DrawControlTexture = true;
+ _drawFormat = TextFormatFlags.WordBreak;
+
+ _font = ScaleFont(new Font(Settings.FontName, 8F));
+ _outLine = true;
+ _outLineColour = Color.Black;
+ _text = string.Empty;
+
+ }
+
+ protected override unsafe void CreateTexture()
+ {
+ if (string.IsNullOrEmpty(Text))
+ return;
+
+ if (Size.Width == 0 || Size.Height == 0)
+ return;
+
+ if (TextureSize != Size)
+ DisposeTexture();
+
+ if (ControlTexture == null || ControlTexture.Disposed)
+ {
+ DXManager.ControlList.Add(this);
+
+ ControlTexture = new Texture(DXManager.Device, Size.Width, Size.Height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+ TextureSize = Size;
+ }
+
+ DataRectangle stream = ControlTexture.LockRectangle(0, LockFlags.Discard);
+ using (Bitmap image = new Bitmap(Size.Width, Size.Height, Size.Width * 4, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
+ {
+ using (Graphics graphics = Graphics.FromImage(image))
+ {
+ graphics.SmoothingMode = SmoothingMode.AntiAlias;
+ graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.TextContrast = 0;
+ graphics.Clear(BackColour);
+
+
+ if (OutLine)
+ {
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(1, 0, Size.Width, Size.Height), OutLineColour, DrawFormat);
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(0, 1, Size.Width, Size.Height), OutLineColour, DrawFormat);
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(2, 1, Size.Width, Size.Height), OutLineColour, DrawFormat);
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(1, 2, Size.Width, Size.Height), OutLineColour, DrawFormat);
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(1, 1, Size.Width, Size.Height), ForeColour, DrawFormat);
+
+ //LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, this.Size.Width, this.Size.Height), Color.FromArgb(239, 243, 239), Color.White, LinearGradientMode.Vertical);
+ ////graphics.DrawString(Text, Font, brush, 37, 9);
+ ////graphics.DrawString(this.Text, this.Font, new SolidBrush(Color.Black), 39, 9, StringFormat.GenericDefault);
+ }
+ else
+ TextRenderer.DrawText(graphics, Text, Font, new Rectangle(1, 0, Size.Width, Size.Height), ForeColour, DrawFormat);
+ }
+ }
+
+ ControlTexture.UnlockRectangle(0);
+ DXManager.Sprite.Flush();
+ TextureValid = true;
+ }
+
+ #region Disposable
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ AutoSizeChanged = null;
+ _autoSize = false;
+
+ DrawFormatChanged = null;
+ _drawFormat = 0;
+
+ FontChanged = null;
+ if (_font != null)
+ {
+ _font.Dispose();
+ _font = null;
+ }
+
+ OutLineChanged = null;
+ _outLine = false;
+
+ OutLineColourChanged = null;
+ _outLineColour = Color.Empty;
+
+ TextChanged = null;
+ _text = null;
+ }
+ #endregion
+
+ }
+}
diff --git a/Client/MirControls/MirMessageBox.cs b/Client/MirControls/MirMessageBox.cs
new file mode 100644
index 0000000..d00a033
--- /dev/null
+++ b/Client/MirControls/MirMessageBox.cs
@@ -0,0 +1,251 @@
+using Client.MirGraphics;
+
+namespace Client.MirControls
+{
+ public enum MirMessageBoxButtons { OK, OKCancel, YesNo, YesNoCancel, Cancel }
+
+ public sealed class MirMessageBox : MirImageControl
+ {
+ public MirLabel Label;
+ public MirButton OKButton, CancelButton, NoButton, YesButton;
+ public MirMessageBoxButtons Buttons;
+ private MirGeneratedBox GeneratedBox;
+ public bool AllowKeyPress = true;
+
+ public MirMessageBox(string message, MirMessageBoxButtons b = MirMessageBoxButtons.OK, bool allowKeys = true)
+ {
+ DrawImage = false;
+ ForeColour = Color.White;
+ Buttons = b;
+ Modal = true;
+ Movable = false;
+ AllowKeyPress = allowKeys;
+
+ AutoSize = false;
+ Size = new Size(440, 160);
+
+ Location = new Point((Settings.ScreenWidth - Size.Width) / 2, (Settings.ScreenHeight - Size.Height) / 2);
+
+ GeneratedBox = new MirGeneratedBox(79, Size)
+ {
+ Parent = this,
+ Visible = true
+ };
+
+ Label = new MirLabel
+ {
+ AutoSize = false,
+ Location = new Point(10, 10),
+ Size = new Size(390, 110),
+ Parent = this,
+ Text = message
+ };
+
+
+ switch (Buttons)
+ {
+ case MirMessageBoxButtons.OK:
+ OKButton = new MirButton
+ {
+ Index = 115,
+ Library = Libraries.Prguse,
+ Location = new Point(182, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 116,
+ };
+ OKButton.Click += (o, e) => Dispose();
+ break;
+ case MirMessageBoxButtons.OKCancel:
+ OKButton = new MirButton
+ {
+ Index = 115,
+ Library = Libraries.Prguse,
+ Location = new Point(124, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 116,
+ };
+ OKButton.Click += (o, e) => Dispose();
+ CancelButton = new MirButton
+ {
+ Index = 117,
+ Library = Libraries.Prguse,
+ Location = new Point(240, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 118,
+ };
+ CancelButton.Click += (o, e) => Dispose();
+ break;
+ case MirMessageBoxButtons.YesNo:
+ YesButton = new MirButton
+ {
+ Index = 50,
+ Library = Libraries.Prguse,
+ Location = new Point(124, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 51,
+ };
+ YesButton.Click += (o, e) => Dispose();
+ NoButton = new MirButton
+ {
+ Index = 52,
+ Library = Libraries.Prguse,
+ Location = new Point(240, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 53,
+ };
+ NoButton.Click += (o, e) => Dispose();
+ break;
+ case MirMessageBoxButtons.YesNoCancel:
+ YesButton = new MirButton
+ {
+ Index = 50,
+ Library = Libraries.Prguse,
+ Location = new Point(124, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 51,
+ };
+ YesButton.Click += (o, e) => Dispose();
+ NoButton = new MirButton
+ {
+ Index = 52,
+ Library = Libraries.Prguse,
+ Location = new Point(240, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 53,
+ };
+ NoButton.Click += (o, e) => Dispose();
+ CancelButton = new MirButton
+ {
+ Index = 117,
+ Library = Libraries.Prguse,
+ Location = new Point(364, Size.Height - 35),
+ Parent = this,
+ PressedIndex = 118,
+ };
+ CancelButton.Click += (o, e) => Dispose();
+ break;
+ case MirMessageBoxButtons.Cancel:
+ CancelButton = new MirButton
+ {
+ Index = 117,
+ Library = Libraries.Prguse,
+ Location = new Point(182, Size.Height - 35),
+ Parent = this,
+ };
+ CancelButton.Click += (o, e) => Dispose();
+ break;
+ }
+ }
+
+ public override void Show()
+ {
+ if (Parent != null) return;
+
+ Parent = MirScene.ActiveScene;
+
+ Highlight();
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = Program.Form.Controls[i] as TextBox;
+ if (T != null && T.Tag != null && T.Tag != null)
+ ((MirTextBox)T.Tag).DialogChanged();
+ }
+ }
+
+
+ public override void OnKeyDown(KeyEventArgs e)
+ {
+ if (AllowKeyPress)
+ {
+ base.OnKeyDown(e);
+ e.Handled = true;
+ }
+ }
+ public override void OnKeyUp(KeyEventArgs e)
+ {
+ if (AllowKeyPress)
+ {
+ base.OnKeyUp(e);
+ e.Handled = true;
+ }
+ }
+ public override void OnKeyPress(KeyPressEventArgs e)
+ {
+ base.OnKeyPress(e);
+
+ if (AllowKeyPress)
+ {
+ if (e.KeyChar == (char)Keys.Escape)
+ {
+ switch (Buttons)
+ {
+ case MirMessageBoxButtons.OK:
+ if (OKButton != null && !OKButton.IsDisposed) OKButton.InvokeMouseClick(null);
+ break;
+ case MirMessageBoxButtons.OKCancel:
+ case MirMessageBoxButtons.YesNoCancel:
+ if (CancelButton != null && !CancelButton.IsDisposed) CancelButton.InvokeMouseClick(null);
+ break;
+ case MirMessageBoxButtons.YesNo:
+ if (NoButton != null && !NoButton.IsDisposed) NoButton.InvokeMouseClick(null);
+ break;
+ }
+ }
+
+ else if (e.KeyChar == (char)Keys.Enter)
+ {
+ switch (Buttons)
+ {
+ case MirMessageBoxButtons.OK:
+ case MirMessageBoxButtons.OKCancel:
+ if (OKButton != null && !OKButton.IsDisposed) OKButton.InvokeMouseClick(null);
+ break;
+ case MirMessageBoxButtons.YesNoCancel:
+ case MirMessageBoxButtons.YesNo:
+ if (YesButton != null && !YesButton.IsDisposed) YesButton.InvokeMouseClick(null);
+ break;
+
+ }
+ }
+ e.Handled = true;
+ }
+ }
+
+
+ public static void Show(string message, bool close = false)
+ {
+ MirMessageBox box = new MirMessageBox(message, MirMessageBoxButtons.OK);
+
+ if (close) box.OKButton.Click += (o, e) => Program.Form.Close();
+
+ box.Show();
+ }
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ Label = null;
+ OKButton = null;
+ CancelButton = null;
+ NoButton = null;
+ YesButton = null;
+ Buttons = 0;
+
+ for (int i = 0; i < Program.Form.Controls.Count; i++)
+ {
+ TextBox T = (TextBox) Program.Form.Controls[i];
+ if (T != null && T.Tag != null)
+ ((MirTextBox) T.Tag).DialogChanged();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Client/MirControls/MirScene.cs b/Client/MirControls/MirScene.cs
new file mode 100644
index 0000000..0215e98
--- /dev/null
+++ b/Client/MirControls/MirScene.cs
@@ -0,0 +1,259 @@
+using Client.MirGraphics;
+using Client.MirNetwork;
+using Client.MirScenes;
+using SlimDX.Direct3D9;
+using S = ServerPackets;
+
+namespace Client.MirControls
+{
+ public abstract class MirScene : MirControl
+ {
+ public static MirScene ActiveScene = new LoginScene();
+
+ private static MouseButtons _buttons;
+ private static long _lastClickTime;
+ private static MirControl _clickedControl;
+
+ protected MirScene()
+ {
+ DrawControlTexture = true;
+ BackColour = Color.Magenta;
+ Size = new Size(Settings.ScreenWidth, Settings.ScreenHeight);
+ }
+
+ public override sealed Size Size
+ {
+ get { return base.Size; }
+ set { base.Size = value; }
+ }
+
+ public override void Draw()
+ {
+ if (IsDisposed || !Visible)
+ return;
+
+ OnBeforeShown();
+
+ DrawControl();
+
+ if (CMain.DebugBaseLabel != null && !CMain.DebugBaseLabel.IsDisposed)
+ CMain.DebugBaseLabel.Draw();
+
+ if (CMain.HintBaseLabel != null && !CMain.HintBaseLabel.IsDisposed)
+ CMain.HintBaseLabel.Draw();
+
+ OnShown();
+ }
+
+ protected override void CreateTexture()
+ {
+ if (Size != TextureSize)
+ DisposeTexture();
+
+ if (ControlTexture == null || ControlTexture.Disposed)
+ {
+ DXManager.ControlList.Add(this);
+ ControlTexture = new Texture(DXManager.Device, Size.Width, Size.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
+ TextureSize = Size;
+ }
+ Surface oldSurface = DXManager.CurrentSurface;
+ Surface surface = ControlTexture.GetSurfaceLevel(0);
+ DXManager.SetSurface(surface);
+
+ DXManager.Device.Clear(ClearFlags.Target, BackColour, 0, 0);
+
+ BeforeDrawControl();
+ DrawChildControls();
+ AfterDrawControl();
+
+ DXManager.Sprite.Flush();
+
+
+ DXManager.SetSurface(oldSurface);
+ TextureValid = true;
+ surface.Dispose();
+ }
+
+ public override void OnMouseDown(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ if (MouseControl != null && MouseControl != this)
+ MouseControl.OnMouseDown(e);
+ else
+ base.OnMouseDown(e);
+ }
+ public override void OnMouseUp(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+ if (MouseControl != null && MouseControl != this)
+ MouseControl.OnMouseUp(e);
+ else
+ base.OnMouseUp(e);
+ }
+ public override void OnMouseMove(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ if (MouseControl != null && MouseControl != this && MouseControl.Moving)
+ MouseControl.OnMouseMove(e);
+ else
+ base.OnMouseMove(e);
+ }
+ public override void OnMouseWheel(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+
+ if (MouseControl != null && MouseControl != this)
+ MouseControl.OnMouseWheel(e);
+ else
+ base.OnMouseWheel(e);
+ }
+
+ public override void OnMouseClick(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+ if (_buttons == e.Button)
+ {
+ if (_lastClickTime + SystemInformation.DoubleClickTime >= CMain.Time)
+ {
+ OnMouseDoubleClick(e);
+ return;
+ }
+ }
+ else
+ _lastClickTime = 0;
+
+ if (ActiveControl != null && ActiveControl.IsMouseOver(CMain.MPoint) && ActiveControl != this)
+ ActiveControl.OnMouseClick(e);
+ else
+ base.OnMouseClick(e);
+
+ _clickedControl = ActiveControl;
+
+ _lastClickTime = CMain.Time;
+ _buttons = e.Button;
+ }
+
+ public override void OnMouseDoubleClick(MouseEventArgs e)
+ {
+ if (!Enabled)
+ return;
+ _lastClickTime = 0;
+ _buttons = MouseButtons.None;
+
+ if (ActiveControl != null && ActiveControl.IsMouseOver(CMain.MPoint) && ActiveControl != this)
+ {
+ if (ActiveControl == _clickedControl)
+ ActiveControl.OnMouseDoubleClick(e);
+ else
+ ActiveControl.OnMouseClick(e);
+ }
+ else
+ {
+ if (ActiveControl == _clickedControl)
+ base.OnMouseDoubleClick(e);
+ else
+ base.OnMouseClick(e);
+ }
+ }
+
+ public override void Redraw()
+ {
+ TextureValid = false;
+ }
+
+ public virtual void ProcessPacket(Packet p)
+ {
+ switch (p.Index)
+ {
+ case (short)ServerPacketIds.Disconnect: // Disconnected
+ Disconnect((S.Disconnect) p);
+ Network.Disconnect();
+ break;
+ case (short)ServerPacketIds.NewItemInfo:
+ NewItemInfo((S.NewItemInfo) p);
+ break;
+ case (short)ServerPacketIds.NewChatItem:
+ NewChatItem((S.NewChatItem)p);
+ break;
+ case (short)ServerPacketIds.NewQuestInfo:
+ NewQuestInfo((S.NewQuestInfo)p);
+ break;
+ }
+ }
+
+ private void NewItemInfo(S.NewItemInfo info)
+ {
+ GameScene.ItemInfoList.Add(info.Info);
+ }
+
+ private void NewChatItem(S.NewChatItem p)
+ {
+ if (GameScene.ChatItemList.Any(x => x.UniqueID == p.Item.UniqueID)) return;
+
+ GameScene.Bind(p.Item);
+ GameScene.ChatItemList.Add(p.Item);
+ }
+
+ private void NewQuestInfo(S.NewQuestInfo info)
+ {
+ GameScene.QuestInfoList.Add(info.Info);
+ }
+
+ private static void Disconnect(S.Disconnect p)
+ {
+ switch (p.Reason)
+ {
+ case 0:
+ MirMessageBox.Show(GameLanguage.ShuttingDown, true);
+ break;
+ case 1:
+ MirMessageBox.Show("Disconnected: Another user logged onto your account.", true);
+ break;
+ case 2:
+ MirMessageBox.Show("Disconnected: Packet Error.", true);
+ break;
+ case 3:
+ MirMessageBox.Show("Disconnected: Server Crashed.", true);
+ break;
+ case 4:
+ MirMessageBox.Show("Disconnected: Kicked by Admin.", true);
+ break;
+ case 5:
+ MirMessageBox.Show("Disconnected: Maximum connections reached.", true);
+ break;
+ case 6:
+ MirMessageBox.Show("Disconnected: Account has been Banned!.", true);
+ break;
+ }
+
+ GameScene.LogTime = 0;
+ }
+
+ public abstract void Process();
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ if (ActiveScene == this) ActiveScene = null;
+
+ _buttons = 0;
+ _lastClickTime = 0;
+ _clickedControl = null;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Client/MirControls/MirScrollingLabel.cs b/Client/MirControls/MirScrollingLabel.cs
new file mode 100644
index 0000000..1d3ccdf
--- /dev/null
+++ b/Client/MirControls/MirScrollingLabel.cs
@@ -0,0 +1,110 @@
+using System.Text.RegularExpressions;
+
+namespace Client.MirControls
+{
+ public class MirScrollingLabel : MirControl
+ {
+ private static readonly Regex R = new Regex(@"<(.*?/\@.*?)>");
+ private static readonly Regex C = new Regex(@"{(.*?/.*?)}");
+
+ private readonly MirLabel[] _textLabel;
+ private readonly List _textButtons;
+
+ public int Index;
+
+ public Font Font = new Font(Settings.FontName, 8F);
+ public List CurrentLines = new List();
+ public int VisibleLines = 8;
+
+ public MirScrollingLabel()
+ {
+ _textLabel = new MirLabel[12];
+ _textButtons = new List();
+ }
+
+ public void NewText(List lines, bool resetIndex = true)
+ {
+ if (resetIndex)
+ {
+ Index = 0;
+ CurrentLines = lines;
+ }
+
+ foreach (MirLabel t in _textButtons)
+ t.Dispose();
+
+ foreach (MirLabel t in _textLabel.Where(t => t != null))
+ t.Text = "";
+
+ _textButtons.Clear();
+
+ int lastLine = lines.Count > VisibleLines ? ((VisibleLines + Index) > lines.Count ? lines.Count : (VisibleLines + Index)) : lines.Count;
+
+ for (int i = Index; i < lastLine; i++)
+ {
+ _textLabel[i - Index] = new MirLabel
+ {
+ Font = Font,
+ DrawFormat = TextFormatFlags.WordBreak,
+ Visible = true,
+ Parent = this,
+ Size = new Size(Size.Width, 20),
+ Location = new Point(0, 0 + (i - Index) * 15),
+ NotControl = true
+ };
+
+ if (i >= lines.Count)
+ {
+ _textLabel[i - Index].Text = string.Empty;
+ continue;
+ }
+
+ string currentLine = lines[i];
+
+ List matchList = R.Matches(currentLine).Cast().ToList();
+ matchList.AddRange(C.Matches(currentLine).Cast());
+
+ int oldLength = currentLine.Length;
+
+ foreach (Match match in matchList.OrderBy(o => o.Index).ToList())
+ {
+ int offSet = oldLength - currentLine.Length;
+
+ Capture capture = match.Groups[1].Captures[0];
+ string[] values = capture.Value.Split('/');
+ currentLine = currentLine.Remove(capture.Index - 1 - offSet, capture.Length + 2).Insert(capture.Index - 1 - offSet, values[0]);
+ string text = currentLine.Substring(0, capture.Index - 1 - offSet) + " ";
+ Size size = TextRenderer.MeasureText(CMain.Graphics, text, _textLabel[i - Index].Font, _textLabel[i - Index].Size, TextFormatFlags.TextBoxControl);
+
+ //if (R.Match(match.Value).Success)
+ // NewButton(values[0], values[1], TextLabel[i].Location.Add(new Point(size.Width - 10, 0)));
+
+ if (C.Match(match.Value).Success)
+ NewColour(values[0], values[1], _textLabel[i - Index].Location.Add(new Point(size.Width - 10, 0)));
+ }
+
+ _textLabel[i - Index].Text = currentLine;
+ //TextLabel[i].MouseWheel += NPCDialog_MouseWheel;
+ }
+ }
+
+ private void NewColour(string text, string colour, Point p)
+ {
+ Color textColour = Color.FromName(colour);
+
+ MirLabel temp = new MirLabel
+ {
+ AutoSize = true,
+ Visible = true,
+ Parent = this,
+ Location = p,
+ Text = text,
+ ForeColour = textColour,
+ Font = Font
+ };
+ //temp.MouseWheel += NPCDialog_MouseWheel;
+
+ _textButtons.Add(temp);
+ }
+ }
+}
diff --git a/Client/MirControls/MirTextBox.cs b/Client/MirControls/MirTextBox.cs
new file mode 100644
index 0000000..db1f1a2
--- /dev/null
+++ b/Client/MirControls/MirTextBox.cs
@@ -0,0 +1,423 @@
+using Client.MirGraphics;
+using SlimDX;
+using SlimDX.Direct3D9;
+using System.Drawing.Imaging;
+
+namespace Client.MirControls
+{
+ public sealed class MirTextBox : MirControl
+ {
+ #region Back Color
+
+ protected override void OnBackColourChanged()
+ {
+ base.OnBackColourChanged();
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.BackColor = BackColour;
+ }
+
+ #endregion
+
+ #region Enabled
+
+ protected override void OnEnabledChanged()
+ {
+ base.OnEnabledChanged();
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Enabled = Enabled;
+ }
+
+ #endregion
+
+ #region Fore Color
+
+ protected override void OnForeColourChanged()
+ {
+ base.OnForeColourChanged();
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.ForeColor = ForeColour;
+ }
+
+ #endregion
+
+ #region Location
+
+ protected override void OnLocationChanged()
+ {
+ base.OnLocationChanged();
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Location = DisplayLocation;
+
+ TextureValid = false;
+ Redraw();
+ }
+
+ #endregion
+
+ #region Max Length
+
+ public int MaxLength
+ {
+ get
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ return TextBox.MaxLength;
+ return -1;
+ }
+ set
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.MaxLength = value;
+ }
+ }
+
+ #endregion
+
+ #region Parent
+
+ protected override void OnParentChanged()
+ {
+ base.OnParentChanged();
+ if (TextBox != null && !TextBox.IsDisposed)
+ OnVisibleChanged();
+ }
+
+ #endregion
+
+ #region Password
+
+ public bool Password
+ {
+ get
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ return TextBox.UseSystemPasswordChar;
+ return false;
+ }
+ set
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.UseSystemPasswordChar = value;
+ }
+ }
+
+ #endregion
+
+ #region Font
+
+ public System.Drawing.Font Font
+ {
+ get
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ return TextBox.Font;
+ return null;
+ }
+ set
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Font = ScaleFont(value);
+ }
+ }
+
+ #endregion
+
+ #region Size
+
+ protected override void OnSizeChanged()
+ {
+ TextBox.Size = Size;
+
+ DisposeTexture();
+
+ _size = Size;
+
+ if (TextBox != null && !TextBox.IsDisposed)
+ base.OnSizeChanged();
+ }
+
+ #endregion
+
+ #region TextBox
+
+ public bool CanLoseFocus;
+ public readonly TextBox TextBox;
+ private Pen CaretPen;
+
+ #endregion
+
+ #region Label
+
+ public string Text
+ {
+ get
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ return TextBox.Text;
+ return null;
+ }
+ set
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Text = value;
+ }
+ }
+ public string[] MultiText
+ {
+ get
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ return TextBox.Lines;
+ return null;
+ }
+ set
+ {
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Lines = value;
+ }
+ }
+
+ #endregion
+
+ #region Visible
+
+ public override bool Visible
+ {
+ get
+ {
+ return base.Visible;
+ }
+ set
+ {
+ base.Visible = value;
+ OnVisibleChanged();
+ }
+ }
+
+ protected override void OnVisibleChanged()
+ {
+ base.OnVisibleChanged();
+
+ if (TextBox != null && !TextBox.IsDisposed)
+ TextBox.Visible = Visible;
+ }
+ private void TextBox_VisibleChanged(object sender, EventArgs e)
+ {
+ DialogChanged();
+
+ if (TextBox.Visible && TextBox.CanFocus)
+ if (Program.Form.ActiveControl == null || Program.Form.ActiveControl == Program.Form)
+ Program.Form.ActiveControl = TextBox;
+
+ if (!TextBox.Visible)
+ if (Program.Form.ActiveControl == TextBox)
+ Program.Form.Focus();
+ }
+ private void SetFocus(object sender, EventArgs e)
+ {
+ if (TextBox.Visible)
+ TextBox.VisibleChanged -= SetFocus;
+ if (TextBox.Parent != null)
+ TextBox.ParentChanged -= SetFocus;
+
+ if (TextBox.CanFocus) TextBox.Focus();
+ else if (TextBox.Visible && TextBox.Parent != null)
+ Program.Form.ActiveControl = TextBox;
+
+
+ }
+
+ #endregion
+
+ #region MultiLine
+
+ public override void MultiLine()
+ {
+ TextBox.Multiline = true;
+ TextBox.Size = Size;
+
+ DisposeTexture();
+ Redraw();
+ }
+
+ #endregion
+
+ public MirTextBox()
+ {
+ BackColour = Color.Black;
+
+ DrawControlTexture = true;
+ TextureValid = false;
+
+ TextBox = new TextBox
+ {
+ BackColor = BackColour,
+ BorderStyle = BorderStyle.None,
+ Font = new System.Drawing.Font(Settings.FontName, 10F * 96f / CMain.Graphics.DpiX),
+ ForeColor = ForeColour,
+ Location = DisplayLocation,
+ Size = Size,
+ Visible = Visible,
+ Tag = this,
+ Cursor = CMain.Cursors[(byte)MouseCursor.TextPrompt]
+ };
+
+ CaretPen = new Pen(ForeColour, 1);
+
+ TextBox.VisibleChanged += TextBox_VisibleChanged;
+ TextBox.ParentChanged += TextBox_VisibleChanged;
+ TextBox.KeyUp += TextBoxOnKeyUp;
+ TextBox.KeyPress += TextBox_KeyPress;
+
+ TextBox.KeyPress += TextBox_NeedRedraw;
+ TextBox.KeyUp += TextBox_NeedRedraw;
+ TextBox.MouseDown += TextBox_NeedRedraw;
+ TextBox.MouseUp += TextBox_NeedRedraw;
+ TextBox.LostFocus += TextBox_NeedRedraw;
+ TextBox.GotFocus += TextBox_NeedRedraw;
+ TextBox.MouseWheel += TextBox_NeedRedraw;
+
+ Shown += MirTextBox_Shown;
+ TextBox.MouseMove += CMain.CMain_MouseMove;
+ }
+
+ private void TextBox_NeedRedraw(object sender, EventArgs e)
+ {
+ TextureValid = false;
+ Redraw();
+ }
+
+ protected unsafe override void CreateTexture()
+ {
+ if (!Settings.FullScreen) return;
+
+ if (Size.IsEmpty)
+ return;
+
+ if (TextureSize != Size)
+ DisposeTexture();
+
+ if (ControlTexture == null || ControlTexture.Disposed)
+ {
+ DXManager.ControlList.Add(this);
+
+ ControlTexture = new Texture(DXManager.Device, Size.Width, Size.Height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+ TextureSize = Size;
+ }
+
+ Point caret = GetCaretPosition();
+
+ DataRectangle stream = ControlTexture.LockRectangle(0, LockFlags.Discard);
+ using (Bitmap bm = new Bitmap(Size.Width, Size.Height, Size.Width * 4, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
+ {
+ TextBox.DrawToBitmap(bm, new Rectangle(0, 0, Size.Width, Size.Height));
+ using (Graphics graphics = Graphics.FromImage(bm))
+ {
+ graphics.DrawImage(bm, Point.Empty);
+ if (TextBox.Focused)
+ graphics.DrawLine(CaretPen, new Point(caret.X, caret.Y), new Point(caret.X, caret.Y + TextBox.Font.Height));
+ }
+
+ }
+ ControlTexture.UnlockRectangle(0);
+ DXManager.Sprite.Flush();
+ TextureValid = true;
+ }
+
+ private Point GetCaretPosition()
+ {
+ Point result = TextBox.GetPositionFromCharIndex(TextBox.SelectionStart);
+
+ if (result.X == 0 && TextBox.Text.Length > 0)
+ {
+ result = TextBox.GetPositionFromCharIndex(TextBox.Text.Length - 1);
+ int s = result.X / TextBox.Text.Length;
+ result.X = (int)(result.X + (s * 1.46));
+ result.Y = TextBox.GetLineFromCharIndex(TextBox.SelectionStart) * TextBox.Font.Height;
+ }
+
+ return result;
+ }
+
+ private void TextBoxOnKeyUp(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.PrintScreen:
+ CMain.CMain_KeyUp(sender, e);
+ break;
+
+ }
+ }
+
+ void TextBox_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ base.OnKeyPress(e);
+
+ if (e.KeyChar == (char)Keys.Escape)
+ {
+ Program.Form.ActiveControl = null;
+ e.Handled = true;
+ }
+ }
+
+
+ void MirTextBox_Shown(object sender, EventArgs e)
+ {
+ TextBox.Parent = Program.Form;
+ CMain.Ctrl = false;
+ CMain.Shift = false;
+ CMain.Alt = false;
+ CMain.Tilde = false;
+
+ TextureValid = false;
+ SetFocus();
+ }
+
+ public void SetFocus()
+ {
+ if (!TextBox.Visible)
+ TextBox.VisibleChanged += SetFocus;
+ else if (TextBox.Parent == null)
+ TextBox.ParentChanged += SetFocus;
+ else
+ TextBox.Focus();
+ }
+
+ public void DialogChanged()
+ {
+ MirMessageBox box1 = null;
+ MirInputBox box2 = null;
+ MirAmountBox box3 = null;
+
+ if (MirScene.ActiveScene != null && MirScene.ActiveScene.Controls.Count > 0)
+ {
+ box1 = (MirMessageBox) MirScene.ActiveScene.Controls.FirstOrDefault(ob => ob is MirMessageBox);
+ box2 = (MirInputBox) MirScene.ActiveScene.Controls.FirstOrDefault(O => O is MirInputBox);
+ box3 = (MirAmountBox) MirScene.ActiveScene.Controls.FirstOrDefault(ob => ob is MirAmountBox);
+ }
+
+
+ if ((box1 != null && box1 != Parent) || (box2 != null && box2 != Parent) || (box3 != null && box3 != Parent))
+ TextBox.Visible = false;
+ else
+ TextBox.Visible = Visible && TextBox.Parent != null;
+ }
+
+
+ #region Disposable
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (!disposing) return;
+
+ if (!TextBox.IsDisposed)
+ TextBox.Dispose();
+ }
+
+
+ #endregion
+ }
+}
diff --git a/Client/MirGraphics/DXManager.cs b/Client/MirGraphics/DXManager.cs
new file mode 100644
index 0000000..cdc7742
--- /dev/null
+++ b/Client/MirGraphics/DXManager.cs
@@ -0,0 +1,595 @@
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using Client.MirControls;
+using Client.MirScenes;
+using SlimDX;
+using SlimDX.Direct3D9;
+using Blend = SlimDX.Direct3D9.Blend;
+
+namespace Client.MirGraphics
+{
+ class DXManager
+ {
+ public static List TextureList = new List();
+ public static List ControlList = new List();
+
+ public static Device Device;
+ public static Sprite Sprite;
+ public static Line Line;
+
+ public static Surface CurrentSurface;
+ public static Surface MainSurface;
+ public static PresentParameters Parameters;
+ public static bool DeviceLost;
+ public static float Opacity = 1F;
+ public static bool Blending;
+ public static float BlendingRate;
+ public static BlendMode BlendingMode;
+
+
+ public static Texture RadarTexture;
+ public static List Lights = new List();
+ public static Texture PoisonDotBackground;
+
+ public static Texture FloorTexture, LightTexture;
+ public static Surface FloorSurface, LightSurface;
+
+ public static PixelShader GrayScalePixelShader;
+ public static PixelShader NormalPixelShader;
+ public static PixelShader MagicPixelShader;
+
+ public static bool GrayScale;
+
+ public static Point[] LightSizes =
+ {
+ new Point(125,95),
+ new Point(205,156),
+ new Point(285,217),
+ new Point(365,277),
+ new Point(445,338),
+ new Point(525,399),
+ new Point(605,460),
+ new Point(685,521),
+ new Point(765,581),
+ new Point(845,642),
+ new Point(925,703)
+ };
+
+ public static void Create()
+ {
+ Parameters = new PresentParameters
+ {
+ BackBufferFormat = Format.X8R8G8B8,
+ PresentFlags = PresentFlags.LockableBackBuffer,
+ BackBufferWidth = Settings.ScreenWidth,
+ BackBufferHeight = Settings.ScreenHeight,
+ SwapEffect = SwapEffect.Discard,
+ PresentationInterval = Settings.FPSCap ? PresentInterval.One : PresentInterval.Immediate,
+ Windowed = !Settings.FullScreen,
+ };
+
+
+ Direct3D d3d = new Direct3D();
+
+ Capabilities devCaps = d3d.GetDeviceCaps(0, DeviceType.Hardware);
+ DeviceType devType = DeviceType.Reference;
+ CreateFlags devFlags = CreateFlags.HardwareVertexProcessing;
+
+ if (devCaps.VertexShaderVersion.Major >= 2 && devCaps.PixelShaderVersion.Major >= 2)
+ devType = DeviceType.Hardware;
+
+ if ((devCaps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
+ devFlags = CreateFlags.HardwareVertexProcessing;
+
+
+ if ((devCaps.DeviceCaps & DeviceCaps.PureDevice) != 0)
+ devFlags |= CreateFlags.PureDevice;
+
+
+ Device = new Device(d3d, d3d.Adapters.DefaultAdapter.Adapter, devType, Program.Form.Handle, devFlags, Parameters);
+
+ Device.SetDialogBoxMode(true);
+
+ LoadTextures();
+ LoadPixelsShaders();
+ }
+
+ private static unsafe void LoadPixelsShaders()
+ {
+ var shaderNormalPath = Settings.ShadersPath + "normal.ps";
+ var shaderGrayScalePath = Settings.ShadersPath + "grayscale.ps";
+ var shaderMagicPath = Settings.ShadersPath + "magic.ps";
+
+ if (System.IO.File.Exists(shaderNormalPath))
+ {
+ using (var gs = ShaderBytecode.AssembleFromFile(shaderNormalPath, ShaderFlags.None))
+ NormalPixelShader = new PixelShader(Device, gs);
+ }
+ if (System.IO.File.Exists(shaderGrayScalePath))
+ {
+ using (var gs = ShaderBytecode.AssembleFromFile(shaderGrayScalePath, ShaderFlags.None))
+ GrayScalePixelShader = new PixelShader(Device, gs);
+ }
+ if (System.IO.File.Exists(shaderMagicPath))
+ {
+ using (var gs = ShaderBytecode.AssembleFromFile(shaderMagicPath, ShaderFlags.None))
+ MagicPixelShader = new PixelShader(Device, gs);
+ }
+ }
+
+ private static unsafe void LoadTextures()
+ {
+ Sprite = new Sprite(Device);
+ Line = new Line(Device) { Width = 1F };
+
+ MainSurface = Device.GetBackBuffer(0, 0);
+ CurrentSurface = MainSurface;
+ Device.SetRenderTarget(0, MainSurface);
+
+ if (RadarTexture == null || RadarTexture.Disposed)
+ {
+ RadarTexture = new Texture(Device, 2, 2, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+
+ DataRectangle stream = RadarTexture.LockRectangle(0, LockFlags.Discard);
+ using (Bitmap image = new Bitmap(2, 2, 8, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
+ using (Graphics graphics = Graphics.FromImage(image))
+ graphics.Clear(Color.White);
+ RadarTexture.UnlockRectangle(0);
+ }
+ if (PoisonDotBackground == null || PoisonDotBackground.Disposed)
+ {
+ PoisonDotBackground = new Texture(Device, 5, 5, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+
+ DataRectangle stream = PoisonDotBackground.LockRectangle(0, LockFlags.Discard);
+ using (Bitmap image = new Bitmap(5, 5, 20, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
+ using (Graphics graphics = Graphics.FromImage(image))
+ graphics.Clear(Color.White);
+ PoisonDotBackground.UnlockRectangle(0);
+ }
+ CreateLights();
+ }
+
+ private unsafe static void CreateLights()
+ {
+
+ for (int i = Lights.Count - 1; i >= 0; i--)
+ Lights[i].Dispose();
+
+ Lights.Clear();
+
+ for (int i = 1; i < LightSizes.Length; i++)
+ {
+ // int width = 125 + (57 *i);
+ //int height = 110 + (57 * i);
+ int width = LightSizes[i].X;
+ int height = LightSizes[i].Y;
+
+ Texture light = new Texture(Device, width, height, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+
+ DataRectangle stream = light.LockRectangle(0, LockFlags.Discard);
+ using (Bitmap image = new Bitmap(width, height, width * 4, PixelFormat.Format32bppArgb, stream.Data.DataPointer))
+ {
+ using (Graphics graphics = Graphics.FromImage(image))
+ {
+ using (GraphicsPath path = new GraphicsPath())
+ {
+ //path.AddEllipse(new Rectangle(0, 0, width, height));
+ //using (PathGradientBrush brush = new PathGradientBrush(path))
+ //{
+ // graphics.Clear(Color.FromArgb(0, 0, 0, 0));
+ // brush.SurroundColors = new[] { Color.FromArgb(0, 255, 255, 255) };
+ // brush.CenterColor = Color.FromArgb(255, 255, 255, 255);
+ // graphics.FillPath(brush, path);
+ // graphics.Save();
+ //}
+
+ path.AddEllipse(new Rectangle(0, 0, width, height));
+ using (PathGradientBrush brush = new PathGradientBrush(path))
+ {
+ Color[] blendColours = { Color.White,
+ Color.FromArgb(255,210,210,210),
+ Color.FromArgb(255,160,160,160),
+ Color.FromArgb(255,70,70,70),
+ Color.FromArgb(255,40,40,40),
+ Color.FromArgb(0,0,0,0)};
+
+ float[] radiusPositions = { 0f, .20f, .40f, .60f, .80f, 1.0f };
+
+ ColorBlend colourBlend = new ColorBlend();
+ colourBlend.Colors = blendColours;
+ colourBlend.Positions = radiusPositions;
+
+ graphics.Clear(Color.FromArgb(0, 0, 0, 0));
+ brush.InterpolationColors = colourBlend;
+ brush.SurroundColors = blendColours;
+ brush.CenterColor = Color.White;
+ graphics.FillPath(brush, path);
+ graphics.Save();
+ }
+ }
+ }
+ }
+
+ light.UnlockRectangle(0);
+ //light.Disposing += (o, e) => Lights.Remove(light);
+ Lights.Add(light);
+ }
+ }
+
+ public static void SetSurface(Surface surface)
+ {
+ if (CurrentSurface == surface)
+ return;
+
+ Sprite.Flush();
+ CurrentSurface = surface;
+ Device.SetRenderTarget(0, surface);
+ }
+ public static void SetGrayscale(bool value)
+ {
+ GrayScale = value;
+
+ if (value == true)
+ {
+ if (Device.PixelShader == GrayScalePixelShader) return;
+ Sprite.Flush();
+ Device.PixelShader = GrayScalePixelShader;
+ }
+ else
+ {
+ if (Device.PixelShader == null) return;
+ Sprite.Flush();
+ Device.PixelShader = null;
+ }
+ }
+
+ public static void DrawOpaque(Texture texture, Rectangle? sourceRect, Vector3? position, Color4 color, float opacity)
+ {
+ color.Alpha = opacity;
+ Draw(texture, sourceRect, position, color);
+ }
+
+ public static void Draw(Texture texture, Rectangle? sourceRect, Vector3? position, Color4 color)
+ {
+ Sprite.Draw(texture, sourceRect, Vector3.Zero, position, color);
+ CMain.DPSCounter++;
+ }
+
+ public static void AttemptReset()
+ {
+ try
+ {
+ Result result = DXManager.Device.TestCooperativeLevel();
+
+ if (result.Code == ResultCode.DeviceLost.Code) return;
+
+ if (result.Code == ResultCode.DeviceNotReset.Code)
+ {
+ DXManager.ResetDevice();
+ return;
+ }
+
+ if (result.Code != ResultCode.Success.Code) return;
+
+ DXManager.DeviceLost = false;
+ }
+ catch
+ {
+ }
+ }
+
+ public static void ResetDevice()
+ {
+ DXManager.CleanUp();
+ DXManager.DeviceLost = true;
+
+ if (DXManager.Parameters == null) return;
+
+ Size clientSize = Program.Form.ClientSize;
+
+ if (clientSize.Width == 0 || clientSize.Height == 0) return;
+
+ DXManager.Parameters.Windowed = !Settings.FullScreen;
+ DXManager.Parameters.BackBufferWidth = clientSize.Width;
+ DXManager.Parameters.BackBufferHeight = clientSize.Height;
+ DXManager.Parameters.PresentationInterval = Settings.FPSCap ? PresentInterval.Default : PresentInterval.Immediate;
+ DXManager.Device.Reset(DXManager.Parameters);
+
+ DXManager.LoadTextures();
+ }
+
+ public static void AttemptRecovery()
+ {
+ try
+ {
+ Sprite.End();
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ Device.EndScene();
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ MainSurface = Device.GetBackBuffer(0, 0);
+ CurrentSurface = MainSurface;
+ Device.SetRenderTarget(0, MainSurface);
+ }
+ catch
+ {
+ }
+ }
+ public static void SetOpacity(float opacity)
+ {
+ if (Opacity == opacity)
+ return;
+
+ Sprite.Flush();
+ Device.SetRenderState(RenderState.AlphaBlendEnable, true);
+ if (opacity >= 1 || opacity < 0)
+ {
+ Device.SetRenderState(RenderState.SourceBlend, SlimDX.Direct3D9.Blend.SourceAlpha);
+ Device.SetRenderState(RenderState.DestinationBlend, SlimDX.Direct3D9.Blend.InverseSourceAlpha);
+ Device.SetRenderState(RenderState.SourceBlendAlpha, Blend.One);
+ Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb(255, 255, 255, 255).ToArgb());
+ }
+ else
+ {
+ Device.SetRenderState(RenderState.SourceBlend, Blend.BlendFactor);
+ Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseBlendFactor);
+ Device.SetRenderState(RenderState.SourceBlendAlpha, Blend.SourceAlpha);
+ Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb((byte)(255 * opacity), (byte)(255 * opacity), (byte)(255 * opacity), (byte)(255 * opacity)).ToArgb());
+ }
+ Opacity = opacity;
+ Sprite.Flush();
+ }
+ public static void SetBlend(bool value, float rate = 1F, BlendMode mode = BlendMode.NORMAL)
+ {
+ if (value == Blending && BlendingRate == rate && BlendingMode == mode) return;
+
+ Blending = value;
+ BlendingRate = rate;
+ BlendingMode = mode;
+
+ Sprite.Flush();
+
+ Sprite.End();
+
+ if (Blending)
+ {
+ Sprite.Begin(SpriteFlags.DoNotSaveState);
+ Device.SetRenderState(RenderState.AlphaBlendEnable, true);
+
+ switch (BlendingMode)
+ {
+ case BlendMode.INVLIGHT:
+ Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
+ Device.SetRenderState(RenderState.SourceBlend, Blend.BlendFactor);
+ Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceColor);
+ break;
+ default:
+ Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
+ Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
+ break;
+ }
+
+ Device.SetRenderState(RenderState.BlendFactor, Color.FromArgb((byte)(255 * BlendingRate), (byte)(255 * BlendingRate),
+ (byte)(255 * BlendingRate), (byte)(255 * BlendingRate)).ToArgb());
+ }
+ else
+ Sprite.Begin(SpriteFlags.AlphaBlend);
+
+ Device.SetRenderTarget(0, CurrentSurface);
+ }
+
+ public static void SetNormal(float blend, Color tintcolor)
+ {
+ if (Device.PixelShader == NormalPixelShader)
+ return;
+
+ Sprite.Flush();
+ Device.PixelShader = NormalPixelShader;
+ Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
+ Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
+ Sprite.Flush();
+ }
+
+ public static void SetGrayscale(float blend, Color tintcolor)
+ {
+ if (Device.PixelShader == GrayScalePixelShader)
+ return;
+
+ Sprite.Flush();
+ Device.PixelShader = GrayScalePixelShader;
+ Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
+ Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
+ Sprite.Flush();
+ }
+
+ public static void SetBlendMagic(float blend, Color tintcolor)
+ {
+ if (Device.PixelShader == MagicPixelShader || MagicPixelShader == null)
+ return;
+
+ Sprite.Flush();
+ Device.PixelShader = MagicPixelShader;
+ Device.SetPixelShaderConstant(0, new Vector4[] { new Vector4(1.0F, 1.0F, 1.0F, blend) });
+ Device.SetPixelShaderConstant(1, new Vector4[] { new Vector4(tintcolor.R / 255, tintcolor.G / 255, tintcolor.B / 255, 1.0F) });
+ Sprite.Flush();
+ }
+
+ public static void Clean()
+ {
+ for (int i = TextureList.Count - 1; i >= 0; i--)
+ {
+ MImage m = TextureList[i];
+
+ if (m == null)
+ {
+ TextureList.RemoveAt(i);
+ continue;
+ }
+
+ if (CMain.Time <= m.CleanTime) continue;
+
+ m.DisposeTexture();
+ }
+
+ for (int i = ControlList.Count - 1; i >= 0; i--)
+ {
+ MirControl c = ControlList[i];
+
+ if (c == null)
+ {
+ ControlList.RemoveAt(i);
+ continue;
+ }
+
+ if (CMain.Time <= c.CleanTime) continue;
+
+ c.DisposeTexture();
+ }
+ }
+
+
+ private static void CleanUp()
+ {
+ if (Sprite != null)
+ {
+ if (!Sprite.Disposed)
+ {
+ Sprite.Dispose();
+ }
+
+ Sprite = null;
+ }
+
+ if (Line != null)
+ {
+ if (!Line.Disposed)
+ {
+ Line.Dispose();
+ }
+
+ Line = null;
+ }
+
+ if (CurrentSurface != null)
+ {
+ if (!CurrentSurface.Disposed)
+ {
+ CurrentSurface.Dispose();
+ }
+
+ CurrentSurface = null;
+ }
+
+ if (PoisonDotBackground != null)
+ {
+ if (!PoisonDotBackground.Disposed)
+ {
+ PoisonDotBackground.Dispose();
+ }
+
+ PoisonDotBackground = null;
+ }
+
+ if (RadarTexture != null)
+ {
+ if (!RadarTexture.Disposed)
+ {
+ RadarTexture.Dispose();
+ }
+
+ RadarTexture = null;
+ }
+
+ if (FloorTexture != null)
+ {
+ if (!FloorTexture.Disposed)
+ {
+ FloorTexture.Dispose();
+ }
+
+ DXManager.FloorTexture = null;
+ GameScene.Scene.MapControl.FloorValid = false;
+
+ if (DXManager.FloorSurface != null && !DXManager.FloorSurface.Disposed)
+ {
+ DXManager.FloorSurface.Dispose();
+ }
+
+ DXManager.FloorSurface = null;
+ }
+
+ if (LightTexture != null)
+ {
+ if (!LightTexture.Disposed)
+ LightTexture.Dispose();
+
+ DXManager.LightTexture = null;
+
+ if (DXManager.LightSurface != null && !DXManager.LightSurface.Disposed)
+ {
+ DXManager.LightSurface.Dispose();
+ }
+
+ DXManager.LightSurface = null;
+ }
+
+ if (Lights != null)
+ {
+ for (int i = 0; i < Lights.Count; i++)
+ {
+ if (!Lights[i].Disposed)
+ Lights[i].Dispose();
+ }
+ Lights.Clear();
+ }
+
+ for (int i = TextureList.Count - 1; i >= 0; i--)
+ {
+ MImage m = TextureList[i];
+
+ if (m == null) continue;
+
+ m.DisposeTexture();
+ }
+ TextureList.Clear();
+
+
+ for (int i = ControlList.Count - 1; i >= 0; i--)
+ {
+ MirControl c = ControlList[i];
+
+ if (c == null) continue;
+
+ c.DisposeTexture();
+ }
+ ControlList.Clear();
+ }
+
+ public static void Dispose()
+ {
+ CleanUp();
+
+ Device.Direct3D?.Dispose();
+
+ if (Program.Form.WindowState != FormWindowState.Normal)
+ {
+ Device.Dispose();
+ }
+
+ NormalPixelShader?.Dispose();
+ GrayScalePixelShader?.Dispose();
+ MagicPixelShader?.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Client/MirGraphics/MLibrary.cs b/Client/MirGraphics/MLibrary.cs
new file mode 100644
index 0000000..e5f7e8d
--- /dev/null
+++ b/Client/MirGraphics/MLibrary.cs
@@ -0,0 +1,679 @@
+using SlimDX;
+using SlimDX.Direct3D9;
+using System.IO.Compression;
+using Frame = Client.MirObjects.Frame;
+using Client.MirObjects;
+using System.Text.RegularExpressions;
+
+namespace Client.MirGraphics
+{
+ public static class Libraries
+ {
+ public static bool Loaded;
+ public static int Count, Progress;
+
+ public static readonly MLibrary
+ Body = new MLibrary(Settings.DataPath + "Body"),
+ Head = new MLibrary(Settings.DataPath + "Head"),
+ Weapon = new MLibrary(Settings.DataPath + "Weapon"),
+ Monster = new MLibrary(Settings.DataPath + "Monster"),
+ DungeonMonster = new MLibrary(Settings.DataPath + "DungeonMonster"),
+ Prguse = new MLibrary(Settings.DataPath + "Prguse"),
+ Prguse2 = new MLibrary(Settings.DataPath + "Prguse2"),
+ BuffIcon = new MLibrary(Settings.DataPath + "BuffIcon"),
+ Help = new MLibrary(Settings.DataPath + "Help"),
+ MiniMap = new MLibrary(Settings.DataPath + "MMap"),
+ MagIcon = new MLibrary(Settings.DataPath + "MagIcon"),
+ Magic = new MLibrary(Settings.DataPath + "Magic"),
+ Magic2 = new MLibrary(Settings.DataPath + "Magic2"),
+ Effect = new MLibrary(Settings.DataPath + "Effect");
+
+ //Map
+ public static readonly MLibrary[] MapLibs = new MLibrary[3];
+
+ //Items
+ public static readonly MLibrary
+ Items = new MLibrary(Settings.DataPath + "Items"),
+ StateItems = new MLibrary(Settings.DataPath + "StateItem"),
+ FloorItems = new MLibrary(Settings.DataPath + "DNItems");
+
+ static Libraries()
+ {
+ MapLibs[0] = new MLibrary(Settings.DataPath + "Tiles");
+ MapLibs[1] = new MLibrary(Settings.DataPath + "Smtiles");
+ MapLibs[2] = new MLibrary(Settings.DataPath + "Objects");
+
+ LoadLibraries();
+
+ Thread thread = new Thread(LoadGameLibraries) { IsBackground = true };
+ thread.Start();
+ }
+
+ static void LoadLibraries()
+ {
+ Prguse.Initialize();
+ Progress++;
+
+ Prguse2.Initialize();
+ Progress++;
+ }
+
+ private static void LoadGameLibraries()
+ {
+ Count = MapLibs.Length + 17;
+
+ Body.Initialize();
+ Progress++;
+
+ Head.Initialize();
+ Progress++;
+
+ Weapon.Initialize();
+ Progress++;
+
+ Monster.Initialize();
+ Progress++;
+
+ DungeonMonster.Initialize();
+ Progress++;
+
+ BuffIcon.Initialize();
+ Progress++;
+
+ Help.Initialize();
+ Progress++;
+
+ MiniMap.Initialize();
+ Progress++;
+
+ MagIcon.Initialize();
+ Progress++;
+
+ Magic.Initialize();
+ Progress++;
+ Magic2.Initialize();
+ Progress++;
+
+ Effect.Initialize();
+ Progress++;
+
+ Items.Initialize();
+ Progress++;
+ StateItems.Initialize();
+ Progress++;
+ FloorItems.Initialize();
+ Progress++;
+
+ for (int i = 0; i < MapLibs.Length; i++)
+ {
+ if (MapLibs[i] == null)
+ MapLibs[i] = new MLibrary("");
+ else
+ MapLibs[i].Initialize();
+ Progress++;
+ }
+
+ Loaded = true;
+ }
+
+ }
+
+ public sealed class MLibrary
+ {
+ public const string Extention = ".Lib";
+ public const int LibVersion = 1;
+
+ private readonly string _fileName;
+
+ private MImage[] _images;
+ private int[] _indexList;
+ private int _count;
+ private bool _initialized;
+
+ private BinaryReader _reader;
+ private FileStream _fStream;
+
+ public MLibrary(string filename)
+ {
+ _fileName = Path.ChangeExtension(filename, Extention);
+ }
+
+ public void Initialize()
+ {
+ _initialized = true;
+
+ if (!File.Exists(_fileName))
+ return;
+
+ try
+ {
+ _fStream = new FileStream(_fileName, FileMode.Open, FileAccess.Read);
+ _reader = new BinaryReader(_fStream);
+ int currentVersion = _reader.ReadInt32();
+ if (currentVersion != 1)
+ {
+ System.Windows.Forms.MessageBox.Show("Wrong version, expecting lib version: " + LibVersion.ToString() + " found version: " + currentVersion.ToString() + ".", _fileName, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error, System.Windows.Forms.MessageBoxDefaultButton.Button1);
+ System.Windows.Forms.Application.Exit();
+ return;
+ }
+ _count = _reader.ReadInt32();
+ _images = new MImage[_count];
+ _indexList = new int[_count];
+
+ for (int i = 0; i < _count; i++)
+ _indexList[i] = _reader.ReadInt32();
+ }
+ catch (Exception)
+ {
+ _initialized = false;
+ throw;
+ }
+ }
+
+ private bool CheckImage(int index)
+ {
+ if (!_initialized)
+ Initialize();
+
+ if (_images == null || index < 0 || index >= _images.Length)
+ return false;
+
+ if (_images[index] == null)
+ {
+ _fStream.Position = _indexList[index];
+ _images[index] = new MImage(_reader);
+ }
+ MImage mi = _images[index];
+ if (!mi.TextureValid)
+ {
+ if ((mi.Width == 0) || (mi.Height == 0))
+ return false;
+ _fStream.Seek(_indexList[index] + 12, SeekOrigin.Begin);
+ mi.CreateTexture(_reader);
+ }
+
+ return true;
+ }
+
+ public Point GetOffSet(int index)
+ {
+ if (!_initialized) Initialize();
+
+ if (_images == null || index < 0 || index >= _images.Length)
+ return Point.Empty;
+
+ if (_images[index] == null)
+ {
+ _fStream.Seek(_indexList[index], SeekOrigin.Begin);
+ _images[index] = new MImage(_reader);
+ }
+
+ return new Point(_images[index].X, _images[index].Y);
+ }
+ public Size GetSize(int index)
+ {
+ if (!_initialized) Initialize();
+ if (_images == null || index < 0 || index >= _images.Length)
+ return Size.Empty;
+
+ if (_images[index] == null)
+ {
+ _fStream.Seek(_indexList[index], SeekOrigin.Begin);
+ _images[index] = new MImage(_reader);
+ }
+
+ return new Size(_images[index].Width, _images[index].Height);
+ }
+ public Size GetTrueSize(int index)
+ {
+ if (!_initialized)
+ Initialize();
+
+ if (_images == null || index < 0 || index >= _images.Length)
+ return Size.Empty;
+
+ if (_images[index] == null)
+ {
+ _fStream.Position = _indexList[index];
+ _images[index] = new MImage(_reader);
+ }
+ MImage mi = _images[index];
+ if (mi.TrueSize.IsEmpty)
+ {
+ if (!mi.TextureValid)
+ {
+ if ((mi.Width == 0) || (mi.Height == 0))
+ return Size.Empty;
+
+ _fStream.Seek(_indexList[index] + 12, SeekOrigin.Begin);
+ mi.CreateTexture(_reader);
+ }
+ return mi.GetTrueSize();
+ }
+ return mi.TrueSize;
+ }
+
+ public void Draw(int index, int x, int y)
+ {
+ if (x >= Settings.ScreenWidth || y >= Settings.ScreenHeight)
+ return;
+
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (x + mi.Width < 0 || y + mi.Height < 0)
+ return;
+
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)x, (float)y, 0.0F), Color.White);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ public void Draw(int index, Point point, Color colour, bool offSet = false)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (offSet) point.Offset(mi.X, mi.Y);
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), colour);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public void Draw(int index, Point point, Color colour, bool offSet, float opacity)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (offSet) point.Offset(mi.X, mi.Y);
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ DXManager.DrawOpaque(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), colour, opacity);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public void DrawBlend(int index, Point point, Color colour, bool offSet = false, float rate = 1)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (offSet) point.Offset(mi.X, mi.Y);
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ bool oldBlend = DXManager.Blending;
+ DXManager.SetBlend(true, rate);
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), colour);
+
+ DXManager.SetBlend(oldBlend);
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ public void Draw(int index, Rectangle section, Point point, Color colour, bool offSet)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (offSet) point.Offset(mi.X, mi.Y);
+
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ if (section.Right > mi.Width)
+ section.Width -= section.Right - mi.Width;
+
+ if (section.Bottom > mi.Height)
+ section.Height -= section.Bottom - mi.Height;
+
+ DXManager.Draw(mi.Image, section, new Vector3((float)point.X, (float)point.Y, 0.0F), colour);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ public void Draw(int index, Rectangle section, Point point, Color colour, float opacity)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ if (section.Right > mi.Width)
+ section.Width -= section.Right - mi.Width;
+
+ if (section.Bottom > mi.Height)
+ section.Height -= section.Bottom - mi.Height;
+
+ DXManager.DrawOpaque(mi.Image, section, new Vector3((float)point.X, (float)point.Y, 0.0F), colour, opacity);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ public void Draw(int index, Point point, Size size, Color colour)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + size.Width < 0 || point.Y + size.Height < 0)
+ return;
+
+ float scaleX = (float)size.Width / mi.Width;
+ float scaleY = (float)size.Height / mi.Height;
+
+ Matrix matrix = Matrix.Scaling(scaleX, scaleY, 0);
+ DXManager.Sprite.Transform = matrix;
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X / scaleX, (float)point.Y / scaleY, 0.0F), Color.White);
+
+ DXManager.Sprite.Transform = Matrix.Identity;
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public void DrawTinted(int index, Point point, Color colour, Color Tint, bool offSet = false)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ if (offSet) point.Offset(mi.X, mi.Y);
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), colour);
+
+ if (mi.HasMask)
+ {
+ DXManager.Draw(mi.MaskImage, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), Tint);
+ }
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public void DrawUp(int index, int x, int y)
+ {
+ if (x >= Settings.ScreenWidth)
+ return;
+
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+ y -= mi.Height;
+ if (y >= Settings.ScreenHeight)
+ return;
+ if (x + mi.Width < 0 || y + mi.Height < 0)
+ return;
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3(x, y, 0.0F), Color.White);
+
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+ public void DrawUpBlend(int index, Point point)
+ {
+ if (!CheckImage(index))
+ return;
+
+ MImage mi = _images[index];
+
+ point.Y -= mi.Height;
+
+
+ if (point.X >= Settings.ScreenWidth || point.Y >= Settings.ScreenHeight || point.X + mi.Width < 0 || point.Y + mi.Height < 0)
+ return;
+
+ bool oldBlend = DXManager.Blending;
+ DXManager.SetBlend(true, 1);
+
+ DXManager.Draw(mi.Image, new Rectangle(0, 0, mi.Width, mi.Height), new Vector3((float)point.X, (float)point.Y, 0.0F), Color.White);
+
+ DXManager.SetBlend(oldBlend);
+ mi.CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public bool VisiblePixel(int index, Point point, bool accuate)
+ {
+ if (!CheckImage(index))
+ return false;
+
+ if (accuate)
+ return _images[index].VisiblePixel(point);
+
+ int accuracy = 2;
+
+ for (int x = -accuracy; x <= accuracy; x++)
+ for (int y = -accuracy; y <= accuracy; y++)
+ if (_images[index].VisiblePixel(new Point(point.X + x, point.Y + y)))
+ return true;
+
+ return false;
+ }
+ }
+
+ public sealed class MImage
+ {
+ public short Width, Height, X, Y, ShadowX, ShadowY;
+ public byte Shadow;
+ public int Length;
+
+ public bool TextureValid;
+ public Texture Image;
+ //layer 2:
+ public short MaskWidth, MaskHeight, MaskX, MaskY;
+ public int MaskLength;
+
+ public Texture MaskImage;
+ public Boolean HasMask;
+
+ public long CleanTime;
+ public Size TrueSize;
+
+ public unsafe byte* Data;
+
+ public MImage(BinaryReader reader)
+ {
+ //read layer 1
+ Width = reader.ReadInt16();
+ Height = reader.ReadInt16();
+ X = reader.ReadInt16();
+ Y = reader.ReadInt16();
+ Length = reader.ReadInt32();
+ }
+
+ public unsafe void CreateTexture(BinaryReader reader)
+ {
+ int w = Width;// + (4 - Width % 4) % 4;
+ int h = Height;// + (4 - Height % 4) % 4;
+
+ Image = new Texture(DXManager.Device, w, h, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
+ DataRectangle stream = Image.LockRectangle(0, LockFlags.Discard);
+ Data = (byte*)stream.Data.DataPointer;
+
+ DecompressImage(reader.ReadBytes(Length), stream.Data);
+
+ stream.Data.Dispose();
+ Image.UnlockRectangle(0);
+
+ DXManager.TextureList.Add(this);
+ TextureValid = true;
+
+ CleanTime = CMain.Time + Settings.CleanDelay;
+ }
+
+ public unsafe void DisposeTexture()
+ {
+ DXManager.TextureList.Remove(this);
+
+ if (Image != null && !Image.Disposed)
+ {
+ Image.Dispose();
+ }
+
+ if (MaskImage != null && !MaskImage.Disposed)
+ {
+ MaskImage.Dispose();
+ }
+
+ TextureValid = false;
+ Image = null;
+ MaskImage = null;
+ Data = null;
+ }
+
+ public unsafe bool VisiblePixel(Point p)
+ {
+ if (p.X < 0 || p.Y < 0 || p.X >= Width || p.Y >= Height)
+ return false;
+
+ int w = Width;
+
+ bool result = false;
+ if (Data != null)
+ {
+ int x = p.X;
+ int y = p.Y;
+
+ int index = (y * (w << 2)) + (x << 2);
+
+ byte col = Data[index + 3];
+
+ if (col == 0) return false;
+ else return true;
+ }
+ return result;
+ }
+
+ public Size GetTrueSize()
+ {
+ if (TrueSize != Size.Empty) return TrueSize;
+
+ int l = 0, t = 0, r = Width, b = Height;
+
+ bool visible = false;
+ for (int x = 0; x < r; x++)
+ {
+ for (int y = 0; y < b; y++)
+ {
+ if (!VisiblePixel(new Point(x, y))) continue;
+
+ visible = true;
+ break;
+ }
+
+ if (!visible) continue;
+
+ l = x;
+ break;
+ }
+
+ visible = false;
+ for (int y = 0; y < b; y++)
+ {
+ for (int x = l; x < r; x++)
+ {
+ if (!VisiblePixel(new Point(x, y))) continue;
+
+ visible = true;
+ break;
+
+ }
+ if (!visible) continue;
+
+ t = y;
+ break;
+ }
+
+ visible = false;
+ for (int x = r - 1; x >= l; x--)
+ {
+ for (int y = 0; y < b; y++)
+ {
+ if (!VisiblePixel(new Point(x, y))) continue;
+
+ visible = true;
+ break;
+ }
+
+ if (!visible) continue;
+
+ r = x + 1;
+ break;
+ }
+
+ visible = false;
+ for (int y = b - 1; y >= t; y--)
+ {
+ for (int x = l; x < r; x++)
+ {
+ if (!VisiblePixel(new Point(x, y))) continue;
+
+ visible = true;
+ break;
+
+ }
+ if (!visible) continue;
+
+ b = y + 1;
+ break;
+ }
+
+ TrueSize = Rectangle.FromLTRB(l, t, r, b).Size;
+
+ return TrueSize;
+ }
+
+ private static byte[] DecompressImage(byte[] image)
+ {
+ using (GZipStream stream = new GZipStream(new MemoryStream(image), CompressionMode.Decompress))
+ {
+ const int size = 4096;
+ byte[] buffer = new byte[size];
+ using (MemoryStream memory = new MemoryStream())
+ {
+ int count = 0;
+ do
+ {
+ count = stream.Read(buffer, 0, size);
+ if (count > 0)
+ {
+ memory.Write(buffer, 0, count);
+ }
+ }
+ while (count > 0);
+ return memory.ToArray();
+ }
+ }
+ }
+
+ private static void DecompressImage(byte[] data, Stream destination)
+ {
+ using (var stream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress))
+ {
+ stream.CopyTo(destination);
+ }
+ }
+ }
+}
diff --git a/Client/MirNetwork/Network.cs b/Client/MirNetwork/Network.cs
new file mode 100644
index 0000000..57ff0a9
--- /dev/null
+++ b/Client/MirNetwork/Network.cs
@@ -0,0 +1,256 @@
+using System.Collections.Concurrent;
+using System.Net.Sockets;
+using Client.MirControls;
+using C = ClientPackets;
+
+
+namespace Client.MirNetwork
+{
+ static class Network
+ {
+ private static TcpClient _client;
+ public static int ConnectAttempt = 0;
+ public static int MaxAttempts = 20;
+ public static bool ErrorShown;
+ public static bool Connected;
+ public static long TimeOutTime, TimeConnected, RetryTime = CMain.Time + 5000;
+
+ private static ConcurrentQueue _receiveList;
+ private static ConcurrentQueue _sendList;
+
+ static byte[] _rawData = new byte[0];
+ static readonly byte[] _rawBytes = new byte[8 * 1024];
+
+ public static void Connect()
+ {
+ if (_client != null)
+ Disconnect();
+
+ if (ConnectAttempt >= MaxAttempts)
+ {
+ if (ErrorShown)
+ {
+ return;
+ }
+
+ ErrorShown = true;
+
+ MirMessageBox errorBox = new("Error Connecting to Server", MirMessageBoxButtons.Cancel);
+ errorBox.CancelButton.Click += (o, e) => Program.Form.Close();
+ errorBox.Label.Text = $"Maximum Connection Attempts Reached: {MaxAttempts}" +
+ $"{Environment.NewLine}Please try again later or check your connection settings.";
+ errorBox.Show();
+ return;
+ }
+
+ ConnectAttempt++;
+
+ try
+ {
+ _client = new TcpClient { NoDelay = true };
+ _client?.BeginConnect(Settings.IPAddress, Settings.Port, Connection, null);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ if (Settings.LogErrors) CMain.SaveError(ex.ToString());
+ Disconnect();
+ }
+ }
+
+ private static void Connection(IAsyncResult result)
+ {
+ try
+ {
+ _client?.EndConnect(result);
+
+ if ((_client != null &&
+ !_client.Connected) ||
+ _client == null)
+ {
+ Connect();
+ return;
+ }
+
+ _receiveList = new ConcurrentQueue();
+ _sendList = new ConcurrentQueue();
+ _rawData = new byte[0];
+
+ TimeOutTime = CMain.Time + Settings.TimeOut;
+ TimeConnected = CMain.Time;
+
+ BeginReceive();
+ }
+ catch (SocketException)
+ {
+ Thread.Sleep(100);
+ Connect();
+ }
+ catch (Exception ex)
+ {
+ if (Settings.LogErrors) CMain.SaveError(ex.ToString());
+ Disconnect();
+ }
+ }
+
+ private static void BeginReceive()
+ {
+ if (_client == null || !_client.Connected) return;
+
+ try
+ {
+ _client.Client.BeginReceive(_rawBytes, 0, _rawBytes.Length, SocketFlags.None, ReceiveData, _rawBytes);
+ }
+ catch
+ {
+ Disconnect();
+ }
+ }
+ private static void ReceiveData(IAsyncResult result)
+ {
+ if (_client == null || !_client.Connected) return;
+
+ int dataRead;
+
+ try
+ {
+ dataRead = _client.Client.EndReceive(result);
+ }
+ catch
+ {
+ Disconnect();
+ return;
+ }
+
+ if (dataRead == 0)
+ {
+ Disconnect();
+ }
+
+ byte[] rawBytes = result.AsyncState as byte[];
+
+ byte[] temp = _rawData;
+ _rawData = new byte[dataRead + temp.Length];
+ Buffer.BlockCopy(temp, 0, _rawData, 0, temp.Length);
+ Buffer.BlockCopy(rawBytes, 0, _rawData, temp.Length, dataRead);
+
+ Packet p;
+ List data = new List();
+
+ while ((p = Packet.ReceivePacket(_rawData, out _rawData)) != null)
+ {
+ data.AddRange(p.GetPacketBytes());
+ _receiveList.Enqueue(p);
+ }
+
+ CMain.BytesReceived += data.Count;
+
+ BeginReceive();
+ }
+
+ private static void BeginSend(List data)
+ {
+ if (_client == null || !_client.Connected || data.Count == 0) return;
+
+ try
+ {
+ _client.Client.BeginSend(data.ToArray(), 0, data.Count, SocketFlags.None, SendData, null);
+ }
+ catch
+ {
+ Disconnect();
+ }
+ }
+ private static void SendData(IAsyncResult result)
+ {
+ try
+ {
+ _client.Client.EndSend(result);
+ }
+ catch
+ { }
+ }
+
+ public static void Disconnect()
+ {
+ if (_client == null) return;
+
+ _client?.Close();
+
+ TimeConnected = 0;
+ Connected = false;
+ _sendList = null;
+ _client = null;
+
+ _receiveList = null;
+ }
+
+ public static void Process()
+ {
+ if (_client == null || !_client.Connected)
+ {
+ if (Connected)
+ {
+ while (_receiveList != null && !_receiveList.IsEmpty)
+ {
+ if (!_receiveList.TryDequeue(out Packet p) || p == null) continue;
+ if (!(p is ServerPackets.Disconnect) && !(p is ServerPackets.ClientVersion)) continue;
+
+ MirScene.ActiveScene.ProcessPacket(p);
+ _receiveList = null;
+ return;
+ }
+
+ MirMessageBox.Show("Lost connection with the server.", true);
+ Disconnect();
+ return;
+ }
+ else if (CMain.Time >= RetryTime)
+ {
+ RetryTime = CMain.Time + 5000;
+ Connect();
+ }
+ return;
+ }
+
+ if (!Connected && TimeConnected > 0 && CMain.Time > TimeConnected + 5000)
+ {
+ Disconnect();
+ Connect();
+ return;
+ }
+
+
+
+ while (_receiveList != null && !_receiveList.IsEmpty)
+ {
+ if (!_receiveList.TryDequeue(out Packet p) || p == null) continue;
+ MirScene.ActiveScene.ProcessPacket(p);
+ }
+
+
+ if (CMain.Time > TimeOutTime && _sendList != null && _sendList.IsEmpty)
+ _sendList.Enqueue(new C.KeepAlive());
+
+ if (_sendList == null || _sendList.IsEmpty) return;
+
+ TimeOutTime = CMain.Time + Settings.TimeOut;
+
+ List data = new List();
+ while (!_sendList.IsEmpty)
+ {
+ if (!_sendList.TryDequeue(out Packet p)) continue;
+ data.AddRange(p.GetPacketBytes());
+ }
+
+ CMain.BytesSent += data.Count;
+
+ BeginSend(data);
+ }
+
+ public static void Enqueue(Packet p)
+ {
+ if (_sendList != null && p != null)
+ _sendList.Enqueue(p);
+ }
+ }
+}
diff --git a/Client/MirObjects/Damage.cs b/Client/MirObjects/Damage.cs
new file mode 100644
index 0000000..5c39f3a
--- /dev/null
+++ b/Client/MirObjects/Damage.cs
@@ -0,0 +1,50 @@
+using Client.MirControls;
+
+namespace Client.MirObjects
+{
+ public class Damage
+ {
+ public string Text;
+ public Color Colour;
+ public int Distance;
+ public long ExpireTime;
+ public double Factor;
+ public int Offset;
+
+ public MirLabel DamageLabel;
+
+ public Damage(string text, int duration, Color colour, int distance = 50)
+ {
+ ExpireTime = (long)(CMain.Time + duration);
+ Text = text;
+ Distance = distance;
+ Factor = duration / this.Distance;
+ Colour = colour;
+ }
+
+ public void Draw(Point displayLocation)
+ {
+ long timeRemaining = ExpireTime - CMain.Time;
+
+ if (DamageLabel == null)
+ {
+ DamageLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = Colour,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = Text,
+ Font = new Font(Settings.FontName, 8F, FontStyle.Bold)
+ };
+ }
+
+ displayLocation.Offset((int)(15 - (Text.Length * 3)), (int)(((int)((double)timeRemaining / Factor)) - Distance) - 75 - Offset);
+
+ DamageLabel.Location = displayLocation;
+ DamageLabel.Draw();
+ }
+ }
+
+}
diff --git a/Client/MirObjects/Effect.cs b/Client/MirObjects/Effect.cs
new file mode 100644
index 0000000..514dde5
--- /dev/null
+++ b/Client/MirObjects/Effect.cs
@@ -0,0 +1,354 @@
+using Client.MirGraphics;
+using Client.MirScenes;
+using Client.MirSounds;
+
+namespace Client.MirObjects
+{
+ public class Effect
+ {
+ public MLibrary Library;
+
+ public int BaseIndex, Count, Duration;
+ public long Start;
+
+ public int CurrentFrame;
+ public long NextFrame;
+
+ public Point Source;
+ public MapObject Owner;
+
+ public int Light = 6;
+ public Color LightColour = Color.White;
+
+ public bool Blend = true;
+ public float Rate = 1F;
+ public Point DrawLocation;
+ public Point DrawOffset = Point.Empty;
+ public bool Repeat;
+ public long RepeatUntil;
+
+ public bool DrawBehind = false;
+
+ public long CurrentDelay;
+ public long Delay;
+
+ public event EventHandler Complete;
+ public event EventHandler Played;
+
+ public Effect(MLibrary library, int baseIndex, int count, int duration, MapObject owner, long starttime = 0, bool drawBehind = false)
+ {
+ Library = library;
+ BaseIndex = baseIndex;
+ Count = count == 0 ? 1 : count;
+ Duration = duration;
+ Start = starttime == 0 ? CMain.Time : starttime;
+
+ NextFrame = Start + (Duration / Count) * (CurrentFrame + 1);
+ Owner = owner;
+ Source = Owner.CurrentLocation;
+
+ DrawBehind = drawBehind;
+ }
+ public Effect(MLibrary library, int baseIndex, int count, int duration, Point source, long starttime = 0, bool drawBehind = false)
+ {
+ Library = library;
+ BaseIndex = baseIndex;
+ Count = count == 0 ? 1 : count;
+ Duration = duration;
+ Start = starttime == 0 ? CMain.Time : starttime;
+
+ NextFrame = Start + (Duration / Count) * (CurrentFrame + 1);
+ Source = source;
+
+ DrawBehind = drawBehind;
+ }
+
+ public void SetStart(long start)
+ {
+ Start = start;
+
+ NextFrame = Start + (Duration / Count) * (CurrentFrame + 1);
+ }
+
+ public virtual void Process()
+ {
+ if (CurrentFrame == 1)
+ {
+ if (Played != null)
+ Played(this, EventArgs.Empty);
+ }
+
+ if (CMain.Time <= NextFrame) return;
+
+ if (Owner != null && Owner.SkipFrames) CurrentFrame++;
+
+ if (++CurrentFrame >= Count)
+ {
+ if (Repeat && (RepeatUntil == 0 || CMain.Time < RepeatUntil))
+ {
+ CurrentFrame = 0;
+ Start = CMain.Time + Delay;
+ NextFrame = Start + (Duration / Count) * (CurrentFrame + 1);
+ }
+ else
+ Remove();
+ }
+ else NextFrame = Start + (Duration / Count) * (CurrentFrame + 1);
+
+ GameScene.Scene.MapControl.TextureValid = false;
+ }
+
+ public virtual void Remove()
+ {
+ if (Owner != null)
+ Owner.Effects.Remove(this);
+ else
+ MapControl.Effects.Remove(this);
+
+ if (Complete != null)
+ Complete(this, EventArgs.Empty);
+ }
+
+ public virtual void Draw()
+ {
+ if (CMain.Time < Start) return;
+
+ if (Owner != null)
+ {
+ DrawLocation = Owner.DrawLocation;
+ }
+ else
+ {
+ DrawLocation = new Point((Source.X - MapObject.User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth,
+ (Source.Y - MapObject.User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(DrawOffset);
+ DrawLocation.Offset(MapObject.User.OffSetMove);
+ }
+
+
+ if (Blend)
+ Library.DrawBlend(BaseIndex + CurrentFrame, DrawLocation, Color.White, true, Rate);
+ else
+ Library.Draw(BaseIndex + CurrentFrame, DrawLocation, Color.White, true);
+ }
+
+ public void Clear()
+ {
+ Complete = null;
+ Played = null;
+ }
+ }
+
+ public class Missile : Effect
+ {
+ public static List Missiles = new List();
+ public MapObject Target;
+ public Point Destination;
+ public int Interval, FrameCount, Skip;
+ public int Direction;
+ public bool Explode;
+
+
+ public Missile(MLibrary library, int baseIndex, int count, int duration, MapObject owner, Point target, bool direction16 = true)
+ : base(library, baseIndex, count, duration, owner)
+ {
+ Missiles.Add(this);
+ Source = Owner.CurrentLocation;
+ Destination = target;
+ Direction = direction16 ? MapControl.Direction16(Source, Destination) : (int)Functions.DirectionFromPoint(Source, Destination);
+ }
+
+ public Missile(MLibrary library, int baseIndex, int count, int duration, Point source, Point target)
+ : base(library, baseIndex, count, duration, source)
+ {
+ Missiles.Add(this);
+ Destination = target;
+
+ Direction = MapControl.Direction16(Source, Destination);
+
+
+ }
+
+ public override void Process()
+ {
+ if (CMain.Time < Start) return;
+
+ if (Target != null) Destination = Target.CurrentLocation;
+ else if (!Explode)
+ {
+ int dist = Functions.MaxDistance(Owner.CurrentLocation, Destination);
+
+ if (dist < Globals.DataRange)
+ Destination.Offset(Destination.X - Source.X, Destination.Y - Source.Y);
+ }
+
+ Duration = Functions.MaxDistance(Source, Destination) * 50;
+ Count = Duration / Interval;
+ if (Count == 0) Count = 1;
+
+ base.Process();
+ }
+ public override void Remove()
+ {
+ base.Remove();
+ Missiles.Remove(this);
+ }
+ public override void Draw()
+ {
+ if (CMain.Time < Start) return;
+
+
+ int index = BaseIndex + (CurrentFrame % FrameCount) + Direction * (Skip + FrameCount);
+
+ DrawLocation = new Point((Source.X - MapObject.User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth,
+ (Source.Y - MapObject.User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(MapObject.User.OffSetMove);
+
+ int x = (Destination.X - Source.X) * MapControl.CellWidth;
+ int y = (Destination.Y - Source.Y) * MapControl.CellHeight;
+
+
+ DrawLocation.Offset(x * CurrentFrame / Count, y * CurrentFrame / Count);
+
+ if (!Blend)
+ Library.Draw(index, DrawLocation, Color.White, true);
+ else
+ Library.DrawBlend(index, DrawLocation, Color.White, true, Rate);
+ }
+
+ }
+
+ public class SpecialEffect : Effect
+ {
+ public uint EffectType = 0;
+
+ public SpecialEffect(MLibrary library, int baseIndex, int count, int duration, MapObject owner, bool blend, bool drawBehind, uint type)
+ : base(library, baseIndex, count, duration, owner, 0, drawBehind)
+ {
+ Blend = blend;
+ DrawBehind = drawBehind;
+ EffectType = type;
+ Light = -1;
+ }
+
+ public override void Process()
+ {
+ base.Process();
+ }
+ }
+
+ public class BuffEffect : Effect
+ {
+ public BuffType BuffType;
+
+ public BuffEffect(MLibrary library, int baseIndex, int count, int duration, MapObject owner, bool blend, BuffType buffType)
+ : base(library, baseIndex, count, duration, owner, 0)
+ {
+ Repeat = true;
+ Blend = blend;
+ BuffType = buffType;
+ Light = -1;
+ }
+
+ public override void Process()
+ {
+ base.Process();
+ }
+ }
+
+ public class TrackableEffect : Effect
+ {
+ public static List effectlist = new List();
+ public string EffectName = "default";
+
+ public TrackableEffect(Effect baseEffect, string effName = "null")
+ : base(baseEffect.Library, baseEffect.BaseIndex, baseEffect.Count, baseEffect.Duration, baseEffect.Owner, baseEffect.Start)
+ {
+ Repeat = baseEffect.Repeat;
+ RepeatUntil = baseEffect.RepeatUntil;
+ Blend = baseEffect.Blend;
+
+ EffectName = effName;
+
+ effectlist.Add(this);
+ }
+
+ public static int GetOwnerEffectID(uint objectID, string effectName = "null")
+ {
+ for (int i = 0; i < effectlist.Count; i++)
+ {
+ if (effectlist[i].Owner.ObjectID != objectID) continue;
+ if (effectName != "null" && effectlist[i].EffectName != effectName) continue;
+ return i;
+ }
+ return -1;
+ }
+
+ public override void Process()
+ {
+ base.Process();
+
+ if (Owner == null) Remove();
+ else if (Owner.Dead) Remove();
+ }
+
+ public override void Remove()
+ {
+ base.Remove();
+ effectlist.Remove(this);
+ }
+
+ public void RemoveNoComplete()
+ {
+ if (Owner != null)
+ Owner.Effects.Remove(this);
+ else
+ MapControl.Effects.Remove(this);
+ }
+
+ }
+
+ public class LightEffect : Effect
+ {
+ public LightEffect(int duration, MapObject owner, long starttime = 0, int lightDistance = 6, Color? lightColour = null)
+ : base(null, 0, 0, duration, owner, starttime)
+ {
+ Light = lightDistance;
+ LightColour = lightColour == null ? Color.White : (Color)lightColour;
+ }
+
+ public LightEffect(int duration, Point source, long starttime = 0, int lightDistance = 6, Color? lightColour = null)
+ : base(null, 0, 0, duration, source, starttime)
+ {
+ Light = lightDistance;
+ LightColour = lightColour == null ? Color.White : (Color)lightColour;
+ }
+
+ public override void Process()
+ {
+ if (CMain.Time >= Start + Duration)
+ Remove();
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ }
+
+ public override void Draw()
+ {
+
+ if (CMain.Time < Start) return;
+
+
+ if (Owner != null)
+ {
+ DrawLocation = Owner.DrawLocation;
+ }
+ else
+ {
+ DrawLocation = new Point((Source.X - MapObject.User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth,
+ (Source.Y - MapObject.User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(MapObject.User.OffSetMove);
+ }
+ }
+ }
+
+}
diff --git a/Client/MirObjects/Frames.cs b/Client/MirObjects/Frames.cs
new file mode 100644
index 0000000..62bd2dd
--- /dev/null
+++ b/Client/MirObjects/Frames.cs
@@ -0,0 +1,106 @@
+namespace Client.MirObjects
+{
+ public class FrameSet : Dictionary
+ {
+ public static FrameSet Player;
+ public static FrameSet DefaultNPC, DefaultMonster, DungeonMonster1, DungeonMonster2, DungeonMonster3, DungeonMonster4, DungeonMonster5;
+
+ static FrameSet()
+ {
+ FrameSet frame;
+
+ Player = new FrameSet();
+
+ DefaultNPC = new FrameSet
+ {
+ { MirAction.Standing, new Frame(56, 1, 3, 450) }
+ };
+
+ DefaultMonster = new FrameSet
+ {
+ { MirAction.Standing, new Frame(16, 1, 3, 500) },
+ { MirAction.Walking, new Frame(16, 4, 0, 100) },
+ { MirAction.Attack1, new Frame(0, 2, 0, 100) }
+ };
+
+ DungeonMonster1 = new FrameSet
+ {
+ { MirAction.Standing, new Frame(0, 1, 0, 500) },
+ { MirAction.Walking, new Frame(10, 6, 4, 100) },
+ { MirAction.Attack1, new Frame(90, 6, 4, 100) }
+ };
+
+ DungeonMonster2 = new FrameSet
+ {
+ { MirAction.Standing, new Frame(48, 1, 5, 500) },
+ { MirAction.Walking, new Frame(48, 6, 0, 100) },
+ { MirAction.Attack1, new Frame(0, 6, 0, 100) }
+ };
+
+ DungeonMonster3 = new FrameSet
+ {
+ { MirAction.Standing, new Frame(0, 1, 0, 500) },
+ { MirAction.Walking, new Frame(10, 6, 4, 100) },
+ { MirAction.Attack1, new Frame(90, 4, 6, 100) }
+ };
+
+ DungeonMonster4 = new FrameSet
+ {
+ { MirAction.Standing, new Frame(10, 8, 2, 500) },
+ { MirAction.Walking, new Frame(10, 8, 2, 100) },
+ { MirAction.Attack1, new Frame(90, 8, 2, 100) }
+ };
+
+ DungeonMonster5 = new FrameSet
+ {
+ { MirAction.Standing, new Frame(10, 8, 2, 500) },
+ { MirAction.Walking, new Frame(10, 8, 2, 100) },
+ { MirAction.Attack1, new Frame(90, 6, 4, 100) }
+ };
+
+
+ #region Player
+ Player.Add(MirAction.Standing, new Frame(56, 1, 3, 500, 0, 8, 0, 250));
+ Player.Add(MirAction.Walking, new Frame(56, 4, 0, 100, 64, 6, 0, 100));
+ Player.Add(MirAction.Stance, new Frame(9, 1, 2, 1000, 160, 1, 0, 1000));
+ Player.Add(MirAction.Attack1, new Frame(8, 3, 0, 100, 168, 6, 0, 100));
+ Player.Add(MirAction.Spell, new Frame(8, 3, 0, 100, 328, 6, 0, 100));
+ Player.Add(MirAction.Harvest, new Frame(0, 1, 0, 300, 376, 2, 0, 300));
+ Player.Add(MirAction.Die, new Frame(88, 1, -1, 100, 416, 4, 0, 100));
+ Player.Add(MirAction.Dead, new Frame(88, 1, -1, 1000, 419, 1, 3, 1000));
+ Player.Add(MirAction.Revive, new Frame(56, 1, 3, 100, 416, 4, 0, 100) { Reverse = true });
+
+ #endregion
+ }
+ }
+
+ public class Frame
+ {
+ public int Start, Count, Skip, EffectStart, EffectCount, EffectSkip;
+ public int Interval, EffectInterval;
+ public bool Reverse, Blend;
+
+ public int OffSet
+ {
+ get { return Count + Skip; }
+ }
+
+ public int EffectOffSet
+ {
+ get { return EffectCount + EffectSkip; }
+ }
+
+ public Frame(int start, int count, int skip, int interval, int effectstart = 0, int effectcount = 0, int effectskip = 0, int effectinterval = 0)
+ {
+ Start = start;
+ Count = count;
+ Skip = skip;
+ Interval = interval;
+ EffectStart = effectstart;
+ EffectCount = effectcount;
+ EffectSkip = effectskip;
+ EffectInterval = effectinterval;
+ }
+ }
+
+}
diff --git a/Client/MirObjects/ItemObject.cs b/Client/MirObjects/ItemObject.cs
new file mode 100644
index 0000000..99828b3
--- /dev/null
+++ b/Client/MirObjects/ItemObject.cs
@@ -0,0 +1,143 @@
+using Client.MirGraphics;
+using Client.MirScenes;
+using S = ServerPackets;
+using System.Text.RegularExpressions;
+
+namespace Client.MirObjects
+{
+ public class ItemObject : MapObject
+ {
+ public override ObjectType Race{
+ get { return ObjectType.Item; }
+ }
+
+ public override bool Blocking
+ {
+ get { return false; }
+ }
+
+ public Size Size;
+
+
+ public ItemObject(uint objectID) : base(objectID)
+ {
+ }
+
+
+ public void Load(S.ObjectItem info)
+ {
+ Name = info.Name;
+ NameColour = info.NameColour;
+
+ BodyLibrary = Libraries.FloorItems;
+
+ CurrentLocation = info.Location;
+ MapLocation = info.Location;
+ GameScene.Scene.MapControl.AddObject(this);
+ DrawFrame = info.Image;
+
+ Size = BodyLibrary.GetTrueSize(DrawFrame);
+
+ DrawY = CurrentLocation.Y;
+
+ }
+ public void Load(S.ObjectGold info)
+ {
+ Name = string.Format("Gold ({0:###,###,###})", info.Gold);
+
+
+ BodyLibrary = Libraries.Prguse;
+
+ CurrentLocation = info.Location;
+ MapLocation = info.Location;
+ GameScene.Scene.MapControl.AddObject(this);
+
+ DrawFrame = 38;
+
+ Size = BodyLibrary.GetTrueSize(DrawFrame);
+
+ DrawY = CurrentLocation.Y;
+ }
+ public override void Draw()
+ {
+ if (BodyLibrary != null)
+ BodyLibrary.Draw(DrawFrame, DrawLocation, DrawColour);
+ }
+
+ public override void Process()
+ {
+ DrawLocation = new Point((CurrentLocation.X - User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth, (CurrentLocation.Y - User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset((MapControl.CellWidth - Size.Width) / 2, (MapControl.CellHeight - Size.Height) / 2);
+ DrawLocation.Offset(User.OffSetMove);
+ DrawLocation.Offset(GlobalDisplayLocationOffset);
+ FinalDrawLocation = DrawLocation;
+
+ DisplayRectangle = new Rectangle(DrawLocation, Size);
+ }
+ public override bool MouseOver(Point p)
+ {
+ return MapControl.MapLocation == CurrentLocation;
+ // return DisplayRectangle.Contains(p);
+ }
+
+ public override void DrawName()
+ {
+ CreateLabel(Color.Transparent, false, true);
+
+ if (NameLabel == null) return;
+ NameLabel.Location = new Point(
+ DisplayRectangle.X + (DisplayRectangle.Width - NameLabel.Size.Width) / 2,
+ DisplayRectangle.Y + (DisplayRectangle.Height - NameLabel.Size.Height) / 2 - 20);
+ NameLabel.Draw();
+ }
+
+ public override void DrawBehindEffects(bool effectsEnabled)
+ {
+ }
+
+ public override void DrawEffects(bool effectsEnabled)
+ {
+
+
+ }
+
+ public void DrawName(int y)
+ {
+ CreateLabel(Color.FromArgb(100, 0, 24, 48), true, false);
+
+ NameLabel.Location = new Point(
+ DisplayRectangle.X + (DisplayRectangle.Width - NameLabel.Size.Width) / 2,
+ DisplayRectangle.Y + y + (DisplayRectangle.Height - NameLabel.Size.Height) / 2 - 20);
+ NameLabel.Draw();
+ }
+
+ private void CreateLabel(Color backColour, bool border, bool outline)
+ {
+ NameLabel = null;
+
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != Name || LabelList[i].Border != border || LabelList[i].BackColour != backColour || LabelList[i].ForeColour != NameColour || LabelList[i].OutLine != outline) continue;
+ NameLabel = LabelList[i];
+ break;
+ }
+
+ if (NameLabel != null && !NameLabel.IsDisposed) return;
+
+ NameLabel = new MirControls.MirLabel
+ {
+ AutoSize = true,
+ BorderColour = Color.Black,
+ BackColour = backColour,
+ ForeColour = NameColour,
+ OutLine = outline,
+ Border = border,
+ Text = Regex.Replace(Name, @"\d+$", string.Empty),
+ };
+
+ LabelList.Add(NameLabel);
+ }
+
+
+ }
+}
diff --git a/Client/MirObjects/MapCode.cs b/Client/MirObjects/MapCode.cs
new file mode 100644
index 0000000..47a2997
--- /dev/null
+++ b/Client/MirObjects/MapCode.cs
@@ -0,0 +1,165 @@
+namespace Client.MirObjects
+{
+ public class CellInfo
+ {
+ public short BackIndex;
+ public int BackImage;
+ public short MiddleIndex;
+ public int MiddleImage;
+ public short FrontIndex;
+ public int FrontImage;
+
+ public byte DoorIndex;
+ public byte DoorOffset;
+
+ public byte FrontAnimationFrame;
+ public byte FrontAnimationTick;
+
+ public byte MiddleAnimationFrame;
+ public byte MiddleAnimationTick;
+
+ public short TileAnimationImage;
+ public short TileAnimationOffset;
+ public byte TileAnimationFrames;
+
+ public byte Light;
+ public byte Unknown;
+ public List CellObjects;
+
+ public void AddObject(MapObject ob)
+ {
+ if (CellObjects == null) CellObjects = new List();
+
+ CellObjects.Insert(0, ob);
+ Sort();
+ }
+ public void RemoveObject(MapObject ob)
+ {
+ if (CellObjects == null) return;
+
+ CellObjects.Remove(ob);
+
+ if (CellObjects.Count == 0) CellObjects = null;
+ else Sort();
+ }
+ public MapObject FindObject(uint ObjectID)
+ {
+ return CellObjects.Find(
+ delegate(MapObject mo)
+ {
+ return mo.ObjectID == ObjectID;
+ });
+ }
+ public void DrawObjects()
+ {
+ if (CellObjects == null) return;
+
+ for (int i = 0; i < CellObjects.Count; i++)
+ {
+ if (!CellObjects[i].Dead)
+ {
+ CellObjects[i].Draw();
+ continue;
+ }
+ }
+ }
+ public void DrawDeadObjects()
+ {
+ if (CellObjects == null) return;
+ for (int i = 0; i < CellObjects.Count; i++)
+ {
+ if (!CellObjects[i].Dead) continue;
+
+ CellObjects[i].Draw();
+ }
+ }
+
+ public void Sort()
+ {
+ CellObjects.Sort(delegate(MapObject ob1, MapObject ob2)
+ {
+ if (ob1.Race == ObjectType.Item && ob2.Race != ObjectType.Item)
+ return -1;
+ if (ob2.Race == ObjectType.Item && ob1.Race != ObjectType.Item)
+ return 1;
+ if (ob1.Race == ObjectType.Spell && ob2.Race != ObjectType.Spell)
+ return -1;
+ if (ob2.Race == ObjectType.Spell && ob1.Race != ObjectType.Spell)
+ return 1;
+
+ int i = ob2.Dead.CompareTo(ob1.Dead);
+ return i == 0 ? ob1.ObjectID.CompareTo(ob2.ObjectID) : i;
+ });
+ }
+ }
+
+ class MapReader
+ {
+ public int Width, Height;
+ public CellInfo[,] MapCells;
+ private string FileName;
+ private byte[] Bytes;
+
+ public MapReader(string FileName)
+ {
+ this.FileName = FileName;
+ initiate();
+ }
+
+ private void initiate()
+ {
+ if (File.Exists(FileName))
+ {
+ Bytes = File.ReadAllBytes(FileName);
+ }
+ else
+ {
+ Width = 1000;
+ Height = 1000;
+ MapCells = new CellInfo[Width, Height];
+
+ for (int x = 0; x < Width; x++)
+ for (int y = 0; y < Height; y++)
+ {
+ MapCells[x, y] = new CellInfo();
+ }
+ return;
+ }
+
+ LoadMap();
+ }
+
+ private void LoadMap()
+ {
+ try
+ {
+ int offset = 0;
+ Width = BitConverter.ToInt16(Bytes, offset);
+ offset += 2;
+ Height = BitConverter.ToInt16(Bytes, offset);
+ MapCells = new CellInfo[Width, Height];
+
+ offset = 56;
+
+ for (int x = 0; x < Width; x++)
+ for (int y = 0; y < Height; y++)
+ {
+ MapCells[x, y] = new CellInfo();
+ MapCells[x, y].MiddleIndex = 1;
+ MapCells[x, y].MiddleImage = (short)BitConverter.ToInt16(Bytes, offset);
+ offset += 2;
+ MapCells[x, y].FrontIndex = 2;
+ MapCells[x, y].FrontImage = (short)BitConverter.ToInt16(Bytes, offset);
+ offset += 2;
+ if ((MapCells[x, y].MiddleImage & 0x8000) != 0)
+ MapCells[x, y].BackImage = 0x20000000;
+ MapCells[x, y].MiddleImage = (MapCells[x, y].MiddleImage & 0x7FFF);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (Settings.LogErrors) CMain.SaveError(ex.ToString());
+ }
+ }
+ }
+}
diff --git a/Client/MirObjects/MapObject.cs b/Client/MirObjects/MapObject.cs
new file mode 100644
index 0000000..df4e826
--- /dev/null
+++ b/Client/MirObjects/MapObject.cs
@@ -0,0 +1,420 @@
+using Client.MirControls;
+using Client.MirGraphics;
+using Client.MirScenes;
+using Client.MirSounds;
+using Client.MirScenes.Dialogs;
+using SlimDX;
+
+namespace Client.MirObjects
+{
+ public abstract class MapObject
+ {
+ public static Font ChatFont = new Font(Settings.FontName, 10F);
+ public static List LabelList = new List();
+
+ public static UserObject User;
+ public static MapObject MouseObject, TargetObject, MagicObject;
+
+ private static uint mouseObjectID;
+ public static uint MouseObjectID
+ {
+ get { return mouseObjectID; }
+ set
+ {
+ if (mouseObjectID == value) return;
+ mouseObjectID = value;
+ MouseObject = MapControl.Objects.Find(x => x.ObjectID == value);
+ }
+ }
+
+ private static uint targetObjectID;
+ public static uint TargetObjectID
+ {
+ get { return targetObjectID; }
+ set
+ {
+ if (targetObjectID == value) return;
+ targetObjectID = value;
+ TargetObject = MapControl.Objects.Find(x => x.ObjectID == value);
+ }
+ }
+
+ private static uint magicObjectID;
+ public static uint MagicObjectID
+ {
+ get { return magicObjectID; }
+ set
+ {
+ if (magicObjectID == value) return;
+ magicObjectID = value;
+ MagicObject = MapControl.Objects.Find(x => x.ObjectID == value);
+ }
+ }
+
+ public abstract ObjectType Race { get; }
+ public abstract bool Blocking { get; }
+
+ public uint ObjectID;
+ public string Name = string.Empty;
+ public Point CurrentLocation, MapLocation;
+ public MirDirection Direction;
+ public bool Dead, Hidden;
+ public PoisonType Poison;
+ public long DeadTime;
+ public byte AI;
+
+ public bool Blend = true;
+
+ public long BlindTime;
+ public byte BlindCount;
+
+ private byte percentHealth;
+ public virtual byte PercentHealth
+ {
+ get { return percentHealth; }
+ set
+ {
+ if (percentHealth == value) return;
+
+ percentHealth = value;
+ }
+ }
+ public long HealthTime;
+
+ private byte percentMana;
+ public virtual byte PercentMana
+ {
+ get { return percentMana; }
+ set
+ {
+ if (percentMana == value) return;
+
+ percentMana = value;
+ }
+ }
+
+ public List ActionFeed = new List();
+ public QueuedAction NextAction
+ {
+ get { return ActionFeed.Count > 0 ? ActionFeed[0] : null; }
+ }
+
+ public List Effects = new List();
+ public List Buffs = new List();
+
+ public MLibrary BodyLibrary;
+ public Color DrawColour = Color.White, NameColour = Color.White, LightColour = Color.White;
+ public MirLabel NameLabel, ChatLabel, GuildLabel;
+ public long ChatTime;
+ public int DrawFrame, DrawWingFrame;
+ public Point DrawLocation, Movement, FinalDrawLocation, OffSetMove;
+ public Rectangle DisplayRectangle;
+ public int Light, DrawY;
+ public long NextMotion, NextMotion2;
+ public MirAction CurrentAction;
+ public byte CurrentActionLevel;
+ public bool SkipFrames;
+ public FrameLoop FrameLoop = null;
+
+ //Sound
+ public int StruckWeapon;
+
+ public MirLabel TempLabel;
+
+ public static List DamageLabelList = new List();
+ public List Damages = new List();
+
+ protected Point GlobalDisplayLocationOffset
+ {
+ get { return new Point(0, 0); }
+ }
+
+ protected MapObject() { }
+
+ protected MapObject(uint objectID)
+ {
+ ObjectID = objectID;
+
+ for (int i = MapControl.Objects.Count - 1; i >= 0; i--)
+ {
+ MapObject ob = MapControl.Objects[i];
+ if (ob.ObjectID != ObjectID) continue;
+ ob.Remove();
+ }
+
+ MapControl.Objects.Add(this);
+ }
+ public void Remove()
+ {
+ if (MouseObject == this) MouseObjectID = 0;
+ if (TargetObject == this) TargetObjectID = 0;
+ if (MagicObject == this) MagicObjectID = 0;
+
+ if (this == User.NextMagicObject)
+ User.ClearMagic();
+
+ MapControl.Objects.Remove(this);
+ GameScene.Scene.MapControl.RemoveObject(this);
+
+ if (ObjectID != GameScene.NPCID) return;
+
+ GameScene.NPCID = 0;
+ GameScene.Scene.NPCDialog.Hide();
+ }
+
+ public abstract void Process();
+ public abstract void Draw();
+ public abstract bool MouseOver(Point p);
+
+ public void AddBuffEffect(BuffType type)
+ {
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (!(Effects[i] is BuffEffect)) continue;
+ if (((BuffEffect)(Effects[i])).BuffType == type) return;
+ }
+
+ PlayerObject ob = null;
+
+ if (Race == ObjectType.Player)
+ {
+ ob = (PlayerObject)this;
+ }
+ }
+ public void RemoveBuffEffect(BuffType type)
+ {
+ PlayerObject ob = null;
+
+ if (Race == ObjectType.Player)
+ {
+ ob = (PlayerObject)this;
+ }
+
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (!(Effects[i] is BuffEffect)) continue;
+ if (((BuffEffect)(Effects[i])).BuffType != type) continue;
+ Effects[i].Repeat = false;
+ }
+ }
+
+ public Color ApplyDrawColour()
+ {
+ Color drawColour = DrawColour;
+ if (drawColour == Color.Gray)
+ {
+ drawColour = Color.White;
+ DXManager.SetGrayscale(true);
+ }
+ return drawColour;
+ }
+
+ public virtual Missile CreateProjectile(int baseIndex, MLibrary library, bool blend, int count, int interval, int skip, int lightDistance = 6, bool direction16 = true, Color? lightColour = null, uint targetID = 0)
+ {
+ return null;
+ }
+
+ public void Chat(string text)
+ {
+ if (ChatLabel != null && !ChatLabel.IsDisposed)
+ {
+ ChatLabel.Dispose();
+ ChatLabel = null;
+ }
+
+ const int chatWidth = 200;
+ List chat = new List();
+
+ int index = 0;
+ for (int i = 1; i < text.Length; i++)
+ if (TextRenderer.MeasureText(CMain.Graphics, text.Substring(index, i - index), ChatFont).Width > chatWidth)
+ {
+ chat.Add(text.Substring(index, i - index - 1));
+ index = i - 1;
+ }
+ chat.Add(text.Substring(index, text.Length - index));
+
+ text = chat[0];
+ for (int i = 1; i < chat.Count; i++)
+ text += string.Format("\n{0}", chat[i]);
+
+ ChatLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = Color.White,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ DrawFormat = TextFormatFlags.HorizontalCenter,
+ Text = text,
+ };
+ ChatTime = CMain.Time + 5000;
+ }
+ public virtual void DrawChat()
+ {
+ if (ChatLabel == null || ChatLabel.IsDisposed) return;
+
+ if (CMain.Time > ChatTime)
+ {
+ ChatLabel.Dispose();
+ ChatLabel = null;
+ return;
+ }
+
+ ChatLabel.ForeColour = Dead ? Color.Gray : Color.White;
+ ChatLabel.Location = new Point(DisplayRectangle.X + (48 - ChatLabel.Size.Width) / 2, DisplayRectangle.Y - (60 + ChatLabel.Size.Height) - (Dead ? 35 : 0));
+ ChatLabel.Draw();
+ }
+
+ public virtual void CreateLabel()
+ {
+ NameLabel = null;
+
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != Name || LabelList[i].ForeColour != NameColour) continue;
+ NameLabel = LabelList[i];
+ break;
+ }
+
+
+ if (NameLabel != null && !NameLabel.IsDisposed) return;
+
+ NameLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = NameColour,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = Name,
+ };
+ NameLabel.Disposing += (o, e) => LabelList.Remove(NameLabel);
+ LabelList.Add(NameLabel);
+
+
+
+ }
+ public virtual void DrawName()
+ {
+ CreateLabel();
+
+ if (NameLabel == null) return;
+
+ NameLabel.Text = Name;
+ NameLabel.Location = new Point(DisplayRectangle.X + (50 - NameLabel.Size.Width) / 2, DisplayRectangle.Y - (32 - NameLabel.Size.Height / 2) + (Dead ? 35 : 8)); //was 48 -
+ NameLabel.Draw();
+ }
+ public virtual void DrawBlend()
+ {
+ DXManager.SetBlend(true, 0.3F); //0.8
+ Draw();
+ DXManager.SetBlend(false);
+ }
+ public void DrawDamages()
+ {
+ for (int i = Damages.Count - 1; i >= 0; i--)
+ {
+ Damage info = Damages[i];
+ if (CMain.Time > info.ExpireTime)
+ {
+ if (info.DamageLabel != null)
+ {
+ info.DamageLabel.Dispose();
+ }
+
+ Damages.RemoveAt(i);
+ }
+ else
+ {
+ info.Draw(DisplayRectangle.Location);
+ }
+ }
+ }
+ public virtual bool ShouldDrawHealth()
+ {
+ return false;
+ }
+ public void DrawHealth()
+ {
+ string name = Name;
+ if (Name.Contains("(")) name = Name.Substring(Name.IndexOf("(") + 1, Name.Length - Name.IndexOf("(") - 2);
+
+ if (Dead) return;
+ if (Race != ObjectType.Player && Race != ObjectType.Monster) return;
+
+ if (CMain.Time >= HealthTime)
+ {
+ if (!ShouldDrawHealth()) return;
+ }
+
+ Libraries.Prguse.Draw(151, DisplayRectangle.X + 8, DisplayRectangle.Y - 80);
+ int index = this == User ? 152 : 183;
+ Libraries.Prguse.Draw(index, new Rectangle(0, 0, (int)(40 * PercentHealth / 100F), 4), new Point(DisplayRectangle.X + 8, DisplayRectangle.Y - 80), Color.White, false);
+ }
+
+ public virtual void PlayStruckSound()
+ {
+ }
+
+ public void DrawPoison()
+ {
+ byte poisoncount = 0;
+ if (Poison != PoisonType.None)
+ {
+ if (Poison.HasFlag(PoisonType.Green))
+ {
+ DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
+ DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Green);
+ poisoncount++;
+ }
+ if (Poison.HasFlag(PoisonType.Red))
+ {
+ DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
+ DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Red);
+ poisoncount++;
+ }
+ if (Poison.HasFlag(PoisonType.Slow))
+ {
+ DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
+ DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Purple);
+ poisoncount++;
+ }
+ if (Poison.HasFlag(PoisonType.Frozen))
+ {
+ DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
+ DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Blue);
+ poisoncount++;
+ }
+ }
+ }
+
+ public abstract void DrawBehindEffects(bool effectsEnabled);
+
+ public abstract void DrawEffects(bool effectsEnabled);
+
+ protected void LoopFrame(int start, int frameCount, int frameInterval, int duration)
+ {
+ if (FrameLoop == null)
+ {
+ FrameLoop = new FrameLoop
+ {
+ Start = start,
+ End = start + frameCount - 1,
+ Loops = (duration / (frameInterval * frameCount)) - 1 //Remove 1 count as we've already done a loop before this is checked
+ };
+ }
+ }
+ }
+
+ public class FrameLoop
+ {
+ public MirAction Action { get; set; }
+ public int Start { get; set; }
+ public int End { get; set; }
+ public int Loops { get; set; }
+
+ public int CurrentCount { get; set; }
+ }
+
+}
diff --git a/Client/MirObjects/MonsterObject.cs b/Client/MirObjects/MonsterObject.cs
new file mode 100644
index 0000000..56be7cb
--- /dev/null
+++ b/Client/MirObjects/MonsterObject.cs
@@ -0,0 +1,923 @@
+using Client.MirGraphics;
+using Client.MirScenes;
+using Client.MirSounds;
+using S = ServerPackets;
+using Client.MirControls;
+
+namespace Client.MirObjects
+{
+ class MonsterObject : MapObject
+ {
+ public override ObjectType Race
+ {
+ get { return ObjectType.Monster; }
+ }
+
+ public override bool Blocking
+ {
+ get { return AI == 64 || (AI == 81 && Direction == (MirDirection)6) ? false : !Dead; }
+ }
+
+ public Point ManualLocationOffset
+ {
+ get
+ {
+ switch (BaseImage)
+ {
+ default:
+ return new Point(0, 0);
+ }
+ }
+ }
+
+ public Monster BaseImage;
+ public byte Effect;
+ public bool Skeleton;
+
+ public FrameSet Frames = new FrameSet();
+ public Frame Frame;
+ public int FrameIndex, FrameInterval, EffectFrameIndex;
+
+ public uint TargetID;
+ public Point TargetPoint;
+
+ public bool Stoned;
+ public byte Stage;
+ public int BaseSound;
+
+ public long ShockTime;
+ public bool BindingShotCenter;
+
+ public Color OldNameColor;
+
+ public SpellEffect CurrentEffect;
+
+ public MonsterObject(uint objectID) : base(objectID) { }
+
+ public void Load(S.ObjectMonster info, bool update = false)
+ {
+ Name = info.Name;
+ NameColour = info.NameColour;
+ BaseImage = info.Image;
+
+ OldNameColor = NameColour;
+
+ CurrentLocation = info.Location;
+ MapLocation = info.Location;
+ if (!update) GameScene.Scene.MapControl.AddObject(this);
+
+ Effect = info.Effect;
+ AI = info.AI;
+ Light = info.Light;
+
+ Direction = info.Direction;
+ Dead = info.Dead;
+ Poison = info.Poison;
+ Skeleton = info.Skeleton;
+ Hidden = info.Hidden;
+ ShockTime = CMain.Time + info.ShockTime;
+ BindingShotCenter = info.BindingShotCenter;
+
+ Buffs = info.Buffs;
+
+ Stage = info.ExtraByte;
+
+ BodyLibrary = (int)BaseImage < 1000 ? Libraries.Monster : Libraries.DungeonMonster;
+
+ if (Dead)
+ ActionFeed.Add(new QueuedAction { Action = MirAction.Dead, Direction = Direction, Location = CurrentLocation });
+
+ BaseSound = (ushort)BaseImage * 10;
+
+ switch (BaseImage)
+ {
+ case Monster.BoneElite:
+ case Monster.Wooma1:
+ case Monster.GiantLizard:
+ case Monster.Goblin:
+ Frames = FrameSet.DungeonMonster2;
+ break;
+ case Monster.Centipede:
+ case Monster.Centipede2:
+ case Monster.Reptile:
+ case Monster.Spider:
+ Frames = FrameSet.DungeonMonster3;
+ break;
+ case Monster.DragonBat:
+ Frames = FrameSet.DungeonMonster4;
+ break;
+ case Monster.Wooma2:
+ case Monster.Minotaur:
+ Frames = FrameSet.DungeonMonster5;
+ break;
+ case Monster.Zombie:
+ case Monster.GiantFrog:
+ Frames = FrameSet.DungeonMonster1;
+ break;
+ default:
+ Frames = FrameSet.DefaultMonster;
+ break;
+ }
+
+ switch (BaseImage)
+ {
+ case Monster.Wolf:
+ case Monster.Wolf2:
+ BaseSound = SoundList.Wolf;
+ break;
+ case Monster.Deer:
+ BaseSound = SoundList.Deer;
+ break;
+ case Monster.Bull:
+ BaseSound = SoundList.Bull;
+ break;
+ case Monster.Doe:
+ BaseSound = SoundList.Doe;
+ break;
+ case Monster.Hen:
+ BaseSound = SoundList.Hen;
+ break;
+ case Monster.Tiger:
+ BaseSound = SoundList.Tiger;
+ break;
+ }
+
+ SetAction();
+ SetCurrentEffects();
+
+ if (CurrentAction == MirAction.Standing)
+ {
+ PlayAppearSound();
+
+ if (Frame != null)
+ {
+ FrameIndex = CMain.Random.Next(Frame.Count);
+ }
+ }
+
+ NextMotion -= NextMotion % 100;
+
+ ProcessBuffs();
+ }
+
+ public void ProcessBuffs()
+ {
+ for (int i = 0; i < Buffs.Count; i++)
+ {
+ AddBuffEffect(Buffs[i]);
+ }
+ }
+
+ public override bool ShouldDrawHealth()
+ {
+ string name = string.Empty;
+ if (Name.Contains("(")) name = Name.Substring(Name.IndexOf("(") + 1, Name.Length - Name.IndexOf("(") - 2);
+
+ return Name.EndsWith(string.Format("({0})", User.Name)) || MirScenes.Dialogs.GroupDialog.GroupList.Contains(name);
+ }
+
+ public override void Process()
+ {
+ bool update = CMain.Time >= NextMotion || GameScene.CanMove;
+ SkipFrames = ActionFeed.Count > 1;
+
+ ProcessFrames();
+
+ if (Frame == null)
+ {
+ DrawFrame = 0;
+ DrawWingFrame = 0;
+ }
+ else
+ {
+ int BaseIndex = 0;
+ if ((int)BaseImage < 1000)
+ BaseIndex = (int)BaseImage * 50;
+ else //Dungeon Monsters
+ BaseIndex = ((int)BaseImage - 1000) * 180;
+
+ DrawFrame = BaseIndex + (Frame.Start + (Frame.OffSet * (byte)Direction) + FrameIndex);
+ DrawWingFrame = BaseIndex + (Frame.EffectStart + (Frame.EffectOffSet * (byte)Direction) + EffectFrameIndex);
+ }
+
+
+ #region Moving OffSet
+
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ case MirAction.DashL:
+ case MirAction.DashR:
+ if (Frame == null)
+ {
+ OffSetMove = Point.Empty;
+ Movement = CurrentLocation;
+ break;
+ }
+ int i = 1;
+
+ Movement = Functions.PointMove(CurrentLocation, Direction, CurrentAction == MirAction.Pushed ? 0 : -i);
+
+ int count = Frame.Count;
+ int index = FrameIndex;
+
+ if (CurrentAction == MirAction.DashR || CurrentAction == MirAction.DashL)
+ {
+ count = 3;
+ index %= 3;
+ }
+
+ switch (Direction)
+ {
+ case MirDirection.Up:
+ OffSetMove = new Point(0, (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.UpRight:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Right:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), 0);
+ break;
+ case MirDirection.DownRight:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Down:
+ OffSetMove = new Point(0, (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.DownLeft:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Left:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), 0);
+ break;
+ case MirDirection.UpLeft:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ }
+
+ OffSetMove = new Point(OffSetMove.X % 2 + OffSetMove.X, OffSetMove.Y % 2 + OffSetMove.Y);
+ break;
+ default:
+ OffSetMove = Point.Empty;
+ Movement = CurrentLocation;
+ break;
+ }
+
+ #endregion
+
+ DrawY = Movement.Y > CurrentLocation.Y ? Movement.Y : CurrentLocation.Y;
+
+ DrawLocation = new Point((Movement.X - User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth, (Movement.Y - User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(-OffSetMove.X, -OffSetMove.Y);
+ DrawLocation.Offset(User.OffSetMove);
+ DrawLocation = DrawLocation.Add(ManualLocationOffset);
+ DrawLocation.Offset(GlobalDisplayLocationOffset);
+
+ if (BodyLibrary != null && update)
+ {
+ FinalDrawLocation = DrawLocation.Add(BodyLibrary.GetOffSet(DrawFrame));
+ DisplayRectangle = new Rectangle(DrawLocation, BodyLibrary.GetTrueSize(DrawFrame));
+ }
+
+ for (int i = 0; i < Effects.Count; i++)
+ Effects[i].Process();
+
+ Color colour = DrawColour;
+ if (Poison == PoisonType.None)
+ DrawColour = Color.White;
+ if (Poison.HasFlag(PoisonType.Green))
+ DrawColour = Color.Green;
+ if (Poison.HasFlag(PoisonType.Red))
+ DrawColour = Color.Red;
+ if (Poison.HasFlag(PoisonType.Slow))
+ DrawColour = Color.Purple;
+ if (Poison.HasFlag(PoisonType.Stun))
+ DrawColour = Color.Yellow;
+ if (Poison.HasFlag(PoisonType.Frozen))
+ DrawColour = Color.Blue;
+ if (Poison.HasFlag(PoisonType.Paralysis))
+ DrawColour = Color.Gray;
+ if (colour != DrawColour) GameScene.Scene.MapControl.TextureValid = false;
+ }
+
+ public bool SetAction()
+ {
+ if (NextAction != null && !GameScene.CanMove)
+ {
+ switch (NextAction.Action)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ return false;
+ }
+ }
+
+ if (ActionFeed.Count == 0)
+ {
+ CurrentAction = MirAction.Standing;
+ Frames.TryGetValue(CurrentAction, out Frame);
+
+ if (MapLocation != CurrentLocation)
+ {
+ GameScene.Scene.MapControl.RemoveObject(this);
+ MapLocation = CurrentLocation;
+ GameScene.Scene.MapControl.AddObject(this);
+ }
+
+ FrameIndex = 0;
+
+ if (Frame == null) return false;
+
+ FrameInterval = Frame.Interval;
+ }
+ else
+ {
+ QueuedAction action = ActionFeed[0];
+ ActionFeed.RemoveAt(0);
+
+ CurrentActionLevel = 0;
+ CurrentAction = action.Action;
+ CurrentLocation = action.Location;
+ Direction = action.Direction;
+
+ Point temp;
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ int i = 1;
+ temp = Functions.PointMove(CurrentLocation, Direction, CurrentAction == MirAction.Pushed ? 0 : -i);
+ break;
+ default:
+ temp = CurrentLocation;
+ break;
+ }
+
+ temp = new Point(action.Location.X, temp.Y > CurrentLocation.Y ? temp.Y : CurrentLocation.Y);
+
+ if (MapLocation != temp)
+ {
+ GameScene.Scene.MapControl.RemoveObject(this);
+ MapLocation = temp;
+ GameScene.Scene.MapControl.AddObject(this);
+ }
+
+
+ switch (CurrentAction)
+ {
+ case MirAction.Pushed:
+ Frames.TryGetValue(MirAction.Walking, out Frame);
+ break;
+ case MirAction.AttackRange1:
+ if (!Frames.TryGetValue(CurrentAction, out Frame))
+ Frames.TryGetValue(MirAction.Attack1, out Frame);
+ break;
+ case MirAction.Hide:
+ switch (BaseImage)
+ {
+ default:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+ }
+ break;
+ case MirAction.Dead:
+ switch (BaseImage)
+ {
+ default:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+ }
+ break;
+ default:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+
+ }
+
+ FrameIndex = 0;
+
+ if (Frame == null) return false;
+
+ FrameInterval = Frame.Interval;
+
+ Point front = Functions.PointMove(CurrentLocation, Direction, 1);
+
+ switch (CurrentAction)
+ {
+ case MirAction.Show:
+ PlayPopupSound();
+ break;
+ case MirAction.Pushed:
+ FrameIndex = Frame.Count - 1;
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.Walking:
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.Attack1:
+ PlayAttackSound();
+ CurrentActionLevel = (byte)action.Params[1];
+ break;
+ case MirAction.AttackRange1:
+ PlayRangeSound();
+ TargetID = (uint)action.Params[0];
+ CurrentActionLevel = (byte)action.Params[4];
+ break;
+ case MirAction.Die:
+ PlayDieSound();
+ break;
+ case MirAction.Dead:
+ GameScene.Scene.Redraw();
+ GameScene.Scene.MapControl.SortObject(this);
+ if (MouseObject == this) MouseObjectID = 0;
+ if (TargetObject == this) TargetObjectID = 0;
+ if (MagicObject == this) MagicObjectID = 0;
+
+ for (int i = 0; i < Effects.Count; i++)
+ Effects[i].Remove();
+
+ DeadTime = CMain.Time;
+
+ break;
+ }
+
+ }
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ NextMotion = CMain.Time + FrameInterval;
+
+ return true;
+ }
+
+ public void SetCurrentEffects()
+ {
+ //BindingShot
+ if (BindingShotCenter && ShockTime > CMain.Time)
+ {
+ int effectid = TrackableEffect.GetOwnerEffectID(ObjectID);
+ if (effectid >= 0)
+ TrackableEffect.effectlist[effectid].RemoveNoComplete();
+ }
+ else if (BindingShotCenter && ShockTime <= CMain.Time)
+ {
+ int effectid = TrackableEffect.GetOwnerEffectID(ObjectID);
+ if (effectid >= 0)
+ TrackableEffect.effectlist[effectid].Remove();
+
+ //SoundManager.PlaySound(20000 + 130 * 10 + 6);//sound M130-6
+ //Effects.Add(new TrackableEffect(new Effect(Libraries.ArcherMagic, 8, 8, 700, this)));
+
+ ShockTime = 0;
+ BindingShotCenter = false;
+ }
+
+ }
+
+
+ private void ProcessFrames()
+ {
+ if (Frame == null) return;
+
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ switch (FrameIndex)
+ {
+ case 1:
+ PlayWalkSound(true);
+ break;
+ case 4:
+ PlayWalkSound(false);
+ break;
+ }
+ }
+ break;
+ case MirAction.Pushed:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ FrameIndex -= 2;
+
+ if (FrameIndex < 0)
+ {
+ FrameIndex = 0;
+ SetAction();
+ }
+ break;
+ case MirAction.Show:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.Hide:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.Standing:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.Attack1:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ Point front = Functions.PointMove(CurrentLocation, Direction, 1);
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ switch (FrameIndex)
+ {
+ case 3:
+ {
+ PlaySwingSound();
+ break;
+ }
+ }
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.AttackRange1:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ if (FrameIndex == 2) PlaySwingSound();
+ MapObject ob = null;
+ Missile missile;
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+
+ case MirAction.Die:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ ActionFeed.Clear();
+ ActionFeed.Add(new QueuedAction { Action = MirAction.Dead, Direction = Direction, Location = CurrentLocation });
+ SetAction();
+ }
+ else
+ {
+ switch (FrameIndex)
+ {
+ case 4:
+ PlayDeadSound();
+ break;
+ }
+
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.Revive:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ ActionFeed.Clear();
+ ActionFeed.Add(new QueuedAction { Action = MirAction.Standing, Direction = Direction, Location = CurrentLocation });
+ SetAction();
+ }
+ else
+ {
+ if (FrameIndex == 3)
+ PlayReviveSound();
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+ case MirAction.Dead:
+ break;
+
+ }
+
+ if ((CurrentAction == MirAction.Standing) && NextAction != null)
+ SetAction();
+ else if (CurrentAction == MirAction.Dead && NextAction != null && (NextAction.Action == MirAction.Revive))
+ SetAction();
+ }
+
+ public int UpdateFrame()
+ {
+ if (Frame == null) return 0;
+
+ if (FrameLoop != null)
+ {
+ if (FrameLoop.CurrentCount > FrameLoop.Loops)
+ {
+ FrameLoop = null;
+ }
+ else if (FrameIndex >= FrameLoop.End)
+ {
+ FrameIndex = FrameLoop.Start - 1;
+ FrameLoop.CurrentCount++;
+ }
+ }
+
+ if (Frame.Reverse) return Math.Abs(--FrameIndex);
+
+ return ++FrameIndex;
+ }
+
+ public override Missile CreateProjectile(int baseIndex, MLibrary library, bool blend, int count, int interval, int skip, int lightDistance = 6, bool direction16 = true, Color? lightColour = null, uint targetID = 0)
+ {
+ if (targetID == 0)
+ {
+ targetID = TargetID;
+ }
+
+ MapObject ob = MapControl.GetObject(targetID);
+
+ var targetPoint = TargetPoint;
+
+ if (ob != null) targetPoint = ob.CurrentLocation;
+
+ int duration = Functions.MaxDistance(CurrentLocation, targetPoint) * 50;
+
+ Missile missile = new Missile(library, baseIndex, duration / interval, duration, this, targetPoint, direction16)
+ {
+ Target = ob,
+ Interval = interval,
+ FrameCount = count,
+ Blend = blend,
+ Skip = skip,
+ Light = lightDistance,
+ LightColour = lightColour == null ? Color.White : (Color)lightColour
+ };
+
+ Effects.Add(missile);
+
+ return missile;
+ }
+
+ private void PlaySummonSound()
+ {
+ }
+ private void PlayWalkSound(bool left = true)
+ {
+ if (left)
+ {
+ }
+ else
+ {
+ }
+ }
+ public void PlayAppearSound()
+ {
+ SoundManager.PlaySound(BaseSound);
+ }
+ public void PlayPopupSound()
+ {
+ SoundManager.PlaySound(BaseSound);
+ }
+
+ public void PlayRunSound()
+ {
+ }
+
+ public void PlayJumpSound()
+ {
+ }
+
+ public void PlayDashSound()
+ {
+ }
+
+ public override void PlayStruckSound()
+ {
+ switch (StruckWeapon)
+ {
+ default:
+ SoundManager.PlaySound(SoundList.StruckBodySword);
+ break;
+ case -1:
+ SoundManager.PlaySound(SoundList.StruckBodyFist);
+ break;
+ }
+ }
+
+ public void PlayAttackSound()
+ {
+ }
+
+ public void PlaySwingSound()
+ {
+ }
+ public void PlayDieSound()
+ {
+ }
+
+ public void PlayDeadSound()
+ {
+ }
+ public void PlayReviveSound()
+ {
+ }
+ public void PlayRangeSound()
+ {
+ }
+ public override void Draw()
+ {
+ DrawBehindEffects(Settings.Effect);
+
+ float oldOpacity = DXManager.Opacity;
+ if (Hidden && !DXManager.Blending) DXManager.SetOpacity(0.5F);
+
+ if (BodyLibrary == null || Frame == null) return;
+
+ bool oldGrayScale = DXManager.GrayScale;
+ Color drawColour = ApplyDrawColour();
+
+ if (!DXManager.Blending && Frame.Blend)
+ BodyLibrary.DrawBlend(DrawFrame, DrawLocation, drawColour, true);
+ else
+ BodyLibrary.Draw(DrawFrame, DrawLocation, drawColour, true);
+
+ DXManager.SetGrayscale(oldGrayScale);
+ DXManager.SetOpacity(oldOpacity);
+ }
+
+
+ public override bool MouseOver(Point p)
+ {
+ return MapControl.MapLocation == CurrentLocation || BodyLibrary != null && BodyLibrary.VisiblePixel(DrawFrame, p.Subtract(FinalDrawLocation), false);
+ }
+
+ public override void DrawBehindEffects(bool effectsEnabled)
+ {
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (!Effects[i].DrawBehind) continue;
+ Effects[i].Draw();
+ }
+ }
+
+ public override void DrawEffects(bool effectsEnabled)
+ {
+ if (!effectsEnabled) return;
+
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (Effects[i].DrawBehind) continue;
+ Effects[i].Draw();
+ }
+ }
+
+ public override void DrawName()
+ {
+ if (!Name.Contains("_"))
+ {
+ base.DrawName();
+ return;
+ }
+
+ string[] splitName = Name.Split('_');
+
+ //IntelligentCreature
+ int yOffset = 0;
+
+ for (int s = 0; s < splitName.Count(); s++)
+ {
+ CreateMonsterLabel(splitName[s], s);
+
+ TempLabel.Text = splitName[s];
+ TempLabel.Location = new Point(DisplayRectangle.X + (48 - TempLabel.Size.Width) / 2, DisplayRectangle.Y - (32 - TempLabel.Size.Height / 2) + (Dead ? 35 : 8) - (((splitName.Count() - 1) * 10) / 2) + (s * 12) + yOffset);
+ TempLabel.Draw();
+ }
+ }
+
+ public void CreateMonsterLabel(string word, int wordOrder)
+ {
+ TempLabel = null;
+
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != word) continue;
+ TempLabel = LabelList[i];
+ break;
+ }
+
+ if (TempLabel != null && !TempLabel.IsDisposed && NameColour == OldNameColor) return;
+
+ OldNameColor = NameColour;
+
+ TempLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = NameColour,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = word,
+ };
+
+ TempLabel.Disposing += (o, e) => LabelList.Remove(TempLabel);
+ LabelList.Add(TempLabel);
+ }
+
+ public override void DrawChat()
+ {
+ if (ChatLabel == null || ChatLabel.IsDisposed) return;
+
+ if (CMain.Time > ChatTime)
+ {
+ ChatLabel.Dispose();
+ ChatLabel = null;
+ return;
+ }
+
+ int yOffset = 0;
+
+ ChatLabel.ForeColour = Dead ? Color.Gray : Color.White;
+ ChatLabel.Location = new Point(DisplayRectangle.X + (48 - ChatLabel.Size.Width) / 2, DisplayRectangle.Y - (60 + ChatLabel.Size.Height) - (Dead ? 35 : 0) + yOffset);
+ ChatLabel.Draw();
+ }
+ }
+}
diff --git a/Client/MirObjects/NPCObject.cs b/Client/MirObjects/NPCObject.cs
new file mode 100644
index 0000000..5b2597d
--- /dev/null
+++ b/Client/MirObjects/NPCObject.cs
@@ -0,0 +1,443 @@
+using Client.MirControls;
+using Client.MirGraphics;
+using Client.MirScenes;
+using S = ServerPackets;
+
+namespace Client.MirObjects
+{
+ public class NPCObject : MapObject
+ {
+ public override ObjectType Race
+ {
+ get { return ObjectType.Merchant; }
+ }
+ public override bool Blocking
+ {
+ get { return true; }
+ }
+
+ public FrameSet Frames;
+ public Frame Frame;
+
+ public MLibrary HairLibrary;
+
+ public long QuestTime;
+ public int BaseIndex, FrameIndex, FrameInterval, EffectFrameIndex, EffectFrameInterval, QuestIndex;
+
+ public ushort Image;
+ public MirGender Gender;
+ public byte Hair;
+ public Color Colour = Color.White;
+
+ public QuestIcon QuestIcon = QuestIcon.None;
+
+ private bool _canChangeDir = true;
+
+ public bool CanChangeDir
+ {
+ get { return _canChangeDir; }
+ set
+ {
+ _canChangeDir = value;
+ if (value == false) Direction = MirDirection.Down;
+ }
+ }
+
+ public List Quests;
+
+
+ public NPCObject(uint objectID) : base(objectID)
+ {
+ }
+
+ public void Load(S.ObjectNPC info)
+ {
+ Name = info.Name;
+ NameColour = info.NameColour;
+ CurrentLocation = info.Location;
+ Direction = info.Direction;
+ Movement = info.Location;
+ MapLocation = info.Location;
+ GameScene.Scene.MapControl.AddObject(this);
+
+ Quests = GameScene.QuestInfoList.Where(c => c.NPCIndex == ObjectID).ToList();
+
+ Image = info.Image;
+ Gender = info.Gender;
+ Hair = info.Hair;
+ Colour = info.Colour;
+
+ LoadLibrary();
+
+ Frames = FrameSet.DefaultNPC;
+
+ Light = 10;
+ BaseIndex = 0;
+
+ SetAction(true);
+ }
+
+ public void LoadLibrary()
+ {
+ BodyLibrary = Libraries.Body;
+ HairLibrary = Libraries.Head;
+ }
+
+ public override void Process()
+ {
+ bool update = CMain.Time >= NextMotion || GameScene.CanMove;
+
+ ProcessFrames();
+
+ if (update)
+ {
+ UpdateBestQuestIcon();
+ }
+
+ if (Frame == null)
+ {
+ DrawFrame = 0;
+ DrawWingFrame = 0;
+ }
+ else
+ {
+ DrawFrame = Frame.Start + (Frame.OffSet * (byte)Direction) + FrameIndex;
+ DrawWingFrame = Frame.EffectStart + (Frame.EffectOffSet * (byte)Direction) + EffectFrameIndex;
+ }
+
+ DrawY = CurrentLocation.Y;
+
+ DrawLocation = new Point((Movement.X - User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth, (Movement.Y - User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(User.OffSetMove);
+ DrawLocation.Offset(GlobalDisplayLocationOffset);
+
+ if (BodyLibrary != null)
+ FinalDrawLocation = DrawLocation.Add(BodyLibrary.GetOffSet(DrawFrame));
+
+ if (BodyLibrary != null && update)
+ {
+ FinalDrawLocation = DrawLocation.Add(BodyLibrary.GetOffSet(DrawFrame));
+ DisplayRectangle = new Rectangle(DrawLocation, BodyLibrary.GetTrueSize(DrawFrame));
+ }
+
+ for (int i = 0; i < Effects.Count; i++)
+ Effects[i].Process();
+
+ Color colour = DrawColour;
+
+ switch (Poison)
+ {
+ case PoisonType.None:
+ DrawColour = Color.White;
+ break;
+ case PoisonType.Green:
+ DrawColour = Color.Green;
+ break;
+ case PoisonType.Red:
+ DrawColour = Color.Red;
+ break;
+ case PoisonType.Slow:
+ DrawColour = Color.Purple;
+ break;
+ case PoisonType.Stun:
+ DrawColour = Color.Yellow;
+ break;
+ case PoisonType.Frozen:
+ DrawColour = Color.Blue;
+ break;
+ case PoisonType.Paralysis:
+ DrawColour = Color.Gray;
+ break;
+ }
+
+
+ if (colour != DrawColour) GameScene.Scene.MapControl.TextureValid = false;
+
+
+ if (CMain.Time > QuestTime)
+ {
+ QuestTime = CMain.Time + 500;
+ if (++QuestIndex > 1) QuestIndex = 0;
+ }
+ }
+ public virtual void ProcessFrames()
+ {
+ if (Frame == null) return;
+
+ switch (CurrentAction)
+ {
+ case MirAction.Standing:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+
+ if(EffectFrameInterval > 0)
+ if (CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+
+ }
+
+ }
+ public int UpdateFrame()
+ {
+ if (Frame == null) return 0;
+
+ if (Frame.Reverse) return Math.Abs(--FrameIndex);
+
+ return ++FrameIndex;
+ }
+
+ public int UpdateFrame2()
+ {
+ if (Frame == null) return 0;
+
+ if (Frame.Reverse) return Math.Abs(--EffectFrameIndex);
+
+ return ++EffectFrameIndex;
+ }
+
+ public virtual void SetAction(bool randomStartFrame = false)
+ {
+ if (ActionFeed.Count == 0)
+ {
+ CurrentAction = MirAction.Standing;
+ Frames.TryGetValue(CurrentAction, out Frame);
+
+ if (randomStartFrame)
+ {
+ var frameIndex = new Random().Next(Frame.Count);
+
+ FrameIndex = frameIndex;
+ EffectFrameIndex = Math.Min(Frame.EffectCount, frameIndex);
+ }
+ else
+ {
+ FrameIndex = 0;
+ EffectFrameIndex = 0;
+ }
+
+ if (MapLocation != CurrentLocation)
+ {
+ GameScene.Scene.MapControl.RemoveObject(this);
+ MapLocation = CurrentLocation;
+ GameScene.Scene.MapControl.AddObject(this);
+ }
+
+ if (Frame == null) return;
+
+ FrameInterval = Frame.Interval;
+ EffectFrameInterval = Frame.EffectInterval;
+ }
+ else
+ {
+ QueuedAction action = ActionFeed[0];
+ ActionFeed.RemoveAt(0);
+
+ CurrentAction = action.Action;
+ CurrentLocation = action.Location;
+
+ FrameIndex = 0;
+ EffectFrameIndex = 0;
+
+ if (Frame == null) return;
+
+ FrameInterval = Frame.Interval;
+ EffectFrameInterval = Frame.EffectInterval;
+ }
+
+ NextMotion = CMain.Time + FrameInterval;
+ NextMotion2 = CMain.Time + EffectFrameInterval;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ }
+ public override void Draw()
+ {
+ if (BodyLibrary == null) return;
+
+ BodyLibrary.DrawTinted(240 * Image + 120 * (byte)Gender + DrawFrame, DrawLocation, DrawColour, Colour, true);
+ HairLibrary.DrawTinted(240 * Hair + 120 * (byte)Gender + DrawFrame, DrawLocation, DrawColour, Colour, true);
+
+ if (QuestIcon == QuestIcon.None) return;
+
+ var offSet = BodyLibrary.GetOffSet(BaseIndex);
+ var size = BodyLibrary.GetSize(BaseIndex);
+
+ int imageIndex = 981 + ((int)QuestIcon * 2) + QuestIndex;
+
+ Libraries.Prguse.Draw(imageIndex, DrawLocation.Add(offSet).Add(size.Width / 2 - 28, -40), Color.White, false);
+ }
+
+ public override bool MouseOver(Point p)
+ {
+ return MapControl.MapLocation == CurrentLocation || BodyLibrary != null && BodyLibrary.VisiblePixel(DrawFrame, p.Subtract(FinalDrawLocation), false);
+ }
+
+ public override void DrawBehindEffects(bool effectsEnabled)
+ {
+ }
+
+ public override void DrawEffects(bool effectsEnabled)
+ {
+ if (!effectsEnabled) return;
+
+ if (BodyLibrary == null) return;
+
+ if (DrawWingFrame > 0)
+ BodyLibrary.DrawBlend(DrawWingFrame, DrawLocation, Color.White, true);
+ }
+
+ public override void DrawName()
+ {
+ if (!Name.Contains("_"))
+ {
+ base.DrawName();
+ return;
+ }
+
+ string[] splitName = Name.Split('_');
+
+ for (int s = 0; s < splitName.Count(); s++)
+ {
+ CreateNPCLabel(splitName[s], s);
+
+ TempLabel.Text = splitName[s];
+ TempLabel.Location = new Point(DisplayRectangle.X + (48 - TempLabel.Size.Width) / 2, DisplayRectangle.Y - (32 - TempLabel.Size.Height / 2) + (Dead ? 35 : 8) - (((splitName.Count() - 1) * 10) / 2) + (s * 12));
+ TempLabel.Draw();
+ }
+ }
+
+ public void CreateNPCLabel(string word, int wordOrder)
+ {
+ TempLabel = null;
+
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != word || LabelList[i].ForeColour != (wordOrder == 0 ? NameColour : Color.White)) continue;
+ TempLabel = LabelList[i];
+ break;
+ }
+
+ if (TempLabel != null && !TempLabel.IsDisposed) return;
+
+ TempLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = wordOrder == 0 ? NameColour : Color.White,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = word,
+ };
+
+ TempLabel.Disposing += (o, e) => LabelList.Remove(TempLabel);
+ LabelList.Add(TempLabel);
+ }
+
+
+ //Quests
+
+ #region Quest System
+ public void UpdateBestQuestIcon()
+ {
+ ClientQuestProgress quests = GetAvailableQuests(true).FirstOrDefault();
+ QuestIcon bestIcon = QuestIcon.None;
+
+ if (quests != null)
+ {
+ bestIcon = quests.Icon;
+ }
+
+ QuestIcon = bestIcon;
+ }
+
+ public List GetAvailableQuests(bool returnFirst = false)
+ {
+ List quests = new List();
+
+ foreach (ClientQuestProgress q in User.CurrentQuests.Where(q => !User.CompletedQuests.Contains(q.QuestInfo.Index)))
+ {
+ if (q.QuestInfo.FinishNPCIndex == ObjectID)
+ {
+ quests.Add(q);
+ }
+ else if (q.QuestInfo.NPCIndex == ObjectID && q.QuestInfo.SameFinishNPC)
+ {
+ quests.Add(q);
+
+ if (returnFirst) return quests;
+ }
+ }
+
+ foreach (ClientQuestProgress quest in (
+ from q in Quests
+ where !quests.Exists(p => p.QuestInfo.Index == q.Index)
+ where CanAccept(q)
+ where !User.CompletedQuests.Contains(q.Index)
+ select q).Select(
+ q => User.CurrentQuests.Exists(p => p.QuestInfo.Index == q.Index) ?
+ new ClientQuestProgress { QuestInfo = q, Taken = true, Completed = false } :
+ new ClientQuestProgress { QuestInfo = q }))
+ {
+ quests.Add(quest);
+
+ if (returnFirst) return quests;
+ }
+
+ return quests;
+ }
+
+ public bool CanAccept(ClientQuestInfo quest)
+ {
+ if (quest.MinLevelNeeded > User.Level || quest.MaxLevelNeeded < User.Level)
+ return false;
+
+ if (!quest.ClassNeeded.HasFlag(RequiredClass.None))
+ {
+ switch (User.Class)
+ {
+ case MirClass.Warrior:
+ if (!quest.ClassNeeded.HasFlag(RequiredClass.Warrior))
+ return false;
+ break;
+ case MirClass.Wizard:
+ if (!quest.ClassNeeded.HasFlag(RequiredClass.Wizard))
+ return false;
+ break;
+ case MirClass.Taoist:
+ if (!quest.ClassNeeded.HasFlag(RequiredClass.Taoist))
+ return false;
+ break;
+ }
+ }
+
+ //check against active quest list
+ return quest.QuestNeeded <= 0 || User.CompletedQuests.Contains(quest.QuestNeeded);
+ }
+
+ #endregion
+ }
+}
diff --git a/Client/MirObjects/PathFinder.cs b/Client/MirObjects/PathFinder.cs
new file mode 100644
index 0000000..f8fdff3
--- /dev/null
+++ b/Client/MirObjects/PathFinder.cs
@@ -0,0 +1,297 @@
+using Client.MirScenes;
+
+namespace Client.MirObjects
+{
+ public class Heap where T : IHeapItem
+ {
+ private T[] items;
+ private int currentItemCount;
+
+ public Heap(int maxHeapSize)
+ {
+ items = new T[maxHeapSize];
+ }
+
+ public void Add(T item)
+ {
+ item.HeapIndex = currentItemCount;
+ items[currentItemCount] = item;
+ SortUp(item);
+ currentItemCount++;
+ }
+
+ public T RemoveFirst()
+ {
+ T firstItem = items[0];
+ currentItemCount--;
+
+ items[0] = items[currentItemCount];
+ items[0].HeapIndex = 0;
+
+ SortDown(items[0]);
+
+ return firstItem;
+ }
+
+ public void UpdateItem(T item)
+ {
+ SortUp(item);
+ }
+
+ public int Count { get { return currentItemCount; } }
+
+ public bool Contains(T item)
+ {
+ return Equals(items[item.HeapIndex], item);
+ }
+
+ private void SortDown(T item)
+ {
+ while (true)
+ {
+ int childIndexLeft = (item.HeapIndex * 2) + 1;
+ int childIndexRight = (item.HeapIndex * 2) + 2;
+ int swapIndex = 0;
+
+ if (childIndexLeft < currentItemCount)
+ {
+ swapIndex = childIndexLeft;
+ if (childIndexRight < currentItemCount)
+ {
+ if (items[childIndexLeft].CompareTo(items[childIndexRight]) < 0)
+ {
+ swapIndex = childIndexRight;
+ }
+ }
+
+ if (item.CompareTo(items[swapIndex]) < 0)
+ {
+ Swap(item, items[swapIndex]);
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+ private void SortUp(T item)
+ {
+ int parentIndex = (item.HeapIndex - 1) / 2;
+
+ while (true)
+ {
+ T parentItem = items[parentIndex];
+ if (item.CompareTo(parentItem) > 0)
+ {
+ Swap(item, parentItem);
+ }
+ else
+ break;
+
+ parentIndex = (item.HeapIndex - 1) / 2;
+ }
+ }
+
+ private void Swap(T itemA, T itemB)
+ {
+ items[itemA.HeapIndex] = itemB;
+ items[itemB.HeapIndex] = itemA;
+
+ int itemAIndex = itemA.HeapIndex;
+ itemA.HeapIndex = itemB.HeapIndex;
+ itemB.HeapIndex = itemAIndex;
+ }
+ }
+
+ public interface IHeapItem : IComparable
+ {
+ int HeapIndex
+ {
+ get; set;
+ }
+ }
+
+ public class Node : IHeapItem
+ {
+ public bool Walkable
+ {
+ get { return Map.EmptyCell(Location); }
+ }
+
+ public MapControl Map;
+ public Point Location;
+ public Node Parent;
+
+ public int GCost, HCost;
+
+ public int FCost
+ {
+ get { return GCost + HCost; }
+ }
+
+ private int _heapIndex;
+
+ public int HeapIndex
+ {
+ get { return _heapIndex; }
+ set { _heapIndex = value; }
+ }
+
+ public int CompareTo(Node nodeToCompare)
+ {
+ int compare = FCost.CompareTo(nodeToCompare.FCost);
+ if (compare == 0)
+ {
+ compare = HCost.CompareTo(nodeToCompare.HCost);
+ }
+ return -compare;
+ }
+
+ public Node(MapControl map, int x, int y)
+ {
+ Map = map;
+ Location = new Point(x, y);
+ }
+ }
+
+ public class PathFinder
+ {
+ private Node[,] Grid;
+
+ public MapControl Map;
+
+ public int MaxSize
+ {
+ get { return Map.Width * Map.Height; }
+ }
+
+ public PathFinder(MapControl map)
+ {
+ Map = map;
+
+ CreateGrid();
+ }
+
+ private void CreateGrid()
+ {
+ Grid = new Node[Map.Width, Map.Height];
+
+ for (int x = 0; x < Map.Width; x++)
+ {
+ for (int y = 0; y < Map.Height; y++)
+ {
+ Grid[x, y] = new Node(Map, x, y);
+ }
+ }
+ }
+
+ public List FindPath(Point start, Point target, int MaxNodes = 0)
+ {
+ Node startNode = GetNode(start);
+ Node targetNode = GetNode(target);
+
+ Heap openSet = new Heap(MaxSize);
+ HashSet closedSet = new HashSet();
+
+ openSet.Add(startNode);
+
+ while (openSet.Count > 0)
+ {
+ Node currentNode = openSet.RemoveFirst();
+
+ closedSet.Add(currentNode);
+
+ if (currentNode == targetNode)
+ {
+ var path = RetracePath(startNode, targetNode);
+ return MaxNodes == 0 || path.Count < MaxNodes ? path : null;
+ }
+
+ foreach (Node neighbor in GetNeighbours(currentNode))
+ {
+ if (!neighbor.Walkable || closedSet.Contains(neighbor))
+ continue;
+
+ int newMovementCostToNeighbor = currentNode.GCost + GetDistance(currentNode, neighbor);
+ if (newMovementCostToNeighbor < neighbor.GCost || !openSet.Contains(neighbor))
+ {
+ neighbor.GCost = newMovementCostToNeighbor;
+ neighbor.HCost = GetDistance(neighbor, targetNode);
+ neighbor.Parent = currentNode;
+
+ if (!openSet.Contains(neighbor))
+ openSet.Add(neighbor);
+ else
+ {
+ openSet.UpdateItem(neighbor);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public List RetracePath(Node startNode, Node endNode)
+ {
+ List path = new List();
+ Node currentNode = endNode;
+
+ while (currentNode != startNode)
+ {
+ path.Add(currentNode);
+ currentNode = currentNode.Parent;
+ }
+
+ path.Add(startNode);
+ path.Reverse();
+
+ return path;
+ }
+
+ private int GetDistance(Node nodeA, Node nodeB)
+ {
+ int distX = Math.Abs(nodeA.Location.X - nodeB.Location.X);
+ int distY = Math.Abs(nodeA.Location.Y - nodeB.Location.Y);
+
+ if (distX > distY)
+ return 14 * distY + (10 * (distX - distY));
+
+ return 14 * distX + (10 * (distY - distX));
+ }
+
+ private Node GetNode(Point location)
+ {
+ return Grid[location.X, location.Y];
+ }
+
+ private List GetNeighbours(Node node)
+ {
+ List neighbours = new List();
+ for (int x = -1; x <= 1; x++)
+ {
+ for (int y = -1; y <= 1; y++)
+ {
+ if (x == 0 && y == 0) continue;
+
+ int checkX = node.Location.X + x;
+ int checkY = node.Location.Y + y;
+
+ if (checkX >= 0 && checkX < Grid.GetLength(0) && checkY >= 0 && checkY < Grid.GetLength(1))
+ {
+ neighbours.Add(Grid[checkX, checkY]);
+ }
+ }
+ }
+
+ return neighbours;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Client/MirObjects/PlayerObject.cs b/Client/MirObjects/PlayerObject.cs
new file mode 100644
index 0000000..dbd23d2
--- /dev/null
+++ b/Client/MirObjects/PlayerObject.cs
@@ -0,0 +1,1934 @@
+using Client.MirGraphics;
+using Client.MirNetwork;
+using Client.MirScenes;
+using Client.MirSounds;
+using Client.MirControls;
+using S = ServerPackets;
+using C = ClientPackets;
+using Client.MirScenes.Dialogs;
+using System.Reflection;
+
+namespace Client.MirObjects
+{
+ public class PlayerObject : MapObject
+ {
+ public override ObjectType Race
+ {
+ get { return ObjectType.Player; }
+ }
+
+ public override bool Blocking
+ {
+ get { return !Dead; }
+ }
+
+ public MirGender Gender;
+ public MirClass Class;
+ public byte Hair;
+ public ushort Level;
+
+ public MLibrary WeaponLibrary1, HairLibrary, WingLibrary;
+ public int Armour, Weapon, ArmourOffSet, HairOffSet, WeaponOffSet, WingOffset;
+
+ public int DieSound, FlinchSound, AttackSound;
+
+
+ public FrameSet Frames;
+ public Frame Frame, WingFrame;
+ public int FrameIndex, FrameInterval, EffectFrameIndex, EffectFrameInterval, SlowFrameIndex;
+ public byte SkipFrameUpdate = 0;
+
+ public Spell Spell;
+ public byte SpellLevel;
+ public bool Cast;
+ public uint TargetID;
+ public List SecondaryTargetIDs;
+ public Point TargetPoint;
+
+ public bool MagicShield;
+ public Effect ShieldEffect;
+
+ public byte WingEffect;
+ private short StanceDelay = 2500;
+
+ public SpellEffect CurrentEffect;
+
+ public long StanceTime;
+
+ public string GuildName;
+ public string GuildRankName;
+
+ public LevelEffects LevelEffects;
+
+ public PlayerObject() { }
+ public PlayerObject(uint objectID) : base(objectID)
+ {
+ Frames = FrameSet.Player;
+ }
+
+ public void Load(S.ObjectPlayer info)
+ {
+ Name = info.Name;
+ NameColour = info.NameColour;
+ GuildName = info.GuildName;
+ GuildRankName = info.GuildRankName;
+ Class = info.Class;
+ Gender = info.Gender;
+ Level = info.Level;
+
+ CurrentLocation = info.Location;
+ MapLocation = info.Location;
+ GameScene.Scene.MapControl.AddObject(this);
+
+ Direction = info.Direction;
+ Hair = info.Hair;
+
+ Weapon = info.Weapon;
+ Armour = info.Armour;
+ Light = info.Light;
+
+ Poison = info.Poison;
+
+ Dead = info.Dead;
+ Hidden = info.Hidden;
+
+ WingEffect = info.WingEffect;
+ CurrentEffect = info.Effect;
+
+ SetLibraries();
+
+ if (Dead) ActionFeed.Add(new QueuedAction { Action = MirAction.Dead, Direction = Direction, Location = CurrentLocation });
+ if (info.Extra) Effects.Add(new Effect(Libraries.Magic2, 670, 10, 800, this));
+
+ Buffs = info.Buffs;
+
+ LevelEffects = info.LevelEffects;
+
+ ProcessBuffs();
+
+ SetAction();
+
+ SetEffects();
+ }
+ public void Update(S.PlayerUpdate info)
+ {
+ Weapon = info.Weapon;
+ Armour = info.Armour;
+ Light = info.Light;
+ WingEffect = info.WingEffect;
+
+ SetLibraries();
+ SetEffects();
+ }
+
+ public override bool ShouldDrawHealth()
+ {
+ if (GroupDialog.GroupList.Contains(Name) || this == User)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void ProcessBuffs()
+ {
+ for (int i = 0; i < Buffs.Count; i++)
+ {
+ AddBuffEffect(Buffs[i]);
+ }
+ }
+
+
+ public virtual void SetLibraries()
+ {
+ #region Armours
+ BodyLibrary = Libraries.Body;
+ HairLibrary = Libraries.Head;
+ #endregion
+
+ #region Weapons
+
+ if (Weapon >= 0)
+ {
+ WeaponLibrary1 = Libraries.Weapon;
+ }
+ else
+ {
+ WeaponLibrary1 = null;
+ }
+
+ #endregion
+
+ #region WingEffects
+ if (WingEffect > 0 && WingEffect < 100)
+ {
+ WingLibrary = null;
+ }
+ #endregion
+
+ #region Offsets
+ ArmourOffSet = 240 * Armour + 120 * (int)Gender;
+ HairOffSet = 240 * Hair + 120 * (int)Gender;
+ WeaponOffSet = 240 * Weapon + 120 * (int)Gender;
+ WingOffset = 240 * WingEffect + 120 * (int)Gender;
+ #endregion
+ }
+
+ public virtual void SetEffects()
+ {
+ for (int i = Effects.Count - 1; i >= 0; i--)
+ {
+ if (Effects[i] is SpecialEffect) Effects[i].Remove();
+ }
+
+ if (CurrentEffect == SpellEffect.MagicShieldUp)
+ {
+ if (ShieldEffect != null)
+ {
+ ShieldEffect.Clear();
+ ShieldEffect.Remove();
+ }
+
+ MagicShield = true;
+ Effects.Add(ShieldEffect = new Effect(Libraries.Magic, 3890, 3, 600, this) { Repeat = true });
+ }
+
+ if (WingEffect >= 100)
+ {
+ switch(WingEffect)
+ {
+ case 100: //Oma King Robe effect
+ Effects.Add(new SpecialEffect(Libraries.Effect, 352, 33, 3600, this, true, false, 0) { Repeat = true });
+ break;
+ }
+ }
+
+ long delay = 5000;
+
+ if (LevelEffects == LevelEffects.None) return;
+
+ //Effects dependant on flags
+ if (LevelEffects.HasFlag(LevelEffects.BlueDragon))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Effect, 1210, 20, 3200, this, true, true, 1) { Repeat = true });
+ SpecialEffect effect = new SpecialEffect(Libraries.Effect, 1240, 32, 4200, this, true, false, 1) { Repeat = true };
+ effect.SetStart(CMain.Time);
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.RedDragon))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Effect, 990, 20, 3200, this, true, true, 1) { Repeat = true });
+ SpecialEffect effect = new SpecialEffect(Libraries.Effect, 1020, 32, 4200, this, true, false, 1) { Repeat = true, Delay = delay };
+ effect.SetStart(CMain.Time + delay);
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.Mist))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Effect, 296, 32, 3600, this, true, false, 1) { Repeat = true });
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.Rebirth1))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 6800, 20, 3600, this, true, false, 1) { Repeat = true });
+
+
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.Rebirth2))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 6870, 19, 3600, this, true, true, 1) { Repeat = true });
+ SpecialEffect effect = new SpecialEffect(Libraries.Magic2, 6840, 22, 3600, this, true, false, 1) { Repeat = true, Delay = delay };
+ effect.SetStart(CMain.Time + delay);
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.Rebirth3))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 6906, 19, 3600, this, true, false, 1) { Repeat = true, Delay = delay });
+ SpecialEffect effect = new SpecialEffect(Libraries.Magic2, 6930, 29, 3600, this, true, true, 1) { Repeat = true };
+
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.NewBlue))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 7040, 31, 3600, this, true, false, 1) { Repeat = true, Delay = delay });
+ SpecialEffect effect = new SpecialEffect(Libraries.Magic2,7080, 24, 3600, this, true, true, 1) { Repeat = true };
+
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.YellowDragon))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 7120, 31, 3600, this, true, false, 1) { Repeat = true, Delay = delay });
+ SpecialEffect effect = new SpecialEffect(Libraries.Magic2, 7160, 24, 3600, this, true, true, 1) { Repeat = true };
+
+ Effects.Add(effect);
+ }
+
+ if (LevelEffects.HasFlag(LevelEffects.Phoenix))
+ {
+ Effects.Add(new SpecialEffect(Libraries.Magic2, 6970, 26, 3600, this, true, false, 1) { Repeat = true, Delay = delay });
+ SpecialEffect effect = new SpecialEffect(Libraries.Magic2, 7000, 21, 3600, this, true, true, 1) { Repeat = true };
+
+ Effects.Add(effect);
+ }
+ }
+
+ public override void Process()
+ {
+ bool update = CMain.Time >= NextMotion || GameScene.CanMove;
+
+ SkipFrames = this != User && ActionFeed.Count > 1;
+
+ ProcessFrames();
+
+ if (Frame == null)
+ {
+ DrawFrame = 0;
+ DrawWingFrame = 0;
+ }
+ else
+ {
+ DrawFrame = Frame.Start + (Frame.OffSet * (byte)Direction) + FrameIndex;
+ DrawWingFrame = Frame.EffectStart + (Frame.EffectOffSet * (byte)Direction) + EffectFrameIndex;
+ }
+
+ #region Moving OffSet
+
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ case MirAction.DashL:
+ case MirAction.DashR:
+ if (Frame == null)
+ {
+ OffSetMove = Point.Empty;
+ Movement = CurrentLocation;
+ break;
+ }
+
+ var i = 1;
+
+ Movement = Functions.PointMove(CurrentLocation, Direction, CurrentAction == MirAction.Pushed ? 0 : -i);
+
+ int count = Frame.Count;
+ int index = FrameIndex;
+
+ if (CurrentAction == MirAction.DashR || CurrentAction == MirAction.DashL)
+ {
+ count = 3;
+ index %= 3;
+ }
+
+ switch (Direction)
+ {
+ case MirDirection.Up:
+ OffSetMove = new Point(0, (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.UpRight:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Right:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), 0);
+ break;
+ case MirDirection.DownRight:
+ OffSetMove = new Point((int)((-MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Down:
+ OffSetMove = new Point(0, (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.DownLeft:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((-MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ case MirDirection.Left:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), 0);
+ break;
+ case MirDirection.UpLeft:
+ OffSetMove = new Point((int)((MapControl.CellWidth * i / (float)(count)) * (index + 1)), (int)((MapControl.CellHeight * i / (float)(count)) * (index + 1)));
+ break;
+ }
+
+ OffSetMove = new Point(OffSetMove.X % 2 + OffSetMove.X, OffSetMove.Y % 2 + OffSetMove.Y);
+ break;
+ default:
+ OffSetMove = Point.Empty;
+ Movement = CurrentLocation;
+ break;
+ }
+
+ #endregion
+
+
+ DrawY = Movement.Y > CurrentLocation.Y ? Movement.Y : CurrentLocation.Y;
+
+ DrawLocation = new Point((Movement.X - User.Movement.X + MapControl.OffSetX) * MapControl.CellWidth, (Movement.Y - User.Movement.Y + MapControl.OffSetY) * MapControl.CellHeight);
+ DrawLocation.Offset(GlobalDisplayLocationOffset);
+
+ if (this != User)
+ {
+ DrawLocation.Offset(User.OffSetMove);
+ DrawLocation.Offset(-OffSetMove.X, -OffSetMove.Y);
+ }
+
+ if (BodyLibrary != null && update)
+ {
+ FinalDrawLocation = DrawLocation.Add(BodyLibrary.GetOffSet(DrawFrame));
+ DisplayRectangle = new Rectangle(DrawLocation, BodyLibrary.GetTrueSize(DrawFrame));
+ }
+
+ for (int i = 0; i < Effects.Count; i++)
+ Effects[i].Process();
+
+ Color colour = DrawColour;
+ DrawColour = Color.White;
+ if (Poison != PoisonType.None)
+ {
+
+ if (Poison.HasFlag(PoisonType.Green))
+ DrawColour = Color.Green;
+ if (Poison.HasFlag(PoisonType.Red))
+ DrawColour = Color.Red;
+ if (Poison.HasFlag(PoisonType.Slow))
+ DrawColour = Color.Purple;
+ if (Poison.HasFlag(PoisonType.Stun))
+ DrawColour = Color.Yellow;
+ if (Poison.HasFlag(PoisonType.Frozen))
+ DrawColour = Color.Blue;
+ if (Poison.HasFlag(PoisonType.Paralysis))
+ DrawColour = Color.Gray;
+ }
+
+
+ if (colour != DrawColour) GameScene.Scene.MapControl.TextureValid = false;
+ }
+ public virtual void SetAction()
+ {
+ if (NextAction != null && !GameScene.CanMove)
+ {
+ switch (NextAction.Action)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ case MirAction.DashL:
+ case MirAction.DashR:
+ return;
+ }
+ }
+
+ if (User == this && CMain.Time < MapControl.NextAction)// && CanSetAction)
+ {
+ //NextMagic = null;
+ return;
+ }
+
+
+ if (ActionFeed.Count == 0)
+ {
+ CurrentAction = MirAction.Standing;
+
+ if (CurrentAction == MirAction.Standing)
+ {
+ CurrentAction = CMain.Time > StanceTime ? MirAction.Standing : MirAction.Stance;
+ }
+
+ Frames.TryGetValue(CurrentAction, out Frame);
+ FrameIndex = 0;
+ EffectFrameIndex = 0;
+
+ if (MapLocation != CurrentLocation)
+ {
+ GameScene.Scene.MapControl.RemoveObject(this);
+ MapLocation = CurrentLocation;
+ GameScene.Scene.MapControl.AddObject(this);
+ }
+
+ if (Frame == null) return;
+
+ FrameInterval = Frame.Interval;
+ EffectFrameInterval = Frame.EffectInterval;
+
+ SetLibraries();
+ }
+ else
+ {
+ QueuedAction action = ActionFeed[0];
+ ActionFeed.RemoveAt(0);
+
+
+ CurrentAction = action.Action;
+
+ CurrentLocation = action.Location;
+ MirDirection olddirection = Direction;
+ Direction = action.Direction;
+
+ Point temp;
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ case MirAction.Pushed:
+ case MirAction.DashL:
+ case MirAction.DashR:
+ var steps = 1;
+
+ temp = Functions.PointMove(CurrentLocation, Direction, CurrentAction == MirAction.Pushed ? 0 : -steps);
+
+ break;
+ default:
+ temp = CurrentLocation;
+ break;
+ }
+
+ temp = new Point(action.Location.X, temp.Y > CurrentLocation.Y ? temp.Y : CurrentLocation.Y);
+
+ if (MapLocation != temp)
+ {
+ GameScene.Scene.MapControl.RemoveObject(this);
+ MapLocation = temp;
+ GameScene.Scene.MapControl.AddObject(this);
+ }
+
+
+ bool ArcherLayTrap = false;
+
+ switch (CurrentAction)
+ {
+ case MirAction.Pushed:
+ if (this == User)
+ MapControl.InputDelay = CMain.Time + 500;
+ Frames.TryGetValue(MirAction.Walking, out Frame);
+ break;
+ case MirAction.DashL:
+ case MirAction.DashR:
+ Frames.TryGetValue(MirAction.Walking, out Frame);
+ break;
+ case MirAction.DashFail:
+ Frames.TryGetValue(MirAction.Standing, out Frame);
+ break;
+ case MirAction.Attack1:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+ case MirAction.Spell:
+ Spell = (Spell)action.Params[0];
+ switch (Spell)
+ {
+ case Spell.ShoulderDash:
+ Frames.TryGetValue(MirAction.Walking, out Frame);
+ CurrentAction = MirAction.DashL;
+ Direction = olddirection;
+ CurrentLocation = Functions.PointMove(CurrentLocation, Direction, 1);
+ if (this == User)
+ {
+ MapControl.NextAction = CMain.Time + 2500;
+ GameScene.SpellTime = CMain.Time + 2500; //Spell Delay
+
+ Network.Enqueue(new C.Magic { ObjectID = GameScene.User.ObjectID, Spell = Spell, Direction = Direction, });
+ }
+ break;
+ default:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+ }
+
+ break;
+ default:
+ Frames.TryGetValue(CurrentAction, out Frame);
+ break;
+
+ }
+
+ SetLibraries();
+
+ FrameIndex = 0;
+ EffectFrameIndex = 0;
+ Spell = Spell.None;
+ SpellLevel = 0;
+ //NextMagic = null;
+
+ ClientMagic magic;
+
+ if (Frame == null) return;
+
+ FrameInterval = Frame.Interval;
+ EffectFrameInterval = Frame.EffectInterval;
+
+ if (this == User)
+ {
+ switch (CurrentAction)
+ {
+ case MirAction.DashFail:
+ //CanSetAction = false;
+ break;
+ case MirAction.Standing:
+ Network.Enqueue(new C.Turn { Direction = Direction });
+ MapControl.NextAction = CMain.Time + 2500;
+ break;
+ case MirAction.Walking:
+ Network.Enqueue(new C.Walk { Direction = Direction });
+ GameScene.Scene.MapControl.FloorValid = false;
+ MapControl.NextAction = CMain.Time + 2500;
+ break;
+ case MirAction.Pushed:
+ GameScene.Scene.MapControl.FloorValid = false;
+ MapControl.InputDelay = CMain.Time + 500;
+ GameScene.CanMove = false;
+ break;
+ case MirAction.DashL:
+ case MirAction.DashR:
+ GameScene.Scene.MapControl.FloorValid = false;
+ //CanSetAction = false;
+ break;
+ case MirAction.Attack1:
+ if (GameScene.User.Slaying && TargetObject != null)
+ Spell = Spell.Slaying;
+
+ if (GameScene.User.Thrusting && GameScene.Scene.MapControl.HasTarget(Functions.PointMove(CurrentLocation, Direction, 2)))
+ Spell = Spell.Thrusting;
+
+ if (GameScene.User.HalfMoon)
+ {
+ if (TargetObject != null || GameScene.Scene.MapControl.CanHalfMoon(CurrentLocation, Direction))
+ {
+ magic = User.GetMagic(Spell.HalfMoon);
+ if (magic != null && magic.BaseCost + magic.LevelCost * magic.Level <= User.MP)
+ Spell = Spell.HalfMoon;
+ }
+ }
+
+ if (GameScene.User.FlamingSword)
+ {
+ if (TargetObject != null)
+ {
+ magic = User.GetMagic(Spell.FlamingSword);
+ if (magic != null)
+ {
+ Spell = Spell.FlamingSword;
+ magic.CastTime = CMain.Time;
+ }
+ }
+ }
+
+
+ Network.Enqueue(new C.Attack { Direction = Direction, Spell = Spell });
+
+ if (Spell == Spell.Slaying)
+ GameScene.User.Slaying = false;
+ if (Spell == Spell.FlamingSword)
+ GameScene.User.FlamingSword = false;
+
+ magic = User.GetMagic(Spell);
+
+ if (magic != null) SpellLevel = magic.Level;
+
+ GameScene.AttackTime = CMain.Time + User.AttackSpeed;
+ MapControl.NextAction = CMain.Time + 2500;
+ break;
+
+ case MirAction.AttackRange1:
+ {
+ GameScene.AttackTime = CMain.Time + User.AttackSpeed + 200;
+
+ uint targetID = (uint)action.Params[0];
+ Point location = (Point)action.Params[1];
+
+ Network.Enqueue(new C.RangeAttack { Direction = Direction, Location = CurrentLocation, TargetID = targetID, TargetLocation = location });
+ }
+ break;
+ case MirAction.Spell:
+ {
+ Spell = (Spell)action.Params[0];
+ uint targetID = (uint)action.Params[1];
+ Point location = (Point)action.Params[2];
+
+ Network.Enqueue(new C.Magic { ObjectID = GameScene.User.ObjectID, Spell = Spell, Direction = Direction, TargetID = targetID, Location = location });
+
+ GameScene.SpellTime = CMain.Time + 1800;
+ MapControl.NextAction = CMain.Time + 2500;
+ }
+ break;
+ case MirAction.Harvest:
+ if (ArcherLayTrap)
+ {
+ ArcherLayTrap = false;
+ SoundManager.PlaySound(20000 + 124 * 10);
+ }
+ else
+ {
+ Network.Enqueue(new C.Harvest { Direction = Direction });
+ MapControl.NextAction = CMain.Time + 2500;
+ }
+ break;
+
+ }
+ }
+
+
+ switch (CurrentAction)
+ {
+ case MirAction.Pushed:
+ FrameIndex = Frame.Count - 1;
+ EffectFrameIndex = Frame.EffectCount - 1;
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.DashL:
+ FrameIndex = 0;
+ EffectFrameIndex = 0;
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.DashR:
+ FrameIndex = 3;
+ EffectFrameIndex = 3;
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.Walking:
+ GameScene.Scene.Redraw();
+ break;
+ case MirAction.Attack1:
+ if (this != User)
+ {
+ Spell = (Spell)action.Params[0];
+ SpellLevel = (byte)action.Params[1];
+ }
+
+ switch (Spell)
+ {
+ case Spell.Slaying:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + (Gender == MirGender.Male ? 0 : 1));
+ break;
+ case Spell.Thrusting:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+ case Spell.HalfMoon:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+ case Spell.FlamingSword:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ break;
+
+
+ }
+ break;
+ case MirAction.AttackRange1: //ArcherTest - Assign Target for other users
+ if (this != User)
+ {
+ TargetID = (uint)action.Params[0];
+ TargetPoint = (Point)action.Params[1];
+ Spell = (Spell)action.Params[2];
+ }
+ break;
+ case MirAction.Spell:
+ if (this != User)
+ {
+ Spell = (Spell)action.Params[0];
+ TargetID = (uint)action.Params[1];
+ TargetPoint = (Point)action.Params[2];
+ Cast = (bool)action.Params[3];
+ SpellLevel = (byte)action.Params[4];
+ SecondaryTargetIDs = (List)action.Params[5];
+ }
+
+ switch (Spell)
+ {
+ #region FireBall
+
+ case Spell.FireBall:
+ Effects.Add(new Effect(Libraries.Magic, 0, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Healing
+
+ case Spell.Healing:
+ Effects.Add(new Effect(Libraries.Magic, 200, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Repulsion
+
+ case Spell.Repulsion:
+ Effects.Add(new Effect(Libraries.Magic, 900, 6, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region ElectricShock
+
+ case Spell.ElectricShock:
+ Effects.Add(new Effect(Libraries.Magic, 1560, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Poisoning
+
+ case Spell.Poisoning:
+ Effects.Add(new Effect(Libraries.Magic, 600, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region GreatFireBall
+
+ case Spell.GreatFireBall:
+ Effects.Add(new Effect(Libraries.Magic, 400, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region HellFire
+
+ case Spell.HellFire:
+ Effects.Add(new Effect(Libraries.Magic, 920, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region ThunderBolt
+
+ case Spell.ThunderBolt:
+ Effects.Add(new Effect(Libraries.Magic2, 20, 3, 300, this));
+ break;
+
+ #endregion
+
+ #region SoulFireBall
+
+ case Spell.SoulFireBall:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region SummonSkeleton
+
+ case Spell.SummonSkeleton:
+ Effects.Add(new Effect(Libraries.Magic, 1500, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Teleport
+
+ case Spell.Teleport:
+ Effects.Add(new Effect(Libraries.Magic, 1590, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Hiding
+
+ case Spell.Hiding:
+ Effects.Add(new Effect(Libraries.Magic, 1520, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region FireBang
+
+ case Spell.FireBang:
+ Effects.Add(new Effect(Libraries.Magic, 1650, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region FireWall
+
+ case Spell.FireWall:
+ Effects.Add(new Effect(Libraries.Magic, 1620, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region TrapHexagon
+
+ case Spell.TrapHexagon:
+ Effects.Add(new Effect(Libraries.Magic, 1380, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region EnergyRepulsor
+
+ case Spell.EnergyRepulsor:
+ Effects.Add(new Effect(Libraries.Magic2, 190, 6, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region UltimateEnchancer
+
+ case Spell.UltimateEnhancer:
+ Effects.Add(new Effect(Libraries.Magic2, 160, 15, 1000, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region FrostCrunch
+
+ case Spell.FrostCrunch:
+ Effects.Add(new Effect(Libraries.Magic2, 400, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Purification
+
+ case Spell.Purification:
+ Effects.Add(new Effect(Libraries.Magic2, 600, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region ThunderStorm
+
+ case Spell.ThunderStorm:
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1680, 10, Frame.Count * FrameInterval, CurrentLocation));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region MassHealing
+
+ case Spell.MassHealing:
+ Effects.Add(new Effect(Libraries.Magic, 1790, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region MagicShield
+
+ case Spell.MagicShield:
+ Effects.Add(new Effect(Libraries.Magic, 3880, 10, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region Revelation
+
+ case Spell.Revelation:
+ Effects.Add(new Effect(Libraries.Magic, 3960, 20, 1200, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+ }
+
+
+ break;
+ case MirAction.Dead:
+ GameScene.Scene.Redraw();
+ GameScene.Scene.MapControl.SortObject(this);
+ if (MouseObject == this) MouseObjectID = 0;
+ if (TargetObject == this) TargetObjectID = 0;
+ if (MagicObject == this) MagicObjectID = 0;
+ DeadTime = CMain.Time;
+ break;
+
+ }
+
+ }
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ NextMotion = CMain.Time + FrameInterval;
+ NextMotion2 = CMain.Time + EffectFrameInterval;
+
+ if (MagicShield)
+ {
+ switch (CurrentAction)
+ {
+ default:
+ if (ShieldEffect == null)
+ Effects.Add(ShieldEffect = new Effect(Libraries.Magic, 3890, 3, 600, this) { Repeat = true });
+ break;
+ }
+ }
+
+ }
+
+ public virtual void ProcessFrames()
+ {
+ if (Frame == null) return;
+
+ switch (CurrentAction)
+ {
+ case MirAction.Walking:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (this == User) GameScene.Scene.MapControl.FloorValid = false;
+ //if (CMain.Time < NextMotion) return;
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame(false) >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ if (this == User) GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+ case MirAction.DashL:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (this == User) GameScene.Scene.MapControl.FloorValid = false;
+ if (UpdateFrame() >= 3)
+ {
+ FrameIndex = 2;
+ SetAction();
+ }
+
+ if (UpdateFrame2() >= 3) EffectFrameIndex = 2;
+ break;
+ case MirAction.DashR:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (this == User) GameScene.Scene.MapControl.FloorValid = false;
+
+ if (UpdateFrame() >= 6)
+ {
+ FrameIndex = 5;
+ SetAction();
+ }
+
+ if (UpdateFrame2() >= 6) EffectFrameIndex = 5;
+ break;
+ case MirAction.Pushed:
+ if (!GameScene.CanMove) return;
+
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (this == User) GameScene.Scene.MapControl.FloorValid = false;
+
+ FrameIndex -= 2;
+ EffectFrameIndex -= 2;
+
+ if (FrameIndex < 0)
+ {
+ FrameIndex = 0;
+ SetAction();
+ }
+
+ if (FrameIndex < 0) EffectFrameIndex = 0;
+ break;
+
+ case MirAction.Standing:
+ case MirAction.DashFail:
+ case MirAction.Harvest:
+ case MirAction.Stance:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+ case MirAction.Attack1:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ //if (ActionFeed.Count == 0)
+ // ActionFeed.Add(new QueuedAction { Action = MirAction.Stance, Direction = Direction, Location = CurrentLocation });
+
+ StanceTime = CMain.Time + StanceDelay;
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ if (FrameIndex == 1) PlayAttackSound();
+ NextMotion += FrameInterval;
+ }
+ }
+
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+
+ case MirAction.AttackRange1:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+ }
+ else
+ {
+ if (FrameIndex == 1) PlayAttackSound();
+ Missile missile;
+ switch (FrameIndex)
+ {
+ case 5:
+ missile = CreateProjectile(1030, Libraries.Magic2, true, 5, 30, 5);
+ StanceTime = CMain.Time + StanceDelay;
+ SoundManager.PlaySound(20000 + 121 * 10);
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ SoundManager.PlaySound(20000 + 121 * 10 + 2);
+ };
+ }
+ break;
+ }
+
+ NextMotion += FrameInterval;
+ }
+ }
+
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+ case MirAction.Spell:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ if (Cast)
+ {
+
+ MapObject ob = MapControl.GetObject(TargetID);
+
+ Missile missile;
+ Effect effect;
+ switch (Spell)
+ {
+ #region FireBall
+
+ case Spell.FireBall:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ missile = CreateProjectile(10, Libraries.Magic, true, 6, 30, 4);
+
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ if (missile.Target.CurrentAction == MirAction.Dead) return;
+ missile.Target.Effects.Add(new Effect(Libraries.Magic, 170, 10, 600, missile.Target));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 2);
+ };
+ }
+ break;
+
+ #endregion
+
+ #region GreatFireBall
+
+ case Spell.GreatFireBall:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ missile = CreateProjectile(410, Libraries.Magic, true, 6, 30, 4);
+
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ if (missile.Target.CurrentAction == MirAction.Dead) return;
+ missile.Target.Effects.Add(new Effect(Libraries.Magic, 570, 10, 600, missile.Target));
+ SoundManager.PlaySound(20000 + (ushort)Spell.GreatFireBall * 10 + 2);
+ };
+ }
+ break;
+
+ #endregion
+
+ #region Healing
+
+ case Spell.Healing:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ if (ob == null)
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 370, 10, 800, TargetPoint));
+ else
+ ob.Effects.Add(new Effect(Libraries.Magic, 370, 10, 800, ob));
+ break;
+
+ #endregion
+
+ #region ElectricShock
+
+ case Spell.ElectricShock:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ if (ob == null)
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1570, 10, 1000, TargetPoint));
+ else
+ ob.Effects.Add(new Effect(Libraries.Magic, 1570, 10, 1000, ob));
+ break;
+ #endregion
+
+ #region Poisoning
+
+ case Spell.Poisoning:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ if (ob != null)
+ ob.Effects.Add(new Effect(Libraries.Magic, 770, 10, 1000, ob));
+ break;
+ #endregion
+
+ #region HellFire
+
+ case Spell.HellFire:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+
+
+ Point dest = CurrentLocation;
+ for (int i = 0; i < 4; i++)
+ {
+ dest = Functions.PointMove(dest, Direction, 1);
+ if (!GameScene.Scene.MapControl.ValidPoint(dest)) break;
+ effect = new Effect(Libraries.Magic, 930, 6, 500, dest) { Rate = 0.7F };
+
+ effect.SetStart(CMain.Time + i * 50);
+ MapControl.Effects.Add(effect);
+ }
+
+ if (SpellLevel == 3)
+ {
+ MirDirection dir = (MirDirection)(((int)Direction + 1) % 8);
+ dest = CurrentLocation;
+ for (int r = 0; r < 4; r++)
+ {
+ dest = Functions.PointMove(dest, dir, 1);
+ if (!GameScene.Scene.MapControl.ValidPoint(dest)) break;
+ effect = new Effect(Libraries.Magic, 930, 6, 500, dest) { Rate = 0.7F };
+
+ effect.SetStart(CMain.Time + r * 50);
+ MapControl.Effects.Add(effect);
+ }
+
+ dir = (MirDirection)(((int)Direction - 1 + 8) % 8);
+ dest = CurrentLocation;
+ for (int r = 0; r < 4; r++)
+ {
+ dest = Functions.PointMove(dest, dir, 1);
+ if (!GameScene.Scene.MapControl.ValidPoint(dest)) break;
+ effect = new Effect(Libraries.Magic, 930, 6, 500, dest) { Rate = 0.7F };
+
+ effect.SetStart(CMain.Time + r * 50);
+ MapControl.Effects.Add(effect);
+ }
+ }
+ break;
+
+ #endregion
+
+ #region ThunderBolt
+
+ case Spell.ThunderBolt:
+
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+
+ if (ob == null)
+ MapControl.Effects.Add(new Effect(Libraries.Magic2, 10, 5, 400, TargetPoint));
+ else
+ ob.Effects.Add(new Effect(Libraries.Magic2, 10, 5, 400, ob));
+ break;
+
+ #endregion
+
+ #region SoulFireBall
+
+ case Spell.SoulFireBall:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ missile = CreateProjectile(1160, Libraries.Magic, true, 3, 30, 7);
+
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ if (missile.Target.CurrentAction == MirAction.Dead) return;
+ missile.Target.Effects.Add(new Effect(Libraries.Magic, 1360, 10, 600, missile.Target));
+ SoundManager.PlaySound(20000 + (ushort)Spell.SoulFireBall * 10 + 2);
+ };
+ }
+ break;
+
+ #endregion
+
+ #region FireBang
+
+ case Spell.FireBang:
+
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1660, 10, 1000, TargetPoint));
+ break;
+
+ #endregion
+
+ #region MassHiding
+
+ case Spell.MassHiding:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ missile = CreateProjectile(1160, Libraries.Magic, true, 3, 30, 7);
+ missile.Explode = true;
+
+ missile.Complete += (o, e) =>
+ {
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1540, 10, 800, TargetPoint));
+ SoundManager.PlaySound(20000 + (ushort)Spell.MassHiding * 10 + 1);
+ };
+ break;
+
+ #endregion
+
+ #region SoulShield
+
+ case Spell.SoulShield:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ missile = CreateProjectile(1160, Libraries.Magic, true, 3, 30, 7);
+ missile.Explode = true;
+
+ missile.Complete += (o, e) =>
+ {
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1320, 15, 1200, TargetPoint));
+ SoundManager.PlaySound(20000 + (ushort)Spell.SoulShield * 10 + 1);
+ };
+ break;
+
+ #endregion
+
+ #region BlessedArmour
+
+ case Spell.BlessedArmour:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ missile = CreateProjectile(1160, Libraries.Magic, true, 3, 30, 7);
+ missile.Explode = true;
+
+ missile.Complete += (o, e) =>
+ {
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1340, 15, 1200, TargetPoint));
+ SoundManager.PlaySound(20000 + (ushort)Spell.BlessedArmour * 10 + 1);
+ };
+ break;
+
+ #endregion
+
+ #region FireWall
+
+ case Spell.FireWall:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ break;
+
+ #endregion
+
+ #region MassHealing
+
+ case Spell.MassHealing:
+
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 1800, 10, 1000, TargetPoint));
+ break;
+
+ #endregion
+
+ #region Revelation
+
+ case Spell.Revelation:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ if (ob == null)
+ MapControl.Effects.Add(new Effect(Libraries.Magic, 3990, 10, 1000, TargetPoint));
+ else
+ ob.Effects.Add(new Effect(Libraries.Magic, 3990, 10, 1000, ob));
+ break;
+ #endregion
+
+ #region FrostCrunch
+
+ case Spell.FrostCrunch:
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10 + 1);
+ missile = CreateProjectile(410, Libraries.Magic2, true, 4, 30, 6);
+
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ if (missile.Target.CurrentAction == MirAction.Dead) return;
+ missile.Target.Effects.Add(new Effect(Libraries.Magic2, 570, 8, 600, missile.Target));
+ SoundManager.PlaySound(20000 + (ushort)Spell.FrostCrunch * 10 + 2);
+ };
+ }
+ break;
+
+ #endregion
+
+ #region Purification
+
+ case Spell.Purification:
+ if (ob == null)
+ MapControl.Effects.Add(new Effect(Libraries.Magic2, 620, 10, 800, TargetPoint));
+ else
+ ob.Effects.Add(new Effect(Libraries.Magic2, 620, 10, 800, ob));
+ break;
+
+ #endregion
+
+ #region Hallucination
+
+ case Spell.Hallucination:
+ missile = CreateProjectile(1160, Libraries.Magic, true, 3, 48, 7);
+
+ if (missile.Target != null)
+ {
+ missile.Complete += (o, e) =>
+ {
+ if (missile.Target.CurrentAction == MirAction.Dead) return;
+ missile.Target.Effects.Add(new Effect(Libraries.Magic2, 1110, 10, 1000, missile.Target));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ };
+ }
+ break;
+
+ #endregion
+
+ #region Lightning
+
+ case Spell.Lightning:
+ Effects.Add(new Effect(Libraries.Magic, 970 + (int)Direction * 20, 6, Frame.Count * FrameInterval, this));
+ SoundManager.PlaySound(20000 + (ushort)Spell * 10);
+ break;
+
+ #endregion
+
+ #region UltimateEnhancer
+
+ case Spell.UltimateEnhancer:
+ if (ob != null && ob != User)
+ ob.Effects.Add(new Effect(Libraries.Magic2, 160, 15, 1000, ob));
+ break;
+
+ #endregion
+
+ #region TrapHexagon
+
+ case Spell.TrapHexagon:
+ if (ob != null)
+ SoundManager.PlaySound(20000 + (ushort)Spell.TrapHexagon * 10 + 1);
+ break;
+
+ #endregion
+ }
+
+
+ Cast = false;
+ }
+ //if (ActionFeed.Count == 0)
+ // ActionFeed.Add(new QueuedAction { Action = MirAction.Stance, Direction = Direction, Location = CurrentLocation });
+
+ StanceTime = CMain.Time + StanceDelay;
+ FrameIndex = Frame.Count - 1;
+ SetAction();
+
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+
+ }
+ }
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+ case MirAction.Die:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ ActionFeed.Clear();
+ ActionFeed.Add(new QueuedAction { Action = MirAction.Dead, Direction = Direction, Location = CurrentLocation });
+ SetAction();
+ }
+ else
+ {
+ if (FrameIndex == 1)
+ PlayDieSound();
+
+ NextMotion += FrameInterval;
+ }
+ }
+ if (WingEffect > 0 && CMain.Time >= NextMotion2)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame2();
+
+ if (UpdateFrame2() >= Frame.EffectCount)
+ EffectFrameIndex = Frame.EffectCount - 1;
+ else
+ NextMotion2 += EffectFrameInterval;
+ }
+ break;
+ case MirAction.Dead:
+ break;
+ case MirAction.Revive:
+ if (CMain.Time >= NextMotion)
+ {
+ GameScene.Scene.MapControl.TextureValid = false;
+
+ if (SkipFrames) UpdateFrame();
+
+ if (UpdateFrame() >= Frame.Count)
+ {
+ FrameIndex = Frame.Count - 1;
+ ActionFeed.Clear();
+ ActionFeed.Add(new QueuedAction { Action = MirAction.Standing, Direction = Direction, Location = CurrentLocation });
+ SetAction();
+ }
+ else
+ {
+ NextMotion += FrameInterval;
+ }
+ }
+ break;
+
+ }
+
+ if (this == User) return;
+
+ if ((CurrentAction == MirAction.Standing || CurrentAction == MirAction.Stance || CurrentAction == MirAction.DashFail) && NextAction != null)
+ SetAction();
+ //if Revive and dead set action
+
+ }
+ public int UpdateFrame(bool skip = true)
+ {
+ if (Frame == null) return 0;
+ if (Poison.HasFlag(PoisonType.Slow) && !skip)
+ {
+ SkipFrameUpdate++;
+ if (SkipFrameUpdate == 2)
+ SkipFrameUpdate = 0;
+ else
+ return FrameIndex;
+ }
+ if (Frame.Reverse) return Math.Abs(--FrameIndex);
+
+ return ++FrameIndex;
+ }
+
+ public int UpdateFrame2()
+ {
+ if (Frame == null) return 0;
+
+ if (Frame.Reverse) return Math.Abs(--EffectFrameIndex);
+
+ return ++EffectFrameIndex;
+ }
+
+
+ public override Missile CreateProjectile(int baseIndex, MLibrary library, bool blend, int count, int interval, int skip, int lightDistance = 6, bool direction16 = true, Color? lightColour = null, uint targetID = 0)
+ {
+ if (targetID == 0)
+ {
+ targetID = TargetID;
+ }
+
+ MapObject ob = MapControl.GetObject(targetID);
+
+ var targetPoint = TargetPoint;
+
+ if (ob != null) targetPoint = ob.CurrentLocation;
+
+ int duration = Functions.MaxDistance(CurrentLocation, targetPoint) * 50;
+
+ Missile missile = new Missile(library, baseIndex, duration / interval, duration, this, targetPoint)
+ {
+ Target = ob,
+ Interval = interval,
+ FrameCount = count,
+ Blend = blend,
+ Skip = skip,
+ Light = lightDistance,
+ LightColour = lightColour == null ? Color.White : (Color)lightColour
+ };
+
+ Effects.Add(missile);
+
+ return missile;
+ }
+
+ public override void PlayStruckSound()
+ {
+ switch (StruckWeapon)
+ {
+ default:
+ SoundManager.PlaySound(SoundList.StruckBodySword);
+ break;
+ case -1:
+ SoundManager.PlaySound(SoundList.StruckBodyFist);
+ break;
+ }
+ }
+
+ public void PlayAttackSound()
+ {
+ switch (Weapon)
+ {
+ case 1:
+ case 2:
+ case 4:
+ SoundManager.PlaySound(SoundList.SwingWood);
+ break;
+ case 3:
+ case 5:
+ case 6:
+ SoundManager.PlaySound(SoundList.SwingSword);
+ break;
+ default:
+ SoundManager.PlaySound(SoundList.SwingFist);
+ break;
+ }
+ }
+
+ public void PlayDieSound()
+ {
+ }
+
+
+ public override void Draw()
+ {
+ DrawBehindEffects(Settings.Effect);
+
+ float oldOpacity = DXManager.Opacity;
+ if (Hidden && !DXManager.Blending) DXManager.SetOpacity(0.5F);
+
+
+ if (Direction == MirDirection.Left || Direction == MirDirection.Up || Direction == MirDirection.UpLeft || Direction == MirDirection.DownLeft)
+ DrawWeapon();
+
+ DrawBody();
+
+ if (Direction == MirDirection.Up || Direction == MirDirection.UpLeft || Direction == MirDirection.UpRight || Direction == MirDirection.Right || Direction == MirDirection.Left)
+ {
+ DrawHead();
+ if (this != User)
+ {
+ DrawWings();
+ }
+ }
+ else
+ {
+ if (this != User)
+ {
+ DrawWings();
+ }
+ DrawHead();
+ }
+
+
+ if (Direction == MirDirection.UpRight || Direction == MirDirection.Right || Direction == MirDirection.DownRight || Direction == MirDirection.Down)
+ DrawWeapon();
+
+ DXManager.SetOpacity(oldOpacity);
+ }
+
+ public override void DrawBehindEffects(bool effectsEnabled)
+ {
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (!Effects[i].DrawBehind) continue;
+ if (!Settings.LevelEffect && (Effects[i] is SpecialEffect) && ((SpecialEffect)Effects[i]).EffectType == 1) continue;
+ if ((!effectsEnabled) && (!IsVitalEffect(Effects[i]))) continue;
+ Effects[i].Draw();
+ }
+ }
+
+ public override void DrawEffects(bool effectsEnabled)
+ {
+ for (int i = 0; i < Effects.Count; i++)
+ {
+ if (Effects[i].DrawBehind) continue;
+ if (!Settings.LevelEffect && (Effects[i] is SpecialEffect) && ((SpecialEffect)Effects[i]).EffectType == 1) continue;
+ if ((!effectsEnabled) && (!IsVitalEffect(Effects[i]))) continue;
+ Effects[i].Draw();
+ }
+
+ if (!effectsEnabled) return;
+
+ switch (CurrentAction)
+ {
+ case MirAction.Attack1:
+ switch (Spell)
+ {
+ case Spell.Slaying:
+ Libraries.Magic.DrawBlend(1820 + ((int)Direction * 10) + SpellLevel * 90 + FrameIndex, DrawLocation, Color.White, true, 0.7F);
+ break;
+ case Spell.Thrusting:
+ Libraries.Magic.DrawBlend(2190 + ((int)Direction * 10) + SpellLevel * 90 + FrameIndex, DrawLocation, Color.White, true, 0.7F);
+ break;
+ case Spell.HalfMoon:
+ Libraries.Magic.DrawBlend(2560 + ((int)Direction * 10) + SpellLevel * 90 + FrameIndex, DrawLocation, Color.White, true, 0.7F);
+ break;
+ case Spell.FlamingSword:
+ Libraries.Magic.DrawBlend(3480 + ((int)Direction * 10) + FrameIndex, DrawLocation, Color.White, true, 0.7F);
+ break;
+ }
+ break;
+ }
+
+
+ }
+
+ public void DrawCurrentEffects()
+ {
+ if (CurrentEffect == SpellEffect.MagicShieldUp && !MagicShield)
+ {
+ MagicShield = true;
+ Effects.Add(ShieldEffect = new Effect(Libraries.Magic, 3890, 3, 600, this) { Repeat = true });
+ CurrentEffect = SpellEffect.None;
+ }
+ }
+
+ public override void DrawBlend()
+ {
+ DXManager.SetBlend(true, 0.3F);
+ Draw();
+ DXManager.SetBlend(false);
+ }
+ public void DrawBody()
+ {
+ bool oldGrayScale = DXManager.GrayScale;
+ Color drawColour = ApplyDrawColour();
+
+ if (BodyLibrary != null)
+ BodyLibrary.Draw(DrawFrame + ArmourOffSet, DrawLocation, drawColour, true);
+
+ DXManager.SetGrayscale(oldGrayScale);
+
+ //BodyLibrary.DrawTinted(DrawFrame + ArmourOffSet, DrawLocation, DrawColour, Color.DarkSeaGreen);
+ }
+ public void DrawHead()
+ {
+ if (HairLibrary != null)
+ HairLibrary.Draw(DrawFrame + HairOffSet, DrawLocation, DrawColour, true);
+ }
+ public void DrawWeapon()
+ {
+ if (Weapon < 0) return;
+
+ if (WeaponLibrary1 != null)
+ {
+ WeaponLibrary1.Draw(DrawFrame + WeaponOffSet, DrawLocation, DrawColour, true); //original
+ }
+ }
+ public void DrawWings()
+ {
+ if (WingEffect <= 0 || WingEffect >= 100) return;
+
+ if (WingLibrary != null)
+ WingLibrary.DrawBlend(DrawWingFrame + WingOffset, DrawLocation, DrawColour, true);
+ }
+
+ private bool IsVitalEffect(Effect effect)
+ {
+ if ((effect.Library == Libraries.Magic) && (effect.BaseIndex == 3890))
+ return true;
+ if ((effect.Library == Libraries.Magic2) && (effect.BaseIndex == 1890))
+ return true;
+ return false;
+ }
+
+ public override bool MouseOver(Point p)
+ {
+ return MapControl.MapLocation == CurrentLocation || BodyLibrary != null && BodyLibrary.VisiblePixel(DrawFrame + ArmourOffSet, p.Subtract(FinalDrawLocation), false);
+ }
+
+ private void CreateNameLabel()
+ {
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != Name || LabelList[i].ForeColour != NameColour) continue;
+ NameLabel = LabelList[i];
+ break;
+ }
+
+ if (NameLabel != null && !NameLabel.IsDisposed) return;
+
+ NameLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = NameColour,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = Name,
+ };
+ NameLabel.Disposing += (o, e) => LabelList.Remove(NameLabel);
+ LabelList.Add(NameLabel);
+ }
+
+ private void CreateGuildLabel()
+ {
+ if (string.IsNullOrEmpty(GuildName))
+ return;
+
+ for (int i = 0; i < LabelList.Count; i++)
+ {
+ if (LabelList[i].Text != GuildName || LabelList[i].ForeColour != NameColour) continue;
+ GuildLabel = LabelList[i];
+ break;
+ }
+
+ if (GuildLabel != null && !GuildLabel.IsDisposed) return;
+
+ GuildLabel = new MirLabel
+ {
+ AutoSize = true,
+ BackColour = Color.Transparent,
+ ForeColour = NameColour,
+ OutLine = true,
+ OutLineColour = Color.Black,
+ Text = GuildName,
+ };
+ GuildLabel.Disposing += (o, e) => LabelList.Remove(GuildLabel);
+ LabelList.Add(GuildLabel);
+ }
+
+ public override void CreateLabel()
+ {
+ NameLabel = null;
+ GuildLabel = null;
+
+ CreateNameLabel();
+ CreateGuildLabel();
+ }
+
+ public override void DrawName()
+ {
+ CreateLabel();
+
+ if (GuildLabel != null && !string.IsNullOrEmpty(GuildName))
+ {
+ GuildLabel.Text = GuildName;
+ GuildLabel.Location = new Point(DisplayRectangle.X + (50 - GuildLabel.Size.Width) / 2, DisplayRectangle.Y - (19 - GuildLabel.Size.Height / 2) + (Dead ? 35 : 8)); //was 48 -
+ GuildLabel.Draw();
+ }
+
+ if (NameLabel != null)
+ {
+ NameLabel.Text = Name;
+ NameLabel.Location = new Point(DisplayRectangle.X + (50 - NameLabel.Size.Width) / 2, DisplayRectangle.Y - (51 - NameLabel.Size.Height / 2) + (Dead ? 55 : 8)); //was 48 -
+ NameLabel.Draw();
+ }
+ }
+
+ }
+
+
+ public class QueuedAction
+ {
+ public MirAction Action;
+ public Point Location;
+ public MirDirection Direction;
+ public List