diff --git a/MosswartMassacre/MosswartMassacre.csproj b/MosswartMassacre/MosswartMassacre.csproj
index b200028..b2d0613 100644
--- a/MosswartMassacre/MosswartMassacre.csproj
+++ b/MosswartMassacre/MosswartMassacre.csproj
@@ -29,7 +29,7 @@
pdbonly
true
bin\Release\
- TRACE;VVS_REFERENCED;DECAL_INTEROP
+ TRACE
prompt
4
@@ -175,9 +175,14 @@
True
Resources.resx
-
-
+
+
+
+
+
+
+
diff --git a/MosswartMassacre/NavRoute.cs b/MosswartMassacre/NavRoute.cs
index 6f3ccfa..f1d0fa3 100644
--- a/MosswartMassacre/NavRoute.cs
+++ b/MosswartMassacre/NavRoute.cs
@@ -48,23 +48,25 @@ namespace MosswartMassacre
return false;
}
- PluginCore.WriteToChat($"Navigation: Loading {FileName}...");
+ PluginCore.WriteToChat($"[NavRoute] Loading {FileName}...");
using (StreamReader sr = File.OpenText(FilePath))
{
// Read header
string header = sr.ReadLine();
+ PluginCore.WriteToChat($"[NavRoute] Header: '{header}'");
if (string.IsNullOrEmpty(header) || !header.StartsWith("uTank2 NAV"))
{
- PluginCore.WriteToChat($"Navigation: Invalid file format - {FileName}");
+ PluginCore.WriteToChat($"Invalid nav file format: {FileName} (header: {header})");
return false;
}
// Read nav type
string navTypeLine = sr.ReadLine();
+ PluginCore.WriteToChat($"[NavRoute] Nav type line: '{navTypeLine}'");
if (string.IsNullOrEmpty(navTypeLine) || !int.TryParse(navTypeLine.Trim(), out int navType))
{
- PluginCore.WriteToChat($"Navigation: Failed to parse route type - {FileName}");
+ PluginCore.WriteToChat($"Could not parse nav type: {FileName} (line: '{navTypeLine}')");
return false;
}
@@ -88,43 +90,46 @@ namespace MosswartMassacre
break;
default:
navTypeDescription = $"Unknown ({navType})";
- PluginCore.WriteToChat($"Navigation: Unknown route type {navType} in {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] WARNING: Unknown nav type {navType} in {FileName}");
break;
}
+
+ PluginCore.WriteToChat($"[NavRoute] Nav type: {navTypeDescription}");
// Handle target nav (type 3) - follows a specific player/object
if (navType == 3)
{
if (sr.EndOfStream)
{
- PluginCore.WriteToChat($"Navigation: Target route file is empty - {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] Target nav file is empty: {FileName}");
return false;
}
string targetName = sr.ReadLine();
if (sr.EndOfStream)
{
- PluginCore.WriteToChat($"Navigation: Target route missing target ID - {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] Target nav missing target ID: {FileName}");
return false;
}
string targetIdLine = sr.ReadLine();
- PluginCore.WriteToChat($"Navigation: Target route '{targetName}' cannot be visualized");
+ PluginCore.WriteToChat($"[NavRoute] Target navigation for '{targetName}' (ID: {targetIdLine}) - No visual representation available");
return true; // Successfully loaded but can't visualize
}
// Read record count
string recordCountLine = sr.ReadLine();
+ PluginCore.WriteToChat($"[NavRoute] Record count line: '{recordCountLine}'");
if (string.IsNullOrEmpty(recordCountLine) || !int.TryParse(recordCountLine.Trim(), out int recordCount))
{
- PluginCore.WriteToChat($"Navigation: Failed to parse waypoint count - {FileName}");
+ PluginCore.WriteToChat($"Could not parse record count: {FileName} (line: '{recordCountLine}')");
return false;
}
if (recordCount <= 0 || recordCount > 10000) // Sanity check
{
- PluginCore.WriteToChat($"Navigation: Invalid waypoint count {recordCount} - {FileName}");
+ PluginCore.WriteToChat($"Invalid record count: {recordCount} in {FileName}");
return false;
}
@@ -133,14 +138,33 @@ namespace MosswartMassacre
while (!sr.EndOfStream && waypointsRead < recordCount)
{
+ PluginCore.WriteToChat($"[NavRoute] Reading waypoint {waypointsRead + 1}/{recordCount}");
+
// Read waypoint type
string waypointTypeLine = sr.ReadLine();
+ PluginCore.WriteToChat($"[NavRoute] Waypoint type line: '{waypointTypeLine}'");
if (string.IsNullOrEmpty(waypointTypeLine) || !int.TryParse(waypointTypeLine.Trim(), out int waypointType))
{
- PluginCore.WriteToChat($"Navigation: Failed to parse waypoint {waypointsRead + 1} in {FileName}");
+ PluginCore.WriteToChat($"Could not parse waypoint type at waypoint {waypointsRead}: '{waypointTypeLine}'");
break; // Skip this waypoint, don't fail entirely
}
+
+ string waypointTypeDesc = waypointType switch
+ {
+ 0 => "Point",
+ 1 => "Portal",
+ 2 => "Recall",
+ 3 => "Pause",
+ 4 => "ChatCommand",
+ 5 => "OpenVendor",
+ 6 => "Portal2",
+ 7 => "UseNPC",
+ 8 => "Checkpoint",
+ 9 => "Jump",
+ _ => $"Unknown ({waypointType})"
+ };
+ PluginCore.WriteToChat($"[NavRoute] Waypoint {waypointsRead + 1}: Type {waypointType} ({waypointTypeDesc})");
// Read coordinates (all waypoint types have EW, NS, Z, Unknown)
string ewLine = sr.ReadLine();
@@ -148,9 +172,11 @@ namespace MosswartMassacre
string zLine = sr.ReadLine();
string unknownLine = sr.ReadLine(); // Unknown value (always 0)
+ PluginCore.WriteToChat($"[NavRoute] Coordinates: EW={ewLine}, NS={nsLine}, Z={zLine}, Unknown={unknownLine}");
+
if (string.IsNullOrEmpty(ewLine) || string.IsNullOrEmpty(nsLine) || string.IsNullOrEmpty(zLine) || string.IsNullOrEmpty(unknownLine))
{
- PluginCore.WriteToChat($"Navigation: Missing coordinates at waypoint {waypointsRead + 1} in {FileName}");
+ PluginCore.WriteToChat($"Missing coordinate lines at waypoint {waypointsRead}");
break;
}
@@ -158,7 +184,7 @@ namespace MosswartMassacre
!double.TryParse(nsLine.Trim(), out double ns) ||
!double.TryParse(zLine.Trim(), out double z))
{
- PluginCore.WriteToChat($"Navigation: Invalid coordinates at waypoint {waypointsRead + 1} in {FileName}");
+ PluginCore.WriteToChat($"Could not parse coordinates at waypoint {waypointsRead}: EW={ewLine}, NS={nsLine}, Z={zLine}");
break; // Skip this waypoint
}
@@ -178,18 +204,17 @@ namespace MosswartMassacre
// Skip additional data based on waypoint type
if (!SkipWaypointData(sr, waypointType))
{
- PluginCore.WriteToChat($"Navigation: Failed to parse waypoint {waypointsRead + 1} data in {FileName}");
+ PluginCore.WriteToChat($"Failed to skip waypoint data for type {waypointType} at waypoint {waypointsRead}");
break; // Don't continue if we can't parse properly
}
}
+ PluginCore.WriteToChat($"[NavRoute] Loaded {waypoints.Count} waypoints from {FileName}");
+
+ // Debug: Show if we have waypoints to visualize
if (waypoints.Count > 0)
{
- PluginCore.WriteToChat($"Navigation: Loaded {FileName} ({waypoints.Count} waypoints)");
- }
- else
- {
- PluginCore.WriteToChat($"Navigation: No valid waypoints found in {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] Route ready for visualization with {waypoints.Count} waypoints");
}
return waypoints.Count > 0;
@@ -197,7 +222,7 @@ namespace MosswartMassacre
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"Navigation: Error loading {FileName} - {ex.Message}");
+ PluginCore.WriteToChat($"[NavRoute] Error loading nav file {FileName}: {ex.Message}");
return false;
}
}
@@ -256,31 +281,39 @@ namespace MosswartMassacre
sr.ReadLine(); // Milliseconds
break;
default:
- // Unknown waypoint type - skip silently
+ PluginCore.WriteToChat($"[NavRoute] Unknown waypoint type: {waypointType}");
break;
}
return true;
}
- catch
+ catch (Exception ex)
{
- // Silently handle parsing errors
+ PluginCore.WriteToChat($"[NavRoute] Error skipping waypoint data: {ex.Message}");
return false;
}
}
public void Show()
{
- if (isVisible) return;
+ PluginCore.WriteToChat($"[NavRoute] Show() called for {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] isVisible: {isVisible}, waypoints.Count: {waypoints.Count}");
+
+ if (isVisible)
+ {
+ PluginCore.WriteToChat($"[NavRoute] Route {FileName} is already visible, skipping");
+ return;
+ }
if (waypoints.Count == 0)
{
- PluginCore.WriteToChat($"Navigation: No waypoints to visualize in {FileName}");
+ PluginCore.WriteToChat($"[NavRoute] Route {FileName} has no waypoints to visualize");
return;
}
+ PluginCore.WriteToChat($"[NavRoute] Creating line objects for {FileName}...");
CreateLineObjects();
isVisible = true;
- PluginCore.WriteToChat($"Navigation: Showing {FileName} ({waypoints.Count} waypoints)");
+ PluginCore.WriteToChat($"[NavRoute] Route {FileName} visualization complete - isVisible: {isVisible}");
}
public void Hide()
@@ -289,28 +322,34 @@ namespace MosswartMassacre
ClearRoute();
isVisible = false;
- PluginCore.WriteToChat($"Navigation: Hidden {FileName}");
+ PluginCore.WriteToChat($"Hidden route: {FileName}");
}
private void CreateLineObjects()
{
try
{
+ PluginCore.WriteToChat($"[NavRoute] CreateLineObjects() starting for {FileName}");
+
// Check D3DService availability
if (CoreManager.Current?.D3DService == null)
{
- PluginCore.WriteToChat($"Navigation: 3D service unavailable");
+ PluginCore.WriteToChat($"[NavRoute] ERROR: D3DService is null!");
return;
}
// Limit the number of lines to prevent lag
int maxLines = Math.Min(waypoints.Count - 1, 500); // Max 500 lines
+ PluginCore.WriteToChat($"[NavRoute] Creating {maxLines} navigation lines from {waypoints.Count} waypoints...");
+
int linesCreated = 0;
for (int i = 1; i <= maxLines; i++)
{
var current = waypoints[i];
var previous = waypoints[i - 1];
+
+ PluginCore.WriteToChat($"[NavRoute] Creating line {i}: From ({previous.NS:F2}, {previous.EW:F2}, {previous.Z:F2}) to ({current.NS:F2}, {current.EW:F2}, {current.Z:F2})");
if (CreateLineBetweenWaypoints(previous, current))
{
@@ -324,14 +363,18 @@ namespace MosswartMassacre
}
}
+ PluginCore.WriteToChat($"[NavRoute] Successfully created {linesCreated} D3D line objects out of {maxLines} attempted");
+ PluginCore.WriteToChat($"[NavRoute] Total D3D objects in list: {lineObjects.Count}");
+
if (waypoints.Count > 501)
{
- PluginCore.WriteToChat($"Navigation: Large route - showing {maxLines} of {waypoints.Count} segments");
+ PluginCore.WriteToChat($"[NavRoute] Route has {waypoints.Count} waypoints, showing first {maxLines} segments");
}
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"Navigation: Error creating visualization - {ex.Message}");
+ PluginCore.WriteToChat($"[NavRoute] Error creating line objects: {ex.Message}");
+ PluginCore.WriteToChat($"[NavRoute] Stack trace: {ex.StackTrace}");
}
}
@@ -346,20 +389,34 @@ namespace MosswartMassacre
Math.Pow((to.Z - from.Z) * 240, 2)
);
- if (distance <= 0) return false;
+ if (distance <= 0)
+ {
+ PluginCore.WriteToChat($"[NavRoute] Skipping line with zero distance");
+ return false;
+ }
+
+ PluginCore.WriteToChat($"[NavRoute] Creating D3D line object with distance: {distance:F2}");
// Create D3D line object
var lineObj = CoreManager.Current.D3DService.NewD3DObj();
- if (lineObj == null) return false;
+ if (lineObj == null)
+ {
+ PluginCore.WriteToChat($"[NavRoute] ERROR: Failed to create D3D object!");
+ return false;
+ }
+
+ PluginCore.WriteToChat($"[NavRoute] D3D object created successfully");
lineObj.SetShape(D3DShape.Cube);
lineObj.Color = routeColor.ToArgb();
+ PluginCore.WriteToChat($"[NavRoute] Set shape and color (ARGB: {routeColor.ToArgb()})");
// Position at midpoint between waypoints
float midNS = (float)(from.NS + to.NS) / 2;
float midEW = (float)(from.EW + to.EW) / 2;
float midZ = (float)((from.Z + to.Z) * 120) + 0.1f; // Slightly higher than UtilityBelt
+ PluginCore.WriteToChat($"[NavRoute] Anchoring at: NS={midNS:F2}, EW={midEW:F2}, Z={midZ:F2}");
lineObj.Anchor(midNS, midEW, midZ);
// Orient toward destination
@@ -367,20 +424,28 @@ namespace MosswartMassacre
float orientEW = (float)from.EW;
float orientZ = (float)(from.Z * 240) + 0.1f;
+ PluginCore.WriteToChat($"[NavRoute] Orienting to: NS={orientNS:F2}, EW={orientEW:F2}, Z={orientZ:F2}");
lineObj.OrientToCoords(orientNS, orientEW, orientZ, true);
// Scale to create line effect
lineObj.ScaleX = 0.3f; // Slightly thicker than UtilityBelt
lineObj.ScaleZ = 0.3f;
lineObj.ScaleY = (float)distance;
+
+ PluginCore.WriteToChat($"[NavRoute] Set scale: X={lineObj.ScaleX}, Y={lineObj.ScaleY:F2}, Z={lineObj.ScaleZ}");
lineObj.Visible = true;
+ PluginCore.WriteToChat($"[NavRoute] Set visible to true");
+
lineObjects.Add(lineObj);
+ PluginCore.WriteToChat($"[NavRoute] Added line object to list (total: {lineObjects.Count})");
return true;
}
- catch
+ catch (Exception ex)
{
+ PluginCore.WriteToChat($"[NavRoute] Error creating line: {ex.Message}");
+ PluginCore.WriteToChat($"[NavRoute] Stack trace: {ex.StackTrace}");
return false;
}
}
diff --git a/MosswartMassacre/NavVisualization.cs b/MosswartMassacre/NavVisualization.cs
index 824462f..3180d56 100644
--- a/MosswartMassacre/NavVisualization.cs
+++ b/MosswartMassacre/NavVisualization.cs
@@ -39,6 +39,7 @@ namespace MosswartMassacre
if (!string.IsNullOrEmpty(PluginSettings.Instance?.VTankProfilesPath))
{
vtankProfilesDirectory = PluginSettings.Instance.VTankProfilesPath;
+ PluginCore.WriteToChat($"[NavViz] Using configured VTank profiles path: {vtankProfilesDirectory}");
return;
}
@@ -53,17 +54,20 @@ namespace MosswartMassacre
if (!string.IsNullOrEmpty(profilePath))
{
vtankProfilesDirectory = profilePath;
+ PluginCore.WriteToChat($"[NavViz] Found VTank profiles from registry: {vtankProfilesDirectory}");
return;
}
}
}
- catch
+ catch (Exception regEx)
{
+ PluginCore.WriteToChat($"[NavViz] Registry lookup failed: {regEx.Message}");
}
// Fall back to default path
vtankProfilesDirectory = defaultPath;
- // Using default path - user can configure in Settings if needed
+ PluginCore.WriteToChat($"[NavViz] Using default VTank path: {vtankProfilesDirectory}");
+ PluginCore.WriteToChat($"[NavViz] If this is wrong, configure the correct path in Settings tab.");
}
catch (Exception ex)
{
@@ -72,10 +76,6 @@ namespace MosswartMassacre
}
}
- ///
- /// Scan VTank directory for .nav files and populate available routes list
- /// Filters out follow files and temporary files, sorts alphabetically
- ///
public void RefreshNavFileList()
{
// Re-initialize directory in case settings changed
@@ -83,26 +83,43 @@ namespace MosswartMassacre
availableNavFiles.Clear();
+ PluginCore.WriteToChat($"[NavViz] Refreshing nav files from: {vtankProfilesDirectory}");
if (string.IsNullOrEmpty(vtankProfilesDirectory))
{
- PluginCore.WriteToChat("VTank directory not configured. Set path in Settings tab.");
+ PluginCore.WriteToChat("[NavViz] No VTank directory set");
return;
}
if (!Directory.Exists(vtankProfilesDirectory))
{
- PluginCore.WriteToChat($"VTank directory not found: {vtankProfilesDirectory}");
+ PluginCore.WriteToChat($"[NavViz] Directory does not exist: {vtankProfilesDirectory}");
return;
}
try
{
- // Get all files and filter for .nav files only, excluding follow/temporary files
+ // Get ALL files first for debugging
var allFiles = Directory.GetFiles(vtankProfilesDirectory);
+ PluginCore.WriteToChat($"[NavViz] Directory contents ({allFiles.Length} files):");
+ foreach (var file in allFiles.Take(10)) // Show first 10 files
+ {
+ PluginCore.WriteToChat($" - {Path.GetFileName(file)}");
+ }
+
+ // Filter for .nav files ONLY and exclude follow files
var navFiles = allFiles
- .Where(file => Path.GetExtension(file).Equals(".nav", StringComparison.OrdinalIgnoreCase))
- .Select(file => Path.GetFileNameWithoutExtension(file))
+ .Where(file => {
+ var ext = Path.GetExtension(file);
+ var isNav = ext.Equals(".nav", StringComparison.OrdinalIgnoreCase);
+ PluginCore.WriteToChat($"[NavViz] File: {Path.GetFileName(file)} - Extension: '{ext}' - IsNav: {isNav}");
+ return isNav;
+ })
+ .Select(file => {
+ var name = Path.GetFileNameWithoutExtension(file);
+ PluginCore.WriteToChat($"[NavViz] Nav file name: {name}");
+ return name;
+ })
.Where(name => !string.IsNullOrEmpty(name) &&
!name.StartsWith("follow", StringComparison.OrdinalIgnoreCase) &&
!name.StartsWith("--", StringComparison.OrdinalIgnoreCase))
@@ -111,24 +128,14 @@ namespace MosswartMassacre
availableNavFiles.AddRange(navFiles);
- // Only report summary - no need to spam chat with every file
- if (navFiles.Count > 0)
- {
- PluginCore.WriteToChat($"Navigation: Found {navFiles.Count} route files");
- }
+ PluginCore.WriteToChat($"[NavViz] Found {navFiles.Count} .nav files: {string.Join(", ", navFiles)}");
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"Navigation: Error scanning files - {ex.Message}");
+ PluginCore.WriteToChat($"[NavViz] Error refreshing nav files: {ex.Message}");
}
}
- ///
- /// Load a specific navigation route file for visualization
- /// Clears current route if "None" specified, otherwise loads .nav file
- ///
- /// Name of .nav file (without extension) or "None"
- /// True if route loaded successfully, false otherwise
public bool LoadRoute(string navFileName)
{
try
@@ -142,6 +149,7 @@ namespace MosswartMassacre
if (string.IsNullOrEmpty(navFileName) || navFileName == "None")
{
+ PluginCore.WriteToChat("[NavViz] Route cleared");
RouteChanged?.Invoke(this, EventArgs.Empty);
return true;
}
@@ -150,7 +158,7 @@ namespace MosswartMassacre
if (!File.Exists(fullPath))
{
- PluginCore.WriteToChat($"Navigation file '{navFileName}' not found");
+ PluginCore.WriteToChat($"[NavViz] Nav file not found: {navFileName}");
return false;
}
@@ -164,35 +172,41 @@ namespace MosswartMassacre
}
// Show route if visualization is enabled
+ PluginCore.WriteToChat($"[NavViz] LoadRoute: IsEnabled = {IsEnabled}");
if (IsEnabled)
{
+ PluginCore.WriteToChat($"[NavViz] Calling Show() for route {navFileName}");
currentRoute.Show();
}
+ else
+ {
+ PluginCore.WriteToChat($"[NavViz] Visualization disabled, not showing route");
+ }
RouteChanged?.Invoke(this, EventArgs.Empty);
return true;
}
catch (Exception ex)
{
- PluginCore.WriteToChat($"Navigation: Failed to load '{navFileName}' - {ex.Message}");
+ PluginCore.WriteToChat($"[NavViz] Error loading route {navFileName}: {ex.Message}");
return false;
}
}
- ///
- /// Enable or disable navigation route visualization in 3D world
- /// Shows/hides the currently loaded route based on enabled state
- ///
- /// True to show route lines, false to hide
public void SetEnabled(bool enabled)
{
- // No change needed if already in desired state
- if (IsEnabled == enabled) return;
+ PluginCore.WriteToChat($"[NavViz] SetEnabled called: current={IsEnabled}, new={enabled}");
+ if (IsEnabled == enabled)
+ {
+ PluginCore.WriteToChat($"[NavViz] SetEnabled: no change needed");
+ return;
+ }
IsEnabled = enabled;
if (currentRoute != null)
{
+ PluginCore.WriteToChat($"[NavViz] SetEnabled: currentRoute exists, {(enabled ? "showing" : "hiding")}");
if (enabled)
{
currentRoute.Show();
@@ -204,9 +218,10 @@ namespace MosswartMassacre
}
else
{
+ PluginCore.WriteToChat($"[NavViz] SetEnabled: no currentRoute to {(enabled ? "show" : "hide")}");
}
- PluginCore.WriteToChat($"Navigation visualization {(enabled ? "enabled" : "disabled")}");
+ PluginCore.WriteToChat($"[NavViz] Navigation visualization {(enabled ? "enabled" : "disabled")}");
}
public void ToggleEnabled()
diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs
index cacdeeb..aa05bbb 100644
--- a/MosswartMassacre/PluginCore.cs
+++ b/MosswartMassacre/PluginCore.cs
@@ -28,45 +28,6 @@ namespace MosswartMassacre
internal static DateTime statsStartTime = DateTime.Now;
internal static Timer updateTimer;
public static bool RareMetaEnabled { get; set; } = true;
-
- // VVS View Management
- private static class ViewManager
- {
- public static void ViewInit()
- {
- Views.VVSTabbedMainView.ViewInit();
- }
-
- public static void ViewDestroy()
- {
- Views.VVSTabbedMainView.ViewDestroy();
- }
-
- public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour)
- {
- Views.VVSTabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
- }
-
- public static void UpdateElapsedTime(TimeSpan elapsed)
- {
- Views.VVSTabbedMainView.UpdateElapsedTime(elapsed);
- }
-
- public static void UpdateRareCount(int rareCount)
- {
- Views.VVSTabbedMainView.UpdateRareCount(rareCount);
- }
-
- public static void SetRareMetaToggleState(bool enabled)
- {
- Views.VVSTabbedMainView.SetRareMetaToggleState(enabled);
- }
-
- public static void RefreshSettingsFromConfig()
- {
- Views.VVSTabbedMainView.RefreshSettingsFromConfig();
- }
- }
public static bool RemoteCommandsEnabled { get; set; } = false;
public static bool HttpServerEnabled { get; set; } = false;
public static string CharTag { get; set; } = "";
@@ -102,7 +63,7 @@ namespace MosswartMassacre
updateTimer.Start();
// Initialize the view (UI) - use tabbed interface by default
- ViewManager.ViewInit();
+ TabbedMainView.ViewInit();
// Enable TLS1.2
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
@@ -152,7 +113,7 @@ namespace MosswartMassacre
}
// Clean up the view
- ViewManager.ViewDestroy();
+ TabbedMainView.ViewDestroy();
//Disable vtank interface
vTank.Disable();
// sluta lyssna på commands
@@ -188,8 +149,8 @@ namespace MosswartMassacre
HttpServerEnabled = PluginSettings.Instance.HttpServerEnabled;
TelemetryEnabled = PluginSettings.Instance.TelemetryEnabled;
CharTag = PluginSettings.Instance.CharTag;
- ViewManager.SetRareMetaToggleState(RareMetaEnabled);
- ViewManager.RefreshSettingsFromConfig(); // Refresh all UI settings after loading
+ TabbedMainView.SetRareMetaToggleState(RareMetaEnabled);
+ TabbedMainView.RefreshSettingsFromConfig(); // Refresh all UI settings after loading
if (TelemetryEnabled)
Telemetry.Start();
if (WebSocketEnabled)
@@ -277,13 +238,13 @@ namespace MosswartMassacre
totalKills++;
lastKillTime = DateTime.Now;
CalculateKillsPerInterval();
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
+ TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
}
if (IsRareDiscoveryMessage(e.Text, out string rareText))
{
rareCount++;
- ViewManager.UpdateRareCount(rareCount);
+ TabbedMainView.UpdateRareCount(rareCount);
if (RareMetaEnabled)
{
@@ -363,11 +324,11 @@ namespace MosswartMassacre
{
// Update the elapsed time
TimeSpan elapsed = DateTime.Now - statsStartTime;
- ViewManager.UpdateElapsedTime(elapsed);
+ TabbedMainView.UpdateElapsedTime(elapsed);
// Recalculate kill rates
CalculateKillsPerInterval();
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
+ TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
}
catch (Exception ex)
{
@@ -465,14 +426,14 @@ namespace MosswartMassacre
killsPerHour = 0;
WriteToChat("Stats have been reset.");
- ViewManager.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
- ViewManager.UpdateRareCount(rareCount);
+ TabbedMainView.UpdateKillStats(totalKills, killsPer5Min, killsPerHour);
+ TabbedMainView.UpdateRareCount(rareCount);
}
public static void ToggleRareMeta()
{
PluginSettings.Instance.RareMetaEnabled = !PluginSettings.Instance.RareMetaEnabled;
RareMetaEnabled = PluginSettings.Instance.RareMetaEnabled;
- ViewManager.SetRareMetaToggleState(RareMetaEnabled);
+ TabbedMainView.SetRareMetaToggleState(RareMetaEnabled);
}
[DllImport("Decal.dll")]
@@ -602,7 +563,7 @@ namespace MosswartMassacre
case "meta":
RareMetaEnabled = !RareMetaEnabled;
WriteToChat($"Rare meta state is now {(RareMetaEnabled ? "ON" : "OFF")}");
- ViewManager.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI
+ TabbedMainView.SetRareMetaToggleState(RareMetaEnabled); // <-- sync the UI
break;
case "http":
diff --git a/MosswartMassacre/Properties/AssemblyInfo.cs b/MosswartMassacre/Properties/AssemblyInfo.cs
index b7482f9..e084d4c 100644
--- a/MosswartMassacre/Properties/AssemblyInfo.cs
+++ b/MosswartMassacre/Properties/AssemblyInfo.cs
@@ -26,5 +26,5 @@ using System.Runtime.InteropServices;
// Minor Version
// Build Number
// Revision
-[assembly: AssemblyVersion("3.0.1.0")]
-[assembly: AssemblyFileVersion("3.0.1.0")]
\ No newline at end of file
+[assembly: AssemblyVersion("3.0.0.6")]
+[assembly: AssemblyFileVersion("3.0.0.6")]
\ No newline at end of file
diff --git a/MosswartMassacre/ViewSystemSelector.cs b/MosswartMassacre/ViewSystemSelector.cs
new file mode 100644
index 0000000..5e75b7a
--- /dev/null
+++ b/MosswartMassacre/ViewSystemSelector.cs
@@ -0,0 +1,262 @@
+///////////////////////////////////////////////////////////////////////////////
+//File: ViewSystemSelector.cs
+//
+//Description: Contains the MyClasses.MetaViewWrappers.ViewSystemSelector class,
+// which is used to determine whether the Virindi View Service is enabled.
+// As with all the VVS wrappers, the VVS_REFERENCED compilation symbol must be
+// defined for the VVS code to be compiled. Otherwise, only Decal views are used.
+//
+//References required:
+// VirindiViewService (if VVS_REFERENCED is defined)
+// Decal.Adapter
+// Decal.Interop.Core
+//
+//This file is Copyright (c) 2009 VirindiPlugins
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+
+#if METAVIEW_PUBLIC_NS
+namespace MetaViewWrappers
+#else
+namespace MyClasses.MetaViewWrappers
+#endif
+{
+ internal static class ViewSystemSelector
+ {
+ public enum eViewSystem
+ {
+ DecalInject,
+ VirindiViewService,
+ }
+
+
+ ///////////////////////////////System presence detection///////////////////////////////
+
+ public static bool IsPresent(Decal.Adapter.Wrappers.PluginHost pHost, eViewSystem VSystem)
+ {
+ switch (VSystem)
+ {
+ case eViewSystem.DecalInject:
+ return true;
+ case eViewSystem.VirindiViewService:
+ return VirindiViewsPresent(pHost);
+ default:
+ return false;
+ }
+ }
+ static bool VirindiViewsPresent(Decal.Adapter.Wrappers.PluginHost pHost)
+ {
+#if VVS_REFERENCED
+ System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
+
+ foreach (System.Reflection.Assembly a in asms)
+ {
+ AssemblyName nmm = a.GetName();
+ if ((nmm.Name == "VirindiViewService") && (nmm.Version >= new System.Version("1.0.0.37")))
+ {
+ try
+ {
+ return Curtain_VVS_Running();
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+#else
+ return false;
+#endif
+ }
+ public static bool VirindiViewsPresent(Decal.Adapter.Wrappers.PluginHost pHost, Version minver)
+ {
+#if VVS_REFERENCED
+ System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
+
+ foreach (System.Reflection.Assembly a in asms)
+ {
+ AssemblyName nm = a.GetName();
+ if ((nm.Name == "VirindiViewService") && (nm.Version >= minver))
+ {
+ try
+ {
+ return Curtain_VVS_Running();
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+#else
+ return false;
+#endif
+ }
+
+#if VVS_REFERENCED
+ static bool Curtain_VVS_Running()
+ {
+ return VirindiViewService.Service.Running;
+ }
+#endif
+
+ ///////////////////////////////CreateViewResource///////////////////////////////
+
+ public static IView CreateViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource)
+ {
+#if VVS_REFERENCED
+ if (IsPresent(pHost, eViewSystem.VirindiViewService))
+ return CreateViewResource(pHost, pXMLResource, eViewSystem.VirindiViewService);
+ else
+#endif
+ return CreateViewResource(pHost, pXMLResource, eViewSystem.DecalInject);
+ }
+ public static IView CreateViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource, eViewSystem VSystem)
+ {
+ if (!IsPresent(pHost, VSystem)) return null;
+ switch (VSystem)
+ {
+ case eViewSystem.DecalInject:
+ return CreateDecalViewResource(pHost, pXMLResource);
+ case eViewSystem.VirindiViewService:
+#if VVS_REFERENCED
+ return CreateMyHudViewResource(pHost, pXMLResource);
+#else
+ break;
+#endif
+ }
+ return null;
+ }
+ static IView CreateDecalViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource)
+ {
+ IView ret = new DecalControls.View();
+ ret.Initialize(pHost, pXMLResource);
+ return ret;
+ }
+
+#if VVS_REFERENCED
+ static IView CreateMyHudViewResource(Decal.Adapter.Wrappers.PluginHost pHost, string pXMLResource)
+ {
+ IView ret = new VirindiViewServiceHudControls.View();
+ ret.Initialize(pHost, pXMLResource);
+ return ret;
+ }
+#endif
+
+
+ ///////////////////////////////CreateViewXML///////////////////////////////
+
+ public static IView CreateViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML)
+ {
+#if VVS_REFERENCED
+ if (IsPresent(pHost, eViewSystem.VirindiViewService))
+ return CreateViewXML(pHost, pXML, eViewSystem.VirindiViewService);
+ else
+#endif
+ return CreateViewXML(pHost, pXML, eViewSystem.DecalInject);
+ }
+
+ public static IView CreateViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML, eViewSystem VSystem)
+ {
+ if (!IsPresent(pHost, VSystem)) return null;
+ switch (VSystem)
+ {
+ case eViewSystem.DecalInject:
+ return CreateDecalViewXML(pHost, pXML);
+ case eViewSystem.VirindiViewService:
+#if VVS_REFERENCED
+ return CreateMyHudViewXML(pHost, pXML);
+#else
+ break;
+#endif
+ }
+ return null;
+ }
+ static IView CreateDecalViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML)
+ {
+ IView ret = new DecalControls.View();
+ ret.InitializeRawXML(pHost, pXML);
+ return ret;
+ }
+
+#if VVS_REFERENCED
+ static IView CreateMyHudViewXML(Decal.Adapter.Wrappers.PluginHost pHost, string pXML)
+ {
+ IView ret = new VirindiViewServiceHudControls.View();
+ ret.InitializeRawXML(pHost, pXML);
+ return ret;
+ }
+#endif
+
+
+ ///////////////////////////////HasChatOpen///////////////////////////////
+
+ public static bool AnySystemHasChatOpen(Decal.Adapter.Wrappers.PluginHost pHost)
+ {
+ if (IsPresent(pHost, eViewSystem.VirindiViewService))
+ if (HasChatOpen_VirindiViews()) return true;
+ if (pHost.Actions.ChatState) return true;
+ return false;
+ }
+
+ static bool HasChatOpen_VirindiViews()
+ {
+#if VVS_REFERENCED
+ if (VirindiViewService.HudView.FocusControl != null)
+ {
+ if (VirindiViewService.HudView.FocusControl.GetType() == typeof(VirindiViewService.Controls.HudTextBox))
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif
+ }
+
+ public delegate void delConditionalSplit(object data);
+ public static void ViewConditionalSplit(IView v, delConditionalSplit onDecal, delConditionalSplit onVVS, object data)
+ {
+ Type vtype = v.GetType();
+
+#if VVS_REFERENCED
+ if (vtype == typeof(VirindiViewServiceHudControls.View))
+ {
+ if (onVVS != null)
+ onVVS(data);
+ }
+#endif
+
+ if (vtype == typeof(DecalControls.View))
+ {
+ if (onDecal != null)
+ onDecal(data);
+ }
+ }
+ }
+}
diff --git a/MosswartMassacre/ViewXML/mainViewTabbed.xml b/MosswartMassacre/ViewXML/mainViewTabbed.xml
index 2ce4ff4..22303ae 100644
--- a/MosswartMassacre/ViewXML/mainViewTabbed.xml
+++ b/MosswartMassacre/ViewXML/mainViewTabbed.xml
@@ -25,19 +25,19 @@
-
+
-
+
-
+
-
+
-
+
@@ -46,7 +46,7 @@
-
+
@@ -90,10 +90,10 @@
-
+
-
+
@@ -101,14 +101,14 @@
-
+
-
+
-
-
+
+
diff --git a/MosswartMassacre/Views/BaseView.cs b/MosswartMassacre/Views/BaseView.cs
new file mode 100644
index 0000000..2020be7
--- /dev/null
+++ b/MosswartMassacre/Views/BaseView.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Drawing;
+using System.IO;
+using System.Runtime.InteropServices;
+using MyClasses.MetaViewWrappers;
+
+namespace MosswartMassacre.Views
+{
+ public class BaseView : IDisposable
+ {
+ #region Windows API for boundary checking
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public int Width { get { return Right - Left; } }
+ public int Height { get { return Bottom - Top; } }
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
+ #endregion
+
+ internal IView view;
+ protected PluginCore pluginCore;
+
+ public BaseView(PluginCore core)
+ {
+ pluginCore = core;
+ }
+
+ protected void CreateFromXMLResource(string resourcePath)
+ {
+ try
+ {
+ view = ViewSystemSelector.CreateViewResource(PluginCore.MyHost, resourcePath);
+ // Note: IView doesn't have VisibleChanged event, so we'll check bounds manually when needed
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error creating view from {resourcePath}: {ex.Message}");
+ }
+ }
+
+ protected void KeepWindowInBounds()
+ {
+ try
+ {
+ RECT rect = new RECT();
+ IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero;
+
+ if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect))
+ {
+ Point currentLocation = view.Location;
+ Size viewSize = view.Size;
+
+ // Check if window is outside right boundary
+ if (currentLocation.X + viewSize.Width > rect.Width)
+ {
+ currentLocation.X = rect.Width - viewSize.Width;
+ }
+ // Check if window is outside left boundary
+ else if (currentLocation.X < 0)
+ {
+ currentLocation.X = 20;
+ }
+
+ // Check if window is outside bottom boundary
+ if (currentLocation.Y + viewSize.Height > rect.Height)
+ {
+ currentLocation.Y = rect.Height - viewSize.Height;
+ }
+ // Check if window is outside top boundary
+ else if (currentLocation.Y < 0)
+ {
+ currentLocation.Y = 20;
+ }
+
+ // Only update location if it changed
+ if (currentLocation != view.Location)
+ {
+ view.Location = currentLocation;
+ }
+ }
+ }
+ catch
+ {
+ // Don't spam chat with boundary check errors, just log silently
+ }
+ }
+
+ protected virtual void SaveWindowPosition()
+ {
+ // Override in derived classes to save position to settings
+ }
+
+ protected virtual void RestoreWindowPosition()
+ {
+ // Override in derived classes to restore position from settings
+ }
+
+ public virtual void Initialize()
+ {
+ try
+ {
+ RestoreWindowPosition();
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error initializing view: {ex.Message}");
+ }
+ }
+
+ public virtual void Show()
+ {
+ if (view != null)
+ {
+ view.Visible = true;
+ }
+ }
+
+ public virtual void Hide()
+ {
+ if (view != null)
+ {
+ view.Visible = false;
+ }
+ }
+
+ public virtual void Toggle()
+ {
+ if (view != null)
+ {
+ view.Visible = !view.Visible;
+ }
+ }
+
+ #region IDisposable Support
+ private bool disposedValue = false;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ try
+ {
+ SaveWindowPosition();
+
+ if (view != null)
+ {
+ view.Dispose();
+ }
+ view = null;
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error disposing view: {ex.Message}");
+ }
+ }
+ disposedValue = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/MosswartMassacre/Views/TabbedMainView.cs b/MosswartMassacre/Views/TabbedMainView.cs
new file mode 100644
index 0000000..29f429f
--- /dev/null
+++ b/MosswartMassacre/Views/TabbedMainView.cs
@@ -0,0 +1,794 @@
+using System;
+using System.Drawing;
+using System.Timers;
+using MyClasses.MetaViewWrappers;
+
+namespace MosswartMassacre.Views
+{
+ internal class TabbedMainView : BaseView
+ {
+ private static TabbedMainView instance;
+
+ // Main tab controls (existing functionality)
+ private IStaticText lblTotalKills;
+ private IStaticText lblKillsPer5Min;
+ private IStaticText lblKillsPerHour;
+ private IStaticText lblElapsedTime;
+ private IStaticText lblRareCount;
+ private IStaticText lblAutoLootRare;
+ private IStaticText lblStatus;
+ private IStaticText lblWebSocketStatus;
+
+ // Settings tab controls
+ private ICheckBox chkRareMetaEnabled;
+ private ICheckBox chkRemoteCommandsEnabled;
+ private ICheckBox chkHttpServerEnabled;
+ private ICheckBox chkWebSocketEnabled;
+ private ICheckBox chkTelemetryEnabled;
+ private ITextBox txtCharTag;
+ private ITextBox txtVTankPath;
+
+ // Statistics tab controls
+ private IStaticText lblDetailedKillsValue;
+ private IStaticText lblBestHourValue;
+ private IStaticText lblAverageKillsValue;
+ private IStaticText lblRareStatsValue;
+ private IStaticText lblRareRateValue;
+ private IStaticText lblSessionTimeValue;
+ private IStaticText lblLastKillValue;
+ private IButton btnResetStats;
+
+ // Navigation tab controls
+ private ICheckBox chkNavVisualizationEnabled;
+ private ICombo cmbNavFiles;
+ private IButton btnRefreshNavFiles;
+ private IStaticText lblNavStatus;
+ private IButton btnLoadRoute;
+ private IButton btnClearRoute;
+
+ // Position tracking
+ private Timer positionSaveTimer;
+ private Timer positionCheckTimer;
+ private Point lastKnownPosition;
+
+ // Statistics tracking
+ private double bestHourlyKills = 0;
+ private DateTime sessionStartTime;
+
+ public TabbedMainView(PluginCore core) : base(core)
+ {
+ instance = this;
+ sessionStartTime = DateTime.Now;
+ InitializePositionTimer();
+ }
+
+ private void InitializePositionTimer()
+ {
+ positionSaveTimer = new Timer(2000);
+ positionSaveTimer.Elapsed += (s, e) => {
+ SaveWindowPosition();
+ positionSaveTimer.Stop();
+ };
+
+ positionCheckTimer = new Timer(500);
+ positionCheckTimer.Elapsed += CheckPositionChanged;
+ positionCheckTimer.Start();
+ }
+
+ public static void ViewInit()
+ {
+ try
+ {
+ if (instance == null)
+ {
+ instance = new TabbedMainView(null);
+ }
+ instance.InitializeView();
+ PluginCore.WriteToChat("Enhanced tabbed view initialized.");
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat("Error initializing tabbed view: " + ex.Message);
+ }
+ }
+
+ private void InitializeView()
+ {
+ try
+ {
+ // Load the new tabbed view
+ CreateFromXMLResource("MosswartMassacre.ViewXML.mainViewTabbed.xml");
+
+ InitializeMainTabControls();
+ InitializeSettingsTabControls();
+ InitializeStatisticsTabControls();
+ InitializeNavigationTabControls();
+
+ // Initialize the base view and set initial position
+ Initialize();
+ lastKnownPosition = view?.Location ?? new Point(100, 100);
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat("Error in InitializeView: " + ex.Message);
+ }
+ }
+
+ private void InitializeMainTabControls()
+ {
+ try
+ {
+ // Main tab - existing functionality
+ lblTotalKills = (IStaticText)view["lblTotalKills"];
+ lblKillsPer5Min = (IStaticText)view["lblKillsPer5Min"];
+ lblKillsPerHour = (IStaticText)view["lblKillsPerHour"];
+ lblElapsedTime = (IStaticText)view["lblElapsedTime"];
+ lblRareCount = (IStaticText)view["lblRareCount"];
+ lblAutoLootRare = (IStaticText)view["lblAutoLootRare"];
+ lblStatus = (IStaticText)view["lblStatus"];
+ lblWebSocketStatus = (IStaticText)view["lblWebSocketStatus"];
+
+ // Update status, auto loot indicator, and websocket status immediately
+ UpdateStatus();
+ UpdateAutoLootRareIndicator();
+ UpdateWebSocketStatus();
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error initializing main tab controls: {ex.Message}");
+ }
+ }
+
+ private void InitializeSettingsTabControls()
+ {
+ // Settings tab controls
+ chkRareMetaEnabled = (ICheckBox)view["chkRareMetaEnabled"];
+ chkRemoteCommandsEnabled = (ICheckBox)view["chkRemoteCommandsEnabled"];
+ chkHttpServerEnabled = (ICheckBox)view["chkHttpServerEnabled"];
+ chkWebSocketEnabled = (ICheckBox)view["chkWebSocketEnabled"];
+ chkTelemetryEnabled = (ICheckBox)view["chkTelemetryEnabled"];
+ txtCharTag = (ITextBox)view["txtCharTag"];
+ txtVTankPath = (ITextBox)view["txtVTankPath"];
+
+ // Hook up settings events
+ chkRareMetaEnabled.Change += OnRareMetaSettingChanged;
+ chkRemoteCommandsEnabled.Change += OnRemoteCommandsSettingChanged;
+ chkHttpServerEnabled.Change += OnHttpServerSettingChanged;
+ chkWebSocketEnabled.Change += OnWebSocketSettingChanged;
+ chkTelemetryEnabled.Change += OnTelemetrySettingChanged;
+ txtCharTag.Change += OnCharTagChanged;
+ txtVTankPath.Change += OnVTankPathChanged;
+
+ // Load current settings
+ LoadCurrentSettings();
+ }
+
+ private void InitializeStatisticsTabControls()
+ {
+ try
+ {
+ // Statistics tab controls
+ lblDetailedKillsValue = (IStaticText)view["lblDetailedKillsValue"];
+ lblBestHourValue = (IStaticText)view["lblBestHourValue"];
+ lblAverageKillsValue = (IStaticText)view["lblAverageKillsValue"];
+ lblRareStatsValue = (IStaticText)view["lblRareStatsValue"];
+ lblRareRateValue = (IStaticText)view["lblRareRateValue"];
+ lblSessionTimeValue = (IStaticText)view["lblSessionTimeValue"];
+ lblLastKillValue = (IStaticText)view["lblLastKillValue"];
+ btnResetStats = (IButton)view["btnResetStats"];
+
+ // Hook up statistics events
+ if (btnResetStats != null)
+ btnResetStats.Hit += OnResetStatsClick;
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error initializing statistics controls: {ex.Message}");
+ }
+ }
+
+ private void InitializeNavigationTabControls()
+ {
+ try
+ {
+ // Navigation tab controls
+ chkNavVisualizationEnabled = (ICheckBox)view["chkNavVisualizationEnabled"];
+ cmbNavFiles = (ICombo)view["cmbNavFiles"];
+ btnRefreshNavFiles = (IButton)view["btnRefreshNavFiles"];
+ lblNavStatus = (IStaticText)view["lblNavStatus"];
+ btnLoadRoute = (IButton)view["btnLoadRoute"];
+ btnClearRoute = (IButton)view["btnClearRoute"];
+
+ // Hook up navigation events
+ if (chkNavVisualizationEnabled != null)
+ chkNavVisualizationEnabled.Change += OnNavVisualizationEnabledChanged;
+ if (btnRefreshNavFiles != null)
+ btnRefreshNavFiles.Hit += OnRefreshNavFilesClick;
+ if (btnLoadRoute != null)
+ btnLoadRoute.Hit += OnLoadRouteClick;
+ if (btnClearRoute != null)
+ btnClearRoute.Hit += OnClearRouteClick;
+
+ // Initialize navigation system
+ InitializeNavigationSystem();
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error initializing navigation controls: {ex.Message}");
+ }
+ }
+
+
+ #region Event Handlers - Main Tab
+ // No main tab event handlers needed anymore - buttons removed
+ #endregion
+
+ #region Event Handlers - Settings Tab
+ private void OnRareMetaSettingChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.RareMetaEnabled = chkRareMetaEnabled.Checked;
+ PluginCore.RareMetaEnabled = chkRareMetaEnabled.Checked; // Update the static property too
+ UpdateAutoLootRareIndicator();
+
+ // Add chat message like websockets
+ PluginCore.WriteToChat($"Rare meta automation {(chkRareMetaEnabled.Checked ? "ENABLED" : "DISABLED")}.");
+ }
+
+ private void OnRemoteCommandsSettingChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.RemoteCommandsEnabled = chkRemoteCommandsEnabled.Checked;
+ }
+
+ private void OnHttpServerSettingChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.HttpServerEnabled = chkHttpServerEnabled.Checked;
+ if (chkHttpServerEnabled.Checked)
+ HttpCommandServer.Start();
+ else
+ HttpCommandServer.Stop();
+ }
+
+ private void OnWebSocketSettingChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.WebSocketEnabled = chkWebSocketEnabled.Checked;
+ if (chkWebSocketEnabled.Checked)
+ {
+ WebSocket.Start();
+ PluginCore.WriteToChat("WebSocket streaming ENABLED.");
+ }
+ else
+ {
+ WebSocket.Stop();
+ PluginCore.WriteToChat("WebSocket streaming DISABLED.");
+ }
+ UpdateWebSocketStatus();
+ }
+
+ private void OnTelemetrySettingChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.TelemetryEnabled = chkTelemetryEnabled.Checked;
+ if (chkTelemetryEnabled.Checked)
+ Telemetry.Start();
+ else
+ Telemetry.Stop();
+ }
+
+ private void OnCharTagChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.CharTag = txtCharTag.Text;
+ }
+
+ private void OnVTankPathChanged(object sender, EventArgs e)
+ {
+ PluginSettings.Instance.VTankProfilesPath = txtVTankPath.Text;
+ // Refresh navigation system with new path
+ if (PluginCore.navVisualization != null)
+ {
+ PluginCore.navVisualization.RefreshNavFileList();
+ // Also refresh the dropdown list in Navigation tab
+ RefreshNavFileList();
+ UpdateNavigationStatus();
+ }
+ }
+
+ // Settings save automatically via property setters - no manual save/reset buttons needed
+
+ private void LoadCurrentSettings()
+ {
+ try
+ {
+ if (PluginSettings.Instance != null && chkRareMetaEnabled != null)
+ {
+ chkRareMetaEnabled.Checked = PluginSettings.Instance.RareMetaEnabled;
+ chkRemoteCommandsEnabled.Checked = PluginSettings.Instance.RemoteCommandsEnabled;
+ chkHttpServerEnabled.Checked = PluginSettings.Instance.HttpServerEnabled;
+ chkWebSocketEnabled.Checked = PluginSettings.Instance.WebSocketEnabled;
+ chkTelemetryEnabled.Checked = PluginSettings.Instance.TelemetryEnabled;
+ txtCharTag.Text = PluginSettings.Instance.CharTag ?? "default";
+ txtVTankPath.Text = PluginSettings.Instance.VTankProfilesPath ?? "";
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error loading settings: {ex.Message}");
+ }
+ }
+ #endregion
+
+ #region Event Handlers - Statistics Tab
+ private void OnResetStatsClick(object sender, EventArgs e)
+ {
+ // Reset stats functionality moved here from removed OnRestartClick
+ PluginCore.RestartStats();
+ sessionStartTime = DateTime.Now;
+ bestHourlyKills = 0;
+ UpdateStatistics();
+ }
+ #endregion
+
+ #region Event Handlers - Navigation Tab
+ private void OnNavVisualizationEnabledChanged(object sender, EventArgs e)
+ {
+ if (PluginCore.navVisualization != null)
+ {
+ PluginCore.navVisualization.SetEnabled(chkNavVisualizationEnabled.Checked);
+ UpdateNavigationStatus();
+ }
+ }
+
+ private void OnRefreshNavFilesClick(object sender, EventArgs e)
+ {
+ RefreshNavFileList();
+ }
+
+ private void OnLoadRouteClick(object sender, EventArgs e)
+ {
+ try
+ {
+ if (cmbNavFiles != null && PluginCore.navVisualization != null &&
+ cmbNavFiles.Selected >= 0 && cmbNavFiles.Count > 0 &&
+ cmbNavFiles.Selected < cmbNavFiles.Count)
+ {
+ string selectedFile = cmbNavFiles.Text[cmbNavFiles.Selected];
+ if (selectedFile != "None" && !string.IsNullOrEmpty(selectedFile))
+ {
+ PluginCore.navVisualization.LoadRoute(selectedFile);
+ UpdateNavigationStatus();
+ }
+ else
+ {
+ PluginCore.WriteToChat("[NavViz] Please select a valid nav file from the dropdown");
+ }
+ }
+ else
+ {
+ PluginCore.WriteToChat("[NavViz] No nav files available. Click Refresh or configure VTank path in Settings tab");
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"[NavViz] Error loading route: {ex.Message}");
+ }
+ }
+
+ private void OnClearRouteClick(object sender, EventArgs e)
+ {
+ if (PluginCore.navVisualization != null)
+ {
+ PluginCore.navVisualization.LoadRoute("None");
+ if (cmbNavFiles != null)
+ {
+ cmbNavFiles.Selected = 0; // Select "None" which should be at index 0
+ }
+ UpdateNavigationStatus();
+ }
+ }
+
+ private void InitializeNavigationSystem()
+ {
+ try
+ {
+ RefreshNavFileList();
+ UpdateNavigationStatus();
+
+ // Subscribe to route changes
+ if (PluginCore.navVisualization != null)
+ {
+ PluginCore.navVisualization.RouteChanged += (s, e) => UpdateNavigationStatus();
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error initializing navigation system: {ex.Message}");
+ }
+ }
+
+ private void RefreshNavFileList()
+ {
+ try
+ {
+ if (PluginCore.navVisualization != null && cmbNavFiles != null)
+ {
+ PluginCore.navVisualization.RefreshNavFileList();
+
+ cmbNavFiles.Clear();
+ cmbNavFiles.Add("None");
+
+ foreach (string navFile in PluginCore.navVisualization.AvailableNavFiles)
+ {
+ PluginCore.WriteToChat($"[NavViz UI] Adding to dropdown: {navFile}");
+ cmbNavFiles.Add(navFile);
+ }
+
+ if (cmbNavFiles.Count > 0)
+ cmbNavFiles.Selected = 0; // Select "None" which should be at index 0
+
+ PluginCore.WriteToChat($"[NavViz UI] Dropdown populated with {cmbNavFiles.Count} items (including 'None')");
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error refreshing nav file list: {ex.Message}");
+ }
+ }
+
+ private void UpdateNavigationStatus()
+ {
+ try
+ {
+ if (lblNavStatus != null && PluginCore.navVisualization != null)
+ {
+ lblNavStatus.Text = $"Status: {PluginCore.navVisualization.GetStatus()}";
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error updating navigation status: {ex.Message}");
+ }
+ }
+ #endregion
+
+
+ #region Position Management
+ private void CheckPositionChanged(object sender, ElapsedEventArgs e)
+ {
+ try
+ {
+ if (view != null)
+ {
+ Point currentPosition = view.Location;
+ if (currentPosition != lastKnownPosition)
+ {
+ lastKnownPosition = currentPosition;
+ if (positionSaveTimer != null)
+ {
+ positionSaveTimer.Stop();
+ positionSaveTimer.Start();
+ }
+ }
+ }
+ }
+ catch
+ {
+ // Ignore errors in position checking
+ }
+ }
+
+ protected override void SaveWindowPosition()
+ {
+ try
+ {
+ if (view != null && PluginSettings.Instance != null)
+ {
+ PluginSettings.Instance.MainWindowX = view.Location.X;
+ PluginSettings.Instance.MainWindowY = view.Location.Y;
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error saving window position: {ex.Message}");
+ }
+ }
+
+ protected override void RestoreWindowPosition()
+ {
+ try
+ {
+ if (view != null && PluginSettings.Instance != null)
+ {
+ view.Location = new Point(
+ PluginSettings.Instance.MainWindowX,
+ PluginSettings.Instance.MainWindowY
+ );
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error restoring window position: {ex.Message}");
+ }
+ }
+ #endregion
+
+ #region Public Update Methods (maintain compatibility with existing code)
+ public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour)
+ {
+ try
+ {
+ if (instance?.lblTotalKills != null)
+ {
+ instance.lblTotalKills.Text = $"Total Kills: {totalKills}";
+ }
+ if (instance?.lblKillsPer5Min != null)
+ {
+ instance.lblKillsPer5Min.Text = $"Kills per 5 Min: {killsPer5Min:F2}";
+ }
+ if (instance?.lblKillsPerHour != null)
+ {
+ instance.lblKillsPerHour.Text = $"Kills per Hour: {killsPerHour:F2}";
+ }
+
+ // Update detailed statistics
+ if (instance?.lblDetailedKillsValue != null)
+ {
+ instance.lblDetailedKillsValue.Text = totalKills.ToString();
+ }
+ if (instance?.lblAverageKillsValue != null)
+ {
+ instance.lblAverageKillsValue.Text = $"{killsPerHour:F2} kills/hr";
+ }
+
+ // Track best hourly performance
+ if (instance != null && killsPerHour > instance.bestHourlyKills)
+ {
+ instance.bestHourlyKills = killsPerHour;
+ if (instance.lblBestHourValue != null)
+ {
+ instance.lblBestHourValue.Text = $"{instance.bestHourlyKills:F2} kills/hr";
+ }
+ }
+
+ // Update status and auto loot indicator
+ instance?.UpdateStatus();
+ instance?.UpdateAutoLootRareIndicator();
+ instance?.UpdateWebSocketStatus();
+
+ instance?.UpdateStatistics();
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error in UpdateKillStats: {ex.Message}");
+ }
+ }
+
+ public static void UpdateElapsedTime(TimeSpan elapsed)
+ {
+ try
+ {
+ if (instance?.lblElapsedTime != null)
+ {
+ int days = elapsed.Days;
+ int hours = elapsed.Hours;
+ int minutes = elapsed.Minutes;
+ int seconds = elapsed.Seconds;
+
+ if (days > 0)
+ instance.lblElapsedTime.Text = $"Time: {days}d {hours:D2}:{minutes:D2}:{seconds:D2}";
+ else
+ instance.lblElapsedTime.Text = $"Time: {hours:D2}:{minutes:D2}:{seconds:D2}";
+ }
+
+ if (instance?.lblSessionTimeValue != null && instance?.lblElapsedTime != null)
+ {
+ instance.lblSessionTimeValue.Text = instance.lblElapsedTime.Text.Replace("Time: ", "");
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error in UpdateElapsedTime: {ex.Message}");
+ }
+ }
+
+ public static void UpdateRareCount(int rareCount)
+ {
+ try
+ {
+ if (instance?.lblRareCount != null)
+ {
+ instance.lblRareCount.Text = $"Rare Count: {rareCount}";
+ }
+ if (instance?.lblRareStatsValue != null)
+ {
+ instance.lblRareStatsValue.Text = rareCount.ToString();
+ }
+
+ // Calculate rare drop rate
+ int totalKills = PluginCore.totalKills;
+ if (totalKills > 0 && instance?.lblRareRateValue != null)
+ {
+ double rareRate = (double)rareCount / totalKills * 100;
+ instance.lblRareRateValue.Text = $"{rareRate:F2}%";
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error in UpdateRareCount: {ex.Message}");
+ }
+ }
+
+ public static void SetRareMetaToggleState(bool enabled)
+ {
+ if (instance?.chkRareMetaEnabled != null)
+ {
+ instance.chkRareMetaEnabled.Checked = enabled;
+ }
+ instance?.UpdateAutoLootRareIndicator();
+ }
+
+ public static void RefreshSettingsFromConfig()
+ {
+ // Call this after settings are loaded to refresh UI
+ instance?.LoadCurrentSettings();
+ instance?.UpdateAutoLootRareIndicator();
+ instance?.UpdateWebSocketStatus();
+ }
+
+ private void UpdateStatus()
+ {
+ try
+ {
+ if (lblStatus != null)
+ {
+ string metaState = VtankControl.VtGetMetaState();
+ lblStatus.Text = $"Meta State: {metaState}";
+ }
+ }
+ catch
+ {
+ if (lblStatus != null)
+ lblStatus.Text = "Meta State: Unknown";
+ }
+ }
+
+ private void UpdateAutoLootRareIndicator()
+ {
+ try
+ {
+ if (lblAutoLootRare != null)
+ {
+ bool isEnabled = PluginSettings.Instance?.RareMetaEnabled == true;
+ if (isEnabled)
+ {
+ lblAutoLootRare.Text = "Auto Loot Rare: [ON]";
+ }
+ else
+ {
+ lblAutoLootRare.Text = "Auto Loot Rare: [OFF]";
+ }
+ }
+ }
+ catch
+ {
+ if (lblAutoLootRare != null)
+ lblAutoLootRare.Text = "Auto Loot Rare: Unknown";
+ }
+ }
+
+ private void UpdateWebSocketStatus()
+ {
+ try
+ {
+ if (lblWebSocketStatus != null)
+ {
+ bool isConnected = PluginSettings.Instance?.WebSocketEnabled == true;
+ if (isConnected)
+ {
+ lblWebSocketStatus.Text = "WebSocket: [CONNECTED]";
+ }
+ else
+ {
+ lblWebSocketStatus.Text = "WebSocket: [DISCONNECTED]";
+ }
+ }
+ }
+ catch
+ {
+ if (lblWebSocketStatus != null)
+ lblWebSocketStatus.Text = "WebSocket: Unknown";
+ }
+ }
+ #endregion
+
+ private void UpdateStatistics()
+ {
+ try
+ {
+ // Update last kill time
+ if (lblLastKillValue != null)
+ {
+ if (PluginCore.lastKillTime != DateTime.MinValue)
+ {
+ TimeSpan timeSinceLastKill = DateTime.Now - PluginCore.lastKillTime;
+ if (timeSinceLastKill.TotalMinutes < 60)
+ lblLastKillValue.Text = $"{timeSinceLastKill.TotalMinutes:F0} min ago";
+ else
+ lblLastKillValue.Text = $"{timeSinceLastKill.TotalHours:F1} hr ago";
+ }
+ else
+ {
+ lblLastKillValue.Text = "Never";
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat($"Error in UpdateStatistics: {ex.Message}");
+ }
+ }
+
+ public static void ViewDestroy()
+ {
+ try
+ {
+ if (instance != null)
+ {
+ // Save final position before destruction
+ instance.SaveWindowPosition();
+
+ // No main tab event handlers to clean up - buttons removed
+
+ // Clean up event handlers - Settings tab
+ if (instance.chkRareMetaEnabled != null)
+ instance.chkRareMetaEnabled.Change -= instance.OnRareMetaSettingChanged;
+ if (instance.chkRemoteCommandsEnabled != null)
+ instance.chkRemoteCommandsEnabled.Change -= instance.OnRemoteCommandsSettingChanged;
+ if (instance.chkHttpServerEnabled != null)
+ instance.chkHttpServerEnabled.Change -= instance.OnHttpServerSettingChanged;
+ if (instance.chkWebSocketEnabled != null)
+ instance.chkWebSocketEnabled.Change -= instance.OnWebSocketSettingChanged;
+ if (instance.chkTelemetryEnabled != null)
+ instance.chkTelemetryEnabled.Change -= instance.OnTelemetrySettingChanged;
+ if (instance.txtCharTag != null)
+ instance.txtCharTag.Change -= instance.OnCharTagChanged;
+ if (instance.txtVTankPath != null)
+ instance.txtVTankPath.Change -= instance.OnVTankPathChanged;
+
+ // Clean up event handlers - Statistics tab
+ if (instance.btnResetStats != null)
+ instance.btnResetStats.Hit -= instance.OnResetStatsClick;
+
+ // Clean up event handlers - Navigation tab
+ if (instance.chkNavVisualizationEnabled != null)
+ instance.chkNavVisualizationEnabled.Change -= instance.OnNavVisualizationEnabledChanged;
+ if (instance.btnRefreshNavFiles != null)
+ instance.btnRefreshNavFiles.Hit -= instance.OnRefreshNavFilesClick;
+ if (instance.btnLoadRoute != null)
+ instance.btnLoadRoute.Hit -= instance.OnLoadRouteClick;
+ if (instance.btnClearRoute != null)
+ instance.btnClearRoute.Hit -= instance.OnClearRouteClick;
+
+ // Clean up timers
+ if (instance.positionSaveTimer != null)
+ {
+ instance.positionSaveTimer.Stop();
+ instance.positionSaveTimer.Dispose();
+ instance.positionSaveTimer = null;
+ }
+ if (instance.positionCheckTimer != null)
+ {
+ instance.positionCheckTimer.Stop();
+ instance.positionCheckTimer.Dispose();
+ instance.positionCheckTimer = null;
+ }
+
+ instance.Dispose();
+ instance = null;
+ PluginCore.WriteToChat("Enhanced tabbed view destroyed.");
+ }
+ }
+ catch (Exception ex)
+ {
+ PluginCore.WriteToChat("Error destroying tabbed view: " + ex.Message);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MosswartMassacre/Views/VVSBaseView.cs b/MosswartMassacre/Views/VVSBaseView.cs
deleted file mode 100644
index e5adc2d..0000000
--- a/MosswartMassacre/Views/VVSBaseView.cs
+++ /dev/null
@@ -1,395 +0,0 @@
-using System;
-using System.Drawing;
-using System.Runtime.InteropServices;
-using System.Timers;
-using VirindiViewService;
-using VirindiViewService.XMLParsers;
-
-namespace MosswartMassacre.Views
-{
- ///
- /// Base class for VVS (VirindiViewService) based views.
- /// Replaces the wrapper-based BaseView with direct VVS integration.
- ///
- public class VVSBaseView : IDisposable
- {
- #region Windows API for boundary checking
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT
- {
- public int Left;
- public int Top;
- public int Right;
- public int Bottom;
-
- public int Width { get { return Right - Left; } }
- public int Height { get { return Bottom - Top; } }
- }
-
- [DllImport("user32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
- #endregion
-
- #region Core VVS Components
- protected HudView view;
- protected ViewProperties properties;
- protected ControlGroup controls;
- protected PluginCore pluginCore;
- #endregion
-
- #region Position Management
- private Timer positionSaveTimer;
- #endregion
-
- public VVSBaseView(PluginCore core)
- {
- pluginCore = core;
- InitializePositionTimer();
- }
-
- #region VVS Initialization
- protected void CreateFromXMLResource(string resourcePath, bool doIcon = true, bool doTitle = true)
- {
- try
- {
- // Parse XML using VVS Decal3XMLParser
- new Decal3XMLParser().ParseFromResource(resourcePath, out properties, out controls);
-
- // Set window properties
- if (doTitle)
- {
- properties.Title = "Mosswart Massacre v3.0";
- }
-
- if (doIcon)
- {
- // Use default icon for now - can be customized later
- properties.Icon = 7735; // Same icon as in XML
- }
-
- // Create the HudView
- view = new HudView(properties, controls);
-
- // Subscribe to essential events
- view.VisibleChanged += View_VisibleChanged;
- view.Moved += View_Moved;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error creating VVS view from {resourcePath}: {ex.Message}");
- PluginCore.WriteToChat($"Stack trace: {ex.StackTrace}");
- }
- }
-
- protected void CreateFromXMLString(string xmlString, bool doIcon = true, bool doTitle = true)
- {
- try
- {
- // Parse XML string using VVS Decal3XMLParser
- new Decal3XMLParser().Parse(xmlString, out properties, out controls);
-
- if (doTitle)
- {
- properties.Title = "Mosswart Massacre v3.0";
- }
-
- if (doIcon)
- {
- properties.Icon = 7735;
- }
-
- view = new HudView(properties, controls);
- view.VisibleChanged += View_VisibleChanged;
- view.Moved += View_Moved;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error creating VVS view from XML string: {ex.Message}");
- }
- }
- #endregion
-
- #region Control Access
- ///
- /// Get a control by name with proper type casting.
- /// Usage: var button = GetControl<HudButton>("btnExample");
- ///
- protected T GetControl(string controlName) where T : class
- {
- try
- {
- if (view != null && view[controlName] != null)
- {
- return view[controlName] as T;
- }
- return null;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}");
- return null;
- }
- }
-
- ///
- /// Get a control by name (alternative syntax)
- /// Usage: var button = (HudButton)GetControl("btnExample");
- ///
- protected object GetControl(string controlName)
- {
- try
- {
- return view?[controlName];
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error getting control '{controlName}': {ex.Message}");
- return null;
- }
- }
- #endregion
-
- #region Window Management
- protected virtual void SaveWindowPosition()
- {
- try
- {
- if (view != null && PluginSettings.Instance != null)
- {
- PluginSettings.Instance.MainWindowX = view.Location.X;
- PluginSettings.Instance.MainWindowY = view.Location.Y;
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error saving window position: {ex.Message}");
- }
- }
-
- protected virtual void RestoreWindowPosition()
- {
- try
- {
- if (view != null && PluginSettings.Instance != null)
- {
- view.Location = new Point(
- PluginSettings.Instance.MainWindowX,
- PluginSettings.Instance.MainWindowY
- );
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error restoring window position: {ex.Message}");
- }
- }
-
- protected void KeepWindowInBounds()
- {
- try
- {
- if (view == null) return;
-
- RECT rect = new RECT();
- IntPtr gameWindowHandle = PluginCore.MyHost?.Decal?.Hwnd ?? IntPtr.Zero;
-
- if (gameWindowHandle != IntPtr.Zero && GetWindowRect(gameWindowHandle, ref rect))
- {
- Point currentLocation = view.Location;
- int viewWidth = view.Width;
- int viewHeight = view.Height;
-
- bool needsUpdate = false;
-
- // Check right boundary
- if (currentLocation.X + viewWidth > rect.Width)
- {
- currentLocation.X = rect.Width - viewWidth;
- needsUpdate = true;
- }
- // Check left boundary
- else if (currentLocation.X < 0)
- {
- currentLocation.X = 20;
- needsUpdate = true;
- }
-
- // Check bottom boundary
- if (currentLocation.Y + viewHeight > rect.Height)
- {
- currentLocation.Y = rect.Height - viewHeight;
- needsUpdate = true;
- }
- // Check top boundary
- else if (currentLocation.Y < 0)
- {
- currentLocation.Y = 20;
- needsUpdate = true;
- }
-
- if (needsUpdate)
- {
- view.Location = currentLocation;
- }
- }
- }
- catch
- {
- // Silently ignore boundary check errors
- }
- }
- #endregion
-
- #region Position Timer Management
- private void InitializePositionTimer()
- {
- positionSaveTimer = new Timer(2000); // 2 second delay after movement stops
- positionSaveTimer.Elapsed += (s, e) => {
- SaveWindowPosition();
- positionSaveTimer.Stop();
- };
- }
-
- private void View_Moved(object sender, EventArgs e)
- {
- try
- {
- // Reset timer when window moves
- if (positionSaveTimer != null)
- {
- if (positionSaveTimer.Enabled)
- positionSaveTimer.Stop();
-
- positionSaveTimer.Start();
- }
- }
- catch
- {
- // Ignore timer errors
- }
- }
-
- private void View_VisibleChanged(object sender, EventArgs e)
- {
- try
- {
- if (view.Visible)
- {
- KeepWindowInBounds();
- }
- }
- catch
- {
- // Ignore visibility change errors
- }
- }
- #endregion
-
- #region Public Interface
- public virtual void Initialize()
- {
- try
- {
- RestoreWindowPosition();
- KeepWindowInBounds();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing VVS view: {ex.Message}");
- }
- }
-
- public virtual void Show()
- {
- if (view != null)
- {
- view.Visible = true;
- }
- }
-
- public virtual void Hide()
- {
- if (view != null)
- {
- view.Visible = false;
- }
- }
-
- public virtual void Toggle()
- {
- if (view != null)
- {
- view.Visible = !view.Visible;
- }
- }
-
- public bool IsVisible
- {
- get { return view?.Visible ?? false; }
- }
-
- public Point Location
- {
- get { return view?.Location ?? Point.Empty; }
- set { if (view != null) view.Location = value; }
- }
-
- public Size Size
- {
- get { return view != null ? new Size(view.Width, view.Height) : Size.Empty; }
- }
- #endregion
-
- #region IDisposable Support
- private bool disposedValue = false;
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- try
- {
- // Save final position before disposal
- SaveWindowPosition();
-
- // Clean up timers
- if (positionSaveTimer != null)
- {
- positionSaveTimer.Stop();
- positionSaveTimer.Dispose();
- positionSaveTimer = null;
- }
-
- // Clean up VVS view
- if (view != null)
- {
- view.VisibleChanged -= View_VisibleChanged;
- view.Moved -= View_Moved;
- view.Dispose();
- view = null;
- }
-
- // Clean up VVS objects
- properties = null;
- controls = null;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error disposing VVS view: {ex.Message}");
- }
- }
- disposedValue = true;
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/MosswartMassacre/Views/VVSTabbedMainView.cs b/MosswartMassacre/Views/VVSTabbedMainView.cs
deleted file mode 100644
index 0c13665..0000000
--- a/MosswartMassacre/Views/VVSTabbedMainView.cs
+++ /dev/null
@@ -1,845 +0,0 @@
-using System;
-using System.Drawing;
-using System.Timers;
-using VirindiViewService.Controls;
-
-namespace MosswartMassacre.Views
-{
- ///
- /// VVS-based tabbed main view - direct VirindiViewService integration.
- /// Replaces wrapper-based TabbedMainView with modern VVS controls.
- ///
- internal class VVSTabbedMainView : VVSBaseView
- {
- private static VVSTabbedMainView instance;
-
- #region Main Tab Controls
- private HudStaticText lblTotalKills;
- private HudStaticText lblKillsPer5Min;
- private HudStaticText lblKillsPerHour;
- private HudStaticText lblElapsedTime;
- private HudStaticText lblRareCount;
- private HudStaticText lblAutoLootRare;
- private HudStaticText lblStatus;
- private HudStaticText lblWebSocketStatus;
- #endregion
-
- #region Settings Tab Controls
- private HudCheckBox chkRareMetaEnabled;
- private HudCheckBox chkRemoteCommandsEnabled;
- private HudCheckBox chkHttpServerEnabled;
- private HudCheckBox chkWebSocketEnabled;
- private HudCheckBox chkTelemetryEnabled;
- private HudTextBox txtCharTag;
- private HudTextBox txtVTankPath;
- #endregion
-
- #region Statistics Tab Controls
- private HudStaticText lblDetailedKillsValue;
- private HudStaticText lblBestHourValue;
- private HudStaticText lblAverageKillsValue;
- private HudStaticText lblRareStatsValue;
- private HudStaticText lblRareRateValue;
- private HudStaticText lblSessionTimeValue;
- private HudStaticText lblLastKillValue;
- private HudButton btnResetStats;
- #endregion
-
- #region Navigation Tab Controls (Basic)
- private HudCheckBox chkNavVisualizationEnabled;
- private HudCombo cmbNavFiles;
- private HudButton btnRefreshNavFiles;
- private HudStaticText lblNavStatus;
- private HudButton btnLoadRoute;
- private HudButton btnClearRoute;
- #endregion
-
- #region Statistics Tracking
- private double bestHourlyKills = 0;
- private DateTime sessionStartTime;
- #endregion
-
- public VVSTabbedMainView(PluginCore core) : base(core)
- {
- instance = this;
- sessionStartTime = DateTime.Now;
- }
-
- #region Static Interface Methods
- public static void ViewInit()
- {
- try
- {
- if (instance == null)
- {
- instance = new VVSTabbedMainView(null);
- }
- instance.InitializeView();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat("Error initializing VVS tabbed view: " + ex.Message);
- }
- }
-
- public static void ViewDestroy()
- {
- try
- {
- if (instance != null)
- {
- instance.Dispose();
- instance = null;
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat("Error destroying VVS tabbed view: " + ex.Message);
- }
- }
- #endregion
-
- #region Initialization
- private void InitializeView()
- {
- try
- {
- // Create view from working original XML layout
- CreateFromXMLResource("MosswartMassacre.ViewXML.mainViewTabbed.xml");
-
- // Initialize all tab controls
- InitializeMainTabControls();
- InitializeSettingsTabControls();
- InitializeStatisticsTabControls();
- InitializeNavigationTabControls();
-
- // Initialize the base view and set initial position
- Initialize();
-
- // Make the view visible and show in plugin bar
- if (view != null)
- {
- view.Visible = true;
- view.ShowInBar = true;
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat("Error in VVS InitializeView: " + ex.Message);
- }
- }
-
- private void InitializeMainTabControls()
- {
- try
- {
- // Main tab - existing functionality using VVS controls
- lblTotalKills = GetControl("lblTotalKills");
- lblKillsPer5Min = GetControl("lblKillsPer5Min");
- lblKillsPerHour = GetControl("lblKillsPerHour");
- lblElapsedTime = GetControl("lblElapsedTime");
- lblRareCount = GetControl("lblRareCount");
- lblAutoLootRare = GetControl("lblAutoLootRare");
- lblStatus = GetControl("lblStatus");
- lblWebSocketStatus = GetControl("lblWebSocketStatus");
-
- // Update status displays immediately
- UpdateStatus();
- UpdateAutoLootRareIndicator();
- UpdateWebSocketStatus();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing main tab controls: {ex.Message}");
- }
- }
-
- private void InitializeSettingsTabControls()
- {
- try
- {
- // Settings tab controls
- chkRareMetaEnabled = GetControl("chkRareMetaEnabled");
- chkRemoteCommandsEnabled = GetControl("chkRemoteCommandsEnabled");
- chkHttpServerEnabled = GetControl("chkHttpServerEnabled");
- chkWebSocketEnabled = GetControl("chkWebSocketEnabled");
- chkTelemetryEnabled = GetControl("chkTelemetryEnabled");
- txtCharTag = GetControl("txtCharTag");
- txtVTankPath = GetControl("txtVTankPath");
-
- // Hook up settings events
- if (chkRareMetaEnabled != null)
- chkRareMetaEnabled.Change += OnRareMetaSettingChanged;
- if (chkRemoteCommandsEnabled != null)
- chkRemoteCommandsEnabled.Change += OnRemoteCommandsSettingChanged;
- if (chkHttpServerEnabled != null)
- chkHttpServerEnabled.Change += OnHttpServerSettingChanged;
- if (chkWebSocketEnabled != null)
- chkWebSocketEnabled.Change += OnWebSocketSettingChanged;
- if (chkTelemetryEnabled != null)
- chkTelemetryEnabled.Change += OnTelemetrySettingChanged;
- if (txtCharTag != null)
- txtCharTag.Change += OnCharTagChanged;
- if (txtVTankPath != null)
- txtVTankPath.Change += OnVTankPathChanged;
-
- // Load current settings
- LoadCurrentSettings();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing settings tab controls: {ex.Message}");
- }
- }
-
- private void InitializeStatisticsTabControls()
- {
- try
- {
- // Statistics tab controls
- lblDetailedKillsValue = GetControl("lblDetailedKillsValue");
- lblBestHourValue = GetControl("lblBestHourValue");
- lblAverageKillsValue = GetControl("lblAverageKillsValue");
- lblRareStatsValue = GetControl("lblRareStatsValue");
- lblRareRateValue = GetControl("lblRareRateValue");
- lblSessionTimeValue = GetControl("lblSessionTimeValue");
- lblLastKillValue = GetControl("lblLastKillValue");
- btnResetStats = GetControl("btnResetStats");
-
- // Hook up statistics events
- if (btnResetStats != null)
- btnResetStats.Hit += OnResetStatsClick;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing statistics controls: {ex.Message}");
- }
- }
-
- private void InitializeNavigationTabControls()
- {
- try
- {
- // Basic navigation tab controls
- chkNavVisualizationEnabled = GetControl("chkNavVisualizationEnabled");
- cmbNavFiles = GetControl("cmbNavFiles");
- btnRefreshNavFiles = GetControl("btnRefreshNavFiles");
- lblNavStatus = GetControl("lblNavStatus");
- btnLoadRoute = GetControl("btnLoadRoute");
- btnClearRoute = GetControl("btnClearRoute");
-
- // Hook up basic navigation events
- if (chkNavVisualizationEnabled != null)
- chkNavVisualizationEnabled.Change += OnNavVisualizationEnabledChanged;
- if (btnRefreshNavFiles != null)
- btnRefreshNavFiles.Hit += OnRefreshNavFilesClick;
- if (btnLoadRoute != null)
- btnLoadRoute.Hit += OnLoadRouteClick;
- if (btnClearRoute != null)
- btnClearRoute.Hit += OnClearRouteClick;
-
- // Initialize navigation system
- InitializeNavigationSystem();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing navigation controls: {ex.Message}");
- }
- }
- #endregion
-
- #region Event Handlers - Settings Tab
- private void OnRareMetaSettingChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.RareMetaEnabled = chkRareMetaEnabled.Checked;
- PluginCore.RareMetaEnabled = chkRareMetaEnabled.Checked;
- UpdateAutoLootRareIndicator();
- PluginCore.WriteToChat($"Rare meta automation {(chkRareMetaEnabled.Checked ? "ENABLED" : "DISABLED")}.");
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in rare meta setting change: {ex.Message}");
- }
- }
-
- private void OnRemoteCommandsSettingChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.RemoteCommandsEnabled = chkRemoteCommandsEnabled.Checked;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in remote commands setting change: {ex.Message}");
- }
- }
-
- private void OnHttpServerSettingChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.HttpServerEnabled = chkHttpServerEnabled.Checked;
- if (chkHttpServerEnabled.Checked)
- HttpCommandServer.Start();
- else
- HttpCommandServer.Stop();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in HTTP server setting change: {ex.Message}");
- }
- }
-
- private void OnWebSocketSettingChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.WebSocketEnabled = chkWebSocketEnabled.Checked;
- if (chkWebSocketEnabled.Checked)
- {
- WebSocket.Start();
- PluginCore.WriteToChat("WebSocket streaming ENABLED.");
- }
- else
- {
- WebSocket.Stop();
- PluginCore.WriteToChat("WebSocket streaming DISABLED.");
- }
- UpdateWebSocketStatus();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in WebSocket setting change: {ex.Message}");
- }
- }
-
- private void OnTelemetrySettingChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.TelemetryEnabled = chkTelemetryEnabled.Checked;
- if (chkTelemetryEnabled.Checked)
- Telemetry.Start();
- else
- Telemetry.Stop();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in telemetry setting change: {ex.Message}");
- }
- }
-
- private void OnCharTagChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.CharTag = txtCharTag.Text;
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in char tag change: {ex.Message}");
- }
- }
-
- private void OnVTankPathChanged(object sender, EventArgs e)
- {
- try
- {
- PluginSettings.Instance.VTankProfilesPath = txtVTankPath.Text;
- // Refresh navigation system with new path
- if (PluginCore.navVisualization != null)
- {
- PluginCore.navVisualization.RefreshNavFileList();
- RefreshNavFileList();
- UpdateNavigationStatus();
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in VTank path change: {ex.Message}");
- }
- }
-
- private void LoadCurrentSettings()
- {
- try
- {
- if (PluginSettings.Instance != null)
- {
- if (chkRareMetaEnabled != null)
- chkRareMetaEnabled.Checked = PluginSettings.Instance.RareMetaEnabled;
- if (chkRemoteCommandsEnabled != null)
- chkRemoteCommandsEnabled.Checked = PluginSettings.Instance.RemoteCommandsEnabled;
- if (chkHttpServerEnabled != null)
- chkHttpServerEnabled.Checked = PluginSettings.Instance.HttpServerEnabled;
- if (chkWebSocketEnabled != null)
- chkWebSocketEnabled.Checked = PluginSettings.Instance.WebSocketEnabled;
- if (chkTelemetryEnabled != null)
- chkTelemetryEnabled.Checked = PluginSettings.Instance.TelemetryEnabled;
- if (txtCharTag != null)
- txtCharTag.Text = PluginSettings.Instance.CharTag ?? "default";
- if (txtVTankPath != null)
- txtVTankPath.Text = PluginSettings.Instance.VTankProfilesPath ?? "";
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error loading settings: {ex.Message}");
- }
- }
- #endregion
-
- #region Event Handlers - Statistics Tab
- private void OnResetStatsClick(object sender, EventArgs e)
- {
- try
- {
- PluginCore.RestartStats();
- sessionStartTime = DateTime.Now;
- bestHourlyKills = 0;
- UpdateStatistics();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error resetting stats: {ex.Message}");
- }
- }
- #endregion
-
- #region Event Handlers - Navigation Tab
- private void OnNavVisualizationEnabledChanged(object sender, EventArgs e)
- {
- try
- {
- if (PluginCore.navVisualization != null)
- {
- PluginCore.navVisualization.SetEnabled(chkNavVisualizationEnabled.Checked);
- UpdateNavigationStatus();
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in nav visualization change: {ex.Message}");
- }
- }
-
- private void OnRefreshNavFilesClick(object sender, EventArgs e)
- {
- try
- {
- RefreshNavFileList();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error refreshing nav files: {ex.Message}");
- }
- }
-
- private void OnLoadRouteClick(object sender, EventArgs e)
- {
- try
- {
- // Load from dropdown selection
- string routeName = null;
-
- if (cmbNavFiles != null && cmbNavFiles.Current >= 0 && cmbNavFiles.Count > 0 &&
- cmbNavFiles.Current < cmbNavFiles.Count)
- {
- routeName = ((HudStaticText)cmbNavFiles[cmbNavFiles.Current]).Text;
- }
-
- if (!string.IsNullOrEmpty(routeName) && routeName != "None")
- {
- PluginCore.navVisualization.LoadRoute(routeName);
- UpdateNavigationStatus();
- }
- else
- {
- PluginCore.WriteToChat("[NavViz] Please select a route from the dropdown");
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"[NavViz] Error loading route: {ex.Message}");
- }
- }
-
- private void OnClearRouteClick(object sender, EventArgs e)
- {
- try
- {
- if (PluginCore.navVisualization != null)
- {
- PluginCore.navVisualization.LoadRoute("None");
- // Clear dropdown selection
- if (cmbNavFiles != null && cmbNavFiles.Count > 0)
- {
- cmbNavFiles.Current = 0; // Select "None" which should be at index 0
- }
- UpdateNavigationStatus();
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error clearing route: {ex.Message}");
- }
- }
-
- private void InitializeNavigationSystem()
- {
- try
- {
- RefreshNavFileList();
- UpdateNavigationStatus();
-
- // Subscribe to route changes
- if (PluginCore.navVisualization != null)
- {
- PluginCore.navVisualization.RouteChanged += (s, e) => UpdateNavigationStatus();
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error initializing navigation system: {ex.Message}");
- }
- }
-
- private void RefreshNavFileList()
- {
- try
- {
- if (PluginCore.navVisualization != null)
- {
- PluginCore.navVisualization.RefreshNavFileList();
-
- // Update the basic dropdown
- PopulateNavFileDropdown();
-
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error refreshing nav file list: {ex.Message}");
- }
- }
-
- private void UpdateNavigationStatus()
- {
- try
- {
- if (lblNavStatus != null && PluginCore.navVisualization != null)
- {
- lblNavStatus.Text = $"Status: {PluginCore.navVisualization.GetStatus()}";
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error updating navigation status: {ex.Message}");
- }
- }
- #endregion
-
- #region Public Update Methods (maintain compatibility with existing code)
- public static void UpdateKillStats(int totalKills, double killsPer5Min, double killsPerHour)
- {
- try
- {
- if (instance == null) return;
-
- if (instance.lblTotalKills != null)
- instance.lblTotalKills.Text = $"Total Kills: {totalKills}";
- if (instance.lblKillsPer5Min != null)
- instance.lblKillsPer5Min.Text = $"Kills per 5 Min: {killsPer5Min:F2}";
- if (instance.lblKillsPerHour != null)
- instance.lblKillsPerHour.Text = $"Kills per Hour: {killsPerHour:F2}";
-
- // Update detailed statistics
- if (instance.lblDetailedKillsValue != null)
- instance.lblDetailedKillsValue.Text = totalKills.ToString();
- if (instance.lblAverageKillsValue != null)
- instance.lblAverageKillsValue.Text = $"{killsPerHour:F2} kills/hr";
-
- // Track best hourly performance
- if (killsPerHour > instance.bestHourlyKills)
- {
- instance.bestHourlyKills = killsPerHour;
- if (instance.lblBestHourValue != null)
- instance.lblBestHourValue.Text = $"{instance.bestHourlyKills:F2} kills/hr";
- }
-
- // Update status displays
- instance.UpdateStatus();
- instance.UpdateAutoLootRareIndicator();
- instance.UpdateWebSocketStatus();
- instance.UpdateStatistics();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in UpdateKillStats: {ex.Message}");
- }
- }
-
- public static void UpdateElapsedTime(TimeSpan elapsed)
- {
- try
- {
- if (instance?.lblElapsedTime != null)
- {
- int days = elapsed.Days;
- int hours = elapsed.Hours;
- int minutes = elapsed.Minutes;
- int seconds = elapsed.Seconds;
-
- if (days > 0)
- instance.lblElapsedTime.Text = $"Time: {days}d {hours:D2}:{minutes:D2}:{seconds:D2}";
- else
- instance.lblElapsedTime.Text = $"Time: {hours:D2}:{minutes:D2}:{seconds:D2}";
- }
-
- if (instance?.lblSessionTimeValue != null && instance?.lblElapsedTime != null)
- {
- instance.lblSessionTimeValue.Text = instance.lblElapsedTime.Text.Replace("Time: ", "");
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in UpdateElapsedTime: {ex.Message}");
- }
- }
-
- public static void UpdateRareCount(int rareCount)
- {
- try
- {
- if (instance?.lblRareCount != null)
- instance.lblRareCount.Text = $"Rare Count: {rareCount}";
- if (instance?.lblRareStatsValue != null)
- instance.lblRareStatsValue.Text = rareCount.ToString();
-
- // Calculate rare drop rate
- int totalKills = PluginCore.totalKills;
- if (totalKills > 0 && instance?.lblRareRateValue != null)
- {
- double rareRate = (double)rareCount / totalKills * 100;
- instance.lblRareRateValue.Text = $"{rareRate:F2}%";
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in UpdateRareCount: {ex.Message}");
- }
- }
-
- public static void SetRareMetaToggleState(bool enabled)
- {
- try
- {
- if (instance?.chkRareMetaEnabled != null)
- instance.chkRareMetaEnabled.Checked = enabled;
- instance?.UpdateAutoLootRareIndicator();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error setting rare meta toggle state: {ex.Message}");
- }
- }
-
- public static void RefreshSettingsFromConfig()
- {
- try
- {
- instance?.LoadCurrentSettings();
- instance?.UpdateAutoLootRareIndicator();
- instance?.UpdateWebSocketStatus();
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error refreshing settings from config: {ex.Message}");
- }
- }
- #endregion
-
- #region Status Update Methods
- private void UpdateStatus()
- {
- try
- {
- if (lblStatus != null)
- {
- string metaState = VtankControl.VtGetMetaState();
- lblStatus.Text = $"Meta State: {metaState}";
- }
- }
- catch
- {
- if (lblStatus != null)
- lblStatus.Text = "Meta State: Unknown";
- }
- }
-
- private void UpdateAutoLootRareIndicator()
- {
- try
- {
- if (lblAutoLootRare != null)
- {
- bool isEnabled = PluginSettings.Instance?.RareMetaEnabled == true;
- if (isEnabled)
- {
- lblAutoLootRare.Text = "Auto Loot Rare: [ON]";
- // Try to set green color for ON status
- try { lblAutoLootRare.TextColor = System.Drawing.Color.FromArgb(0, 128, 0); } catch { }
- }
- else
- {
- lblAutoLootRare.Text = "Auto Loot Rare: [OFF]";
- // Try to set red color for OFF status
- try { lblAutoLootRare.TextColor = System.Drawing.Color.FromArgb(255, 0, 0); } catch { }
- }
- }
- }
- catch
- {
- if (lblAutoLootRare != null)
- lblAutoLootRare.Text = "Auto Loot Rare: Unknown";
- }
- }
-
- private void UpdateWebSocketStatus()
- {
- try
- {
- if (lblWebSocketStatus != null)
- {
- bool isConnected = PluginSettings.Instance?.WebSocketEnabled == true;
- if (isConnected)
- {
- lblWebSocketStatus.Text = "WebSocket: [CONNECTED]";
- // Try to set green color for CONNECTED status
- try { lblWebSocketStatus.TextColor = System.Drawing.Color.FromArgb(0, 128, 0); } catch { }
- }
- else
- {
- lblWebSocketStatus.Text = "WebSocket: [DISCONNECTED]";
- // Try to set red color for DISCONNECTED status
- try { lblWebSocketStatus.TextColor = System.Drawing.Color.FromArgb(255, 0, 0); } catch { }
- }
- }
- }
- catch
- {
- if (lblWebSocketStatus != null)
- lblWebSocketStatus.Text = "WebSocket: Unknown";
- }
- }
-
- private void UpdateStatistics()
- {
- try
- {
- // Update last kill time
- if (lblLastKillValue != null)
- {
- if (PluginCore.lastKillTime != DateTime.MinValue)
- {
- TimeSpan timeSinceLastKill = DateTime.Now - PluginCore.lastKillTime;
- if (timeSinceLastKill.TotalMinutes < 60)
- lblLastKillValue.Text = $"{timeSinceLastKill.TotalMinutes:F0} min ago";
- else
- lblLastKillValue.Text = $"{timeSinceLastKill.TotalHours:F1} hr ago";
- }
- else
- {
- lblLastKillValue.Text = "Never";
- }
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error in UpdateStatistics: {ex.Message}");
- }
- }
- #endregion
-
- #region Helper Methods
- private void PopulateNavFileDropdown()
- {
- try
- {
- if (cmbNavFiles != null && PluginCore.navVisualization != null)
- {
- cmbNavFiles.Clear();
- cmbNavFiles.AddItem("None", "None");
-
- foreach (string navFile in PluginCore.navVisualization.AvailableNavFiles)
- {
- cmbNavFiles.AddItem(navFile, navFile);
- }
-
- if (cmbNavFiles.Count > 0)
- cmbNavFiles.Current = 0; // Select "None" which should be at index 0
-
- }
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error populating nav file dropdown: {ex.Message}");
- }
- }
- #endregion
-
- #region IDisposable Override
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- try
- {
- // Unsubscribe from events to prevent memory leaks
-
- // Settings tab event cleanup
- if (chkRareMetaEnabled != null)
- chkRareMetaEnabled.Change -= OnRareMetaSettingChanged;
- if (chkRemoteCommandsEnabled != null)
- chkRemoteCommandsEnabled.Change -= OnRemoteCommandsSettingChanged;
- if (chkHttpServerEnabled != null)
- chkHttpServerEnabled.Change -= OnHttpServerSettingChanged;
- if (chkWebSocketEnabled != null)
- chkWebSocketEnabled.Change -= OnWebSocketSettingChanged;
- if (chkTelemetryEnabled != null)
- chkTelemetryEnabled.Change -= OnTelemetrySettingChanged;
- if (txtCharTag != null)
- txtCharTag.Change -= OnCharTagChanged;
- if (txtVTankPath != null)
- txtVTankPath.Change -= OnVTankPathChanged;
-
- // Statistics tab event cleanup
- if (btnResetStats != null)
- btnResetStats.Hit -= OnResetStatsClick;
-
- // Navigation tab event cleanup
- if (chkNavVisualizationEnabled != null)
- chkNavVisualizationEnabled.Change -= OnNavVisualizationEnabledChanged;
- if (btnRefreshNavFiles != null)
- btnRefreshNavFiles.Hit -= OnRefreshNavFilesClick;
- if (btnLoadRoute != null)
- btnLoadRoute.Hit -= OnLoadRouteClick;
- if (btnClearRoute != null)
- btnClearRoute.Hit -= OnClearRouteClick;
-
- // No enhanced events to clean up
- }
- catch (Exception ex)
- {
- PluginCore.WriteToChat($"Error cleaning up VVS view events: {ex.Message}");
- }
- }
-
- // Call base dispose
- base.Dispose(disposing);
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/MosswartMassacre/Wrapper.cs b/MosswartMassacre/Wrapper.cs
new file mode 100644
index 0000000..7cca722
--- /dev/null
+++ b/MosswartMassacre/Wrapper.cs
@@ -0,0 +1,427 @@
+///////////////////////////////////////////////////////////////////////////////
+//File: Wrapper.cs
+//
+//Description: Contains the interface definitions for the MetaViewWrappers classes.
+//
+//References required:
+// System.Drawing
+//
+//This file is Copyright (c) 2010 VirindiPlugins
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#if METAVIEW_PUBLIC_NS
+namespace MetaViewWrappers
+#else
+namespace MyClasses.MetaViewWrappers
+#endif
+{
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ delegate void dClickedList(object sender, int row, int col);
+
+
+ #region EventArgs Classes
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVControlEventArgs : EventArgs
+ {
+ private int id;
+
+ internal MVControlEventArgs(int ID)
+ {
+ this.id = ID;
+ }
+
+ public int Id
+ {
+ get { return this.id; }
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVIndexChangeEventArgs : MVControlEventArgs
+ {
+ private int index;
+
+ internal MVIndexChangeEventArgs(int ID, int Index)
+ : base(ID)
+ {
+ this.index = Index;
+ }
+
+ public int Index
+ {
+ get { return this.index; }
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVListSelectEventArgs : MVControlEventArgs
+ {
+ private int row;
+ private int col;
+
+ internal MVListSelectEventArgs(int ID, int Row, int Column)
+ : base(ID)
+ {
+ this.row = Row;
+ this.col = Column;
+ }
+
+ public int Row
+ {
+ get { return this.row; }
+ }
+
+ public int Column
+ {
+ get { return this.col; }
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVCheckBoxChangeEventArgs : MVControlEventArgs
+ {
+ private bool check;
+
+ internal MVCheckBoxChangeEventArgs(int ID, bool Check)
+ : base(ID)
+ {
+ this.check = Check;
+ }
+
+ public bool Checked
+ {
+ get { return this.check; }
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVTextBoxChangeEventArgs : MVControlEventArgs
+ {
+ private string text;
+
+ internal MVTextBoxChangeEventArgs(int ID, string text)
+ : base(ID)
+ {
+ this.text = text;
+ }
+
+ public string Text
+ {
+ get { return this.text; }
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class MVTextBoxEndEventArgs : MVControlEventArgs
+ {
+ private bool success;
+
+ internal MVTextBoxEndEventArgs(int ID, bool success)
+ : base(ID)
+ {
+ this.success = success;
+ }
+
+ public bool Success
+ {
+ get { return this.success; }
+ }
+ }
+
+ #endregion EventArgs Classes
+
+
+ #region View
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IView: IDisposable
+ {
+ void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML);
+ void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML);
+ void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey);
+ void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey);
+
+ void SetIcon(int icon, int iconlibrary);
+ void SetIcon(int portalicon);
+
+ string Title { get; set; }
+ bool Visible { get; set; }
+#if !VVS_WRAPPERS_PUBLIC
+ ViewSystemSelector.eViewSystem ViewType { get; }
+#endif
+
+ System.Drawing.Point Location { get; set; }
+ System.Drawing.Rectangle Position { get; set; }
+ System.Drawing.Size Size { get; }
+
+ IControl this[string id] { get; }
+
+ void Activate();
+ void Deactivate();
+ bool Activated { get; set; }
+ }
+
+ #endregion View
+
+ #region Controls
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IControl : IDisposable
+ {
+ string Name { get; }
+ bool Visible { get; set; }
+ string TooltipText { get; set;}
+ int Id { get; }
+ System.Drawing.Rectangle LayoutPosition { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IButton : IControl
+ {
+ string Text { get; set; }
+ event EventHandler Hit;
+ event EventHandler Click;
+ System.Drawing.Color TextColor { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface ICheckBox : IControl
+ {
+ string Text { get; set; }
+ bool Checked { get; set; }
+ event EventHandler Change;
+ event EventHandler Change_Old;
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface ITextBox : IControl
+ {
+ string Text { get; set; }
+ event EventHandler Change;
+ event EventHandler Change_Old;
+ event EventHandler End;
+ int Caret { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface ICombo : IControl
+ {
+ IComboIndexer Text { get; }
+ IComboDataIndexer Data { get; }
+ int Count { get; }
+ int Selected { get; set; }
+ event EventHandler Change;
+ event EventHandler Change_Old;
+ void Add(string text);
+ void Add(string text, object obj);
+ void Insert(int index, string text);
+ void RemoveAt(int index);
+ void Remove(int index);
+ void Clear();
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IComboIndexer
+ {
+ string this[int index] { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IComboDataIndexer
+ {
+ object this[int index] { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface ISlider : IControl
+ {
+ int Position { get; set; }
+ event EventHandler Change;
+ event EventHandler Change_Old;
+ int Maximum { get; set; }
+ int Minimum { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IList : IControl
+ {
+ event EventHandler Selected;
+ event dClickedList Click;
+ void Clear();
+ IListRow this[int row] { get; }
+ IListRow AddRow();
+ IListRow Add();
+ IListRow InsertRow(int pos);
+ IListRow Insert(int pos);
+ int RowCount { get; }
+ void RemoveRow(int index);
+ void Delete(int index);
+ int ColCount { get; }
+ int ScrollPosition { get; set;}
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IListRow
+ {
+ IListCell this[int col] { get; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IListCell
+ {
+ System.Drawing.Color Color { get; set; }
+ int Width { get; set; }
+ object this[int subval] { get; set; }
+ void ResetColor();
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IStaticText : IControl
+ {
+ string Text { get; set; }
+ event EventHandler Click;
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface INotebook : IControl
+ {
+ event EventHandler Change;
+ int ActiveTab { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IProgressBar : IControl
+ {
+ int Position { get; set; }
+ int Value { get; set; }
+ string PreText { get; set; }
+ int MaxValue { get; set; }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ interface IImageButton : IControl
+ {
+ event EventHandler Click;
+ void SetImages(int unpressed, int pressed);
+ void SetImages(int hmodule, int unpressed, int pressed);
+ int Background { set; }
+ System.Drawing.Color Matte { set; }
+ }
+
+ #endregion Controls
+}
diff --git a/MosswartMassacre/Wrapper_Decal.cs b/MosswartMassacre/Wrapper_Decal.cs
new file mode 100644
index 0000000..a917ca8
--- /dev/null
+++ b/MosswartMassacre/Wrapper_Decal.cs
@@ -0,0 +1,1120 @@
+///////////////////////////////////////////////////////////////////////////////
+//File: Wrapper_Decal.cs
+//
+//Description: Contains MetaViewWrapper classes implementing Decal views.
+//
+//References required:
+// System.Drawing
+// Decal.Adapter
+//
+//This file is Copyright (c) 2010 VirindiPlugins
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+#if METAVIEW_PUBLIC_NS
+namespace MetaViewWrappers.DecalControls
+#else
+namespace MyClasses.MetaViewWrappers.DecalControls
+#endif
+
+{
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class View : IView
+ {
+ Decal.Adapter.Wrappers.ViewWrapper myView;
+ public Decal.Adapter.Wrappers.ViewWrapper Underlying { get { return myView; } }
+
+ #region IView Members
+
+ public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML)
+ {
+ myView = p.LoadViewResource(pXML);
+ }
+
+ public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML)
+ {
+ myView = p.LoadView(pXML);
+ }
+
+ public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey)
+ {
+ myView = p.LoadViewResource(pXML);
+ }
+
+ public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey)
+ {
+ myView = p.LoadView(pXML);
+ }
+
+ public void SetIcon(int icon, int iconlibrary)
+ {
+ myView.SetIcon(icon, iconlibrary);
+ }
+
+ public void SetIcon(int portalicon)
+ {
+ //throw new Exception("The method or operation is not implemented.");
+ }
+
+ public string Title
+ {
+ get
+ {
+ return myView.Title;
+ }
+ set
+ {
+ myView.Title = value;
+ }
+ }
+
+ public bool Visible
+ {
+ get
+ {
+ return myView.Activated;
+ }
+ set
+ {
+ myView.Activated = value;
+ }
+ }
+
+ public bool Activated
+ {
+ get
+ {
+ return Visible;
+ }
+ set
+ {
+ Visible = value;
+ }
+ }
+
+ public void Activate()
+ {
+ Visible = true;
+ }
+
+ public void Deactivate()
+ {
+ Visible = false;
+ }
+
+ public System.Drawing.Point Location
+ {
+ get
+ {
+ return new System.Drawing.Point(myView.Position.X, myView.Position.Y);
+ }
+ set
+ {
+ int w = myView.Position.Width;
+ int h = myView.Position.Height;
+ myView.Position = new System.Drawing.Rectangle(value.X, value.Y, w, h);
+ }
+ }
+
+ public System.Drawing.Rectangle Position
+ {
+ get
+ {
+ return myView.Position;
+ }
+ set
+ {
+ myView.Position = value;
+ }
+ }
+
+ public System.Drawing.Size Size
+ {
+ get
+ {
+ return new System.Drawing.Size(myView.Position.Width, myView.Position.Height);
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ internal
+#else
+ public
+#endif
+ ViewSystemSelector.eViewSystem ViewType { get { return ViewSystemSelector.eViewSystem.DecalInject; } }
+ Dictionary CreatedControlsByName = new Dictionary();
+
+ public IControl this[string id]
+ {
+ get
+ {
+ if (CreatedControlsByName.ContainsKey(id)) return CreatedControlsByName[id];
+
+ Control ret = null;
+ Decal.Adapter.Wrappers.IControlWrapper iret = myView.Controls[id];
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.PushButtonWrapper))
+ ret = new Button();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.CheckBoxWrapper))
+ ret = new CheckBox();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.TextBoxWrapper))
+ ret = new TextBox();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ChoiceWrapper))
+ ret = new Combo();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.SliderWrapper))
+ ret = new Slider();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ListWrapper))
+ ret = new List();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.StaticWrapper))
+ ret = new StaticText();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.NotebookWrapper))
+ ret = new Notebook();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ProgressWrapper))
+ ret = new ProgressBar();
+ if (iret.GetType() == typeof(Decal.Adapter.Wrappers.ButtonWrapper))
+ ret = new ImageButton();
+
+ if (ret == null) return null;
+
+ ret.myControl = iret;
+ ret.myName = id;
+ ret.Initialize();
+ allocatedcontrols.Add(ret);
+ CreatedControlsByName[id] = ret;
+ return ret;
+ }
+ }
+
+ List allocatedcontrols = new List();
+
+ #endregion
+
+ #region IDisposable Members
+
+ bool disposed = false;
+ public void Dispose()
+ {
+ if (disposed) return;
+ disposed = true;
+ GC.SuppressFinalize(this);
+
+ foreach (Control c in allocatedcontrols)
+ c.Dispose();
+
+ myView.Dispose();
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Control : IControl
+ {
+ internal Decal.Adapter.Wrappers.IControlWrapper myControl;
+ public Decal.Adapter.Wrappers.IControlWrapper Underlying { get { return myControl; } }
+ internal string myName;
+
+ public virtual void Initialize()
+ {
+
+ }
+
+ #region IControl Members
+
+ public string Name
+ {
+ get { return myName; }
+ }
+
+ public bool Visible
+ {
+ get { return true; }
+ set { }
+ }
+
+ public string TooltipText
+ {
+ get
+ {
+ return "";
+ }
+ set
+ {
+
+ }
+ }
+
+ public int Id
+ {
+ get
+ {
+ return myControl.Id;
+ }
+ }
+
+ public System.Drawing.Rectangle LayoutPosition
+ {
+ get
+ {
+#if DECAL_INTEROP
+ //This is kinda bad, but whatever
+ Decal.Interop.Inject.ILayer Ly = (Decal.Interop.Inject.ILayer)(Underlying.Underlying);
+ Decal.Interop.Core.tagRECT rct = Ly.get_Position();
+ return new System.Drawing.Rectangle(rct.left, rct.top, rct.right - rct.left, rct.bottom - rct.top);
+#else
+#warning DECAL_INTEROP not defined, MetaViewWrappers.DecalControls.Control.LayoutPosition will not be available.
+ return new System.Drawing.Rectangle();
+#endif
+ }
+ set
+ {
+#if DECAL_INTEROP
+ Decal.Interop.Inject.ILayer Ly = (Decal.Interop.Inject.ILayer)(Underlying.Underlying);
+ Decal.Interop.Core.tagRECT rct = new Decal.Interop.Core.tagRECT();
+ rct.left = value.Left;
+ rct.top = value.Top;
+ rct.right = value.Right;
+ rct.bottom = value.Bottom;
+ Ly.set_Position(ref rct);
+#endif
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ bool disposed = false;
+ public virtual void Dispose()
+ {
+ if (disposed) return;
+ disposed = true;
+
+ //myControl.Dispose();
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Button : Control, IButton
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Hit += new EventHandler(Button_Hit);
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Click += new EventHandler(Button_Click);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Hit -= new EventHandler(Button_Hit);
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Click -= new EventHandler(Button_Click);
+ }
+
+ void Button_Hit(object sender, Decal.Adapter.ControlEventArgs e)
+ {
+ if (Hit != null)
+ Hit(this, null);
+ }
+
+ void Button_Click(object sender, Decal.Adapter.ControlEventArgs e)
+ {
+ if (Click != null)
+ Click(this, new MVControlEventArgs(this.Id));
+ }
+
+ #region IButton Members
+
+ public string Text
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Text;
+ //throw new Exception("The method or operation is not implemented.");
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).Text = value;
+ //throw new Exception("The method or operation is not implemented.");
+ }
+ }
+
+ public System.Drawing.Color TextColor
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).TextColor;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.PushButtonWrapper)myControl).TextColor = value;
+ }
+ }
+
+ public event EventHandler Hit;
+ public event EventHandler Click;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class CheckBox : Control, ICheckBox
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Change += new EventHandler(CheckBox_Change);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Change -= new EventHandler(CheckBox_Change);
+ }
+
+ void CheckBox_Change(object sender, Decal.Adapter.CheckBoxChangeEventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVCheckBoxChangeEventArgs(this.Id, Checked));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ #region ICheckBox Members
+
+ public string Text
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Text;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Text = value;
+ }
+ }
+
+ public bool Checked
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Checked;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.CheckBoxWrapper)myControl).Checked = value;
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class TextBox : Control, ITextBox
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Change += new EventHandler(TextBox_Change);
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).End += new EventHandler(TextBox_End);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Change -= new EventHandler(TextBox_Change);
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).End -= new EventHandler(TextBox_End);
+ }
+
+ void TextBox_Change(object sender, Decal.Adapter.TextBoxChangeEventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVTextBoxChangeEventArgs(this.Id, e.Text));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ void TextBox_End(object sender, Decal.Adapter.TextBoxEndEventArgs e)
+ {
+ if (End != null)
+ End(this, new MVTextBoxEndEventArgs(this.Id, e.Success));
+ }
+
+ #region ITextBox Members
+
+ public string Text
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Text;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Text = value;
+ }
+ }
+
+ public int Caret
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Caret;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.TextBoxWrapper)myControl).Caret = value;
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+ public event EventHandler End;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Combo : Control, ICombo
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Change += new EventHandler(Combo_Change);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Change -= new EventHandler(Combo_Change);
+ }
+
+ void Combo_Change(object sender, Decal.Adapter.IndexChangeEventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVIndexChangeEventArgs(this.Id, e.Index));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ #region ICombo Members
+
+ public IComboIndexer Text
+ {
+ get
+ {
+ return new ComboIndexer(this);
+ }
+ }
+
+ public IComboDataIndexer Data
+ {
+ get
+ {
+ return new ComboDataIndexer(this);
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Count;
+ }
+ }
+
+ public int Selected
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Selected;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Selected = value;
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+
+ public void Add(string text)
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Add(text, null);
+ }
+
+ public void Add(string text, object obj)
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Add(text, obj);
+ }
+
+ public void Insert(int index, string text)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ public void RemoveAt(int index)
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Remove(index);
+ }
+
+ public void Remove(int index)
+ {
+ RemoveAt(index);
+ }
+
+ public void Clear()
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myControl).Clear();
+ }
+
+ #endregion
+
+ internal class ComboIndexer: IComboIndexer
+ {
+ Combo myCombo;
+ internal ComboIndexer(Combo c)
+ {
+ myCombo = c;
+ }
+
+ #region IComboIndexer Members
+
+ public string this[int index]
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Text[index];
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Text[index] = value;
+ }
+ }
+
+ #endregion
+ }
+
+ internal class ComboDataIndexer : IComboDataIndexer
+ {
+ Combo myCombo;
+ internal ComboDataIndexer(Combo c)
+ {
+ myCombo = c;
+ }
+
+ #region IComboIndexer Members
+
+ public object this[int index]
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Data[index];
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ChoiceWrapper)myCombo.myControl).Data[index] = value;
+ }
+ }
+
+ #endregion
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Slider : Control, ISlider
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Change += new EventHandler(Slider_Change);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Change -= new EventHandler(Slider_Change);
+ }
+
+ void Slider_Change(object sender, Decal.Adapter.IndexChangeEventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVIndexChangeEventArgs(this.Id, e.Index));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ #region ISlider Members
+
+ public int Position
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).SliderPostition;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.SliderWrapper)myControl).SliderPostition = value;
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+
+ public int Maximum
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Maximum;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Maximum = value;
+ }
+ }
+ public int Minimum
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Minimum;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.SliderWrapper)myControl).Minimum = value;
+ }
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class List : Control, IList
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Selected += new EventHandler(List_Selected);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Selected -= new EventHandler(List_Selected);
+ }
+
+ void List_Selected(object sender, Decal.Adapter.ListSelectEventArgs e)
+ {
+ if (Click != null)
+ Click(this, e.Row, e.Column);
+ if (Selected != null)
+ Selected(this, new MVListSelectEventArgs(this.Id, e.Row, e.Column));
+ }
+
+ #region IList Members
+
+ public event dClickedList Click;
+ public event EventHandler Selected;
+
+ public void Clear()
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Clear();
+ }
+
+ public IListRow this[int row]
+ {
+ get
+ {
+ return new ListRow(this, row);
+ }
+ }
+
+ public IListRow AddRow()
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Add();
+ return new ListRow(this, ((Decal.Adapter.Wrappers.ListWrapper)myControl).RowCount - 1);
+ }
+
+ public IListRow Add()
+ {
+ return AddRow();
+ }
+
+ public IListRow InsertRow(int pos)
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Insert(pos);
+ return new ListRow(this, pos);
+ }
+
+ public IListRow Insert(int pos)
+ {
+ return InsertRow(pos);
+ }
+
+ public int RowCount
+ {
+ get { return ((Decal.Adapter.Wrappers.ListWrapper)myControl).RowCount; }
+ }
+
+ public void RemoveRow(int index)
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).Delete(index);
+ }
+
+ public void Delete(int index)
+ {
+ RemoveRow(index);
+ }
+
+ public int ColCount
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ListWrapper)myControl).ColCount;
+ }
+ }
+
+ public int ScrollPosition
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ListWrapper)myControl).ScrollPosition;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myControl).ScrollPosition = value;
+ }
+ }
+
+ #endregion
+
+ public class ListRow : IListRow
+ {
+ internal List myList;
+ internal int myRow;
+ internal ListRow(List l, int r)
+ {
+ myList = l;
+ myRow = r;
+ }
+
+
+ #region IListRow Members
+
+ public IListCell this[int col]
+ {
+ get { return new ListCell(myList, myRow, col); }
+ }
+
+ #endregion
+ }
+
+ public class ListCell : IListCell
+ {
+ internal List myList;
+ internal int myRow;
+ internal int myCol;
+ public ListCell(List l, int r, int c)
+ {
+ myList = l;
+ myRow = r;
+ myCol = c;
+ }
+
+ #region IListCell Members
+
+ public void ResetColor()
+ {
+ Color = System.Drawing.Color.White;
+ }
+
+ public System.Drawing.Color Color
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Color;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Color = value;
+ }
+ }
+
+ public int Width
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Width;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol].Width = value;
+ }
+ }
+
+ public object this[int subval]
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol][subval];
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ListWrapper)myList.myControl)[myRow][myCol][subval] = value;
+ }
+ }
+
+ #endregion
+ }
+
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class StaticText : Control, IStaticText
+ {
+
+ #region IStaticText Members
+
+ public string Text
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.StaticWrapper)myControl).Text;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.StaticWrapper)myControl).Text = value;
+ }
+ }
+
+#pragma warning disable 0067
+ public event EventHandler Click;
+#pragma warning restore 0067
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Notebook : Control, INotebook
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).Change += new EventHandler(Notebook_Change);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).Change -= new EventHandler(Notebook_Change);
+ }
+
+ void Notebook_Change(object sender, Decal.Adapter.IndexChangeEventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVIndexChangeEventArgs(this.Id, e.Index));
+ }
+
+ #region INotebook Members
+
+ public event EventHandler Change;
+
+ public int ActiveTab
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).ActiveTab;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.NotebookWrapper)myControl).ActiveTab = value;
+ }
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class ProgressBar : Control, IProgressBar
+ {
+
+ #region IProgressBar Members
+
+ public int Position
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).Value;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).Value = value;
+ }
+ }
+
+ public int Value
+ {
+ get
+ {
+ return Position;
+ }
+ set
+ {
+ Position = value;
+ }
+ }
+
+ public string PreText
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).PreText;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).PreText = value;
+ }
+ }
+
+ public int MaxValue
+ {
+ get
+ {
+ return ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).MaxValue;
+ }
+ set
+ {
+ ((Decal.Adapter.Wrappers.ProgressWrapper)myControl).MaxValue = value;
+ }
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class ImageButton : Control, IImageButton
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Click += new EventHandler(ImageButton_Click);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Click -= new EventHandler(ImageButton_Click);
+ }
+
+ void ImageButton_Click(object sender, Decal.Adapter.ControlEventArgs e)
+ {
+ if (Click != null)
+ Click(this, new MVControlEventArgs(this.Id));
+ }
+
+
+ #region IImageButton Members
+
+ public event EventHandler Click;
+
+ public void SetImages(int unpressed, int pressed)
+ {
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).SetImages(unpressed, pressed);
+ }
+
+ public void SetImages(int hmodule, int unpressed, int pressed)
+ {
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).SetImages(hmodule, unpressed, pressed);
+ }
+
+ public int Background
+ {
+ set
+ {
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Background = value;
+ }
+ }
+
+ public System.Drawing.Color Matte
+ {
+ set
+ {
+ ((Decal.Adapter.Wrappers.ButtonWrapper)myControl).Matte = value;
+ }
+ }
+
+ #endregion
+ }
+}
+
diff --git a/MosswartMassacre/Wrapper_MyHuds.cs b/MosswartMassacre/Wrapper_MyHuds.cs
new file mode 100644
index 0000000..e2e097f
--- /dev/null
+++ b/MosswartMassacre/Wrapper_MyHuds.cs
@@ -0,0 +1,1225 @@
+///////////////////////////////////////////////////////////////////////////////
+//File: Wrapper_MyHuds.cs
+//
+//Description: Contains MetaViewWrapper classes implementing Virindi View Service
+// views. These classes are only compiled if the VVS_REFERENCED symbol is defined.
+//
+//References required:
+// System.Drawing
+// VirindiViewService (if VVS_REFERENCED is defined)
+//
+//This file is Copyright (c) 2010 VirindiPlugins
+//
+//Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////
+
+#if VVS_REFERENCED
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using VirindiViewService;
+
+#if METAVIEW_PUBLIC_NS
+namespace MetaViewWrappers.VirindiViewServiceHudControls
+#else
+namespace MyClasses.MetaViewWrappers.VirindiViewServiceHudControls
+#endif
+{
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class View : IView
+ {
+ HudView myView;
+ public HudView Underlying { get { return myView; } }
+
+ #region IView Members
+
+ public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML)
+ {
+ VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser();
+ ViewProperties iprop;
+ ControlGroup igroup;
+ ps.ParseFromResource(pXML, out iprop, out igroup);
+ myView = new VirindiViewService.HudView(iprop, igroup);
+ }
+
+ public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML)
+ {
+ VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser();
+ ViewProperties iprop;
+ ControlGroup igroup;
+ ps.Parse(pXML, out iprop, out igroup);
+ myView = new VirindiViewService.HudView(iprop, igroup);
+ }
+
+ public void Initialize(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey)
+ {
+ VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser();
+ ViewProperties iprop;
+ ControlGroup igroup;
+ ps.ParseFromResource(pXML, out iprop, out igroup);
+ myView = new VirindiViewService.HudView(iprop, igroup, pWindowKey);
+ }
+
+ public void InitializeRawXML(Decal.Adapter.Wrappers.PluginHost p, string pXML, string pWindowKey)
+ {
+ VirindiViewService.XMLParsers.Decal3XMLParser ps = new VirindiViewService.XMLParsers.Decal3XMLParser();
+ ViewProperties iprop;
+ ControlGroup igroup;
+ ps.Parse(pXML, out iprop, out igroup);
+ myView = new VirindiViewService.HudView(iprop, igroup, pWindowKey);
+ }
+
+ public void SetIcon(int icon, int iconlibrary)
+ {
+ myView.Icon = ACImage.FromIconLibrary(icon, iconlibrary);
+ }
+
+ public void SetIcon(int portalicon)
+ {
+ myView.Icon = portalicon;
+ }
+
+ public string Title
+ {
+ get
+ {
+ return myView.Title;
+ }
+ set
+ {
+ myView.Title = value;
+ }
+ }
+
+ public bool Visible
+ {
+ get
+ {
+ return myView.Visible;
+ }
+ set
+ {
+ myView.Visible = value;
+ }
+ }
+
+ public bool Activated
+ {
+ get
+ {
+ return Visible;
+ }
+ set
+ {
+ Visible = value;
+ }
+ }
+
+ public void Activate()
+ {
+ Visible = true;
+ }
+
+ public void Deactivate()
+ {
+ Visible = false;
+ }
+
+ public System.Drawing.Point Location
+ {
+ get
+ {
+ return myView.Location;
+ }
+ set
+ {
+ myView.Location = value;
+ }
+ }
+
+ public System.Drawing.Size Size
+ {
+ get
+ {
+ return new System.Drawing.Size(myView.Width, myView.Height);
+ }
+ }
+
+ public System.Drawing.Rectangle Position
+ {
+ get
+ {
+ return new System.Drawing.Rectangle(Location, Size);
+ }
+ set
+ {
+ Location = value.Location;
+ myView.ClientArea = value.Size;
+ }
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ internal
+#else
+ public
+#endif
+ ViewSystemSelector.eViewSystem ViewType { get { return ViewSystemSelector.eViewSystem.VirindiViewService; } }
+ Dictionary CreatedControlsByName = new Dictionary();
+
+ public IControl this[string id]
+ {
+ get
+ {
+ if (CreatedControlsByName.ContainsKey(id)) return CreatedControlsByName[id];
+
+ Control ret = null;
+ VirindiViewService.Controls.HudControl iret = myView[id];
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudButton))
+ ret = new Button();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudCheckBox))
+ ret = new CheckBox();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudTextBox))
+ ret = new TextBox();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudCombo))
+ ret = new Combo();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudHSlider))
+ ret = new Slider();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudList))
+ ret = new List();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudStaticText))
+ ret = new StaticText();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudTabView))
+ ret = new Notebook();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudProgressBar))
+ ret = new ProgressBar();
+ if (iret.GetType() == typeof(VirindiViewService.Controls.HudImageButton))
+ ret = new ImageButton();
+
+ if (ret == null) return null;
+
+ ret.myControl = iret;
+ ret.myName = id;
+ ret.Initialize();
+ allocatedcontrols.Add(ret);
+ CreatedControlsByName[id] = ret;
+ return ret;
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ bool disposed = false;
+ public void Dispose()
+ {
+ if (disposed) return;
+ disposed = true;
+ GC.SuppressFinalize(this);
+
+ foreach (Control c in allocatedcontrols)
+ c.Dispose();
+
+ myView.Dispose();
+ }
+
+ #endregion
+
+ List allocatedcontrols = new List();
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Control : IControl
+ {
+ internal VirindiViewService.Controls.HudControl myControl;
+ internal string myName;
+ public VirindiViewService.Controls.HudControl Underlying { get { return myControl; } }
+
+ public virtual void Initialize()
+ {
+
+ }
+
+ #region IControl Members
+
+ public string Name
+ {
+ get { return myName; }
+ }
+
+ public bool Visible
+ {
+ get { return myControl.Visible; }
+ set { myControl.Visible = value; }
+ }
+
+ VirindiViewService.TooltipSystem.cTooltipInfo itooltipinfo = null;
+ public string TooltipText
+ {
+ get
+ {
+ if (itooltipinfo != null)
+ return itooltipinfo.Text;
+ else
+ return "";
+ }
+ set
+ {
+ if (itooltipinfo != null)
+ {
+ VirindiViewService.TooltipSystem.RemoveTooltip(itooltipinfo);
+ itooltipinfo = null;
+ }
+ if (!String.IsNullOrEmpty(value))
+ {
+ itooltipinfo = VirindiViewService.TooltipSystem.AssociateTooltip(myControl, value);
+ }
+ }
+ }
+
+ public int Id
+ {
+ get
+ {
+ return myControl.XMLID;
+ }
+ }
+
+ public System.Drawing.Rectangle LayoutPosition
+ {
+ get
+ {
+ //Relative to what?!??!
+ if (Underlying.Group.HeadControl == null)
+ return new System.Drawing.Rectangle();
+
+ if (Underlying.Group.HeadControl.Name == Underlying.Name)
+ return new System.Drawing.Rectangle();
+
+ VirindiViewService.Controls.HudControl myparent = Underlying.Group.ParentOf(Underlying.Name);
+
+ if (myparent == null)
+ return new System.Drawing.Rectangle();
+
+ //Position only valid inside fixedlayouts
+ VirindiViewService.Controls.HudFixedLayout layoutparent = myparent as VirindiViewService.Controls.HudFixedLayout;
+
+ if (layoutparent == null)
+ return new System.Drawing.Rectangle();
+
+ return layoutparent.GetControlRect(Underlying);
+ }
+ set
+ {
+ if (Underlying.Group.HeadControl == null)
+ return;
+
+ if (Underlying.Group.HeadControl.Name == Underlying.Name)
+ return;
+
+ VirindiViewService.Controls.HudControl myparent = Underlying.Group.ParentOf(Underlying.Name);
+
+ if (myparent == null)
+ return;
+
+ //Position only valid inside fixedlayouts
+ VirindiViewService.Controls.HudFixedLayout layoutparent = myparent as VirindiViewService.Controls.HudFixedLayout;
+
+ if (layoutparent == null)
+ return;
+
+ layoutparent.SetControlRect(Underlying, value);
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ bool disposed = false;
+ public virtual void Dispose()
+ {
+ if (disposed) return;
+ disposed = true;
+
+ myControl.Dispose();
+ }
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Button : Control, IButton
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((VirindiViewService.Controls.HudButton)myControl).MouseEvent += new EventHandler(Button_MouseEvent);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((VirindiViewService.Controls.HudButton)myControl).MouseEvent -= new EventHandler(Button_MouseEvent);
+ }
+
+ void Button_MouseEvent(object sender, VirindiViewService.Controls.ControlMouseEventArgs e)
+ {
+ switch (e.EventType)
+ {
+ case VirindiViewService.Controls.ControlMouseEventArgs.MouseEventType.MouseHit:
+ if (Click != null)
+ Click(this, new MVControlEventArgs(this.Id));
+ return;
+ case VirindiViewService.Controls.ControlMouseEventArgs.MouseEventType.MouseDown:
+ if (Hit != null)
+ Hit(this, null);
+ return;
+ }
+ }
+
+ #region IButton Members
+
+ public string Text
+ {
+ get
+ {
+ return ((VirindiViewService.Controls.HudButton)myControl).Text;
+ }
+ set
+ {
+ ((VirindiViewService.Controls.HudButton)myControl).Text = value;
+ }
+ }
+
+ public System.Drawing.Color TextColor
+ {
+ get
+ {
+ return System.Drawing.Color.Black;
+ }
+ set
+ {
+
+ }
+ }
+
+ public event EventHandler Hit;
+ public event EventHandler Click;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class CheckBox : Control, ICheckBox
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((VirindiViewService.Controls.HudCheckBox)myControl).Change += new EventHandler(CheckBox_Change);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((VirindiViewService.Controls.HudCheckBox)myControl).Change -= new EventHandler(CheckBox_Change);
+ }
+
+ void CheckBox_Change(object sender, EventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVCheckBoxChangeEventArgs(this.Id, Checked));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ #region ICheckBox Members
+
+ public string Text
+ {
+ get
+ {
+ return ((VirindiViewService.Controls.HudCheckBox)myControl).Text;
+ }
+ set
+ {
+ ((VirindiViewService.Controls.HudCheckBox)myControl).Text = value;
+ }
+ }
+
+ public bool Checked
+ {
+ get
+ {
+ return ((VirindiViewService.Controls.HudCheckBox)myControl).Checked;
+ }
+ set
+ {
+ ((VirindiViewService.Controls.HudCheckBox)myControl).Checked = value;
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class TextBox : Control, ITextBox
+ {
+ public override void Initialize()
+ {
+ base.Initialize();
+ ((VirindiViewService.Controls.HudTextBox)myControl).Change += new EventHandler(TextBox_Change);
+ myControl.LostFocus += new EventHandler(myControl_LostFocus);
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ ((VirindiViewService.Controls.HudTextBox)myControl).Change -= new EventHandler(TextBox_Change);
+ myControl.LostFocus -= new EventHandler(myControl_LostFocus);
+ }
+
+ void TextBox_Change(object sender, EventArgs e)
+ {
+ if (Change != null)
+ Change(this, new MVTextBoxChangeEventArgs(this.Id, Text));
+ if (Change_Old != null)
+ Change_Old(this, null);
+ }
+
+ void myControl_LostFocus(object sender, EventArgs e)
+ {
+ if (!myControl.HasFocus) return;
+
+ if (End != null)
+ End(this, new MVTextBoxEndEventArgs(this.Id, true));
+ }
+
+ #region ITextBox Members
+
+ public string Text
+ {
+ get
+ {
+ return ((VirindiViewService.Controls.HudTextBox)myControl).Text;
+ }
+ set
+ {
+ ((VirindiViewService.Controls.HudTextBox)myControl).Text = value;
+ }
+ }
+
+ public int Caret
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+
+ }
+ }
+
+ public event EventHandler Change;
+ public event EventHandler Change_Old;
+ public event EventHandler End;
+
+ #endregion
+ }
+
+#if VVS_WRAPPERS_PUBLIC
+ public
+#else
+ internal
+#endif
+ class Combo : Control, ICombo
+ {
+ List