diff --git a/.gitignore b/.gitignore
index a8a8685..9491a2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -360,6 +360,4 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
-FodyWeavers.xsd
-/UI_Creation_Manual.md
-/UI_Creation_VirindiViewService_Manual.md
+FodyWeavers.xsd
\ No newline at end of file
diff --git a/GearCycler/GearCore.cs b/GearCycler/GearCore.cs
new file mode 100644
index 0000000..09b380a
--- /dev/null
+++ b/GearCycler/GearCore.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Decal.Adapter;
+using Decal.Adapter.Wrappers;
+using VirindiViewService;
+using VirindiViewService.Controls;
+
+namespace GearCycler
+{
+ [ComVisible(true)]
+ [Guid("9b6a07e1-ae78-47f4-b09c-174f6a27d7a3")] // Replace with your own unique GUID if needed
+ [FriendlyName("GearCycler")]
+ public class GearCore : PluginBase
+ {
+ public HudView view;
+ private HudButton btnCycle;
+
+ protected override void Startup()
+ {
+ try
+ {
+ string xml = File.ReadAllText("ViewXML\\mainview.xml");
+ view = HudView.ReadXmlLayout(xml);
+ view.Visible = true;
+
+ btnCycle = (HudButton)view.Controls["btnCycle"];
+ btnCycle.Hit += (s, e) =>
+ {
+ CoreManager.Current.Actions.AddChatText("[GearCycler] Button clicked!", 1);
+ };
+ }
+ catch (Exception ex)
+ {
+ CoreManager.Current.Actions.AddChatText($"[GearCycler] Failed to load UI: {ex.Message}", 1);
+ }
+ }
+
+ protected override void Shutdown()
+ {
+ btnCycle?.Dispose();
+ view?.Dispose();
+ }
+ }
+}
diff --git a/GearCycler/GearCycler.csproj b/GearCycler/GearCycler.csproj
new file mode 100644
index 0000000..b4344de
--- /dev/null
+++ b/GearCycler/GearCycler.csproj
@@ -0,0 +1,81 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {1293560E-2A56-417F-8116-8CE0420DC97C}
+ Library
+ Properties
+ GearCycler
+ GearCycler
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;VVS_REFERENCED;DECAL_INTEROP
+ prompt
+ 4
+ x86
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\MosswartMassacre\lib\Decal.Adapter.dll
+
+
+ False
+ True
+ ..\MosswartMassacre\lib\Decal.Interop.Core.DLL
+
+
+ False
+ True
+ ..\MosswartMassacre\lib\Decal.Interop.Inject.dll
+
+
+
+
+
+
+
+
+
+
+
+ ..\MosswartMassacre\lib\VirindiViewService.dll
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GearCycler/Properties/AssemblyInfo.cs b/GearCycler/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c45a3b8
--- /dev/null
+++ b/GearCycler/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GearCycler")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GearCycler")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f5462318-d26a-4ab0-8981-80edd9ec9c99")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/GearCycler/Properties/Resources.Designer.cs b/GearCycler/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..40b9adf
--- /dev/null
+++ b/GearCycler/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GearCycler.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GearCycler.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/GearCycler/Properties/Resources.resx b/GearCycler/Properties/Resources.resx
new file mode 100644
index 0000000..4fdb1b6
--- /dev/null
+++ b/GearCycler/Properties/Resources.resx
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/GearCycler/ViewXML/mainView.xml b/GearCycler/ViewXML/mainView.xml
new file mode 100644
index 0000000..1300d02
--- /dev/null
+++ b/GearCycler/ViewXML/mainView.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/GearCycler/lib/Decal.Adapter.dll b/GearCycler/lib/Decal.Adapter.dll
new file mode 100644
index 0000000..c27e132
Binary files /dev/null and b/GearCycler/lib/Decal.Adapter.dll differ
diff --git a/GearCycler/lib/Decal.Interop.Core.DLL b/GearCycler/lib/Decal.Interop.Core.DLL
new file mode 100644
index 0000000..b8de808
Binary files /dev/null and b/GearCycler/lib/Decal.Interop.Core.DLL differ
diff --git a/GearCycler/lib/Decal.Interop.Inject.dll b/GearCycler/lib/Decal.Interop.Inject.dll
new file mode 100644
index 0000000..f186c93
Binary files /dev/null and b/GearCycler/lib/Decal.Interop.Inject.dll differ
diff --git a/GearCycler/lib/VirindiViewService.dll b/GearCycler/lib/VirindiViewService.dll
new file mode 100644
index 0000000..1e3f4fc
Binary files /dev/null and b/GearCycler/lib/VirindiViewService.dll differ
diff --git a/GearCycler/lib/VirindiViewService.xml b/GearCycler/lib/VirindiViewService.xml
new file mode 100644
index 0000000..c43230e
--- /dev/null
+++ b/GearCycler/lib/VirindiViewService.xml
@@ -0,0 +1,386 @@
+
+
+
+ VirindiViewService
+
+
+
+
+ Implies Top and Left
+
+
+
+
+ Provides theme elements, which can be drawn by controls.
+
+
+
+
+ Displays an element from the current theme.
+
+
+
+
+ The base class for all Virindi Views controls.
+
+
+
+
+ Called after this control is added to a ControlGroup. This is when the Name and details have been set.
+
+
+
+
+ Add and initialize a child control of this control. The child may be removed by disposing it.
+
+
+
+
+
+ Called when a child of this control is disposed.
+
+
+
+
+
+ Recursively disposes all children and removes this control from the view, if it is initialized.
+
+
+
+
+ Handles a mouse wheel event. Parent controls must pass this on to applicable children if necessary.
+
+
+
+
+
+
+ Fires the MouseEvent event for mouse down, and sets this control as the focus control if CanTakeFocus is true.
+
+ Parent controls must pass this on to applicable children if necessary.
+
+
+
+
+
+ Fires the MouseEvent event for mouse up as well as the Hit event.
+
+ Parent controls must pass this on to applicable children if necessary.
+
+
+
+
+
+
+ Fired when the mousedown originated outside the current view. The base version of this method
+ passes on the event to all children if the 'up' point is within its saved rect.
+
+ Mouseup point
+
+
+
+ Tracks mouseover and fires the MouseOverChange event, as well as the MouseEvent event for mouse move.
+
+ Parent controls must pass this on to applicable children if necessary.
+
+
+
+
+
+ Parses a key message and fires the specific key event methods.
+
+ Key events are only sent to the control with focus.
+
+
+
+
+
+
+
+
+ WARNING: ONLY A PARENT CONTROL SHOULD CALL THIS METHOD.
+
+ This method is overridden in derived controls to handle the actual control drawing. Overridden methods should call
+ the base, draw, and recursively call this method on all child controls.
+
+
+
+
+
+ WARNING: ONLY A PARENT CONTROL SHOULD CALL THIS METHOD.
+
+ Notifies a control of changed saved draw options. This method saves its parameters in the Savedxxx properties.
+ Parent controls should override this method and recursively notify children of their new draw options, altering
+ their pClipRegion to reflect their new position in the View.
+
+ This base method also fires the DrawStateChange and ThemeChanged events.
+
+ This control's area, relative to the view area.
+ The theme applied to this control.
+ The context of this control, eg. inside a listbox.
+ The position of the View, in game window coordinates.
+
+
+
+ WARNING: ONLY A PARENT CONTROL SHOULD SET THIS PROPERTY.
+
+
+
+
+ List of XmlAttributes present on the XmlNode that was used to construct this control, if the control was loaded from XML. Otherwise, empty.
+
+
+
+
+ The XmlNode used to construct this control, if the control was loaded from XML. Otherwise, null.
+
+
+
+
+ The name that this control will be initialized with.
+
+
+
+
+ A multiline uneditable scrolling text box.
+
+
+
+
+ A single image control.
+
+
+
+
+ A button using custom images.
+
+
+
+
+ A doubly-linked list with a Dictionary index. Duplicate items are not allowed.
+ -Add is O(1)
+ -Contains is O(1)
+ -Remove is O(1)
+ -Get/set by index is O(n)
+ -Insert is O(n)
+ -RemoveAt is O(n)
+ Additionally, a cached pointer (with associated index) is kept pointing to the last used index item.
+ When looking up an item by index, the list is walked from the head, tail, or cached index pointer.
+ Thus, doing multiple operations in index order is O(1) even without an enumerator.
+
+
+
+
+
+ This method gets the node corresponding to a particular index. To get there,
+ the list is traversed from the head, tail, or cached index pointer (if valid).
+
+
+
+
+
+
+ Web browser control, using Awesomium (free license version)
+
+
+
+
+ A horizontal scrollbar.
+
+
+
+
+ Summary description for ByteCursor.
+
+
+
+
+ A checkbox with optional associated text. Uses its parent to provide the background.
+
+
+
+
+ A single-line text input box.
+
+
+
+
+ Called before render so the required size of the new target area can be calculated.
+ The returned value is the size of the desired draw area, not including outer borders and
+ style-dependent padding. This size must be less than or equal to MaximumSize in each dimension.
+
+
+
+
+
+
+ Draw this element. When this is called, the background and borders will already have been drawn, and
+ target will already be in BeginRender. This method should leave the target in render mode.
+
+
+
+
+
+
+
+ A renderer for string-only tooltips.
+
+
+
+
+ Represents an unordered set of items. Duplicates are not allowed.
+ (This is really just a dictionary which only holds keys.)
+ Should be used when a collection of non-duplicate items is needed and
+ the order doesn't matter.
+
+
+
+
+ A series of titled tabs along the top, each one having an associated control which appears
+ on the bottom when its tab is enabled.
+
+
+
+
+ A progressbar.
+
+
+
+
+ A regular pushbutton-style control.
+
+
+
+
+ Calls the non-hooked IDirect3DDevice9::BeginScene function. When rendering inside a VVS view or texture, use DxTexture.BeginRender() instead.
+
+
+
+
+
+ Calls the non-hooked IDirect3DDevice9::EndScene function. When rendering inside a VVS view or texture, use DxTexture.EndRender() instead.
+
+
+
+
+
+ Gets the current instance of the VVS bar.
+
+
+
+
+ A console containing game chat.
+
+
+
+
+ Initializes Direct3D drawing and sets the rendertarget to this texture. Calls to this method should be minimized to improve performance. DxTexture.EndRender() must be called after calling this method.
+
+
+
+
+
+
+
+
+
+ Ends Direct3D rendering and resets the rendertarget. Must be called after DxTexture.BeginRender().
+
+
+
+
+ Note: Before use, FlushSprite() may need to be called to ensure correct ordering.
+
+
+
+
+
+
+
+
+ Note: Before use, you must call BeginUserDrawOperation().
+
+
+
+
+
+
+
+
+ Note: Before use, you must call BeginUserDrawOperation().
+
+
+
+
+
+
+
+
+
+ A vertically scrolling list, containing a number of rows and columns. Every row
+ has the same number and types of columns. Each column contains a specified control type.
+
+
+
+
+ A number of images on top of each other, which always draw in the proper order.
+
+
+
+
+ A simple text display control. Uses its parent to provide the background.
+
+
+
+
+ A container for multiple controls with set locations and sizes within.
+
+
+
+
+ A dropdown list.
+
+
+
+
+ If the context menu is not visible, it is created at the specified point.
+
+
+
+
+ If the context menu is not visible, it is created at the specified point with the specified theme.
+
+
+
+
+ Provides information about an associated tooltip.
+
+
+
+
+ The HudControl that the tip is attached to.
+
+
+
+
+ Deprecated.
+ Returns the text associated with a tooltip only if the tip contains a cStringRenderer.
+
+
+
+
+ A vertical scrollbar.
+
+
+
+
+ A horizontal slider.
+
+
+
+
+ A control that allows easy access to underlying draw methods.
+
+
+
+
diff --git a/GearCycler/mainView.xml b/GearCycler/mainView.xml
new file mode 100644
index 0000000..d68a2a3
--- /dev/null
+++ b/GearCycler/mainView.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file